OpenTTD Source 20260206-master-g4d4e37dbf1
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.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
58#include "table/strings.h"
59
61
62#include "safeguards.h"
63
64
65#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
66# define HAS_TRUETYPE_FONT
67#endif
68
69static const StringID _autosave_dropdown[] = {
70 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF,
71 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_10_MINUTES,
72 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_30_MINUTES,
73 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_60_MINUTES,
74 STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_120_MINUTES,
76};
77
79static const uint32_t _autosave_dropdown_to_minutes[] = {
80 0,
81 10,
82 30,
83 60,
84 120,
85};
86
92{
93 auto it = std::ranges::find(_resolutions, Dimension(_screen.width, _screen.height));
94 return std::distance(_resolutions.begin(), it);
95}
96
97static void ShowCustCurrency();
98
100struct BaseSetTextfileWindow : public TextfileWindow {
101 const std::string name;
103
104 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)
105 {
106 this->ConstructWindow();
107 this->LoadTextfile(textfile, BASESET_DIR);
108 }
109
110 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
111 {
112 if (widget == WID_TF_CAPTION) {
113 return GetString(stringid, this->content_type, this->name);
114 }
115
116 return this->Window::GetWidgetString(widget, stringid);
117 }
118};
119
127template <class TBaseSet>
128void ShowBaseSetTextfileWindow(Window *parent, TextfileType file_type, const TBaseSet *baseset, StringID content_type)
129{
130 parent->CloseChildWindowById(WC_TEXTFILE, file_type);
131 new BaseSetTextfileWindow(parent, file_type, baseset->name, *baseset->GetTextfile(file_type), content_type);
132}
133
140template <typename TBaseSet>
141static std::string GetListLabel(const TBaseSet *baseset)
142{
143 if (baseset->GetNumInvalid() == 0) return GetString(STR_JUST_RAW_STRING, baseset->name);
144 return GetString(STR_BASESET_STATUS, baseset->name, baseset->GetNumInvalid());
145}
146
147template <class T>
148DropDownList BuildSetDropDownList(int *selected_index)
149{
150 int n = T::GetNumSets();
151 *selected_index = T::GetIndexOfUsedSet();
152 DropDownList list;
153 for (int i = 0; i < n; i++) {
154 list.push_back(MakeDropDownListStringItem(GetListLabel(T::GetSet(i)), i));
155 }
156 return list;
157}
158
159std::set<int> _refresh_rates = { 30, 60, 75, 90, 100, 120, 144, 240 };
160
166{
167 /* Add the refresh rate as selected in the config. */
168 _refresh_rates.insert(_settings_client.gui.refresh_rate);
169
170 /* Add all the refresh rates of all monitors connected to the machine. */
171 std::vector<int> monitor_rates = VideoDriver::GetInstance()->GetListOfMonitorRefreshRates();
172 std::copy(monitor_rates.begin(), monitor_rates.end(), std::inserter(_refresh_rates, _refresh_rates.end()));
173}
174
175static const int SCALE_NMARKS = (MAX_INTERFACE_SCALE - MIN_INTERFACE_SCALE) / 25 + 1; // Show marks at 25% increments
176static const int VOLUME_NMARKS = 9; // Show 5 values and 4 empty marks.
177
178static std::optional<std::string> ScaleMarkFunc(int, int, int value)
179{
180 /* Label only every 100% mark. */
181 if (value % 100 != 0) return std::string{};
182
183 return GetString(STR_GAME_OPTIONS_GUI_SCALE_MARK, value / 100, 0);
184}
185
186static std::optional<std::string> VolumeMarkFunc(int, int mark, int value)
187{
188 /* Label only every other mark. */
189 if (mark % 2 != 0) return std::string{};
190
191 /* 0-127 does not map nicely to 0-100. Dividing first gives us nice round numbers. */
192 return GetString(STR_GAME_OPTIONS_VOLUME_MARK, value / 31 * 25);
193}
194
196static constexpr Colours GAME_OPTIONS_BACKGROUND = COLOUR_MAUVE;
198static constexpr Colours GAME_OPTIONS_BUTTON = COLOUR_YELLOW;
200static constexpr TextColour GAME_OPTIONS_FRAME = TC_ORANGE;
202static constexpr TextColour GAME_OPTIONS_LABEL = TC_LIGHT_BLUE;
204static constexpr TextColour GAME_OPTIONS_SELECTED = TC_WHITE;
205
206static constexpr std::initializer_list<NWidgetPart> _nested_social_plugins_widgets = {
210 NWidget(WWT_TEXT, INVALID_COLOUR), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM), SetTextStyle(GAME_OPTIONS_LABEL),
212 EndContainer(),
214 NWidget(WWT_TEXT, INVALID_COLOUR), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE), SetTextStyle(GAME_OPTIONS_LABEL),
216 EndContainer(),
217 EndContainer(),
218 EndContainer(),
219};
220
221static constexpr std::initializer_list<NWidgetPart> _nested_social_plugins_none_widgets = {
223 NWidget(WWT_TEXT, INVALID_COLOUR), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE), SetTextStyle(GAME_OPTIONS_LABEL),
224 EndContainer(),
225};
226
227class NWidgetSocialPlugins : public NWidgetVertical {
228public:
229 NWidgetSocialPlugins() : NWidgetVertical({}, WID_GO_SOCIAL_PLUGINS)
230 {
231 this->plugins = SocialIntegration::GetPlugins();
232
233 if (this->plugins.empty()) {
234 auto widget = MakeNWidgets(_nested_social_plugins_none_widgets, nullptr);
235 this->Add(std::move(widget));
236 } else {
237 for (size_t i = 0; i < this->plugins.size(); i++) {
238 auto widget = MakeNWidgets(_nested_social_plugins_widgets, nullptr);
239 this->Add(std::move(widget));
240 }
241 }
242
243 this->SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0);
244 }
245
246 void SetupSmallestSize(Window *w) override
247 {
248 this->current_index = -1;
250 }
251
258 template <typename T>
259 std::string &GetWidestPlugin(T SocialIntegrationPlugin::*member) const
260 {
261 std::string *longest = &(this->plugins[0]->*member);
262 int longest_length = 0;
263
264 for (auto *plugin : this->plugins) {
265 int length = GetStringBoundingBox(plugin->*member).width;
266 if (length > longest_length) {
267 longest_length = length;
268 longest = &(plugin->*member);
269 }
270 }
271
272 return *longest;
273 }
274
275 std::string GetWidgetString(WidgetID widget, StringID) const
276 {
277 switch (widget) {
279 /* For SetupSmallestSize, use the longest string we have. */
280 if (this->current_index < 0) {
282 }
283
284 if (this->plugins[this->current_index]->name.empty()) {
285 return this->plugins[this->current_index]->basepath;
286 }
287
288 return GetString(STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE, this->plugins[this->current_index]->name, this->plugins[this->current_index]->version);
289
291 /* For SetupSmallestSize, use the longest string we have. */
292 if (this->current_index < 0) {
294 }
295
296 return this->plugins[this->current_index]->social_platform;
297
299 static const std::pair<SocialIntegrationPlugin::State, StringID> state_to_string[] = {
300 { SocialIntegrationPlugin::RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_RUNNING },
301 { SocialIntegrationPlugin::FAILED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED },
302 { SocialIntegrationPlugin::PLATFORM_NOT_RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_PLATFORM_NOT_RUNNING },
303 { SocialIntegrationPlugin::UNLOADED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNLOADED },
304 { SocialIntegrationPlugin::DUPLICATE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_DUPLICATE },
305 { SocialIntegrationPlugin::UNSUPPORTED_API, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNSUPPORTED_API },
306 { SocialIntegrationPlugin::INVALID_SIGNATURE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_INVALID_SIGNATURE },
307 };
308
309 /* For SetupSmallestSize, use the longest string we have. */
310 if (this->current_index < 0) {
312
313 /* Set the longest plugin when looking for the longest status. */
314 StringID longest = STR_NULL;
315 int longest_length = 0;
316 for (const auto &[state, string] : state_to_string) {
317 int length = GetStringBoundingBox(GetString(string, longest_plugin)).width;
318 if (length > longest_length) {
319 longest_length = length;
320 longest = string;
321 }
322 }
323
324 return GetString(longest, longest_plugin);
325 }
326
327 const auto plugin = this->plugins[this->current_index];
328
329 /* Find the string for the state. */
330 for (const auto &[state, string] : state_to_string) {
331 if (plugin->state == state) {
332 return GetString(string, plugin->social_platform);
333 }
334 }
335
336 /* Default string, in case no state matches. */
337 return GetString(STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED, plugin->social_platform);
338 }
339
340 default: NOT_REACHED();
341 }
342 }
343
344 void Draw(const Window *w) override
345 {
346 this->current_index = 0;
347
348 for (auto &wid : this->children) {
349 wid->Draw(w);
350 this->current_index++;
351 }
352 }
353
354private:
355 int current_index = -1;
356 std::vector<SocialIntegrationPlugin *> plugins{};
357};
358
360std::unique_ptr<NWidgetBase> MakeNWidgetSocialPlugins()
361{
362 return std::make_unique<NWidgetSocialPlugins>();
363}
364
365static const StringID _game_settings_restrict_dropdown[] = {
366 STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
367 STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
368 STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
369 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
370 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
371};
372static_assert(lengthof(_game_settings_restrict_dropdown) == RM_END);
373
381
387static void ResetAllSettingsConfirmationCallback(Window *w, bool confirmed)
388{
389 if (confirmed) {
392 w->InvalidateData();
393 }
394}
395
396struct GameOptionsWindow : Window {
397 static inline GameSettings *settings_ptr;
398
403 bool closing_dropdown = false;
404
409 int warn_lines = 0;
410
411 Scrollbar *vscroll;
412 Scrollbar *vscroll_description;
413 static constexpr uint NUM_DESCRIPTION_LINES = 5;
414
415 GameSettings *opt = nullptr;
416 bool reload = false;
417 bool gui_scale_changed = false;
418 int gui_scale = 0;
419 static inline int previous_gui_scale = 0;
420 static inline WidgetID active_tab = WID_GO_TAB_GENERAL;
421
422 GameOptionsWindow(WindowDesc &desc) : Window(desc), filter_editbox(50)
423 {
424 this->opt = &GetGameSettings();
425
427
428 this->filter.mode = (RestrictionMode)_settings_client.gui.settings_restriction_mode;
429 this->filter.min_cat = RM_ALL;
430 this->filter.type = ST_ALL;
431 this->filter.type_hides = false;
432 this->settings_ptr = &GetGameSettings();
433
434 GetSettingsTree().FoldAll(); // Close all sub-pages
435
436 this->CreateNestedTree();
437 this->vscroll = this->GetScrollbar(WID_GO_SCROLLBAR);
438 this->vscroll_description = this->GetScrollbar(WID_GO_HELP_TEXT_SCROLL);
439 this->vscroll_description->SetCapacity(NUM_DESCRIPTION_LINES);
441
442 this->querystrings[WID_GO_FILTER] = &this->filter_editbox;
443 this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
444
445 this->OnInvalidateData(0);
446
447 this->SetTab(GameOptionsWindow::active_tab);
448
449 if constexpr (!NetworkSurveyHandler::IsSurveyPossible()) this->GetWidget<NWidgetStacked>(WID_GO_SURVEY_SEL)->SetDisplayedPlane(SZSP_NONE);
450 }
451
452 void OnInit() override
453 {
454 BaseSettingEntry::circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
456
457 this->gui_scale = _gui_scale;
458 }
459
460 void Close([[maybe_unused]] int data = 0) override
461 {
463 if (this->reload) _switch_mode = SM_MENU;
464 this->Window::Close();
465 }
466
473 DropDownList BuildDropDownList(WidgetID widget, int *selected_index) const
474 {
475 DropDownList list;
476 switch (widget) {
477 case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
478 *selected_index = this->opt->locale.currency;
479 uint64_t disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies();
480
481 /* Add non-custom currencies; sorted naturally */
482 for (const CurrencySpec &currency : _currency_specs) {
483 int i = &currency - _currency_specs.data();
484 if (i == CURRENCY_CUSTOM) continue;
485 if (currency.code.empty()) {
486 list.push_back(MakeDropDownListStringItem(currency.name, i, HasBit(disabled, i)));
487 } else {
488 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_CURRENCY_CODE, currency.name, currency.code), i, HasBit(disabled, i)));
489 }
490 }
491 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
492
493 /* Append custom currency at the end */
494 list.push_back(MakeDropDownListDividerItem()); // separator line
495 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM)));
496 break;
497 }
498
499 case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
500 int index = 0;
501 for (auto &minutes : _autosave_dropdown_to_minutes) {
502 index++;
503 if (_settings_client.gui.autosave_interval <= minutes) break;
504 }
505 *selected_index = index - 1;
506
507 const StringID *items = _autosave_dropdown;
508 for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
509 list.push_back(MakeDropDownListStringItem(*items, i));
510 }
511 break;
512 }
513
514 case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
515 for (uint i = 0; i < _languages.size(); i++) {
516 bool hide_language = IsReleasedVersion() && !_languages[i].IsReasonablyFinished();
517 if (hide_language) continue;
518 bool hide_percentage = IsReleasedVersion() || _languages[i].missing < _settings_client.gui.missing_strings_threshold;
519 std::string name;
520 if (&_languages[i] == _current_language) {
521 *selected_index = i;
522 name = _languages[i].own_name;
523 } else {
524 /* Especially with sprite-fonts, not all localized
525 * names can be rendered. So instead, we use the
526 * international names for anything but the current
527 * selected language. This avoids showing a few ????
528 * entries in the dropdown list. */
529 name = _languages[i].name;
530 }
531 if (hide_percentage) {
532 list.push_back(MakeDropDownListStringItem(std::move(name), i));
533 } else {
534 int percentage = (LANGUAGE_TOTAL_STRINGS - _languages[i].missing) * 100 / LANGUAGE_TOTAL_STRINGS;
535 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE, std::move(name), percentage), i));
536 }
537 }
538 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
539 break;
540 }
541
542 case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
543 if (_resolutions.empty()) break;
544
545 *selected_index = GetCurrentResolutionIndex();
546 for (uint i = 0; i < _resolutions.size(); i++) {
547 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_RESOLUTION_ITEM, _resolutions[i].width, _resolutions[i].height), i));
548 }
549 break;
550
551 case WID_GO_REFRESH_RATE_DROPDOWN: // Setup refresh rate dropdown
552 for (auto it = _refresh_rates.begin(); it != _refresh_rates.end(); it++) {
553 auto i = std::distance(_refresh_rates.begin(), it);
554 if (*it == _settings_client.gui.refresh_rate) *selected_index = i;
555 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, *it), i));
556 }
557 break;
558
560 list = BuildSetDropDownList<BaseGraphics>(selected_index);
561 break;
562
564 list = BuildSetDropDownList<BaseSounds>(selected_index);
565 break;
566
568 list = BuildSetDropDownList<BaseMusic>(selected_index);
569 break;
570
572 for (int mode = 0; mode != RM_END; mode++) {
573 /* If we are in adv. settings screen for the new game's settings,
574 * we don't want to allow comparing with new game's settings. */
575 bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
576
577 list.push_back(MakeDropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled));
578 }
579 break;
580
582 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL));
583 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME));
584 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY));
585 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT));
586 break;
587 }
588
589 return list;
590 }
591
592 std::string GetToggleString(StringID stringid, WidgetID state_widget) const
593 {
594 return GetString(STR_GAME_OPTIONS_SETTING, stringid, this->IsWidgetLowered(state_widget) ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
595 }
596
597 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
598 {
599 switch (widget) {
601 const CurrencySpec &currency = _currency_specs[this->opt->locale.currency];
602 if (currency.code.empty()) return GetString(currency.name);
603 return GetString(STR_GAME_OPTIONS_CURRENCY_CODE, currency.name, currency.code);
604 }
605
607 int index = 0;
608 for (auto &minutes : _autosave_dropdown_to_minutes) {
609 index++;
610 if (_settings_client.gui.autosave_interval <= minutes) break;
611 }
612 return GetString(_autosave_dropdown[index - 1]);
613 }
614
615 case WID_GO_LANG_DROPDOWN: return _current_language->own_name;
619 case WID_GO_REFRESH_RATE_DROPDOWN: return GetString(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, _settings_client.gui.refresh_rate);
621 auto current_resolution = GetCurrentResolutionIndex();
622
623 if (current_resolution == _resolutions.size()) {
624 return GetString(STR_GAME_OPTIONS_RESOLUTION_OTHER);
625 }
626 return GetString(STR_GAME_OPTIONS_RESOLUTION_ITEM, _resolutions[current_resolution].width, _resolutions[current_resolution].height);
627 }
628
633 assert(plugin != nullptr);
634
635 return plugin->GetWidgetString(widget, stringid);
636 }
637
639 return GetString(_game_settings_restrict_dropdown[this->filter.mode]);
640
642 switch (this->filter.type) {
643 case ST_GAME: return GetString(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME);
644 case ST_COMPANY: return GetString(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME);
645 case ST_CLIENT: return GetString(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT);
646 default: return GetString(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL);
647 }
648 break;
649
651 return GetToggleString(STR_GAME_OPTIONS_PARTICIPATE_SURVEY, WID_GO_SURVEY_PARTICIPATE_BUTTON);
652
654 return GetToggleString(STR_GAME_OPTIONS_GUI_SCALE_AUTO, WID_GO_GUI_SCALE_AUTO);
655
657 return GetToggleString(STR_GAME_OPTIONS_GUI_SCALE_BEVELS, WID_GO_GUI_SCALE_BEVEL_BUTTON);
658
660 return GetToggleString(STR_GAME_OPTIONS_GUI_FONT_SPRITE, WID_GO_GUI_FONT_SPRITE);
661
663 return GetToggleString(STR_GAME_OPTIONS_GUI_FONT_AA, WID_GO_GUI_FONT_AA);
664
666 return GetToggleString(STR_GAME_OPTIONS_FULLSCREEN, WID_GO_FULLSCREEN_BUTTON);
667
669 return GetToggleString(STR_GAME_OPTIONS_VIDEO_ACCELERATION, WID_GO_VIDEO_ACCEL_BUTTON);
670
672 return GetToggleString(STR_GAME_OPTIONS_VIDEO_VSYNC, WID_GO_VIDEO_VSYNC_BUTTON);
673
674 default:
675 return this->Window::GetWidgetString(widget, stringid);
676 }
677 }
678
679 void DrawWidget(const Rect &r, WidgetID widget) const override
680 {
681 switch (widget) {
684 break;
685
688 break;
689
692 break;
693
694 case WID_GO_GUI_SCALE:
695 DrawSliderWidget(r, GAME_OPTIONS_BACKGROUND, GAME_OPTIONS_BUTTON, TC_BLACK, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, SCALE_NMARKS, this->gui_scale, ScaleMarkFunc);
696 break;
697
699 DrawStringMultiLine(r, GetString(STR_GAME_OPTIONS_VIDEO_DRIVER_INFO, std::string{VideoDriver::GetInstance()->GetInfoString()}), GAME_OPTIONS_SELECTED);
700 break;
701
703 DrawSliderWidget(r, GAME_OPTIONS_BACKGROUND, GAME_OPTIONS_BUTTON, TC_BLACK, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.effect_vol, VolumeMarkFunc);
704 break;
705
707 DrawSliderWidget(r, GAME_OPTIONS_BACKGROUND, GAME_OPTIONS_BUTTON, TC_BLACK, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.music_vol, VolumeMarkFunc);
708 break;
709
710 case WID_GO_OPTIONSPANEL: {
712 tr.top += this->warn_lines * BaseSettingEntry::line_height;
713 uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
714 int next_row = GetSettingsTree().Draw(settings_ptr, tr.left, tr.right, tr.top,
715 this->vscroll->GetPosition(), last_row, this->last_clicked);
716 if (next_row == 0) DrawString(tr, STR_CONFIG_SETTINGS_NONE);
717 break;
718 }
719
721 if (this->last_clicked != nullptr) {
722 const IntSettingDesc *sd = this->last_clicked->setting;
723
724 Rect tr = r;
725 std::string str;
726 switch (sd->GetType()) {
727 case ST_COMPANY: str = GetString(STR_CONFIG_SETTING_TYPE, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_COMPANY_INGAME); break;
728 case ST_CLIENT: str = GetString(STR_CONFIG_SETTING_TYPE, STR_CONFIG_SETTING_TYPE_CLIENT); break;
729 case ST_GAME: str = GetString(STR_CONFIG_SETTING_TYPE, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_GAME_MENU : STR_CONFIG_SETTING_TYPE_GAME_INGAME); break;
730 default: NOT_REACHED();
731 }
732 DrawString(tr, str);
733 tr.top += GetCharacterHeight(FS_NORMAL);
734
735 auto [param1, param2] = sd->GetValueParams(sd->GetDefaultValue());
736 DrawString(tr, GetString(STR_CONFIG_SETTING_DEFAULT_VALUE, param1, param2));
737 }
738 break;
739
740 case WID_GO_HELP_TEXT:
741 if (this->last_clicked != nullptr) {
742 const IntSettingDesc *sd = this->last_clicked->setting;
743
744 DrawPixelInfo tmp_dpi;
745 if (FillDrawPixelInfo(&tmp_dpi, r)) {
746 AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
747 int scrolls_pos = this->vscroll_description->GetPosition() * GetCharacterHeight(FS_NORMAL);
748 DrawStringMultiLine(0, r.Width() - 1, -scrolls_pos, r.Height() - 1, sd->GetHelp(), TC_WHITE);
749 }
750 }
751 break;
752
753 default:
754 break;
755 }
756 }
757
763 {
764 if (this->last_clicked != pe) this->SetDirty();
765 this->last_clicked = pe;
766 UpdateHelpTextSize();
767 }
768
769 void UpdateHelpTextSize()
770 {
772 this->vscroll_description->SetCount(this->last_clicked ? CeilDiv(this->last_clicked->GetMaxHelpHeight(wid->current_x), GetCharacterHeight(FS_NORMAL)) : 0);
773 }
774
775 void SetTab(WidgetID widget)
776 {
778 this->LowerWidget(widget);
779 GameOptionsWindow::active_tab = widget;
780
781 int plane;
782 switch (widget) {
783 case WID_GO_TAB_GENERAL: plane = 0; break;
784 case WID_GO_TAB_GRAPHICS: plane = 1; break;
785 case WID_GO_TAB_SOUND: plane = 2; break;
786 case WID_GO_TAB_SOCIAL: plane = 3; break;
787 case WID_GO_TAB_ADVANCED: plane = 4; break;
788 default: NOT_REACHED();
789 }
790
791 this->GetWidget<NWidgetStacked>(WID_GO_TAB_SELECTION)->SetDisplayedPlane(plane);
793 this->SetDirty();
794 }
795
796 void OnResize() override
797 {
798 this->vscroll->SetCapacityFromWidget(this, WID_GO_OPTIONSPANEL, WidgetDimensions::scaled.framerect.Vertical());
799 UpdateHelpTextSize();
800
801 bool changed = false;
802
804 int y = 0;
805 for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
806 std::string str = GetString(STR_JUST_RAW_STRING, BaseGraphics::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
807 y = std::max(y, GetStringHeight(str, wid->current_x));
808 }
809 changed |= wid->UpdateVerticalSize(y);
810
812 y = 0;
813 for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
814 std::string str = GetString(STR_JUST_RAW_STRING, BaseSounds::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
815 y = std::max(y, GetStringHeight(str, wid->current_x));
816 }
817 changed |= wid->UpdateVerticalSize(y);
818
820 y = 0;
821 for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
822 std::string str = GetString(STR_JUST_RAW_STRING, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
823 y = std::max(y, GetStringHeight(str, wid->current_x));
824 }
825 changed |= wid->UpdateVerticalSize(y);
826
828 std::string str = GetString(STR_GAME_OPTIONS_VIDEO_DRIVER_INFO, std::string{VideoDriver::GetInstance()->GetInfoString()});
829 y = GetStringHeight(str, wid->current_x);
830 changed |= wid->UpdateVerticalSize(y);
831
832 if (changed) this->ReInit(0, 0, this->flags.Test(WindowFlag::Centred));
833 }
834
835 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
836 {
837 switch (widget) {
840 Dimension d = maxdim(GetStringBoundingBox(STR_GAME_OPTIONS_SFX_VOLUME), GetStringBoundingBox(STR_GAME_OPTIONS_MUSIC_VOLUME));
841 d.width += padding.width;
842 d.height += padding.height;
843 size = maxdim(size, d);
844 break;
845 }
846
855 int selected;
856 size.width = std::max(size.width, GetDropDownListDimension(this->BuildDropDownList(widget, &selected)).width + padding.width);
857 break;
858 }
859
861 fill.height = resize.height = BaseSettingEntry::line_height;
862 resize.width = 1;
863
864 size.height = 8 * resize.height + WidgetDimensions::scaled.framerect.Vertical();
865 break;
866
868 static const StringID setting_types[] = {
869 STR_CONFIG_SETTING_TYPE_CLIENT,
870 STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
871 STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
872 };
873 for (const auto &setting_type : setting_types) {
874 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_CONFIG_SETTING_TYPE, setting_type)).width + padding.width);
875 }
876 size.height = 2 * GetCharacterHeight(FS_NORMAL);
877 break;
878 }
879
880 case WID_GO_HELP_TEXT:
881 size.height = NUM_DESCRIPTION_LINES * GetCharacterHeight(FS_NORMAL);
882 break;
883
886 size.width = std::max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
887 break;
888
889 default:
890 break;
891 }
892 }
893
894 void OnPaint() override
895 {
896 if (GameOptionsWindow::active_tab != WID_GO_TAB_ADVANCED) {
897 this->DrawWidgets();
898 return;
899 }
900
901 if (this->closing_dropdown) {
902 this->closing_dropdown = false;
903 assert(this->valuedropdown_entry != nullptr);
904 this->valuedropdown_entry->SetButtons({});
905 this->valuedropdown_entry = nullptr;
906 }
907
908 /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
909 const Rect panel = this->GetWidget<NWidgetBase>(WID_GO_OPTIONSPANEL)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext);
910 StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
911 int new_warn_lines;
912 if (this->warn_missing == WHR_NONE) {
913 new_warn_lines = 0;
914 } else {
915 new_warn_lines = GetStringLineCount(GetString(warn_str, _game_settings_restrict_dropdown[this->filter.min_cat]), panel.Width());
916 }
917 if (this->warn_lines != new_warn_lines) {
918 this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
919 this->warn_lines = new_warn_lines;
920 }
921
922 this->DrawWidgets();
923
924 /* Draw the 'some search results are hidden' notice. */
925 if (this->warn_missing != WHR_NONE) {
927 GetString(warn_str, _game_settings_restrict_dropdown[this->filter.min_cat]),
928 TC_BLACK, SA_CENTER);
929 }
930 }
931
932 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
933 {
934 if (widget >= WID_GO_BASE_GRF_TEXTFILE && widget < WID_GO_BASE_GRF_TEXTFILE + TFT_CONTENT_END) {
935 if (BaseGraphics::GetUsedSet() == nullptr) return;
936
937 ShowBaseSetTextfileWindow(this, (TextfileType)(widget - WID_GO_BASE_GRF_TEXTFILE), BaseGraphics::GetUsedSet(), STR_CONTENT_TYPE_BASE_GRAPHICS);
938 return;
939 }
940 if (widget >= WID_GO_BASE_SFX_TEXTFILE && widget < WID_GO_BASE_SFX_TEXTFILE + TFT_CONTENT_END) {
941 if (BaseSounds::GetUsedSet() == nullptr) return;
942
943 ShowBaseSetTextfileWindow(this, (TextfileType)(widget - WID_GO_BASE_SFX_TEXTFILE), BaseSounds::GetUsedSet(), STR_CONTENT_TYPE_BASE_SOUNDS);
944 return;
945 }
946 if (widget >= WID_GO_BASE_MUSIC_TEXTFILE && widget < WID_GO_BASE_MUSIC_TEXTFILE + TFT_CONTENT_END) {
947 if (BaseMusic::GetUsedSet() == nullptr) return;
948
949 ShowBaseSetTextfileWindow(this, (TextfileType)(widget - WID_GO_BASE_MUSIC_TEXTFILE), BaseMusic::GetUsedSet(), STR_CONTENT_TYPE_BASE_MUSIC);
950 return;
951 }
952 switch (widget) {
955 case WID_GO_TAB_SOUND:
958 SndClickBeep();
959 this->SetTab(widget);
960 break;
961
963 switch (_settings_client.network.participate_survey) {
964 case ParticipateSurvey::Ask:
965 case ParticipateSurvey::No:
966 _settings_client.network.participate_survey = ParticipateSurvey::Yes;
967 break;
968
969 case ParticipateSurvey::Yes:
970 _settings_client.network.participate_survey = ParticipateSurvey::No;
971 break;
972 }
973
974 this->SetWidgetLoweredState(WID_GO_SURVEY_PARTICIPATE_BUTTON, _settings_client.network.participate_survey == ParticipateSurvey::Yes);
977 break;
978
980 OpenBrowser(NETWORK_SURVEY_DETAILS_LINK);
981 break;
982
984 ShowSurveyResultTextfileWindow(this);
985 break;
986
987 case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
988 /* try to toggle full-screen on/off */
989 if (!ToggleFullScreen(!_fullscreen)) {
990 ShowErrorMessage(GetEncodedString(STR_ERROR_FULLSCREEN_FAILED), {}, WL_ERROR);
991 }
995 break;
996
999 ShowErrorMessage(GetEncodedString(STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART), {}, WL_INFO);
1003#ifndef __APPLE__
1008#endif
1009 break;
1010
1012 if (!_video_hw_accel) break;
1013
1016
1022 break;
1023
1025 _settings_client.gui.scale_bevels = !_settings_client.gui.scale_bevels;
1026
1028 this->SetDirty();
1029
1031 ReInitAllWindows(true);
1032 break;
1033 }
1034
1035#ifdef HAS_TRUETYPE_FONT
1037 _fcsettings.prefer_sprite = !_fcsettings.prefer_sprite;
1038
1039 this->SetWidgetLoweredState(WID_GO_GUI_FONT_SPRITE, _fcsettings.prefer_sprite);
1040 this->SetWidgetDisabledState(WID_GO_GUI_FONT_AA, _fcsettings.prefer_sprite);
1041 this->SetDirty();
1042
1048 ReInitAllWindows(true);
1049 break;
1050
1051 case WID_GO_GUI_FONT_AA:
1052 _fcsettings.global_aa = !_fcsettings.global_aa;
1053
1054 this->SetWidgetLoweredState(WID_GO_GUI_FONT_AA, _fcsettings.global_aa);
1056
1058 break;
1059#endif /* HAS_TRUETYPE_FONT */
1060
1061 case WID_GO_GUI_SCALE:
1062 /* Any click on the slider deactivates automatic interface scaling, setting it to the current value before being adjusted. */
1063 if (_gui_scale_cfg == -1) {
1064 _gui_scale_cfg = this->gui_scale;
1068 }
1069
1070 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, _ctrl_pressed ? 0 : SCALE_NMARKS, this->gui_scale)) {
1071 this->gui_scale_changed = true;
1072 this->SetWidgetDirty(widget);
1073 }
1074
1075 if (click_count > 0) this->mouse_capture_widget = widget;
1076 break;
1077
1079 {
1080 if (_gui_scale_cfg == -1) {
1081 _gui_scale_cfg = this->previous_gui_scale; // Load the previous GUI scale
1083 if (AdjustGUIZoom(false)) ReInitAllWindows(true);
1084 this->gui_scale = _gui_scale;
1085 } else {
1086 this->previous_gui_scale = _gui_scale; // Set the previous GUI scale value as the current one
1087 _gui_scale_cfg = -1;
1089 if (AdjustGUIZoom(false)) ReInitAllWindows(true);
1090 this->gui_scale = _gui_scale;
1091 }
1092 this->SetWidgetDirty(widget);
1094 break;
1095 }
1096
1098 auto *used_set = BaseGraphics::GetUsedSet();
1099 if (used_set == nullptr || !used_set->IsConfigurable()) break;
1100 GRFConfig &extra_cfg = used_set->GetOrCreateExtraConfig();
1101 if (extra_cfg.param.empty()) extra_cfg.SetParameterDefaults();
1102 OpenGRFParameterWindow(true, extra_cfg, _game_mode == GM_MENU);
1103 if (_game_mode == GM_MENU) this->reload = true;
1104 break;
1105 }
1106
1109 uint8_t &vol = (widget == WID_GO_BASE_MUSIC_VOLUME) ? _settings_client.music.music_vol : _settings_client.music.effect_vol;
1110 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, 0, INT8_MAX, 0, vol)) {
1111 if (widget == WID_GO_BASE_MUSIC_VOLUME) {
1113 } else {
1114 SetEffectVolume(vol);
1115 }
1116 this->SetWidgetDirty(widget);
1118 }
1119
1120 if (click_count > 0) this->mouse_capture_widget = widget;
1121 break;
1122 }
1123
1125 ShowMusicWindow();
1126 break;
1127 }
1128
1130 if (BaseGraphics::GetUsedSet() == nullptr || BaseGraphics::GetUsedSet()->url.empty()) return;
1131 OpenBrowser(BaseGraphics::GetUsedSet()->url);
1132 break;
1133
1135 if (BaseSounds::GetUsedSet() == nullptr || BaseSounds::GetUsedSet()->url.empty()) return;
1136 OpenBrowser(BaseSounds::GetUsedSet()->url);
1137 break;
1138
1140 if (BaseMusic::GetUsedSet() == nullptr || BaseMusic::GetUsedSet()->url.empty()) return;
1141 OpenBrowser(BaseMusic::GetUsedSet()->url);
1142 break;
1143
1146 break;
1147
1150 break;
1151
1154 break;
1155
1164 int selected;
1165 DropDownList list = this->BuildDropDownList(widget, &selected);
1166 if (!list.empty()) {
1167 ShowDropDownList(this, std::move(list), selected, widget);
1168 } else {
1169 if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(GetEncodedString(STR_ERROR_RESOLUTION_LIST_FAILED), {}, WL_ERROR);
1170 }
1171 break;
1172 }
1173
1174 case WID_GO_EXPAND_ALL:
1175 this->manually_changed_folding = true;
1177 this->InvalidateData();
1178 break;
1179
1181 this->manually_changed_folding = true;
1183 this->InvalidateData();
1184 break;
1185
1186 case WID_GO_RESET_ALL:
1187 ShowQuery(
1188 GetEncodedString(STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION),
1189 GetEncodedString(STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT),
1190 this,
1192 );
1193 break;
1194
1196 int selected;
1197 DropDownList list = this->BuildDropDownList(widget, &selected);
1198 if (!list.empty()) {
1199 ShowDropDownList(this, std::move(list), this->filter.mode, widget);
1200 }
1201 break;
1202 }
1203
1204 case WID_GO_TYPE_DROPDOWN: {
1205 int selected;
1206 DropDownList list = this->BuildDropDownList(widget, &selected);
1207 if (!list.empty()) {
1208 ShowDropDownList(this, std::move(list), this->filter.type, widget);
1209 }
1210 break;
1211 }
1212
1214 OptionsPanelClick(pt);
1215 break;
1216 }
1217 }
1218
1219 void OptionsPanelClick(Point pt)
1220 {
1221 int32_t btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GO_OPTIONSPANEL, WidgetDimensions::scaled.framerect.top);
1222 if (btn == INT32_MAX || btn < this->warn_lines) return;
1223 btn -= this->warn_lines;
1224
1225 uint cur_row = 0;
1227
1228 if (clicked_entry == nullptr) return; // Clicked below the last setting of the page
1229
1231 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
1232 if (x < 0) return; // Clicked left of the entry
1233
1234 SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
1235 if (clicked_page != nullptr) {
1236 this->SetDisplayedHelpText(nullptr);
1237 clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
1238
1239 this->manually_changed_folding = true;
1240
1241 this->InvalidateData();
1242 return;
1243 }
1244
1245 SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
1246 assert(pe != nullptr);
1247 const IntSettingDesc *sd = pe->setting;
1248
1249 /* return if action is only active in network, or only settable by server */
1250 if (!sd->IsEditable()) {
1251 this->SetDisplayedHelpText(pe);
1252 return;
1253 }
1254
1255 auto [min_val, max_val] = sd->GetRange();
1256 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
1257
1258 /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
1259 if (x < SETTING_BUTTON_WIDTH && sd->flags.Test(SettingFlag::GuiDropdown)) {
1260 this->SetDisplayedHelpText(pe);
1261
1262 if (this->valuedropdown_entry == pe) {
1263 /* unclick the dropdown */
1265 this->closing_dropdown = false;
1266 this->valuedropdown_entry->SetButtons({});
1267 this->valuedropdown_entry = nullptr;
1268 } else {
1269 if (this->valuedropdown_entry != nullptr) this->valuedropdown_entry->SetButtons({});
1270 this->closing_dropdown = false;
1271
1272 int rel_y = (pt.y - wid->pos_y - WidgetDimensions::scaled.framerect.top) % wid->resize_y;
1273
1274 Rect wi_rect;
1275 wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
1276 wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
1277 wi_rect.top = pt.y - rel_y + (BaseSettingEntry::line_height - SETTING_BUTTON_HEIGHT) / 2;
1278 wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
1279
1280 /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
1281 if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
1282 this->valuedropdown_entry = pe;
1284
1285 DropDownList list;
1286 for (int32_t i = min_val; i <= static_cast<int32_t>(max_val); i++) {
1287 auto [param1, param2] = sd->GetValueParams(i);
1288 list.push_back(MakeDropDownListStringItem(GetString(STR_JUST_STRING1, param1, param2), i));
1289 }
1290
1291 ShowDropDownListAt(this, std::move(list), value, WID_GO_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);
1292 }
1293 }
1294 this->SetDirty();
1295 } else if (x < SETTING_BUTTON_WIDTH) {
1296 this->SetDisplayedHelpText(pe);
1297 int32_t oldvalue = value;
1298
1299 if (sd->IsBoolSetting()) {
1300 value ^= 1;
1301 } else {
1302 /* Add a dynamic step-size to the scroller. In a maximum of
1303 * 50-steps you should be able to get from min to max,
1304 * unless specified otherwise in the 'interval' variable
1305 * of the current setting. */
1306 uint32_t step = (sd->interval == 0) ? ((max_val - min_val) / 50) : sd->interval;
1307 if (step == 0) step = 1;
1308
1309 /* don't allow too fast scrolling */
1310 if (this->flags.Test(WindowFlag::Timeout) && this->timeout_timer > 1) {
1311 _left_button_clicked = false;
1312 return;
1313 }
1314
1315 /* Increase or decrease the value and clamp it to extremes */
1316 if (x >= SETTING_BUTTON_WIDTH / 2) {
1317 value += step;
1318 if (min_val < 0) {
1319 assert(static_cast<int32_t>(max_val) >= 0);
1320 if (value > static_cast<int32_t>(max_val)) value = static_cast<int32_t>(max_val);
1321 } else {
1322 if (static_cast<uint32_t>(value) > max_val) value = static_cast<int32_t>(max_val);
1323 }
1324 if (value < min_val) value = min_val; // skip between "disabled" and minimum
1325 } else {
1326 value -= step;
1327 if (value < min_val) value = sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val;
1328 }
1329
1330 /* Set up scroller timeout for numeric values */
1331 if (value != oldvalue) {
1332 if (this->clicked_entry != nullptr) { // Release previous buttons if any
1333 this->clicked_entry->SetButtons({});
1334 }
1335 this->clicked_entry = pe;
1337 this->SetTimeout();
1338 _left_button_clicked = false;
1339 }
1340 }
1341
1342 if (value != oldvalue) {
1343 SetSettingValue(sd, value);
1344 this->SetDirty();
1345 }
1346 } else {
1347 /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
1348 if (this->last_clicked == pe && !sd->IsBoolSetting() && !sd->flags.Test(SettingFlag::GuiDropdown)) {
1349 int64_t value64 = value;
1350 /* Show the correct currency-translated value */
1351 if (sd->flags.Test(SettingFlag::GuiCurrency)) value64 *= GetCurrency().rate;
1352
1353 CharSetFilter charset_filter = CS_NUMERAL; //default, only numeric input allowed
1354 if (min_val < 0) charset_filter = CS_NUMERAL_SIGNED; // special case, also allow '-' sign for negative input
1355
1356 this->valuewindow_entry = pe;
1357 /* Limit string length to 14 so that MAX_INT32 * max currency rate doesn't exceed MAX_INT64. */
1358 ShowQueryString(GetString(STR_JUST_INT, value64), STR_CONFIG_SETTING_QUERY_CAPTION, 15, this, charset_filter, QueryStringFlag::EnableDefault);
1359 }
1360 this->SetDisplayedHelpText(pe);
1361 }
1362 }
1363
1364 void OnTimeout() override
1365 {
1366 if (this->clicked_entry != nullptr) { // On timeout, release any depressed buttons
1367 this->clicked_entry->SetButtons({});
1368 this->clicked_entry = nullptr;
1369 this->SetDirty();
1370 }
1371 }
1372
1373 void OnQueryTextFinished(std::optional<std::string> str) override
1374 {
1375 /* The user pressed cancel */
1376 if (!str.has_value()) return;
1377
1378 assert(this->valuewindow_entry != nullptr);
1379 const IntSettingDesc *sd = this->valuewindow_entry->setting;
1380
1381 int32_t value;
1382 if (!str->empty()) {
1383 auto llvalue = ParseInteger<int64_t>(*str, 10, true);
1384 if (!llvalue.has_value()) return;
1385
1386 /* Save the correct currency-translated value */
1387 if (sd->flags.Test(SettingFlag::GuiCurrency)) llvalue = *llvalue / GetCurrency().rate;
1388
1389 value = ClampTo<int32_t>(*llvalue);
1390 } else {
1391 value = sd->GetDefaultValue();
1392 }
1393
1394 SetSettingValue(this->valuewindow_entry->setting, value);
1395 this->SetDirty();
1396 }
1397
1398 void OnMouseLoop() override
1399 {
1400 if (_left_button_down || !this->gui_scale_changed) return;
1401
1402 this->gui_scale_changed = false;
1403 _gui_scale_cfg = this->gui_scale;
1404
1405 if (AdjustGUIZoom(false)) {
1406 ReInitAllWindows(true);
1408 this->SetDirty();
1409 }
1410 }
1411
1412 void OnDropdownSelect(WidgetID widget, int index, int) override
1413 {
1414 switch (widget) {
1415 case WID_GO_CURRENCY_DROPDOWN: // Currency
1416 if (index == CURRENCY_CUSTOM) ShowCustCurrency();
1417 this->opt->locale.currency = index;
1418 ReInitAllWindows(false);
1419 break;
1420
1421 case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
1422 _settings_client.gui.autosave_interval = _autosave_dropdown_to_minutes[index];
1424 this->SetDirty();
1425 break;
1426
1427 case WID_GO_LANG_DROPDOWN: // Change interface language
1431 ClearAllCachedNames();
1433 CheckBlitter();
1434 ReInitAllWindows(false);
1435 break;
1436
1437 case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
1438 if ((uint)index < _resolutions.size() && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
1439 this->SetDirty();
1440 }
1441 break;
1442
1444 _settings_client.gui.refresh_rate = *std::next(_refresh_rates.begin(), index);
1445 if (_settings_client.gui.refresh_rate > 60) {
1446 /* Show warning to the user that this refresh rate might not be suitable on
1447 * larger maps with many NewGRFs and vehicles. */
1448 ShowErrorMessage(GetEncodedString(STR_GAME_OPTIONS_REFRESH_RATE_WARNING), {}, WL_INFO);
1449 }
1450 break;
1451 }
1452
1454 if (_game_mode == GM_MENU) {
1456 auto set = BaseGraphics::GetSet(index);
1458 this->reload = true;
1459 this->InvalidateData();
1460 }
1461 break;
1462
1464 ChangeSoundSet(index);
1465 break;
1466
1468 ChangeMusicSet(index);
1469 break;
1470
1472 this->filter.mode = (RestrictionMode)index;
1473 if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
1474 this->filter.mode == RM_CHANGED_AGAINST_NEW) {
1475
1476 if (!this->manually_changed_folding) {
1477 /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
1478 GetSettingsTree().UpdateFilterState(this->filter, false);
1480 }
1481 } else {
1482 /* Non-'changes' filter. Save as default. */
1483 _settings_client.gui.settings_restriction_mode = this->filter.mode;
1484 }
1485 this->InvalidateData();
1486 break;
1487
1489 this->filter.type = (SettingType)index;
1490 this->InvalidateData();
1491 break;
1492
1494 /* Deal with drop down boxes on the panel. */
1495 assert(this->valuedropdown_entry != nullptr);
1496 const IntSettingDesc *sd = this->valuedropdown_entry->setting;
1497 assert(sd->flags.Test(SettingFlag::GuiDropdown));
1498
1499 SetSettingValue(sd, index);
1500 this->SetDirty();
1501 break;
1502 }
1503 }
1504
1505 void OnDropdownClose(Point pt, WidgetID widget, int index, int click_result, bool instant_close) override
1506 {
1507 if (widget != WID_GO_SETTING_DROPDOWN) {
1508 /* Normally the default implementation of OnDropdownClose() takes care of
1509 * a few things. We want that behaviour here too, but only for
1510 * "normal" dropdown boxes. The special dropdown boxes added for every
1511 * setting that needs one can't have this call. */
1512 Window::OnDropdownClose(pt, widget, index, click_result, instant_close);
1513 } else {
1514 /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
1515 * the same dropdown button was clicked again, and then not open the dropdown again.
1516 * So, we only remember that it was closed, and process it on the next OnPaint, which is
1517 * after OnClick. */
1518 assert(this->valuedropdown_entry != nullptr);
1519 this->closing_dropdown = true;
1520 this->SetDirty();
1521 }
1522 }
1523
1529 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1530 {
1531 if (!gui_scope) return;
1532 this->SetWidgetLoweredState(WID_GO_SURVEY_PARTICIPATE_BUTTON, _settings_client.network.participate_survey == ParticipateSurvey::Yes);
1536
1537#ifndef __APPLE__
1540#endif
1541
1544#ifdef HAS_TRUETYPE_FONT
1545 this->SetWidgetLoweredState(WID_GO_GUI_FONT_SPRITE, _fcsettings.prefer_sprite);
1546 this->SetWidgetLoweredState(WID_GO_GUI_FONT_AA, _fcsettings.global_aa);
1547 this->SetWidgetDisabledState(WID_GO_GUI_FONT_AA, _fcsettings.prefer_sprite);
1548#endif /* HAS_TRUETYPE_FONT */
1549
1550 this->SetWidgetDisabledState(WID_GO_BASE_GRF_DROPDOWN, _game_mode != GM_MENU);
1551
1553
1557
1558 for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
1562 }
1563
1565
1566 /* Update which settings are to be visible. */
1567 RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
1568 this->filter.min_cat = min_level;
1569 this->filter.type_hides = false;
1570 GetSettingsTree().UpdateFilterState(this->filter, false);
1571
1572 if (this->filter.string.IsEmpty()) {
1573 this->warn_missing = WHR_NONE;
1574 } else if (min_level < this->filter.min_cat) {
1575 this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
1576 } else {
1577 this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
1578 }
1579 this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
1580
1581 if (this->last_clicked != nullptr && !GetSettingsTree().IsVisible(this->last_clicked)) {
1582 this->SetDisplayedHelpText(nullptr);
1583 }
1584
1585 bool all_folded = true;
1586 bool all_unfolded = true;
1587 GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
1588 this->SetWidgetDisabledState(WID_GO_EXPAND_ALL, all_unfolded);
1590 }
1591
1592 void OnEditboxChanged(WidgetID wid) override
1593 {
1594 if (wid == WID_GO_FILTER) {
1595 this->filter.string.SetFilterTerm(this->filter_editbox.text.GetText());
1596 if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
1597 /* User never expanded/collapsed single pages and entered a filter term.
1598 * Expand everything, to save weird expand clicks, */
1600 }
1601 this->InvalidateData();
1602 }
1603 }
1604};
1605
1606static constexpr std::initializer_list<NWidgetPart> _nested_game_options_widgets = {
1609 NWidget(WWT_CAPTION, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1611 EndContainer(),
1614 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),
1615 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),
1616 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),
1617 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),
1618 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),
1619 EndContainer(),
1620 EndContainer(),
1623 /* General tab */
1627 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_LANG_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1628 EndContainer(),
1629
1631 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_AUTOSAVE_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1632 EndContainer(),
1633
1634 NWidget(WWT_FRAME, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME), SetTextStyle(GAME_OPTIONS_FRAME),
1635 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_CURRENCY_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1636 EndContainer(),
1637
1638 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GO_SURVEY_SEL),
1639 NWidget(WWT_FRAME, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_FRAME), SetTextStyle(GAME_OPTIONS_FRAME), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1643 EndContainer(),
1645 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),
1646 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),
1647 EndContainer(),
1648 EndContainer(),
1649 EndContainer(),
1650 EndContainer(),
1651 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1652 EndContainer(),
1653
1654 /* Graphics tab */
1660 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_GAME_OPTIONS_GUI_SCALE_FRAME), SetTextStyle(GAME_OPTIONS_LABEL),
1661 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_GUI_SCALE), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FS_SMALL), SetFill(1, 0), SetResize(1, 0), SetToolTip(STR_GAME_OPTIONS_GUI_SCALE_TOOLTIP),
1662 EndContainer(),
1666 EndContainer(),
1670 EndContainer(),
1671#ifdef HAS_TRUETYPE_FONT
1675 EndContainer(),
1679 EndContainer(),
1680#endif /* HAS_TRUETYPE_FONT */
1681 EndContainer(),
1682 EndContainer(),
1683
1687 NWidget(WWT_TEXT, INVALID_COLOUR), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_RESOLUTION), SetTextStyle(GAME_OPTIONS_LABEL),
1688 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_RESOLUTION_DROPDOWN), SetFill(1, 0), SetToolTip(STR_GAME_OPTIONS_RESOLUTION_TOOLTIP),
1689 EndContainer(),
1691 NWidget(WWT_TEXT, INVALID_COLOUR), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_REFRESH_RATE), SetTextStyle(GAME_OPTIONS_LABEL),
1692 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_REFRESH_RATE_DROPDOWN), SetFill(1, 0), SetToolTip(STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP),
1693 EndContainer(),
1697 EndContainer(),
1701 EndContainer(),
1702#ifndef __APPLE__
1706 EndContainer(),
1707#endif
1709 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_VIDEO_DRIVER_INFO), SetMinimalTextLines(1, 0), SetFill(1, 0), SetResize(1, 0),
1710 EndContainer(),
1711 EndContainer(),
1712 EndContainer(),
1713
1716 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_BASE_GRF_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1718 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1719 EndContainer(),
1720 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_BASE_GRF_DESCRIPTION), SetStringTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1723 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),
1724 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1725 EndContainer(),
1727 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1728 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1729 EndContainer(),
1730 EndContainer(),
1731 EndContainer(),
1732 EndContainer(),
1733 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1734 EndContainer(),
1735
1736 /* Sound/Music tab */
1741 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_TEXT_SFX_VOLUME), SetStringTip(STR_GAME_OPTIONS_SFX_VOLUME), SetTextStyle(GAME_OPTIONS_LABEL),
1742 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_BASE_SFX_VOLUME), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FS_SMALL), SetFill(1, 0), SetResize(1, 0), SetToolTip(STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
1743 EndContainer(),
1745 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_TEXT_MUSIC_VOLUME), SetStringTip(STR_GAME_OPTIONS_MUSIC_VOLUME), SetTextStyle(GAME_OPTIONS_LABEL),
1746 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_BASE_MUSIC_VOLUME), SetMinimalTextLines(1, 12 + WidgetDimensions::unscaled.vsep_normal, FS_SMALL), SetFill(1, 0), SetResize(1, 0), SetToolTip(STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
1747 EndContainer(),
1748 EndContainer(),
1749
1752 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_BASE_SFX_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1753 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1754 EndContainer(),
1755 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_BASE_SFX_DESCRIPTION), SetMinimalTextLines(1, 0), SetToolTip(STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1758 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),
1759 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1760 EndContainer(),
1762 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1763 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1764 EndContainer(),
1765 EndContainer(),
1766 EndContainer(),
1767
1770 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1771 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1772 EndContainer(),
1774 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_BASE_MUSIC_DESCRIPTION), SetMinimalTextLines(1, 0), SetToolTip(STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1776 NWidget(WWT_PUSHIMGBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_JUKEBOX), SetToolbarMinimalSize(1), SetSpriteTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
1777 EndContainer(),
1778 EndContainer(),
1781 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),
1782 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_README, STR_TEXTFILE_VIEW_README_TOOLTIP),
1783 EndContainer(),
1785 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP),
1786 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TEXTFILE_VIEW_LICENCE, STR_TEXTFILE_VIEW_LICENCE_TOOLTIP),
1787 EndContainer(),
1788 EndContainer(),
1789 EndContainer(),
1790 EndContainer(),
1791 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1792 EndContainer(),
1793
1794 /* Social tab */
1797 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1798 EndContainer(),
1799
1800 /* Advanced settings tab */
1804 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_RESTRICT_CATEGORY), SetStringTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY), SetTextStyle(GAME_OPTIONS_LABEL),
1805 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_RESTRICT_DROPDOWN), SetToolTip(STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
1806 EndContainer(),
1808 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_RESTRICT_TYPE), SetStringTip(STR_CONFIG_SETTING_RESTRICT_TYPE), SetTextStyle(GAME_OPTIONS_LABEL),
1809 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_TYPE_DROPDOWN), SetToolTip(STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
1810 EndContainer(),
1812 NWidget(WWT_TEXT, INVALID_COLOUR), SetFill(0, 1), SetStringTip(STR_CONFIG_SETTING_FILTER_TITLE), SetTextStyle(GAME_OPTIONS_LABEL),
1813 NWidget(WWT_EDITBOX, GAME_OPTIONS_BACKGROUND, WID_GO_FILTER), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1814 EndContainer(),
1815 EndContainer(),
1816
1819 EndContainer(),
1821 EndContainer(),
1822
1824 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_EXPAND_ALL), SetStringTip(STR_CONFIG_SETTING_EXPAND_ALL), SetFill(1, 0), SetResize(1, 0),
1825 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_COLLAPSE_ALL), SetStringTip(STR_CONFIG_SETTING_COLLAPSE_ALL), SetFill(1, 0), SetResize(1, 0),
1826 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_RESET_ALL), SetStringTip(STR_CONFIG_SETTING_RESET_ALL), SetFill(1, 0), SetResize(1, 0),
1827 EndContainer(),
1828
1829 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_SETTING_PROPERTIES), SetFill(1, 0), SetResize(1, 0),
1833 EndContainer(),
1834 EndContainer(),
1835 EndContainer(),
1836
1838 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1840 EndContainer(),
1841 EndContainer(),
1842};
1843
1844static WindowDesc _game_options_desc(
1845 WDP_CENTER, "game_options", 0, 0,
1847 {},
1848 _nested_game_options_widgets
1849);
1850
1853{
1855 new GameOptionsWindow(_game_options_desc);
1856}
1857
1867void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
1868{
1869 PixelColour colour = GetColourGradient(button_colour, SHADE_DARKER);
1870 Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
1871
1872 Rect lr = {x, y, x + (int)dim.width - 1, y + (int)dim.height - 1};
1873 Rect rr = {x + (int)dim.width, y, x + (int)dim.width * 2 - 1, y + (int)dim.height - 1};
1874
1875 DrawFrameRect(lr, button_colour, (state == 1) ? FrameFlag::Lowered : FrameFlags{});
1876 DrawFrameRect(rr, button_colour, (state == 2) ? FrameFlag::Lowered : FrameFlags{});
1877 DrawSpriteIgnorePadding(SPR_ARROW_LEFT, PAL_NONE, lr, SA_CENTER);
1878 DrawSpriteIgnorePadding(SPR_ARROW_RIGHT, PAL_NONE, rr, SA_CENTER);
1879
1880 /* Grey out the buttons that aren't clickable */
1881 bool rtl = _current_text_dir == TD_RTL;
1882 if (rtl ? !clickable_right : !clickable_left) {
1884 }
1885 if (rtl ? !clickable_left : !clickable_right) {
1887 }
1888}
1889
1899void DrawUpDownButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_up, bool clickable_down)
1900{
1901 PixelColour colour = GetColourGradient(button_colour, SHADE_DARKER);
1902
1903 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
1906
1907 DrawFrameRect(ur, button_colour, (state == 1) ? FrameFlag::Lowered : FrameFlags{});
1908 DrawFrameRect(dr, button_colour, (state == 2) ? FrameFlag::Lowered : FrameFlags{});
1909 DrawSpriteIgnorePadding(SPR_ARROW_UP, PAL_NONE, ur, SA_CENTER);
1910 DrawSpriteIgnorePadding(SPR_ARROW_DOWN, PAL_NONE, dr, SA_CENTER);
1911
1912 /* Grey out the buttons that aren't clickable */
1913 if (!clickable_up) GfxFillRect(ur.Shrink(WidgetDimensions::scaled.bevel), colour, FILLRECT_CHECKER);
1914 if (!clickable_down) GfxFillRect(dr.Shrink(WidgetDimensions::scaled.bevel), colour, FILLRECT_CHECKER);
1915}
1916
1925void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
1926{
1927 PixelColour colour = GetColourGradient(button_colour, SHADE_DARKER);
1928
1929 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
1930
1931 DrawFrameRect(r, button_colour, state ? FrameFlag::Lowered : FrameFlags{});
1932 DrawSpriteIgnorePadding(SPR_ARROW_DOWN, PAL_NONE, r, SA_CENTER);
1933
1934 if (!clickable) {
1936 }
1937}
1938
1948void DrawBoolButton(int x, int y, Colours button_colour, Colours background, bool state, bool clickable)
1949{
1950 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
1951 DrawFrameRect(r, state ? COLOUR_GREEN : background, state ? FrameFlags{FrameFlag::Lowered} : FrameFlags{FrameFlag::Lowered, FrameFlag::BorderOnly});
1952 if (!clickable) {
1953 GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(state ? COLOUR_GREEN : background, SHADE_DARKER), FILLRECT_CHECKER);
1954 }
1955
1956 Rect button_rect = r.WithWidth(SETTING_BUTTON_WIDTH / 3, state ^ (_current_text_dir == TD_RTL));
1957 DrawFrameRect(button_rect, button_colour, {});
1958 if (!clickable) {
1959 GfxFillRect(button_rect.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(button_colour, SHADE_DARKER), FILLRECT_CHECKER);
1960 }
1961}
1962
1963struct CustomCurrencyWindow : Window {
1964 WidgetID query_widget{};
1965
1966 CustomCurrencyWindow(WindowDesc &desc) : Window(desc)
1967 {
1968 this->InitNested();
1969
1970 SetButtonState();
1971 }
1972
1973 void SetButtonState()
1974 {
1976 this->SetWidgetDisabledState(WID_CC_RATE_UP, GetCustomCurrency().rate == UINT16_MAX);
1979 }
1980
1981 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1982 {
1983 switch (widget) {
1984 case WID_CC_RATE: return GetString(STR_CURRENCY_EXCHANGE_RATE, 1, 1);
1985 case WID_CC_SEPARATOR: return GetString(STR_CURRENCY_SEPARATOR, GetCustomCurrency().separator);
1986 case WID_CC_PREFIX: return GetString(STR_CURRENCY_PREFIX, GetCustomCurrency().prefix);
1987 case WID_CC_SUFFIX: return GetString(STR_CURRENCY_SUFFIX, GetCustomCurrency().suffix);
1988 case WID_CC_YEAR:
1989 return GetString((GetCustomCurrency().to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER, GetCustomCurrency().to_euro);
1990
1991 case WID_CC_PREVIEW:
1992 return GetString(STR_CURRENCY_PREVIEW, 10000);
1993
1994 default:
1995 return this->Window::GetWidgetString(widget, stringid);
1996 }
1997 }
1998
1999 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
2000 {
2001 switch (widget) {
2002 /* Set the appropriate width for the up/down buttons. */
2003 case WID_CC_RATE_DOWN:
2004 case WID_CC_RATE_UP:
2005 case WID_CC_YEAR_DOWN:
2006 case WID_CC_YEAR_UP:
2007 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH / 2, (uint)SETTING_BUTTON_HEIGHT});
2008 break;
2009
2010 /* Set the appropriate width for the edit buttons. */
2012 case WID_CC_PREFIX_EDIT:
2013 case WID_CC_SUFFIX_EDIT:
2014 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH, (uint)SETTING_BUTTON_HEIGHT});
2015 break;
2016
2017 /* Make sure the window is wide enough for the widest exchange rate */
2018 case WID_CC_RATE:
2019 size = GetStringBoundingBox(GetString(STR_CURRENCY_EXCHANGE_RATE, 1, INT32_MAX));
2020 break;
2021 }
2022 }
2023
2024 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2025 {
2026 int line = 0;
2027 int len = 0;
2028 std::string str;
2030
2031 switch (widget) {
2032 case WID_CC_RATE_DOWN:
2033 if (GetCustomCurrency().rate > 1) GetCustomCurrency().rate--;
2034 if (GetCustomCurrency().rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2036 break;
2037
2038 case WID_CC_RATE_UP:
2039 if (GetCustomCurrency().rate < UINT16_MAX) GetCustomCurrency().rate++;
2040 if (GetCustomCurrency().rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2042 break;
2043
2044 case WID_CC_RATE:
2045 str = GetString(STR_JUST_INT, GetCustomCurrency().rate);
2046 len = 5;
2047 line = WID_CC_RATE;
2048 afilter = CS_NUMERAL;
2049 break;
2050
2052 case WID_CC_SEPARATOR:
2054 len = 7;
2055 line = WID_CC_SEPARATOR;
2056 break;
2057
2058 case WID_CC_PREFIX_EDIT:
2059 case WID_CC_PREFIX:
2060 str = GetCustomCurrency().prefix;
2061 len = 15;
2062 line = WID_CC_PREFIX;
2063 break;
2064
2065 case WID_CC_SUFFIX_EDIT:
2066 case WID_CC_SUFFIX:
2067 str = GetCustomCurrency().suffix;
2068 len = 15;
2069 line = WID_CC_SUFFIX;
2070 break;
2071
2072 case WID_CC_YEAR_DOWN:
2076 break;
2077
2078 case WID_CC_YEAR_UP:
2082 break;
2083
2084 case WID_CC_YEAR:
2085 str = GetString(STR_JUST_INT, GetCustomCurrency().to_euro);
2086 len = 7;
2087 line = WID_CC_YEAR;
2088 afilter = CS_NUMERAL;
2089 break;
2090 }
2091
2092 if (len != 0) {
2093 this->query_widget = line;
2094 ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, {});
2095 }
2096
2097 this->SetTimeout();
2098 this->SetDirty();
2099 }
2100
2101 void OnQueryTextFinished(std::optional<std::string> str) override
2102 {
2103 if (!str.has_value()) return;
2104
2105 switch (this->query_widget) {
2106 case WID_CC_RATE: {
2107 auto val = ParseInteger(*str, 10, true);
2108 if (!val.has_value()) return;
2109 GetCustomCurrency().rate = Clamp(*val, 1, UINT16_MAX);
2110 break;
2111 }
2112
2113 case WID_CC_SEPARATOR: // Thousands separator
2114 GetCustomCurrency().separator = std::move(*str);
2115 break;
2116
2117 case WID_CC_PREFIX:
2118 GetCustomCurrency().prefix = std::move(*str);
2119 break;
2120
2121 case WID_CC_SUFFIX:
2122 GetCustomCurrency().suffix = std::move(*str);
2123 break;
2124
2125 case WID_CC_YEAR: { // Year to switch to euro
2126 TimerGameCalendar::Year year = CF_NOEURO;
2127 if (!str->empty()) {
2128 auto val = ParseInteger(*str, 10, true);
2129 if (!val.has_value()) return;
2130 year = Clamp(static_cast<TimerGameCalendar::Year>(*val), MIN_EURO_YEAR, CalendarTime::MAX_YEAR);
2131 }
2132 GetCustomCurrency().to_euro = year;
2133 break;
2134 }
2135 }
2137 SetButtonState();
2138 }
2139
2140 void OnTimeout() override
2141 {
2142 this->SetDirty();
2143 }
2144};
2145
2146static constexpr std::initializer_list<NWidgetPart> _nested_cust_currency_widgets = {
2148 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2149 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2150 EndContainer(),
2151 NWidget(WWT_PANEL, COLOUR_GREY),
2156 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetArrowWidgetTypeTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
2157 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetArrowWidgetTypeTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
2158 EndContainer(),
2159 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_RATE), SetToolTip(STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2160 EndContainer(),
2162 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2163 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_SEPARATOR), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2164 EndContainer(),
2166 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2167 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_PREFIX), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2168 EndContainer(),
2170 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2171 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_SUFFIX), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2172 EndContainer(),
2175 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetArrowWidgetTypeTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2176 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetArrowWidgetTypeTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2177 EndContainer(),
2178 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_YEAR), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2179 EndContainer(),
2180 EndContainer(),
2181 NWidget(WWT_LABEL, INVALID_COLOUR, WID_CC_PREVIEW),
2182 SetToolTip(STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP),
2183 EndContainer(),
2184 EndContainer(),
2185};
2186
2187static WindowDesc _cust_currency_desc(
2188 WDP_CENTER, {}, 0, 0,
2190 {},
2191 _nested_cust_currency_widgets
2192);
2193
2195static void ShowCustCurrency()
2196{
2198 new CustomCurrencyWindow(_cust_currency_desc);
2199}
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 HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
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)
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:1293
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:1509
Base class for a resizable nested widget.
bool UpdateVerticalSize(uint min_y)
Set absolute (post-scaling) minimal size of the widget.
Definition widget.cpp:1121
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:1719
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:2426
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:2500
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
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:40
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:93
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
uint64_t GetMaskOfAllowedCurrencies()
get a mask of the allowed currencies depending on the year
Definition currency.cpp:128
std::array< CurrencySpec, CURRENCY_END > _currency_specs
Array of currencies used by the system.
Definition currency.cpp:80
Functions to handle different currencies.
static constexpr TimerGameCalendar::Year MIN_EURO_YEAR
The earliest year custom currencies may switch to the Euro.
Definition currency.h:19
@ CURRENCY_CUSTOM
Custom currency.
Definition currency.h:58
CurrencySpec & GetCustomCurrency()
Get the custom currency.
Definition currency.h:110
static constexpr TimerGameCalendar::Year CF_NOEURO
Currency never switches to the Euro (as far as known).
Definition currency.h:17
const CurrencySpec & GetCurrency()
Get the currently selected currency.
Definition currency.h:119
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)
Show a drop down list.
Definition dropdown.cpp:403
Dimension GetDropDownListDimension(const DropDownList &list)
Determine width and height required to fully display a DropDownList.
Definition dropdown.cpp:381
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options)
Show a drop down list.
Definition dropdown.cpp:419
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.
Functions related to errors.
@ WL_ERROR
Errors (eg. saving/loading failed).
Definition error.h:26
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
Factory to 'query' all available blitters.
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game).
Definition fileio_type.h:96
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:87
Functions to read fonts from files and cache them.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:717
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:972
int GetStringLineCount(std::string_view str, int maxw)
Calculates number of lines of string.
Definition gfx.cpp:741
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:900
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:669
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
bool DrawStringMultiLineWithClipping(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment 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:873
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:788
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
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:1573
bool AdjustGUIZoom(bool automatic)
Resolve GUI zoom level and adjust GUI to new zoom, if auto-suggestion is requested.
Definition gfx.cpp:1837
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:325
@ FS_SMALL
Index of the small font in the font tables.
Definition gfx_type.h:250
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:249
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:390
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:398
constexpr FontSizes FONTSIZES_ALL
Mask of all possible font sizes.
Definition gfx_type.h:262
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:307
@ FILLRECT_CHECKER
Draw only every second pixel, used for greying-out.
Definition gfx_type.h:346
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 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 SetTextStyle(TextColour colour, FontSize size=FS_NORMAL)
Widget part function for setting the text style.
constexpr NWidgetPart SetResizeWidgetTypeTip(ResizeWidgetValues widget_type, StringID tip)
Widget part function for setting the resize widget type and tooltip.
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:3375
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetArrowWidgetTypeTip(ArrowWidgetValues widget_type, StringID tip={})
Widget part function for setting the arrow widget type and tooltip.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=INVALID_WIDGET)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetAlignment(StringAlignment align)
Widget part function for setting the alignment of text/images.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
constexpr NWidgetPart SetPIPRatio(uint8_t ratio_pre, uint8_t ratio_inter, uint8_t ratio_post)
Widget part function for setting a pre/inter/post ratio.
void SetDirty() const
Mark entire window as dirty (in need of re-paint).
Definition window.cpp:969
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1554
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:2054
#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.
@ 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:68
Basic functions/variables used all over the place.
Part of the network protocol handling content distribution.
void ShowNetworkContentListWindow(ContentVector *cv=nullptr, ContentType type1=CONTENT_TYPE_END, ContentType type2=CONTENT_TYPE_END)
Show the content list window with a given set of content.
GUIs related to networking.
Part of the network protocol handling opt-in survey.
@ Length
Vehicle length (trains and road vehicles).
Functions to find and configure NewGRFs.
void ChangeAutosaveFrequency(bool reset)
Reset the interval of the autosave.
Definition openttd.cpp:1315
@ SM_MENU
Switch to game intro menu.
Definition openttd.h:33
PixelColour GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:388
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.
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 const uint32_t _autosave_dropdown_to_minutes[]
Available settings for autosave intervals.
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...
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 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 ...
@ 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:253
void ChangeSoundSet(int index)
Change the configured sound set and reset sounds.
Definition sound.cpp:167
Functions related to sound.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
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:2396
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:2303
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames).
@ TD_RTL
Text is written right-to-left by default.
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.
Definition currency.h:77
std::string separator
The thousands separator for this currency.
Definition currency.h:79
std::string prefix
Prefix to apply when formatting money in this currency.
Definition currency.h:81
TimerGameCalendar::Year to_euro
Year of switching to the Euro. May also be CF_NOEURO or CF_ISEURO.
Definition currency.h:80
std::string suffix
Suffix to apply when formatting money in this currency.
Definition currency.h:82
std::string code
3 letter untranslated code to identify the currency.
Definition currency.h:83
uint16_t rate
The conversion rate compared to the base currency.
Definition currency.h:78
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:473
int32_t GetDefaultValue() const
Get the default value of the setting.
Definition settings.cpp:464
StringID GetHelp() const
Get the help text of the setting.
Definition settings.cpp:433
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:442
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition settings.cpp:564
int32_t interval
the interval to use between settings in the 'settings' window. If interval is '0' the interval is dyn...
uint8_t currency
currency we currently use
Colour for pixel/line drawing.
Definition gfx_type.h:405
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:891
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:908
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:168
Data structure for an opened window.
Definition window_gui.h:274
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:981
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1106
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1812
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:321
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:766
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing).
Definition window.cpp:3250
Window * parent
Parent window.
Definition window_gui.h:329
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:559
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:507
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:327
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1078
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void DisableWidget(WidgetID widget_index)
Sets a widget to disabled.
Definition window_gui.h:392
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:516
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1802
void CloseChildWindowById(WindowClass wc, WindowNumber number) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1093
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:488
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition window_gui.h:492
void SetWidgetsLoweredState(bool lowered_stat, Args... widgets)
Sets the lowered/raised status of a list of widgets.
Definition window_gui.h:527
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:401
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:287
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition window_gui.h:356
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1835
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:986
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:461
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1825
WindowFlags flags
Window flags.
Definition window_gui.h:301
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:316
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
int height
Height of the window (number of pixels down in y direction).
Definition window_gui.h:313
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:312
@ CONTENT_TYPE_BASE_SOUNDS
The content consists of base sounds.
@ CONTENT_TYPE_BASE_GRAPHICS
The content consists of base graphics.
@ CONTENT_TYPE_BASE_MUSIC
The content consists of base music.
Stuff related to the text buffer GUI.
@ 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.
@ TFT_LICENSE
Content license.
@ TFT_README
Content readme.
@ TFT_CHANGELOG
Content changelog.
Base of the town class.
bool _video_vsync
Whether we should use vsync (only if active video driver supports HW acceleration).
bool _video_hw_accel
Whether to consider hardware accelerated video drivers on startup.
Base of all video drivers.
Functions related to (drawing on) viewports.
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition widget.cpp:289
void SetupWidgetDimensions()
Set up pre-scaled versions of Widget Dimensions.
Definition widget.cpp:80
@ 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.
@ AWV_DECREASE
Arrow to the left or in case of RTL to the right.
Definition widget_type.h:20
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition widget_type.h:21
@ RWV_HIDE_BEVEL
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:1198
void ReInitAllWindows(bool zoom_changed)
Re-initialize all windows.
Definition window.cpp:3427
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1211
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting).
Definition window.cpp:3218
Window functions not directly related to making/drawing windows.
@ 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:237
@ Timeout
Window timeout counter.
Definition window_gui.h:227
@ WDP_CENTER
Center the window.
Definition window_gui.h:145
int WidgetID
Widget ID.
Definition window_type.h:20
@ WN_GAME_OPTIONS_GAME_OPTIONS
Game options.
Definition window_type.h:31
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:50
@ WC_MUSIC_WINDOW
Music window; Window numbers:
@ WC_CUSTOM_CURRENCY
Custom currency; Window numbers:
@ WC_GAME_OPTIONS
Game options window; Window numbers:
@ WC_TEXTFILE
textfile; Window numbers:
@ WC_DROPDOWN_MENU
Drop down menu; Window numbers:
@ WC_QUERY_STRING
Query string window; Window numbers:
@ WC_GRF_PARAMETERS
NewGRF parameters; Window numbers:
Functions related to zooming.