OpenTTD Source 20250205-master-gfd85ab1e2c
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 StringID ScaleMarkFunc(int, int, int value)
160{
161 /* Label only every 100% mark. */
162 if (value % 100 != 0) return STR_NULL;
163
164 SetDParam(0, value / 100);
165 SetDParam(1, 0);
166 return STR_GAME_OPTIONS_GUI_SCALE_MARK;
167}
168
169static StringID VolumeMarkFunc(int, int mark, int value)
170{
171 /* Label only every other mark. */
172 if (mark % 2 != 0) return STR_NULL;
173
174 SetDParam(0, value / 31 * 25); // 0-127 does not map nicely to 0-100. Dividing first gives us nice round numbers.
175 return STR_GAME_OPTIONS_VOLUME_MARK;
176}
177
178static constexpr NWidgetPart _nested_social_plugins_widgets[] = {
180 NWidget(WWT_FRAME, COLOUR_GREY, WID_GO_SOCIAL_PLUGIN_TITLE), SetStringTip(STR_JUST_STRING2),
182 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM),
183 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_SOCIAL_PLUGIN_PLATFORM), SetMinimalSize(100, 12), SetStringTip(STR_JUST_RAW_STRING), SetAlignment(SA_RIGHT),
184 EndContainer(),
186 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE),
187 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_SOCIAL_PLUGIN_STATE), SetMinimalSize(100, 12), SetStringTip(STR_JUST_STRING1), SetAlignment(SA_RIGHT),
188 EndContainer(),
189 EndContainer(),
190 EndContainer(),
191};
192
193static constexpr NWidgetPart _nested_social_plugins_none_widgets[] = {
195 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE),
196 EndContainer(),
197};
198
200public:
202 {
203 this->plugins = SocialIntegration::GetPlugins();
204
205 if (this->plugins.empty()) {
206 auto widget = MakeNWidgets(_nested_social_plugins_none_widgets, nullptr);
207 this->Add(std::move(widget));
208 } else {
209 for (size_t i = 0; i < this->plugins.size(); i++) {
210 auto widget = MakeNWidgets(_nested_social_plugins_widgets, nullptr);
211 this->Add(std::move(widget));
212 }
213 }
214
215 this->SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0);
216 }
217
218 void FillWidgetLookup(WidgetLookup &widget_lookup) override
219 {
220 widget_lookup[WID_GO_SOCIAL_PLUGINS] = this;
222 }
223
224 void SetupSmallestSize(Window *w) override
225 {
226 this->current_index = -1;
228 }
229
236 template <typename T>
237 std::string &GetWidestPlugin(T SocialIntegrationPlugin::*member) const
238 {
239 std::string *longest = &(this->plugins[0]->*member);
240 int longest_length = 0;
241
242 for (auto *plugin : this->plugins) {
243 int length = GetStringBoundingBox(plugin->*member).width;
244 if (length > longest_length) {
245 longest_length = length;
246 longest = &(plugin->*member);
247 }
248 }
249
250 return *longest;
251 }
252
253 void SetStringParameters(int widget) const
254 {
255 switch (widget) {
257 /* For SetupSmallestSize, use the longest string we have. */
258 if (this->current_index < 0) {
259 SetDParam(0, STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE);
262 break;
263 }
264
265 if (this->plugins[this->current_index]->name.empty()) {
266 SetDParam(0, STR_JUST_RAW_STRING);
267 SetDParamStr(1, this->plugins[this->current_index]->basepath);
268 } else {
269 SetDParam(0, STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE);
270 SetDParamStr(1, this->plugins[this->current_index]->name);
271 SetDParamStr(2, this->plugins[this->current_index]->version);
272 }
273 break;
274
276 /* For SetupSmallestSize, use the longest string we have. */
277 if (this->current_index < 0) {
279 break;
280 }
281
282 SetDParamStr(0, this->plugins[this->current_index]->social_platform);
283 break;
284
286 static const std::pair<SocialIntegrationPlugin::State, StringID> state_to_string[] = {
287 { SocialIntegrationPlugin::RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_RUNNING },
288 { SocialIntegrationPlugin::FAILED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED },
289 { SocialIntegrationPlugin::PLATFORM_NOT_RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_PLATFORM_NOT_RUNNING },
290 { SocialIntegrationPlugin::UNLOADED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNLOADED },
291 { SocialIntegrationPlugin::DUPLICATE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_DUPLICATE },
292 { SocialIntegrationPlugin::UNSUPPORTED_API, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNSUPPORTED_API },
293 { SocialIntegrationPlugin::INVALID_SIGNATURE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_INVALID_SIGNATURE },
294 };
295
296 /* For SetupSmallestSize, use the longest string we have. */
297 if (this->current_index < 0) {
299
300 /* Set the longest plugin when looking for the longest status. */
301 SetDParamStr(0, longest_plugin);
302
303 StringID longest = STR_NULL;
304 int longest_length = 0;
305 for (auto state : state_to_string) {
306 int length = GetStringBoundingBox(state.second).width;
307 if (length > longest_length) {
308 longest_length = length;
309 longest = state.second;
310 }
311 }
312
313 SetDParam(0, longest);
314 SetDParamStr(1, longest_plugin);
315 break;
316 }
317
318 auto plugin = this->plugins[this->current_index];
319
320 /* Default string, in case no state matches. */
321 SetDParam(0, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED);
322 SetDParamStr(1, plugin->social_platform);
323
324 /* Find the string for the state. */
325 for (auto state : state_to_string) {
326 if (plugin->state == state.first) {
327 SetDParam(0, state.second);
328 break;
329 }
330 }
331 }
332 break;
333 }
334 }
335
336 void Draw(const Window *w) override
337 {
338 this->current_index = 0;
339
340 for (auto &wid : this->children) {
341 wid->Draw(w);
342 this->current_index++;
343 }
344 }
345
346private:
347 int current_index = -1;
348 std::vector<SocialIntegrationPlugin *> plugins;
349};
350
352std::unique_ptr<NWidgetBase> MakeNWidgetSocialPlugins()
353{
354 return std::make_unique<NWidgetSocialPlugins>();
355}
356
358 GameSettings *opt;
359 bool reload;
360 int gui_scale;
361 static inline WidgetID active_tab = WID_GO_TAB_GENERAL;
362
363 GameOptionsWindow(WindowDesc &desc) : Window(desc)
364 {
365 this->opt = &GetGameSettings();
366 this->reload = false;
367 this->gui_scale = _gui_scale;
368
370
372 this->OnInvalidateData(0);
373
374 this->SetTab(GameOptionsWindow::active_tab);
375
376 if constexpr (!NetworkSurveyHandler::IsSurveyPossible()) this->GetWidget<NWidgetStacked>(WID_GO_SURVEY_SEL)->SetDisplayedPlane(SZSP_NONE);
377 }
378
379 void Close([[maybe_unused]] int data = 0) override
380 {
383 if (this->reload) _switch_mode = SM_MENU;
384 this->Window::Close();
385 }
386
394 {
395 DropDownList list;
396 switch (widget) {
397 case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
398 *selected_index = this->opt->locale.currency;
399 uint64_t disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies();
400
401 /* Add non-custom currencies; sorted naturally */
402 for (const CurrencySpec &currency : _currency_specs) {
403 int i = &currency - _currency_specs.data();
404 if (i == CURRENCY_CUSTOM) continue;
405 if (currency.code.empty()) {
406 list.push_back(MakeDropDownListStringItem(currency.name, i, HasBit(disabled, i)));
407 } else {
408 SetDParam(0, currency.name);
409 SetDParamStr(1, currency.code);
410 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CODE, i, HasBit(disabled, i)));
411 }
412 }
413 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
414
415 /* Append custom currency at the end */
416 list.push_back(MakeDropDownListDividerItem()); // separator line
417 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM)));
418 break;
419 }
420
421 case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
422 int index = 0;
424 index++;
426 }
427 *selected_index = index - 1;
428
429 const StringID *items = _autosave_dropdown;
430 for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
431 list.push_back(MakeDropDownListStringItem(*items, i));
432 }
433 break;
434 }
435
436 case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
437 for (uint i = 0; i < _languages.size(); i++) {
438 bool hide_language = IsReleasedVersion() && !_languages[i].IsReasonablyFinished();
439 if (hide_language) continue;
440 bool hide_percentage = IsReleasedVersion() || _languages[i].missing < _settings_client.gui.missing_strings_threshold;
441 if (&_languages[i] == _current_language) {
442 *selected_index = i;
443 SetDParamStr(0, _languages[i].own_name);
444 } else {
445 /* Especially with sprite-fonts, not all localized
446 * names can be rendered. So instead, we use the
447 * international names for anything but the current
448 * selected language. This avoids showing a few ????
449 * entries in the dropdown list. */
450 SetDParamStr(0, _languages[i].name);
451 }
453 list.push_back(MakeDropDownListStringItem(hide_percentage ? STR_JUST_RAW_STRING : STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE, i));
454 }
455 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
456 break;
457 }
458
459 case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
460 if (_resolutions.empty()) break;
461
463 for (uint i = 0; i < _resolutions.size(); i++) {
466 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_RESOLUTION_ITEM, i));
467 }
468 break;
469
470 case WID_GO_REFRESH_RATE_DROPDOWN: // Setup refresh rate dropdown
471 for (auto it = _refresh_rates.begin(); it != _refresh_rates.end(); it++) {
472 auto i = std::distance(_refresh_rates.begin(), it);
474 SetDParam(0, *it);
475 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, i));
476 }
477 break;
478
481 break;
482
485 break;
486
489 break;
490 }
491
492 return list;
493 }
494
495 void SetStringParameters(WidgetID widget) const override
496 {
497 switch (widget) {
499 const CurrencySpec &currency = _currency_specs[this->opt->locale.currency];
500 if (currency.code.empty()) {
501 SetDParam(0, currency.name);
502 } else {
504 SetDParam(1, currency.name);
505 SetDParamStr(2, currency.code);
506 }
507 break;
508 }
510 int index = 0;
512 index++;
514 }
515 SetDParam(0, _autosave_dropdown[index - 1]);
516 break;
517 }
519 case WID_GO_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->GetListLabel()); break;
520 case WID_GO_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->GetListLabel()); break;
521 case WID_GO_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->GetListLabel()); break;
525
526 if (current_resolution == _resolutions.size()) {
528 } else {
532 }
533 break;
534 }
535
540 assert(plugin != nullptr);
541
542 plugin->SetStringParameters(widget);
543 break;
544 }
545 }
546 }
547
548 void DrawWidget(const Rect &r, WidgetID widget) const override
549 {
550 switch (widget) {
553 DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK);
554 break;
555
558 DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK);
559 break;
560
563 DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_JUST_RAW_STRING, TC_BLACK);
564 break;
565
566 case WID_GO_GUI_SCALE:
567 DrawSliderWidget(r, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, SCALE_NMARKS, this->gui_scale, ScaleMarkFunc);
568 break;
569
571 SetDParamStr(0, std::string{VideoDriver::GetInstance()->GetInfoString()});
573 break;
574
576 DrawSliderWidget(r, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.effect_vol, VolumeMarkFunc);
577 break;
578
580 DrawSliderWidget(r, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.music_vol, VolumeMarkFunc);
581 break;
582 }
583 }
584
585 void SetTab(WidgetID widget)
586 {
588 this->LowerWidget(widget);
589 GameOptionsWindow::active_tab = widget;
590
591 int pane;
592 switch (widget) {
593 case WID_GO_TAB_GENERAL: pane = 0; break;
594 case WID_GO_TAB_GRAPHICS: pane = 1; break;
595 case WID_GO_TAB_SOUND: pane = 2; break;
596 case WID_GO_TAB_SOCIAL: pane = 3; break;
597 default: NOT_REACHED();
598 }
599
600 this->GetWidget<NWidgetStacked>(WID_GO_TAB_SELECTION)->SetDisplayedPlane(pane);
601 this->SetDirty();
602 }
603
604 void OnResize() override
605 {
606 bool changed = false;
607
609 int y = 0;
610 for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
612 y = std::max(y, GetStringHeight(STR_JUST_RAW_STRING, wid->current_x));
613 }
614 changed |= wid->UpdateVerticalSize(y);
615
617 y = 0;
618 for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
620 y = std::max(y, GetStringHeight(STR_JUST_RAW_STRING, wid->current_x));
621 }
622 changed |= wid->UpdateVerticalSize(y);
623
625 y = 0;
626 for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
628 y = std::max(y, GetStringHeight(STR_JUST_RAW_STRING, wid->current_x));
629 }
630 changed |= wid->UpdateVerticalSize(y);
631
633 SetDParamStr(0, std::string{VideoDriver::GetInstance()->GetInfoString()});
635 changed |= wid->UpdateVerticalSize(y);
636
637 if (changed) this->ReInit(0, 0, this->flags.Test(WindowFlag::Centred));
638 }
639
641 {
642 switch (widget) {
646 d.width += padding.width;
647 d.height += padding.height;
648 size = maxdim(size, d);
649 break;
650 }
651
660 int selected;
661 size.width = std::max(size.width, GetDropDownListDimension(this->BuildDropDownList(widget, &selected)).width + padding.width);
662 break;
663 }
664 }
665 }
666
667 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
668 {
669 if (widget >= WID_GO_BASE_GRF_TEXTFILE && widget < WID_GO_BASE_GRF_TEXTFILE + TFT_CONTENT_END) {
670 if (BaseGraphics::GetUsedSet() == nullptr) return;
671
673 return;
674 }
675 if (widget >= WID_GO_BASE_SFX_TEXTFILE && widget < WID_GO_BASE_SFX_TEXTFILE + TFT_CONTENT_END) {
676 if (BaseSounds::GetUsedSet() == nullptr) return;
677
679 return;
680 }
681 if (widget >= WID_GO_BASE_MUSIC_TEXTFILE && widget < WID_GO_BASE_MUSIC_TEXTFILE + TFT_CONTENT_END) {
682 if (BaseMusic::GetUsedSet() == nullptr) return;
683
685 return;
686 }
687 switch (widget) {
690 case WID_GO_TAB_SOUND:
692 this->SetTab(widget);
693 break;
694
697 case PS_ASK:
698 case PS_NO:
700 break;
701
702 case PS_YES:
704 break;
705 }
706
709 break;
710
712 OpenBrowser(NETWORK_SURVEY_DETAILS_LINK);
713 break;
714
716 ShowSurveyResultTextfileWindow();
717 break;
718
719 case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
720 /* try to toggle full-screen on/off */
721 if (!ToggleFullScreen(!_fullscreen)) {
723 }
726 break;
727
733#ifndef __APPLE__
737#endif
738 break;
739
741 if (!_video_hw_accel) break;
742
745
750 break;
751
754
756 this->SetDirty();
757
759 ReInitAllWindows(true);
760 break;
761 }
762
763#ifdef HAS_TRUETYPE_FONT
765 _fcsettings.prefer_sprite = !_fcsettings.prefer_sprite;
766
769 this->SetDirty();
770
771 InitFontCache(false);
772 InitFontCache(true);
773 ClearFontCache();
777 ReInitAllWindows(true);
778 break;
779
781 _fcsettings.global_aa = !_fcsettings.global_aa;
782
785
786 ClearFontCache();
787 break;
788#endif /* HAS_TRUETYPE_FONT */
789
790 case WID_GO_GUI_SCALE:
791 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, _ctrl_pressed ? 0 : SCALE_NMARKS, this->gui_scale)) {
792 this->SetWidgetDirty(widget);
793 }
794
795 if (click_count > 0) this->mouse_capture_widget = widget;
796 break;
797
799 {
800 if (_gui_scale_cfg == -1) {
803 } else {
804 _gui_scale_cfg = -1;
806 if (AdjustGUIZoom(false)) ReInitAllWindows(true);
807 this->gui_scale = _gui_scale;
808 }
809 this->SetWidgetDirty(widget);
810 break;
811 }
812
814 auto *used_set = BaseGraphics::GetUsedSet();
815 if (used_set == nullptr || !used_set->IsConfigurable()) break;
816 GRFConfig &extra_cfg = used_set->GetOrCreateExtraConfig();
817 if (extra_cfg.param.empty()) extra_cfg.SetParameterDefaults();
818 OpenGRFParameterWindow(true, extra_cfg, _game_mode == GM_MENU);
819 if (_game_mode == GM_MENU) this->reload = true;
820 break;
821 }
822
826 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, 0, INT8_MAX, 0, vol)) {
827 if (widget == WID_GO_BASE_MUSIC_VOLUME) {
829 } else {
830 SetEffectVolume(vol);
831 }
832 this->SetWidgetDirty(widget);
834 }
835
836 if (click_count > 0) this->mouse_capture_widget = widget;
837 break;
838 }
839
841 ShowMusicWindow();
842 break;
843 }
844
846 if (BaseGraphics::GetUsedSet() == nullptr || BaseGraphics::GetUsedSet()->url.empty()) return;
847 OpenBrowser(BaseGraphics::GetUsedSet()->url);
848 break;
849
851 if (BaseSounds::GetUsedSet() == nullptr || BaseSounds::GetUsedSet()->url.empty()) return;
852 OpenBrowser(BaseSounds::GetUsedSet()->url);
853 break;
854
856 if (BaseMusic::GetUsedSet() == nullptr || BaseMusic::GetUsedSet()->url.empty()) return;
857 OpenBrowser(BaseMusic::GetUsedSet()->url);
858 break;
859
862 break;
863
866 break;
867
870 break;
871
880 int selected;
881 DropDownList list = this->BuildDropDownList(widget, &selected);
882 if (!list.empty()) {
883 ShowDropDownList(this, std::move(list), selected, widget);
884 } else {
886 }
887 break;
888 }
889 }
890 }
891
892 void OnMouseLoop() override
893 {
894 if (_left_button_down || this->gui_scale == _gui_scale) return;
895
896 _gui_scale_cfg = this->gui_scale;
897
898 if (AdjustGUIZoom(false)) {
899 ReInitAllWindows(true);
901 this->SetDirty();
902 }
903 }
904
905 void OnDropdownSelect(WidgetID widget, int index) override
906 {
907 switch (widget) {
908 case WID_GO_CURRENCY_DROPDOWN: // Currency
909 if (index == CURRENCY_CUSTOM) ShowCustCurrency();
910 this->opt->locale.currency = index;
911 ReInitAllWindows(false);
912 break;
913
914 case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
917 this->SetDirty();
918 break;
919
920 case WID_GO_LANG_DROPDOWN: // Change interface language
924 ClearAllCachedNames();
926 CheckBlitter();
927 ReInitAllWindows(false);
928 break;
929
930 case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
931 if ((uint)index < _resolutions.size() && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
932 this->SetDirty();
933 }
934 break;
935
937 _settings_client.gui.refresh_rate = *std::next(_refresh_rates.begin(), index);
939 /* Show warning to the user that this refresh rate might not be suitable on
940 * larger maps with many NewGRFs and vehicles. */
942 }
943 break;
944 }
945
947 if (_game_mode == GM_MENU) {
949 auto set = BaseGraphics::GetSet(index);
951 this->reload = true;
952 this->InvalidateData();
953 }
954 break;
955
957 ChangeSoundSet(index);
958 break;
959
961 ChangeMusicSet(index);
962 break;
963 }
964 }
965
971 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
972 {
973 if (!gui_scope) return;
978
979#ifndef __APPLE__
982#endif
983
986#ifdef HAS_TRUETYPE_FONT
990#endif /* HAS_TRUETYPE_FONT */
991
992 this->SetWidgetDisabledState(WID_GO_BASE_GRF_DROPDOWN, _game_mode != GM_MENU);
993
995
999
1000 for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
1004 }
1005
1007 }
1008};
1009
1010static constexpr NWidgetPart _nested_game_options_widgets[] = {
1012 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1013 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1014 EndContainer(),
1015 NWidget(WWT_PANEL, COLOUR_GREY),
1017 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),
1018 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),
1019 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),
1020 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),
1021 EndContainer(),
1022 EndContainer(),
1023 NWidget(WWT_PANEL, COLOUR_GREY),
1025 /* General tab */
1027 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_LANGUAGE),
1028 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),
1029 EndContainer(),
1030
1031 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME),
1032 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),
1033 EndContainer(),
1034
1035 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME),
1036 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),
1037 EndContainer(),
1038
1039 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GO_SURVEY_SEL),
1040 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_FRAME), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1042 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY),
1043 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_SURVEY_PARTICIPATE_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_PARTICIPATE_SURVEY_TOOLTIP),
1044 EndContainer(),
1046 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),
1047 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),
1048 EndContainer(),
1049 EndContainer(),
1050 EndContainer(),
1051 EndContainer(),
1052
1053 /* Graphics tab */
1055 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_GUI_SCALE_FRAME),
1057 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),
1059 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_GUI_SCALE_AUTO),
1060 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),
1061 EndContainer(),
1063 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_GUI_SCALE_BEVELS),
1064 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),
1065 EndContainer(),
1066#ifdef HAS_TRUETYPE_FONT
1068 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_GUI_FONT_SPRITE),
1069 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),
1070 EndContainer(),
1072 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_GUI_FONT_AA),
1073 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),
1074 EndContainer(),
1075#endif /* HAS_TRUETYPE_FONT */
1076 EndContainer(),
1077 EndContainer(),
1078
1079 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_GRAPHICS),
1082 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_RESOLUTION),
1083 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_RESOLUTION_DROPDOWN), SetMinimalSize(100, 12), SetStringTip(STR_JUST_STRING2, STR_GAME_OPTIONS_RESOLUTION_TOOLTIP),
1084 EndContainer(),
1086 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_REFRESH_RATE),
1087 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),
1088 EndContainer(),
1090 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_FULLSCREEN),
1091 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
1092 EndContainer(),
1094 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_VIDEO_ACCELERATION),
1095 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_ACCEL_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP),
1096 EndContainer(),
1097#ifndef __APPLE__
1099 NWidget(WWT_TEXT, INVALID_COLOUR), SetMinimalSize(0, 12), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_VIDEO_VSYNC),
1100 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_VSYNC_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP),
1101 EndContainer(),
1102#endif
1105 EndContainer(),
1106 EndContainer(),
1107 EndContainer(),
1108
1109 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_BASE_GRF), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0), SetFill(1, 0),
1111 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),
1112 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_PARAMETERS), SetStringTip(STR_NEWGRF_SETTINGS_SET_PARAMETERS),
1113 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1114 EndContainer(),
1115 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),
1118 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),
1119 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),
1120 EndContainer(),
1122 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),
1123 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),
1124 EndContainer(),
1125 EndContainer(),
1126 EndContainer(),
1127 EndContainer(),
1128
1129 /* Sound/Music tab */
1131 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_VOLUME), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0),
1133 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_TEXT_SFX_VOLUME), SetMinimalSize(0, 12), SetStringTip(STR_GAME_OPTIONS_SFX_VOLUME),
1134 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),
1135 EndContainer(),
1137 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_TEXT_MUSIC_VOLUME), SetMinimalSize(0, 12), SetStringTip(STR_GAME_OPTIONS_MUSIC_VOLUME),
1138 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),
1139 EndContainer(),
1140 EndContainer(),
1141
1142 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_BASE_SFX), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1144 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),
1145 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1146 EndContainer(),
1147 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),
1150 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),
1151 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),
1152 EndContainer(),
1154 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),
1155 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),
1156 EndContainer(),
1157 EndContainer(),
1158 EndContainer(),
1159
1160 NWidget(WWT_FRAME, COLOUR_GREY), SetStringTip(STR_GAME_OPTIONS_BASE_MUSIC), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1162 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),
1163 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1164 EndContainer(),
1166 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),
1168 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_JUKEBOX), SetMinimalSize(22, 22), SetSpriteTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
1169 EndContainer(),
1170 EndContainer(),
1173 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),
1174 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),
1175 EndContainer(),
1177 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),
1178 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),
1179 EndContainer(),
1180 EndContainer(),
1181 EndContainer(),
1182 EndContainer(),
1183
1184 /* Social tab */
1187 EndContainer(),
1188 EndContainer(),
1189 EndContainer(),
1190};
1191
1192static WindowDesc _game_options_desc(
1193 WDP_CENTER, nullptr, 0, 0,
1195 {},
1196 _nested_game_options_widgets
1197);
1198
1201{
1203 new GameOptionsWindow(_game_options_desc);
1204}
1205
1206static int SETTING_HEIGHT = 11;
1207
1220
1231
1232
1240
1243 uint8_t flags;
1244 uint8_t level;
1245
1246 BaseSettingEntry() : flags(0), level(0) {}
1247 virtual ~BaseSettingEntry() = default;
1248
1249 virtual void Init(uint8_t level = 0);
1250 virtual void FoldAll() {}
1251 virtual void UnFoldAll() {}
1252 virtual void ResetAll() = 0;
1253
1258 void SetLastField(bool last_field) { if (last_field) SETBITS(this->flags, SEF_LAST_FIELD); else CLRBITS(this->flags, SEF_LAST_FIELD); }
1259
1260 virtual uint Length() const = 0;
1261 virtual void GetFoldingState([[maybe_unused]] bool &all_folded, [[maybe_unused]] bool &all_unfolded) const {}
1262 virtual bool IsVisible(const BaseSettingEntry *item) const;
1263 virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
1264 virtual uint GetMaxHelpHeight([[maybe_unused]] int maxw) { return 0; }
1265
1270 bool IsFiltered() const { return (this->flags & SEF_FILTERED) != 0; }
1271
1272 virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible) = 0;
1273
1274 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;
1275
1276protected:
1277 virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
1278};
1279
1282 const char *name;
1284
1285 SettingEntry(const char *name);
1286
1287 void Init(uint8_t level = 0) override;
1288 void ResetAll() override;
1289 uint Length() const override;
1290 uint GetMaxHelpHeight(int maxw) override;
1291 bool UpdateFilterState(SettingFilter &filter, bool force_visible) override;
1292
1293 void SetButtons(uint8_t new_val);
1294
1295protected:
1296 void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const override;
1297
1298private:
1300};
1301
1304 typedef std::vector<BaseSettingEntry*> EntryVector;
1305 EntryVector entries;
1306
1307 template <typename T>
1308 T *Add(T *item)
1309 {
1310 this->entries.push_back(item);
1311 return item;
1312 }
1313
1314 void Init(uint8_t level = 0);
1315 void ResetAll();
1316 void FoldAll();
1317 void UnFoldAll();
1318
1319 uint Length() const;
1320 void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
1321 bool IsVisible(const BaseSettingEntry *item) const;
1322 BaseSettingEntry *FindEntry(uint row, uint *cur_row);
1323 uint GetMaxHelpHeight(int maxw);
1324
1325 bool UpdateFilterState(SettingFilter &filter, bool force_visible);
1326
1327 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;
1328};
1329
1333 bool folded;
1334
1336
1337 void Init(uint8_t level = 0) override;
1338 void ResetAll() override;
1339 void FoldAll() override;
1340 void UnFoldAll() override;
1341
1342 uint Length() const override;
1343 void GetFoldingState(bool &all_folded, bool &all_unfolded) const override;
1344 bool IsVisible(const BaseSettingEntry *item) const override;
1345 BaseSettingEntry *FindEntry(uint row, uint *cur_row) override;
1346 uint GetMaxHelpHeight(int maxw) override { return SettingsContainer::GetMaxHelpHeight(maxw); }
1347
1348 bool UpdateFilterState(SettingFilter &filter, bool force_visible) override;
1349
1350 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;
1351
1352protected:
1353 void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const override;
1354};
1355
1356/* == BaseSettingEntry methods == */
1357
1362void BaseSettingEntry::Init(uint8_t level)
1363{
1364 this->level = level;
1365}
1366
1374{
1375 if (this->IsFiltered()) return false;
1376 return this == item;
1377}
1378
1386{
1387 if (this->IsFiltered()) return nullptr;
1388 if (row_num == *cur_row) return this;
1389 (*cur_row)++;
1390 return nullptr;
1391}
1392
1422uint 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
1423{
1424 if (this->IsFiltered()) return cur_row;
1425 if (cur_row >= max_row) return cur_row;
1426
1427 bool rtl = _current_text_dir == TD_RTL;
1428 int offset = (rtl ? -(int)_circle_size.width : (int)_circle_size.width) / 2;
1430
1431 int x = rtl ? right : left;
1432 if (cur_row >= first_row) {
1433 int colour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
1434 y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
1435
1436 /* Draw vertical for parent nesting levels */
1437 for (uint lvl = 0; lvl < this->level; lvl++) {
1438 if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
1439 x += level_width;
1440 }
1441 /* draw own |- prefix */
1442 int halfway_y = y + SETTING_HEIGHT / 2;
1443 int bottom_y = (flags & SEF_LAST_FIELD) ? halfway_y : y + SETTING_HEIGHT - 1;
1444 GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
1445 /* Small horizontal line from the last vertical line */
1446 GfxDrawLine(x + offset, halfway_y, x + level_width - (rtl ? -WidgetDimensions::scaled.hsep_normal : WidgetDimensions::scaled.hsep_normal), halfway_y, colour);
1447 x += level_width;
1448
1449 this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
1450 }
1451 cur_row++;
1452
1453 return cur_row;
1454}
1455
1456/* == SettingEntry methods == */
1457
1463{
1464 this->name = name;
1465 this->setting = nullptr;
1466}
1467
1472void SettingEntry::Init(uint8_t level)
1473{
1475 this->setting = GetSettingFromName(this->name)->AsIntSetting();
1476}
1477
1478/* Sets the given setting entry to its default value */
1479void SettingEntry::ResetAll()
1480{
1482}
1483
1489void SettingEntry::SetButtons(uint8_t new_val)
1490{
1491 assert((new_val & ~SEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
1492 this->flags = (this->flags & ~SEF_BUTTONS_MASK) | new_val;
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{
1559 CLRBITS(this->flags, SEF_FILTERED);
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) SETBITS(this->flags, SEF_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;
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 SetDParam(0, STR_CONFIG_SETTING_VALUE);
1624 auto [min_val, max_val] = sd->GetRange();
1625 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
1626 if (sd->IsBoolSetting()) {
1627 /* Draw checkbox for boolean-value either on/off */
1628 DrawBoolButton(buttons_left, button_y, value != 0, editable);
1629 } else if (sd->flags.Test(SettingFlag::GuiDropdown)) {
1630 /* Draw [v] button for settings of an enum-type */
1631 DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1632 } else {
1633 /* Draw [<][>] boxes for settings of an integer-type */
1634 DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1635 editable && value != (sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val), editable && static_cast<uint32_t>(value) != max_val);
1636 }
1637 sd->SetValueDParams(1, value);
1638 DrawString(text_left, text_right, y + (SETTING_HEIGHT - GetCharacterHeight(FS_NORMAL)) / 2, sd->GetTitle(), highlight ? TC_WHITE : TC_LIGHT_BLUE);
1639}
1640
1641/* == SettingsContainer methods == */
1642
1647void SettingsContainer::Init(uint8_t level)
1648{
1649 for (auto &it : this->entries) {
1650 it->Init(level);
1651 }
1652}
1653
1656{
1657 for (auto settings_entry : this->entries) {
1658 settings_entry->ResetAll();
1659 }
1660}
1661
1664{
1665 for (auto &it : this->entries) {
1666 it->FoldAll();
1667 }
1668}
1669
1672{
1673 for (auto &it : this->entries) {
1674 it->UnFoldAll();
1675 }
1676}
1677
1683void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1684{
1685 for (auto &it : this->entries) {
1686 it->GetFoldingState(all_folded, all_unfolded);
1687 }
1688}
1689
1697{
1698 bool visible = false;
1699 bool first_visible = true;
1700 for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1701 visible |= (*it)->UpdateFilterState(filter, force_visible);
1702 (*it)->SetLastField(first_visible);
1703 if (visible && first_visible) first_visible = false;
1704 }
1705 return visible;
1706}
1707
1708
1716{
1717 for (const auto &it : this->entries) {
1718 if (it->IsVisible(item)) return true;
1719 }
1720 return false;
1721}
1722
1725{
1726 uint length = 0;
1727 for (const auto &it : this->entries) {
1728 length += it->Length();
1729 }
1730 return length;
1731}
1732
1740{
1741 BaseSettingEntry *pe = nullptr;
1742 for (const auto &it : this->entries) {
1743 pe = it->FindEntry(row_num, cur_row);
1744 if (pe != nullptr) {
1745 break;
1746 }
1747 }
1748 return pe;
1749}
1750
1757{
1758 uint biggest = 0;
1759 for (const auto &it : this->entries) {
1760 biggest = std::max(biggest, it->GetMaxHelpHeight(maxw));
1761 }
1762 return biggest;
1763}
1764
1765
1780uint 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
1781{
1782 for (const auto &it : this->entries) {
1783 cur_row = it->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1784 if (cur_row >= max_row) break;
1785 }
1786 return cur_row;
1787}
1788
1789/* == SettingsPage methods == */
1790
1796{
1797 this->title = title;
1798 this->folded = true;
1799}
1800
1805void SettingsPage::Init(uint8_t level)
1806{
1809}
1810
1813{
1814 for (auto settings_entry : this->entries) {
1815 settings_entry->ResetAll();
1816 }
1817}
1818
1821{
1822 if (this->IsFiltered()) return;
1823 this->folded = true;
1824
1826}
1827
1830{
1831 if (this->IsFiltered()) return;
1832 this->folded = false;
1833
1835}
1836
1842void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1843{
1844 if (this->IsFiltered()) return;
1845
1846 if (this->folded) {
1847 all_unfolded = false;
1848 } else {
1849 all_folded = false;
1850 }
1851
1852 SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1853}
1854
1861bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1862{
1863 if (!force_visible && !filter.string.IsEmpty()) {
1864 filter.string.ResetState();
1865 filter.string.AddLine(this->title);
1866 force_visible = filter.string.GetState();
1867 }
1868
1869 bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1870 if (visible) {
1871 CLRBITS(this->flags, SEF_FILTERED);
1872 } else {
1873 SETBITS(this->flags, SEF_FILTERED);
1874 }
1875 return visible;
1876}
1877
1885{
1886 if (this->IsFiltered()) return false;
1887 if (this == item) return true;
1888 if (this->folded) return false;
1889
1890 return SettingsContainer::IsVisible(item);
1891}
1892
1895{
1896 if (this->IsFiltered()) return 0;
1897 if (this->folded) return 1; // Only displaying the title
1898
1899 return 1 + SettingsContainer::Length();
1900}
1901
1908BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1909{
1910 if (this->IsFiltered()) return nullptr;
1911 if (row_num == *cur_row) return this;
1912 (*cur_row)++;
1913 if (this->folded) return nullptr;
1914
1915 return SettingsContainer::FindEntry(row_num, cur_row);
1916}
1917
1932uint 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
1933{
1934 if (this->IsFiltered()) return cur_row;
1935 if (cur_row >= max_row) return cur_row;
1936
1937 cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1938
1939 if (!this->folded) {
1940 if (this->flags & SEF_LAST_FIELD) {
1941 assert(this->level < 8 * sizeof(parent_last));
1942 SetBit(parent_last, this->level); // Add own last-field state
1943 }
1944
1945 cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1946 }
1947
1948 return cur_row;
1949}
1950
1957void SettingsPage::DrawSetting(GameSettings *, int left, int right, int y, bool) const
1958{
1959 bool rtl = _current_text_dir == TD_RTL;
1960 DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1961 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);
1962}
1963
1966{
1967 static SettingsContainer *main = nullptr;
1968
1969 if (main == nullptr)
1970 {
1971 /* Build up the dynamic settings-array only once per OpenTTD session */
1972 main = new SettingsContainer();
1973
1974 SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1975 {
1976 localisation->Add(new SettingEntry("locale.units_velocity"));
1977 localisation->Add(new SettingEntry("locale.units_velocity_nautical"));
1978 localisation->Add(new SettingEntry("locale.units_power"));
1979 localisation->Add(new SettingEntry("locale.units_weight"));
1980 localisation->Add(new SettingEntry("locale.units_volume"));
1981 localisation->Add(new SettingEntry("locale.units_force"));
1982 localisation->Add(new SettingEntry("locale.units_height"));
1983 localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1984 }
1985
1986 SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1987 {
1988 graphics->Add(new SettingEntry("gui.zoom_min"));
1989 graphics->Add(new SettingEntry("gui.zoom_max"));
1990 graphics->Add(new SettingEntry("gui.sprite_zoom_min"));
1991 graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1992 graphics->Add(new SettingEntry("gui.linkgraph_colours"));
1993 graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1994 }
1995
1996 SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1997 {
1998 sound->Add(new SettingEntry("sound.click_beep"));
1999 sound->Add(new SettingEntry("sound.confirm"));
2000 sound->Add(new SettingEntry("sound.news_ticker"));
2001 sound->Add(new SettingEntry("sound.news_full"));
2002 sound->Add(new SettingEntry("sound.new_year"));
2003 sound->Add(new SettingEntry("sound.disaster"));
2004 sound->Add(new SettingEntry("sound.vehicle"));
2005 sound->Add(new SettingEntry("sound.ambient"));
2006 }
2007
2008 SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
2009 {
2010 SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
2011 {
2012 general->Add(new SettingEntry("gui.osk_activation"));
2013 general->Add(new SettingEntry("gui.hover_delay_ms"));
2014 general->Add(new SettingEntry("gui.errmsg_duration"));
2015 general->Add(new SettingEntry("gui.window_snap_radius"));
2016 general->Add(new SettingEntry("gui.window_soft_limit"));
2017 general->Add(new SettingEntry("gui.right_click_wnd_close"));
2018 }
2019
2020 SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
2021 {
2022 viewports->Add(new SettingEntry("gui.auto_scrolling"));
2023 viewports->Add(new SettingEntry("gui.scroll_mode"));
2024 viewports->Add(new SettingEntry("gui.smooth_scroll"));
2025 /* While the horizontal scrollwheel scrolling is written as general code, only
2026 * the cocoa (OSX) driver generates input for it.
2027 * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
2028 viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
2029 viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
2030#ifdef __APPLE__
2031 /* We might need to emulate a right mouse button on mac */
2032 viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
2033#endif
2034 viewports->Add(new SettingEntry("gui.population_in_label"));
2035 viewports->Add(new SettingEntry("gui.liveries"));
2036 viewports->Add(new SettingEntry("construction.train_signal_side"));
2037 viewports->Add(new SettingEntry("gui.measure_tooltip"));
2038 viewports->Add(new SettingEntry("gui.loading_indicators"));
2039 viewports->Add(new SettingEntry("gui.show_track_reservation"));
2040 }
2041
2042 SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
2043 {
2044 construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
2045 construction->Add(new SettingEntry("gui.persistent_buildingtools"));
2046 construction->Add(new SettingEntry("gui.default_rail_type"));
2047 construction->Add(new SettingEntry("gui.semaphore_build_before"));
2048 construction->Add(new SettingEntry("gui.signal_gui_mode"));
2049 construction->Add(new SettingEntry("gui.cycle_signal_types"));
2050 construction->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
2051 construction->Add(new SettingEntry("gui.auto_remove_signals"));
2052 }
2053
2054 interface->Add(new SettingEntry("gui.toolbar_pos"));
2055 interface->Add(new SettingEntry("gui.statusbar_pos"));
2056 interface->Add(new SettingEntry("gui.prefer_teamchat"));
2057 interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
2058 interface->Add(new SettingEntry("gui.timetable_mode"));
2059 interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
2060 interface->Add(new SettingEntry("gui.show_newgrf_name"));
2061 interface->Add(new SettingEntry("gui.show_cargo_in_vehicle_lists"));
2062 }
2063
2064 SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
2065 {
2066 advisors->Add(new SettingEntry("gui.coloured_news_year"));
2067 advisors->Add(new SettingEntry("news_display.general"));
2068 advisors->Add(new SettingEntry("news_display.new_vehicles"));
2069 advisors->Add(new SettingEntry("news_display.accident"));
2070 advisors->Add(new SettingEntry("news_display.accident_other"));
2071 advisors->Add(new SettingEntry("news_display.company_info"));
2072 advisors->Add(new SettingEntry("news_display.acceptance"));
2073 advisors->Add(new SettingEntry("news_display.arrival_player"));
2074 advisors->Add(new SettingEntry("news_display.arrival_other"));
2075 advisors->Add(new SettingEntry("news_display.advice"));
2076 advisors->Add(new SettingEntry("gui.order_review_system"));
2077 advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
2078 advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
2079 advisors->Add(new SettingEntry("gui.old_vehicle_warn"));
2080 advisors->Add(new SettingEntry("gui.show_finances"));
2081 advisors->Add(new SettingEntry("news_display.economy"));
2082 advisors->Add(new SettingEntry("news_display.subsidies"));
2083 advisors->Add(new SettingEntry("news_display.open"));
2084 advisors->Add(new SettingEntry("news_display.close"));
2085 advisors->Add(new SettingEntry("news_display.production_player"));
2086 advisors->Add(new SettingEntry("news_display.production_other"));
2087 advisors->Add(new SettingEntry("news_display.production_nobody"));
2088 }
2089
2090 SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
2091 {
2092 company->Add(new SettingEntry("gui.starting_colour"));
2093 company->Add(new SettingEntry("gui.starting_colour_secondary"));
2094 company->Add(new SettingEntry("company.engine_renew"));
2095 company->Add(new SettingEntry("company.engine_renew_months"));
2096 company->Add(new SettingEntry("company.engine_renew_money"));
2097 company->Add(new SettingEntry("vehicle.servint_ispercent"));
2098 company->Add(new SettingEntry("vehicle.servint_trains"));
2099 company->Add(new SettingEntry("vehicle.servint_roadveh"));
2100 company->Add(new SettingEntry("vehicle.servint_ships"));
2101 company->Add(new SettingEntry("vehicle.servint_aircraft"));
2102 }
2103
2104 SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
2105 {
2106 accounting->Add(new SettingEntry("difficulty.infinite_money"));
2107 accounting->Add(new SettingEntry("economy.inflation"));
2108 accounting->Add(new SettingEntry("difficulty.initial_interest"));
2109 accounting->Add(new SettingEntry("difficulty.max_loan"));
2110 accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
2111 accounting->Add(new SettingEntry("difficulty.subsidy_duration"));
2112 accounting->Add(new SettingEntry("economy.feeder_payment_share"));
2113 accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
2114 accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
2115 accounting->Add(new SettingEntry("difficulty.construction_cost"));
2116 }
2117
2118 SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
2119 {
2120 SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
2121 {
2122 physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
2123 physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
2124 physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
2125 physics->Add(new SettingEntry("vehicle.freight_trains"));
2126 physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
2127 physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
2128 physics->Add(new SettingEntry("vehicle.smoke_amount"));
2129 physics->Add(new SettingEntry("vehicle.plane_speed"));
2130 }
2131
2132 SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
2133 {
2134 routing->Add(new SettingEntry("vehicle.road_side"));
2135 routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
2136 routing->Add(new SettingEntry("pf.reverse_at_signals"));
2137 routing->Add(new SettingEntry("pf.forbid_90_deg"));
2138 }
2139
2140 SettingsPage *orders = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ORDERS));
2141 {
2142 orders->Add(new SettingEntry("gui.new_nonstop"));
2143 orders->Add(new SettingEntry("gui.quick_goto"));
2144 orders->Add(new SettingEntry("gui.stop_location"));
2145 }
2146 }
2147
2148 SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
2149 {
2150 limitations->Add(new SettingEntry("construction.command_pause_level"));
2151 limitations->Add(new SettingEntry("construction.autoslope"));
2152 limitations->Add(new SettingEntry("construction.extra_dynamite"));
2153 limitations->Add(new SettingEntry("construction.map_height_limit"));
2154 limitations->Add(new SettingEntry("construction.max_bridge_length"));
2155 limitations->Add(new SettingEntry("construction.max_bridge_height"));
2156 limitations->Add(new SettingEntry("construction.max_tunnel_length"));
2157 limitations->Add(new SettingEntry("station.never_expire_airports"));
2158 limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
2159 limitations->Add(new SettingEntry("vehicle.max_trains"));
2160 limitations->Add(new SettingEntry("vehicle.max_roadveh"));
2161 limitations->Add(new SettingEntry("vehicle.max_aircraft"));
2162 limitations->Add(new SettingEntry("vehicle.max_ships"));
2163 limitations->Add(new SettingEntry("vehicle.max_train_length"));
2164 limitations->Add(new SettingEntry("station.station_spread"));
2165 limitations->Add(new SettingEntry("station.distant_join_stations"));
2166 limitations->Add(new SettingEntry("station.modified_catchment"));
2167 limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
2168 limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
2169 limitations->Add(new SettingEntry("construction.crossing_with_competitor"));
2170 limitations->Add(new SettingEntry("vehicle.disable_elrails"));
2171 limitations->Add(new SettingEntry("order.station_length_loading_penalty"));
2172 }
2173
2174 SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
2175 {
2176 disasters->Add(new SettingEntry("difficulty.disasters"));
2177 disasters->Add(new SettingEntry("difficulty.economy"));
2178 disasters->Add(new SettingEntry("vehicle.plane_crashes"));
2179 disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
2180 disasters->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
2181 disasters->Add(new SettingEntry("order.serviceathelipad"));
2182 }
2183
2184 SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
2185 {
2186 genworld->Add(new SettingEntry("game_creation.landscape"));
2187 genworld->Add(new SettingEntry("game_creation.land_generator"));
2188 genworld->Add(new SettingEntry("difficulty.terrain_type"));
2189 genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
2190 genworld->Add(new SettingEntry("game_creation.variety"));
2191 genworld->Add(new SettingEntry("game_creation.snow_coverage"));
2192 genworld->Add(new SettingEntry("game_creation.snow_line_height"));
2193 genworld->Add(new SettingEntry("game_creation.desert_coverage"));
2194 genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
2195 }
2196
2197 SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
2198 {
2199 SettingsPage *time = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TIME));
2200 {
2201 time->Add(new SettingEntry("economy.timekeeping_units"));
2202 time->Add(new SettingEntry("economy.minutes_per_calendar_year"));
2203 time->Add(new SettingEntry("game_creation.ending_year"));
2204 time->Add(new SettingEntry("gui.pause_on_newgame"));
2205 time->Add(new SettingEntry("gui.fast_forward_speed_limit"));
2206 }
2207
2208 SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
2209 {
2210 authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
2211 authorities->Add(new SettingEntry("economy.bribe"));
2212 authorities->Add(new SettingEntry("economy.exclusive_rights"));
2213 authorities->Add(new SettingEntry("economy.fund_roads"));
2214 authorities->Add(new SettingEntry("economy.fund_buildings"));
2215 authorities->Add(new SettingEntry("economy.station_noise_level"));
2216 }
2217
2218 SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
2219 {
2220 towns->Add(new SettingEntry("economy.town_cargo_scale"));
2221 towns->Add(new SettingEntry("economy.town_growth_rate"));
2222 towns->Add(new SettingEntry("economy.allow_town_roads"));
2223 towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
2224 towns->Add(new SettingEntry("economy.found_town"));
2225 towns->Add(new SettingEntry("economy.town_layout"));
2226 towns->Add(new SettingEntry("economy.larger_towns"));
2227 towns->Add(new SettingEntry("economy.initial_city_size"));
2228 towns->Add(new SettingEntry("economy.town_cargogen_mode"));
2229 }
2230
2231 SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
2232 {
2233 industries->Add(new SettingEntry("economy.industry_cargo_scale"));
2234 industries->Add(new SettingEntry("difficulty.industry_density"));
2235 industries->Add(new SettingEntry("construction.raw_industry_construction"));
2236 industries->Add(new SettingEntry("construction.industry_platform"));
2237 industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
2238 industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
2239 industries->Add(new SettingEntry("economy.type"));
2240 industries->Add(new SettingEntry("station.serve_neutral_industries"));
2241 }
2242
2243 SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
2244 {
2245 cdist->Add(new SettingEntry("linkgraph.recalc_time"));
2246 cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
2247 cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
2248 cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
2249 cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
2250 cdist->Add(new SettingEntry("linkgraph.distribution_default"));
2251 cdist->Add(new SettingEntry("linkgraph.accuracy"));
2252 cdist->Add(new SettingEntry("linkgraph.demand_distance"));
2253 cdist->Add(new SettingEntry("linkgraph.demand_size"));
2254 cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
2255 }
2256
2257 SettingsPage *trees = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TREES));
2258 {
2259 trees->Add(new SettingEntry("game_creation.tree_placer"));
2260 trees->Add(new SettingEntry("construction.extra_tree_placement"));
2261 }
2262 }
2263
2264 SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
2265 {
2266 SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
2267 {
2268 npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
2269 npc->Add(new SettingEntry("script.script_max_memory_megabytes"));
2270 npc->Add(new SettingEntry("difficulty.competitor_speed"));
2271 npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
2272 npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
2273 npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
2274 npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
2275 npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
2276 }
2277
2278 ai->Add(new SettingEntry("economy.give_money"));
2279 }
2280
2281 SettingsPage *network = main->Add(new SettingsPage(STR_CONFIG_SETTING_NETWORK));
2282 {
2283 network->Add(new SettingEntry("network.use_relay_service"));
2284 }
2285
2286 main->Init();
2287 }
2288 return *main;
2289}
2290
2291static const StringID _game_settings_restrict_dropdown[] = {
2292 STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
2293 STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
2294 STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
2295 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
2296 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
2297};
2298static_assert(lengthof(_game_settings_restrict_dropdown) == RM_END);
2299
2307
2313static void ResetAllSettingsConfirmationCallback(Window *w, bool confirmed)
2314{
2315 if (confirmed) {
2318 w->InvalidateData();
2319 }
2320}
2321
2325
2331
2337
2338 Scrollbar *vscroll;
2339
2341 {
2342 this->warn_missing = WHR_NONE;
2343 this->warn_lines = 0;
2345 this->filter.min_cat = RM_ALL;
2346 this->filter.type = ST_ALL;
2347 this->filter.type_hides = false;
2348 this->settings_ptr = &GetGameSettings();
2349
2350 GetSettingsTree().FoldAll(); // Close all sub-pages
2351
2352 this->valuewindow_entry = nullptr; // No setting entry for which a entry window is opened
2353 this->clicked_entry = nullptr; // No numeric setting buttons are depressed
2354 this->last_clicked = nullptr;
2355 this->valuedropdown_entry = nullptr;
2356 this->closing_dropdown = false;
2357 this->manually_changed_folding = false;
2358
2359 this->CreateNestedTree();
2360 this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
2362
2364 this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
2366
2367 this->InvalidateData();
2368 }
2369
2370 void OnInit() override
2371 {
2372 _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
2373 }
2374
2376 {
2377 switch (widget) {
2380 resize.width = 1;
2381
2382 size.height = 5 * resize.height + WidgetDimensions::scaled.framerect.Vertical();
2383 break;
2384
2385 case WID_GS_HELP_TEXT: {
2386 static const StringID setting_types[] = {
2390 };
2391 for (const auto &setting_type : setting_types) {
2393 size.width = std::max(size.width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width + padding.width);
2394 }
2396 std::max(size.height, GetSettingsTree().GetMaxHelpHeight(size.width));
2397 break;
2398 }
2399
2403 break;
2404
2405 default:
2406 break;
2407 }
2408 }
2409
2410 void OnPaint() override
2411 {
2412 if (this->closing_dropdown) {
2413 this->closing_dropdown = false;
2414 assert(this->valuedropdown_entry != nullptr);
2415 this->valuedropdown_entry->SetButtons(0);
2416 this->valuedropdown_entry = nullptr;
2417 }
2418
2419 /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
2420 const Rect panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext);
2422 int new_warn_lines;
2423 if (this->warn_missing == WHR_NONE) {
2424 new_warn_lines = 0;
2425 } else {
2426 SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
2428 }
2429 if (this->warn_lines != new_warn_lines) {
2430 this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
2431 this->warn_lines = new_warn_lines;
2432 }
2433
2434 this->DrawWidgets();
2435
2436 /* Draw the 'some search results are hidden' notice. */
2437 if (this->warn_missing != WHR_NONE) {
2438 SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
2439 DrawStringMultiLine(panel.WithHeight(this->warn_lines * GetCharacterHeight(FS_NORMAL)), warn_str, TC_FROMSTRING, SA_CENTER);
2440 }
2441 }
2442
2443 void SetStringParameters(WidgetID widget) const override
2444 {
2445 switch (widget) {
2447 SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
2448 break;
2449
2451 switch (this->filter.type) {
2456 }
2457 break;
2458 }
2459 }
2460
2461 DropDownList BuildDropDownList(WidgetID widget) const
2462 {
2463 DropDownList list;
2464 switch (widget) {
2466 for (int mode = 0; mode != RM_END; mode++) {
2467 /* If we are in adv. settings screen for the new game's settings,
2468 * we don't want to allow comparing with new game's settings. */
2469 bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
2470
2471 list.push_back(MakeDropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled));
2472 }
2473 break;
2474
2476 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL));
2477 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME));
2478 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY));
2479 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT));
2480 break;
2481 }
2482 return list;
2483 }
2484
2485 void DrawWidget(const Rect &r, WidgetID widget) const override
2486 {
2487 switch (widget) {
2488 case WID_GS_OPTIONSPANEL: {
2490 tr.top += this->warn_lines * SETTING_HEIGHT;
2491 uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
2492 int next_row = GetSettingsTree().Draw(settings_ptr, tr.left, tr.right, tr.top,
2493 this->vscroll->GetPosition(), last_row, this->last_clicked);
2495 break;
2496 }
2497
2498 case WID_GS_HELP_TEXT:
2499 if (this->last_clicked != nullptr) {
2500 const IntSettingDesc *sd = this->last_clicked->setting;
2501
2502 Rect tr = r;
2503 switch (sd->GetType()) {
2507 default: NOT_REACHED();
2508 }
2511
2512 sd->SetValueDParams(0, sd->GetDefaultValue());
2515
2516 DrawStringMultiLine(tr, sd->GetHelp(), TC_WHITE);
2517 }
2518 break;
2519
2520 default:
2521 break;
2522 }
2523 }
2524
2530 {
2531 if (this->last_clicked != pe) this->SetDirty();
2532 this->last_clicked = pe;
2533 }
2534
2535 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2536 {
2537 switch (widget) {
2538 case WID_GS_EXPAND_ALL:
2539 this->manually_changed_folding = true;
2541 this->InvalidateData();
2542 break;
2543
2545 this->manually_changed_folding = true;
2547 this->InvalidateData();
2548 break;
2549
2550 case WID_GS_RESET_ALL:
2551 ShowQuery(
2554 this,
2556 );
2557 break;
2558
2560 DropDownList list = this->BuildDropDownList(widget);
2561 if (!list.empty()) {
2562 ShowDropDownList(this, std::move(list), this->filter.mode, widget);
2563 }
2564 break;
2565 }
2566
2567 case WID_GS_TYPE_DROPDOWN: {
2568 DropDownList list = this->BuildDropDownList(widget);
2569 if (!list.empty()) {
2570 ShowDropDownList(this, std::move(list), this->filter.type, widget);
2571 }
2572 break;
2573 }
2574 }
2575
2576 if (widget != WID_GS_OPTIONSPANEL) return;
2577
2579 if (btn == INT32_MAX || btn < this->warn_lines) return;
2580 btn -= this->warn_lines;
2581
2582 uint cur_row = 0;
2584
2585 if (clicked_entry == nullptr) return; // Clicked below the last setting of the page
2586
2587 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
2588 if (x < 0) return; // Clicked left of the entry
2589
2591 if (clicked_page != nullptr) {
2592 this->SetDisplayedHelpText(nullptr);
2593 clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
2594
2595 this->manually_changed_folding = true;
2596
2597 this->InvalidateData();
2598 return;
2599 }
2600
2601 SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
2602 assert(pe != nullptr);
2603 const IntSettingDesc *sd = pe->setting;
2604
2605 /* return if action is only active in network, or only settable by server */
2606 if (!sd->IsEditable()) {
2607 this->SetDisplayedHelpText(pe);
2608 return;
2609 }
2610
2611 auto [min_val, max_val] = sd->GetRange();
2612 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
2613
2614 /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2616 this->SetDisplayedHelpText(pe);
2617
2618 if (this->valuedropdown_entry == pe) {
2619 /* unclick the dropdown */
2621 this->closing_dropdown = false;
2622 this->valuedropdown_entry->SetButtons(0);
2623 this->valuedropdown_entry = nullptr;
2624 } else {
2625 if (this->valuedropdown_entry != nullptr) this->valuedropdown_entry->SetButtons(0);
2626 this->closing_dropdown = false;
2627
2629 int rel_y = (pt.y - wid->pos_y - WidgetDimensions::scaled.framerect.top) % wid->resize_y;
2630
2631 Rect wi_rect;
2632 wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2633 wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2634 wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2635 wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2636
2637 /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2638 if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2639 this->valuedropdown_entry = pe;
2640 this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
2641
2642 DropDownList list;
2644 sd->SetValueDParams(0, i);
2645 list.push_back(MakeDropDownListStringItem(STR_JUST_STRING2, i));
2646 }
2647
2648 ShowDropDownListAt(this, std::move(list), value, WID_GS_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);
2649 }
2650 }
2651 this->SetDirty();
2652 } else if (x < SETTING_BUTTON_WIDTH) {
2653 this->SetDisplayedHelpText(pe);
2654 int32_t oldvalue = value;
2655
2656 if (sd->IsBoolSetting()) {
2657 value ^= 1;
2658 } else {
2659 /* Add a dynamic step-size to the scroller. In a maximum of
2660 * 50-steps you should be able to get from min to max,
2661 * unless specified otherwise in the 'interval' variable
2662 * of the current setting. */
2663 uint32_t step = (sd->interval == 0) ? ((max_val - min_val) / 50) : sd->interval;
2664 if (step == 0) step = 1;
2665
2666 /* don't allow too fast scrolling */
2667 if (this->flags.Test(WindowFlag::Timeout) && this->timeout_timer > 1) {
2668 _left_button_clicked = false;
2669 return;
2670 }
2671
2672 /* Increase or decrease the value and clamp it to extremes */
2673 if (x >= SETTING_BUTTON_WIDTH / 2) {
2674 value += step;
2675 if (min_val < 0) {
2676 assert(static_cast<int32_t>(max_val) >= 0);
2677 if (value > static_cast<int32_t>(max_val)) value = static_cast<int32_t>(max_val);
2678 } else {
2679 if (static_cast<uint32_t>(value) > max_val) value = static_cast<int32_t>(max_val);
2680 }
2681 if (value < min_val) value = min_val; // skip between "disabled" and minimum
2682 } else {
2683 value -= step;
2684 if (value < min_val) value = sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val;
2685 }
2686
2687 /* Set up scroller timeout for numeric values */
2688 if (value != oldvalue) {
2689 if (this->clicked_entry != nullptr) { // Release previous buttons if any
2690 this->clicked_entry->SetButtons(0);
2691 }
2692 this->clicked_entry = pe;
2693 this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED);
2694 this->SetTimeout();
2695 _left_button_clicked = false;
2696 }
2697 }
2698
2699 if (value != oldvalue) {
2700 SetSettingValue(sd, value);
2701 this->SetDirty();
2702 }
2703 } else {
2704 /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2705 if (this->last_clicked == pe && !sd->IsBoolSetting() && !sd->flags.Test(SettingFlag::GuiDropdown)) {
2706 int64_t value64 = value;
2707 /* Show the correct currency-translated value */
2708 if (sd->flags.Test(SettingFlag::GuiCurrency)) value64 *= GetCurrency().rate;
2709
2710 CharSetFilter charset_filter = CS_NUMERAL; //default, only numeric input allowed
2711 if (min_val < 0) charset_filter = CS_NUMERAL_SIGNED; // special case, also allow '-' sign for negative input
2712
2713 this->valuewindow_entry = pe;
2714 SetDParam(0, value64);
2715 /* Limit string length to 14 so that MAX_INT32 * max currency rate doesn't exceed MAX_INT64. */
2717 }
2718 this->SetDisplayedHelpText(pe);
2719 }
2720 }
2721
2722 void OnTimeout() override
2723 {
2724 if (this->clicked_entry != nullptr) { // On timeout, release any depressed buttons
2725 this->clicked_entry->SetButtons(0);
2726 this->clicked_entry = nullptr;
2727 this->SetDirty();
2728 }
2729 }
2730
2731 void OnQueryTextFinished(std::optional<std::string> str) override
2732 {
2733 /* The user pressed cancel */
2734 if (!str.has_value()) return;
2735
2736 assert(this->valuewindow_entry != nullptr);
2737 const IntSettingDesc *sd = this->valuewindow_entry->setting;
2738
2739 int32_t value;
2740 if (!str->empty()) {
2741 long long llvalue = atoll(str->c_str());
2742
2743 /* Save the correct currency-translated value */
2744 if (sd->flags.Test(SettingFlag::GuiCurrency)) llvalue /= GetCurrency().rate;
2745
2746 value = ClampTo<int32_t>(llvalue);
2747 } else {
2748 value = sd->GetDefaultValue();
2749 }
2750
2751 SetSettingValue(this->valuewindow_entry->setting, value);
2752 this->SetDirty();
2753 }
2754
2755 void OnDropdownSelect(WidgetID widget, int index) override
2756 {
2757 switch (widget) {
2759 this->filter.mode = (RestrictionMode)index;
2760 if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2761 this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2762
2763 if (!this->manually_changed_folding) {
2764 /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2765 GetSettingsTree().UpdateFilterState(this->filter, false);
2767 }
2768 } else {
2769 /* Non-'changes' filter. Save as default. */
2771 }
2772 this->InvalidateData();
2773 break;
2774
2776 this->filter.type = (SettingType)index;
2777 this->InvalidateData();
2778 break;
2779
2781 /* Deal with drop down boxes on the panel. */
2782 assert(this->valuedropdown_entry != nullptr);
2783 const IntSettingDesc *sd = this->valuedropdown_entry->setting;
2784 assert(sd->flags.Test(SettingFlag::GuiDropdown));
2785
2786 SetSettingValue(sd, index);
2787 this->SetDirty();
2788 break;
2789 }
2790 }
2791
2792 void OnDropdownClose(Point pt, WidgetID widget, int index, bool instant_close) override
2793 {
2794 if (widget != WID_GS_SETTING_DROPDOWN) {
2795 /* Normally the default implementation of OnDropdownClose() takes care of
2796 * a few things. We want that behaviour here too, but only for
2797 * "normal" dropdown boxes. The special dropdown boxes added for every
2798 * setting that needs one can't have this call. */
2799 Window::OnDropdownClose(pt, widget, index, instant_close);
2800 } else {
2801 /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2802 * the same dropdown button was clicked again, and then not open the dropdown again.
2803 * So, we only remember that it was closed, and process it on the next OnPaint, which is
2804 * after OnClick. */
2805 assert(this->valuedropdown_entry != nullptr);
2806 this->closing_dropdown = true;
2807 this->SetDirty();
2808 }
2809 }
2810
2811 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2812 {
2813 if (!gui_scope) return;
2814
2815 /* Update which settings are to be visible. */
2816 RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2817 this->filter.min_cat = min_level;
2818 this->filter.type_hides = false;
2819 GetSettingsTree().UpdateFilterState(this->filter, false);
2820
2821 if (this->filter.string.IsEmpty()) {
2822 this->warn_missing = WHR_NONE;
2823 } else if (min_level < this->filter.min_cat) {
2824 this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2825 } else {
2826 this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2827 }
2828 this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2829
2830 if (this->last_clicked != nullptr && !GetSettingsTree().IsVisible(this->last_clicked)) {
2831 this->SetDisplayedHelpText(nullptr);
2832 }
2833
2834 bool all_folded = true;
2835 bool all_unfolded = true;
2837 this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2839 }
2840
2842 {
2843 if (wid == WID_GS_FILTER) {
2844 this->filter.string.SetFilterTerm(this->filter_editbox.text.GetText());
2845 if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2846 /* User never expanded/collapsed single pages and entered a filter term.
2847 * Expand everything, to save weird expand clicks, */
2849 }
2850 this->InvalidateData();
2851 }
2852 }
2853
2854 void OnResize() override
2855 {
2856 this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, WidgetDimensions::scaled.framerect.Vertical());
2857 }
2858};
2859
2861
2862static constexpr NWidgetPart _nested_settings_selection_widgets[] = {
2864 NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2865 NWidget(WWT_CAPTION, COLOUR_MAUVE), SetStringTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2866 NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2867 EndContainer(),
2868 NWidget(WWT_PANEL, COLOUR_MAUVE),
2871 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GS_RESTRICT_CATEGORY), SetStringTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY),
2872 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),
2873 EndContainer(),
2875 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GS_RESTRICT_TYPE), SetStringTip(STR_CONFIG_SETTING_RESTRICT_TYPE),
2876 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),
2877 EndContainer(),
2879 NWidget(WWT_TEXT, INVALID_COLOUR), SetFill(0, 1), SetStringTip(STR_CONFIG_SETTING_FILTER_TITLE),
2880 NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
2881 EndContainer(),
2882 EndContainer(),
2883 EndContainer(),
2887 EndContainer(),
2888 NWidget(WWT_PANEL, COLOUR_MAUVE),
2889 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2891 EndContainer(),
2893 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetStringTip(STR_CONFIG_SETTING_EXPAND_ALL),
2894 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetStringTip(STR_CONFIG_SETTING_COLLAPSE_ALL),
2895 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_RESET_ALL), SetStringTip(STR_CONFIG_SETTING_RESET_ALL),
2896 NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2897 EndContainer(),
2898 NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2899 EndContainer(),
2900};
2901
2902static WindowDesc _settings_selection_desc(
2903 WDP_CENTER, "settings", 510, 450,
2905 {},
2906 _nested_settings_selection_widgets
2907);
2908
2911{
2913 new GameSettingsWindow(_settings_selection_desc);
2914}
2915
2916
2926void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
2927{
2928 int colour = GetColourGradient(button_colour, SHADE_DARKER);
2929 Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2930
2931 Rect lr = {x, y, x + (int)dim.width - 1, y + (int)dim.height - 1};
2932 Rect rr = {x + (int)dim.width, y, x + (int)dim.width * 2 - 1, y + (int)dim.height - 1};
2933
2934 DrawFrameRect(lr, button_colour, (state == 1) ? FrameFlag::Lowered : FrameFlags{});
2935 DrawFrameRect(rr, button_colour, (state == 2) ? FrameFlag::Lowered : FrameFlags{});
2936 DrawSpriteIgnorePadding(SPR_ARROW_LEFT, PAL_NONE, lr, SA_CENTER);
2937 DrawSpriteIgnorePadding(SPR_ARROW_RIGHT, PAL_NONE, rr, SA_CENTER);
2938
2939 /* Grey out the buttons that aren't clickable */
2940 bool rtl = _current_text_dir == TD_RTL;
2941 if (rtl ? !clickable_right : !clickable_left) {
2943 }
2944 if (rtl ? !clickable_left : !clickable_right) {
2946 }
2947}
2948
2957void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2958{
2959 int colour = GetColourGradient(button_colour, SHADE_DARKER);
2960
2961 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
2962
2963 DrawFrameRect(r, button_colour, state ? FrameFlag::Lowered : FrameFlags{});
2964 DrawSpriteIgnorePadding(SPR_ARROW_DOWN, PAL_NONE, r, SA_CENTER);
2965
2966 if (!clickable) {
2968 }
2969}
2970
2978void DrawBoolButton(int x, int y, bool state, bool clickable)
2979{
2980 static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2981
2982 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
2983 DrawFrameRect(r, _bool_ctabs[state][clickable], state ? FrameFlag::Lowered : FrameFlags{});
2984}
2985
2987 int query_widget;
2988
2990 {
2991 this->InitNested();
2992
2993 SetButtonState();
2994 }
2995
2996 void SetButtonState()
2997 {
3002 }
3003
3004 void SetStringParameters(WidgetID widget) const override
3005 {
3006 switch (widget) {
3007 case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
3008 case WID_CC_SEPARATOR: SetDParamStr(0, GetCustomCurrency().separator); break;
3009 case WID_CC_PREFIX: SetDParamStr(0, GetCustomCurrency().prefix); break;
3010 case WID_CC_SUFFIX: SetDParamStr(0, GetCustomCurrency().suffix); break;
3011 case WID_CC_YEAR:
3013 SetDParam(1, GetCustomCurrency().to_euro);
3014 break;
3015
3016 case WID_CC_PREVIEW:
3017 SetDParam(0, 10000);
3018 break;
3019 }
3020 }
3021
3023 {
3024 switch (widget) {
3025 /* Set the appropriate width for the up/down buttons. */
3026 case WID_CC_RATE_DOWN:
3027 case WID_CC_RATE_UP:
3028 case WID_CC_YEAR_DOWN:
3029 case WID_CC_YEAR_UP:
3030 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH / 2, (uint)SETTING_BUTTON_HEIGHT});
3031 break;
3032
3033 /* Set the appropriate width for the edit buttons. */
3035 case WID_CC_PREFIX_EDIT:
3036 case WID_CC_SUFFIX_EDIT:
3037 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH, (uint)SETTING_BUTTON_HEIGHT});
3038 break;
3039
3040 /* Make sure the window is wide enough for the widest exchange rate */
3041 case WID_CC_RATE:
3042 SetDParam(0, 1);
3043 SetDParam(1, INT32_MAX);
3045 break;
3046 }
3047 }
3048
3049 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
3050 {
3051 int line = 0;
3052 int len = 0;
3053 StringID str = STR_NULL;
3055
3056 switch (widget) {
3057 case WID_CC_RATE_DOWN:
3058 if (GetCustomCurrency().rate > 1) GetCustomCurrency().rate--;
3059 if (GetCustomCurrency().rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
3061 break;
3062
3063 case WID_CC_RATE_UP:
3067 break;
3068
3069 case WID_CC_RATE:
3070 SetDParam(0, GetCustomCurrency().rate);
3071 str = STR_JUST_INT;
3072 len = 5;
3073 line = WID_CC_RATE;
3074 afilter = CS_NUMERAL;
3075 break;
3076
3078 case WID_CC_SEPARATOR:
3079 SetDParamStr(0, GetCustomCurrency().separator);
3080 str = STR_JUST_RAW_STRING;
3081 len = 7;
3082 line = WID_CC_SEPARATOR;
3083 break;
3084
3085 case WID_CC_PREFIX_EDIT:
3086 case WID_CC_PREFIX:
3087 SetDParamStr(0, GetCustomCurrency().prefix);
3088 str = STR_JUST_RAW_STRING;
3089 len = 15;
3090 line = WID_CC_PREFIX;
3091 break;
3092
3093 case WID_CC_SUFFIX_EDIT:
3094 case WID_CC_SUFFIX:
3095 SetDParamStr(0, GetCustomCurrency().suffix);
3096 str = STR_JUST_RAW_STRING;
3097 len = 15;
3098 line = WID_CC_SUFFIX;
3099 break;
3100
3101 case WID_CC_YEAR_DOWN:
3105 break;
3106
3107 case WID_CC_YEAR_UP:
3111 break;
3112
3113 case WID_CC_YEAR:
3114 SetDParam(0, GetCustomCurrency().to_euro);
3115 str = STR_JUST_INT;
3116 len = 7;
3117 line = WID_CC_YEAR;
3118 afilter = CS_NUMERAL;
3119 break;
3120 }
3121
3122 if (len != 0) {
3123 this->query_widget = line;
3124 ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
3125 }
3126
3127 this->SetTimeout();
3128 this->SetDirty();
3129 }
3130
3131 void OnQueryTextFinished(std::optional<std::string> str) override
3132 {
3133 if (!str.has_value()) return;
3134
3135 switch (this->query_widget) {
3136 case WID_CC_RATE:
3137 GetCustomCurrency().rate = Clamp(atoi(str->c_str()), 1, UINT16_MAX);
3138 break;
3139
3140 case WID_CC_SEPARATOR: // Thousands separator
3141 GetCustomCurrency().separator = std::move(*str);
3142 break;
3143
3144 case WID_CC_PREFIX:
3145 GetCustomCurrency().prefix = std::move(*str);
3146 break;
3147
3148 case WID_CC_SUFFIX:
3149 GetCustomCurrency().suffix = std::move(*str);
3150 break;
3151
3152 case WID_CC_YEAR: { // Year to switch to euro
3153 TimerGameCalendar::Year val{atoi(str->c_str())};
3154
3156 break;
3157 }
3158 }
3160 SetButtonState();
3161 }
3162
3163 void OnTimeout() override
3164 {
3165 this->SetDirty();
3166 }
3167};
3168
3169static constexpr NWidgetPart _nested_cust_currency_widgets[] = {
3171 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
3172 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
3173 EndContainer(),
3174 NWidget(WWT_PANEL, COLOUR_GREY),
3179 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetArrowWidgetTypeTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
3180 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetArrowWidgetTypeTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
3181 EndContainer(),
3182 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_RATE), SetStringTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
3183 EndContainer(),
3185 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
3186 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_SEPARATOR), SetStringTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
3187 EndContainer(),
3189 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
3190 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_PREFIX), SetStringTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
3191 EndContainer(),
3193 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
3194 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_SUFFIX), SetStringTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
3195 EndContainer(),
3198 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetArrowWidgetTypeTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
3199 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetArrowWidgetTypeTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
3200 EndContainer(),
3201 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_YEAR), SetStringTip(STR_JUST_STRING1, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
3202 EndContainer(),
3203 EndContainer(),
3204 NWidget(WWT_LABEL, INVALID_COLOUR, WID_CC_PREVIEW),
3205 SetStringTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP),
3206 EndContainer(),
3207 EndContainer(),
3208};
3209
3210static WindowDesc _cust_currency_desc(
3211 WDP_CENTER, nullptr, 0, 0,
3213 {},
3214 _nested_cust_currency_widgets
3215);
3216
3218static void ShowCustCurrency()
3219{
3221 new CustomCurrencyWindow(_cust_currency_desc);
3222}
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.
#define CLRBITS(x, y)
Clears several bits in a variable.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
#define SETBITS(x, y)
Sets several bits in a variable.
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().
Enum-as-bit-set wrapper.
constexpr bool Test(Tenum value) const
Test if the enum value is set.
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 contaier.
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 identation 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:25
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:61
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(StringID summary_msg, int x, int y, 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:1931
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(StringID caption, StringID 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(StringID 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:1319
@ 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:58
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:56
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.
SettingEntryFlags
Flags for SettingEntry.
@ SEF_FILTERED
Entry is hidden by the string filter.
@ SEF_BUTTONS_MASK
Bit-mask for button flags.
@ SEF_LEFT_DEPRESSED
Of a numeric setting entry, the left button is depressed.
@ SEF_LAST_FIELD
This entry is the last one in a (sub-)page.
@ SEF_RIGHT_DEPRESSED
Of a numeric setting entry, the right button is depressed.
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:2177
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:2285
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:104
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:370
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.
uint8_t 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.
void SetValueDParams(uint first_param, int32_t value) const
Set the DParams for drawing the value of the setting.
Definition settings.cpp:460
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:490
StringID GetTitle() const
Get the title of the setting.
Definition settings.cpp:441
int32_t GetDefaultValue() const
Get the default value of the setting.
Definition settings.cpp:481
StringID GetHelp() const
Get the help text of the setting.
Definition settings.cpp:450
virtual bool IsBoolSetting() const
Check whether this setting is a boolean type setting.
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition settings.cpp:581
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 bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * Get(size_t index)
Returns Titem with given index.
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:903
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:920
const struct IntSettingDesc * AsIntSetting() const
Get the setting description of this setting as an integer setting.
Definition settings.cpp:930
Standard setting.
uint Length() const override
Return number of rows needed to display the (filtered) entry.
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.
void SetButtons(uint8_t new_val)
Set the button-depressed flags (SEF_LEFT_DEPRESSED and SEF_RIGHT_DEPRESSED) to a specified value.
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(const char *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:290
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:970
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).
@ 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
@ NC_EQUALSIZE
Value of the NCB_EQUALSIZE flag.
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.