OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

bootstrap_gui.cpp
Go to the documentation of this file.
1 /* $Id: bootstrap_gui.cpp 26538 2014-04-28 21:06:51Z rubidium $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
9
12 #include "stdafx.h"
13 #include "base_media_base.h"
14 #include "blitter/factory.hpp"
15
16 #if defined(ENABLE_NETWORK) && defined(WITH_FREETYPE)
17
18 #include "core/geometry_func.hpp"
19 #include "fontcache.h"
20 #include "gfx_func.h"
21 #include "network/network.h"
22 #include "network/network_content_gui.h"
23 #include "openttd.h"
24 #include "strings_func.h"
25 #include "video/video_driver.hpp"
26 #include "window_func.h"
27
28 #include "widgets/bootstrap_widget.h"
29
30 #include "table/strings.h"
31
32 #include "safeguards.h"
33
35 static const struct NWidgetPart _background_widgets[] = {
36 NWidget(WWT_PANEL, COLOUR_DARK_BLUE, WID_BB_BACKGROUND), SetResize(1, 1),
37 };
38
42 static WindowDesc _background_desc(
43 WDP_MANUAL, NULL, 0, 0,
44 WC_BOOTSTRAP, WC_NONE,
45 0,
46 _background_widgets, lengthof(_background_widgets)
47 );
48
50 class BootstrapBackground : public Window {
51 public:
52 BootstrapBackground() : Window(&_background_desc)
53 {
54 this->InitNested(0);
55 CLRBITS(this->flags, WF_WHITE_BORDER);
56 ResizeWindow(this, _screen.width, _screen.height);
57 }
58
59 virtual void DrawWidget(const Rect &r, int widget) const
60 {
61 GfxFillRect(r.left, r.top, r.right, r.bottom, 4, FILLRECT_OPAQUE);
62 GfxFillRect(r.left, r.top, r.right, r.bottom, 0, FILLRECT_CHECKER);
63 }
64 };
65
67 static const NWidgetPart _nested_boostrap_download_status_window_widgets[] = {
68 NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
69 NWidget(WWT_PANEL, COLOUR_GREY, WID_NCDS_BACKGROUND),
70 NWidget(NWID_SPACER), SetMinimalSize(350, 0), SetMinimalTextLines(3, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 30),
71 EndContainer(),
72 };
73
75 static WindowDesc _bootstrap_download_status_window_desc(
76 WDP_CENTER, NULL, 0, 0,
77 WC_NETWORK_STATUS_WINDOW, WC_NONE,
78 WDF_MODAL,
79 _nested_boostrap_download_status_window_widgets, lengthof(_nested_boostrap_download_status_window_widgets)
80 );
81
82
84 struct BootstrapContentDownloadStatusWindow : public BaseNetworkContentDownloadStatusWindow {
85 public:
87 BootstrapContentDownloadStatusWindow() : BaseNetworkContentDownloadStatusWindow(&_bootstrap_download_status_window_desc)
88 {
89 }
90
91 virtual void OnDownloadComplete(ContentID cid)
92 {
93 /* We have completed downloading. We can trigger finding the right set now. */
94 BaseGraphics::FindSets();
95
96 /* And continue going into the menu. */
97 _game_mode = GM_MENU;
98
99 /* _exit_game is used to break out of the outer video driver's MainLoop. */
100 _exit_game = true;
101 delete this;
102 }
103 };
104
106 static const NWidgetPart _bootstrap_query_widgets[] = {
107 NWidget(NWID_HORIZONTAL),
108 NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_MISSING_GRAPHICS_SET_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
109 EndContainer(),
110 NWidget(WWT_PANEL, COLOUR_GREY),
111 NWidget(WWT_PANEL, COLOUR_GREY, WID_BAFD_QUESTION), EndContainer(),
112 NWidget(NWID_HORIZONTAL),
113 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BAFD_YES), SetDataTip(STR_MISSING_GRAPHICS_YES_DOWNLOAD, STR_NULL),
114 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_BAFD_NO), SetDataTip(STR_MISSING_GRAPHICS_NO_QUIT, STR_NULL),
115 EndContainer(),
116 EndContainer(),
117 };
118
120 static WindowDesc _bootstrap_query_desc(
121 WDP_CENTER, NULL, 0, 0,
122 WC_CONFIRM_POPUP_QUERY, WC_NONE,
123 0,
124 _bootstrap_query_widgets, lengthof(_bootstrap_query_widgets)
125 );
126
128 class BootstrapAskForDownloadWindow : public Window, ContentCallback {
129 Dimension button_size;
130
131 public:
133 BootstrapAskForDownloadWindow() : Window(&_bootstrap_query_desc)
134 {
135 this->InitNested(WN_CONFIRM_POPUP_QUERY_BOOTSTRAP);
136 _network_content_client.AddCallback(this);
137 }
138
140 ~BootstrapAskForDownloadWindow()
141 {
142 _network_content_client.RemoveCallback(this);
143 }
144
145 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
146 {
147 /* We cache the button size. This is safe as no reinit can happen here. */
148 if (this->button_size.width == 0) {
149 this->button_size = maxdim(GetStringBoundingBox(STR_MISSING_GRAPHICS_YES_DOWNLOAD), GetStringBoundingBox(STR_MISSING_GRAPHICS_NO_QUIT));
150 this->button_size.width += WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
151 this->button_size.height += WD_FRAMETEXT_TOP + WD_FRAMETEXT_BOTTOM;
152 }
153
154 switch (widget) {
155 case WID_BAFD_QUESTION:
156 /* The question is twice as wide as the buttons, and determine the height based on the width. */
157 size->width = this->button_size.width * 2;
158 size->height = GetStringHeight(STR_MISSING_GRAPHICS_SET_MESSAGE, size->width - WD_FRAMETEXT_LEFT - WD_FRAMETEXT_RIGHT) + WD_FRAMETEXT_BOTTOM + WD_FRAMETEXT_TOP;
159 break;
160
161 case WID_BAFD_YES:
162 case WID_BAFD_NO:
163 *size = this->button_size;
164 break;
165 }
166 }
167
168 virtual void DrawWidget(const Rect &r, int widget) const
169 {
170 if (widget != 0) return;
171
172 DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, r.top + WD_FRAMETEXT_TOP, r.bottom - WD_FRAMETEXT_BOTTOM, STR_MISSING_GRAPHICS_SET_MESSAGE, TC_FROMSTRING, SA_CENTER);
173 }
174
175 virtual void OnClick(Point pt, int widget, int click_count)
176 {
177 switch (widget) {
178 case WID_BAFD_YES:
179 /* We got permission to connect! Yay! */
180 _network_content_client.Connect();
181 break;
182
183 case WID_BAFD_NO:
184 _exit_game = true;
185 break;
186
187 default:
188 break;
189 }
190 }
191
192 virtual void OnConnect(bool success)
193 {
194 /* Once connected, request the metadata. */
195 _network_content_client.RequestContentList(CONTENT_TYPE_BASE_GRAPHICS);
196 }
197
198 virtual void OnReceiveContentInfo(const ContentInfo *ci)
199 {
200 /* And once the meta data is received, start downloading it. */
201 _network_content_client.Select(ci->id);
202 new BootstrapContentDownloadStatusWindow();
203 delete this;
204 }
205 };
206
207 #endif /* defined(ENABLE_NETWORK) && defined(WITH_FREETYPE) */
208
215 bool HandleBootstrap()
216 {
217 if (BaseGraphics::GetUsedSet() != NULL) return true;
218
219 /* No user interface, bail out with an error. */
220 if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) goto failure;
221
222 /* If there is no network or no freetype, then there is nothing we can do. Go straight to failure. */
223 #if defined(ENABLE_NETWORK) && defined(WITH_FREETYPE) && (defined(WITH_FONTCONFIG) || defined(WIN32) || defined(__APPLE__))
224 if (!_network_available) goto failure;
225
226 /* First tell the game we're bootstrapping. */
227 _game_mode = GM_BOOTSTRAP;
228
229 /* Initialise the freetype font code. */
230 InitializeUnicodeGlyphMap();
231 /* Next "force" finding a suitable freetype font as the local font is missing. */
232 CheckForMissingGlyphs(false);
233
234 /* Initialise the palette. The biggest step is 'faking' some recolour sprites.
235 * This way the mauve and gray colours work and we can show the user interface. */
236 GfxInitPalettes();
237 static const int offsets[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08 };
238 for (uint i = 0; i != 16; i++) {
239 for (int j = 0; j < 8; j++) {
240 _colour_gradient[i][j] = offsets[i] + j;
241 }
242 }
243
244 /* Finally ask the question. */
245 new BootstrapBackground();
246 new BootstrapAskForDownloadWindow();
247
248 /* Process the user events. */
249 VideoDriver::GetInstance()->MainLoop();
250
251 /* _exit_game is used to get out of the video driver's main loop.
252 * In case GM_BOOTSTRAP is still set we did not exit it via the
253 * "download complete" event, so it was a manual exit. Obey it. */
254 _exit_game = _game_mode == GM_BOOTSTRAP;
255 if (_exit_game) return false;
256
257 /* Try to probe the graphics. Should work this time. */
258 if (!BaseGraphics::SetSet(NULL)) goto failure;
259
260 /* Finally we can continue heading for the menu. */
261 _game_mode = GM_MENU;
262 return true;
263 #endif
264
265 /* Failure to get enough working to get a graphics set. */
266 failure:
267 usererror("Failed to find a graphics set. Please acquire a graphics set for OpenTTD. See section 4.1 of readme.txt.");
268 return false;
269 }