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/>.
10 /** @file intro_gui.cpp The main menu GUI. */
15 #include "window_gui.h"
16 #include "textbuf_gui.h"
17 #include "network/network.h"
19 #include "network/network_gui.h"
20 #include "network/network_content.h"
21 #include "landscape_type.h"
22 #include "strings_func.h"
24 #include "ai/ai_gui.hpp"
26 #include "core/geometry_func.hpp"
29 #include "highscore.h"
31 #include "widgets/intro_widget.h"
33 #include "table/strings.h"
34 #include "table/sprites.h"
36 #include "safeguards.h"
38 struct SelectGameWindow
: public Window
{
40 SelectGameWindow(WindowDesc
*desc
) : Window(desc
)
42 this->CreateNestedTree();
43 this->FinishInitNested(0);
44 this->OnInvalidateData();
48 * Some data on this window has become invalid.
49 * @param data Information about the changed data.
50 * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
52 virtual void OnInvalidateData(int data
= 0, bool gui_scope
= true)
54 if (!gui_scope
) return;
55 this->SetWidgetLoweredState(WID_SGI_TEMPERATE_LANDSCAPE
, _settings_newgame
.game_creation
.landscape
== LT_TEMPERATE
);
56 this->SetWidgetLoweredState(WID_SGI_ARCTIC_LANDSCAPE
, _settings_newgame
.game_creation
.landscape
== LT_ARCTIC
);
57 this->SetWidgetLoweredState(WID_SGI_TROPIC_LANDSCAPE
, _settings_newgame
.game_creation
.landscape
== LT_TROPIC
);
58 this->SetWidgetLoweredState(WID_SGI_TOYLAND_LANDSCAPE
, _settings_newgame
.game_creation
.landscape
== LT_TOYLAND
);
63 bool missing_sprites
= _missing_extra_graphics
> 0 && !IsReleasedVersion();
64 this->GetWidget
<NWidgetStacked
>(WID_SGI_BASESET_SELECTION
)->SetDisplayedPlane(missing_sprites
? 0 : SZSP_NONE
);
66 bool missing_lang
= _current_language
->missing
>= _settings_client
.gui
.missing_strings_threshold
&& !IsReleasedVersion();
67 this->GetWidget
<NWidgetStacked
>(WID_SGI_TRANSLATION_SELECTION
)->SetDisplayedPlane(missing_lang
? 0 : SZSP_NONE
);
70 virtual void DrawWidget(const Rect
&r
, int widget
) const
74 SetDParam(0, _missing_extra_graphics
);
75 DrawStringMultiLine(r
.left
, r
.right
, r
.top
, r
.bottom
, STR_INTRO_BASESET
, TC_FROMSTRING
, SA_CENTER
);
78 case WID_SGI_TRANSLATION
:
79 SetDParam(0, _current_language
->missing
);
80 DrawStringMultiLine(r
.left
, r
.right
, r
.top
, r
.bottom
, STR_INTRO_TRANSLATION
, TC_FROMSTRING
, SA_CENTER
);
85 virtual void UpdateWidgetSize(int widget
, Dimension
*size
, const Dimension
&padding
, Dimension
*fill
, Dimension
*resize
)
90 SetDParam(0, _missing_extra_graphics
);
91 str
= STR_INTRO_BASESET
;
94 case WID_SGI_TRANSLATION
:
95 SetDParam(0, _current_language
->missing
);
96 str
= STR_INTRO_TRANSLATION
;
101 int height
= GetStringHeight(str
, size
->width
);
102 if (height
> 3 * FONT_HEIGHT_NORMAL
) {
103 /* Don't let the window become too high. */
104 Dimension textdim
= GetStringBoundingBox(str
);
106 textdim
.width
-= textdim
.width
/ 2;
107 *size
= maxdim(*size
, textdim
);
109 size
->height
= height
+ padding
.height
;
114 virtual void OnClick(Point pt
, int widget
, int click_count
)
116 #ifdef ENABLE_NETWORK
117 /* Do not create a network server when you (just) have closed one of the game
118 * creation/load windows for the network server. */
119 if (IsInsideMM(widget
, WID_SGI_GENERATE_GAME
, WID_SGI_EDIT_SCENARIO
+ 1)) _is_network_server
= false;
120 #endif /* ENABLE_NETWORK */
123 case WID_SGI_GENERATE_GAME
:
125 StartNewGameWithoutGUI(GENERATE_NEW_SEED
);
127 ShowGenerateLandscape();
131 case WID_SGI_LOAD_GAME
: ShowSaveLoadDialog(FT_SAVEGAME
, SLO_LOAD
); break;
132 case WID_SGI_PLAY_SCENARIO
: ShowSaveLoadDialog(FT_SCENARIO
, SLO_LOAD
); break;
133 case WID_SGI_PLAY_HEIGHTMAP
: ShowSaveLoadDialog(FT_HEIGHTMAP
,SLO_LOAD
); break;
134 case WID_SGI_EDIT_SCENARIO
: StartScenarioEditor(); break;
136 case WID_SGI_PLAY_NETWORK
:
137 if (!_network_available
) {
138 ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE
, INVALID_STRING_ID
, WL_ERROR
);
140 ShowNetworkGameWindow();
144 case WID_SGI_TEMPERATE_LANDSCAPE
: case WID_SGI_ARCTIC_LANDSCAPE
:
145 case WID_SGI_TROPIC_LANDSCAPE
: case WID_SGI_TOYLAND_LANDSCAPE
:
146 SetNewLandscapeType(widget
- WID_SGI_TEMPERATE_LANDSCAPE
);
149 case WID_SGI_OPTIONS
: ShowGameOptions(); break;
150 case WID_SGI_HIGHSCORE
: ShowHighscoreTable(); break;
151 case WID_SGI_SETTINGS_OPTIONS
:ShowGameSettings(); break;
152 case WID_SGI_GRF_SETTINGS
: ShowNewGRFSettings(true, true, false, &_grfconfig_newgame
); break;
153 case WID_SGI_CONTENT_DOWNLOAD
:
154 if (!_network_available
) {
155 ShowErrorMessage(STR_NETWORK_ERROR_NOTAVAILABLE
, INVALID_STRING_ID
, WL_ERROR
);
157 ShowNetworkContentListWindow();
160 case WID_SGI_AI_SETTINGS
: ShowAIConfigWindow(); break;
161 case WID_SGI_EXIT
: HandleExitGameRequest(); break;
166 static const NWidgetPart _nested_select_game_widgets
[] = {
167 NWidget(WWT_CAPTION
, COLOUR_BROWN
), SetDataTip(STR_INTRO_CAPTION
, STR_NULL
),
168 NWidget(WWT_PANEL
, COLOUR_BROWN
),
169 NWidget(NWID_SPACER
), SetMinimalSize(0, 8),
171 /* 'generate game' and 'load game' buttons */
172 NWidget(NWID_HORIZONTAL
, NC_EQUALSIZE
),
173 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_GENERATE_GAME
), SetMinimalSize(158, 12),
174 SetDataTip(STR_INTRO_NEW_GAME
, STR_INTRO_TOOLTIP_NEW_GAME
), SetPadding(0, 0, 0, 10), SetFill(1, 0),
175 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_LOAD_GAME
), SetMinimalSize(158, 12),
176 SetDataTip(STR_INTRO_LOAD_GAME
, STR_INTRO_TOOLTIP_LOAD_GAME
), SetPadding(0, 10, 0, 0), SetFill(1, 0),
179 NWidget(NWID_SPACER
), SetMinimalSize(0, 6),
181 /* 'play scenario' and 'play heightmap' buttons */
182 NWidget(NWID_HORIZONTAL
, NC_EQUALSIZE
),
183 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_PLAY_SCENARIO
), SetMinimalSize(158, 12),
184 SetDataTip(STR_INTRO_PLAY_SCENARIO
, STR_INTRO_TOOLTIP_PLAY_SCENARIO
), SetPadding(0, 0, 0, 10), SetFill(1, 0),
185 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_PLAY_HEIGHTMAP
), SetMinimalSize(158, 12),
186 SetDataTip(STR_INTRO_PLAY_HEIGHTMAP
, STR_INTRO_TOOLTIP_PLAY_HEIGHTMAP
), SetPadding(0, 10, 0, 0), SetFill(1, 0),
189 NWidget(NWID_SPACER
), SetMinimalSize(0, 6),
191 /* 'edit scenario' and 'play multiplayer' buttons */
192 NWidget(NWID_HORIZONTAL
, NC_EQUALSIZE
),
193 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_EDIT_SCENARIO
), SetMinimalSize(158, 12),
194 SetDataTip(STR_INTRO_SCENARIO_EDITOR
, STR_INTRO_TOOLTIP_SCENARIO_EDITOR
), SetPadding(0, 0, 0, 10), SetFill(1, 0),
195 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_PLAY_NETWORK
), SetMinimalSize(158, 12),
196 SetDataTip(STR_INTRO_MULTIPLAYER
, STR_INTRO_TOOLTIP_MULTIPLAYER
), SetPadding(0, 10, 0, 0), SetFill(1, 0),
199 NWidget(NWID_SPACER
), SetMinimalSize(0, 7),
201 /* climate selection buttons */
202 NWidget(NWID_HORIZONTAL
),
203 NWidget(NWID_SPACER
), SetMinimalSize(10, 0), SetFill(1, 0),
204 NWidget(WWT_IMGBTN_2
, COLOUR_ORANGE
, WID_SGI_TEMPERATE_LANDSCAPE
), SetMinimalSize(77, 55),
205 SetDataTip(SPR_SELECT_TEMPERATE
, STR_INTRO_TOOLTIP_TEMPERATE
),
206 NWidget(NWID_SPACER
), SetMinimalSize(3, 0), SetFill(1, 0),
207 NWidget(WWT_IMGBTN_2
, COLOUR_ORANGE
, WID_SGI_ARCTIC_LANDSCAPE
), SetMinimalSize(77, 55),
208 SetDataTip(SPR_SELECT_SUB_ARCTIC
, STR_INTRO_TOOLTIP_SUB_ARCTIC_LANDSCAPE
),
209 NWidget(NWID_SPACER
), SetMinimalSize(3, 0), SetFill(1, 0),
210 NWidget(WWT_IMGBTN_2
, COLOUR_ORANGE
, WID_SGI_TROPIC_LANDSCAPE
), SetMinimalSize(77, 55),
211 SetDataTip(SPR_SELECT_SUB_TROPICAL
, STR_INTRO_TOOLTIP_SUB_TROPICAL_LANDSCAPE
),
212 NWidget(NWID_SPACER
), SetMinimalSize(3, 0), SetFill(1, 0),
213 NWidget(WWT_IMGBTN_2
, COLOUR_ORANGE
, WID_SGI_TOYLAND_LANDSCAPE
), SetMinimalSize(77, 55),
214 SetDataTip(SPR_SELECT_TOYLAND
, STR_INTRO_TOOLTIP_TOYLAND_LANDSCAPE
),
215 NWidget(NWID_SPACER
), SetMinimalSize(10, 0), SetFill(1, 0),
218 NWidget(NWID_SPACER
), SetMinimalSize(0, 7),
219 NWidget(NWID_SELECTION
, INVALID_COLOUR
, WID_SGI_BASESET_SELECTION
),
220 NWidget(NWID_VERTICAL
),
221 NWidget(WWT_EMPTY
, COLOUR_ORANGE
, WID_SGI_BASESET
), SetMinimalSize(316, 12), SetFill(1, 0), SetPadding(0, 10, 7, 10),
224 NWidget(NWID_SELECTION
, INVALID_COLOUR
, WID_SGI_TRANSLATION_SELECTION
),
225 NWidget(NWID_VERTICAL
),
226 NWidget(WWT_EMPTY
, COLOUR_ORANGE
, WID_SGI_TRANSLATION
), SetMinimalSize(316, 12), SetFill(1, 0), SetPadding(0, 10, 7, 10),
230 /* 'game options' and 'advanced settings' buttons */
231 NWidget(NWID_HORIZONTAL
, NC_EQUALSIZE
),
232 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_OPTIONS
), SetMinimalSize(158, 12),
233 SetDataTip(STR_INTRO_GAME_OPTIONS
, STR_INTRO_TOOLTIP_GAME_OPTIONS
), SetPadding(0, 0, 0, 10), SetFill(1, 0),
234 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_SETTINGS_OPTIONS
), SetMinimalSize(158, 12),
235 SetDataTip(STR_INTRO_CONFIG_SETTINGS_TREE
, STR_INTRO_TOOLTIP_CONFIG_SETTINGS_TREE
), SetPadding(0, 10, 0, 0), SetFill(1, 0),
238 NWidget(NWID_SPACER
), SetMinimalSize(0, 6),
240 /* 'script settings' and 'newgrf settings' buttons */
241 NWidget(NWID_HORIZONTAL
, NC_EQUALSIZE
),
242 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_AI_SETTINGS
), SetMinimalSize(158, 12),
243 SetDataTip(STR_INTRO_SCRIPT_SETTINGS
, STR_INTRO_TOOLTIP_SCRIPT_SETTINGS
), SetPadding(0, 0, 0, 10), SetFill(1, 0),
244 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_GRF_SETTINGS
), SetMinimalSize(158, 12),
245 SetDataTip(STR_INTRO_NEWGRF_SETTINGS
, STR_INTRO_TOOLTIP_NEWGRF_SETTINGS
), SetPadding(0, 10, 0, 0), SetFill(1, 0),
248 NWidget(NWID_SPACER
), SetMinimalSize(0, 6),
250 /* 'online content' and 'highscore' buttons */
251 NWidget(NWID_HORIZONTAL
, NC_EQUALSIZE
),
252 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_CONTENT_DOWNLOAD
), SetMinimalSize(158, 12),
253 SetDataTip(STR_INTRO_ONLINE_CONTENT
, STR_INTRO_TOOLTIP_ONLINE_CONTENT
), SetPadding(0, 0, 0, 10), SetFill(1, 0),
254 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_HIGHSCORE
), SetMinimalSize(158, 12),
255 SetDataTip(STR_INTRO_HIGHSCORE
, STR_INTRO_TOOLTIP_HIGHSCORE
), SetPadding(0, 10, 0, 0), SetFill(1, 0),
258 NWidget(NWID_SPACER
), SetMinimalSize(0, 6),
260 /* 'exit program' button */
261 NWidget(NWID_HORIZONTAL
),
262 NWidget(NWID_SPACER
), SetFill(1, 0),
263 NWidget(WWT_PUSHTXTBTN
, COLOUR_ORANGE
, WID_SGI_EXIT
), SetMinimalSize(128, 12),
264 SetDataTip(STR_INTRO_QUIT
, STR_INTRO_TOOLTIP_QUIT
),
265 NWidget(NWID_SPACER
), SetFill(1, 0),
268 NWidget(NWID_SPACER
), SetMinimalSize(0, 8),
273 static WindowDesc
_select_game_desc(
274 WDP_CENTER
, NULL
, 0, 0,
275 WC_SELECT_GAME
, WC_NONE
,
277 _nested_select_game_widgets
, lengthof(_nested_select_game_widgets
)
280 void ShowSelectGameWindow()
282 new SelectGameWindow(&_select_game_desc
);
285 static void AskExitGameCallback(Window
*w
, bool confirmed
)
287 if (confirmed
) _exit_game
= true;
293 SetDParam(0, STR_OSNAME_WINDOWS
);
294 #elif defined(__APPLE__)
295 SetDParam(0, STR_OSNAME_OSX
);
296 #elif defined(__BEOS__)
297 SetDParam(0, STR_OSNAME_BEOS
);
298 #elif defined(__HAIKU__)
299 SetDParam(0, STR_OSNAME_HAIKU
);
300 #elif defined(__MORPHOS__)
301 SetDParam(0, STR_OSNAME_MORPHOS
);
302 #elif defined(__AMIGA__)
303 SetDParam(0, STR_OSNAME_AMIGAOS
);
304 #elif defined(__OS2__)
305 SetDParam(0, STR_OSNAME_OS2
);
307 SetDParam(0, STR_OSNAME_SUNOS
);
309 SetDParam(0, STR_OSNAME_DOS
);
311 SetDParam(0, STR_OSNAME_UNIX
);
315 STR_QUIT_ARE_YOU_SURE_YOU_WANT_TO_EXIT_OPENTTD
,
322 static void AskExitToGameMenuCallback(Window
*w
, bool confirmed
)
325 _switch_mode
= SM_MENU
;
326 ClearErrorMessages();
330 void AskExitToGameMenu()
333 STR_ABANDON_GAME_CAPTION
,
334 (_game_mode
!= GM_EDITOR
) ? STR_ABANDON_GAME_QUERY
: STR_ABANDON_SCENARIO_QUERY
,
336 AskExitToGameMenuCallback