OpenTTD Source 20260801-master-g0de95fb529
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11#include "currency_func.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"
25#include "slider_func.h"
26#include "highscore.h"
27#include "base_media_base.h"
28#include "base_media_graphics.h"
29#include "base_media_music.h"
30#include "base_media_sounds.h"
31#include "company_base.h"
32#include "company_func.h"
33#include "viewport_func.h"
35#include "ai/ai.hpp"
36#include "blitter/factory.hpp"
37#include "language.h"
38#include "textfile_gui.h"
39#include "stringfilter_type.h"
40#include "querystring_gui.h"
41#include "fontcache.h"
42#include "zoom_func.h"
43#include "rev.h"
46#include "gui.h"
47#include "mixer.h"
48#include "newgrf_config.h"
49#include "network/core/config.h"
50#include "network/network_gui.h"
53#include "social_integration.h"
54#include "sound_func.h"
55#include "settingentry_gui.h"
57
59#include "widgets/misc_widget.h"
60
61#include "table/strings.h"
62
64
65#include "safeguards.h"
66
67
68#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
69# define HAS_TRUETYPE_FONT
70#endif
71
72static const StringID _autosave_dropdown[] = {
73 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF,
74 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_10_MINUTES,
75 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_30_MINUTES,
76 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_60_MINUTES,
77 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_120_MINUTES,
79};
80
82static const uint32_t _autosave_dropdown_to_minutes[] = {
83 0,
84 10,
85 30,
86 60,
87 120,
88};
89
95{
96 auto it = std::ranges::find(_resolutions, Dimension(_screen.width, _screen.height));
97 return std::distance(_resolutions.begin(), it);
98}
99
100static void ShowCustCurrency();
101
103struct BaseSetTextfileWindow : public TextfileWindow {
104 const std::string name;
106
107 BaseSetTextfileWindow(Window *parent, TextfileType file_type, const std::string &name, const std::string &textfile, StringID content_type) : TextfileWindow(parent, file_type), name(name), content_type(content_type)
108 {
109 this->ConstructWindow();
110 this->LoadTextfile(textfile, Subdirectory::Baseset);
111 }
112
113 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
114 {
115 if (widget == WID_TF_CAPTION) {
116 return GetString(stringid, this->content_type, this->name);
117 }
118
119 return this->Window::GetWidgetString(widget, stringid);
120 }
121};
122
130template <class TBaseSet>
131void ShowBaseSetTextfileWindow(Window *parent, TextfileType file_type, const TBaseSet *baseset, StringID content_type)
132{
133 parent->CloseChildWindowById(WindowClass::Textfile, file_type);
134 new BaseSetTextfileWindow(parent, file_type, baseset->name, *baseset->GetTextfile(file_type), content_type);
135}
136
144template <typename TBaseSet>
145static std::string GetListLabel(const TBaseSet *baseset)
146{
147 if (baseset->GetNumInvalid() == 0) return GetString(STR_JUST_RAW_STRING, baseset->name);
148 return GetString(STR_BASESET_STATUS, baseset->name, baseset->GetNumInvalid());
149}
150
151template <class T>
152DropDownList BuildSetDropDownList(int *selected_index)
153{
154 int n = T::GetNumSets();
155 *selected_index = T::GetIndexOfUsedSet();
156 DropDownList list;
157 for (int i = 0; i < n; i++) {
158 list.push_back(MakeDropDownListStringItem(GetListLabel(T::GetSet(i)), i));
159 }
160 return list;
161}
162
163std::set<int> _refresh_rates = { 30, 60, 75, 90, 100, 120, 144, 240 };
164
170{
171 /* Add the refresh rate as selected in the config. */
172 _refresh_rates.insert(_settings_client.gui.refresh_rate);
173
174 /* Add all the refresh rates of all monitors connected to the machine. */
175 std::vector<int> monitor_rates = VideoDriver::GetInstance()->GetListOfMonitorRefreshRates();
176 std::copy(monitor_rates.begin(), monitor_rates.end(), std::inserter(_refresh_rates, _refresh_rates.end()));
177}
178
179static const int SCALE_NMARKS = (MAX_INTERFACE_SCALE - MIN_INTERFACE_SCALE) / 25 + 1;
180static const int VOLUME_NMARKS = 9;
181
182static std::optional<std::string> ScaleMarkFunc(int, int, int value)
183{
184 /* Label only every 100% mark. */
185 if (value % 100 != 0) return std::string{};
186
187 return GetString(STR_GAME_OPTIONS_GUI_SCALE_MARK, value / 100, 0);
188}
189
190static std::optional<std::string> VolumeMarkFunc(int, int mark, int value)
191{
192 /* Label only every other mark. */
193 if (mark % 2 != 0) return std::string{};
194
195 /* 0-127 does not map nicely to 0-100. Dividing first gives us nice round numbers. */
196 return GetString(STR_GAME_OPTIONS_VOLUME_MARK, value / 31 * 25);
197}
198
209
210static constexpr std::initializer_list<NWidgetPart> _nested_social_plugins_widgets = {
214 NWidget(WWT_TEXT, Colours::Invalid), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM), SetTextStyle(GAME_OPTIONS_LABEL),
216 EndContainer(),
218 NWidget(WWT_TEXT, Colours::Invalid), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE), SetTextStyle(GAME_OPTIONS_LABEL),
220 EndContainer(),
221 EndContainer(),
222 EndContainer(),
223};
224
225static constexpr std::initializer_list<NWidgetPart> _nested_social_plugins_none_widgets = {
227 NWidget(WWT_TEXT, Colours::Invalid), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE), SetTextStyle(GAME_OPTIONS_LABEL),
228 EndContainer(),
229};
230
231class NWidgetSocialPlugins : public NWidgetVertical {
232public:
233 NWidgetSocialPlugins() : NWidgetVertical({}, WID_GO_SOCIAL_PLUGINS)
234 {
235 this->plugins = SocialIntegration::GetPlugins();
236
237 if (this->plugins.empty()) {
238 auto widget = MakeNWidgets(_nested_social_plugins_none_widgets, nullptr);
239 this->Add(std::move(widget));
240 } else {
241 for (size_t i = 0; i < this->plugins.size(); i++) {
242 auto widget = MakeNWidgets(_nested_social_plugins_widgets, nullptr);
243 this->Add(std::move(widget));
244 }
245 }
246
247 this->SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0);
248 }
249
250 void SetupSmallestSize(Window *w) override
251 {
252 this->current_index = -1;
254 }
255
262 template <typename T>
263 std::string &GetWidestPlugin(T SocialIntegrationPlugin::*member) const
264 {
265 std::string *longest = &(this->plugins[0]->*member);
266 int longest_length = 0;
267
268 for (auto *plugin : this->plugins) {
269 int length = GetStringBoundingBox(plugin->*member).width;
270 if (length > longest_length) {
271 longest_length = length;
272 longest = &(plugin->*member);
273 }
274 }
275
276 return *longest;
277 }
278
279 std::string GetWidgetString(WidgetID widget, StringID) const
280 {
281 switch (widget) {
283 /* For SetupSmallestSize, use the longest string we have. */
284 if (this->current_index < 0) {
286 }
287
288 if (this->plugins[this->current_index]->name.empty()) {
289 return this->plugins[this->current_index]->basepath;
290 }
291
292 return GetString(STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE, this->plugins[this->current_index]->name, this->plugins[this->current_index]->version);
293
295 /* For SetupSmallestSize, use the longest string we have. */
296 if (this->current_index < 0) {
298 }
299
300 return this->plugins[this->current_index]->social_platform;
301
303 static const std::pair<SocialIntegrationPlugin::State, StringID> state_to_string[] = {
304 { SocialIntegrationPlugin::RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_RUNNING },
305 { SocialIntegrationPlugin::FAILED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED },
306 { SocialIntegrationPlugin::PLATFORM_NOT_RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_PLATFORM_NOT_RUNNING },
307 { SocialIntegrationPlugin::UNLOADED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNLOADED },
308 { SocialIntegrationPlugin::DUPLICATE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_DUPLICATE },
309 { SocialIntegrationPlugin::UNSUPPORTED_API, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNSUPPORTED_API },
310 { SocialIntegrationPlugin::INVALID_SIGNATURE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_INVALID_SIGNATURE },
311 };
312
313 /* For SetupSmallestSize, use the longest string we have. */
314 if (this->current_index < 0) {
316
317 /* Set the longest plugin when looking for the longest status. */
318 StringID longest = STR_NULL;
319 int longest_length = 0;
320 for (const auto &[state, string] : state_to_string) {
321 int length = GetStringBoundingBox(GetString(string, longest_plugin)).width;
322 if (length > longest_length) {
323 longest_length = length;
324 longest = string;
325 }
326 }
327
328 return GetString(longest, longest_plugin);
329 }
330
331 const auto plugin = this->plugins[this->current_index];
332
333 /* Find the string for the state. */
334 for (const auto &[state, string] : state_to_string) {
335 if (plugin->state == state) {
336 return GetString(string, plugin->social_platform);
337 }
338 }
339
340 /* Default string, in case no state matches. */
341 return GetString(STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED, plugin->social_platform);
342 }
343
344 default: NOT_REACHED();
345 }
346 }
347
348 void Draw(const Window *w) override
349 {
350 this->current_index = 0;
351
352 for (auto &wid : this->children) {
353 wid->Draw(w);
354 this->current_index++;
355 }
356 }
357
358private:
359 int current_index = -1;
360 std::vector<SocialIntegrationPlugin *> plugins{};
361};
362
364std::unique_ptr<NWidgetBase> MakeNWidgetSocialPlugins()
365{
366 return std::make_unique<NWidgetSocialPlugins>();
367}
368
369static const StringID _game_settings_restrict_dropdown[] = {
370 STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
371 STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
372 STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
373 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
374 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
375};
376static_assert(lengthof(_game_settings_restrict_dropdown) == RM_END);
377
385
391static void ResetAllSettingsConfirmationCallback(Window *w, bool confirmed)
392{
393 if (confirmed) {
396 w->InvalidateData();
397 }
398}
399
400struct GameOptionsWindow : Window {
401 static inline GameSettings *settings_ptr;
402
407 bool closing_dropdown = false;
408
413 int warn_lines = 0;
414
415 Scrollbar *vscroll;
416 Scrollbar *vscroll_description;
417 static constexpr uint NUM_DESCRIPTION_LINES = 5;
418
419 GameSettings *opt = nullptr;
420 bool reload = false;
421 bool gui_scale_changed = false;
422 int gui_scale = 0;
423 static inline int previous_gui_scale = 0;
424 static inline WidgetID active_tab = WID_GO_TAB_GENERAL;
425
426 GameOptionsWindow(WindowDesc &desc) : Window(desc), filter_editbox(50)
427 {
428 this->opt = &GetGameSettings();
429
431
432 this->filter.mode = (RestrictionMode)_settings_client.gui.settings_restriction_mode;
433 this->filter.min_cat = RM_ALL;
434 this->filter.type = ST_ALL;
435 this->filter.type_hides = false;
436 this->settings_ptr = &GetGameSettings();
437
438 GetSettingsTree().FoldAll(); // Close all sub-pages
439
440 this->CreateNestedTree();
441 this->vscroll = this->GetScrollbar(WID_GO_SCROLLBAR);
442 this->vscroll_description = this->GetScrollbar(WID_GO_HELP_TEXT_SCROLL);
443 this->vscroll_description->SetCapacity(NUM_DESCRIPTION_LINES);
445
446 this->querystrings[WID_GO_FILTER] = &this->filter_editbox;
447 this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
448
449 this->OnInvalidateData(0);
450
451 this->SetTab(GameOptionsWindow::active_tab);
452
454 }
455
463
464 void Close([[maybe_unused]] int data = 0) override
465 {
466 CloseWindowById(WindowClass::CustomCurrenty, 0);
467 if (this->reload) _switch_mode = SwitchMode::Menu;
468 this->Window::Close();
469 }
470
477 DropDownList BuildDropDownList(WidgetID widget, int *selected_index) const
478 {
479 DropDownList list;
480 switch (widget) {
481 case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
482 *selected_index = to_underlying(this->opt->locale.currency);
483 Currencies disabled = _game_mode == GameMode::Menu ? Currencies{} : GetMaskOfAllowedCurrencies().Flip();
484
485 /* Add non-custom currencies; sorted naturally */
486 for (Currency i : EnumRange(Currency::End)) {
487 if (i == Currency::Custom) continue;
488 CurrencySpec &currency = _currency_specs[i];
489 if (currency.code.empty()) {
490 list.push_back(MakeDropDownListStringItem(currency.name, i, disabled.Test(i)));
491 } else {
492 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_CURRENCY_CODE, currency.name, currency.code), i, disabled.Test(i)));
493 }
494 }
495 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
496
497 /* Append custom currency at the end */
498 list.push_back(MakeDropDownListDividerItem()); // separator line
499 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, Currency::Custom, disabled.Test(Currency::Custom)));
500 break;
501 }
502
503 case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
504 int index = 0;
505 for (auto &minutes : _autosave_dropdown_to_minutes) {
506 index++;
507 if (_settings_client.gui.autosave_interval <= minutes) break;
508 }
509 *selected_index = index - 1;
510
511 const StringID *items = _autosave_dropdown;
512 for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
513 list.push_back(MakeDropDownListStringItem(*items, i));
514 }
515 break;
516 }
517
518 case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
519 for (uint i = 0; i < _languages.size(); i++) {
520 bool hide_language = IsReleasedVersion() && !_languages[i].IsReasonablyFinished();
521 if (hide_language) continue;
522 bool hide_percentage = IsReleasedVersion() || _languages[i].missing < _settings_client.gui.missing_strings_threshold;
523 std::string name;
524 if (&_languages[i] == _current_language) {
525 *selected_index = i;
526 name = _languages[i].own_name;
527 } else {
528 /* Especially with sprite-fonts, not all localized
529 * names can be rendered. So instead, we use the
530 * international names for anything but the current
531 * selected language. This avoids showing a few ????
532 * entries in the dropdown list. */
533 name = _languages[i].name;
534 }
535 if (hide_percentage) {
536 list.push_back(MakeDropDownListStringItem(std::move(name), i));
537 } else {
538 int percentage = (LANGUAGE_TOTAL_STRINGS - _languages[i].missing) * 100 / LANGUAGE_TOTAL_STRINGS;
539 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE, std::move(name), percentage), i));
540 }
541 }
542 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
543 break;
544 }
545
546 case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
547 if (_resolutions.empty()) break;
548
549 *selected_index = GetCurrentResolutionIndex();
550 for (uint i = 0; i < _resolutions.size(); i++) {
551 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_RESOLUTION_ITEM, _resolutions[i].width, _resolutions[i].height), i));
552 }
553 break;
554
555 case WID_GO_REFRESH_RATE_DROPDOWN: // Setup refresh rate dropdown
556 for (auto it = _refresh_rates.begin(); it != _refresh_rates.end(); it++) {
557 auto i = std::distance(_refresh_rates.begin(), it);
558 if (*it == _settings_client.gui.refresh_rate) *selected_index = i;
559 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, *it), i));
560 }
561 break;
562
564 list = BuildSetDropDownList<BaseGraphics>(selected_index);
565 break;
566
568 list = BuildSetDropDownList<BaseSounds>(selected_index);
569 break;
570
572 list = BuildSetDropDownList<BaseMusic>(selected_index);
573 break;
574
576 for (RestrictionMode mode : EnumRange(RM_END)) {
577 /* If we are in adv. settings screen for the new game's settings,
578 * we don't want to allow comparing with new game's settings. */
579 bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
580
581 list.push_back(MakeDropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled));
582 }
583 break;
584
586 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL));
587 list.push_back(MakeDropDownListStringItem(_game_mode == GameMode::Menu ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME));
588 list.push_back(MakeDropDownListStringItem(_game_mode == GameMode::Menu ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY));
589 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT));
590 break;
591 }
592
593 return list;
594 }
595
596 std::string GetToggleString(StringID stringid, WidgetID state_widget) const
597 {
598 return GetString(STR_GAME_OPTIONS_SETTING, stringid, this->IsWidgetLowered(state_widget) ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
599 }
600
601 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
602 {
603 switch (widget) {
605 const CurrencySpec &currency = _currency_specs[this->opt->locale.currency];
606 if (currency.code.empty()) return GetString(currency.name);
607 return GetString(STR_GAME_OPTIONS_CURRENCY_CODE, currency.name, currency.code);
608 }
609
611 int index = 0;
612 for (auto &minutes : _autosave_dropdown_to_minutes) {
613 index++;
614 if (_settings_client.gui.autosave_interval <= minutes) break;
615 }
616 return GetString(_autosave_dropdown[index - 1]);
617 }
618
619 case WID_GO_LANG_DROPDOWN: return _current_language->own_name;
623 case WID_GO_REFRESH_RATE_DROPDOWN: return GetString(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, _settings_client.gui.refresh_rate);
625 auto current_resolution = GetCurrentResolutionIndex();
626
627 if (current_resolution == _resolutions.size()) {
628 return GetString(STR_GAME_OPTIONS_RESOLUTION_OTHER);
629 }
630 return GetString(STR_GAME_OPTIONS_RESOLUTION_ITEM, _resolutions[current_resolution].width, _resolutions[current_resolution].height);
631 }
632
637 assert(plugin != nullptr);
638
639 return plugin->GetWidgetString(widget, stringid);
640 }
641
643 return GetString(_game_settings_restrict_dropdown[this->filter.mode]);
644
646 switch (this->filter.type) {
647 case ST_GAME: return GetString(_game_mode == GameMode::Menu ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME);
648 case ST_COMPANY: return GetString(_game_mode == GameMode::Menu ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME);
649 case ST_CLIENT: return GetString(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT);
650 default: return GetString(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL);
651 }
652 break;
653
655 return GetToggleString(STR_GAME_OPTIONS_PARTICIPATE_SURVEY, WID_GO_SURVEY_PARTICIPATE_BUTTON);
656
658 return GetToggleString(STR_GAME_OPTIONS_GUI_SCALE_AUTO, WID_GO_GUI_SCALE_AUTO);
659
661 return GetToggleString(STR_GAME_OPTIONS_GUI_SCALE_BEVELS, WID_GO_GUI_SCALE_BEVEL_BUTTON);
662
664 return GetToggleString(STR_GAME_OPTIONS_GUI_FONT_SPRITE, WID_GO_GUI_FONT_SPRITE);
665
667 return GetToggleString(STR_GAME_OPTIONS_GUI_FONT_AA, WID_GO_GUI_FONT_AA);
668
670 return GetToggleString(STR_GAME_OPTIONS_FULLSCREEN, WID_GO_FULLSCREEN_BUTTON);
671
673 return GetToggleString(STR_GAME_OPTIONS_VIDEO_ACCELERATION, WID_GO_VIDEO_ACCEL_BUTTON);
674
676 return GetToggleString(STR_GAME_OPTIONS_VIDEO_VSYNC, WID_GO_VIDEO_VSYNC_BUTTON);
677
678 default:
679 return this->Window::GetWidgetString(widget, stringid);
680 }
681 }
682
683 void DrawWidget(const Rect &r, WidgetID widget) const override
684 {
685 switch (widget) {
688 break;
689
692 break;
693
696 break;
697
698 case WID_GO_GUI_SCALE:
699 DrawSliderWidget(r, GAME_OPTIONS_BACKGROUND, GAME_OPTIONS_BUTTON, TextColour::Black, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, SCALE_NMARKS, this->gui_scale, ScaleMarkFunc);
700 break;
701
703 DrawStringMultiLine(r, GetString(STR_GAME_OPTIONS_VIDEO_DRIVER_INFO, std::string{VideoDriver::GetInstance()->GetInfoString()}), GAME_OPTIONS_SELECTED);
704 break;
705
708 break;
709
712 break;
713
714 case WID_GO_OPTIONSPANEL: {
716 tr.top += this->warn_lines * BaseSettingEntry::line_height;
717 uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
718 int next_row = GetSettingsTree().Draw(settings_ptr, tr.left, tr.right, tr.top,
719 this->vscroll->GetPosition(), last_row, this->last_clicked);
720 if (next_row == 0) DrawString(tr, STR_CONFIG_SETTINGS_NONE);
721 break;
722 }
723
725 if (this->last_clicked != nullptr) {
726 const IntSettingDesc *sd = this->last_clicked->setting;
727
728 Rect tr = r;
729 std::string str;
730 switch (sd->GetType()) {
731 case ST_COMPANY: str = GetString(STR_CONFIG_SETTING_TYPE, _game_mode == GameMode::Menu ? STR_CONFIG_SETTING_TYPE_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_COMPANY_INGAME); break;
732 case ST_CLIENT: str = GetString(STR_CONFIG_SETTING_TYPE, STR_CONFIG_SETTING_TYPE_CLIENT); break;
733 case ST_GAME: str = GetString(STR_CONFIG_SETTING_TYPE, _game_mode == GameMode::Menu ? STR_CONFIG_SETTING_TYPE_GAME_MENU : STR_CONFIG_SETTING_TYPE_GAME_INGAME); break;
734 default: NOT_REACHED();
735 }
736 DrawString(tr, str);
738
739 auto [param1, param2] = sd->GetValueParams(sd->GetDefaultValue());
740 DrawString(tr, GetString(STR_CONFIG_SETTING_DEFAULT_VALUE, param1, param2));
741 }
742 break;
743
744 case WID_GO_HELP_TEXT:
745 if (this->last_clicked != nullptr) {
746 const IntSettingDesc *sd = this->last_clicked->setting;
747
748 DrawPixelInfo tmp_dpi;
749 if (FillDrawPixelInfo(&tmp_dpi, r)) {
750 AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
751 int scrolls_pos = this->vscroll_description->GetPosition() * GetCharacterHeight(FontSize::Normal);
752 DrawStringMultiLine(0, r.Width() - 1, -scrolls_pos, r.Height() - 1, sd->GetHelp(), TextColour::White);
753 }
754 }
755 break;
756
757 default:
758 break;
759 }
760 }
761
767 {
768 if (this->last_clicked != pe) this->SetDirty();
769 this->last_clicked = pe;
770 UpdateHelpTextSize();
771 }
772
773 void UpdateHelpTextSize()
774 {
776 this->vscroll_description->SetCount(this->last_clicked ? CeilDiv(this->last_clicked->GetMaxHelpHeight(wid->current_x), GetCharacterHeight(FontSize::Normal)) : 0);
777 }
778
779 void SetTab(WidgetID widget)
780 {
782 this->LowerWidget(widget);
783 GameOptionsWindow::active_tab = widget;
784
785 int plane;
786 switch (widget) {
787 case WID_GO_TAB_GENERAL: plane = 0; break;
788 case WID_GO_TAB_GRAPHICS: plane = 1; break;
789 case WID_GO_TAB_SOUND: plane = 2; break;
790 case WID_GO_TAB_SOCIAL: plane = 3; break;
791 case WID_GO_TAB_ADVANCED: plane = 4; break;
792 default: NOT_REACHED();
793 }
794
795 this->GetWidget<NWidgetStacked>(WID_GO_TAB_SELECTION)->SetDisplayedPlane(plane);
797 this->SetDirty();
798 }
799
800 void OnResize() override
801 {
802 this->vscroll->SetCapacityFromWidget(this, WID_GO_OPTIONSPANEL, WidgetDimensions::scaled.framerect.Vertical());
803 UpdateHelpTextSize();
804
805 bool changed = false;
806
808 int y = 0;
809 for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
810 std::string str = GetString(STR_JUST_RAW_STRING, BaseGraphics::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
811 y = std::max(y, GetStringHeight(str, wid->current_x));
812 }
813 changed |= wid->UpdateVerticalSize(y);
814
816 y = 0;
817 for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
818 std::string str = GetString(STR_JUST_RAW_STRING, BaseSounds::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
819 y = std::max(y, GetStringHeight(str, wid->current_x));
820 }
821 changed |= wid->UpdateVerticalSize(y);
822
824 y = 0;
825 for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
826 std::string str = GetString(STR_JUST_RAW_STRING, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
827 y = std::max(y, GetStringHeight(str, wid->current_x));
828 }
829 changed |= wid->UpdateVerticalSize(y);
830
832 std::string str = GetString(STR_GAME_OPTIONS_VIDEO_DRIVER_INFO, std::string{VideoDriver::GetInstance()->GetInfoString()});
833 y = GetStringHeight(str, wid->current_x);
834 changed |= wid->UpdateVerticalSize(y);
835
836 if (changed) this->ReInit(0, 0, this->flags.Test(WindowFlag::Centred));
837 }
838
839 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
840 {
841 switch (widget) {
844 Dimension d = maxdim(GetStringBoundingBox(STR_GAME_OPTIONS_SFX_VOLUME), GetStringBoundingBox(STR_GAME_OPTIONS_MUSIC_VOLUME));
845 d.width += padding.width;
846 d.height += padding.height;
847 size = maxdim(size, d);
848 break;
849 }
850
859 int selected;
860 size.width = std::max(size.width, GetDropDownListDimension(this->BuildDropDownList(widget, &selected)).width + padding.width);
861 break;
862 }
863
865 fill.height = resize.height = BaseSettingEntry::line_height;
866 resize.width = 1;
867
868 size.height = 8 * resize.height + WidgetDimensions::scaled.framerect.Vertical();
869 break;
870
872 static const StringID setting_types[] = {
873 STR_CONFIG_SETTING_TYPE_CLIENT,
874 STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
875 STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
876 };
877 for (const auto &setting_type : setting_types) {
878 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_CONFIG_SETTING_TYPE, setting_type)).width + padding.width);
879 }
880 size.height = 2 * GetCharacterHeight(FontSize::Normal);
881 break;
882 }
883
884 case WID_GO_HELP_TEXT:
885 size.height = NUM_DESCRIPTION_LINES * GetCharacterHeight(FontSize::Normal);
886 break;
887
890 size.width = std::max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
891 break;
892
893 default:
894 break;
895 }
896 }
897
898 void OnPaint() override
899 {
900 if (GameOptionsWindow::active_tab != WID_GO_TAB_ADVANCED) {
901 this->DrawWidgets();
902 return;
903 }
904
905 if (this->closing_dropdown) {
906 this->closing_dropdown = false;
907 assert(this->valuedropdown_entry != nullptr);
908 this->valuedropdown_entry->SetButtons({});
909 this->valuedropdown_entry = nullptr;
910 }
911
912 /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
913 const Rect panel = this->GetWidget<NWidgetBase>(WID_GO_OPTIONSPANEL)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext);
914 StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
915 int new_warn_lines;
916 if (this->warn_missing == WHR_NONE) {
917 new_warn_lines = 0;
918 } else {
919 new_warn_lines = GetStringLineCount(GetString(warn_str, _game_settings_restrict_dropdown[this->filter.min_cat]), panel.Width());
920 }
921 if (this->warn_lines != new_warn_lines) {
922 this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
923 this->warn_lines = new_warn_lines;
924 }
925
926 this->DrawWidgets();
927
928 /* Draw the 'some search results are hidden' notice. */
929 if (this->warn_missing != WHR_NONE) {
931 GetString(warn_str, _game_settings_restrict_dropdown[this->filter.min_cat]),
932 TextColour::Black, {AlignmentH::Centre, AlignmentV::Middle});
933 }
934 }
935
936 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
937 {
939 if (BaseGraphics::GetUsedSet() == nullptr) return;
940
941 ShowBaseSetTextfileWindow(this, (TextfileType)(widget - WID_GO_BASE_GRF_TEXTFILE), BaseGraphics::GetUsedSet(), STR_CONTENT_TYPE_BASE_GRAPHICS);
942 return;
943 }
945 if (BaseSounds::GetUsedSet() == nullptr) return;
946
947 ShowBaseSetTextfileWindow(this, (TextfileType)(widget - WID_GO_BASE_SFX_TEXTFILE), BaseSounds::GetUsedSet(), STR_CONTENT_TYPE_BASE_SOUNDS);
948 return;
949 }
951 if (BaseMusic::GetUsedSet() == nullptr) return;
952
953 ShowBaseSetTextfileWindow(this, (TextfileType)(widget - WID_GO_BASE_MUSIC_TEXTFILE), BaseMusic::GetUsedSet(), STR_CONTENT_TYPE_BASE_MUSIC);
954 return;
955 }
956 switch (widget) {
959 case WID_GO_TAB_SOUND:
962 SndClickBeep();
963 this->SetTab(widget);
964 break;
965
967 switch (_settings_client.network.participate_survey) {
968 case ParticipateSurvey::Ask:
969 case ParticipateSurvey::No:
970 _settings_client.network.participate_survey = ParticipateSurvey::Yes;
971 break;
972
973 case ParticipateSurvey::Yes:
974 _settings_client.network.participate_survey = ParticipateSurvey::No;
975 break;
976 }
977
978 this->SetWidgetLoweredState(WID_GO_SURVEY_PARTICIPATE_BUTTON, _settings_client.network.participate_survey == ParticipateSurvey::Yes);
981 break;
982
984 OpenBrowser(NETWORK_SURVEY_DETAILS_LINK);
985 break;
986
989 break;
990
991 case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
992 /* try to toggle full-screen on/off */
993 if (!ToggleFullScreen(!_fullscreen)) {
994 ShowErrorMessage(GetEncodedString(STR_ERROR_FULLSCREEN_FAILED), {}, WarningLevel::Error);
995 }
999 break;
1000
1003 ShowErrorMessage(GetEncodedString(STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART), {}, WarningLevel::Info);
1007#ifndef __APPLE__
1012#endif
1013 break;
1014
1016 if (!_video_hw_accel) break;
1017
1020
1026 break;
1027
1029 _settings_client.gui.scale_bevels = !_settings_client.gui.scale_bevels;
1030
1032 this->SetDirty();
1033
1035 ReInitAllWindows(true);
1036 break;
1037 }
1038
1039#ifdef HAS_TRUETYPE_FONT
1041 _fcsettings.prefer_sprite = !_fcsettings.prefer_sprite;
1042
1043 this->SetWidgetLoweredState(WID_GO_GUI_FONT_SPRITE, _fcsettings.prefer_sprite);
1044 this->SetWidgetDisabledState(WID_GO_GUI_FONT_AA, _fcsettings.prefer_sprite);
1045 this->SetDirty();
1046
1052 ReInitAllWindows(true);
1053 break;
1054
1055 case WID_GO_GUI_FONT_AA:
1056 _fcsettings.global_aa = !_fcsettings.global_aa;
1057
1058 this->SetWidgetLoweredState(WID_GO_GUI_FONT_AA, _fcsettings.global_aa);
1060
1062 break;
1063#endif /* HAS_TRUETYPE_FONT */
1064
1065 case WID_GO_GUI_SCALE:
1066 /* Any click on the slider deactivates automatic interface scaling, setting it to the current value before being adjusted. */
1067 if (_gui_scale_cfg == -1) {
1068 _gui_scale_cfg = this->gui_scale;
1072 }
1073
1074 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, _ctrl_pressed ? 0 : SCALE_NMARKS, this->gui_scale)) {
1075 this->gui_scale_changed = true;
1076 this->SetWidgetDirty(widget);
1077 }
1078
1079 if (click_count > 0) this->mouse_capture_widget = widget;
1080 break;
1081
1083 {
1084 if (_gui_scale_cfg == -1) {
1085 _gui_scale_cfg = this->previous_gui_scale; // Load the previous GUI scale
1087 if (AdjustGUIZoom(false)) ReInitAllWindows(true);
1088 this->gui_scale = _gui_scale;
1089 } else {
1090 this->previous_gui_scale = _gui_scale; // Set the previous GUI scale value as the current one
1091 _gui_scale_cfg = -1;
1093 if (AdjustGUIZoom(false)) ReInitAllWindows(true);
1094 this->gui_scale = _gui_scale;
1095 }
1096 this->SetWidgetDirty(widget);
1098 break;
1099 }
1100
1102 auto *used_set = BaseGraphics::GetUsedSet();
1103 if (used_set == nullptr || !used_set->IsConfigurable()) break;
1104 GRFConfig &extra_cfg = used_set->GetOrCreateExtraConfig();
1105 if (extra_cfg.param.empty()) extra_cfg.SetParameterDefaults();
1106 OpenGRFParameterWindow(true, extra_cfg, _game_mode == GameMode::Menu);
1107 if (_game_mode == GameMode::Menu) this->reload = true;
1108 break;
1109 }
1110
1113 uint8_t &vol = (widget == WID_GO_BASE_MUSIC_VOLUME) ? _settings_client.music.music_vol : _settings_client.music.effect_vol;
1114 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, 0, INT8_MAX, 0, vol)) {
1115 if (widget == WID_GO_BASE_MUSIC_VOLUME) {
1117 } else {
1118 SetEffectVolume(vol);
1119 }
1120 this->SetWidgetDirty(widget);
1121 SetWindowClassesDirty(WindowClass::Music);
1122 }
1123
1124 if (click_count > 0) this->mouse_capture_widget = widget;
1125 break;
1126 }
1127
1129 ShowMusicWindow();
1130 break;
1131 }
1132
1134 if (BaseGraphics::GetUsedSet() == nullptr || BaseGraphics::GetUsedSet()->url.empty()) return;
1135 OpenBrowser(BaseGraphics::GetUsedSet()->url);
1136 break;
1137
1139 if (BaseSounds::GetUsedSet() == nullptr || BaseSounds::GetUsedSet()->url.empty()) return;
1140 OpenBrowser(BaseSounds::GetUsedSet()->url);
1141 break;
1142
1144 if (BaseMusic::GetUsedSet() == nullptr || BaseMusic::GetUsedSet()->url.empty()) return;
1145 OpenBrowser(BaseMusic::GetUsedSet()->url);
1146 break;
1147
1150 break;
1151
1154 break;
1155
1158 break;
1159
1163 int selected;
1164 DropDownList list = this->BuildDropDownList(widget, &selected);
1165 if (!list.empty()) {
1166 ShowDropDownList(this, std::move(list), selected, widget);
1167 } else {
1168 if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(GetEncodedString(STR_ERROR_RESOLUTION_LIST_FAILED), {}, WarningLevel::Error);
1169 }
1170 break;
1171 }
1172
1178 int selected;
1179 DropDownList list = this->BuildDropDownList(widget, &selected);
1180 if (!list.empty()) {
1181 ShowDropDownList(this, std::move(list), selected, widget, 0, DropDownOption::Filterable);
1182 } else {
1183 if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(GetEncodedString(STR_ERROR_RESOLUTION_LIST_FAILED), {}, WarningLevel::Error);
1184 }
1185 break;
1186 }
1187
1188 case WID_GO_EXPAND_ALL:
1189 this->manually_changed_folding = true;
1191 this->InvalidateData();
1192 break;
1193
1195 this->manually_changed_folding = true;
1197 this->InvalidateData();
1198 break;
1199
1200 case WID_GO_RESET_ALL:
1201 ShowQuery(
1202 GetEncodedString(STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION),
1203 GetEncodedString(STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT),
1204 this,
1206 );
1207 break;
1208
1210 int selected;
1211 DropDownList list = this->BuildDropDownList(widget, &selected);
1212 if (!list.empty()) {
1213 ShowDropDownList(this, std::move(list), this->filter.mode, widget);
1214 }
1215 break;
1216 }
1217
1218 case WID_GO_TYPE_DROPDOWN: {
1219 int selected;
1220 DropDownList list = this->BuildDropDownList(widget, &selected);
1221 if (!list.empty()) {
1222 ShowDropDownList(this, std::move(list), this->filter.type, widget);
1223 }
1224 break;
1225 }
1226
1228 OptionsPanelClick(pt);
1229 break;
1230 }
1231 }
1232
1233 void OptionsPanelClick(Point pt)
1234 {
1235 int32_t btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GO_OPTIONSPANEL, WidgetDimensions::scaled.framerect.top);
1236 if (btn == INT32_MAX || btn < this->warn_lines) return;
1237 btn -= this->warn_lines;
1238
1239 uint cur_row = 0;
1241
1242 if (clicked_entry == nullptr) return; // Clicked below the last setting of the page
1243
1245 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 - wid->pos_x; // Shift x coordinate
1246 if (x < 0) return; // Clicked left of the entry
1247
1248 SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
1249 if (clicked_page != nullptr) {
1250 this->SetDisplayedHelpText(nullptr);
1251 clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
1252
1253 this->manually_changed_folding = true;
1254
1255 this->InvalidateData();
1256 return;
1257 }
1258
1259 SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
1260 assert(pe != nullptr);
1261 const IntSettingDesc *sd = pe->setting;
1262
1263 /* return if action is only active in network, or only settable by server */
1264 if (!sd->IsEditable()) {
1265 this->SetDisplayedHelpText(pe);
1266 return;
1267 }
1268
1269 auto [min_val, max_val] = sd->GetRange();
1270 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
1271
1272 /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
1273 if (x < SETTING_BUTTON_WIDTH && sd->flags.Test(SettingFlag::GuiDropdown)) {
1274 this->SetDisplayedHelpText(pe);
1275
1276 if (this->valuedropdown_entry == pe) {
1277 /* unclick the dropdown */
1278 this->CloseChildWindows(WindowClass::DropdownMenu);
1279 this->closing_dropdown = false;
1280 this->valuedropdown_entry->SetButtons({});
1281 this->valuedropdown_entry = nullptr;
1282 } else {
1283 if (this->valuedropdown_entry != nullptr) this->valuedropdown_entry->SetButtons({});
1284 this->closing_dropdown = false;
1285
1286 int rel_y = (pt.y - wid->pos_y - WidgetDimensions::scaled.framerect.top) % wid->resize_y;
1287
1288 Rect wi_rect;
1289 wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
1290 wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
1291 wi_rect.top = pt.y - rel_y + (BaseSettingEntry::line_height - SETTING_BUTTON_HEIGHT) / 2;
1292 wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
1293
1294 /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
1295 if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
1296 this->valuedropdown_entry = pe;
1298
1299 DropDownList list;
1300 for (int32_t i = min_val; i <= static_cast<int32_t>(max_val); i++) {
1301 auto [param1, param2] = sd->GetValueParams(i);
1302 list.push_back(MakeDropDownListStringItem(GetString(STR_JUST_STRING1, param1, param2), i));
1303 }
1304
1305 ShowDropDownListAt(this, std::move(list), value, WID_GO_SETTING_DROPDOWN, wi_rect, Colours::Orange);
1306 }
1307 }
1308 this->SetDirty();
1309 } else if (x < SETTING_BUTTON_WIDTH) {
1310 this->SetDisplayedHelpText(pe);
1311 int32_t oldvalue = value;
1312
1313 if (sd->IsBoolSetting()) {
1314 value ^= 1;
1315 } else {
1316 /* Add a dynamic step-size to the scroller. In a maximum of
1317 * 50-steps you should be able to get from min to max,
1318 * unless specified otherwise in the 'interval' variable
1319 * of the current setting. */
1320 uint32_t step = (sd->interval == 0) ? ((max_val - min_val) / 50) : sd->interval;
1321 if (step == 0) step = 1;
1322
1323 /* don't allow too fast scrolling */
1324 if (this->flags.Test(WindowFlag::Timeout) && this->timeout_timer > 1) {
1325 _left_button_clicked = false;
1326 return;
1327 }
1328
1329 /* Increase or decrease the value and clamp it to extremes */
1330 if (x >= SETTING_BUTTON_WIDTH / 2) {
1331 value += step;
1332 if (min_val < 0) {
1333 assert(static_cast<int32_t>(max_val) >= 0);
1334 if (value > static_cast<int32_t>(max_val)) value = static_cast<int32_t>(max_val);
1335 } else {
1336 if (static_cast<uint32_t>(value) > max_val) value = static_cast<int32_t>(max_val);
1337 }
1338 if (value < min_val) value = min_val; // skip between "disabled" and minimum
1339 } else {
1340 value -= step;
1341 if (value < min_val) value = sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val;
1342 }
1343
1344 /* Set up scroller timeout for numeric values */
1345 if (value != oldvalue) {
1346 if (this->clicked_entry != nullptr) { // Release previous buttons if any
1347 this->clicked_entry->SetButtons({});
1348 }
1349 this->clicked_entry = pe;
1351 this->SetTimeout();
1352 _left_button_clicked = false;
1353 }
1354 }
1355
1356 if (value != oldvalue) {
1357 SetSettingValue(sd, value);
1358 this->SetDirty();
1359 }
1360 } else {
1361 /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
1362 if (this->last_clicked == pe && !sd->IsBoolSetting() && !sd->flags.Test(SettingFlag::GuiDropdown)) {
1363 int64_t value64 = value;
1364 /* Show the correct currency-translated value */
1365 if (sd->flags.Test(SettingFlag::GuiCurrency)) value64 *= GetCurrency().rate;
1366
1367 CharSetFilter charset_filter = CS_NUMERAL; //default, only numeric input allowed
1368 if (min_val < 0) charset_filter = CS_NUMERAL_SIGNED; // special case, also allow '-' sign for negative input
1369
1370 this->valuewindow_entry = pe;
1371 /* Limit string length to 14 so that MAX_INT32 * max currency rate doesn't exceed MAX_INT64. */
1372 ShowQueryString(GetString(STR_JUST_INT, value64), STR_CONFIG_SETTING_QUERY_CAPTION, 15, this, charset_filter, QueryStringFlag::EnableDefault);
1373 }
1374 this->SetDisplayedHelpText(pe);
1375 }
1376 }
1377
1378 void OnTimeout() override
1379 {
1380 if (this->clicked_entry != nullptr) { // On timeout, release any depressed buttons
1381 this->clicked_entry->SetButtons({});
1382 this->clicked_entry = nullptr;
1383 this->SetDirty();
1384 }
1385 }
1386
1387 void OnQueryTextFinished(std::optional<std::string> str) override
1388 {
1389 /* The user pressed cancel */
1390 if (!str.has_value()) return;
1391
1392 assert(this->valuewindow_entry != nullptr);
1393 const IntSettingDesc *sd = this->valuewindow_entry->setting;
1394
1395 int32_t value;
1396 if (!str->empty()) {
1397 auto llvalue = ParseInteger<int64_t>(*str, 10, true);
1398 if (!llvalue.has_value()) return;
1399
1400 /* Save the correct currency-translated value */
1401 if (sd->flags.Test(SettingFlag::GuiCurrency)) llvalue = *llvalue / GetCurrency().rate;
1402
1403 value = ClampTo<int32_t>(*llvalue);
1404 } else {
1405 value = sd->GetDefaultValue();
1406 }
1407
1408 SetSettingValue(this->valuewindow_entry->setting, value);
1409 this->SetDirty();
1410 }
1411
1412 void OnMouseLoop() override
1413 {
1414 if (_left_button_down || !this->gui_scale_changed) return;
1415
1416 this->gui_scale_changed = false;
1417 _gui_scale_cfg = this->gui_scale;
1418
1419 if (AdjustGUIZoom(false)) {
1420 ReInitAllWindows(true);
1422 this->SetDirty();
1423 }
1424 }
1425
1426 void OnDropdownSelect(WidgetID widget, int index, int) override
1427 {
1428 switch (widget) {
1429 case WID_GO_CURRENCY_DROPDOWN: { // Currency
1430 Currency currency = static_cast<Currency>(index);
1431 if (currency == Currency::Custom) ShowCustCurrency();
1432 this->opt->locale.currency = currency;
1433 ReInitAllWindows(false);
1434 break;
1435 }
1436
1437 case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
1438 _settings_client.gui.autosave_interval = _autosave_dropdown_to_minutes[index];
1440 this->SetDirty();
1441 break;
1442
1443 case WID_GO_LANG_DROPDOWN: // Change interface language
1445 CloseWindowByClass(WindowClass::QueryString);
1447 ClearAllCachedNames();
1449 CheckBlitter();
1450 ReInitAllWindows(false);
1451 break;
1452
1453 case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
1454 if ((uint)index < _resolutions.size() && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
1455 this->SetDirty();
1456 }
1457 break;
1458
1460 _settings_client.gui.refresh_rate = *std::next(_refresh_rates.begin(), index);
1461 if (_settings_client.gui.refresh_rate > 60) {
1462 /* Show warning to the user that this refresh rate might not be suitable on
1463 * larger maps with many NewGRFs and vehicles. */
1464 ShowErrorMessage(GetEncodedString(STR_GAME_OPTIONS_REFRESH_RATE_WARNING), {}, WarningLevel::Info);
1465 }
1466 break;
1467 }
1468
1470 if (_game_mode == GameMode::Menu) {
1471 CloseWindowByClass(WindowClass::NewGRFParameters);
1472 auto set = BaseGraphics::GetSet(index);
1474 this->reload = true;
1475 this->InvalidateData();
1476 }
1477 break;
1478
1480 ChangeSoundSet(index);
1481 break;
1482
1484 ChangeMusicSet(index);
1485 break;
1486
1488 this->filter.mode = (RestrictionMode)index;
1489 if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
1490 this->filter.mode == RM_CHANGED_AGAINST_NEW) {
1491
1492 if (!this->manually_changed_folding) {
1493 /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
1494 GetSettingsTree().UpdateFilterState(this->filter, false);
1496 }
1497 } else {
1498 /* Non-'changes' filter. Save as default. */
1499 _settings_client.gui.settings_restriction_mode = this->filter.mode;
1500 }
1501 this->InvalidateData();
1502 break;
1503
1505 this->filter.type = (SettingType)index;
1506 this->InvalidateData();
1507 break;
1508
1510 /* Deal with drop down boxes on the panel. */
1511 assert(this->valuedropdown_entry != nullptr);
1512 const IntSettingDesc *sd = this->valuedropdown_entry->setting;
1513 assert(sd->flags.Test(SettingFlag::GuiDropdown));
1514
1515 SetSettingValue(sd, index);
1516 this->SetDirty();
1517 break;
1518 }
1519 }
1520
1521 void OnDropdownClose(Point pt, WidgetID widget, int index, int click_result, bool instant_close) override
1522 {
1523 if (widget != WID_GO_SETTING_DROPDOWN) {
1524 /* Normally the default implementation of OnDropdownClose() takes care of
1525 * a few things. We want that behaviour here too, but only for
1526 * "normal" dropdown boxes. The special dropdown boxes added for every
1527 * setting that needs one can't have this call. */
1528 Window::OnDropdownClose(pt, widget, index, click_result, instant_close);
1529 } else {
1530 /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
1531 * the same dropdown button was clicked again, and then not open the dropdown again.
1532 * So, we only remember that it was closed, and process it on the next OnPaint, which is
1533 * after OnClick. */
1534 assert(this->valuedropdown_entry != nullptr);
1535 this->closing_dropdown = true;
1536 this->SetDirty();
1537 }
1538 }
1539
1545 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1546 {
1547 if (!gui_scope) return;
1548 this->SetWidgetLoweredState(WID_GO_SURVEY_PARTICIPATE_BUTTON, _settings_client.network.participate_survey == ParticipateSurvey::Yes);
1552
1553#ifndef __APPLE__
1556#endif
1557
1560#ifdef HAS_TRUETYPE_FONT
1561 this->SetWidgetLoweredState(WID_GO_GUI_FONT_SPRITE, _fcsettings.prefer_sprite);
1562 this->SetWidgetLoweredState(WID_GO_GUI_FONT_AA, _fcsettings.global_aa);
1563 this->SetWidgetDisabledState(WID_GO_GUI_FONT_AA, _fcsettings.prefer_sprite);
1564#endif /* HAS_TRUETYPE_FONT */
1565
1567
1569
1573
1578 }
1579
1581
1582 /* Update which settings are to be visible. */
1583 RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
1584 this->filter.min_cat = min_level;
1585 this->filter.type_hides = false;
1586 GetSettingsTree().UpdateFilterState(this->filter, false);
1587
1588 if (this->filter.string.IsEmpty()) {
1589 this->warn_missing = WHR_NONE;
1590 } else if (min_level < this->filter.min_cat) {
1591 this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
1592 } else {
1593 this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
1594 }
1595 this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
1596
1597 if (this->last_clicked != nullptr && !GetSettingsTree().IsVisible(this->last_clicked)) {
1598 this->SetDisplayedHelpText(nullptr);
1599 }
1600
1601 bool all_folded = true;
1602 bool all_unfolded = true;
1603 GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
1604 this->SetWidgetDisabledState(WID_GO_EXPAND_ALL, all_unfolded);
1606 }
1607
1608 void OnEditboxChanged(WidgetID wid) override
1609 {
1610 if (wid == WID_GO_FILTER) {
1611 this->filter.string.SetFilterTerm(this->filter_editbox.text.GetText());
1612 if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
1613 /* User never expanded/collapsed single pages and entered a filter term.
1614 * Expand everything, to save weird expand clicks, */
1616 }
1617 this->InvalidateData();
1618 }
1619 }
1620};
1621
1622static constexpr std::initializer_list<NWidgetPart> _nested_game_options_widgets = {
1625 NWidget(WWT_CAPTION, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1627 EndContainer(),
1630 NWidget(WWT_TEXTBTN, GAME_OPTIONS_BUTTON, WID_GO_TAB_GENERAL), SetMinimalTextLines(2, 0), SetStringTip(STR_GAME_OPTIONS_TAB_GENERAL, STR_GAME_OPTIONS_TAB_GENERAL_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1631 NWidget(WWT_TEXTBTN, GAME_OPTIONS_BUTTON, WID_GO_TAB_GRAPHICS), SetMinimalTextLines(2, 0), SetStringTip(STR_GAME_OPTIONS_TAB_GRAPHICS, STR_GAME_OPTIONS_TAB_GRAPHICS_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1632 NWidget(WWT_TEXTBTN, GAME_OPTIONS_BUTTON, WID_GO_TAB_SOUND), SetMinimalTextLines(2, 0), SetStringTip(STR_GAME_OPTIONS_TAB_SOUND, STR_GAME_OPTIONS_TAB_SOUND_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1633 NWidget(WWT_TEXTBTN, GAME_OPTIONS_BUTTON, WID_GO_TAB_SOCIAL), SetMinimalTextLines(2, 0), SetStringTip(STR_GAME_OPTIONS_TAB_SOCIAL, STR_GAME_OPTIONS_TAB_SOCIAL_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1634 NWidget(WWT_TEXTBTN, GAME_OPTIONS_BUTTON, WID_GO_TAB_ADVANCED), SetMinimalTextLines(2, 0), SetStringTip(STR_GAME_OPTIONS_TAB_ADVANCED, STR_GAME_OPTIONS_TAB_ADVANCED_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1635 EndContainer(),
1636 EndContainer(),
1639 /* General tab */
1643 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_LANG_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1644 EndContainer(),
1645
1647 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_AUTOSAVE_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1648 EndContainer(),
1649
1650 NWidget(WWT_FRAME, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME), SetTextStyle(GAME_OPTIONS_FRAME),
1651 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_CURRENCY_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1652 EndContainer(),
1653
1655 NWidget(WWT_FRAME, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_FRAME), SetTextStyle(GAME_OPTIONS_FRAME), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1659 EndContainer(),
1661 NWidget(WWT_TEXTBTN, GAME_OPTIONS_BUTTON, WID_GO_SURVEY_PREVIEW_BUTTON), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW, STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW_TOOLTIP),
1662 NWidget(WWT_TEXTBTN, GAME_OPTIONS_BUTTON, WID_GO_SURVEY_LINK_BUTTON), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK, STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK_TOOLTIP),
1663 EndContainer(),
1664 EndContainer(),
1665 EndContainer(),
1666 EndContainer(),
1667 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1668 EndContainer(),
1669
1670 /* Graphics tab */
1676 NWidget(WWT_TEXT, Colours::Invalid), SetStringTip(STR_GAME_OPTIONS_GUI_SCALE_FRAME), SetTextStyle(GAME_OPTIONS_LABEL),
1677 NWidget(WWT_EMPTY, Colours::Invalid, WID_GO_GUI_SCALE), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FontSize::Small), SetFill(1, 0), SetResize(1, 0), SetToolTip(STR_GAME_OPTIONS_GUI_SCALE_TOOLTIP),
1678 EndContainer(),
1682 EndContainer(),
1686 EndContainer(),
1687#ifdef HAS_TRUETYPE_FONT
1691 EndContainer(),
1695 EndContainer(),
1696#endif /* HAS_TRUETYPE_FONT */
1697 EndContainer(),
1698 EndContainer(),
1699
1703 NWidget(WWT_TEXT, Colours::Invalid), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_RESOLUTION), SetTextStyle(GAME_OPTIONS_LABEL),
1704 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_RESOLUTION_DROPDOWN), SetFill(1, 0), SetToolTip(STR_GAME_OPTIONS_RESOLUTION_TOOLTIP),
1705 EndContainer(),
1707 NWidget(WWT_TEXT, Colours::Invalid), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_REFRESH_RATE), SetTextStyle(GAME_OPTIONS_LABEL),
1708 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_REFRESH_RATE_DROPDOWN), SetFill(1, 0), SetToolTip(STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP),
1709 EndContainer(),
1713 EndContainer(),
1717 EndContainer(),
1718#ifndef __APPLE__
1722 EndContainer(),
1723#endif
1726 EndContainer(),
1727 EndContainer(),
1728 EndContainer(),
1729
1732 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_BASE_GRF_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1734 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1735 EndContainer(),
1736 NWidget(WWT_TEXT, Colours::Invalid, WID_GO_BASE_GRF_DESCRIPTION), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1739 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
1740 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_TEXTFILE + TextfileType::Readme), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1741 EndContainer(),
1743 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_TEXTFILE + TextfileType::Changelog), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1744 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_TEXTFILE + TextfileType::License), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1745 EndContainer(),
1746 EndContainer(),
1747 EndContainer(),
1748 EndContainer(),
1749 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1750 EndContainer(),
1751
1752 /* Sound/Music tab */
1758 NWidget(WWT_EMPTY, Colours::Invalid, WID_GO_BASE_SFX_VOLUME), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FontSize::Small), SetFill(1, 0), SetResize(1, 0), SetToolTip(STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
1759 EndContainer(),
1762 NWidget(WWT_EMPTY, Colours::Invalid, WID_GO_BASE_MUSIC_VOLUME), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FontSize::Small), SetFill(1, 0), SetResize(1, 0), SetToolTip(STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
1763 EndContainer(),
1764 EndContainer(),
1765
1768 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_BASE_SFX_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1769 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1770 EndContainer(),
1771 NWidget(WWT_EMPTY, Colours::Invalid, WID_GO_BASE_SFX_DESCRIPTION), SetMinimalTextLines(1, 0), SetToolTip(STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1774 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
1775 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_TEXTFILE + TextfileType::Readme), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1776 EndContainer(),
1778 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_TEXTFILE + TextfileType::Changelog), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1779 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_TEXTFILE + TextfileType::License), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1780 EndContainer(),
1781 EndContainer(),
1782 EndContainer(),
1783
1786 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1787 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1788 EndContainer(),
1790 NWidget(WWT_EMPTY, Colours::Invalid, WID_GO_BASE_MUSIC_DESCRIPTION), SetMinimalTextLines(1, 0), SetToolTip(STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1793 EndContainer(),
1794 EndContainer(),
1797 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_OPEN_URL), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_CONTENT_OPEN_URL, STR_CONTENT_OPEN_URL_TOOLTIP),
1798 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_TEXTFILE + TextfileType::Readme), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1799 EndContainer(),
1801 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_TEXTFILE + TextfileType::Changelog), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1802 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_TEXTFILE + TextfileType::License), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1803 EndContainer(),
1804 EndContainer(),
1805 EndContainer(),
1806 EndContainer(),
1807 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1808 EndContainer(),
1809
1810 /* Social tab */
1813 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1814 EndContainer(),
1815
1816 /* Advanced settings tab */
1821 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_RESTRICT_DROPDOWN), SetToolTip(STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
1822 EndContainer(),
1825 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_TYPE_DROPDOWN), SetToolTip(STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
1826 EndContainer(),
1828 NWidget(WWT_TEXT, Colours::Invalid), SetFill(0, 1), SetStringTip(STR_CONFIG_SETTING_FILTER_TITLE), SetTextStyle(GAME_OPTIONS_LABEL),
1829 NWidget(WWT_EDITBOX, GAME_OPTIONS_BACKGROUND, WID_GO_FILTER), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1830 EndContainer(),
1831 EndContainer(),
1832
1835 EndContainer(),
1837 EndContainer(),
1838
1840 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_EXPAND_ALL), SetStringTip(STR_CONFIG_SETTING_EXPAND_ALL), SetFill(1, 0), SetResize(1, 0),
1841 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_COLLAPSE_ALL), SetStringTip(STR_CONFIG_SETTING_COLLAPSE_ALL), SetFill(1, 0), SetResize(1, 0),
1842 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_RESET_ALL), SetStringTip(STR_CONFIG_SETTING_RESET_ALL), SetFill(1, 0), SetResize(1, 0),
1843 EndContainer(),
1844
1849 EndContainer(),
1850 EndContainer(),
1851 EndContainer(),
1852
1854 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1856 EndContainer(),
1857 EndContainer(),
1858};
1859
1862 WindowPosition::Center, "game_options", 0, 0,
1863 WindowClass::GameOptions, WindowClass::None,
1864 {},
1865 _nested_game_options_widgets
1866);
1867
1870{
1871 CloseWindowByClass(WindowClass::GameOptions);
1873}
1874
1884void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
1885{
1886 PixelColour colour = GetColourGradient(button_colour, Shade::Darker);
1887 Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
1888
1889 Rect lr = {x, y, x + (int)dim.width - 1, y + (int)dim.height - 1};
1890 Rect rr = {x + (int)dim.width, y, x + (int)dim.width * 2 - 1, y + (int)dim.height - 1};
1891
1892 DrawFrameRect(lr, button_colour, (state == 1) ? FrameFlag::Lowered : FrameFlags{});
1893 DrawFrameRect(rr, button_colour, (state == 2) ? FrameFlag::Lowered : FrameFlags{});
1896
1897 /* Grey out the buttons that aren't clickable */
1898 bool rtl = _current_text_dir == TD_RTL;
1899 if (rtl ? !clickable_right : !clickable_left) {
1901 }
1902 if (rtl ? !clickable_left : !clickable_right) {
1904 }
1905}
1906
1916void DrawUpDownButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_up, bool clickable_down)
1917{
1918 PixelColour colour = GetColourGradient(button_colour, Shade::Darker);
1919
1920 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
1923
1924 DrawFrameRect(ur, button_colour, (state == 1) ? FrameFlag::Lowered : FrameFlags{});
1925 DrawFrameRect(dr, button_colour, (state == 2) ? FrameFlag::Lowered : FrameFlags{});
1928
1929 /* Grey out the buttons that aren't clickable */
1930 if (!clickable_up) GfxFillRect(ur.Shrink(WidgetDimensions::scaled.bevel), colour, FillRectMode::Checker);
1931 if (!clickable_down) GfxFillRect(dr.Shrink(WidgetDimensions::scaled.bevel), colour, FillRectMode::Checker);
1932}
1933
1942void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
1943{
1944 PixelColour colour = GetColourGradient(button_colour, Shade::Darker);
1945
1946 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
1947
1948 DrawFrameRect(r, button_colour, state ? FrameFlag::Lowered : FrameFlags{});
1950
1951 if (!clickable) {
1953 }
1954}
1955
1965void DrawBoolButton(int x, int y, Colours button_colour, Colours background, bool state, bool clickable)
1966{
1967 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
1969 if (!clickable) {
1971 }
1972
1973 Rect button_rect = r.WithWidth(SETTING_BUTTON_WIDTH / 3, state ^ (_current_text_dir == TD_RTL));
1974 DrawFrameRect(button_rect, button_colour, {});
1975 if (!clickable) {
1977 }
1978}
1979
1980struct CustomCurrencyWindow : Window {
1981 WidgetID query_widget{};
1982
1983 CustomCurrencyWindow(WindowDesc &desc) : Window(desc)
1984 {
1985 this->InitNested();
1986
1987 SetButtonState();
1988 }
1989
1990 void SetButtonState()
1991 {
1993 this->SetWidgetDisabledState(WID_CC_RATE_UP, GetCustomCurrency().rate == UINT16_MAX);
1996 }
1997
1998 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1999 {
2000 switch (widget) {
2001 case WID_CC_RATE: return GetString(STR_CURRENCY_EXCHANGE_RATE, 1, 1);
2002 case WID_CC_SEPARATOR: return GetString(STR_CURRENCY_SEPARATOR, GetCustomCurrency().separator);
2003 case WID_CC_PREFIX: return GetString(STR_CURRENCY_PREFIX, GetCustomCurrency().prefix);
2004 case WID_CC_SUFFIX: return GetString(STR_CURRENCY_SUFFIX, GetCustomCurrency().suffix);
2005 case WID_CC_YEAR:
2006 return GetString((GetCustomCurrency().to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER, GetCustomCurrency().to_euro);
2007
2008 case WID_CC_PREVIEW:
2009 return GetString(STR_CURRENCY_PREVIEW, 10000);
2010
2011 default:
2012 return this->Window::GetWidgetString(widget, stringid);
2013 }
2014 }
2015
2016 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
2017 {
2018 switch (widget) {
2019 /* Set the appropriate width for the up/down buttons. */
2020 case WID_CC_RATE_DOWN:
2021 case WID_CC_RATE_UP:
2022 case WID_CC_YEAR_DOWN:
2023 case WID_CC_YEAR_UP:
2024 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH / 2, (uint)SETTING_BUTTON_HEIGHT});
2025 break;
2026
2027 /* Set the appropriate width for the edit buttons. */
2029 case WID_CC_PREFIX_EDIT:
2030 case WID_CC_SUFFIX_EDIT:
2031 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH, (uint)SETTING_BUTTON_HEIGHT});
2032 break;
2033
2034 /* Make sure the window is wide enough for the widest exchange rate */
2035 case WID_CC_RATE:
2036 size = GetStringBoundingBox(GetString(STR_CURRENCY_EXCHANGE_RATE, 1, INT32_MAX));
2037 break;
2038 }
2039 }
2040
2041 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2042 {
2043 int line = 0;
2044 int len = 0;
2045 std::string str;
2047
2048 switch (widget) {
2049 case WID_CC_RATE_DOWN:
2050 if (GetCustomCurrency().rate > 1) GetCustomCurrency().rate--;
2051 if (GetCustomCurrency().rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2053 break;
2054
2055 case WID_CC_RATE_UP:
2056 if (GetCustomCurrency().rate < UINT16_MAX) GetCustomCurrency().rate++;
2057 if (GetCustomCurrency().rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2059 break;
2060
2061 case WID_CC_RATE:
2062 str = GetString(STR_JUST_INT, GetCustomCurrency().rate);
2063 len = 5;
2064 line = WID_CC_RATE;
2065 afilter = CS_NUMERAL;
2066 break;
2067
2069 case WID_CC_SEPARATOR:
2071 len = 7;
2072 line = WID_CC_SEPARATOR;
2073 break;
2074
2075 case WID_CC_PREFIX_EDIT:
2076 case WID_CC_PREFIX:
2077 str = GetCustomCurrency().prefix;
2078 len = 15;
2079 line = WID_CC_PREFIX;
2080 break;
2081
2082 case WID_CC_SUFFIX_EDIT:
2083 case WID_CC_SUFFIX:
2084 str = GetCustomCurrency().suffix;
2085 len = 15;
2086 line = WID_CC_SUFFIX;
2087 break;
2088
2089 case WID_CC_YEAR_DOWN:
2093 break;
2094
2095 case WID_CC_YEAR_UP:
2099 break;
2100
2101 case WID_CC_YEAR:
2102 str = GetString(STR_JUST_INT, GetCustomCurrency().to_euro);
2103 len = 7;
2104 line = WID_CC_YEAR;
2105 afilter = CS_NUMERAL;
2106 break;
2107 }
2108
2109 if (len != 0) {
2110 this->query_widget = line;
2111 ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, {});
2112 }
2113
2114 this->SetTimeout();
2115 this->SetDirty();
2116 }
2117
2118 void OnQueryTextFinished(std::optional<std::string> str) override
2119 {
2120 if (!str.has_value()) return;
2121
2122 switch (this->query_widget) {
2123 case WID_CC_RATE: {
2124 auto val = ParseInteger(*str, 10, true);
2125 if (!val.has_value()) return;
2126 GetCustomCurrency().rate = Clamp(*val, 1, UINT16_MAX);
2127 break;
2128 }
2129
2130 case WID_CC_SEPARATOR: // Thousands separator
2131 GetCustomCurrency().separator = std::move(*str);
2132 break;
2133
2134 case WID_CC_PREFIX:
2135 GetCustomCurrency().prefix = std::move(*str);
2136 break;
2137
2138 case WID_CC_SUFFIX:
2139 GetCustomCurrency().suffix = std::move(*str);
2140 break;
2141
2142 case WID_CC_YEAR: { // Year to switch to euro
2144 if (!str->empty()) {
2145 auto val = ParseInteger(*str, 10, true);
2146 if (!val.has_value()) return;
2148 }
2149 GetCustomCurrency().to_euro = year;
2150 break;
2151 }
2152 }
2154 SetButtonState();
2155 }
2156
2157 void OnTimeout() override
2158 {
2159 this->SetDirty();
2160 }
2161};
2162
2163static constexpr std::initializer_list<NWidgetPart> _nested_cust_currency_widgets = {
2166 NWidget(WWT_CAPTION, Colours::Grey), SetStringTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2167 EndContainer(),
2175 EndContainer(),
2176 NWidget(WWT_TEXT, Colours::Invalid, WID_CC_RATE), SetToolTip(STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2177 EndContainer(),
2179 NWidget(WWT_PUSHBTN, Colours::DarkBlue, WID_CC_SEPARATOR_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2180 NWidget(WWT_TEXT, Colours::Invalid, WID_CC_SEPARATOR), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2181 EndContainer(),
2183 NWidget(WWT_PUSHBTN, Colours::DarkBlue, WID_CC_PREFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2184 NWidget(WWT_TEXT, Colours::Invalid, WID_CC_PREFIX), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2185 EndContainer(),
2187 NWidget(WWT_PUSHBTN, Colours::DarkBlue, WID_CC_SUFFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2188 NWidget(WWT_TEXT, Colours::Invalid, WID_CC_SUFFIX), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2189 EndContainer(),
2192 NWidget(WWT_PUSHARROWBTN, Colours::Yellow, WID_CC_YEAR_DOWN), SetArrowWidgetTypeTip(ArrowWidgetType::Decrease, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2193 NWidget(WWT_PUSHARROWBTN, Colours::Yellow, WID_CC_YEAR_UP), SetArrowWidgetTypeTip(ArrowWidgetType::Increase, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2194 EndContainer(),
2195 NWidget(WWT_TEXT, Colours::Invalid, WID_CC_YEAR), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2196 EndContainer(),
2197 EndContainer(),
2199 SetToolTip(STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP),
2200 EndContainer(),
2201 EndContainer(),
2202};
2203
2206 WindowPosition::Center, {}, 0, 0,
2207 WindowClass::CustomCurrenty, WindowClass::None,
2208 {},
2209 _nested_cust_currency_widgets
2210);
2211
2213static void ShowCustCurrency()
2214{
2215 CloseWindowById(WindowClass::CustomCurrenty, 0);
2217}
void UpdateAllVirtCoords()
Update the viewport coordinates of all signs.
Base functions for all AIs.
Generic functions for replacing base data (graphics, sounds).
Generic functions for replacing base graphics data.
Generic functions for replacing base music data.
Generic functions for replacing base sounds data.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Flip()
Flip all bits.
static const GraphicsSet * GetUsedSet()
static const GraphicsSet * GetSet(int index)
static bool SetSet(const GraphicsSet *set)
static bool NatSortFunc(std::unique_ptr< const DropDownListItem > const &first, std::unique_ptr< const DropDownListItem > const &second)
Iterate a range of enum values.
static void ClearFontCaches(FontSizes fontsizes)
Clear cached information for the specified font caches.
static void LoadFontCaches(FontSizes fontsizes)
(Re)initialize the font cache related things, i.e.
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.
uint current_x
Current horizontal size (after resizing).
int pos_y
Vertical position of top-left corner of the widget in the window.
int pos_x
Horizontal position of top-left corner of the widget in the window.
uint resize_y
Vertical resize step (0 means not resizable).
void Add(std::unique_ptr< NWidgetBase > &&wid)
Append widget wid to container.
Definition widget.cpp:1328
std::vector< std::unique_ptr< NWidgetBase > > children
Child widgets in container.
void SetPIP(uint8_t pip_pre, uint8_t pip_inter, uint8_t pip_post)
Set additional pre/inter/post space for the container.
Definition widget.cpp:1544
Base class for a resizable nested widget.
bool UpdateVerticalSize(uint min_y)
Set absolute (post-scaling) minimal size of the widget.
Definition widget.cpp:1156
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).
void SetupSmallestSize(Window *w) override
Compute smallest size needed by the widget.
Definition widget.cpp:1760
static constexpr bool IsSurveyPossible()
Check whether a survey is possible.
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.
void SetCapacity(size_t capacity)
Set the capacity of visible elements.
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:2474
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:2548
size_type GetCount() const
Gets the number of elements in the list.
size_type GetPosition() const
Gets the position of the first visible element in the list.
std::string social_platform
Social platform this plugin is for.
std::string name
Name of the plugin.
std::string version
Version of the plugin.
@ PLATFORM_NOT_RUNNING
The plugin failed to initialize because the Social Platform is not running.
@ UNSUPPORTED_API
The plugin does not support the current API version.
@ RUNNING
The plugin is successfully loaded and running.
@ FAILED
The plugin failed to initialize.
@ DUPLICATE
Another plugin of the same Social Platform is already loaded.
@ INVALID_SIGNATURE
The signature of the plugin is invalid.
@ UNLOADED
The plugin is unloaded upon request.
static std::vector< SocialIntegrationPlugin * > GetPlugins()
Get the list of loaded social integration plugins.
static constexpr TimerGame< struct Calendar >::Year MAX_YEAR
StrongType::Typedef< int32_t, struct YearTag< struct Calendar >, StrongType::Compare, StrongType::Integer > Year
virtual std::string_view GetInfoString() const
Get some information about the selected driver/backend to be shown to the user.
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
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:95
Functions related to commands.
Definition of stuff that is very close to a company, like the company struct itself.
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:28
Currencies GetMaskOfAllowedCurrencies()
get a mask of the allowed currencies depending on the year
Definition currency.cpp:128
EnumIndexArray< CurrencySpec, Currency, Currency::End > _currency_specs
Array of currencies used by the system.
Definition currency.cpp:80
Functions to handle different currencies.
CurrencySpec & GetCustomCurrency()
Get the custom currency.
const CurrencySpec & GetCurrency()
Get the currently selected currency.
static constexpr TimerGameCalendar::Year MIN_EURO_YEAR
The earliest year custom currencies may switch to the Euro.
Currency
This enum gives the currencies a unique id which must be maintained for savegame compatibility and in...
@ End
Always the last item.
@ Custom
Custom currency.
static constexpr TimerGameCalendar::Year CF_NOEURO
Currency never switches to the Euro (as far as known).
EnumBitSet< Currency, uint64_t, Currency::End > Currencies
Bitmask of Currency.
std::vector< Dimension > _resolutions
List of resolutions.
Definition driver.cpp:28
void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, DropDownOptions options, std::string *const persistent_filter_text)
Show a drop down list.
Definition dropdown.cpp:570
std::unique_ptr< DropDownListItem > MakeDropDownListDividerItem()
Creates new DropDownListDividerItem.
Definition dropdown.cpp:36
std::unique_ptr< DropDownListItem > MakeDropDownListStringItem(StringID str, int value, bool masked, bool shaded)
Creates new DropDownListStringItem.
Definition dropdown.cpp:49
Dimension GetDropDownListDimension(const DropDownList &list)
Determine width and height required to fully display a DropDownList.
Definition dropdown.cpp:547
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options, std::string *const persistent_filter_text)
Show a drop down list.
Definition dropdown.cpp:587
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.
@ Filterable
Set if the dropdown is filterable.
#define T
Climate temperate.
Definition engines.h:91
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
Functions related to errors.
@ Info
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
@ Error
Errors (eg. saving/loading failed).
Definition error.h:26
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
Factory to 'query' all available blitters.
@ Baseset
Subdirectory for all base data (base sets, intro game).
Definition fileio_type.h:96
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:88
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.
@ Centre
Align to the centre.
@ End
Align to the end, LTR/RTL aware.
@ Middle
Align to the middle.
bool DrawStringMultiLineWithClipping(int left, int right, int top, int bottom, std::string_view str, ExtendedTextColour colour, Alignment align, bool underline, FontSize fontsize)
Draw a multiline string, possibly over multiple lines, if the region is within the current display cl...
Definition gfx.cpp:872
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:716
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:971
int GetStringLineCount(std::string_view str, int maxw)
Calculates number of lines of string.
Definition gfx.cpp:740
bool _left_button_down
Is left mouse button pressed?
Definition gfx.cpp:42
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:899
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:39
bool _left_button_clicked
Is left mouse button clicked?
Definition gfx.cpp:43
int _gui_scale_cfg
GUI scale in config.
Definition gfx.cpp:65
void GfxFillRect(int left, int top, int right, int bottom, const std::variant< PixelColour, PaletteID > &colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:116
SwitchMode _switch_mode
The next mainloop command.
Definition gfx.cpp:50
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, ExtendedTextColour colour, Alignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:787
int DrawString(int left, int right, int top, std::string_view str, ExtendedTextColour colour, Alignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:668
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
Definition gfx.cpp:1572
bool AdjustGUIZoom(bool automatic)
Resolve GUI zoom level and adjust GUI to new zoom, if auto-suggestion is requested.
Definition gfx.cpp:1836
int _gui_scale
GUI scale, 100 is 100%.
Definition gfx.cpp:64
void CheckBlitter()
Check whether we still use the right blitter, or use another (better) one.
Definition gfxinit.cpp:324
void DrawSpriteIgnorePadding(SpriteID img, PaletteID pal, const Rect &r, Alignment align)
Draw a sprite within a Rect, ignoring the sprite's padding.
Definition widget.cpp:350
@ Small
Index of the small font in the font tables.
Definition gfx_type.h:250
@ Normal
Index of the normal font in the font tables.
Definition gfx_type.h:249
constexpr FontSizes FONTSIZES_ALL
Mask of all possible font sizes.
Definition gfx_type.h:262
Colours
One of 16 base colours used for companies and windows/widgets.
Definition gfx_type.h:283
@ Mauve
Mauve.
Definition gfx_type.h:295
@ Invalid
Invalid marker.
Definition gfx_type.h:302
@ Yellow
Yellow.
Definition gfx_type.h:288
@ DarkBlue
Dark blue.
Definition gfx_type.h:285
@ Orange
Orange.
Definition gfx_type.h:297
@ Grey
Grey.
Definition gfx_type.h:299
@ Green
Green.
Definition gfx_type.h:291
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:315
@ White
White colour.
Definition gfx_type.h:330
@ LightBlue
Light blue colour.
Definition gfx_type.h:331
@ Orange
Orange colour.
Definition gfx_type.h:324
@ Black
Black colour.
Definition gfx_type.h:334
@ Checker
Draw only every second pixel, used for greying-out.
Definition gfx_type.h:393
constexpr NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
Obtain a nested widget (sub)tree from an external source.
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
constexpr NWidgetPart SetResizeWidgetTypeTip(ResizeWidgetType widget_type, StringID tip)
Widget part function for setting the resize widget type and tooltip.
constexpr NWidgetPart SetToolbarMinimalSize(int width)
Widget part function to setting the minimal size for a toolbar button.
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 SetAlternateColourTip(Colours colour, StringID tip)
Widget part function for setting the alternate colour and tooltip.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FontSize::Normal)
Widget part function for setting the minimal text lines.
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:3431
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetTextStyle(TextColour colour, FontSize size=FontSize::Normal)
Widget part function for setting the text style.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=INVALID_WIDGET)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetArrowWidgetTypeTip(ArrowWidgetType widget_type, StringID tip={})
Widget part function for setting the arrow widget type and tooltip.
constexpr NWidgetPart SetAlignment(Alignment align)
Widget part function for setting the alignment of text/images.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
constexpr NWidgetPart SetPIPRatio(uint8_t ratio_pre, uint8_t ratio_inter, uint8_t ratio_post)
Widget part function for setting a pre/inter/post ratio.
void SetDirty() const
Mark entire window as dirty (in need of re-paint).
Definition window.cpp:975
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1553
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:2051
#define Rect
Macro that prevents name conflicts between included headers.
#define Point
Macro that prevents name conflicts between included headers.
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
constexpr To ClampTo(From value)
Clamp the given value down to lie within the requested type.
void ShowQuery(EncodedString &&caption, EncodedString &&message, Window *parent, QueryCallbackProc *callback, bool focus)
Show a confirmation window with standard 'yes' and 'no' buttons The window is aligned to the centre o...
void ShowQueryString(std::string_view str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
Types related to the misc widgets.
@ WID_TF_CAPTION
The caption of the window.
Definition misc_widget.h:53
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:69
Basic functions/variables used all over the place.
Part of the network protocol handling content distribution.
void ShowNetworkContentListWindow(ContentVector *cv=nullptr, ContentType type1=ContentType::End, ContentType type2=ContentType::End)
Show the content list window with a given set of content.
void ShowSurveyResultTextfileWindow(Window *parent)
Show the surver results as a text file.
GUIs related to networking.
Part of the network protocol handling opt-in survey.
@ Length
Vehicle length (trains and road vehicles).
Functions to find and configure NewGRFs.
void ChangeAutosaveFrequency(bool reset)
Reset the interval of the autosave.
Definition openttd.cpp:1310
@ Menu
In the main menu.
Definition openttd.h:19
@ Menu
Switch to game intro menu.
Definition openttd.h:33
PixelColour GetColourGradient(Colours colour, Shade shade)
Get colour gradient palette index.
Definition palette.cpp:393
@ Darker
Darker colour shade.
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.
const void * ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd)
Resolve the underlying object where to dynamically load/save a setting to.
SettingsContainer & GetSettingsTree()
Construct settings tree.
Declarations of classes for handling display of individual configuration settings.
RestrictionMode
How the list of advanced settings is filtered.
@ RM_CHANGED_AGAINST_DEFAULT
Show only settings which are different compared to default values.
@ 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.
@ LeftDepressed
Of a numeric setting entry, the left button is depressed.
@ RightDepressed
Of a numeric setting entry, the right button is depressed.
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.
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition settings.cpp:62
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
static constexpr TextColour GAME_OPTIONS_LABEL
Colour for label text of game options.
static constexpr Colours GAME_OPTIONS_BACKGROUND
Colour for background of game options.
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.
void DrawBoolButton(int x, int y, Colours button_colour, Colours background, bool state, bool clickable)
Draw a toggle button.
void DrawUpDownButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_up, bool clickable_down)
Draw [^][v] buttons.
void ShowBaseSetTextfileWindow(Window *parent, TextfileType file_type, const TBaseSet *baseset, StringID content_type)
Open the BaseSet version of the textfile window.
static WindowDesc _cust_currency_desc(WindowPosition::Center, {}, 0, 0, WindowClass::CustomCurrenty, WindowClass::None, {}, _nested_cust_currency_widgets)
Window definition for the custom currency window.
static const uint32_t _autosave_dropdown_to_minutes[]
Available settings for autosave intervals.
static const int VOLUME_NMARKS
Show 5 values and 4 empty marks.
static std::string GetListLabel(const TBaseSet *baseset)
Get string to use when listing this set in the settings window.
static void AddCustomRefreshRates()
Add the refresh rate from the config and the refresh rates from all the monitors to our list of refre...
static WindowDesc _game_options_desc(WindowPosition::Center, "game_options", 0, 0, WindowClass::GameOptions, WindowClass::None, {}, _nested_game_options_widgets)
Window definition for the game options window.
std::unique_ptr< NWidgetBase > MakeNWidgetSocialPlugins()
Construct nested container widget for managing the list of social plugins.
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
Draw a dropdown button.
static constexpr TextColour GAME_OPTIONS_FRAME
Colour for frame text of game options.
static uint GetCurrentResolutionIndex()
Get index of the current screen resolution.
static constexpr Colours GAME_OPTIONS_BUTTON
Colour for buttons of game options.
static void ShowCustCurrency()
Open custom currency window.
static const int SCALE_NMARKS
Show marks at 25% increments.
static constexpr TextColour GAME_OPTIONS_SELECTED
Colour for selected text of game options.
void ShowGameOptions()
Open the game options window.
Functions for setting GUIs.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
Functions and types used internally for the settings configurations.
@ GuiCurrency
The number represents money, so when reading value multiply by exchange rate.
@ GuiZeroIsSpecial
A value of zero is possible and has a custom string (the one after "strval").
@ GuiDropdown
The value represents a limited number of string-options (internally integer) presented as dropdown.
SettingType
Type of settings for filtering.
@ ST_CLIENT
Client setting.
@ ST_ALL
Used in setting filter to match all types.
@ ST_GAME
Game setting.
@ ST_COMPANY
Company setting.
GameSettings & GetGameSettings()
Get the settings-object applicable for the current situation: the newgame settings when we're in the ...
Types related to the settings widgets.
@ WID_GO_BASE_SFX_OPEN_URL
Open base SFX URL.
@ WID_GO_SETTING_DROPDOWN
Dynamically created dropdown for changing setting value.
@ 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_RESTRICT_DROPDOWN
The drop down box to restrict the list of settings.
@ WID_GO_RESOLUTION_DROPDOWN
Dropdown for the resolution.
@ WID_GO_COLLAPSE_ALL
Collapse all button.
@ 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_FONT_AA_TEXT
Text for anti-alias toggle.
@ WID_GO_RESET_ALL
Reset all button.
@ 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_TAB_ADVANCED
Advanced tab.
@ 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_FILTER
Text filter.
@ WID_GO_BASE_GRF_TEXTFILE
Open base GRF readme, changelog (+1) or license (+2).
@ WID_GO_TAB_GENERAL
General tab.
@ WID_GO_VIDEO_VSYNC_TEXT
Text for video vsync toggle.
@ WID_GO_BASE_GRF_DROPDOWN
Use to select a base GRF.
@ WID_GO_BASE_MUSIC_VOLUME
Change music volume.
@ WID_GO_GUI_FONT_SPRITE_TEXT
Text for sprite font toggle.
@ 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_VIDEO_ACCEL_TEXT
Text for video acceleration toggle.
@ 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_SURVEY_PARTICIPATE_TEXT
Text for automated survey toggle.
@ WID_GO_OPTIONSPANEL
Panel widget containing the option lists.
@ 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_HELP_TEXT_SCROLL
Scrollbar for setting description.
@ WID_GO_SCROLLBAR
Scrollbar.
@ WID_GO_GUI_SCALE_AUTO_TEXT
Text for Autodetect GUI scale.
@ WID_GO_TEXT_MUSIC_VOLUME
Music volume label.
@ WID_GO_GUI_SCALE_BEVEL_TEXT
Text for chunky bevels.
@ WID_GO_BASE_MUSIC_JUKEBOX
Open the jukebox.
@ WID_GO_SOCIAL_PLUGIN_STATE
State of the social plugin.
@ WID_GO_SETTING_PROPERTIES
Information area to display setting type and default value.
@ 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_EXPAND_ALL
Expand all button.
@ 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_RESTRICT_CATEGORY
Label upfront to the category drop-down box to restrict the list of settings to show.
@ WID_GO_VIDEO_ACCEL_BUTTON
Toggle for video acceleration.
@ WID_GO_TAB_SOCIAL
Social tab.
@ WID_GO_FULLSCREEN_TEXT
Text for toggle fullscreen.
@ WID_GO_HELP_TEXT
Information area to display help text of the selected option.
@ 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_TYPE_DROPDOWN
The drop down box to choose client/game/company/all settings.
@ 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_GO_RESTRICT_TYPE
Label upfront to the type drop-down box to restrict the list of settings to show.
@ 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, Colours wedge_colour, Colours handle_colour, TextColour text_colour, 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:34
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:94
Functions related to the horizontal slider widget.
Interface definitions for game to report/respond to social integration.
void SndClickBeep()
Play a beep sound for a click event if enabled in settings.
Definition sound.cpp:254
void ChangeSoundSet(int index)
Change the configured sound set and reset sounds.
Definition sound.cpp:168
Functions related to sound.
static const SpriteID SPR_ARROW_RIGHT
Definition sprites.h:88
static const SpriteID SPR_IMG_MUSIC
Definition sprites.h:1272
static const SpriteID SPR_CIRCLE_FOLDED
(+) icon.
Definition sprites.h:97
static const SpriteID SPR_ARROW_LEFT
Definition sprites.h:87
static const SpriteID SPR_CIRCLE_UNFOLDED
(-) icon.
Definition sprites.h:98
static const SpriteID SPR_ARROW_DOWN
Definition sprites.h:85
static const SpriteID SPR_ARROW_UP
Definition sprites.h:86
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:261
Parse strings.
static std::optional< T > ParseInteger(std::string_view arg, int base=10, bool clamp=false)
Change a string into its number representation.
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.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
void CheckForMissingGlyphs(MissingGlyphSearcher *searcher)
Check whether the currently loaded language pack uses characters that the currently loaded font does ...
Definition strings.cpp:2382
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
std::string_view GetCurrentLanguageIsoCode()
Get the ISO language code of the currently loaded language.
Definition strings.cpp:2299
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
StrongType::Typedef< uint32_t, struct StringIDTag, StrongType::Compare, StrongType::Integer > StringID
Numeric value that represents a string, independent of the selected language.
static constexpr StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames).
@ TD_RTL
Text is written right-to-left by default.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
Window for displaying the textfile of a BaseSet.
const std::string name
Name of the content.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
const StringID content_type
STR_CONTENT_TYPE_xxx for title.
Data structure describing a single setting in a tab.
static Dimension circle_size
Dimension of the circle +/- icon.
static int line_height
Height of a single setting.
uint8_t level
Nesting level of this setting entry.
T y
Y coordinate.
T x
X coordinate.
Specification of a currency.
std::string separator
The thousands separator for this currency.
std::string prefix
Prefix to apply when formatting money in this currency.
TimerGameCalendar::Year to_euro
Year of switching to the Euro. May also be CF_NOEURO or CF_ISEURO.
std::string suffix
Suffix to apply when formatting money in this currency.
std::string code
3 letter untranslated code to identify the currency.
uint16_t rate
The conversion rate compared to the base currency.
StringID name
Translated name of this currency.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string 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 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 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.
Data about how and where to blit pixels.
Definition gfx_type.h:157
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.
void OnResize() override
Called after the window got resized.
SettingFilter filter
Filter for the list.
bool closing_dropdown
True, if the dropdown list is currently closing.
void OnTimeout() override
Called when this window's timeout has been reached.
void OnDropdownClose(Point pt, WidgetID widget, int index, int click_result, bool instant_close) override
A dropdown window associated to this window has been closed.
SettingEntry * valuewindow_entry
If non-nullptr, pointer to setting for which a value-entering window has been opened.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
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.
static int previous_gui_scale
Previous GUI scale.
void OnDropdownSelect(WidgetID widget, int index, int) override
A dropdown option associated to this window has been selected.
SettingEntry * valuedropdown_entry
If non-nullptr, pointer to the value for which a dropdown window is currently opened.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnPaint() override
The window must be repainted.
SettingEntry * clicked_entry
If non-nullptr, pointer to a clicked numeric setting (with a depressed left or right button).
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
QueryString filter_editbox
Filter editbox;.
WarnHiddenResult warn_missing
Whether and how to warn about missing search results.
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 SetDisplayedHelpText(SettingEntry *pe)
Set the entry that should have its help text displayed, and mark the window dirty so it gets repainte...
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
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.
bool manually_changed_folding
Whether the user expanded/collapsed something manually.
SettingEntry * last_clicked
If non-nullptr, pointer to the last clicked setting.
DropDownList BuildDropDownList(WidgetID widget, int *selected_index) const
Build the dropdown list for a specific widget.
void OnInit() override
Notification that the nested widget tree gets initialized.
static GameSettings * settings_ptr
Pointer to the game settings being displayed and modified.
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.
std::tuple< int32_t, uint32_t > GetRange() const
Get the min/max range for the setting.
Definition settings.cpp:502
int32_t GetDefaultValue() const
Get the default value of the setting.
Definition settings.cpp:493
StringID GetHelp() const
Get the help text of the setting.
Definition settings.cpp:461
virtual bool IsBoolSetting() const
Check whether this setting is a boolean type setting.
std::pair< StringParameter, StringParameter > GetValueParams(int32_t value) const
Get parameters for drawing the value of the setting.
Definition settings.cpp:471
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition settings.cpp:593
int32_t interval
the interval to use between settings in the 'settings' window. If interval is '0' the interval is dyn...
Currency currency
Currency we currently use.
Colour for pixel/line drawing.
Definition gfx_type.h:307
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.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
int Width() const
Get width of Rect.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
int Height() const
Get height of Rect.
bool IsEditable(bool do_command=false) const
Check whether the setting is editable in the current gamemode.
Definition settings.cpp:920
SettingFlags flags
Handles how a setting would show up in the GUI (text/currency, etc.).
SettingType GetType() const
Return the type of the setting.
Definition settings.cpp:937
Standard setting.
void SetButtons(SettingEntryFlags new_val)
Set the button-depressed flags (SettingsEntryFlag::LeftDepressed and SettingsEntryFlag::RightDepresse...
uint GetMaxHelpHeight(int maxw) override
Get the biggest height of the help text(s), if the width is at least maxw.
const IntSettingDesc * setting
Setting description 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.
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.
void ResetAll()
Resets all settings to their default values.
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.
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.
Data structure describing one page of settings in the settings window.
bool folded
Sub-page is folded (not visible except for its title).
bool IsEmpty() const
Check whether any filter words were entered.
void SetFilterTerm(std::string_view str)
Set the term to filter on.
std::string_view GetText() const
Get the current text.
Definition textbuf.cpp:284
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:172
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:987
void CloseChildWindows(WindowClass wc=WindowClass::Invalid) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1084
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1112
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1817
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:792
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing).
Definition window.cpp:3258
Window * parent
Parent window.
Definition window_gui.h:328
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:565
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:513
WidgetID mouse_capture_widget
ID of current mouse capture widget (e.g. dragged scrollbar). INVALID_WIDGET if no widget has mouse ca...
Definition window_gui.h:326
ResizeInfo resize
Resize information.
Definition window_gui.h:314
void DisableWidget(WidgetID widget_index)
Sets a widget to disabled.
Definition window_gui.h:391
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:515
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1807
void CloseChildWindowById(WindowClass wc, WindowNumber number) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1099
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:494
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition window_gui.h:491
void SetWidgetsLoweredState(bool lowered_stat, Args... widgets)
Sets the lowered/raised status of a list of widgets.
Definition window_gui.h:526
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:441
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:400
virtual void OnDropdownClose(Point pt, WidgetID widget, int index, int click_result, bool instant_close)
A dropdown window associated to this window has been closed.
Definition window.cpp:293
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition window_gui.h:355
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1841
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:989
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:460
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1831
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:322
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:381
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
@ BaseSounds
The content consists of base sounds.
@ BaseGraphics
The content consists of base graphics.
@ BaseMusic
The content consists of base music.
Stuff related to the text buffer GUI.
@ EnableDefault
enable the 'Default' button ("\0" is returned)
Definition textbuf_gui.h:20
std::optional< std::string > GetTextfile(TextfileType type, Subdirectory dir, std::string_view filename)
Search a textfile file next to the given content.
GUI functions related to textfiles.
TextfileType
Additional text files accompanying Tar archives.
@ Readme
Content readme.
@ ContentBegin
This marker is used to generate the below three buttons in sequence by various of places in the code.
@ ContentEnd
This marker is used to generate the above three buttons in sequence by various of places in the code.
@ License
Content license.
@ 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:308
void SetupWidgetDimensions()
Set up pre-scaled versions of Widget Dimensions.
Definition widget.cpp:98
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_PUSHBTN
Normal push-button (no toggle button) with custom drawing.
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ WWT_PUSHARROWBTN
Normal push-button (no toggle button) with arrow caption.
@ WWT_LABEL
Centered label.
Definition widget_type.h:48
@ NWID_SPACER
Invisible widget that takes some space.
Definition widget_type.h:70
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:62
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:44
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:39
@ WWT_CAPTION
Window caption (window title between closebox and stickybox).
Definition widget_type.h:52
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:76
@ WWT_BOOLBTN
Standard boolean toggle button.
Definition widget_type.h:46
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:68
@ WWT_CLOSEBOX
Close box (at top-left of a window).
Definition widget_type.h:60
@ WWT_FRAME
Frame.
Definition widget_type.h:51
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:37
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window).
Definition widget_type.h:59
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX).
Definition widget_type.h:56
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:61
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:49
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:71
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
@ EqualSize
Containers should keep all their (resizing) children equally large.
@ Decrease
Arrow to the left or in case of RTL to the right.
Definition widget_type.h:20
@ Increase
Arrow to the right or in case of RTL to the left.
Definition widget_type.h:21
@ HideBevel
Bevel of resize box is hidden.
Definition widget_type.h:29
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:1204
void ReInitAllWindows(bool zoom_changed)
Re-initialize all windows.
Definition window.cpp:3435
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1217
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting).
Definition window.cpp:3226
Window functions not directly related to making/drawing windows.
EnumBitSet< FrameFlag, uint8_t > FrameFlags
Bitset of FrameFlag elements.
Definition window_gui.h:32
@ BorderOnly
Draw border only, no background.
Definition window_gui.h:26
@ Lowered
If set the frame is lowered and the background colour brighter (ie. buttons when pressed).
Definition window_gui.h:27
@ Centred
Window is centered and shall stay centered after ReInit.
Definition window_gui.h:234
@ Timeout
Window timeout counter.
Definition window_gui.h:224
@ Center
Center the window.
Definition window_gui.h:147
int WidgetID
Widget ID.
Definition window_type.h:21
@ GameOptions
Game options.
Definition window_type.h:32
Functions related to zooming.