OpenTTD Source 20250218-master-g53dd1258a7
settings_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
6 */
7
10#include "stdafx.h"
11#include "currency.h"
12#include "error.h"
13#include "settings_gui.h"
14#include "textbuf_gui.h"
15#include "command_func.h"
16#include "network/network.h"
18#include "town.h"
19#include "settings_internal.h"
20#include "strings_func.h"
21#include "window_func.h"
22#include "string_func.h"
23#include "dropdown_type.h"
24#include "dropdown_func.h"
26#include "slider_func.h"
27#include "highscore.h"
28#include "base_media_base.h"
29#include "company_base.h"
30#include "company_func.h"
31#include "viewport_func.h"
33#include "ai/ai.hpp"
34#include "blitter/factory.hpp"
35#include "language.h"
36#include "textfile_gui.h"
37#include "stringfilter_type.h"
38#include "querystring_gui.h"
39#include "fontcache.h"
40#include "zoom_func.h"
41#include "rev.h"
44#include "gui.h"
45#include "mixer.h"
46#include "newgrf_config.h"
47#include "network/core/config.h"
48#include "network/network_gui.h"
51#include "social_integration.h"
52#include "sound_func.h"
53
54#include "safeguards.h"
55
56
57#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
58# define HAS_TRUETYPE_FONT
59#endif
60
61static const StringID _autosave_dropdown[] = {
62 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF,
63 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_10_MINUTES,
64 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_30_MINUTES,
65 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_60_MINUTES,
66 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_120_MINUTES,
68};
69
71static const uint32_t _autosave_dropdown_to_minutes[] = {
72 0,
73 10,
74 30,
75 60,
76 120,
77};
78
80
81static const void *ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd);
82
88{
89 auto it = std::ranges::find(_resolutions, Dimension(_screen.width, _screen.height));
90 return std::distance(_resolutions.begin(), it);
91}
92
93static void ShowCustCurrency();
94
97 const std::string name;
99
101 {
102 this->ConstructWindow();
103 this->LoadTextfile(textfile, BASESET_DIR);
104 }
105
106 void SetStringParameters(WidgetID widget) const override
107 {
108 if (widget == WID_TF_CAPTION) {
110 SetDParamStr(1, this->name);
111 }
112 }
113};
114
121template <class TBaseSet>
122void ShowBaseSetTextfileWindow(TextfileType file_type, const TBaseSet *baseset, StringID content_type)
123{
124 CloseWindowById(WC_TEXTFILE, file_type);
125 new BaseSetTextfileWindow(file_type, baseset->name, *baseset->GetTextfile(file_type), content_type);
126}
127
128template <class T>
129DropDownList BuildSetDropDownList(int *selected_index)
130{
131 int n = T::GetNumSets();
132 *selected_index = T::GetIndexOfUsedSet();
133 DropDownList list;
134 for (int i = 0; i < n; i++) {
135 list.push_back(MakeDropDownListStringItem(T::GetSet(i)->GetListLabel(), i));
136 }
137 return list;
138}
139
140std::set<int> _refresh_rates = { 30, 60, 75, 90, 100, 120, 144, 240 };
141
147{
148 /* Add the refresh rate as selected in the config. */
149 _refresh_rates.insert(_settings_client.gui.refresh_rate);
150
151 /* Add all the refresh rates of all monitors connected to the machine. */
152 std::vector<int> monitorRates = VideoDriver::GetInstance()->GetListOfMonitorRefreshRates();
153 std::copy(monitorRates.begin(), monitorRates.end(), std::inserter(_refresh_rates, _refresh_rates.end()));
154}
155
156static const int SCALE_NMARKS = (MAX_INTERFACE_SCALE - MIN_INTERFACE_SCALE) / 25 + 1; // Show marks at 25% increments
157static const int VOLUME_NMARKS = 9; // Show 5 values and 4 empty marks.
158
159static std::optional<std::string> ScaleMarkFunc(int, int, int value)
160{
161 /* Label only every 100% mark. */
162 if (value % 100 != 0) return std::string{};
163
164 return GetString(STR_GAME_OPTIONS_GUI_SCALE_MARK, value / 100, 0);
165}
166
167static std::optional<std::string> VolumeMarkFunc(int, int mark, int value)
168{
169 /* Label only every other mark. */
170 if (mark % 2 != 0) return std::string{};
171
172 // 0-127 does not map nicely to 0-100. Dividing first gives us nice round numbers.
173 return GetString(STR_GAME_OPTIONS_VOLUME_MARK, value / 31 * 25);
174}
175
176static constexpr NWidgetPart _nested_social_plugins_widgets[] = {
178 NWidget(WWT_FRAME, COLOUR_GREY, WID_GO_SOCIAL_PLUGIN_TITLE), SetStringTip(STR_JUST_STRING2),
180 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM),
181 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_SOCIAL_PLUGIN_PLATFORM), SetMinimalSize(100, 12), SetStringTip(STR_JUST_RAW_STRING), SetAlignment(SA_RIGHT),
182 EndContainer(),
184 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE),
185 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_SOCIAL_PLUGIN_STATE), SetMinimalSize(100, 12), SetStringTip(STR_JUST_STRING1), SetAlignment(SA_RIGHT),
186 EndContainer(),
187 EndContainer(),
188 EndContainer(),
189};
190
191static constexpr NWidgetPart _nested_social_plugins_none_widgets[] = {
193 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE),
194 EndContainer(),
195};
196
198public:
200 {
201 this->plugins = SocialIntegration::GetPlugins();
202
203 if (this->plugins.empty()) {
204 auto widget = MakeNWidgets(_nested_social_plugins_none_widgets, nullptr);
205 this->Add(std::move(widget));
206 } else {
207 for (size_t i = 0; i < this->plugins.size(); i++) {
208 auto widget = MakeNWidgets(_nested_social_plugins_widgets, nullptr);
209 this->Add(std::move(widget));
210 }
211 }
212
213 this->SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0);
214 }
215
216 void FillWidgetLookup(WidgetLookup &widget_lookup) override
217 {
218 widget_lookup[WID_GO_SOCIAL_PLUGINS] = this;
220 }
221
222 void SetupSmallestSize(Window *w) override
223 {
224 this->current_index = -1;
226 }
227
234 template <typename T>
235 std::string &GetWidestPlugin(T SocialIntegrationPlugin::*member) const
236 {
237 std::string *longest = &(this->plugins[0]->*member);
238 int longest_length = 0;
239
240 for (auto *plugin : this->plugins) {
241 int length = GetStringBoundingBox(plugin->*member).width;
242 if (length > longest_length) {
243 longest_length = length;
244 longest = &(plugin->*member);
245 }
246 }
247
248 return *longest;
249 }
250
251 void SetStringParameters(int widget) const
252 {
253 switch (widget) {
255 /* For SetupSmallestSize, use the longest string we have. */
256 if (this->current_index < 0) {
257 SetDParam(0, STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE);
260 break;
261 }
262
263 if (this->plugins[this->current_index]->name.empty()) {
264 SetDParam(0, STR_JUST_RAW_STRING);
265 SetDParamStr(1, this->plugins[this->current_index]->basepath);
266 } else {
267 SetDParam(0, STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE);
268 SetDParamStr(1, this->plugins[this->current_index]->name);
269 SetDParamStr(2, this->plugins[this->current_index]->version);
270 }
271 break;
272
274 /* For SetupSmallestSize, use the longest string we have. */
275 if (this->current_index < 0) {
277 break;
278 }
279
280 SetDParamStr(0, this->plugins[this->current_index]->social_platform);
281 break;
282
284 static const std::pair<SocialIntegrationPlugin::State, StringID> state_to_string[] = {
285 { SocialIntegrationPlugin::RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_RUNNING },
286 { SocialIntegrationPlugin::FAILED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED },
287 { SocialIntegrationPlugin::PLATFORM_NOT_RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_PLATFORM_NOT_RUNNING },
288 { SocialIntegrationPlugin::UNLOADED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNLOADED },
289 { SocialIntegrationPlugin::DUPLICATE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_DUPLICATE },
290 { SocialIntegrationPlugin::UNSUPPORTED_API, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNSUPPORTED_API },
291 { SocialIntegrationPlugin::INVALID_SIGNATURE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_INVALID_SIGNATURE },
292 };
293
294 /* For SetupSmallestSize, use the longest string we have. */
295 if (this->current_index < 0) {
297
298 /* Set the longest plugin when looking for the longest status. */
299 SetDParamStr(0, longest_plugin);
300
301 StringID longest = STR_NULL;
302 int longest_length = 0;
303 for (auto state : state_to_string) {
304 int length = GetStringBoundingBox(state.second).width;
305 if (length > longest_length) {
306 longest_length = length;
307 longest = state.second;
308 }
309 }
310
311 SetDParam(0, longest);
312 SetDParamStr(1, longest_plugin);
313 break;
314 }
315
316 auto plugin = this->plugins[this->current_index];
317
318 /* Default string, in case no state matches. */
319 SetDParam(0, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED);
320 SetDParamStr(1, plugin->social_platform);
321
322 /* Find the string for the state. */
323 for (auto state : state_to_string) {
324 if (plugin->state == state.first) {
325 SetDParam(0, state.second);
326 break;
327 }
328 }
329 }
330 break;
331 }
332 }
333
334 void Draw(const Window *w) override
335 {
336 this->current_index = 0;
337
338 for (auto &wid : this->children) {
339 wid->Draw(w);
340 this->current_index++;
341 }
342 }
343
344private:
345 int current_index = -1;
346 std::vector<SocialIntegrationPlugin *> plugins;
347};
348
350std::unique_ptr<NWidgetBase> MakeNWidgetSocialPlugins()
351{
352 return std::make_unique<NWidgetSocialPlugins>();
353}
354
356 GameSettings *opt;
357 bool reload;
358 int gui_scale;
359 static inline WidgetID active_tab = WID_GO_TAB_GENERAL;
360
361 GameOptionsWindow(WindowDesc &desc) : Window(desc)
362 {
363 this->opt = &GetGameSettings();
364 this->reload = false;
365 this->gui_scale = _gui_scale;
366
368
370 this->OnInvalidateData(0);
371
372 this->SetTab(GameOptionsWindow::active_tab);
373
374 if constexpr (!NetworkSurveyHandler::IsSurveyPossible()) this->GetWidget<NWidgetStacked>(WID_GO_SURVEY_SEL)->SetDisplayedPlane(SZSP_NONE);
375 }
376
377 void Close([[maybe_unused]] int data = 0) override
378 {
381 if (this->reload) _switch_mode = SM_MENU;
382 this->Window::Close();
383 }
384
392 {
393 DropDownList list;
394 switch (widget) {
395 case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
396 *selected_index = this->opt->locale.currency;
397 uint64_t disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies();
398
399 /* Add non-custom currencies; sorted naturally */
400 for (const CurrencySpec &currency : _currency_specs) {
401 int i = &currency - _currency_specs.data();
402 if (i == CURRENCY_CUSTOM) continue;
403 if (currency.code.empty()) {
404 list.push_back(MakeDropDownListStringItem(currency.name, i, HasBit(disabled, i)));
405 } else {
406 SetDParam(0, currency.name);
407 SetDParamStr(1, currency.code);
408 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CODE, i, HasBit(disabled, i)));
409 }
410 }
411 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
412
413 /* Append custom currency at the end */
414 list.push_back(MakeDropDownListDividerItem()); // separator line
415 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM)));
416 break;
417 }
418
419 case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
420 int index = 0;
422 index++;
424 }
425 *selected_index = index - 1;
426
427 const StringID *items = _autosave_dropdown;
428 for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
429 list.push_back(MakeDropDownListStringItem(*items, i));
430 }
431 break;
432 }
433
434 case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
435 for (uint i = 0; i < _languages.size(); i++) {
436 bool hide_language = IsReleasedVersion() && !_languages[i].IsReasonablyFinished();
437 if (hide_language) continue;
438 bool hide_percentage = IsReleasedVersion() || _languages[i].missing < _settings_client.gui.missing_strings_threshold;
439 if (&_languages[i] == _current_language) {
440 *selected_index = i;
441 SetDParamStr(0, _languages[i].own_name);
442 } else {
443 /* Especially with sprite-fonts, not all localized
444 * names can be rendered. So instead, we use the
445 * international names for anything but the current
446 * selected language. This avoids showing a few ????
447 * entries in the dropdown list. */
448 SetDParamStr(0, _languages[i].name);
449 }
451 list.push_back(MakeDropDownListStringItem(hide_percentage ? STR_JUST_RAW_STRING : STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE, i));
452 }
453 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
454 break;
455 }
456
457 case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
458 if (_resolutions.empty()) break;
459
461 for (uint i = 0; i < _resolutions.size(); i++) {
464 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_RESOLUTION_ITEM, i));
465 }
466 break;
467
468 case WID_GO_REFRESH_RATE_DROPDOWN: // Setup refresh rate dropdown
469 for (auto it = _refresh_rates.begin(); it != _refresh_rates.end(); it++) {
470 auto i = std::distance(_refresh_rates.begin(), it);
472 SetDParam(0, *it);
473 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, i));
474 }
475 break;
476
479 break;
480
483 break;
484
487 break;
488 }
489
490 return list;
491 }
492
493 void SetStringParameters(WidgetID widget) const override
494 {
495 switch (widget) {
497 const CurrencySpec &currency = _currency_specs[this->opt->locale.currency];
498 if (currency.code.empty()) {
499 SetDParam(0, currency.name);
500 } else {
502 SetDParam(1, currency.name);
503 SetDParamStr(2, currency.code);
504 }
505 break;
506 }
508 int index = 0;
510 index++;
512 }
513 SetDParam(0, _autosave_dropdown[index - 1]);
514 break;
515 }
517 case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->GetListLabel()); break;
518 case WID_GO_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->GetListLabel()); break;
519 case WID_GO_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->GetListLabel()); break;
523
524 if (current_resolution == _resolutions.size()) {
526 } else {
530 }
531 break;
532 }
533
538 assert(plugin != nullptr);
539
540 plugin->SetStringParameters(widget);
541 break;
542 }
543 }
544 }
545
546 void DrawWidget(const Rect &r, WidgetID widget) const override
547 {
548 switch (widget) {
551 DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK);
552 break;
553
556 DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK);
557 break;
558
561 DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK);
562 break;
563
564 case WID_GO_GUI_SCALE:
565 DrawSliderWidget(r, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, SCALE_NMARKS, this->gui_scale, ScaleMarkFunc);
566 break;
567
569 SetDParamStr(0, std::string{VideoDriver::GetInstance()->GetInfoString()});
571 break;
572
574 DrawSliderWidget(r, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.effect_vol, VolumeMarkFunc);
575 break;
576
578 DrawSliderWidget(r, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.music_vol, VolumeMarkFunc);
579 break;
580 }
581 }
582
583 void SetTab(WidgetID widget)
584 {
586 this->LowerWidget(widget);
587 GameOptionsWindow::active_tab = widget;
588
589 int pane;
590 switch (widget) {
591 case WID_GO_TAB_GENERAL: pane = 0; break;
592 case WID_GO_TAB_GRAPHICS: pane = 1; break;
593 case WID_GO_TAB_SOUND: pane = 2; break;
594 case WID_GO_TAB_SOCIAL: pane = 3; break;
595 default: NOT_REACHED();
596 }
597
598 this->GetWidget<NWidgetStacked>(WID_GO_TAB_SELECTION)->SetDisplayedPlane(pane);
599 this->SetDirty();
600 }
601
602 void OnResize() override
603 {
604 bool changed = false;
605
607 int y = 0;
608 for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
610 y = std::max(y, GetStringHeight(STR_JUST_RAW_STRING, wid->current_x));
611 }
612 changed |= wid->UpdateVerticalSize(y);
613
615 y = 0;
616 for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
618 y = std::max(y, GetStringHeight(STR_JUST_RAW_STRING, wid->current_x));
619 }
620 changed |= wid->UpdateVerticalSize(y);
621
623 y = 0;
624 for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
626 y = std::max(y, GetStringHeight(STR_JUST_RAW_STRING, wid->current_x));
627 }
628 changed |= wid->UpdateVerticalSize(y);
629
631 SetDParamStr(0, std::string{VideoDriver::GetInstance()->GetInfoString()});
633 changed |= wid->UpdateVerticalSize(y);
634
635 if (changed) this->ReInit(0, 0, this->flags.Test(WindowFlag::Centred));
636 }
637
639 {
640 switch (widget) {
644 d.width += padding.width;
645 d.height += padding.height;
646 size = maxdim(size, d);
647 break;
648 }
649
658 int selected;
659 size.width = std::max(size.width, GetDropDownListDimension(this->BuildDropDownList(widget, &selected)).width + padding.width);
660 break;
661 }
662 }
663 }
664
665 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
666 {
667 if (widget >= WID_GO_BASE_GRF_TEXTFILE && widget < WID_GO_BASE_GRF_TEXTFILE + TFT_CONTENT_END) {
668 if (BaseGraphics::GetUsedSet() == nullptr) return;
669
671 return;
672 }
673 if (widget >= WID_GO_BASE_SFX_TEXTFILE && widget < WID_GO_BASE_SFX_TEXTFILE + TFT_CONTENT_END) {
674 if (BaseSounds::GetUsedSet() == nullptr) return;
675
677 return;
678 }
679 if (widget >= WID_GO_BASE_MUSIC_TEXTFILE && widget < WID_GO_BASE_MUSIC_TEXTFILE + TFT_CONTENT_END) {
680 if (BaseMusic::GetUsedSet() == nullptr) return;
681
683 return;
684 }
685 switch (widget) {
688 case WID_GO_TAB_SOUND:
690 this->SetTab(widget);
691 break;
692
695 case PS_ASK:
696 case PS_NO:
698 break;
699
700 case PS_YES:
702 break;
703 }
704
707 break;
708
710 OpenBrowser(NETWORK_SURVEY_DETAILS_LINK);
711 break;
712
714 ShowSurveyResultTextfileWindow();
715 break;
716
717 case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
718 /* try to toggle full-screen on/off */
719 if (!ToggleFullScreen(!_fullscreen)) {
721 }
724 break;
725
731#ifndef __APPLE__
735#endif
736 break;
737
739 if (!_video_hw_accel) break;
740
743
748 break;
749
752
754 this->SetDirty();
755
757 ReInitAllWindows(true);
758 break;
759 }
760
761#ifdef HAS_TRUETYPE_FONT
763 _fcsettings.prefer_sprite = !_fcsettings.prefer_sprite;
764
767 this->SetDirty();
768
769 InitFontCache(false);
770 InitFontCache(true);
771 ClearFontCache();
775 ReInitAllWindows(true);
776 break;
777
779 _fcsettings.global_aa = !_fcsettings.global_aa;
780
783
784 ClearFontCache();
785 break;
786#endif /* HAS_TRUETYPE_FONT */
787
788 case WID_GO_GUI_SCALE:
789 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, _ctrl_pressed ? 0 : SCALE_NMARKS, this->gui_scale)) {
790 this->SetWidgetDirty(widget);
791 }
792
793 if (click_count > 0) this->mouse_capture_widget = widget;
794 break;
795
797 {
798 if (_gui_scale_cfg == -1) {
801 } else {
802 _gui_scale_cfg = -1;
804 if (AdjustGUIZoom(false)) ReInitAllWindows(true);
805 this->gui_scale = _gui_scale;
806 }
807 this->SetWidgetDirty(widget);
808 break;
809 }
810
812 auto *used_set = BaseGraphics::GetUsedSet();
813 if (used_set == nullptr || !used_set->IsConfigurable()) break;
814 GRFConfig &extra_cfg = used_set->GetOrCreateExtraConfig();
815 if (extra_cfg.param.empty()) extra_cfg.SetParameterDefaults();
816 OpenGRFParameterWindow(true, extra_cfg, _game_mode == GM_MENU);
817 if (_game_mode == GM_MENU) this->reload = true;
818 break;
819 }
820
824 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, 0, INT8_MAX, 0, vol)) {
825 if (widget == WID_GO_BASE_MUSIC_VOLUME) {
827 } else {
828 SetEffectVolume(vol);
829 }
830 this->SetWidgetDirty(widget);
832 }
833
834 if (click_count > 0) this->mouse_capture_widget = widget;
835 break;
836 }
837
839 ShowMusicWindow();
840 break;
841 }
842
844 if (BaseGraphics::GetUsedSet() == nullptr || BaseGraphics::GetUsedSet()->url.empty()) return;
845 OpenBrowser(BaseGraphics::GetUsedSet()->url);
846 break;
847
849 if (BaseSounds::GetUsedSet() == nullptr || BaseSounds::GetUsedSet()->url.empty()) return;
850 OpenBrowser(BaseSounds::GetUsedSet()->url);
851 break;
852
854 if (BaseMusic::GetUsedSet() == nullptr || BaseMusic::GetUsedSet()->url.empty()) return;
855 OpenBrowser(BaseMusic::GetUsedSet()->url);
856 break;
857
860 break;
861
864 break;
865
868 break;
869
878 int selected;
879 DropDownList list = this->BuildDropDownList(widget, &selected);
880 if (!list.empty()) {
881 ShowDropDownList(this, std::move(list), selected, widget);
882 } else {
884 }
885 break;
886 }
887 }
888 }
889
890 void OnMouseLoop() override
891 {
892 if (_left_button_down || this->gui_scale == _gui_scale) return;
893
894 _gui_scale_cfg = this->gui_scale;
895
896 if (AdjustGUIZoom(false)) {
897 ReInitAllWindows(true);
899 this->SetDirty();
900 }
901 }
902
903 void OnDropdownSelect(WidgetID widget, int index) override
904 {
905 switch (widget) {
906 case WID_GO_CURRENCY_DROPDOWN: // Currency
907 if (index == CURRENCY_CUSTOM) ShowCustCurrency();
908 this->opt->locale.currency = index;
909 ReInitAllWindows(false);
910 break;
911
912 case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
915 this->SetDirty();
916 break;
917
918 case WID_GO_LANG_DROPDOWN: // Change interface language
922 ClearAllCachedNames();
924 CheckBlitter();
925 ReInitAllWindows(false);
926 break;
927
928 case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
929 if ((uint)index < _resolutions.size() && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
930 this->SetDirty();
931 }
932 break;
933
935 _settings_client.gui.refresh_rate = *std::next(_refresh_rates.begin(), index);
937 /* Show warning to the user that this refresh rate might not be suitable on
938 * larger maps with many NewGRFs and vehicles. */
940 }
941 break;
942 }
943
945 if (_game_mode == GM_MENU) {
947 auto set = BaseGraphics::GetSet(index);
949 this->reload = true;
950 this->InvalidateData();
951 }
952 break;
953
955 ChangeSoundSet(index);
956 break;
957
959 ChangeMusicSet(index);
960 break;
961 }
962 }
963
969 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
970 {
971 if (!gui_scope) return;
976
977#ifndef __APPLE__
980#endif
981
984#ifdef HAS_TRUETYPE_FONT
988#endif /* HAS_TRUETYPE_FONT */
989
990 this->SetWidgetDisabledState(WID_GO_BASE_GRF_DROPDOWN, _game_mode != GM_MENU);
991
993
997
998 for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
1002 }
1003
1005 }
1006};
1007
1008static constexpr NWidgetPart _nested_game_options_widgets[] = {
1010 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1011 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1012 EndContainer(),
1013 NWidget(WWT_PANEL, COLOUR_GREY),
1015 NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_GENERAL), SetMinimalTextLines(2, 0), SetStringTip(STR_GAME_OPTIONS_TAB_GENERAL, STR_GAME_OPTIONS_TAB_GENERAL_TOOLTIP), SetFill(1, 0),
1016 NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_GRAPHICS), SetMinimalTextLines(2, 0), SetStringTip(STR_GAME_OPTIONS_TAB_GRAPHICS, STR_GAME_OPTIONS_TAB_GRAPHICS_TOOLTIP), SetFill(1, 0),
1017 NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_SOUND), SetMinimalTextLines(2, 0), SetStringTip(STR_GAME_OPTIONS_TAB_SOUND, STR_GAME_OPTIONS_TAB_SOUND_TOOLTIP), SetFill(1, 0),
1018 NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_SOCIAL), SetMinimalTextLines(2, 0), SetStringTip(STR_GAME_OPTIONS_TAB_SOCIAL, STR_GAME_OPTIONS_TAB_SOCIAL_TOOLTIP), SetFill(1, 0),
1019 EndContainer(),
1020 EndContainer(),
1021 NWidget(WWT_PANEL, COLOUR_GREY),
1023 /* General tab */
1025 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_LANGUAGE),
1026 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_LANG_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_RAW_STRING, STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0),
1027 EndContainer(),
1028
1029 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME),
1030 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_AUTOSAVE_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_STRING, STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP), SetFill(1, 0),
1031 EndContainer(),
1032
1033 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME),
1034 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_CURRENCY_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_STRING2, STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP), SetFill(1, 0),
1035 EndContainer(),
1036
1037 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GO_SURVEY_SEL),
1038 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_FRAME), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1040 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY),
1041 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_SURVEY_PARTICIPATE_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_PARTICIPATE_SURVEY_TOOLTIP),
1042 EndContainer(),
1044 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_SURVEY_PREVIEW_BUTTON), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW, STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW_TOOLTIP),
1045 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_SURVEY_LINK_BUTTON), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK, STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK_TOOLTIP),
1046 EndContainer(),
1047 EndContainer(),
1048 EndContainer(),
1049 EndContainer(),
1050
1051 /* Graphics tab */
1053 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_GUI_SCALE_FRAME),
1055 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_GUI_SCALE), SetMinimalSize(67, 0), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FS_SMALL), SetFill(0, 0), SetToolTip(STR_GAME_OPTIONS_GUI_SCALE_TOOLTIP),
1057 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_GUI_SCALE_AUTO),
1058 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_SCALE_AUTO), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_SCALE_AUTO_TOOLTIP),
1059 EndContainer(),
1061 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_GUI_SCALE_BEVELS),
1062 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_SCALE_BEVEL_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_SCALE_BEVELS_TOOLTIP),
1063 EndContainer(),
1064#ifdef HAS_TRUETYPE_FONT
1066 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_GUI_FONT_SPRITE),
1067 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_FONT_SPRITE), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_FONT_SPRITE_TOOLTIP),
1068 EndContainer(),
1070 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_GUI_FONT_AA),
1071 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_FONT_AA), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_FONT_AA_TOOLTIP),
1072 EndContainer(),
1073#endif /* HAS_TRUETYPE_FONT */
1074 EndContainer(),
1075 EndContainer(),
1076
1077 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_GRAPHICS),
1080 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_RESOLUTION),
1081 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_RESOLUTION_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_STRING2, STR_GAME_OPTIONS_RESOLUTION_TOOLTIP),
1082 EndContainer(),
1084 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_REFRESH_RATE),
1085 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_REFRESH_RATE_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP),
1086 EndContainer(),
1088 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_FULLSCREEN),
1089 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
1090 EndContainer(),
1092 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_VIDEO_ACCELERATION),
1093 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_ACCEL_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP),
1094 EndContainer(),
1095#ifndef __APPLE__
1097 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_VIDEO_VSYNC),
1098 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_VSYNC_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP),
1099 EndContainer(),
1100#endif
1103 EndContainer(),
1104 EndContainer(),
1105 EndContainer(),
1106
1107 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_BASE_GRF), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0), SetFill(1, 0),
1109 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP), SetFill(1, 0),
1110 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_PARAMETERS), SetStringTip(STR_NEWGRF_SETTINGS_SET_PARAMETERS),
1111 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1112 EndContainer(),
1113 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_BASE_GRF_DESCRIPTION), SetMinimalSize(200, 0), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP), SetFill(1, 0),
1116 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
1117 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1118 EndContainer(),
1120 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1121 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1122 EndContainer(),
1123 EndContainer(),
1124 EndContainer(),
1125 EndContainer(),
1126
1127 /* Sound/Music tab */
1129 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_VOLUME), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0),
1131 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_TEXT_SFX_VOLUME), SetMinimalSize(0, 12), SetStringTip(STR_GAME_OPTIONS_SFX_VOLUME),
1132 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_BASE_SFX_VOLUME), SetMinimalSize(67, 0), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FS_SMALL), SetFill(1, 0), SetToolTip(STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
1133 EndContainer(),
1135 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_TEXT_MUSIC_VOLUME), SetMinimalSize(0, 12), SetStringTip(STR_GAME_OPTIONS_MUSIC_VOLUME),
1136 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_BASE_MUSIC_VOLUME), SetMinimalSize(67, 0), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FS_SMALL), SetFill(1, 0), SetToolTip(STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
1137 EndContainer(),
1138 EndContainer(),
1139
1140 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_BASE_SFX), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1142 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP), SetFill(1, 0),
1143 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1144 EndContainer(),
1145 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_BASE_SFX_DESCRIPTION), SetMinimalSize(200, 0), SetMinimalTextLines(1, 0), SetToolTip(STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP), SetFill(1, 0),
1148 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
1149 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1150 EndContainer(),
1152 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1153 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1154 EndContainer(),
1155 EndContainer(),
1156 EndContainer(),
1157
1158 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_BASE_MUSIC), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1160 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP), SetFill(1, 0),
1161 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1162 EndContainer(),
1164 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_BASE_MUSIC_DESCRIPTION), SetMinimalSize(200, 0), SetMinimalTextLines(1, 0), SetToolTip(STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0),
1166 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_JUKEBOX), SetMinimalSize(22, 22), SetSpriteTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
1167 EndContainer(),
1168 EndContainer(),
1171 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
1172 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1173 EndContainer(),
1175 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1176 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1177 EndContainer(),
1178 EndContainer(),
1179 EndContainer(),
1180 EndContainer(),
1181
1182 /* Social tab */
1185 EndContainer(),
1186 EndContainer(),
1187 EndContainer(),
1188};
1189
1190static WindowDesc _game_options_desc(
1191 WDP_CENTER, nullptr, 0, 0,
1193 {},
1194 _nested_game_options_widgets
1195);
1196
1199{
1201 new GameOptionsWindow(_game_options_desc);
1202}
1203
1204static int SETTING_HEIGHT = 11;
1205
1210enum class SettingEntryFlag : uint8_t {
1213 LastField,
1214 Filtered,
1215};
1217
1219
1230
1231
1239
1243 uint8_t level;
1244
1245 BaseSettingEntry() : flags(), level(0) {}
1246 virtual ~BaseSettingEntry() = default;
1247
1248 virtual void Init(uint8_t level = 0);
1249 virtual void FoldAll() {}
1250 virtual void UnFoldAll() {}
1251 virtual void ResetAll() = 0;
1252
1257 void SetLastField(bool last_field) { this->flags.Set(SettingEntryFlag::LastField, last_field); }
1258
1259 virtual uint Length() const = 0;
1260 virtual void GetFoldingState([[maybe_unused]] bool &all_folded, [[maybe_unused]] bool &all_unfolded) const {}
1261 virtual bool IsVisible(const BaseSettingEntry *item) const;
1262 virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
1263 virtual uint GetMaxHelpHeight([[maybe_unused]] int maxw) { return 0; }
1264
1269 bool IsFiltered() const { return this->flags.Test(SettingEntryFlag::Filtered); }
1270
1271 virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible) = 0;
1272
1273 virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row = 0, uint parent_last = 0) const;
1274
1275protected:
1276 virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
1277};
1278
1281 const char *name;
1283
1284 SettingEntry(const char *name);
1285
1286 void Init(uint8_t level = 0) override;
1287 void ResetAll() override;
1288 uint Length() const override;
1289 uint GetMaxHelpHeight(int maxw) override;
1290 bool UpdateFilterState(SettingFilter &filter, bool force_visible) override;
1291
1292 void SetButtons(SettingEntryFlags new_val);
1293
1294protected:
1295 void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const override;
1296
1297private:
1299};
1300
1303 typedef std::vector<BaseSettingEntry*> EntryVector;
1304 EntryVector entries;
1305
1306 template <typename T>
1307 T *Add(T *item)
1308 {
1309 this->entries.push_back(item);
1310 return item;
1311 }
1312
1313 void Init(uint8_t level = 0);
1314 void ResetAll();
1315 void FoldAll();
1316 void UnFoldAll();
1317
1318 uint Length() const;
1319 void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
1320 bool IsVisible(const BaseSettingEntry *item) const;
1321 BaseSettingEntry *FindEntry(uint row, uint *cur_row);
1322 uint GetMaxHelpHeight(int maxw);
1323
1324 bool UpdateFilterState(SettingFilter &filter, bool force_visible);
1325
1326 uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row = 0, uint parent_last = 0) const;
1327};
1328
1332 bool folded;
1333
1335
1336 void Init(uint8_t level = 0) override;
1337 void ResetAll() override;
1338 void FoldAll() override;
1339 void UnFoldAll() override;
1340
1341 uint Length() const override;
1342 void GetFoldingState(bool &all_folded, bool &all_unfolded) const override;
1343 bool IsVisible(const BaseSettingEntry *item) const override;
1344 BaseSettingEntry *FindEntry(uint row, uint *cur_row) override;
1345 uint GetMaxHelpHeight(int maxw) override { return SettingsContainer::GetMaxHelpHeight(maxw); }
1346
1347 bool UpdateFilterState(SettingFilter &filter, bool force_visible) override;
1348
1349 uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row = 0, uint parent_last = 0) const override;
1350
1351protected:
1352 void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const override;
1353};
1354
1355/* == BaseSettingEntry methods == */
1356
1361void BaseSettingEntry::Init(uint8_t level)
1362{
1363 this->level = level;
1364}
1365
1373{
1374 if (this->IsFiltered()) return false;
1375 return this == item;
1376}
1377
1385{
1386 if (this->IsFiltered()) return nullptr;
1387 if (row_num == *cur_row) return this;
1388 (*cur_row)++;
1389 return nullptr;
1390}
1391
1421uint BaseSettingEntry::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
1422{
1423 if (this->IsFiltered()) return cur_row;
1424 if (cur_row >= max_row) return cur_row;
1425
1426 bool rtl = _current_text_dir == TD_RTL;
1427 int offset = (rtl ? -(int)_circle_size.width : (int)_circle_size.width) / 2;
1429
1430 int x = rtl ? right : left;
1431 if (cur_row >= first_row) {
1432 int colour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
1433 y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
1434
1435 /* Draw vertical for parent nesting levels */
1436 for (uint lvl = 0; lvl < this->level; lvl++) {
1437 if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
1438 x += level_width;
1439 }
1440 /* draw own |- prefix */
1441 int halfway_y = y + SETTING_HEIGHT / 2;
1442 int bottom_y = flags.Test(SettingEntryFlag::LastField) ? halfway_y : y + SETTING_HEIGHT - 1;
1443 GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
1444 /* Small horizontal line from the last vertical line */
1445 GfxDrawLine(x + offset, halfway_y, x + level_width - (rtl ? -WidgetDimensions::scaled.hsep_normal : WidgetDimensions::scaled.hsep_normal), halfway_y, colour);
1446 x += level_width;
1447
1448 this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
1449 }
1450 cur_row++;
1451
1452 return cur_row;
1453}
1454
1455/* == SettingEntry methods == */
1456
1462{
1463 this->name = name;
1464 this->setting = nullptr;
1465}
1466
1471void SettingEntry::Init(uint8_t level)
1472{
1474 this->setting = GetSettingFromName(this->name)->AsIntSetting();
1475}
1476
1477/* Sets the given setting entry to its default value */
1478void SettingEntry::ResetAll()
1479{
1481}
1482
1489{
1490 assert((new_val & SEF_BUTTONS_MASK) == new_val); // Should not touch any flags outside the buttons
1493}
1494
1497{
1498 return this->IsFiltered() ? 0 : 1;
1499}
1500
1507{
1508 return GetStringHeight(this->setting->GetHelp(), maxw);
1509}
1510
1517{
1518 /* There shall not be any restriction, i.e. all settings shall be visible. */
1519 if (mode == RM_ALL) return true;
1520
1521 const IntSettingDesc *sd = this->setting;
1522
1523 if (mode == RM_BASIC) return (this->setting->cat & SC_BASIC_LIST) != 0;
1524 if (mode == RM_ADVANCED) return (this->setting->cat & SC_ADVANCED_LIST) != 0;
1525
1526 /* Read the current value. */
1527 const void *object = ResolveObject(&GetGameSettings(), sd);
1528 int64_t current_value = sd->Read(object);
1529 int64_t filter_value;
1530
1531 if (mode == RM_CHANGED_AGAINST_DEFAULT) {
1532 /* This entry shall only be visible, if the value deviates from its default value. */
1533
1534 /* Read the default value. */
1535 filter_value = sd->GetDefaultValue();
1536 } else {
1537 assert(mode == RM_CHANGED_AGAINST_NEW);
1538 /* This entry shall only be visible, if the value deviates from
1539 * its value is used when starting a new game. */
1540
1541 /* Make sure we're not comparing the new game settings against itself. */
1542 assert(&GetGameSettings() != &_settings_newgame);
1543
1544 /* Read the new game's value. */
1545 filter_value = sd->Read(ResolveObject(&_settings_newgame, sd));
1546 }
1547
1548 return current_value != filter_value;
1549}
1550
1557bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
1558{
1560
1561 bool visible = true;
1562
1563 const IntSettingDesc *sd = this->setting;
1564 if (!force_visible && !filter.string.IsEmpty()) {
1565 /* Process the search text filter for this item. */
1566 filter.string.ResetState();
1567
1568 SetDParam(0, STR_EMPTY);
1569 filter.string.AddLine(sd->GetTitle());
1570 filter.string.AddLine(sd->GetHelp());
1571
1572 visible = filter.string.GetState();
1573 }
1574
1575 if (visible) {
1576 if (filter.type != ST_ALL && sd->GetType() != filter.type) {
1577 filter.type_hides = true;
1578 visible = false;
1579 }
1580 if (!this->IsVisibleByRestrictionMode(filter.mode)) {
1581 while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
1582 visible = false;
1583 }
1584 }
1585
1586 if (!visible) this->flags.Set(SettingEntryFlag::Filtered);
1587 return visible;
1588}
1589
1590static const void *ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd)
1591{
1593 if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
1594 return &Company::Get(_local_company)->settings;
1595 }
1596 return &_settings_client.company;
1597 }
1598 return settings_ptr;
1599}
1600
1609void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1610{
1611 const IntSettingDesc *sd = this->setting;
1612 int state = (this->flags & SEF_BUTTONS_MASK).base();
1613
1614 bool rtl = _current_text_dir == TD_RTL;
1615 uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
1616 uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide);
1617 uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide : 0);
1618 uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
1619
1620 /* We do not allow changes of some items when we are a client in a networkgame */
1621 bool editable = sd->IsEditable();
1622
1623 auto [min_val, max_val] = sd->GetRange();
1624 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
1625 if (sd->IsBoolSetting()) {
1626 /* Draw checkbox for boolean-value either on/off */
1627 DrawBoolButton(buttons_left, button_y, value != 0, editable);
1628 } else if (sd->flags.Test(SettingFlag::GuiDropdown)) {
1629 /* Draw [v] button for settings of an enum-type */
1630 DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1631 } else {
1632 /* Draw [<][>] boxes for settings of an integer-type */
1633 DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1634 editable && value != (sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val), editable && static_cast<uint32_t>(value) != max_val);
1635 }
1636 auto [param1, param2] = sd->GetValueParams(value);
1637 DrawString(text_left, text_right, y + (SETTING_HEIGHT - GetCharacterHeight(FS_NORMAL)) / 2, GetString(sd->GetTitle(), STR_CONFIG_SETTING_VALUE, param1, param2), highlight ? TC_WHITE : TC_LIGHT_BLUE);
1638}
1639
1640/* == SettingsContainer methods == */
1641
1646void SettingsContainer::Init(uint8_t level)
1647{
1648 for (auto &it : this->entries) {
1649 it->Init(level);
1650 }
1651}
1652
1655{
1656 for (auto settings_entry : this->entries) {
1657 settings_entry->ResetAll();
1658 }
1659}
1660
1663{
1664 for (auto &it : this->entries) {
1665 it->FoldAll();
1666 }
1667}
1668
1671{
1672 for (auto &it : this->entries) {
1673 it->UnFoldAll();
1674 }
1675}
1676
1682void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1683{
1684 for (auto &it : this->entries) {
1685 it->GetFoldingState(all_folded, all_unfolded);
1686 }
1687}
1688
1696{
1697 bool visible = false;
1698 bool first_visible = true;
1699 for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1700 visible |= (*it)->UpdateFilterState(filter, force_visible);
1701 (*it)->SetLastField(first_visible);
1702 if (visible && first_visible) first_visible = false;
1703 }
1704 return visible;
1705}
1706
1707
1715{
1716 for (const auto &it : this->entries) {
1717 if (it->IsVisible(item)) return true;
1718 }
1719 return false;
1720}
1721
1724{
1725 uint length = 0;
1726 for (const auto &it : this->entries) {
1727 length += it->Length();
1728 }
1729 return length;
1730}
1731
1739{
1740 BaseSettingEntry *pe = nullptr;
1741 for (const auto &it : this->entries) {
1742 pe = it->FindEntry(row_num, cur_row);
1743 if (pe != nullptr) {
1744 break;
1745 }
1746 }
1747 return pe;
1748}
1749
1756{
1757 uint biggest = 0;
1758 for (const auto &it : this->entries) {
1759 biggest = std::max(biggest, it->GetMaxHelpHeight(maxw));
1760 }
1761 return biggest;
1762}
1763
1764
1779uint SettingsContainer::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
1780{
1781 for (const auto &it : this->entries) {
1782 cur_row = it->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1783 if (cur_row >= max_row) break;
1784 }
1785 return cur_row;
1786}
1787
1788/* == SettingsPage methods == */
1789
1795{
1796 this->title = title;
1797 this->folded = true;
1798}
1799
1804void SettingsPage::Init(uint8_t level)
1805{
1808}
1809
1812{
1813 for (auto settings_entry : this->entries) {
1814 settings_entry->ResetAll();
1815 }
1816}
1817
1820{
1821 if (this->IsFiltered()) return;
1822 this->folded = true;
1823
1825}
1826
1829{
1830 if (this->IsFiltered()) return;
1831 this->folded = false;
1832
1834}
1835
1841void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1842{
1843 if (this->IsFiltered()) return;
1844
1845 if (this->folded) {
1846 all_unfolded = false;
1847 } else {
1848 all_folded = false;
1849 }
1850
1851 SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1852}
1853
1860bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1861{
1862 if (!force_visible && !filter.string.IsEmpty()) {
1863 filter.string.ResetState();
1864 filter.string.AddLine(this->title);
1865 force_visible = filter.string.GetState();
1866 }
1867
1868 bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1869 this->flags.Set(SettingEntryFlag::Filtered, !visible);
1870 return visible;
1871}
1872
1880{
1881 if (this->IsFiltered()) return false;
1882 if (this == item) return true;
1883 if (this->folded) return false;
1884
1885 return SettingsContainer::IsVisible(item);
1886}
1887
1890{
1891 if (this->IsFiltered()) return 0;
1892 if (this->folded) return 1; // Only displaying the title
1893
1894 return 1 + SettingsContainer::Length();
1895}
1896
1903BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1904{
1905 if (this->IsFiltered()) return nullptr;
1906 if (row_num == *cur_row) return this;
1907 (*cur_row)++;
1908 if (this->folded) return nullptr;
1909
1910 return SettingsContainer::FindEntry(row_num, cur_row);
1911}
1912
1927uint SettingsPage::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
1928{
1929 if (this->IsFiltered()) return cur_row;
1930 if (cur_row >= max_row) return cur_row;
1931
1932 cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1933
1934 if (!this->folded) {
1936 assert(this->level < 8 * sizeof(parent_last));
1937 SetBit(parent_last, this->level); // Add own last-field state
1938 }
1939
1940 cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1941 }
1942
1943 return cur_row;
1944}
1945
1952void SettingsPage::DrawSetting(GameSettings *, int left, int right, int y, bool) const
1953{
1954 bool rtl = _current_text_dir == TD_RTL;
1955 DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1956 DrawString(rtl ? left : left + _circle_size.width + WidgetDimensions::scaled.hsep_normal, rtl ? right - _circle_size.width - WidgetDimensions::scaled.hsep_normal : right, y + (SETTING_HEIGHT - GetCharacterHeight(FS_NORMAL)) / 2, this->title, TC_ORANGE);
1957}
1958
1961{
1962 static SettingsContainer *main = nullptr;
1963
1964 if (main == nullptr)
1965 {
1966 /* Build up the dynamic settings-array only once per OpenTTD session */
1967 main = new SettingsContainer();
1968
1969 SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1970 {
1971 localisation->Add(new SettingEntry("locale.units_velocity"));
1972 localisation->Add(new SettingEntry("locale.units_velocity_nautical"));
1973 localisation->Add(new SettingEntry("locale.units_power"));
1974 localisation->Add(new SettingEntry("locale.units_weight"));
1975 localisation->Add(new SettingEntry("locale.units_volume"));
1976 localisation->Add(new SettingEntry("locale.units_force"));
1977 localisation->Add(new SettingEntry("locale.units_height"));
1978 localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1979 }
1980
1981 SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1982 {
1983 graphics->Add(new SettingEntry("gui.zoom_min"));
1984 graphics->Add(new SettingEntry("gui.zoom_max"));
1985 graphics->Add(new SettingEntry("gui.sprite_zoom_min"));
1986 graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1987 graphics->Add(new SettingEntry("gui.linkgraph_colours"));
1988 graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1989 }
1990
1991 SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1992 {
1993 sound->Add(new SettingEntry("sound.click_beep"));
1994 sound->Add(new SettingEntry("sound.confirm"));
1995 sound->Add(new SettingEntry("sound.news_ticker"));
1996 sound->Add(new SettingEntry("sound.news_full"));
1997 sound->Add(new SettingEntry("sound.new_year"));
1998 sound->Add(new SettingEntry("sound.disaster"));
1999 sound->Add(new SettingEntry("sound.vehicle"));
2000 sound->Add(new SettingEntry("sound.ambient"));
2001 }
2002
2003 SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
2004 {
2005 SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
2006 {
2007 general->Add(new SettingEntry("gui.osk_activation"));
2008 general->Add(new SettingEntry("gui.hover_delay_ms"));
2009 general->Add(new SettingEntry("gui.errmsg_duration"));
2010 general->Add(new SettingEntry("gui.window_snap_radius"));
2011 general->Add(new SettingEntry("gui.window_soft_limit"));
2012 general->Add(new SettingEntry("gui.right_click_wnd_close"));
2013 }
2014
2015 SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
2016 {
2017 viewports->Add(new SettingEntry("gui.auto_scrolling"));
2018 viewports->Add(new SettingEntry("gui.scroll_mode"));
2019 viewports->Add(new SettingEntry("gui.smooth_scroll"));
2020 /* While the horizontal scrollwheel scrolling is written as general code, only
2021 * the cocoa (OSX) driver generates input for it.
2022 * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
2023 viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
2024 viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
2025#ifdef __APPLE__
2026 /* We might need to emulate a right mouse button on mac */
2027 viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
2028#endif
2029 viewports->Add(new SettingEntry("gui.population_in_label"));
2030 viewports->Add(new SettingEntry("gui.liveries"));
2031 viewports->Add(new SettingEntry("construction.train_signal_side"));
2032 viewports->Add(new SettingEntry("gui.measure_tooltip"));
2033 viewports->Add(new SettingEntry("gui.loading_indicators"));
2034 viewports->Add(new SettingEntry("gui.show_track_reservation"));
2035 }
2036
2037 SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
2038 {
2039 construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
2040 construction->Add(new SettingEntry("gui.persistent_buildingtools"));
2041 construction->Add(new SettingEntry("gui.default_rail_type"));
2042 construction->Add(new SettingEntry("gui.semaphore_build_before"));
2043 construction->Add(new SettingEntry("gui.signal_gui_mode"));
2044 construction->Add(new SettingEntry("gui.cycle_signal_types"));
2045 construction->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
2046 construction->Add(new SettingEntry("gui.auto_remove_signals"));
2047 }
2048
2049 interface->Add(new SettingEntry("gui.toolbar_pos"));
2050 interface->Add(new SettingEntry("gui.statusbar_pos"));
2051 interface->Add(new SettingEntry("gui.prefer_teamchat"));
2052 interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
2053 interface->Add(new SettingEntry("gui.timetable_mode"));
2054 interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
2055 interface->Add(new SettingEntry("gui.show_newgrf_name"));
2056 interface->Add(new SettingEntry("gui.show_cargo_in_vehicle_lists"));
2057 }
2058
2059 SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
2060 {
2061 advisors->Add(new SettingEntry("gui.coloured_news_year"));
2062 advisors->Add(new SettingEntry("news_display.general"));
2063 advisors->Add(new SettingEntry("news_display.new_vehicles"));
2064 advisors->Add(new SettingEntry("news_display.accident"));
2065 advisors->Add(new SettingEntry("news_display.accident_other"));
2066 advisors->Add(new SettingEntry("news_display.company_info"));
2067 advisors->Add(new SettingEntry("news_display.acceptance"));
2068 advisors->Add(new SettingEntry("news_display.arrival_player"));
2069 advisors->Add(new SettingEntry("news_display.arrival_other"));
2070 advisors->Add(new SettingEntry("news_display.advice"));
2071 advisors->Add(new SettingEntry("gui.order_review_system"));
2072 advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
2073 advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
2074 advisors->Add(new SettingEntry("gui.old_vehicle_warn"));
2075 advisors->Add(new SettingEntry("gui.show_finances"));
2076 advisors->Add(new SettingEntry("news_display.economy"));
2077 advisors->Add(new SettingEntry("news_display.subsidies"));
2078 advisors->Add(new SettingEntry("news_display.open"));
2079 advisors->Add(new SettingEntry("news_display.close"));
2080 advisors->Add(new SettingEntry("news_display.production_player"));
2081 advisors->Add(new SettingEntry("news_display.production_other"));
2082 advisors->Add(new SettingEntry("news_display.production_nobody"));
2083 }
2084
2085 SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
2086 {
2087 company->Add(new SettingEntry("gui.starting_colour"));
2088 company->Add(new SettingEntry("gui.starting_colour_secondary"));
2089 company->Add(new SettingEntry("company.engine_renew"));
2090 company->Add(new SettingEntry("company.engine_renew_months"));
2091 company->Add(new SettingEntry("company.engine_renew_money"));
2092 company->Add(new SettingEntry("vehicle.servint_ispercent"));
2093 company->Add(new SettingEntry("vehicle.servint_trains"));
2094 company->Add(new SettingEntry("vehicle.servint_roadveh"));
2095 company->Add(new SettingEntry("vehicle.servint_ships"));
2096 company->Add(new SettingEntry("vehicle.servint_aircraft"));
2097 }
2098
2099 SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
2100 {
2101 accounting->Add(new SettingEntry("difficulty.infinite_money"));
2102 accounting->Add(new SettingEntry("economy.inflation"));
2103 accounting->Add(new SettingEntry("difficulty.initial_interest"));
2104 accounting->Add(new SettingEntry("difficulty.max_loan"));
2105 accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
2106 accounting->Add(new SettingEntry("difficulty.subsidy_duration"));
2107 accounting->Add(new SettingEntry("economy.feeder_payment_share"));
2108 accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
2109 accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
2110 accounting->Add(new SettingEntry("difficulty.construction_cost"));
2111 }
2112
2113 SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
2114 {
2115 SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
2116 {
2117 physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
2118 physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
2119 physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
2120 physics->Add(new SettingEntry("vehicle.freight_trains"));
2121 physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
2122 physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
2123 physics->Add(new SettingEntry("vehicle.smoke_amount"));
2124 physics->Add(new SettingEntry("vehicle.plane_speed"));
2125 }
2126
2127 SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
2128 {
2129 routing->Add(new SettingEntry("vehicle.road_side"));
2130 routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
2131 routing->Add(new SettingEntry("pf.reverse_at_signals"));
2132 routing->Add(new SettingEntry("pf.forbid_90_deg"));
2133 }
2134
2135 SettingsPage *orders = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ORDERS));
2136 {
2137 orders->Add(new SettingEntry("gui.new_nonstop"));
2138 orders->Add(new SettingEntry("gui.quick_goto"));
2139 orders->Add(new SettingEntry("gui.stop_location"));
2140 }
2141 }
2142
2143 SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
2144 {
2145 limitations->Add(new SettingEntry("construction.command_pause_level"));
2146 limitations->Add(new SettingEntry("construction.autoslope"));
2147 limitations->Add(new SettingEntry("construction.extra_dynamite"));
2148 limitations->Add(new SettingEntry("construction.map_height_limit"));
2149 limitations->Add(new SettingEntry("construction.max_bridge_length"));
2150 limitations->Add(new SettingEntry("construction.max_bridge_height"));
2151 limitations->Add(new SettingEntry("construction.max_tunnel_length"));
2152 limitations->Add(new SettingEntry("station.never_expire_airports"));
2153 limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
2154 limitations->Add(new SettingEntry("vehicle.max_trains"));
2155 limitations->Add(new SettingEntry("vehicle.max_roadveh"));
2156 limitations->Add(new SettingEntry("vehicle.max_aircraft"));
2157 limitations->Add(new SettingEntry("vehicle.max_ships"));
2158 limitations->Add(new SettingEntry("vehicle.max_train_length"));
2159 limitations->Add(new SettingEntry("station.station_spread"));
2160 limitations->Add(new SettingEntry("station.distant_join_stations"));
2161 limitations->Add(new SettingEntry("station.modified_catchment"));
2162 limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
2163 limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
2164 limitations->Add(new SettingEntry("construction.crossing_with_competitor"));
2165 limitations->Add(new SettingEntry("vehicle.disable_elrails"));
2166 limitations->Add(new SettingEntry("order.station_length_loading_penalty"));
2167 }
2168
2169 SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
2170 {
2171 disasters->Add(new SettingEntry("difficulty.disasters"));
2172 disasters->Add(new SettingEntry("difficulty.economy"));
2173 disasters->Add(new SettingEntry("vehicle.plane_crashes"));
2174 disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
2175 disasters->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
2176 disasters->Add(new SettingEntry("order.serviceathelipad"));
2177 }
2178
2179 SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
2180 {
2181 genworld->Add(new SettingEntry("game_creation.landscape"));
2182 genworld->Add(new SettingEntry("game_creation.land_generator"));
2183 genworld->Add(new SettingEntry("difficulty.terrain_type"));
2184 genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
2185 genworld->Add(new SettingEntry("game_creation.variety"));
2186 genworld->Add(new SettingEntry("game_creation.snow_coverage"));
2187 genworld->Add(new SettingEntry("game_creation.snow_line_height"));
2188 genworld->Add(new SettingEntry("game_creation.desert_coverage"));
2189 genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
2190 }
2191
2192 SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
2193 {
2194 SettingsPage *time = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TIME));
2195 {
2196 time->Add(new SettingEntry("economy.timekeeping_units"));
2197 time->Add(new SettingEntry("economy.minutes_per_calendar_year"));
2198 time->Add(new SettingEntry("game_creation.ending_year"));
2199 time->Add(new SettingEntry("gui.pause_on_newgame"));
2200 time->Add(new SettingEntry("gui.fast_forward_speed_limit"));
2201 }
2202
2203 SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
2204 {
2205 authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
2206 authorities->Add(new SettingEntry("economy.bribe"));
2207 authorities->Add(new SettingEntry("economy.exclusive_rights"));
2208 authorities->Add(new SettingEntry("economy.fund_roads"));
2209 authorities->Add(new SettingEntry("economy.fund_buildings"));
2210 authorities->Add(new SettingEntry("economy.station_noise_level"));
2211 }
2212
2213 SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
2214 {
2215 towns->Add(new SettingEntry("economy.town_cargo_scale"));
2216 towns->Add(new SettingEntry("economy.town_growth_rate"));
2217 towns->Add(new SettingEntry("economy.allow_town_roads"));
2218 towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
2219 towns->Add(new SettingEntry("economy.found_town"));
2220 towns->Add(new SettingEntry("economy.place_houses"));
2221 towns->Add(new SettingEntry("economy.town_layout"));
2222 towns->Add(new SettingEntry("economy.larger_towns"));
2223 towns->Add(new SettingEntry("economy.initial_city_size"));
2224 towns->Add(new SettingEntry("economy.town_cargogen_mode"));
2225 }
2226
2227 SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
2228 {
2229 industries->Add(new SettingEntry("economy.industry_cargo_scale"));
2230 industries->Add(new SettingEntry("difficulty.industry_density"));
2231 industries->Add(new SettingEntry("construction.raw_industry_construction"));
2232 industries->Add(new SettingEntry("construction.industry_platform"));
2233 industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
2234 industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
2235 industries->Add(new SettingEntry("economy.type"));
2236 industries->Add(new SettingEntry("station.serve_neutral_industries"));
2237 }
2238
2239 SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
2240 {
2241 cdist->Add(new SettingEntry("linkgraph.recalc_time"));
2242 cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
2243 cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
2244 cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
2245 cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
2246 cdist->Add(new SettingEntry("linkgraph.distribution_default"));
2247 cdist->Add(new SettingEntry("linkgraph.accuracy"));
2248 cdist->Add(new SettingEntry("linkgraph.demand_distance"));
2249 cdist->Add(new SettingEntry("linkgraph.demand_size"));
2250 cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
2251 }
2252
2253 SettingsPage *trees = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TREES));
2254 {
2255 trees->Add(new SettingEntry("game_creation.tree_placer"));
2256 trees->Add(new SettingEntry("construction.extra_tree_placement"));
2257 }
2258 }
2259
2260 SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
2261 {
2262 SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
2263 {
2264 npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
2265 npc->Add(new SettingEntry("script.script_max_memory_megabytes"));
2266 npc->Add(new SettingEntry("difficulty.competitor_speed"));
2267 npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
2268 npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
2269 npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
2270 npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
2271 npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
2272 }
2273
2274 ai->Add(new SettingEntry("economy.give_money"));
2275 }
2276
2277 SettingsPage *network = main->Add(new SettingsPage(STR_CONFIG_SETTING_NETWORK));
2278 {
2279 network->Add(new SettingEntry("network.use_relay_service"));
2280 }
2281
2282 main->Init();
2283 }
2284 return *main;
2285}
2286
2287static const StringID _game_settings_restrict_dropdown[] = {
2288 STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
2289 STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
2290 STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
2291 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
2292 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
2293};
2294static_assert(lengthof(_game_settings_restrict_dropdown) == RM_END);
2295
2303
2309static void ResetAllSettingsConfirmationCallback(Window *w, bool confirmed)
2310{
2311 if (confirmed) {
2314 w->InvalidateData();
2315 }
2316}
2317
2321
2327
2333
2334 Scrollbar *vscroll;
2335
2337 {
2338 this->warn_missing = WHR_NONE;
2339 this->warn_lines = 0;
2341 this->filter.min_cat = RM_ALL;
2342 this->filter.type = ST_ALL;
2343 this->filter.type_hides = false;
2344 this->settings_ptr = &GetGameSettings();
2345
2346 GetSettingsTree().FoldAll(); // Close all sub-pages
2347
2348 this->valuewindow_entry = nullptr; // No setting entry for which a entry window is opened
2349 this->clicked_entry = nullptr; // No numeric setting buttons are depressed
2350 this->last_clicked = nullptr;
2351 this->valuedropdown_entry = nullptr;
2352 this->closing_dropdown = false;
2353 this->manually_changed_folding = false;
2354
2355 this->CreateNestedTree();
2356 this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
2358
2360 this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
2362
2363 this->InvalidateData();
2364 }
2365
2366 void OnInit() override
2367 {
2368 _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
2369 }
2370
2372 {
2373 switch (widget) {
2376 resize.width = 1;
2377
2378 size.height = 5 * resize.height + WidgetDimensions::scaled.framerect.Vertical();
2379 break;
2380
2381 case WID_GS_HELP_TEXT: {
2382 static const StringID setting_types[] = {
2386 };
2387 for (const auto &setting_type : setting_types) {
2389 size.width = std::max(size.width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width + padding.width);
2390 }
2392 std::max(size.height, GetSettingsTree().GetMaxHelpHeight(size.width));
2393 break;
2394 }
2395
2399 break;
2400
2401 default:
2402 break;
2403 }
2404 }
2405
2406 void OnPaint() override
2407 {
2408 if (this->closing_dropdown) {
2409 this->closing_dropdown = false;
2410 assert(this->valuedropdown_entry != nullptr);
2411 this->valuedropdown_entry->SetButtons({});
2412 this->valuedropdown_entry = nullptr;
2413 }
2414
2415 /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
2416 const Rect panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext);
2418 int new_warn_lines;
2419 if (this->warn_missing == WHR_NONE) {
2420 new_warn_lines = 0;
2421 } else {
2422 SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
2424 }
2425 if (this->warn_lines != new_warn_lines) {
2426 this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
2427 this->warn_lines = new_warn_lines;
2428 }
2429
2430 this->DrawWidgets();
2431
2432 /* Draw the 'some search results are hidden' notice. */
2433 if (this->warn_missing != WHR_NONE) {
2434 SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
2435 DrawStringMultiLine(panel.WithHeight(this->warn_lines * GetCharacterHeight(FS_NORMAL)), warn_str, TC_FROMSTRING, SA_CENTER);
2436 }
2437 }
2438
2439 void SetStringParameters(WidgetID widget) const override
2440 {
2441 switch (widget) {
2443 SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
2444 break;
2445
2447 switch (this->filter.type) {
2452 }
2453 break;
2454 }
2455 }
2456
2457 DropDownList BuildDropDownList(WidgetID widget) const
2458 {
2459 DropDownList list;
2460 switch (widget) {
2462 for (int mode = 0; mode != RM_END; mode++) {
2463 /* If we are in adv. settings screen for the new game's settings,
2464 * we don't want to allow comparing with new game's settings. */
2465 bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
2466
2467 list.push_back(MakeDropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled));
2468 }
2469 break;
2470
2472 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL));
2473 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME));
2474 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY));
2475 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT));
2476 break;
2477 }
2478 return list;
2479 }
2480
2481 void DrawWidget(const Rect &r, WidgetID widget) const override
2482 {
2483 switch (widget) {
2484 case WID_GS_OPTIONSPANEL: {
2486 tr.top += this->warn_lines * SETTING_HEIGHT;
2487 uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
2488 int next_row = GetSettingsTree().Draw(settings_ptr, tr.left, tr.right, tr.top,
2489 this->vscroll->GetPosition(), last_row, this->last_clicked);
2491 break;
2492 }
2493
2494 case WID_GS_HELP_TEXT:
2495 if (this->last_clicked != nullptr) {
2496 const IntSettingDesc *sd = this->last_clicked->setting;
2497
2498 Rect tr = r;
2499 switch (sd->GetType()) {
2503 default: NOT_REACHED();
2504 }
2507
2508 auto [param1, param2] = sd->GetValueParams(sd->GetDefaultValue());
2511
2512 DrawStringMultiLine(tr, sd->GetHelp(), TC_WHITE);
2513 }
2514 break;
2515
2516 default:
2517 break;
2518 }
2519 }
2520
2526 {
2527 if (this->last_clicked != pe) this->SetDirty();
2528 this->last_clicked = pe;
2529 }
2530
2531 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2532 {
2533 switch (widget) {
2534 case WID_GS_EXPAND_ALL:
2535 this->manually_changed_folding = true;
2537 this->InvalidateData();
2538 break;
2539
2541 this->manually_changed_folding = true;
2543 this->InvalidateData();
2544 break;
2545
2546 case WID_GS_RESET_ALL:
2547 ShowQuery(
2550 this,
2552 );
2553 break;
2554
2556 DropDownList list = this->BuildDropDownList(widget);
2557 if (!list.empty()) {
2558 ShowDropDownList(this, std::move(list), this->filter.mode, widget);
2559 }
2560 break;
2561 }
2562
2563 case WID_GS_TYPE_DROPDOWN: {
2564 DropDownList list = this->BuildDropDownList(widget);
2565 if (!list.empty()) {
2566 ShowDropDownList(this, std::move(list), this->filter.type, widget);
2567 }
2568 break;
2569 }
2570 }
2571
2572 if (widget != WID_GS_OPTIONSPANEL) return;
2573
2575 if (btn == INT32_MAX || btn < this->warn_lines) return;
2576 btn -= this->warn_lines;
2577
2578 uint cur_row = 0;
2580
2581 if (clicked_entry == nullptr) return; // Clicked below the last setting of the page
2582
2583 int x = (_current_text_dir == TD_RTL ? this->width - 1 - pt.x : pt.x) - WidgetDimensions::scaled.frametext.left - (clicked_entry->level + 1) * WidgetDimensions::scaled.hsep_indent; // Shift x coordinate
2584 if (x < 0) return; // Clicked left of the entry
2585
2587 if (clicked_page != nullptr) {
2588 this->SetDisplayedHelpText(nullptr);
2589 clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
2590
2591 this->manually_changed_folding = true;
2592
2593 this->InvalidateData();
2594 return;
2595 }
2596
2597 SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
2598 assert(pe != nullptr);
2599 const IntSettingDesc *sd = pe->setting;
2600
2601 /* return if action is only active in network, or only settable by server */
2602 if (!sd->IsEditable()) {
2603 this->SetDisplayedHelpText(pe);
2604 return;
2605 }
2606
2607 auto [min_val, max_val] = sd->GetRange();
2608 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
2609
2610 /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2612 this->SetDisplayedHelpText(pe);
2613
2614 if (this->valuedropdown_entry == pe) {
2615 /* unclick the dropdown */
2617 this->closing_dropdown = false;
2618 this->valuedropdown_entry->SetButtons({});
2619 this->valuedropdown_entry = nullptr;
2620 } else {
2621 if (this->valuedropdown_entry != nullptr) this->valuedropdown_entry->SetButtons({});
2622 this->closing_dropdown = false;
2623
2625 int rel_y = (pt.y - wid->pos_y - WidgetDimensions::scaled.framerect.top) % wid->resize_y;
2626
2627 Rect wi_rect;
2628 wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2629 wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2630 wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2631 wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2632
2633 /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2634 if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2635 this->valuedropdown_entry = pe;
2636 this->valuedropdown_entry->SetButtons(SettingEntryFlag::LeftDepressed);
2637
2638 DropDownList list;
2640 auto [param1, param2] = sd->GetValueParams(i);
2641 list.push_back(MakeDropDownListStringItem(GetString(STR_JUST_STRING1, param1, param2), i));
2642 }
2643
2644 ShowDropDownListAt(this, std::move(list), value, WID_GS_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);
2645 }
2646 }
2647 this->SetDirty();
2648 } else if (x < SETTING_BUTTON_WIDTH) {
2649 this->SetDisplayedHelpText(pe);
2650 int32_t oldvalue = value;
2651
2652 if (sd->IsBoolSetting()) {
2653 value ^= 1;
2654 } else {
2655 /* Add a dynamic step-size to the scroller. In a maximum of
2656 * 50-steps you should be able to get from min to max,
2657 * unless specified otherwise in the 'interval' variable
2658 * of the current setting. */
2659 uint32_t step = (sd->interval == 0) ? ((max_val - min_val) / 50) : sd->interval;
2660 if (step == 0) step = 1;
2661
2662 /* don't allow too fast scrolling */
2663 if (this->flags.Test(WindowFlag::Timeout) && this->timeout_timer > 1) {
2664 _left_button_clicked = false;
2665 return;
2666 }
2667
2668 /* Increase or decrease the value and clamp it to extremes */
2669 if (x >= SETTING_BUTTON_WIDTH / 2) {
2670 value += step;
2671 if (min_val < 0) {
2672 assert(static_cast<int32_t>(max_val) >= 0);
2673 if (value > static_cast<int32_t>(max_val)) value = static_cast<int32_t>(max_val);
2674 } else {
2675 if (static_cast<uint32_t>(value) > max_val) value = static_cast<int32_t>(max_val);
2676 }
2677 if (value < min_val) value = min_val; // skip between "disabled" and minimum
2678 } else {
2679 value -= step;
2680 if (value < min_val) value = sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val;
2681 }
2682
2683 /* Set up scroller timeout for numeric values */
2684 if (value != oldvalue) {
2685 if (this->clicked_entry != nullptr) { // Release previous buttons if any
2686 this->clicked_entry->SetButtons({});
2687 }
2688 this->clicked_entry = pe;
2690 this->SetTimeout();
2691 _left_button_clicked = false;
2692 }
2693 }
2694
2695 if (value != oldvalue) {
2696 SetSettingValue(sd, value);
2697 this->SetDirty();
2698 }
2699 } else {
2700 /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2701 if (this->last_clicked == pe && !sd->IsBoolSetting() && !sd->flags.Test(SettingFlag::GuiDropdown)) {
2702 int64_t value64 = value;
2703 /* Show the correct currency-translated value */
2704 if (sd->flags.Test(SettingFlag::GuiCurrency)) value64 *= GetCurrency().rate;
2705
2706 CharSetFilter charset_filter = CS_NUMERAL; //default, only numeric input allowed
2707 if (min_val < 0) charset_filter = CS_NUMERAL_SIGNED; // special case, also allow '-' sign for negative input
2708
2709 this->valuewindow_entry = pe;
2710 /* Limit string length to 14 so that MAX_INT32 * max currency rate doesn't exceed MAX_INT64. */
2712 }
2713 this->SetDisplayedHelpText(pe);
2714 }
2715 }
2716
2717 void OnTimeout() override
2718 {
2719 if (this->clicked_entry != nullptr) { // On timeout, release any depressed buttons
2720 this->clicked_entry->SetButtons({});
2721 this->clicked_entry = nullptr;
2722 this->SetDirty();
2723 }
2724 }
2725
2726 void OnQueryTextFinished(std::optional<std::string> str) override
2727 {
2728 /* The user pressed cancel */
2729 if (!str.has_value()) return;
2730
2731 assert(this->valuewindow_entry != nullptr);
2732 const IntSettingDesc *sd = this->valuewindow_entry->setting;
2733
2734 int32_t value;
2735 if (!str->empty()) {
2736 long long llvalue = atoll(str->c_str());
2737
2738 /* Save the correct currency-translated value */
2739 if (sd->flags.Test(SettingFlag::GuiCurrency)) llvalue /= GetCurrency().rate;
2740
2741 value = ClampTo<int32_t>(llvalue);
2742 } else {
2743 value = sd->GetDefaultValue();
2744 }
2745
2746 SetSettingValue(this->valuewindow_entry->setting, value);
2747 this->SetDirty();
2748 }
2749
2750 void OnDropdownSelect(WidgetID widget, int index) override
2751 {
2752 switch (widget) {
2754 this->filter.mode = (RestrictionMode)index;
2755 if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2756 this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2757
2758 if (!this->manually_changed_folding) {
2759 /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2760 GetSettingsTree().UpdateFilterState(this->filter, false);
2762 }
2763 } else {
2764 /* Non-'changes' filter. Save as default. */
2766 }
2767 this->InvalidateData();
2768 break;
2769
2771 this->filter.type = (SettingType)index;
2772 this->InvalidateData();
2773 break;
2774
2776 /* Deal with drop down boxes on the panel. */
2777 assert(this->valuedropdown_entry != nullptr);
2778 const IntSettingDesc *sd = this->valuedropdown_entry->setting;
2779 assert(sd->flags.Test(SettingFlag::GuiDropdown));
2780
2781 SetSettingValue(sd, index);
2782 this->SetDirty();
2783 break;
2784 }
2785 }
2786
2787 void OnDropdownClose(Point pt, WidgetID widget, int index, bool instant_close) override
2788 {
2789 if (widget != WID_GS_SETTING_DROPDOWN) {
2790 /* Normally the default implementation of OnDropdownClose() takes care of
2791 * a few things. We want that behaviour here too, but only for
2792 * "normal" dropdown boxes. The special dropdown boxes added for every
2793 * setting that needs one can't have this call. */
2794 Window::OnDropdownClose(pt, widget, index, instant_close);
2795 } else {
2796 /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2797 * the same dropdown button was clicked again, and then not open the dropdown again.
2798 * So, we only remember that it was closed, and process it on the next OnPaint, which is
2799 * after OnClick. */
2800 assert(this->valuedropdown_entry != nullptr);
2801 this->closing_dropdown = true;
2802 this->SetDirty();
2803 }
2804 }
2805
2806 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2807 {
2808 if (!gui_scope) return;
2809
2810 /* Update which settings are to be visible. */
2811 RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2812 this->filter.min_cat = min_level;
2813 this->filter.type_hides = false;
2814 GetSettingsTree().UpdateFilterState(this->filter, false);
2815
2816 if (this->filter.string.IsEmpty()) {
2817 this->warn_missing = WHR_NONE;
2818 } else if (min_level < this->filter.min_cat) {
2819 this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2820 } else {
2821 this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2822 }
2823 this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2824
2825 if (this->last_clicked != nullptr && !GetSettingsTree().IsVisible(this->last_clicked)) {
2826 this->SetDisplayedHelpText(nullptr);
2827 }
2828
2829 bool all_folded = true;
2830 bool all_unfolded = true;
2832 this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2834 }
2835
2837 {
2838 if (wid == WID_GS_FILTER) {
2839 this->filter.string.SetFilterTerm(this->filter_editbox.text.GetText());
2840 if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2841 /* User never expanded/collapsed single pages and entered a filter term.
2842 * Expand everything, to save weird expand clicks, */
2844 }
2845 this->InvalidateData();
2846 }
2847 }
2848
2849 void OnResize() override
2850 {
2851 this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, WidgetDimensions::scaled.framerect.Vertical());
2852 }
2853};
2854
2856
2857static constexpr NWidgetPart _nested_settings_selection_widgets[] = {
2859 NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2860 NWidget(WWT_CAPTION, COLOUR_MAUVE), SetStringTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2861 NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2862 EndContainer(),
2863 NWidget(WWT_PANEL, COLOUR_MAUVE),
2866 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GS_RESTRICT_CATEGORY), SetStringTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY),
2867 NWidget(WWT_DROPDOWN, COLOUR_MAUVE, WID_GS_RESTRICT_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_STRING, STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
2868 EndContainer(),
2870 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GS_RESTRICT_TYPE), SetStringTip(STR_CONFIG_SETTING_RESTRICT_TYPE),
2871 NWidget(WWT_DROPDOWN, COLOUR_MAUVE, WID_GS_TYPE_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_STRING, STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
2872 EndContainer(),
2874 NWidget(WWT_TEXT, INVALID_COLOUR), SetFill(0, 1), SetStringTip(STR_CONFIG_SETTING_FILTER_TITLE),
2875 NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
2876 EndContainer(),
2877 EndContainer(),
2878 EndContainer(),
2882 EndContainer(),
2883 NWidget(WWT_PANEL, COLOUR_MAUVE),
2884 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2886 EndContainer(),
2888 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetStringTip(STR_CONFIG_SETTING_EXPAND_ALL),
2889 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetStringTip(STR_CONFIG_SETTING_COLLAPSE_ALL),
2890 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_RESET_ALL), SetStringTip(STR_CONFIG_SETTING_RESET_ALL),
2891 NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2892 EndContainer(),
2893 NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2894 EndContainer(),
2895};
2896
2897static WindowDesc _settings_selection_desc(
2898 WDP_CENTER, "settings", 510, 450,
2900 {},
2901 _nested_settings_selection_widgets
2902);
2903
2906{
2908 new GameSettingsWindow(_settings_selection_desc);
2909}
2910
2911
2921void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
2922{
2923 int colour = GetColourGradient(button_colour, SHADE_DARKER);
2924 Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2925
2926 Rect lr = {x, y, x + (int)dim.width - 1, y + (int)dim.height - 1};
2927 Rect rr = {x + (int)dim.width, y, x + (int)dim.width * 2 - 1, y + (int)dim.height - 1};
2928
2929 DrawFrameRect(lr, button_colour, (state == 1) ? FrameFlag::Lowered : FrameFlags{});
2930 DrawFrameRect(rr, button_colour, (state == 2) ? FrameFlag::Lowered : FrameFlags{});
2931 DrawSpriteIgnorePadding(SPR_ARROW_LEFT, PAL_NONE, lr, SA_CENTER);
2932 DrawSpriteIgnorePadding(SPR_ARROW_RIGHT, PAL_NONE, rr, SA_CENTER);
2933
2934 /* Grey out the buttons that aren't clickable */
2935 bool rtl = _current_text_dir == TD_RTL;
2936 if (rtl ? !clickable_right : !clickable_left) {
2938 }
2939 if (rtl ? !clickable_left : !clickable_right) {
2941 }
2942}
2943
2952void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2953{
2954 int colour = GetColourGradient(button_colour, SHADE_DARKER);
2955
2956 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
2957
2958 DrawFrameRect(r, button_colour, state ? FrameFlag::Lowered : FrameFlags{});
2959 DrawSpriteIgnorePadding(SPR_ARROW_DOWN, PAL_NONE, r, SA_CENTER);
2960
2961 if (!clickable) {
2963 }
2964}
2965
2973void DrawBoolButton(int x, int y, bool state, bool clickable)
2974{
2975 static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2976
2977 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
2978 DrawFrameRect(r, _bool_ctabs[state][clickable], state ? FrameFlag::Lowered : FrameFlags{});
2979}
2980
2982 int query_widget;
2983
2985 {
2986 this->InitNested();
2987
2988 SetButtonState();
2989 }
2990
2991 void SetButtonState()
2992 {
2997 }
2998
2999 void SetStringParameters(WidgetID widget) const override
3000 {
3001 switch (widget) {
3002 case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
3003 case WID_CC_SEPARATOR: SetDParamStr(0, GetCustomCurrency().separator); break;
3004 case WID_CC_PREFIX: SetDParamStr(0, GetCustomCurrency().prefix); break;
3005 case WID_CC_SUFFIX: SetDParamStr(0, GetCustomCurrency().suffix); break;
3006 case WID_CC_YEAR:
3008 SetDParam(1, GetCustomCurrency().to_euro);
3009 break;
3010
3011 case WID_CC_PREVIEW:
3012 SetDParam(0, 10000);
3013 break;
3014 }
3015 }
3016
3018 {
3019 switch (widget) {
3020 /* Set the appropriate width for the up/down buttons. */
3021 case WID_CC_RATE_DOWN:
3022 case WID_CC_RATE_UP:
3023 case WID_CC_YEAR_DOWN:
3024 case WID_CC_YEAR_UP:
3025 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH / 2, (uint)SETTING_BUTTON_HEIGHT});
3026 break;
3027
3028 /* Set the appropriate width for the edit buttons. */
3030 case WID_CC_PREFIX_EDIT:
3031 case WID_CC_SUFFIX_EDIT:
3032 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH, (uint)SETTING_BUTTON_HEIGHT});
3033 break;
3034
3035 /* Make sure the window is wide enough for the widest exchange rate */
3036 case WID_CC_RATE:
3037 SetDParam(0, 1);
3038 SetDParam(1, INT32_MAX);
3040 break;
3041 }
3042 }
3043
3044 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
3045 {
3046 int line = 0;
3047 int len = 0;
3048 std::string str;
3050
3051 switch (widget) {
3052 case WID_CC_RATE_DOWN:
3053 if (GetCustomCurrency().rate > 1) GetCustomCurrency().rate--;
3054 if (GetCustomCurrency().rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
3056 break;
3057
3058 case WID_CC_RATE_UP:
3062 break;
3063
3064 case WID_CC_RATE:
3066 len = 5;
3067 line = WID_CC_RATE;
3068 afilter = CS_NUMERAL;
3069 break;
3070
3072 case WID_CC_SEPARATOR:
3074 len = 7;
3075 line = WID_CC_SEPARATOR;
3076 break;
3077
3078 case WID_CC_PREFIX_EDIT:
3079 case WID_CC_PREFIX:
3080 str = GetCustomCurrency().prefix;
3081 len = 15;
3082 line = WID_CC_PREFIX;
3083 break;
3084
3085 case WID_CC_SUFFIX_EDIT:
3086 case WID_CC_SUFFIX:
3087 str = GetCustomCurrency().suffix;
3088 len = 15;
3089 line = WID_CC_SUFFIX;
3090 break;
3091
3092 case WID_CC_YEAR_DOWN:
3096 break;
3097
3098 case WID_CC_YEAR_UP:
3102 break;
3103
3104 case WID_CC_YEAR:
3105 str = GetString(STR_JUST_INT, GetCustomCurrency().to_euro);
3106 len = 7;
3107 line = WID_CC_YEAR;
3108 afilter = CS_NUMERAL;
3109 break;
3110 }
3111
3112 if (len != 0) {
3113 this->query_widget = line;
3114 ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
3115 }
3116
3117 this->SetTimeout();
3118 this->SetDirty();
3119 }
3120
3121 void OnQueryTextFinished(std::optional<std::string> str) override
3122 {
3123 if (!str.has_value()) return;
3124
3125 switch (this->query_widget) {
3126 case WID_CC_RATE:
3127 GetCustomCurrency().rate = Clamp(atoi(str->c_str()), 1, UINT16_MAX);
3128 break;
3129
3130 case WID_CC_SEPARATOR: // Thousands separator
3131 GetCustomCurrency().separator = std::move(*str);
3132 break;
3133
3134 case WID_CC_PREFIX:
3135 GetCustomCurrency().prefix = std::move(*str);
3136 break;
3137
3138 case WID_CC_SUFFIX:
3139 GetCustomCurrency().suffix = std::move(*str);
3140 break;
3141
3142 case WID_CC_YEAR: { // Year to switch to euro
3143 TimerGameCalendar::Year val{atoi(str->c_str())};
3144
3146 break;
3147 }
3148 }
3150 SetButtonState();
3151 }
3152
3153 void OnTimeout() override
3154 {
3155 this->SetDirty();
3156 }
3157};
3158
3159static constexpr NWidgetPart _nested_cust_currency_widgets[] = {
3161 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
3162 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
3163 EndContainer(),
3164 NWidget(WWT_PANEL, COLOUR_GREY),
3169 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetArrowWidgetTypeTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
3170 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetArrowWidgetTypeTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
3171 EndContainer(),
3172 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_RATE), SetStringTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
3173 EndContainer(),
3175 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
3176 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_SEPARATOR), SetStringTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
3177 EndContainer(),
3179 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
3180 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_PREFIX), SetStringTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
3181 EndContainer(),
3183 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
3184 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_SUFFIX), SetStringTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
3185 EndContainer(),
3188 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetArrowWidgetTypeTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
3189 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetArrowWidgetTypeTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
3190 EndContainer(),
3191 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_YEAR), SetStringTip(STR_JUST_STRING1, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
3192 EndContainer(),
3193 EndContainer(),
3194 NWidget(WWT_LABEL, INVALID_COLOUR, WID_CC_PREVIEW),
3195 SetStringTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP),
3196 EndContainer(),
3197 EndContainer(),
3198};
3199
3200static WindowDesc _cust_currency_desc(
3201 WDP_CENTER, nullptr, 0, 0,
3203 {},
3204 _nested_cust_currency_widgets
3205);
3206
3208static void ShowCustCurrency()
3209{
3211 new CustomCurrencyWindow(_cust_currency_desc);
3212}
void UpdateAllVirtCoords()
Update the viewport coordinates of all signs.
Base functions for all AIs.
Generic functions for replacing base data (graphics, sounds).
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
constexpr Timpl & Reset(Tvalue_type value)
Reset the value-th bit.
static const GraphicsSet * GetUsedSet()
Return the used set.
static int GetNumSets()
Count the number of available graphics sets.
static const GraphicsSet * GetSet(int index)
Get the name of the graphics set at the specified index.
static bool SetSet(const GraphicsSet *set)
Set the set to be used.
static bool NatSortFunc(std::unique_ptr< const DropDownListItem > const &first, std::unique_ptr< const DropDownListItem > const &second)
Natural sorting comparator function for DropDownList::sort().
static MusicDriver * GetInstance()
Get the currently active instance of the music driver.
virtual void SetVolume(uint8_t vol)=0
Set the volume, if possible.
Baseclass for nested widgets.
virtual void FillWidgetLookup(WidgetLookup &widget_lookup)=0
Fill the Window::widget_lookup with pointers to nested widgets in the tree.
void Add(std::unique_ptr< NWidgetBase > &&wid)
Append widget wid to container.
Definition widget.cpp:1281
std::vector< std::unique_ptr< NWidgetBase > > children
Child widgets in container.
void SetPIP(uint8_t pip_pre, uint8_t pip_inter, uint8_t pip_post)
Set additional pre/inter/post space for the container.
Definition widget.cpp:1513
Base class for a resizable nested widget.
void FillWidgetLookup(WidgetLookup &widget_lookup) override
Fill the Window::widget_lookup with pointers to nested widgets in the tree.
void Draw(const Window *w) override
Draw the widgets of the tree.
void SetupSmallestSize(Window *w) override
Compute smallest size needed by the widget.
std::string & GetWidestPlugin(T SocialIntegrationPlugin::*member) const
Find of all the plugins the one where the member is the widest (in pixels).
Vertical container.
void SetupSmallestSize(Window *w) override
Compute smallest size needed by the widget.
Definition widget.cpp:1739
Scrollbar data structure.
size_type GetCapacity() const
Gets the number of visible elements of the scrollbar.
void SetCount(size_t num)
Sets the number of elements in the list.
size_type GetScrolledRowFromWidget(int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition widget.cpp:2459
void SetCapacityFromWidget(Window *w, WidgetID widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget.
Definition widget.cpp:2533
size_type GetCount() const
Gets the number of elements in the list.
size_type GetPosition() const
Gets the position of the first visible element in the list.
std::string social_platform
Social platform this plugin is for.
std::string name
Name of the plugin.
std::string version
Version of the plugin.
@ PLATFORM_NOT_RUNNING
The plugin failed to initialize because the Social Platform is not running.
@ UNSUPPORTED_API
The plugin does not support the current API version.
@ RUNNING
The plugin is successfully loaded and running.
@ FAILED
The plugin failed to initialize.
@ DUPLICATE
Another plugin of the same Social Platform is already loaded.
@ INVALID_SIGNATURE
The signature of the plugin is invalid.
@ UNLOADED
The plugin is unloaded upon request.
static std::vector< SocialIntegrationPlugin * > GetPlugins()
Get the list of loaded social integration plugins.
static constexpr TimerGame< struct Calendar >::Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date,...
virtual void ToggleVsync(bool vsync)
Change the vsync setting.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
virtual std::vector< int > GetListOfMonitorRefreshRates()
Get a list of refresh rates of each available monitor.
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:40
RectPadding frametext
Padding inside frame with text.
Definition window_gui.h:41
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:28
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:58
int hsep_wide
Wide horizontal spacing.
Definition window_gui.h:62
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:94
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:38
int hsep_indent
Width of indentation for tree layouts.
Definition window_gui.h:63
Functions related to commands.
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
Configuration options of the network stuff.
static const std::string NETWORK_SURVEY_DETAILS_LINK
Link with more details & privacy statement of the survey.
Definition config.h:30
std::array< CurrencySpec, CURRENCY_END > _currency_specs
Array of currencies used by the system.
Definition currency.cpp:78
Functions to handle different currencies.
static constexpr TimerGameCalendar::Year MIN_EURO_YEAR
The earliest year custom currencies may switch to the Euro.
Definition currency.h:19
@ CURRENCY_CUSTOM
Custom currency.
Definition currency.h:58
CurrencySpec & GetCustomCurrency()
Get the custom currency.
Definition currency.h:109
static constexpr TimerGameCalendar::Year CF_NOEURO
Currency never switches to the Euro (as far as known).
Definition currency.h:17
const CurrencySpec & GetCurrency()
Get the currently selected currency.
Definition currency.h:118
std::vector< Dimension > _resolutions
List of resolutions.
Definition driver.cpp:26
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, bool instant_close, bool persist)
Show a drop down list.
Definition dropdown.cpp:404
Dimension GetDropDownListDimension(const DropDownList &list)
Determine width and height required to fully display a DropDownList.
Definition dropdown.cpp:363
void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, bool instant_close, bool persist)
Show a drop down list.
Definition dropdown.cpp:386
Common drop down list components.
Functions related to the drop down widget.
Types related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
#define DECLARE_INCREMENT_DECREMENT_OPERATORS(enum_type)
For some enums it is useful to have pre/post increment/decrement operators.
Definition enum_type.hpp:63
Functions related to errors.
@ WL_ERROR
Errors (eg. saving/loading failed)
Definition error.h:26
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, const CommandCost &cc)
Display an error message in a window.
Factory to 'query' all available blitters.
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game)
void InitFontCache(bool monospace)
(Re)initialize the font cache related things, i.e.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
Functions to read fonts from files and cache them.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:704
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:922
bool _left_button_down
Is left mouse button pressed?
Definition gfx.cpp:41
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:851
int GetStringLineCount(StringID str, int maxw)
Calculates number of lines of string.
Definition gfx.cpp:728
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:657
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
bool _left_button_clicked
Is left mouse button clicked?
Definition gfx.cpp:42
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:114
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:988
int _gui_scale_cfg
GUI scale in config.
Definition gfx.cpp:64
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:774
SwitchMode _switch_mode
The next mainloop command.
Definition gfx.cpp:49
bool AdjustGUIZoom(bool automatic)
Resolve GUI zoom level and adjust GUI to new zoom, if auto-suggestion is requested.
Definition gfx.cpp:1793
int _gui_scale
GUI scale, 100 is 100%.
Definition gfx.cpp:63
void CheckBlitter()
Check whether we still use the right blitter, or use another (better) one.
Definition gfxinit.cpp:326
@ FS_SMALL
Index of the small font in the font tables.
Definition gfx_type.h:244
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:243
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:377
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:385
@ FILLRECT_CHECKER
Draw only every second pixel, used for greying-out.
Definition gfx_type.h:333
constexpr NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
Obtain a nested widget (sub)tree from an external source.
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlag::ResizeX)
Widget part function for setting the aspect ratio.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
std::unique_ptr< NWidgetBase > MakeNWidgets(std::span< const NWidgetPart > nwid_parts, std::unique_ptr< NWidgetBase > &&container)
Construct a nested widget tree from an array of parts.
Definition widget.cpp:3381
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetArrowWidgetTypeTip(ArrowWidgetValues widget_type, StringID tip={})
Widget part function for setting the arrow widget type and tooltip.
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetAlignment(StringAlignment align)
Widget part function for setting the alignment of text/images.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
constexpr NWidgetPart SetPIPRatio(uint8_t ratio_pre, uint8_t ratio_inter, uint8_t ratio_post)
Widget part function for setting a pre/inter/post ratio.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:937
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1529
GUI functions that shouldn't be here.
Declaration of functions and types defined in highscore.h and highscore_gui.h.
Information about languages and their files.
LanguageList _languages
The actual list of language meta data.
Definition strings.cpp:53
const LanguageMetadata * _current_language
The currently loaded language.
Definition strings.cpp:54
bool ReadLanguagePack(const LanguageMetadata *lang)
Read a particular language.
Definition strings.cpp:2025
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
void ShowQuery(EncodedString &&caption, EncodedString &&message, Window *parent, QueryCallbackProc *callback, bool focus)
Show a confirmation window with standard 'yes' and 'no' buttons The window is aligned to the centre o...
void ShowQueryString(std::string_view str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
@ WID_TF_CAPTION
The caption of the window.
Definition misc_widget.h:50
Functions to mix sound samples.
Base for all music playback.
void ChangeMusicSet(int index)
Change the configured music set and reset playback.
bool _network_available
is network mode available?
Definition network.cpp:67
Basic functions/variables used all over the place.
Part of the network protocol handling content distribution.
void ShowNetworkContentListWindow(ContentVector *cv=nullptr, ContentType type1=CONTENT_TYPE_END, ContentType type2=CONTENT_TYPE_END)
Show the content list window with a given set of content.
GUIs related to networking.
Part of the network protocol handling opt-in survey.
@ Length
Vehicle length (trains and road vehicles)
Functions to find and configure NewGRFs.
void ChangeAutosaveFrequency(bool reset)
Reset the interval of the autosave.
Definition openttd.cpp:1312
@ SM_MENU
Switch to game intro menu.
Definition openttd.h:33
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:387
Base for the GUIs that have an edit box in them.
declaration of OTTD revision dependent variables
A number of safeguards to prevent using unsafe methods.
bool SetSettingValue(const IntSettingDesc *sd, int32_t value, bool force_newgame)
Top function to save the new value of an element of the Settings struct.
static const SettingDesc * GetSettingFromName(const std::string_view name, const SettingTable &settings)
Given a name of setting, return a setting description from the table.
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition settings.cpp:59
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:57
void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
Draw [<][>] boxes.
static void ResetAllSettingsConfirmationCallback(Window *w, bool confirmed)
Callback function for the reset all settings button.
WarnHiddenResult
Warnings about hidden search results.
@ WHR_CATEGORY_TYPE
Both category and type settings filtered matches away.
@ WHR_CATEGORY
Category setting filtered matches away.
@ WHR_NONE
Nothing was filtering matches away.
@ WHR_TYPE
Type setting filtered matches away.
static const uint32_t _autosave_dropdown_to_minutes[]
Available settings for autosave intervals.
static SettingsContainer & GetSettingsTree()
Construct settings tree.
static void AddCustomRefreshRates()
Add the refresh rate from the config and the refresh rates from all the monitors to our list of refre...
std::unique_ptr< NWidgetBase > MakeNWidgetSocialPlugins()
Construct nested container widget for managing the list of social plugins.
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
Draw a dropdown button.
void ShowBaseSetTextfileWindow(TextfileType file_type, const TBaseSet *baseset, StringID content_type)
Open the BaseSet version of the textfile window.
static int SETTING_HEIGHT
Height of a single setting in the tree view in pixels.
RestrictionMode
How the list of advanced settings is filtered.
@ RM_CHANGED_AGAINST_DEFAULT
Show only settings which are different compared to default values.
@ RM_ADVANCED
Display settings associated to the "advanced" list.
@ RM_ALL
List all settings regardless of the default/newgame/... values.
@ RM_CHANGED_AGAINST_NEW
Show only settings which are different compared to the user's new game setting values.
@ RM_END
End for iteration.
@ RM_BASIC
Display settings associated to the "basic" list.
void ShowGameSettings()
Open advanced settings window.
static uint GetCurrentResolutionIndex()
Get index of the current screen resolution.
void DrawBoolButton(int x, int y, bool state, bool clickable)
Draw a toggle button.
static void ShowCustCurrency()
Open custom currency window.
static constexpr SettingEntryFlags SEF_BUTTONS_MASK
Mask for button flags.
SettingEntryFlag
Flags for SettingEntry.
@ LeftDepressed
Of a numeric setting entry, the left button is depressed.
@ LastField
This entry is the last one in a (sub-)page.
@ RightDepressed
Of a numeric setting entry, the right button is depressed.
@ Filtered
Entry is hidden by the string filter.
void ShowGameOptions()
Open the game options window.
static Dimension _circle_size
Dimension of the circle +/- icon. This is here as not all users are within the class of the settings ...
Functions for setting GUIs.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
Functions and types used internally for the settings configurations.
@ GuiCurrency
The number represents money, so when reading value multiply by exchange rate.
@ PerCompany
This setting can be different for each company (saved in company struct).
@ GuiZeroIsSpecial
A value of zero is possible and has a custom string (the one after "strval").
@ GuiDropdown
The value represents a limited number of string-options (internally integer) presented as dropdown.
SettingType
Type of settings for filtering.
@ ST_CLIENT
Client setting.
@ ST_ALL
Used in setting filter to match all types.
@ ST_GAME
Game setting.
@ ST_COMPANY
Company setting.
@ SC_ADVANCED_LIST
Settings displayed in the list of advanced settings.
@ SC_BASIC_LIST
Settings displayed in the list of basic settings.
GameSettings & GetGameSettings()
Get the settings-object applicable for the current situation: the newgame settings when we're in the ...
@ WID_GS_TYPE_DROPDOWN
The drop down box to choose client/game/company/all settings.
@ WID_GS_SETTING_DROPDOWN
Dynamically created dropdown for changing setting value.
@ WID_GS_EXPAND_ALL
Expand all button.
@ WID_GS_OPTIONSPANEL
Panel widget containing the option lists.
@ WID_GS_RESTRICT_CATEGORY
Label upfront to the category drop-down box to restrict the list of settings to show.
@ WID_GS_HELP_TEXT
Information area to display help text of the selected option.
@ WID_GS_RESTRICT_DROPDOWN
The drop down box to restrict the list of settings.
@ WID_GS_RESTRICT_TYPE
Label upfront to the type drop-down box to restrict the list of settings to show.
@ WID_GS_RESET_ALL
Reset all button.
@ WID_GS_SCROLLBAR
Scrollbar.
@ WID_GS_COLLAPSE_ALL
Collapse all button.
@ WID_GS_FILTER
Text filter.
@ WID_GO_BASE_SFX_OPEN_URL
Open base SFX URL.
@ WID_GO_BASE_MUSIC_DESCRIPTION
Description of selected base music set.
@ WID_GO_BASE_MUSIC_CONTENT_DOWNLOAD
'Get Content' button for base music.
@ WID_GO_RESOLUTION_DROPDOWN
Dropdown for the resolution.
@ WID_GO_CURRENCY_DROPDOWN
Currency dropdown.
@ WID_GO_BASE_GRF_DESCRIPTION
Description of selected base GRF.
@ WID_GO_BASE_SFX_DESCRIPTION
Description of selected base SFX.
@ WID_GO_GUI_SCALE_BEVEL_BUTTON
Toggle for chunky bevels.
@ WID_GO_GUI_SCALE
GUI Scale slider.
@ WID_GO_BASE_SFX_TEXTFILE
Open base SFX readme, changelog (+1) or license (+2).
@ WID_GO_GUI_FONT_SPRITE
Toggle whether to prefer the sprite font over TTF fonts.
@ WID_GO_GUI_SCALE_AUTO
Autodetect GUI scale button.
@ WID_GO_SOCIAL_PLUGINS
Main widget handling the social plugins.
@ WID_GO_BASE_GRF_CONTENT_DOWNLOAD
'Get Content' button for base GRF.
@ WID_GO_BASE_GRF_TEXTFILE
Open base GRF readme, changelog (+1) or license (+2).
@ WID_GO_TAB_GENERAL
General tab.
@ WID_GO_BASE_GRF_DROPDOWN
Use to select a base GRF.
@ WID_GO_BASE_MUSIC_VOLUME
Change music volume.
@ WID_GO_BASE_SFX_VOLUME
Change sound effects volume.
@ WID_GO_BASE_GRF_PARAMETERS
Base GRF parameters.
@ WID_GO_LANG_DROPDOWN
Language dropdown.
@ WID_GO_GUI_FONT_AA
Toggle whether to anti-alias fonts.
@ WID_GO_VIDEO_VSYNC_BUTTON
Toggle for video vsync.
@ WID_GO_SURVEY_LINK_BUTTON
Button to open browser to go to the survey website.
@ WID_GO_TAB_SELECTION
Background of the tab selection.
@ WID_GO_SURVEY_PARTICIPATE_BUTTON
Toggle for participating in the automated survey.
@ WID_GO_AUTOSAVE_DROPDOWN
Dropdown to say how often to autosave.
@ WID_GO_TAB_GRAPHICS
Graphics tab.
@ WID_GO_TEXT_MUSIC_VOLUME
Music volume label.
@ WID_GO_BASE_MUSIC_JUKEBOX
Open the jukebox.
@ WID_GO_SOCIAL_PLUGIN_STATE
State of the social plugin.
@ WID_GO_SURVEY_SEL
Selection to hide survey if no JSON library is compiled in.
@ WID_GO_REFRESH_RATE_DROPDOWN
Dropdown for all available refresh rates.
@ WID_GO_SOCIAL_PLUGIN_TITLE
Title of the frame of the social plugin.
@ WID_GO_BASE_GRF_OPEN_URL
Open base GRF URL.
@ WID_GO_BASE_MUSIC_TEXTFILE
Open base music readme, changelog (+1) or license (+2).
@ WID_GO_VIDEO_ACCEL_BUTTON
Toggle for video acceleration.
@ WID_GO_TAB_SOCIAL
Social tab.
@ WID_GO_SURVEY_PREVIEW_BUTTON
Button to open a preview window with the survey results.
@ WID_GO_BASE_SFX_CONTENT_DOWNLOAD
'Get Content' button for base SFX.
@ WID_GO_SOCIAL_PLUGIN_PLATFORM
Platform of the social plugin.
@ WID_GO_BASE_MUSIC_DROPDOWN
Use to select a base music set.
@ WID_GO_BASE_MUSIC_OPEN_URL
Open base music URL.
@ WID_GO_FULLSCREEN_BUTTON
Toggle fullscreen.
@ WID_GO_TAB_SOUND
Sound tab.
@ WID_GO_BASE_SFX_DROPDOWN
Use to select a base SFX.
@ WID_GO_TEXT_SFX_VOLUME
Sound effects volume label.
@ WID_GO_VIDEO_DRIVER_INFO
Label showing details about the current video driver.
@ WID_CC_YEAR_DOWN
Down button.
@ WID_CC_YEAR
Year of introduction.
@ WID_CC_SUFFIX_EDIT
Suffix edit button.
@ WID_CC_SEPARATOR_EDIT
Separator edit button.
@ WID_CC_RATE_DOWN
Down button.
@ WID_CC_RATE_UP
Up button.
@ WID_CC_PREVIEW
Preview.
@ WID_CC_PREFIX
Current prefix.
@ WID_CC_PREFIX_EDIT
Prefix edit button.
@ WID_CC_SUFFIX
Current suffix.
@ WID_CC_YEAR_UP
Up button.
@ WID_CC_SEPARATOR
Current separator.
@ WID_CC_RATE
Rate of currency.
void DrawSliderWidget(Rect r, int min_value, int max_value, int nmarks, int value, SliderMarkFunc *mark_func)
Draw a slider widget with knob at given value.
Definition slider.cpp:31
bool ClickSliderWidget(Rect r, Point pt, int min_value, int max_value, int nmarks, int &value)
Handle click on a slider widget to change the value.
Definition slider.cpp:91
Interface definitions for game to report/respond to social integration.
void ChangeSoundSet(int index)
Change the configured sound set and reset sounds.
Definition sound.cpp:169
Functions related to sound.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:277
Functions related to low-level strings.
CharSetFilter
Valid filter types for IsValidChar.
Definition string_type.h:24
@ CS_NUMERAL
Only numeric ones.
Definition string_type.h:26
@ CS_NUMERAL_SIGNED
Only numbers and '-' for negative values.
Definition string_type.h:28
@ CS_ALPHANUMERAL
Both numeric and alphabetic and spaces and stuff.
Definition string_type.h:25
Searching and filtering using a stringterm.
const char * GetCurrentLanguageIsoCode()
Get the ISO language code of the currently loaded language.
Definition strings.cpp:2271
void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
Check whether the currently loaded language pack uses characters that the currently loaded font does ...
Definition strings.cpp:2379
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition strings.cpp:163
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:103
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition strings.cpp:420
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition strings.cpp:466
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
@ TD_RTL
Text is written right-to-left by default.
Window for displaying the textfile of a BaseSet.
const std::string name
Name of the content.
const StringID content_type
STR_CONTENT_TYPE_xxx for title.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
Data structure describing a single setting in a tab.
void SetLastField(bool last_field)
Set whether this is the last visible entry of the parent node.
bool IsFiltered() const
Check whether an entry is hidden due to filters.
virtual BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find setting entry at row row_num.
virtual void Init(uint8_t level=0)
Initialization of a setting entry.
virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
SettingEntryFlags flags
Flags of the setting entry.
virtual bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
uint8_t level
Nesting level of this setting entry.
CompanySettings company
default values for per-company settings
MusicSettings music
settings related to music/sound
NetworkSettings network
settings related to the network
GUISettings gui
settings related to the GUI
Specification of a currency.
Definition currency.h:76
std::string separator
The thousands separator for this currency.
Definition currency.h:78
std::string prefix
Prefix to apply when formatting money in this currency.
Definition currency.h:80
TimerGameCalendar::Year to_euro
Year of switching to the Euro. May also be CF_NOEURO or CF_ISEURO.
Definition currency.h:79
std::string suffix
Suffix to apply when formatting money in this currency.
Definition currency.h:81
std::string code
3 letter untranslated code to identify the currency.
Definition currency.h:82
uint16_t rate
The conversion rate compared to the base currency.
Definition currency.h:77
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
void OnTimeout() override
Called when this window's timeout has been reached.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
Dimensions (a width and height) of a rectangle in 2D.
bool prefer_sprite
Whether to prefer the built-in sprite font over resizable fonts.
Definition fontcache.h:205
bool global_aa
Whether to anti alias all font sizes.
Definition fontcache.h:206
Information about GRF, used in the game and (part of it) in savegames.
void SetParameterDefaults()
Set the default value for all parameters as specified by action14.
std::vector< uint32_t > param
GRF parameters.
uint8_t settings_restriction_mode
selected restriction mode in adv. settings GUI.
uint16_t refresh_rate
How often we refresh the screen (time between draw-ticks).
uint32_t autosave_interval
how often should we do autosaves?
uint8_t missing_strings_threshold
the number of missing strings before showing the warning
bool scale_bevels
bevels are scaled with GUI scale.
void OnResize() override
Called after the window got resized.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
void OnDropdownSelect(WidgetID widget, int index) override
A dropdown option associated to this window has been selected.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnMouseLoop() override
Called for every mouse loop run, which is at least once per (game) tick.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
DropDownList BuildDropDownList(WidgetID widget, int *selected_index) const
Build the dropdown list for a specific widget.
Window to edit settings of the game.
bool manually_changed_folding
Whether the user expanded/collapsed something manually.
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
SettingEntry * valuewindow_entry
If non-nullptr, pointer to setting for which a value-entering window has been opened.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
SettingEntry * clicked_entry
If non-nullptr, pointer to a clicked numeric setting (with a depressed left or right button).
void OnTimeout() override
Called when this window's timeout has been reached.
QueryString filter_editbox
Filter editbox;.
SettingEntry * valuedropdown_entry
If non-nullptr, pointer to the value for which a dropdown window is currently opened.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
bool closing_dropdown
True, if the dropdown list is currently closing.
void OnInit() override
Notification that the nested widget tree gets initialized.
SettingFilter filter
Filter for the list.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void SetDisplayedHelpText(SettingEntry *pe)
Set the entry that should have its help text displayed, and mark the window dirty so it gets repainte...
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
void OnResize() override
Called after the window got resized.
SettingEntry * last_clicked
If non-nullptr, pointer to the last clicked setting.
void OnDropdownClose(Point pt, WidgetID widget, int index, bool instant_close) override
A dropdown window associated to this window has been closed.
WarnHiddenResult warn_missing
Whether and how to warn about missing search results.
void OnDropdownSelect(WidgetID widget, int index) override
A dropdown option associated to this window has been selected.
void OnPaint() override
The window must be repainted.
static GameSettings * settings_ptr
Pointer to the game settings being displayed and modified.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
int warn_lines
Number of lines used for warning about missing search results.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
All settings together for the game.
LocaleSettings locale
settings related to used currency/unit system in the current game
Base integer type, including boolean, settings.
SettingCategory cat
assigned categories of the setting
std::tuple< int32_t, uint32_t > GetRange() const
Get the min/max range for the setting.
Definition settings.cpp:488
StringID GetTitle() const
Get the title of the setting.
Definition settings.cpp:439
int32_t GetDefaultValue() const
Get the default value of the setting.
Definition settings.cpp:479
StringID GetHelp() const
Get the help text of the setting.
Definition settings.cpp:448
virtual bool IsBoolSetting() const
Check whether this setting is a boolean type setting.
std::pair< StringParameter, StringParameter > GetValueParams(int32_t value) const
Get parameters for drawing the value of the setting.
Definition settings.cpp:457
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition settings.cpp:579
char own_name[32]
the localized name of this language
Definition language.h:30
uint8_t currency
currency we currently use
uint8_t effect_vol
The requested effects volume.
uint8_t music_vol
The requested music volume.
Partial widget specification to allow NWidgets to be written nested.
ParticipateSurvey participate_survey
Participate in the automated survey.
Coordinates of a point in 2D.
static Titem * Get(auto index)
Returns Titem with given index.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Data stored about a string that can be modified in the GUI.
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
static const int ACTION_CLEAR
Clear editbox.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
bool IsEditable(bool do_command=false) const
Check whether the setting is editable in the current gamemode.
Definition settings.cpp:901
SettingFlags flags
Handles how a setting would show up in the GUI (text/currency, etc.).
SettingType GetType() const
Return the type of the setting.
Definition settings.cpp:918
const struct IntSettingDesc * AsIntSetting() const
Get the setting description of this setting as an integer setting.
Definition settings.cpp:928
Standard setting.
uint Length() const override
Return number of rows needed to display the (filtered) entry.
void SetButtons(SettingEntryFlags new_val)
Set the button-depressed flags (#SettingsEntryFlag::LeftDepressed and #SettingsEntryFlag::RightDepres...
void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const override
Function to draw setting value (button + text + current value)
bool IsVisibleByRestrictionMode(RestrictionMode mode) const
Checks whether an entry shall be made visible based on the restriction mode.
uint GetMaxHelpHeight(int maxw) override
Get the biggest height of the help text(s), if the width is at least maxw.
void Init(uint8_t level=0) override
Initialization of a setting entry.
const IntSettingDesc * setting
Setting description of the setting.
SettingEntry(const char *name)
Constructor for a single setting in the 'advanced settings' window.
bool UpdateFilterState(SettingFilter &filter, bool force_visible) override
Update the filter state.
const char * name
Name of the setting.
Filter for settings list.
SettingType type
Filter based on type.
bool type_hides
Whether the type hides filtered strings.
RestrictionMode mode
Filter based on category.
RestrictionMode min_cat
Minimum category needed to display all filtered strings (RM_BASIC, RM_ADVANCED, or RM_ALL).
StringFilter string
Filter string.
Containers for BaseSettingEntry.
bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
void GetFoldingState(bool &all_folded, bool &all_unfolded) const
Recursively accumulate the folding state of the tree.
uint GetMaxHelpHeight(int maxw)
Get the biggest height of the help texts, if the width is at least maxw.
void ResetAll()
Resets all settings to their default values.
bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
void FoldAll()
Recursively close all folds of sub-pages.
void UnFoldAll()
Recursively open all folds of sub-pages.
BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find the setting entry at row number row_num.
EntryVector entries
Settings on this page.
uint Length() const
Return number of rows needed to display the whole page.
uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
void Init(uint8_t level=0)
Initialization of an entire setting page.
Data structure describing one page of settings in the settings window.
StringID title
Title of the sub-page.
bool IsVisible(const BaseSettingEntry *item) const override
Check whether an entry is visible and not folded or filtered away.
SettingsPage(StringID title)
Constructor for a sub-page in the 'advanced settings' window.
void UnFoldAll() override
Recursively open all (filtered) folds of sub-pages.
void FoldAll() override
Recursively close all (filtered) folds of sub-pages.
uint Length() const override
Return number of rows needed to display the (filtered) entry.
BaseSettingEntry * FindEntry(uint row, uint *cur_row) override
Find setting entry at row row_num.
uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const override
Draw a row in the settings panel.
void Init(uint8_t level=0) override
Initialization of an entire setting page.
void GetFoldingState(bool &all_folded, bool &all_unfolded) const override
Recursively accumulate the folding state of the (filtered) tree.
void ResetAll() override
Resets all settings to their default values.
bool folded
Sub-page is folded (not visible except for its title)
bool UpdateFilterState(SettingFilter &filter, bool force_visible) override
Update the filter state.
void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const override
Function to draw setting value (button + text + current value)
String filter and state.
bool IsEmpty() const
Check whether any filter words were entered.
void SetFilterTerm(std::string_view str)
Set the term to filter on.
void ResetState()
Reset the matching state to process a new item.
void AddLine(const char *str)
Pass another text line from the current item to the filter.
bool GetState() const
Get the matching state of the current item.
Templated helper to make a type-safe 'typedef' representing a single POD value.
const char * GetText() const
Get the current text.
Definition textbuf.cpp:287
Window for displaying a textfile.
TextfileType file_type
Type of textfile to view.
virtual void LoadTextfile(const std::string &textfile, Subdirectory dir)
Loads the textfile text from file and setup lines.
High level window description.
Definition window_gui.h:168
Data structure for an opened window.
Definition window_gui.h:272
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:949
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1044
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1730
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:319
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:731
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3157
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:548
WidgetID mouse_capture_widget
ID of current mouse capture widget (e.g. dragged scrollbar). -1 if no widget has mouse capture.
Definition window_gui.h:325
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1032
ResizeInfo resize
Resize information.
Definition window_gui.h:313
void DisableWidget(WidgetID widget_index)
Sets a widget to disabled.
Definition window_gui.h:390
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:514
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1720
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:483
virtual void OnDropdownClose(Point pt, WidgetID widget, int index, bool instant_close)
A dropdown window associated to this window has been closed.
Definition window.cpp:284
void SetWidgetsLoweredState(bool lowered_stat, Args... widgets)
Sets the lowered/raised status of a list of widgets.
Definition window_gui.h:525
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:440
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:399
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition window_gui.h:354
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:969
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:459
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1743
WindowFlags flags
Window flags.
Definition window_gui.h:299
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:311
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:380
int height
Height of the window (number of pixels down in y direction)
Definition window_gui.h:311
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:310
@ CONTENT_TYPE_BASE_SOUNDS
The content consists of base sounds.
@ CONTENT_TYPE_BASE_GRAPHICS
The content consists of base graphics.
@ CONTENT_TYPE_BASE_MUSIC
The content consists of base music.
Stuff related to the text buffer GUI.
@ QSF_ENABLE_DEFAULT
enable the 'Default' button ("\0" is returned)
Definition textbuf_gui.h:21
std::optional< std::string > GetTextfile(TextfileType type, Subdirectory dir, const std::string &filename)
Search a textfile file next to the given content.
GUI functions related to textfiles.
TextfileType
Additional text files accompanying Tar archives.
@ TFT_LICENSE
Content license.
@ TFT_README
Content readme.
@ TFT_CHANGELOG
Content changelog.
Base of the town class.
bool _video_vsync
Whether we should use vsync (only if active video driver supports HW acceleration).
bool _video_hw_accel
Whether to consider hardware accelerated video drivers on startup.
Base of all video drivers.
Functions related to (drawing on) viewports.
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition widget.cpp:283
void SetupWidgetDimensions()
Set up pre-scaled versions of Widget Dimensions.
Definition widget.cpp:66
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_PUSHBTN
Normal push-button (no toggle button) with custom drawing.
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ WWT_PUSHARROWBTN
Normal push-button (no toggle button) with arrow caption.
@ WWT_LABEL
Centered label.
Definition widget_type.h:48
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:62
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:46
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:41
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:52
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:76
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:68
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:60
@ WWT_FRAME
Frame.
Definition widget_type.h:51
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:39
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:59
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:56
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:61
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:49
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:71
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
@ EqualSize
Containers should keep all their (resizing) children equally large.
@ AWV_DECREASE
Arrow to the left or in case of RTL to the right.
Definition widget_type.h:22
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition widget_type.h:23
std::map< WidgetID, class NWidgetBase * > WidgetLookup
Lookup between widget IDs and NWidget objects.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1137
void ReInitAllWindows(bool zoom_changed)
Re-initialize all windows.
Definition window.cpp:3333
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1149
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition window.cpp:3125
Window functions not directly related to making/drawing windows.
@ Lowered
If set the frame is lowered and the background colour brighter (ie. buttons when pressed)
@ Centred
Window is centered and shall stay centered after ReInit.
@ Timeout
Window timeout counter.
@ WDP_CENTER
Center the window.
Definition window_gui.h:146
int WidgetID
Widget ID.
Definition window_type.h:20
@ WN_GAME_OPTIONS_GAME_OPTIONS
Game options.
Definition window_type.h:28
@ WN_GAME_OPTIONS_GAME_SETTINGS
Game settings.
Definition window_type.h:29
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_MUSIC_WINDOW
Music window; Window numbers:
@ WC_CUSTOM_CURRENCY
Custom currency; Window numbers:
@ WC_GAME_OPTIONS
Game options window; Window numbers:
@ WC_TEXTFILE
textfile; Window numbers:
@ WC_DROPDOWN_MENU
Drop down menu; Window numbers:
@ WC_QUERY_STRING
Query string window; Window numbers:
@ WC_GRF_PARAMETERS
NewGRF parameters; Window numbers:
Functions related to zooming.