OpenTTD Source 20241224-master-gf74b0cf984
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), SetDataTip(STR_JUST_STRING2, STR_NULL),
182 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM, STR_NULL),
183 NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_SOCIAL_PLUGIN_PLATFORM), SetMinimalSize(100, 12), SetDataTip(STR_JUST_RAW_STRING, STR_NULL), SetAlignment(SA_RIGHT),
184 EndContainer(),
186 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE, STR_NULL),
187 NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_SOCIAL_PLUGIN_STATE), SetMinimalSize(100, 12), SetDataTip(STR_JUST_STRING1, STR_NULL), SetAlignment(SA_RIGHT),
188 EndContainer(),
189 EndContainer(),
190 EndContainer(),
191};
192
193static constexpr NWidgetPart _nested_social_plugins_none_widgets[] = {
195 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE, STR_NULL),
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 & WF_CENTERED);
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), SetDataTip(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), SetDataTip(STR_GAME_OPTIONS_TAB_GENERAL, STR_GAME_OPTIONS_TAB_GENERAL_TT), SetFill(1, 0),
1018 NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_GRAPHICS), SetMinimalTextLines(2, 0), SetDataTip(STR_GAME_OPTIONS_TAB_GRAPHICS, STR_GAME_OPTIONS_TAB_GRAPHICS_TT), SetFill(1, 0),
1019 NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_SOUND), SetMinimalTextLines(2, 0), SetDataTip(STR_GAME_OPTIONS_TAB_SOUND, STR_GAME_OPTIONS_TAB_SOUND_TT), SetFill(1, 0),
1020 NWidget(WWT_TEXTBTN, COLOUR_YELLOW, WID_GO_TAB_SOCIAL), SetMinimalTextLines(2, 0), SetDataTip(STR_GAME_OPTIONS_TAB_SOCIAL, STR_GAME_OPTIONS_TAB_SOCIAL_TT), SetFill(1, 0),
1021 EndContainer(),
1022 EndContainer(),
1023 NWidget(WWT_PANEL, COLOUR_GREY),
1025 /* General tab */
1027 NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
1028 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_LANG_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_JUST_RAW_STRING, STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0),
1029 EndContainer(),
1030
1031 NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME, STR_NULL),
1032 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_AUTOSAVE_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_JUST_STRING, STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP), SetFill(1, 0),
1033 EndContainer(),
1034
1035 NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
1036 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_CURRENCY_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(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), SetDataTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_FRAME, STR_NULL), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1042 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY, STR_NULL),
1043 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_SURVEY_PARTICIPATE_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetDataTip(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), SetDataTip(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), SetDataTip(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), SetDataTip(STR_GAME_OPTIONS_GUI_SCALE_FRAME, STR_NULL),
1057 NWidget(WWT_EMPTY, COLOUR_GREY, WID_GO_GUI_SCALE), SetMinimalSize(67, 0), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FS_SMALL), SetFill(0, 0), SetDataTip(0x0, STR_GAME_OPTIONS_GUI_SCALE_TOOLTIP),
1059 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_GUI_SCALE_AUTO, STR_NULL),
1060 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_SCALE_AUTO), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_SCALE_AUTO_TOOLTIP),
1061 EndContainer(),
1063 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_GUI_SCALE_BEVELS, STR_NULL),
1064 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_SCALE_BEVEL_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_SCALE_BEVELS_TOOLTIP),
1065 EndContainer(),
1066#ifdef HAS_TRUETYPE_FONT
1068 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_GUI_FONT_SPRITE, STR_NULL),
1069 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_FONT_SPRITE), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_GUI_FONT_SPRITE_TOOLTIP),
1070 EndContainer(),
1072 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_GUI_FONT_AA, STR_NULL),
1073 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_GUI_FONT_AA), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetDataTip(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), SetDataTip(STR_GAME_OPTIONS_GRAPHICS, STR_NULL),
1082 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL),
1083 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_RESOLUTION_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_JUST_STRING2, STR_GAME_OPTIONS_RESOLUTION_TOOLTIP),
1084 EndContainer(),
1086 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_REFRESH_RATE, STR_NULL),
1087 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_REFRESH_RATE_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP),
1088 EndContainer(),
1090 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL),
1091 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
1092 EndContainer(),
1094 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_VIDEO_ACCELERATION, STR_NULL),
1095 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_ACCEL_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_VIDEO_ACCELERATION_TOOLTIP),
1096 EndContainer(),
1097#ifndef __APPLE__
1099 NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_VIDEO_VSYNC, STR_NULL),
1100 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_VIDEO_VSYNC_BUTTON), SetAspect(WidgetDimensions::ASPECT_SETTINGS_BUTTON), SetDataTip(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), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0), SetFill(1, 0),
1111 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_JUST_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP), SetFill(1, 0),
1112 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_PARAMETERS), SetDataTip(STR_NEWGRF_SETTINGS_SET_PARAMETERS, STR_NULL),
1113 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_CONTENT_DOWNLOAD), SetDataTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1114 EndContainer(),
1115 NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_DESCRIPTION), SetMinimalSize(200, 0), SetDataTip(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), SetDataTip(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), SetDataTip(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), SetDataTip(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), SetDataTip(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), SetDataTip(STR_GAME_OPTIONS_VOLUME, STR_NULL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0),
1133 NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_TEXT_SFX_VOLUME), SetMinimalSize(0, 12), SetDataTip(STR_GAME_OPTIONS_SFX_VOLUME, STR_NULL),
1134 NWidget(WWT_EMPTY, COLOUR_GREY, WID_GO_BASE_SFX_VOLUME), SetMinimalSize(67, 0), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FS_SMALL), SetFill(1, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
1135 EndContainer(),
1137 NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_TEXT_MUSIC_VOLUME), SetMinimalSize(0, 12), SetDataTip(STR_GAME_OPTIONS_MUSIC_VOLUME, STR_NULL),
1138 NWidget(WWT_EMPTY, COLOUR_GREY, WID_GO_BASE_MUSIC_VOLUME), SetMinimalSize(67, 0), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FS_SMALL), SetFill(1, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
1139 EndContainer(),
1140 EndContainer(),
1141
1142 NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1144 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(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), SetDataTip(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), SetDataTip(STR_NULL, 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), SetDataTip(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), SetDataTip(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), SetDataTip(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), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1156 EndContainer(),
1157 EndContainer(),
1158 EndContainer(),
1159
1160 NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1162 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(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), SetDataTip(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), SetDataTip(STR_NULL, STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0),
1168 NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_JUKEBOX), SetMinimalSize(22, 22), SetDataTip(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), SetDataTip(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), SetDataTip(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), SetDataTip(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), SetDataTip(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 0,
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{
1481 SetSettingValue(this->setting, this->setting->def);
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->def;
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{
1592 if ((sd->flags & SF_PER_COMPANY) != 0) {
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 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
1625 if (sd->IsBoolSetting()) {
1626 /* Draw checkbox for boolean-value either on/off */
1627 DrawBoolButton(buttons_left, button_y, value != 0, editable);
1628 } else if ((sd->flags & SF_GUI_DROPDOWN) != 0) {
1629 /* Draw [v] button for settings of an enum-type */
1630 DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1631 } else {
1632 /* Draw [<][>] boxes for settings of an integer-type */
1633 DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1634 editable && value != (sd->flags & SF_GUI_0_IS_SPECIAL ? 0 : sd->min), editable && (uint32_t)value != sd->max);
1635 }
1636 sd->SetValueDParams(1, value);
1637 DrawString(text_left, text_right, y + (SETTING_HEIGHT - GetCharacterHeight(FS_NORMAL)) / 2, sd->GetTitle(), highlight ? TC_WHITE : TC_LIGHT_BLUE);
1638}
1639
1640/* == SettingsContainer methods == */
1641
1646void SettingsContainer::Init(uint8_t level)
1647{
1648 for (auto &it : this->entries) {
1649 it->Init(level);
1650 }
1651}
1652
1655{
1656 for (auto settings_entry : this->entries) {
1657 settings_entry->ResetAll();
1658 }
1659}
1660
1663{
1664 for (auto &it : this->entries) {
1665 it->FoldAll();
1666 }
1667}
1668
1671{
1672 for (auto &it : this->entries) {
1673 it->UnFoldAll();
1674 }
1675}
1676
1682void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1683{
1684 for (auto &it : this->entries) {
1685 it->GetFoldingState(all_folded, all_unfolded);
1686 }
1687}
1688
1696{
1697 bool visible = false;
1698 bool first_visible = true;
1699 for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1700 visible |= (*it)->UpdateFilterState(filter, force_visible);
1701 (*it)->SetLastField(first_visible);
1702 if (visible && first_visible) first_visible = false;
1703 }
1704 return visible;
1705}
1706
1707
1715{
1716 for (const auto &it : this->entries) {
1717 if (it->IsVisible(item)) return true;
1718 }
1719 return false;
1720}
1721
1724{
1725 uint length = 0;
1726 for (const auto &it : this->entries) {
1727 length += it->Length();
1728 }
1729 return length;
1730}
1731
1739{
1740 BaseSettingEntry *pe = nullptr;
1741 for (const auto &it : this->entries) {
1742 pe = it->FindEntry(row_num, cur_row);
1743 if (pe != nullptr) {
1744 break;
1745 }
1746 }
1747 return pe;
1748}
1749
1756{
1757 uint biggest = 0;
1758 for (const auto &it : this->entries) {
1759 biggest = std::max(biggest, it->GetMaxHelpHeight(maxw));
1760 }
1761 return biggest;
1762}
1763
1764
1779uint SettingsContainer::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
1780{
1781 for (const auto &it : this->entries) {
1782 cur_row = it->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1783 if (cur_row >= max_row) break;
1784 }
1785 return cur_row;
1786}
1787
1788/* == SettingsPage methods == */
1789
1795{
1796 this->title = title;
1797 this->folded = true;
1798}
1799
1804void SettingsPage::Init(uint8_t level)
1805{
1808}
1809
1812{
1813 for (auto settings_entry : this->entries) {
1814 settings_entry->ResetAll();
1815 }
1816}
1817
1820{
1821 if (this->IsFiltered()) return;
1822 this->folded = true;
1823
1825}
1826
1829{
1830 if (this->IsFiltered()) return;
1831 this->folded = false;
1832
1834}
1835
1841void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1842{
1843 if (this->IsFiltered()) return;
1844
1845 if (this->folded) {
1846 all_unfolded = false;
1847 } else {
1848 all_folded = false;
1849 }
1850
1851 SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1852}
1853
1860bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1861{
1862 if (!force_visible && !filter.string.IsEmpty()) {
1863 filter.string.ResetState();
1864 filter.string.AddLine(this->title);
1865 force_visible = filter.string.GetState();
1866 }
1867
1868 bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1869 if (visible) {
1870 CLRBITS(this->flags, SEF_FILTERED);
1871 } else {
1872 SETBITS(this->flags, SEF_FILTERED);
1873 }
1874 return visible;
1875}
1876
1884{
1885 if (this->IsFiltered()) return false;
1886 if (this == item) return true;
1887 if (this->folded) return false;
1888
1889 return SettingsContainer::IsVisible(item);
1890}
1891
1894{
1895 if (this->IsFiltered()) return 0;
1896 if (this->folded) return 1; // Only displaying the title
1897
1898 return 1 + SettingsContainer::Length();
1899}
1900
1907BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1908{
1909 if (this->IsFiltered()) return nullptr;
1910 if (row_num == *cur_row) return this;
1911 (*cur_row)++;
1912 if (this->folded) return nullptr;
1913
1914 return SettingsContainer::FindEntry(row_num, cur_row);
1915}
1916
1931uint 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
1932{
1933 if (this->IsFiltered()) return cur_row;
1934 if (cur_row >= max_row) return cur_row;
1935
1936 cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1937
1938 if (!this->folded) {
1939 if (this->flags & SEF_LAST_FIELD) {
1940 assert(this->level < 8 * sizeof(parent_last));
1941 SetBit(parent_last, this->level); // Add own last-field state
1942 }
1943
1944 cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1945 }
1946
1947 return cur_row;
1948}
1949
1956void SettingsPage::DrawSetting(GameSettings *, int left, int right, int y, bool) const
1957{
1958 bool rtl = _current_text_dir == TD_RTL;
1959 DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1960 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);
1961}
1962
1965{
1966 static SettingsContainer *main = nullptr;
1967
1968 if (main == nullptr)
1969 {
1970 /* Build up the dynamic settings-array only once per OpenTTD session */
1971 main = new SettingsContainer();
1972
1973 SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1974 {
1975 localisation->Add(new SettingEntry("locale.units_velocity"));
1976 localisation->Add(new SettingEntry("locale.units_velocity_nautical"));
1977 localisation->Add(new SettingEntry("locale.units_power"));
1978 localisation->Add(new SettingEntry("locale.units_weight"));
1979 localisation->Add(new SettingEntry("locale.units_volume"));
1980 localisation->Add(new SettingEntry("locale.units_force"));
1981 localisation->Add(new SettingEntry("locale.units_height"));
1982 localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1983 }
1984
1985 SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1986 {
1987 graphics->Add(new SettingEntry("gui.zoom_min"));
1988 graphics->Add(new SettingEntry("gui.zoom_max"));
1989 graphics->Add(new SettingEntry("gui.sprite_zoom_min"));
1990 graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1991 graphics->Add(new SettingEntry("gui.linkgraph_colours"));
1992 graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1993 }
1994
1995 SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1996 {
1997 sound->Add(new SettingEntry("sound.click_beep"));
1998 sound->Add(new SettingEntry("sound.confirm"));
1999 sound->Add(new SettingEntry("sound.news_ticker"));
2000 sound->Add(new SettingEntry("sound.news_full"));
2001 sound->Add(new SettingEntry("sound.new_year"));
2002 sound->Add(new SettingEntry("sound.disaster"));
2003 sound->Add(new SettingEntry("sound.vehicle"));
2004 sound->Add(new SettingEntry("sound.ambient"));
2005 }
2006
2007 SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
2008 {
2009 SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
2010 {
2011 general->Add(new SettingEntry("gui.osk_activation"));
2012 general->Add(new SettingEntry("gui.hover_delay_ms"));
2013 general->Add(new SettingEntry("gui.errmsg_duration"));
2014 general->Add(new SettingEntry("gui.window_snap_radius"));
2015 general->Add(new SettingEntry("gui.window_soft_limit"));
2016 general->Add(new SettingEntry("gui.right_click_wnd_close"));
2017 }
2018
2019 SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
2020 {
2021 viewports->Add(new SettingEntry("gui.auto_scrolling"));
2022 viewports->Add(new SettingEntry("gui.scroll_mode"));
2023 viewports->Add(new SettingEntry("gui.smooth_scroll"));
2024 /* While the horizontal scrollwheel scrolling is written as general code, only
2025 * the cocoa (OSX) driver generates input for it.
2026 * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
2027 viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
2028 viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
2029#ifdef __APPLE__
2030 /* We might need to emulate a right mouse button on mac */
2031 viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
2032#endif
2033 viewports->Add(new SettingEntry("gui.population_in_label"));
2034 viewports->Add(new SettingEntry("gui.liveries"));
2035 viewports->Add(new SettingEntry("construction.train_signal_side"));
2036 viewports->Add(new SettingEntry("gui.measure_tooltip"));
2037 viewports->Add(new SettingEntry("gui.loading_indicators"));
2038 viewports->Add(new SettingEntry("gui.show_track_reservation"));
2039 }
2040
2041 SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
2042 {
2043 construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
2044 construction->Add(new SettingEntry("gui.persistent_buildingtools"));
2045 construction->Add(new SettingEntry("gui.default_rail_type"));
2046 construction->Add(new SettingEntry("gui.semaphore_build_before"));
2047 construction->Add(new SettingEntry("gui.signal_gui_mode"));
2048 construction->Add(new SettingEntry("gui.cycle_signal_types"));
2049 construction->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
2050 construction->Add(new SettingEntry("gui.auto_remove_signals"));
2051 }
2052
2053 interface->Add(new SettingEntry("gui.toolbar_pos"));
2054 interface->Add(new SettingEntry("gui.statusbar_pos"));
2055 interface->Add(new SettingEntry("gui.prefer_teamchat"));
2056 interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
2057 interface->Add(new SettingEntry("gui.timetable_mode"));
2058 interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
2059 interface->Add(new SettingEntry("gui.show_newgrf_name"));
2060 interface->Add(new SettingEntry("gui.show_cargo_in_vehicle_lists"));
2061 }
2062
2063 SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
2064 {
2065 advisors->Add(new SettingEntry("gui.coloured_news_year"));
2066 advisors->Add(new SettingEntry("news_display.general"));
2067 advisors->Add(new SettingEntry("news_display.new_vehicles"));
2068 advisors->Add(new SettingEntry("news_display.accident"));
2069 advisors->Add(new SettingEntry("news_display.accident_other"));
2070 advisors->Add(new SettingEntry("news_display.company_info"));
2071 advisors->Add(new SettingEntry("news_display.acceptance"));
2072 advisors->Add(new SettingEntry("news_display.arrival_player"));
2073 advisors->Add(new SettingEntry("news_display.arrival_other"));
2074 advisors->Add(new SettingEntry("news_display.advice"));
2075 advisors->Add(new SettingEntry("gui.order_review_system"));
2076 advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
2077 advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
2078 advisors->Add(new SettingEntry("gui.old_vehicle_warn"));
2079 advisors->Add(new SettingEntry("gui.show_finances"));
2080 advisors->Add(new SettingEntry("news_display.economy"));
2081 advisors->Add(new SettingEntry("news_display.subsidies"));
2082 advisors->Add(new SettingEntry("news_display.open"));
2083 advisors->Add(new SettingEntry("news_display.close"));
2084 advisors->Add(new SettingEntry("news_display.production_player"));
2085 advisors->Add(new SettingEntry("news_display.production_other"));
2086 advisors->Add(new SettingEntry("news_display.production_nobody"));
2087 }
2088
2089 SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
2090 {
2091 company->Add(new SettingEntry("gui.starting_colour"));
2092 company->Add(new SettingEntry("gui.starting_colour_secondary"));
2093 company->Add(new SettingEntry("company.engine_renew"));
2094 company->Add(new SettingEntry("company.engine_renew_months"));
2095 company->Add(new SettingEntry("company.engine_renew_money"));
2096 company->Add(new SettingEntry("vehicle.servint_ispercent"));
2097 company->Add(new SettingEntry("vehicle.servint_trains"));
2098 company->Add(new SettingEntry("vehicle.servint_roadveh"));
2099 company->Add(new SettingEntry("vehicle.servint_ships"));
2100 company->Add(new SettingEntry("vehicle.servint_aircraft"));
2101 }
2102
2103 SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
2104 {
2105 accounting->Add(new SettingEntry("difficulty.infinite_money"));
2106 accounting->Add(new SettingEntry("economy.inflation"));
2107 accounting->Add(new SettingEntry("difficulty.initial_interest"));
2108 accounting->Add(new SettingEntry("difficulty.max_loan"));
2109 accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
2110 accounting->Add(new SettingEntry("difficulty.subsidy_duration"));
2111 accounting->Add(new SettingEntry("economy.feeder_payment_share"));
2112 accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
2113 accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
2114 accounting->Add(new SettingEntry("difficulty.construction_cost"));
2115 }
2116
2117 SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
2118 {
2119 SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
2120 {
2121 physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
2122 physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
2123 physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
2124 physics->Add(new SettingEntry("vehicle.freight_trains"));
2125 physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
2126 physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
2127 physics->Add(new SettingEntry("vehicle.smoke_amount"));
2128 physics->Add(new SettingEntry("vehicle.plane_speed"));
2129 }
2130
2131 SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
2132 {
2133 routing->Add(new SettingEntry("vehicle.road_side"));
2134 routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
2135 routing->Add(new SettingEntry("pf.reverse_at_signals"));
2136 routing->Add(new SettingEntry("pf.forbid_90_deg"));
2137 }
2138
2139 SettingsPage *orders = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ORDERS));
2140 {
2141 orders->Add(new SettingEntry("gui.new_nonstop"));
2142 orders->Add(new SettingEntry("gui.quick_goto"));
2143 orders->Add(new SettingEntry("gui.stop_location"));
2144 }
2145 }
2146
2147 SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
2148 {
2149 limitations->Add(new SettingEntry("construction.command_pause_level"));
2150 limitations->Add(new SettingEntry("construction.autoslope"));
2151 limitations->Add(new SettingEntry("construction.extra_dynamite"));
2152 limitations->Add(new SettingEntry("construction.map_height_limit"));
2153 limitations->Add(new SettingEntry("construction.max_bridge_length"));
2154 limitations->Add(new SettingEntry("construction.max_bridge_height"));
2155 limitations->Add(new SettingEntry("construction.max_tunnel_length"));
2156 limitations->Add(new SettingEntry("station.never_expire_airports"));
2157 limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
2158 limitations->Add(new SettingEntry("vehicle.max_trains"));
2159 limitations->Add(new SettingEntry("vehicle.max_roadveh"));
2160 limitations->Add(new SettingEntry("vehicle.max_aircraft"));
2161 limitations->Add(new SettingEntry("vehicle.max_ships"));
2162 limitations->Add(new SettingEntry("vehicle.max_train_length"));
2163 limitations->Add(new SettingEntry("station.station_spread"));
2164 limitations->Add(new SettingEntry("station.distant_join_stations"));
2165 limitations->Add(new SettingEntry("station.modified_catchment"));
2166 limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
2167 limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
2168 limitations->Add(new SettingEntry("construction.crossing_with_competitor"));
2169 limitations->Add(new SettingEntry("vehicle.disable_elrails"));
2170 limitations->Add(new SettingEntry("order.station_length_loading_penalty"));
2171 }
2172
2173 SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
2174 {
2175 disasters->Add(new SettingEntry("difficulty.disasters"));
2176 disasters->Add(new SettingEntry("difficulty.economy"));
2177 disasters->Add(new SettingEntry("vehicle.plane_crashes"));
2178 disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
2179 disasters->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
2180 disasters->Add(new SettingEntry("order.serviceathelipad"));
2181 }
2182
2183 SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
2184 {
2185 genworld->Add(new SettingEntry("game_creation.landscape"));
2186 genworld->Add(new SettingEntry("game_creation.land_generator"));
2187 genworld->Add(new SettingEntry("difficulty.terrain_type"));
2188 genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
2189 genworld->Add(new SettingEntry("game_creation.variety"));
2190 genworld->Add(new SettingEntry("game_creation.snow_coverage"));
2191 genworld->Add(new SettingEntry("game_creation.snow_line_height"));
2192 genworld->Add(new SettingEntry("game_creation.desert_coverage"));
2193 genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
2194 }
2195
2196 SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
2197 {
2198 SettingsPage *time = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TIME));
2199 {
2200 time->Add(new SettingEntry("economy.timekeeping_units"));
2201 time->Add(new SettingEntry("economy.minutes_per_calendar_year"));
2202 time->Add(new SettingEntry("game_creation.ending_year"));
2203 time->Add(new SettingEntry("gui.pause_on_newgame"));
2204 time->Add(new SettingEntry("gui.fast_forward_speed_limit"));
2205 }
2206
2207 SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
2208 {
2209 authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
2210 authorities->Add(new SettingEntry("economy.bribe"));
2211 authorities->Add(new SettingEntry("economy.exclusive_rights"));
2212 authorities->Add(new SettingEntry("economy.fund_roads"));
2213 authorities->Add(new SettingEntry("economy.fund_buildings"));
2214 authorities->Add(new SettingEntry("economy.station_noise_level"));
2215 }
2216
2217 SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
2218 {
2219 towns->Add(new SettingEntry("economy.town_cargo_scale"));
2220 towns->Add(new SettingEntry("economy.town_growth_rate"));
2221 towns->Add(new SettingEntry("economy.allow_town_roads"));
2222 towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
2223 towns->Add(new SettingEntry("economy.found_town"));
2224 towns->Add(new SettingEntry("economy.town_layout"));
2225 towns->Add(new SettingEntry("economy.larger_towns"));
2226 towns->Add(new SettingEntry("economy.initial_city_size"));
2227 towns->Add(new SettingEntry("economy.town_cargogen_mode"));
2228 }
2229
2230 SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
2231 {
2232 industries->Add(new SettingEntry("economy.industry_cargo_scale"));
2233 industries->Add(new SettingEntry("difficulty.industry_density"));
2234 industries->Add(new SettingEntry("construction.raw_industry_construction"));
2235 industries->Add(new SettingEntry("construction.industry_platform"));
2236 industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
2237 industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
2238 industries->Add(new SettingEntry("economy.type"));
2239 industries->Add(new SettingEntry("station.serve_neutral_industries"));
2240 }
2241
2242 SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
2243 {
2244 cdist->Add(new SettingEntry("linkgraph.recalc_time"));
2245 cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
2246 cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
2247 cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
2248 cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
2249 cdist->Add(new SettingEntry("linkgraph.distribution_default"));
2250 cdist->Add(new SettingEntry("linkgraph.accuracy"));
2251 cdist->Add(new SettingEntry("linkgraph.demand_distance"));
2252 cdist->Add(new SettingEntry("linkgraph.demand_size"));
2253 cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
2254 }
2255
2256 SettingsPage *trees = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TREES));
2257 {
2258 trees->Add(new SettingEntry("game_creation.tree_placer"));
2259 trees->Add(new SettingEntry("construction.extra_tree_placement"));
2260 }
2261 }
2262
2263 SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
2264 {
2265 SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
2266 {
2267 npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
2268 npc->Add(new SettingEntry("script.script_max_memory_megabytes"));
2269 npc->Add(new SettingEntry("difficulty.competitor_speed"));
2270 npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
2271 npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
2272 npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
2273 npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
2274 npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
2275 }
2276
2277 ai->Add(new SettingEntry("economy.give_money"));
2278 }
2279
2280 SettingsPage *network = main->Add(new SettingsPage(STR_CONFIG_SETTING_NETWORK));
2281 {
2282 network->Add(new SettingEntry("network.use_relay_service"));
2283 }
2284
2285 main->Init();
2286 }
2287 return *main;
2288}
2289
2290static const StringID _game_settings_restrict_dropdown[] = {
2291 STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
2292 STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
2293 STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
2294 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
2295 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
2296};
2297static_assert(lengthof(_game_settings_restrict_dropdown) == RM_END);
2298
2306
2312static void ResetAllSettingsConfirmationCallback(Window *w, bool confirmed)
2313{
2314 if (confirmed) {
2317 w->InvalidateData();
2318 }
2319}
2320
2324
2330
2336
2337 Scrollbar *vscroll;
2338
2340 {
2341 this->warn_missing = WHR_NONE;
2342 this->warn_lines = 0;
2344 this->filter.min_cat = RM_ALL;
2345 this->filter.type = ST_ALL;
2346 this->filter.type_hides = false;
2347 this->settings_ptr = &GetGameSettings();
2348
2349 GetSettingsTree().FoldAll(); // Close all sub-pages
2350
2351 this->valuewindow_entry = nullptr; // No setting entry for which a entry window is opened
2352 this->clicked_entry = nullptr; // No numeric setting buttons are depressed
2353 this->last_clicked = nullptr;
2354 this->valuedropdown_entry = nullptr;
2355 this->closing_dropdown = false;
2356 this->manually_changed_folding = false;
2357
2358 this->CreateNestedTree();
2359 this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
2361
2363 this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
2365
2366 this->InvalidateData();
2367 }
2368
2369 void OnInit() override
2370 {
2371 _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
2372 }
2373
2375 {
2376 switch (widget) {
2379 resize.width = 1;
2380
2381 size.height = 5 * resize.height + WidgetDimensions::scaled.framerect.Vertical();
2382 break;
2383
2384 case WID_GS_HELP_TEXT: {
2385 static const StringID setting_types[] = {
2389 };
2390 for (const auto &setting_type : setting_types) {
2392 size.width = std::max(size.width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width + padding.width);
2393 }
2395 std::max(size.height, GetSettingsTree().GetMaxHelpHeight(size.width));
2396 break;
2397 }
2398
2402 break;
2403
2404 default:
2405 break;
2406 }
2407 }
2408
2409 void OnPaint() override
2410 {
2411 if (this->closing_dropdown) {
2412 this->closing_dropdown = false;
2413 assert(this->valuedropdown_entry != nullptr);
2414 this->valuedropdown_entry->SetButtons(0);
2415 this->valuedropdown_entry = nullptr;
2416 }
2417
2418 /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
2419 const Rect panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext);
2421 int new_warn_lines;
2422 if (this->warn_missing == WHR_NONE) {
2423 new_warn_lines = 0;
2424 } else {
2425 SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
2427 }
2428 if (this->warn_lines != new_warn_lines) {
2429 this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
2430 this->warn_lines = new_warn_lines;
2431 }
2432
2433 this->DrawWidgets();
2434
2435 /* Draw the 'some search results are hidden' notice. */
2436 if (this->warn_missing != WHR_NONE) {
2437 SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
2438 DrawStringMultiLine(panel.WithHeight(this->warn_lines * GetCharacterHeight(FS_NORMAL)), warn_str, TC_FROMSTRING, SA_CENTER);
2439 }
2440 }
2441
2442 void SetStringParameters(WidgetID widget) const override
2443 {
2444 switch (widget) {
2446 SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
2447 break;
2448
2450 switch (this->filter.type) {
2455 }
2456 break;
2457 }
2458 }
2459
2460 DropDownList BuildDropDownList(WidgetID widget) const
2461 {
2462 DropDownList list;
2463 switch (widget) {
2465 for (int mode = 0; mode != RM_END; mode++) {
2466 /* If we are in adv. settings screen for the new game's settings,
2467 * we don't want to allow comparing with new game's settings. */
2468 bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
2469
2470 list.push_back(MakeDropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled));
2471 }
2472 break;
2473
2475 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL));
2476 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME));
2477 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY));
2478 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT));
2479 break;
2480 }
2481 return list;
2482 }
2483
2484 void DrawWidget(const Rect &r, WidgetID widget) const override
2485 {
2486 switch (widget) {
2487 case WID_GS_OPTIONSPANEL: {
2489 tr.top += this->warn_lines * SETTING_HEIGHT;
2490 uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
2491 int next_row = GetSettingsTree().Draw(settings_ptr, tr.left, tr.right, tr.top,
2492 this->vscroll->GetPosition(), last_row, this->last_clicked);
2494 break;
2495 }
2496
2497 case WID_GS_HELP_TEXT:
2498 if (this->last_clicked != nullptr) {
2499 const IntSettingDesc *sd = this->last_clicked->setting;
2500
2501 Rect tr = r;
2502 switch (sd->GetType()) {
2506 default: NOT_REACHED();
2507 }
2510
2511 int32_t def_val = sd->get_def_cb != nullptr ? sd->get_def_cb() : sd->def;
2512 sd->SetValueDParams(0, def_val);
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 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
2612
2613 /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2614 if (x < SETTING_BUTTON_WIDTH && (sd->flags & SF_GUI_DROPDOWN)) {
2615 this->SetDisplayedHelpText(pe);
2616
2617 if (this->valuedropdown_entry == pe) {
2618 /* unclick the dropdown */
2620 this->closing_dropdown = false;
2621 this->valuedropdown_entry->SetButtons(0);
2622 this->valuedropdown_entry = nullptr;
2623 } else {
2624 if (this->valuedropdown_entry != nullptr) this->valuedropdown_entry->SetButtons(0);
2625 this->closing_dropdown = false;
2626
2628 int rel_y = (pt.y - wid->pos_y - WidgetDimensions::scaled.framerect.top) % wid->resize_y;
2629
2630 Rect wi_rect;
2631 wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2632 wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2633 wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2634 wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2635
2636 /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2637 if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2638 this->valuedropdown_entry = pe;
2639 this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
2640
2641 DropDownList list;
2642 for (int i = sd->min; i <= (int)sd->max; i++) {
2643 sd->SetValueDParams(0, i);
2644 list.push_back(MakeDropDownListStringItem(STR_JUST_STRING2, i));
2645 }
2646
2647 ShowDropDownListAt(this, std::move(list), value, WID_GS_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);
2648 }
2649 }
2650 this->SetDirty();
2651 } else if (x < SETTING_BUTTON_WIDTH) {
2652 this->SetDisplayedHelpText(pe);
2653 int32_t oldvalue = value;
2654
2655 if (sd->IsBoolSetting()) {
2656 value ^= 1;
2657 } else {
2658 /* Add a dynamic step-size to the scroller. In a maximum of
2659 * 50-steps you should be able to get from min to max,
2660 * unless specified otherwise in the 'interval' variable
2661 * of the current setting. */
2662 uint32_t step = (sd->interval == 0) ? ((sd->max - sd->min) / 50) : sd->interval;
2663 if (step == 0) step = 1;
2664
2665 /* don't allow too fast scrolling */
2666 if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) {
2667 _left_button_clicked = false;
2668 return;
2669 }
2670
2671 /* Increase or decrease the value and clamp it to extremes */
2672 if (x >= SETTING_BUTTON_WIDTH / 2) {
2673 value += step;
2674 if (sd->min < 0) {
2675 assert((int32_t)sd->max >= 0);
2676 if (value > (int32_t)sd->max) value = (int32_t)sd->max;
2677 } else {
2678 if ((uint32_t)value > sd->max) value = (int32_t)sd->max;
2679 }
2680 if (value < sd->min) value = sd->min; // skip between "disabled" and minimum
2681 } else {
2682 value -= step;
2683 if (value < sd->min) value = (sd->flags & SF_GUI_0_IS_SPECIAL) ? 0 : sd->min;
2684 }
2685
2686 /* Set up scroller timeout for numeric values */
2687 if (value != oldvalue) {
2688 if (this->clicked_entry != nullptr) { // Release previous buttons if any
2689 this->clicked_entry->SetButtons(0);
2690 }
2691 this->clicked_entry = pe;
2692 this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED);
2693 this->SetTimeout();
2694 _left_button_clicked = false;
2695 }
2696 }
2697
2698 if (value != oldvalue) {
2699 SetSettingValue(sd, value);
2700 this->SetDirty();
2701 }
2702 } else {
2703 /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2704 if (this->last_clicked == pe && !sd->IsBoolSetting() && !(sd->flags & SF_GUI_DROPDOWN)) {
2705 int64_t value64 = value;
2706 /* Show the correct currency-translated value */
2707 if (sd->flags & SF_GUI_CURRENCY) value64 *= GetCurrency().rate;
2708
2709 CharSetFilter charset_filter = CS_NUMERAL; //default, only numeric input allowed
2710 if (sd->min < 0) charset_filter = CS_NUMERAL_SIGNED; // special case, also allow '-' sign for negative input
2711
2712 this->valuewindow_entry = pe;
2713 SetDParam(0, value64);
2714 /* Limit string length to 14 so that MAX_INT32 * max currency rate doesn't exceed MAX_INT64. */
2716 }
2717 this->SetDisplayedHelpText(pe);
2718 }
2719 }
2720
2721 void OnTimeout() override
2722 {
2723 if (this->clicked_entry != nullptr) { // On timeout, release any depressed buttons
2724 this->clicked_entry->SetButtons(0);
2725 this->clicked_entry = nullptr;
2726 this->SetDirty();
2727 }
2728 }
2729
2730 void OnQueryTextFinished(std::optional<std::string> str) override
2731 {
2732 /* The user pressed cancel */
2733 if (!str.has_value()) return;
2734
2735 assert(this->valuewindow_entry != nullptr);
2736 const IntSettingDesc *sd = this->valuewindow_entry->setting;
2737
2738 int32_t value;
2739 if (!str->empty()) {
2740 long long llvalue = atoll(str->c_str());
2741
2742 /* Save the correct currency-translated value */
2743 if (sd->flags & SF_GUI_CURRENCY) llvalue /= GetCurrency().rate;
2744
2745 value = ClampTo<int32_t>(llvalue);
2746 } else if (sd->get_def_cb != nullptr) {
2747 value = sd->get_def_cb();
2748 } else {
2749 value = sd->def;
2750 }
2751
2752 SetSettingValue(this->valuewindow_entry->setting, value);
2753 this->SetDirty();
2754 }
2755
2756 void OnDropdownSelect(WidgetID widget, int index) override
2757 {
2758 switch (widget) {
2760 this->filter.mode = (RestrictionMode)index;
2761 if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2762 this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2763
2764 if (!this->manually_changed_folding) {
2765 /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2766 GetSettingsTree().UpdateFilterState(this->filter, false);
2768 }
2769 } else {
2770 /* Non-'changes' filter. Save as default. */
2772 }
2773 this->InvalidateData();
2774 break;
2775
2777 this->filter.type = (SettingType)index;
2778 this->InvalidateData();
2779 break;
2780
2782 /* Deal with drop down boxes on the panel. */
2783 assert(this->valuedropdown_entry != nullptr);
2784 const IntSettingDesc *sd = this->valuedropdown_entry->setting;
2785 assert(sd->flags & SF_GUI_DROPDOWN);
2786
2787 SetSettingValue(sd, index);
2788 this->SetDirty();
2789 break;
2790 }
2791 }
2792
2793 void OnDropdownClose(Point pt, WidgetID widget, int index, bool instant_close) override
2794 {
2795 if (widget != WID_GS_SETTING_DROPDOWN) {
2796 /* Normally the default implementation of OnDropdownClose() takes care of
2797 * a few things. We want that behaviour here too, but only for
2798 * "normal" dropdown boxes. The special dropdown boxes added for every
2799 * setting that needs one can't have this call. */
2800 Window::OnDropdownClose(pt, widget, index, instant_close);
2801 } else {
2802 /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2803 * the same dropdown button was clicked again, and then not open the dropdown again.
2804 * So, we only remember that it was closed, and process it on the next OnPaint, which is
2805 * after OnClick. */
2806 assert(this->valuedropdown_entry != nullptr);
2807 this->closing_dropdown = true;
2808 this->SetDirty();
2809 }
2810 }
2811
2812 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2813 {
2814 if (!gui_scope) return;
2815
2816 /* Update which settings are to be visible. */
2817 RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2818 this->filter.min_cat = min_level;
2819 this->filter.type_hides = false;
2820 GetSettingsTree().UpdateFilterState(this->filter, false);
2821
2822 if (this->filter.string.IsEmpty()) {
2823 this->warn_missing = WHR_NONE;
2824 } else if (min_level < this->filter.min_cat) {
2825 this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2826 } else {
2827 this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2828 }
2829 this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2830
2831 if (this->last_clicked != nullptr && !GetSettingsTree().IsVisible(this->last_clicked)) {
2832 this->SetDisplayedHelpText(nullptr);
2833 }
2834
2835 bool all_folded = true;
2836 bool all_unfolded = true;
2838 this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2840 }
2841
2843 {
2844 if (wid == WID_GS_FILTER) {
2845 this->filter.string.SetFilterTerm(this->filter_editbox.text.buf);
2846 if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2847 /* User never expanded/collapsed single pages and entered a filter term.
2848 * Expand everything, to save weird expand clicks, */
2850 }
2851 this->InvalidateData();
2852 }
2853 }
2854
2855 void OnResize() override
2856 {
2857 this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, WidgetDimensions::scaled.framerect.Vertical());
2858 }
2859};
2860
2862
2863static constexpr NWidgetPart _nested_settings_selection_widgets[] = {
2865 NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2866 NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2867 NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2868 EndContainer(),
2869 NWidget(WWT_PANEL, COLOUR_MAUVE),
2872 NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_CATEGORY), SetDataTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY, STR_NULL),
2873 NWidget(WWT_DROPDOWN, COLOUR_MAUVE, WID_GS_RESTRICT_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_JUST_STRING, STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
2874 EndContainer(),
2876 NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL),
2877 NWidget(WWT_DROPDOWN, COLOUR_MAUVE, WID_GS_TYPE_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_JUST_STRING, STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
2878 EndContainer(),
2880 NWidget(WWT_TEXT, COLOUR_MAUVE), SetFill(0, 1), SetDataTip(STR_CONFIG_SETTING_FILTER_TITLE, STR_NULL),
2881 NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
2882 EndContainer(),
2883 EndContainer(),
2884 EndContainer(),
2888 EndContainer(),
2889 NWidget(WWT_PANEL, COLOUR_MAUVE),
2890 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2892 EndContainer(),
2894 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
2895 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
2896 NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_RESET_ALL), SetDataTip(STR_CONFIG_SETTING_RESET_ALL, STR_NULL),
2897 NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2898 EndContainer(),
2899 NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2900 EndContainer(),
2901};
2902
2903static WindowDesc _settings_selection_desc(
2904 WDP_CENTER, "settings", 510, 450,
2906 0,
2907 _nested_settings_selection_widgets
2908);
2909
2912{
2914 new GameSettingsWindow(_settings_selection_desc);
2915}
2916
2917
2927void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
2928{
2929 int colour = GetColourGradient(button_colour, SHADE_DARKER);
2930 Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2931
2932 Rect lr = {x, y, x + (int)dim.width - 1, y + (int)dim.height - 1};
2933 Rect rr = {x + (int)dim.width, y, x + (int)dim.width * 2 - 1, y + (int)dim.height - 1};
2934
2935 DrawFrameRect(lr, button_colour, (state == 1) ? FR_LOWERED : FR_NONE);
2936 DrawFrameRect(rr, button_colour, (state == 2) ? FR_LOWERED : FR_NONE);
2937 DrawSpriteIgnorePadding(SPR_ARROW_LEFT, PAL_NONE, lr, SA_CENTER);
2938 DrawSpriteIgnorePadding(SPR_ARROW_RIGHT, PAL_NONE, rr, SA_CENTER);
2939
2940 /* Grey out the buttons that aren't clickable */
2941 bool rtl = _current_text_dir == TD_RTL;
2942 if (rtl ? !clickable_right : !clickable_left) {
2944 }
2945 if (rtl ? !clickable_left : !clickable_right) {
2947 }
2948}
2949
2958void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2959{
2960 int colour = GetColourGradient(button_colour, SHADE_DARKER);
2961
2962 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
2963
2964 DrawFrameRect(r, button_colour, state ? FR_LOWERED : FR_NONE);
2965 DrawSpriteIgnorePadding(SPR_ARROW_DOWN, PAL_NONE, r, SA_CENTER);
2966
2967 if (!clickable) {
2969 }
2970}
2971
2979void DrawBoolButton(int x, int y, bool state, bool clickable)
2980{
2981 static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2982
2983 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
2984 DrawFrameRect(r, _bool_ctabs[state][clickable], state ? FR_LOWERED : FR_NONE);
2985}
2986
2988 int query_widget;
2989
2991 {
2992 this->InitNested();
2993
2994 SetButtonState();
2995 }
2996
2997 void SetButtonState()
2998 {
3003 }
3004
3005 void SetStringParameters(WidgetID widget) const override
3006 {
3007 switch (widget) {
3008 case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
3009 case WID_CC_SEPARATOR: SetDParamStr(0, GetCustomCurrency().separator); break;
3010 case WID_CC_PREFIX: SetDParamStr(0, GetCustomCurrency().prefix); break;
3011 case WID_CC_SUFFIX: SetDParamStr(0, GetCustomCurrency().suffix); break;
3012 case WID_CC_YEAR:
3014 SetDParam(1, GetCustomCurrency().to_euro);
3015 break;
3016
3017 case WID_CC_PREVIEW:
3018 SetDParam(0, 10000);
3019 break;
3020 }
3021 }
3022
3024 {
3025 switch (widget) {
3026 /* Set the appropriate width for the up/down buttons. */
3027 case WID_CC_RATE_DOWN:
3028 case WID_CC_RATE_UP:
3029 case WID_CC_YEAR_DOWN:
3030 case WID_CC_YEAR_UP:
3031 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH / 2, (uint)SETTING_BUTTON_HEIGHT});
3032 break;
3033
3034 /* Set the appropriate width for the edit buttons. */
3036 case WID_CC_PREFIX_EDIT:
3037 case WID_CC_SUFFIX_EDIT:
3038 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH, (uint)SETTING_BUTTON_HEIGHT});
3039 break;
3040
3041 /* Make sure the window is wide enough for the widest exchange rate */
3042 case WID_CC_RATE:
3043 SetDParam(0, 1);
3044 SetDParam(1, INT32_MAX);
3046 break;
3047 }
3048 }
3049
3050 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
3051 {
3052 int line = 0;
3053 int len = 0;
3054 StringID str = 0;
3056
3057 switch (widget) {
3058 case WID_CC_RATE_DOWN:
3059 if (GetCustomCurrency().rate > 1) GetCustomCurrency().rate--;
3060 if (GetCustomCurrency().rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
3062 break;
3063
3064 case WID_CC_RATE_UP:
3068 break;
3069
3070 case WID_CC_RATE:
3071 SetDParam(0, GetCustomCurrency().rate);
3072 str = STR_JUST_INT;
3073 len = 5;
3074 line = WID_CC_RATE;
3075 afilter = CS_NUMERAL;
3076 break;
3077
3079 case WID_CC_SEPARATOR:
3080 SetDParamStr(0, GetCustomCurrency().separator);
3081 str = STR_JUST_RAW_STRING;
3082 len = 7;
3083 line = WID_CC_SEPARATOR;
3084 break;
3085
3086 case WID_CC_PREFIX_EDIT:
3087 case WID_CC_PREFIX:
3088 SetDParamStr(0, GetCustomCurrency().prefix);
3089 str = STR_JUST_RAW_STRING;
3090 len = 15;
3091 line = WID_CC_PREFIX;
3092 break;
3093
3094 case WID_CC_SUFFIX_EDIT:
3095 case WID_CC_SUFFIX:
3096 SetDParamStr(0, GetCustomCurrency().suffix);
3097 str = STR_JUST_RAW_STRING;
3098 len = 15;
3099 line = WID_CC_SUFFIX;
3100 break;
3101
3102 case WID_CC_YEAR_DOWN:
3106 break;
3107
3108 case WID_CC_YEAR_UP:
3112 break;
3113
3114 case WID_CC_YEAR:
3115 SetDParam(0, GetCustomCurrency().to_euro);
3116 str = STR_JUST_INT;
3117 len = 7;
3118 line = WID_CC_YEAR;
3119 afilter = CS_NUMERAL;
3120 break;
3121 }
3122
3123 if (len != 0) {
3124 this->query_widget = line;
3125 ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
3126 }
3127
3128 this->SetTimeout();
3129 this->SetDirty();
3130 }
3131
3132 void OnQueryTextFinished(std::optional<std::string> str) override
3133 {
3134 if (!str.has_value()) return;
3135
3136 switch (this->query_widget) {
3137 case WID_CC_RATE:
3138 GetCustomCurrency().rate = Clamp(atoi(str->c_str()), 1, UINT16_MAX);
3139 break;
3140
3141 case WID_CC_SEPARATOR: // Thousands separator
3142 GetCustomCurrency().separator = std::move(*str);
3143 break;
3144
3145 case WID_CC_PREFIX:
3146 GetCustomCurrency().prefix = std::move(*str);
3147 break;
3148
3149 case WID_CC_SUFFIX:
3150 GetCustomCurrency().suffix = std::move(*str);
3151 break;
3152
3153 case WID_CC_YEAR: { // Year to switch to euro
3154 TimerGameCalendar::Year val = atoi(str->c_str());
3155
3157 break;
3158 }
3159 }
3161 SetButtonState();
3162 }
3163
3164 void OnTimeout() override
3165 {
3166 this->SetDirty();
3167 }
3168};
3169
3170static constexpr NWidgetPart _nested_cust_currency_widgets[] = {
3172 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
3173 NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
3174 EndContainer(),
3175 NWidget(WWT_PANEL, COLOUR_GREY),
3180 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
3181 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
3182 EndContainer(),
3183 NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_RATE), SetDataTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
3184 EndContainer(),
3186 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
3187 NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SEPARATOR), SetDataTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
3188 EndContainer(),
3190 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
3191 NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_PREFIX), SetDataTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
3192 EndContainer(),
3194 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
3195 NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SUFFIX), SetDataTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
3196 EndContainer(),
3199 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
3200 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
3201 EndContainer(),
3202 NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_YEAR), SetDataTip(STR_JUST_STRING1, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
3203 EndContainer(),
3204 EndContainer(),
3205 NWidget(WWT_LABEL, COLOUR_BLUE, WID_CC_PREVIEW),
3206 SetDataTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP),
3207 EndContainer(),
3208 EndContainer(),
3209};
3210
3211static WindowDesc _cust_currency_desc(
3212 WDP_CENTER, nullptr, 0, 0,
3214 0,
3215 _nested_cust_currency_widgets
3216);
3217
3219static void ShowCustCurrency()
3220{
3222 new CustomCurrencyWindow(_cust_currency_desc);
3223}
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().
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:1198
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:1430
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:1656
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:2377
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:2451
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.
@ 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.
std::string social_platform
Social platform this plugin is for.
std::string name
Name of the plugin.
std::string version
Version of the plugin.
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:42
RectPadding frametext
Padding inside frame with text.
Definition window_gui.h:43
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:60
int hsep_wide
Wide horizontal spacing.
Definition window_gui.h:64
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:96
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:63
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:40
int hsep_indent
Width of identation for tree layouts.
Definition window_gui.h:65
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:77
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
CurrencySpec & GetCustomCurrency()
Get the custom currency.
Definition currency.h:108
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:117
@ CURRENCY_CUSTOM
Custom currency.
Definition currency.h:58
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_POSTFIX_INCREMENT(enum_type)
Some enums need to have allowed incrementing (i.e.
Definition enum_type.hpp:18
Functions related to errors.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
@ 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
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:313
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:345
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:353
@ FS_SMALL
Index of the small font in the font tables.
Definition gfx_type.h:210
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:209
@ FILLRECT_CHECKER
Draw only every second pixel, used for greying-out.
Definition gfx_type.h:299
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 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 SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
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:3297
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
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 SetAspect(float ratio, AspectFlags flags=AspectFlags::ResizeX)
Widget part function for setting the aspect ratio.
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:940
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:1937
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.
Functions to find and configure NewGRFs.
void ChangeAutosaveFrequency(bool reset)
Reset the interval of the autosave.
Definition openttd.cpp:1318
@ 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:314
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
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.
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.
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...
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.
std::unique_ptr< NWidgetBase > MakeNWidgetSocialPlugins()
Construct nested container widget for managing the list of social plugins.
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 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.
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.
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.
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.
@ SF_GUI_DROPDOWN
The value represents a limited number of string-options (internally integer) presented as dropdown.
@ SF_PER_COMPANY
This setting can be different for each company (saved in company struct).
@ SF_GUI_CURRENCY
The number represents money, so when reading value multiply by exchange rate.
@ SF_GUI_0_IS_SPECIAL
A value of zero is possible and has a custom string (the one after "strval").
@ 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:280
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:2183
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:2291
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:371
Functions related to OTTD's strings.
@ TD_RTL
Text is written right-to-left by default.
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)
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:75
std::string separator
The thousands separator for this currency.
Definition currency.h:77
std::string prefix
Prefix to apply when formatting money in this currency.
Definition currency.h:79
TimerGameCalendar::Year to_euro
Year of switching to the Euro. May also be CF_NOEURO or CF_ISEURO.
Definition currency.h:78
std::string suffix
Suffix to apply when formatting money in this currency.
Definition currency.h:80
std::string code
3 letter untranslated code to identify the currency.
Definition currency.h:81
uint16_t rate
The conversion rate compared to the base currency.
Definition currency.h:76
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
int32_t def
default value given when none is present
SettingCategory cat
assigned categories of the setting
StringID GetTitle() const
Get the title of the setting.
Definition settings.cpp:441
uint32_t max
maximum values
int32_t min
minimum values
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:561
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:883
SettingType GetType() const
Return the type of the setting.
Definition settings.cpp:900
const struct IntSettingDesc * AsIntSetting() const
Get the setting description of this setting as an integer setting.
Definition settings.cpp:910
SettingFlag flags
Handles how a setting would show up in the GUI (text/currency, etc.).
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.
char *const buf
buffer in which text is saved
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:159
Data structure for an opened window.
Definition window_gui.h:273
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:952
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1047
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1733
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:320
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:732
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3159
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:551
uint8_t timeout_timer
Timer value of the WF_TIMEOUT for flags.
Definition window_gui.h:306
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:326
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1035
ResizeInfo resize
Resize information.
Definition window_gui.h:314
void DisableWidget(WidgetID widget_index)
Sets a widget to disabled.
Definition window_gui.h:397
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:521
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1723
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:486
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:287
void SetWidgetsLoweredState(bool lowered_stat, Args... widgets)
Sets the lowered/raised status of a list of widgets.
Definition window_gui.h:532
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:447
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:406
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition window_gui.h:361
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:977
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:466
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1746
WindowFlags flags
Window flags.
Definition window_gui.h:300
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:314
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:387
int height
Height of the window (number of pixels down in y direction)
Definition window_gui.h:312
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:311
@ 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
@ 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:31
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition widget_type.h:32
@ NC_EQUALSIZE
Value of the NCB_EQUALSIZE flag.
@ 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:57
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:71
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:75
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:55
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:50
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:61
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:85
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:77
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:69
@ WWT_FRAME
Frame.
Definition widget_type.h:60
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:48
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:68
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:65
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:70
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:58
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:80
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:1140
void ReInitAllWindows(bool zoom_changed)
Re-initialize all windows.
Definition window.cpp:3335
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1152
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition window.cpp:3127
Window functions not directly related to making/drawing windows.
@ WF_TIMEOUT
Window timeout counter.
Definition window_gui.h:228
@ WF_CENTERED
Window is centered and shall stay centered after ReInit.
Definition window_gui.h:238
@ FR_LOWERED
If set the frame is lowered and the background colour brighter (ie. buttons when pressed)
Definition window_gui.h:28
@ WDP_CENTER
Center the window.
Definition window_gui.h:148
int WidgetID
Widget ID.
Definition window_type.h:18
@ WN_GAME_OPTIONS_GAME_OPTIONS
Game options.
Definition window_type.h:26
@ WN_GAME_OPTIONS_GAME_SETTINGS
Game settings.
Definition window_type.h:27
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:45
@ 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.