OpenTTD Source 20251213-master-g1091fa6071
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
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
101 const std::string name;
103
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
126template <class TBaseSet>
127void ShowBaseSetTextfileWindow(Window *parent, TextfileType file_type, const TBaseSet *baseset, StringID content_type)
128{
129 parent->CloseChildWindowById(WC_TEXTFILE, file_type);
130 new BaseSetTextfileWindow(parent, file_type, baseset->name, *baseset->GetTextfile(file_type), content_type);
131}
132
139template <typename TBaseSet>
140static std::string GetListLabel(const TBaseSet *baseset)
141{
142 if (baseset->GetNumInvalid() == 0) return GetString(STR_JUST_RAW_STRING, baseset->name);
143 return GetString(STR_BASESET_STATUS, baseset->name, baseset->GetNumInvalid());
144}
145
146template <class T>
147DropDownList BuildSetDropDownList(int *selected_index)
148{
149 int n = T::GetNumSets();
150 *selected_index = T::GetIndexOfUsedSet();
151 DropDownList list;
152 for (int i = 0; i < n; i++) {
153 list.push_back(MakeDropDownListStringItem(GetListLabel(T::GetSet(i)), i));
154 }
155 return list;
156}
157
158std::set<int> _refresh_rates = { 30, 60, 75, 90, 100, 120, 144, 240 };
159
165{
166 /* Add the refresh rate as selected in the config. */
167 _refresh_rates.insert(_settings_client.gui.refresh_rate);
168
169 /* Add all the refresh rates of all monitors connected to the machine. */
170 std::vector<int> monitor_rates = VideoDriver::GetInstance()->GetListOfMonitorRefreshRates();
171 std::copy(monitor_rates.begin(), monitor_rates.end(), std::inserter(_refresh_rates, _refresh_rates.end()));
172}
173
174static const int SCALE_NMARKS = (MAX_INTERFACE_SCALE - MIN_INTERFACE_SCALE) / 25 + 1; // Show marks at 25% increments
175static const int VOLUME_NMARKS = 9; // Show 5 values and 4 empty marks.
176
177static std::optional<std::string> ScaleMarkFunc(int, int, int value)
178{
179 /* Label only every 100% mark. */
180 if (value % 100 != 0) return std::string{};
181
182 return GetString(STR_GAME_OPTIONS_GUI_SCALE_MARK, value / 100, 0);
183}
184
185static std::optional<std::string> VolumeMarkFunc(int, int mark, int value)
186{
187 /* Label only every other mark. */
188 if (mark % 2 != 0) return std::string{};
189
190 /* 0-127 does not map nicely to 0-100. Dividing first gives us nice round numbers. */
191 return GetString(STR_GAME_OPTIONS_VOLUME_MARK, value / 31 * 25);
192}
193
195static constexpr Colours GAME_OPTIONS_BACKGROUND = COLOUR_MAUVE;
197static constexpr Colours GAME_OPTIONS_BUTTON = COLOUR_YELLOW;
199static constexpr TextColour GAME_OPTIONS_FRAME = TC_ORANGE;
201static constexpr TextColour GAME_OPTIONS_LABEL = TC_LIGHT_BLUE;
203static constexpr TextColour GAME_OPTIONS_SELECTED = TC_WHITE;
204
205static constexpr std::initializer_list<NWidgetPart> _nested_social_plugins_widgets = {
209 NWidget(WWT_TEXT, INVALID_COLOUR), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM), SetTextStyle(GAME_OPTIONS_LABEL),
211 EndContainer(),
213 NWidget(WWT_TEXT, INVALID_COLOUR), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE), SetTextStyle(GAME_OPTIONS_LABEL),
215 EndContainer(),
216 EndContainer(),
217 EndContainer(),
218};
219
220static constexpr std::initializer_list<NWidgetPart> _nested_social_plugins_none_widgets = {
222 NWidget(WWT_TEXT, INVALID_COLOUR), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE), SetTextStyle(GAME_OPTIONS_LABEL),
223 EndContainer(),
224};
225
227public:
229 {
230 this->plugins = SocialIntegration::GetPlugins();
231
232 if (this->plugins.empty()) {
233 auto widget = MakeNWidgets(_nested_social_plugins_none_widgets, nullptr);
234 this->Add(std::move(widget));
235 } else {
236 for (size_t i = 0; i < this->plugins.size(); i++) {
237 auto widget = MakeNWidgets(_nested_social_plugins_widgets, nullptr);
238 this->Add(std::move(widget));
239 }
240 }
241
242 this->SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0);
243 }
244
245 void SetupSmallestSize(Window *w) override
246 {
247 this->current_index = -1;
249 }
250
257 template <typename T>
258 std::string &GetWidestPlugin(T SocialIntegrationPlugin::*member) const
259 {
260 std::string *longest = &(this->plugins[0]->*member);
261 int longest_length = 0;
262
263 for (auto *plugin : this->plugins) {
264 int length = GetStringBoundingBox(plugin->*member).width;
265 if (length > longest_length) {
266 longest_length = length;
267 longest = &(plugin->*member);
268 }
269 }
270
271 return *longest;
272 }
273
274 std::string GetWidgetString(WidgetID widget, StringID) const
275 {
276 switch (widget) {
278 /* For SetupSmallestSize, use the longest string we have. */
279 if (this->current_index < 0) {
281 }
282
283 if (this->plugins[this->current_index]->name.empty()) {
284 return this->plugins[this->current_index]->basepath;
285 }
286
287 return GetString(STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE, this->plugins[this->current_index]->name, this->plugins[this->current_index]->version);
288
290 /* For SetupSmallestSize, use the longest string we have. */
291 if (this->current_index < 0) {
293 }
294
295 return this->plugins[this->current_index]->social_platform;
296
298 static const std::pair<SocialIntegrationPlugin::State, StringID> state_to_string[] = {
299 { SocialIntegrationPlugin::RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_RUNNING },
300 { SocialIntegrationPlugin::FAILED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED },
301 { SocialIntegrationPlugin::PLATFORM_NOT_RUNNING, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_PLATFORM_NOT_RUNNING },
302 { SocialIntegrationPlugin::UNLOADED, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNLOADED },
303 { SocialIntegrationPlugin::DUPLICATE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_DUPLICATE },
304 { SocialIntegrationPlugin::UNSUPPORTED_API, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_UNSUPPORTED_API },
305 { SocialIntegrationPlugin::INVALID_SIGNATURE, STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_INVALID_SIGNATURE },
306 };
307
308 /* For SetupSmallestSize, use the longest string we have. */
309 if (this->current_index < 0) {
311
312 /* Set the longest plugin when looking for the longest status. */
313 StringID longest = STR_NULL;
314 int longest_length = 0;
315 for (const auto &[state, string] : state_to_string) {
316 int length = GetStringBoundingBox(GetString(string, longest_plugin)).width;
317 if (length > longest_length) {
318 longest_length = length;
319 longest = string;
320 }
321 }
322
323 return GetString(longest, longest_plugin);
324 }
325
326 const auto plugin = this->plugins[this->current_index];
327
328 /* Find the string for the state. */
329 for (const auto &[state, string] : state_to_string) {
330 if (plugin->state == state) {
331 return GetString(string, plugin->social_platform);
332 }
333 }
334
335 /* Default string, in case no state matches. */
336 return GetString(STR_GAME_OPTIONS_SOCIAL_PLUGIN_STATE_FAILED, plugin->social_platform);
337 }
338
339 default: NOT_REACHED();
340 }
341 }
342
343 void Draw(const Window *w) override
344 {
345 this->current_index = 0;
346
347 for (auto &wid : this->children) {
348 wid->Draw(w);
349 this->current_index++;
350 }
351 }
352
353private:
354 int current_index = -1;
355 std::vector<SocialIntegrationPlugin *> plugins{};
356};
357
359std::unique_ptr<NWidgetBase> MakeNWidgetSocialPlugins()
360{
361 return std::make_unique<NWidgetSocialPlugins>();
362}
363
364static const StringID _game_settings_restrict_dropdown[] = {
365 STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
366 STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
367 STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
368 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
369 STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
370};
371static_assert(lengthof(_game_settings_restrict_dropdown) == RM_END);
372
380
386static void ResetAllSettingsConfirmationCallback(Window *w, bool confirmed)
387{
388 if (confirmed) {
391 w->InvalidateData();
392 }
393}
394
396 static inline GameSettings *settings_ptr;
397
402 bool closing_dropdown = false;
403
408 int warn_lines = 0;
409
410 Scrollbar *vscroll;
411 Scrollbar *vscroll_description;
412 static constexpr uint NUM_DESCRIPTION_LINES = 5;
413
414 GameSettings *opt = nullptr;
415 bool reload = false;
416 bool gui_scale_changed = false;
417 int gui_scale = 0;
418 static inline int previous_gui_scale = 0;
419 static inline WidgetID active_tab = WID_GO_TAB_GENERAL;
420
422 {
423 this->opt = &GetGameSettings();
424
426
428 this->filter.min_cat = RM_ALL;
429 this->filter.type = ST_ALL;
430 this->filter.type_hides = false;
431 this->settings_ptr = &GetGameSettings();
432
433 GetSettingsTree().FoldAll(); // Close all sub-pages
434
435 this->CreateNestedTree();
436 this->vscroll = this->GetScrollbar(WID_GO_SCROLLBAR);
437 this->vscroll_description = this->GetScrollbar(WID_GO_HELP_TEXT_SCROLL);
438 this->vscroll_description->SetCapacity(NUM_DESCRIPTION_LINES);
440
442 this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
443
444 this->OnInvalidateData(0);
445
446 this->SetTab(GameOptionsWindow::active_tab);
447
448 if constexpr (!NetworkSurveyHandler::IsSurveyPossible()) this->GetWidget<NWidgetStacked>(WID_GO_SURVEY_SEL)->SetDisplayedPlane(SZSP_NONE);
449 }
450
451 void OnInit() override
452 {
453 BaseSettingEntry::circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
455
456 this->gui_scale = _gui_scale;
457 }
458
459 void Close([[maybe_unused]] int data = 0) override
460 {
462 if (this->reload) _switch_mode = SM_MENU;
463 this->Window::Close();
464 }
465
472 DropDownList BuildDropDownList(WidgetID widget, int *selected_index) const
473 {
474 DropDownList list;
475 switch (widget) {
476 case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
477 *selected_index = this->opt->locale.currency;
478 uint64_t disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies();
479
480 /* Add non-custom currencies; sorted naturally */
481 for (const CurrencySpec &currency : _currency_specs) {
482 int i = &currency - _currency_specs.data();
483 if (i == CURRENCY_CUSTOM) continue;
484 if (currency.code.empty()) {
485 list.push_back(MakeDropDownListStringItem(currency.name, i, HasBit(disabled, i)));
486 } else {
487 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_CURRENCY_CODE, currency.name, currency.code), i, HasBit(disabled, i)));
488 }
489 }
490 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
491
492 /* Append custom currency at the end */
493 list.push_back(MakeDropDownListDividerItem()); // separator line
494 list.push_back(MakeDropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM)));
495 break;
496 }
497
498 case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
499 int index = 0;
500 for (auto &minutes : _autosave_dropdown_to_minutes) {
501 index++;
502 if (_settings_client.gui.autosave_interval <= minutes) break;
503 }
504 *selected_index = index - 1;
505
506 const StringID *items = _autosave_dropdown;
507 for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
508 list.push_back(MakeDropDownListStringItem(*items, i));
509 }
510 break;
511 }
512
513 case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
514 for (uint i = 0; i < _languages.size(); i++) {
515 bool hide_language = IsReleasedVersion() && !_languages[i].IsReasonablyFinished();
516 if (hide_language) continue;
517 bool hide_percentage = IsReleasedVersion() || _languages[i].missing < _settings_client.gui.missing_strings_threshold;
518 std::string name;
519 if (&_languages[i] == _current_language) {
520 *selected_index = i;
521 name = _languages[i].own_name;
522 } else {
523 /* Especially with sprite-fonts, not all localized
524 * names can be rendered. So instead, we use the
525 * international names for anything but the current
526 * selected language. This avoids showing a few ????
527 * entries in the dropdown list. */
528 name = _languages[i].name;
529 }
530 if (hide_percentage) {
531 list.push_back(MakeDropDownListStringItem(std::move(name), i));
532 } else {
533 int percentage = (LANGUAGE_TOTAL_STRINGS - _languages[i].missing) * 100 / LANGUAGE_TOTAL_STRINGS;
534 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE, std::move(name), percentage), i));
535 }
536 }
537 std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
538 break;
539 }
540
541 case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
542 if (_resolutions.empty()) break;
543
544 *selected_index = GetCurrentResolutionIndex();
545 for (uint i = 0; i < _resolutions.size(); i++) {
546 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_RESOLUTION_ITEM, _resolutions[i].width, _resolutions[i].height), i));
547 }
548 break;
549
550 case WID_GO_REFRESH_RATE_DROPDOWN: // Setup refresh rate dropdown
551 for (auto it = _refresh_rates.begin(); it != _refresh_rates.end(); it++) {
552 auto i = std::distance(_refresh_rates.begin(), it);
553 if (*it == _settings_client.gui.refresh_rate) *selected_index = i;
554 list.push_back(MakeDropDownListStringItem(GetString(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, *it), i));
555 }
556 break;
557
559 list = BuildSetDropDownList<BaseGraphics>(selected_index);
560 break;
561
563 list = BuildSetDropDownList<BaseSounds>(selected_index);
564 break;
565
567 list = BuildSetDropDownList<BaseMusic>(selected_index);
568 break;
569
571 for (int mode = 0; mode != RM_END; mode++) {
572 /* If we are in adv. settings screen for the new game's settings,
573 * we don't want to allow comparing with new game's settings. */
574 bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
575
576 list.push_back(MakeDropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled));
577 }
578 break;
579
581 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL));
582 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME));
583 list.push_back(MakeDropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY));
584 list.push_back(MakeDropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT));
585 break;
586 }
587
588 return list;
589 }
590
591 std::string GetToggleString(StringID stringid, WidgetID state_widget) const
592 {
593 return GetString(STR_GAME_OPTIONS_SETTING, stringid, this->IsWidgetLowered(state_widget) ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
594 }
595
596 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
597 {
598 switch (widget) {
600 const CurrencySpec &currency = _currency_specs[this->opt->locale.currency];
601 if (currency.code.empty()) return GetString(currency.name);
602 return GetString(STR_GAME_OPTIONS_CURRENCY_CODE, currency.name, currency.code);
603 }
604
606 int index = 0;
607 for (auto &minutes : _autosave_dropdown_to_minutes) {
608 index++;
609 if (_settings_client.gui.autosave_interval <= minutes) break;
610 }
611 return GetString(_autosave_dropdown[index - 1]);
612 }
613
618 case WID_GO_REFRESH_RATE_DROPDOWN: return GetString(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, _settings_client.gui.refresh_rate);
620 auto current_resolution = GetCurrentResolutionIndex();
621
622 if (current_resolution == _resolutions.size()) {
623 return GetString(STR_GAME_OPTIONS_RESOLUTION_OTHER);
624 }
625 return GetString(STR_GAME_OPTIONS_RESOLUTION_ITEM, _resolutions[current_resolution].width, _resolutions[current_resolution].height);
626 }
627
631 const NWidgetSocialPlugins *plugin = this->GetWidget<NWidgetSocialPlugins>(WID_GO_SOCIAL_PLUGINS);
632 assert(plugin != nullptr);
633
634 return plugin->GetWidgetString(widget, stringid);
635 }
636
638 return GetString(_game_settings_restrict_dropdown[this->filter.mode]);
639
641 switch (this->filter.type) {
642 case ST_GAME: return GetString(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME);
643 case ST_COMPANY: return GetString(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME);
644 case ST_CLIENT: return GetString(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT);
645 default: return GetString(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL);
646 }
647 break;
648
650 return GetToggleString(STR_GAME_OPTIONS_PARTICIPATE_SURVEY, WID_GO_SURVEY_PARTICIPATE_BUTTON);
651
653 return GetToggleString(STR_GAME_OPTIONS_GUI_SCALE_AUTO, WID_GO_GUI_SCALE_AUTO);
654
656 return GetToggleString(STR_GAME_OPTIONS_GUI_SCALE_BEVELS, WID_GO_GUI_SCALE_BEVEL_BUTTON);
657
659 return GetToggleString(STR_GAME_OPTIONS_GUI_FONT_SPRITE, WID_GO_GUI_FONT_SPRITE);
660
662 return GetToggleString(STR_GAME_OPTIONS_GUI_FONT_DEFAULT, WID_GO_GUI_FONT_DEFAULT);
663
665 return GetToggleString(STR_GAME_OPTIONS_GUI_FONT_AA, WID_GO_GUI_FONT_AA);
666
668 return GetToggleString(STR_GAME_OPTIONS_FULLSCREEN, WID_GO_FULLSCREEN_BUTTON);
669
671 return GetToggleString(STR_GAME_OPTIONS_VIDEO_ACCELERATION, WID_GO_VIDEO_ACCEL_BUTTON);
672
674 return GetToggleString(STR_GAME_OPTIONS_VIDEO_VSYNC, WID_GO_VIDEO_VSYNC_BUTTON);
675
676 default:
677 return this->Window::GetWidgetString(widget, stringid);
678 }
679 }
680
681 void DrawWidget(const Rect &r, WidgetID widget) const override
682 {
683 switch (widget) {
686 break;
687
690 break;
691
694 break;
695
696 case WID_GO_GUI_SCALE:
697 DrawSliderWidget(r, GAME_OPTIONS_BACKGROUND, GAME_OPTIONS_BUTTON, TC_BLACK, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, SCALE_NMARKS, this->gui_scale, ScaleMarkFunc);
698 break;
699
701 DrawStringMultiLine(r, GetString(STR_GAME_OPTIONS_VIDEO_DRIVER_INFO, std::string{VideoDriver::GetInstance()->GetInfoString()}), GAME_OPTIONS_SELECTED);
702 break;
703
705 DrawSliderWidget(r, GAME_OPTIONS_BACKGROUND, GAME_OPTIONS_BUTTON, TC_BLACK, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.effect_vol, VolumeMarkFunc);
706 break;
707
709 DrawSliderWidget(r, GAME_OPTIONS_BACKGROUND, GAME_OPTIONS_BUTTON, TC_BLACK, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.music_vol, VolumeMarkFunc);
710 break;
711
712 case WID_GO_OPTIONSPANEL: {
714 tr.top += this->warn_lines * BaseSettingEntry::line_height;
715 uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
716 int next_row = GetSettingsTree().Draw(settings_ptr, tr.left, tr.right, tr.top,
717 this->vscroll->GetPosition(), last_row, this->last_clicked);
718 if (next_row == 0) DrawString(tr, STR_CONFIG_SETTINGS_NONE);
719 break;
720 }
721
723 if (this->last_clicked != nullptr) {
724 const IntSettingDesc *sd = this->last_clicked->setting;
725
726 Rect tr = r;
727 std::string str;
728 switch (sd->GetType()) {
729 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;
730 case ST_CLIENT: str = GetString(STR_CONFIG_SETTING_TYPE, STR_CONFIG_SETTING_TYPE_CLIENT); break;
731 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;
732 default: NOT_REACHED();
733 }
734 DrawString(tr, str);
735 tr.top += GetCharacterHeight(FS_NORMAL);
736
737 auto [param1, param2] = sd->GetValueParams(sd->GetDefaultValue());
738 DrawString(tr, GetString(STR_CONFIG_SETTING_DEFAULT_VALUE, param1, param2));
739 }
740 break;
741
742 case WID_GO_HELP_TEXT:
743 if (this->last_clicked != nullptr) {
744 const IntSettingDesc *sd = this->last_clicked->setting;
745
746 DrawPixelInfo tmp_dpi;
747 if (FillDrawPixelInfo(&tmp_dpi, r)) {
748 AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
749 int scrolls_pos = this->vscroll_description->GetPosition() * GetCharacterHeight(FS_NORMAL);
750 DrawStringMultiLine(0, r.Width() - 1, -scrolls_pos, r.Height() - 1, sd->GetHelp(), TC_WHITE);
751 }
752 }
753 break;
754
755 default:
756 break;
757 }
758 }
759
765 {
766 if (this->last_clicked != pe) this->SetDirty();
767 this->last_clicked = pe;
768 UpdateHelpTextSize();
769 }
770
771 void UpdateHelpTextSize()
772 {
773 NWidgetResizeBase *wid = this->GetWidget<NWidgetResizeBase>(WID_GO_HELP_TEXT);
774 this->vscroll_description->SetCount(this->last_clicked ? CeilDiv(this->last_clicked->GetMaxHelpHeight(wid->current_x), GetCharacterHeight(FS_NORMAL)) : 0);
775 }
776
777 void SetTab(WidgetID widget)
778 {
780 this->LowerWidget(widget);
781 GameOptionsWindow::active_tab = widget;
782
783 int plane;
784 switch (widget) {
785 case WID_GO_TAB_GENERAL: plane = 0; break;
786 case WID_GO_TAB_GRAPHICS: plane = 1; break;
787 case WID_GO_TAB_SOUND: plane = 2; break;
788 case WID_GO_TAB_SOCIAL: plane = 3; break;
789 case WID_GO_TAB_ADVANCED: plane = 4; break;
790 default: NOT_REACHED();
791 }
792
793 this->GetWidget<NWidgetStacked>(WID_GO_TAB_SELECTION)->SetDisplayedPlane(plane);
795 this->SetDirty();
796 }
797
798 void OnResize() override
799 {
800 this->vscroll->SetCapacityFromWidget(this, WID_GO_OPTIONSPANEL, WidgetDimensions::scaled.framerect.Vertical());
801 UpdateHelpTextSize();
802
803 bool changed = false;
804
805 NWidgetResizeBase *wid = this->GetWidget<NWidgetResizeBase>(WID_GO_BASE_GRF_DESCRIPTION);
806 int y = 0;
807 for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
808 std::string str = GetString(STR_JUST_RAW_STRING, BaseGraphics::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
809 y = std::max(y, GetStringHeight(str, wid->current_x));
810 }
811 changed |= wid->UpdateVerticalSize(y);
812
813 wid = this->GetWidget<NWidgetResizeBase>(WID_GO_BASE_SFX_DESCRIPTION);
814 y = 0;
815 for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
816 std::string str = GetString(STR_JUST_RAW_STRING, BaseSounds::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
817 y = std::max(y, GetStringHeight(str, wid->current_x));
818 }
819 changed |= wid->UpdateVerticalSize(y);
820
821 wid = this->GetWidget<NWidgetResizeBase>(WID_GO_BASE_MUSIC_DESCRIPTION);
822 y = 0;
823 for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
824 std::string str = GetString(STR_JUST_RAW_STRING, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
825 y = std::max(y, GetStringHeight(str, wid->current_x));
826 }
827 changed |= wid->UpdateVerticalSize(y);
828
829 wid = this->GetWidget<NWidgetResizeBase>(WID_GO_VIDEO_DRIVER_INFO);
830 std::string str = GetString(STR_GAME_OPTIONS_VIDEO_DRIVER_INFO, std::string{VideoDriver::GetInstance()->GetInfoString()});
831 y = GetStringHeight(str, wid->current_x);
832 changed |= wid->UpdateVerticalSize(y);
833
834 if (changed) this->ReInit(0, 0, this->flags.Test(WindowFlag::Centred));
835 }
836
837 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
838 {
839 switch (widget) {
842 Dimension d = maxdim(GetStringBoundingBox(STR_GAME_OPTIONS_SFX_VOLUME), GetStringBoundingBox(STR_GAME_OPTIONS_MUSIC_VOLUME));
843 d.width += padding.width;
844 d.height += padding.height;
845 size = maxdim(size, d);
846 break;
847 }
848
857 int selected;
858 size.width = std::max(size.width, GetDropDownListDimension(this->BuildDropDownList(widget, &selected)).width + padding.width);
859 break;
860 }
861
863 fill.height = resize.height = BaseSettingEntry::line_height;
864 resize.width = 1;
865
866 size.height = 8 * resize.height + WidgetDimensions::scaled.framerect.Vertical();
867 break;
868
870 static const StringID setting_types[] = {
871 STR_CONFIG_SETTING_TYPE_CLIENT,
872 STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
873 STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
874 };
875 for (const auto &setting_type : setting_types) {
876 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_CONFIG_SETTING_TYPE, setting_type)).width + padding.width);
877 }
878 size.height = 2 * GetCharacterHeight(FS_NORMAL);
879 break;
880 }
881
882 case WID_GO_HELP_TEXT:
883 size.height = NUM_DESCRIPTION_LINES * GetCharacterHeight(FS_NORMAL);
884 break;
885
888 size.width = std::max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
889 break;
890
891 default:
892 break;
893 }
894 }
895
896 void OnPaint() override
897 {
898 if (this->GetWidget<NWidgetStacked>(WID_GO_TAB_SELECTION)->shown_plane != 4) {
899 this->DrawWidgets();
900 return;
901 }
902
903 if (this->closing_dropdown) {
904 this->closing_dropdown = false;
905 assert(this->valuedropdown_entry != nullptr);
906 this->valuedropdown_entry->SetButtons({});
907 this->valuedropdown_entry = nullptr;
908 }
909
910 /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
911 const Rect panel = this->GetWidget<NWidgetBase>(WID_GO_OPTIONSPANEL)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext);
912 StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
913 int new_warn_lines;
914 if (this->warn_missing == WHR_NONE) {
915 new_warn_lines = 0;
916 } else {
917 new_warn_lines = GetStringLineCount(GetString(warn_str, _game_settings_restrict_dropdown[this->filter.min_cat]), panel.Width());
918 }
919 if (this->warn_lines != new_warn_lines) {
920 this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
921 this->warn_lines = new_warn_lines;
922 }
923
924 this->DrawWidgets();
925
926 /* Draw the 'some search results are hidden' notice. */
927 if (this->warn_missing != WHR_NONE) {
929 GetString(warn_str, _game_settings_restrict_dropdown[this->filter.min_cat]),
930 TC_BLACK, SA_CENTER);
931 }
932 }
933
934#ifdef HAS_TRUETYPE_FONT
935 static void ReloadFonts()
936 {
942 ReInitAllWindows(true);
943 }
944#endif /* HAS_TRUETYPE_FONT */
945
946 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
947 {
948 if (widget >= WID_GO_BASE_GRF_TEXTFILE && widget < WID_GO_BASE_GRF_TEXTFILE + TFT_CONTENT_END) {
949 if (BaseGraphics::GetUsedSet() == nullptr) return;
950
951 ShowBaseSetTextfileWindow(this, (TextfileType)(widget - WID_GO_BASE_GRF_TEXTFILE), BaseGraphics::GetUsedSet(), STR_CONTENT_TYPE_BASE_GRAPHICS);
952 return;
953 }
954 if (widget >= WID_GO_BASE_SFX_TEXTFILE && widget < WID_GO_BASE_SFX_TEXTFILE + TFT_CONTENT_END) {
955 if (BaseSounds::GetUsedSet() == nullptr) return;
956
957 ShowBaseSetTextfileWindow(this, (TextfileType)(widget - WID_GO_BASE_SFX_TEXTFILE), BaseSounds::GetUsedSet(), STR_CONTENT_TYPE_BASE_SOUNDS);
958 return;
959 }
960 if (widget >= WID_GO_BASE_MUSIC_TEXTFILE && widget < WID_GO_BASE_MUSIC_TEXTFILE + TFT_CONTENT_END) {
961 if (BaseMusic::GetUsedSet() == nullptr) return;
962
963 ShowBaseSetTextfileWindow(this, (TextfileType)(widget - WID_GO_BASE_MUSIC_TEXTFILE), BaseMusic::GetUsedSet(), STR_CONTENT_TYPE_BASE_MUSIC);
964 return;
965 }
966 switch (widget) {
969 case WID_GO_TAB_SOUND:
972 SndClickBeep();
973 this->SetTab(widget);
974 break;
975
978 case PS_ASK:
979 case PS_NO:
981 break;
982
983 case PS_YES:
985 break;
986 }
987
991 break;
992
994 OpenBrowser(NETWORK_SURVEY_DETAILS_LINK);
995 break;
996
998 ShowSurveyResultTextfileWindow(this);
999 break;
1000
1001 case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
1002 /* try to toggle full-screen on/off */
1003 if (!ToggleFullScreen(!_fullscreen)) {
1004 ShowErrorMessage(GetEncodedString(STR_ERROR_FULLSCREEN_FAILED), {}, WL_ERROR);
1005 }
1009 break;
1010
1013 ShowErrorMessage(GetEncodedString(STR_GAME_OPTIONS_VIDEO_ACCELERATION_RESTART), {}, WL_INFO);
1017#ifndef __APPLE__
1022#endif
1023 break;
1024
1026 if (!_video_hw_accel) break;
1027
1030
1036 break;
1037
1040
1042 this->SetDirty();
1043
1045 ReInitAllWindows(true);
1046 break;
1047 }
1048
1049#ifdef HAS_TRUETYPE_FONT
1051 _fcsettings.prefer_sprite = !_fcsettings.prefer_sprite;
1052
1055 this->SetDirty();
1056 ReloadFonts();
1057 break;
1058
1060 _fcsettings.prefer_default = !_fcsettings.prefer_default;
1061
1063 this->SetDirty();
1064 ReloadFonts();
1065 break;
1066
1067 case WID_GO_GUI_FONT_AA:
1068 _fcsettings.global_aa = !_fcsettings.global_aa;
1069
1072
1074 break;
1075#endif /* HAS_TRUETYPE_FONT */
1076
1077 case WID_GO_GUI_SCALE:
1078 /* Any click on the slider deactivates automatic interface scaling, setting it to the current value before being adjusted. */
1079 if (_gui_scale_cfg == -1) {
1080 _gui_scale_cfg = this->gui_scale;
1084 }
1085
1086 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, _ctrl_pressed ? 0 : SCALE_NMARKS, this->gui_scale)) {
1087 this->gui_scale_changed = true;
1088 this->SetWidgetDirty(widget);
1089 }
1090
1091 if (click_count > 0) this->mouse_capture_widget = widget;
1092 break;
1093
1095 {
1096 if (_gui_scale_cfg == -1) {
1097 _gui_scale_cfg = this->previous_gui_scale; // Load the previous GUI scale
1099 if (AdjustGUIZoom(false)) ReInitAllWindows(true);
1100 this->gui_scale = _gui_scale;
1101 } else {
1102 this->previous_gui_scale = _gui_scale; // Set the previous GUI scale value as the current one
1103 _gui_scale_cfg = -1;
1105 if (AdjustGUIZoom(false)) ReInitAllWindows(true);
1106 this->gui_scale = _gui_scale;
1107 }
1108 this->SetWidgetDirty(widget);
1110 break;
1111 }
1112
1114 auto *used_set = BaseGraphics::GetUsedSet();
1115 if (used_set == nullptr || !used_set->IsConfigurable()) break;
1116 GRFConfig &extra_cfg = used_set->GetOrCreateExtraConfig();
1117 if (extra_cfg.param.empty()) extra_cfg.SetParameterDefaults();
1118 OpenGRFParameterWindow(true, extra_cfg, _game_mode == GM_MENU);
1119 if (_game_mode == GM_MENU) this->reload = true;
1120 break;
1121 }
1122
1126 if (ClickSliderWidget(this->GetWidget<NWidgetBase>(widget)->GetCurrentRect(), pt, 0, INT8_MAX, 0, vol)) {
1127 if (widget == WID_GO_BASE_MUSIC_VOLUME) {
1129 } else {
1130 SetEffectVolume(vol);
1131 }
1132 this->SetWidgetDirty(widget);
1134 }
1135
1136 if (click_count > 0) this->mouse_capture_widget = widget;
1137 break;
1138 }
1139
1141 ShowMusicWindow();
1142 break;
1143 }
1144
1146 if (BaseGraphics::GetUsedSet() == nullptr || BaseGraphics::GetUsedSet()->url.empty()) return;
1147 OpenBrowser(BaseGraphics::GetUsedSet()->url);
1148 break;
1149
1151 if (BaseSounds::GetUsedSet() == nullptr || BaseSounds::GetUsedSet()->url.empty()) return;
1152 OpenBrowser(BaseSounds::GetUsedSet()->url);
1153 break;
1154
1156 if (BaseMusic::GetUsedSet() == nullptr || BaseMusic::GetUsedSet()->url.empty()) return;
1157 OpenBrowser(BaseMusic::GetUsedSet()->url);
1158 break;
1159
1162 break;
1163
1166 break;
1167
1170 break;
1171
1180 int selected;
1181 DropDownList list = this->BuildDropDownList(widget, &selected);
1182 if (!list.empty()) {
1183 ShowDropDownList(this, std::move(list), selected, widget);
1184 } else {
1185 if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(GetEncodedString(STR_ERROR_RESOLUTION_LIST_FAILED), {}, WL_ERROR);
1186 }
1187 break;
1188 }
1189
1190 case WID_GO_EXPAND_ALL:
1191 this->manually_changed_folding = true;
1193 this->InvalidateData();
1194 break;
1195
1197 this->manually_changed_folding = true;
1199 this->InvalidateData();
1200 break;
1201
1202 case WID_GO_RESET_ALL:
1203 ShowQuery(
1204 GetEncodedString(STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_CAPTION),
1205 GetEncodedString(STR_CONFIG_SETTING_RESET_ALL_CONFIRMATION_DIALOG_TEXT),
1206 this,
1208 );
1209 break;
1210
1212 int selected;
1213 DropDownList list = this->BuildDropDownList(widget, &selected);
1214 if (!list.empty()) {
1215 ShowDropDownList(this, std::move(list), this->filter.mode, widget);
1216 }
1217 break;
1218 }
1219
1220 case WID_GO_TYPE_DROPDOWN: {
1221 int selected;
1222 DropDownList list = this->BuildDropDownList(widget, &selected);
1223 if (!list.empty()) {
1224 ShowDropDownList(this, std::move(list), this->filter.type, widget);
1225 }
1226 break;
1227 }
1228
1230 OptionsPanelClick(pt);
1231 break;
1232 }
1233 }
1234
1235 void OptionsPanelClick(Point pt)
1236 {
1237 int32_t btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GO_OPTIONSPANEL, WidgetDimensions::scaled.framerect.top);
1238 if (btn == INT32_MAX || btn < this->warn_lines) return;
1239 btn -= this->warn_lines;
1240
1241 uint cur_row = 0;
1243
1244 if (clicked_entry == nullptr) return; // Clicked below the last setting of the page
1245
1246 const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_GO_OPTIONSPANEL);
1247 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
1248 if (x < 0) return; // Clicked left of the entry
1249
1250 SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
1251 if (clicked_page != nullptr) {
1252 this->SetDisplayedHelpText(nullptr);
1253 clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
1254
1255 this->manually_changed_folding = true;
1256
1257 this->InvalidateData();
1258 return;
1259 }
1260
1261 SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
1262 assert(pe != nullptr);
1263 const IntSettingDesc *sd = pe->setting;
1264
1265 /* return if action is only active in network, or only settable by server */
1266 if (!sd->IsEditable()) {
1267 this->SetDisplayedHelpText(pe);
1268 return;
1269 }
1270
1271 auto [min_val, max_val] = sd->GetRange();
1272 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
1273
1274 /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
1275 if (x < SETTING_BUTTON_WIDTH && sd->flags.Test(SettingFlag::GuiDropdown)) {
1276 this->SetDisplayedHelpText(pe);
1277
1278 if (this->valuedropdown_entry == pe) {
1279 /* unclick the dropdown */
1281 this->closing_dropdown = false;
1282 this->valuedropdown_entry->SetButtons({});
1283 this->valuedropdown_entry = nullptr;
1284 } else {
1285 if (this->valuedropdown_entry != nullptr) this->valuedropdown_entry->SetButtons({});
1286 this->closing_dropdown = false;
1287
1288 int rel_y = (pt.y - wid->pos_y - WidgetDimensions::scaled.framerect.top) % wid->resize_y;
1289
1290 Rect wi_rect;
1291 wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
1292 wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
1293 wi_rect.top = pt.y - rel_y + (BaseSettingEntry::line_height - SETTING_BUTTON_HEIGHT) / 2;
1294 wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
1295
1296 /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
1297 if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
1298 this->valuedropdown_entry = pe;
1299 this->valuedropdown_entry->SetButtons(SettingEntryFlag::LeftDepressed);
1300
1301 DropDownList list;
1302 for (int32_t i = min_val; i <= static_cast<int32_t>(max_val); i++) {
1303 auto [param1, param2] = sd->GetValueParams(i);
1304 list.push_back(MakeDropDownListStringItem(GetString(STR_JUST_STRING1, param1, param2), i));
1305 }
1306
1307 ShowDropDownListAt(this, std::move(list), value, WID_GO_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);
1308 }
1309 }
1310 this->SetDirty();
1311 } else if (x < SETTING_BUTTON_WIDTH) {
1312 this->SetDisplayedHelpText(pe);
1313 int32_t oldvalue = value;
1314
1315 if (sd->IsBoolSetting()) {
1316 value ^= 1;
1317 } else {
1318 /* Add a dynamic step-size to the scroller. In a maximum of
1319 * 50-steps you should be able to get from min to max,
1320 * unless specified otherwise in the 'interval' variable
1321 * of the current setting. */
1322 uint32_t step = (sd->interval == 0) ? ((max_val - min_val) / 50) : sd->interval;
1323 if (step == 0) step = 1;
1324
1325 /* don't allow too fast scrolling */
1326 if (this->flags.Test(WindowFlag::Timeout) && this->timeout_timer > 1) {
1327 _left_button_clicked = false;
1328 return;
1329 }
1330
1331 /* Increase or decrease the value and clamp it to extremes */
1332 if (x >= SETTING_BUTTON_WIDTH / 2) {
1333 value += step;
1334 if (min_val < 0) {
1335 assert(static_cast<int32_t>(max_val) >= 0);
1336 if (value > static_cast<int32_t>(max_val)) value = static_cast<int32_t>(max_val);
1337 } else {
1338 if (static_cast<uint32_t>(value) > max_val) value = static_cast<int32_t>(max_val);
1339 }
1340 if (value < min_val) value = min_val; // skip between "disabled" and minimum
1341 } else {
1342 value -= step;
1343 if (value < min_val) value = sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val;
1344 }
1345
1346 /* Set up scroller timeout for numeric values */
1347 if (value != oldvalue) {
1348 if (this->clicked_entry != nullptr) { // Release previous buttons if any
1349 this->clicked_entry->SetButtons({});
1350 }
1351 this->clicked_entry = pe;
1353 this->SetTimeout();
1354 _left_button_clicked = false;
1355 }
1356 }
1357
1358 if (value != oldvalue) {
1359 SetSettingValue(sd, value);
1360 this->SetDirty();
1361 }
1362 } else {
1363 /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
1364 if (this->last_clicked == pe && !sd->IsBoolSetting() && !sd->flags.Test(SettingFlag::GuiDropdown)) {
1365 int64_t value64 = value;
1366 /* Show the correct currency-translated value */
1367 if (sd->flags.Test(SettingFlag::GuiCurrency)) value64 *= GetCurrency().rate;
1368
1369 CharSetFilter charset_filter = CS_NUMERAL; //default, only numeric input allowed
1370 if (min_val < 0) charset_filter = CS_NUMERAL_SIGNED; // special case, also allow '-' sign for negative input
1371
1372 this->valuewindow_entry = pe;
1373 /* Limit string length to 14 so that MAX_INT32 * max currency rate doesn't exceed MAX_INT64. */
1374 ShowQueryString(GetString(STR_JUST_INT, value64), STR_CONFIG_SETTING_QUERY_CAPTION, 15, this, charset_filter, QueryStringFlag::EnableDefault);
1375 }
1376 this->SetDisplayedHelpText(pe);
1377 }
1378 }
1379
1380 void OnTimeout() override
1381 {
1382 if (this->clicked_entry != nullptr) { // On timeout, release any depressed buttons
1383 this->clicked_entry->SetButtons({});
1384 this->clicked_entry = nullptr;
1385 this->SetDirty();
1386 }
1387 }
1388
1389 void OnQueryTextFinished(std::optional<std::string> str) override
1390 {
1391 /* The user pressed cancel */
1392 if (!str.has_value()) return;
1393
1394 assert(this->valuewindow_entry != nullptr);
1395 const IntSettingDesc *sd = this->valuewindow_entry->setting;
1396
1397 int32_t value;
1398 if (!str->empty()) {
1399 auto llvalue = ParseInteger<int64_t>(*str, 10, true);
1400 if (!llvalue.has_value()) return;
1401
1402 /* Save the correct currency-translated value */
1403 if (sd->flags.Test(SettingFlag::GuiCurrency)) llvalue = *llvalue / GetCurrency().rate;
1404
1405 value = ClampTo<int32_t>(*llvalue);
1406 } else {
1407 value = sd->GetDefaultValue();
1408 }
1409
1410 SetSettingValue(this->valuewindow_entry->setting, value);
1411 this->SetDirty();
1412 }
1413
1414 void OnMouseLoop() override
1415 {
1416 if (_left_button_down || !this->gui_scale_changed) return;
1417
1418 this->gui_scale_changed = false;
1419 _gui_scale_cfg = this->gui_scale;
1420
1421 if (AdjustGUIZoom(false)) {
1422 ReInitAllWindows(true);
1424 this->SetDirty();
1425 }
1426 }
1427
1428 void OnDropdownSelect(WidgetID widget, int index, int) override
1429 {
1430 switch (widget) {
1431 case WID_GO_CURRENCY_DROPDOWN: // Currency
1432 if (index == CURRENCY_CUSTOM) ShowCustCurrency();
1433 this->opt->locale.currency = index;
1434 ReInitAllWindows(false);
1435 break;
1436
1437 case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
1440 this->SetDirty();
1441 break;
1442
1443 case WID_GO_LANG_DROPDOWN: // Change interface language
1447 ClearAllCachedNames();
1449 CheckBlitter();
1450 ReInitAllWindows(false);
1451 break;
1452
1453 case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
1454 if ((uint)index < _resolutions.size() && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
1455 this->SetDirty();
1456 }
1457 break;
1458
1460 _settings_client.gui.refresh_rate = *std::next(_refresh_rates.begin(), index);
1462 /* Show warning to the user that this refresh rate might not be suitable on
1463 * larger maps with many NewGRFs and vehicles. */
1464 ShowErrorMessage(GetEncodedString(STR_GAME_OPTIONS_REFRESH_RATE_WARNING), {}, WL_INFO);
1465 }
1466 break;
1467 }
1468
1470 if (_game_mode == GM_MENU) {
1472 auto set = BaseGraphics::GetSet(index);
1474 this->reload = true;
1475 this->InvalidateData();
1476 }
1477 break;
1478
1480 ChangeSoundSet(index);
1481 break;
1482
1484 ChangeMusicSet(index);
1485 break;
1486
1488 this->filter.mode = (RestrictionMode)index;
1489 if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
1490 this->filter.mode == RM_CHANGED_AGAINST_NEW) {
1491
1492 if (!this->manually_changed_folding) {
1493 /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
1496 }
1497 } else {
1498 /* Non-'changes' filter. Save as default. */
1500 }
1501 this->InvalidateData();
1502 break;
1503
1505 this->filter.type = (SettingType)index;
1506 this->InvalidateData();
1507 break;
1508
1510 /* Deal with drop down boxes on the panel. */
1511 assert(this->valuedropdown_entry != nullptr);
1512 const IntSettingDesc *sd = this->valuedropdown_entry->setting;
1513 assert(sd->flags.Test(SettingFlag::GuiDropdown));
1514
1515 SetSettingValue(sd, index);
1516 this->SetDirty();
1517 break;
1518 }
1519 }
1520
1521 void OnDropdownClose(Point pt, WidgetID widget, int index, int click_result, bool instant_close) override
1522 {
1523 if (widget != WID_GO_SETTING_DROPDOWN) {
1524 /* Normally the default implementation of OnDropdownClose() takes care of
1525 * a few things. We want that behaviour here too, but only for
1526 * "normal" dropdown boxes. The special dropdown boxes added for every
1527 * setting that needs one can't have this call. */
1528 Window::OnDropdownClose(pt, widget, index, click_result, instant_close);
1529 } else {
1530 /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
1531 * the same dropdown button was clicked again, and then not open the dropdown again.
1532 * So, we only remember that it was closed, and process it on the next OnPaint, which is
1533 * after OnClick. */
1534 assert(this->valuedropdown_entry != nullptr);
1535 this->closing_dropdown = true;
1536 this->SetDirty();
1537 }
1538 }
1539
1545 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1546 {
1547 if (!gui_scope) return;
1552
1553#ifndef __APPLE__
1556#endif
1557
1560#ifdef HAS_TRUETYPE_FONT
1565#endif /* HAS_TRUETYPE_FONT */
1566
1567 this->SetWidgetDisabledState(WID_GO_BASE_GRF_DROPDOWN, _game_mode != GM_MENU);
1568
1570
1574
1575 for (TextfileType tft = TFT_CONTENT_BEGIN; tft < TFT_CONTENT_END; tft++) {
1579 }
1580
1582
1583 /* Update which settings are to be visible. */
1584 RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
1585 this->filter.min_cat = min_level;
1586 this->filter.type_hides = false;
1588
1589 if (this->filter.string.IsEmpty()) {
1590 this->warn_missing = WHR_NONE;
1591 } else if (min_level < this->filter.min_cat) {
1592 this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
1593 } else {
1594 this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
1595 }
1596 this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
1597
1598 if (this->last_clicked != nullptr && !GetSettingsTree().IsVisible(this->last_clicked)) {
1599 this->SetDisplayedHelpText(nullptr);
1600 }
1601
1602 bool all_folded = true;
1603 bool all_unfolded = true;
1604 GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
1605 this->SetWidgetDisabledState(WID_GO_EXPAND_ALL, all_unfolded);
1607 }
1608
1609 void OnEditboxChanged(WidgetID wid) override
1610 {
1611 if (wid == WID_GO_FILTER) {
1612 this->filter.string.SetFilterTerm(this->filter_editbox.text.GetText());
1613 if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
1614 /* User never expanded/collapsed single pages and entered a filter term.
1615 * Expand everything, to save weird expand clicks, */
1617 }
1618 this->InvalidateData();
1619 }
1620 }
1621};
1622
1623static constexpr std::initializer_list<NWidgetPart> _nested_game_options_widgets = {
1626 NWidget(WWT_CAPTION, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1628 EndContainer(),
1631 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),
1632 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),
1633 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),
1634 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),
1635 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),
1636 EndContainer(),
1637 EndContainer(),
1640 /* General tab */
1644 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_LANG_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1645 EndContainer(),
1646
1648 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_AUTOSAVE_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1649 EndContainer(),
1650
1651 NWidget(WWT_FRAME, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME), SetTextStyle(GAME_OPTIONS_FRAME),
1652 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_CURRENCY_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1653 EndContainer(),
1654
1655 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GO_SURVEY_SEL),
1656 NWidget(WWT_FRAME, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_PARTICIPATE_SURVEY_FRAME), SetTextStyle(GAME_OPTIONS_FRAME), SetPIP(0, WidgetDimensions::unscaled.vsep_sparse, 0),
1660 EndContainer(),
1662 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),
1663 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),
1664 EndContainer(),
1665 EndContainer(),
1666 EndContainer(),
1667 EndContainer(),
1668 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1669 EndContainer(),
1670
1671 /* Graphics tab */
1677 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_GAME_OPTIONS_GUI_SCALE_FRAME), SetTextStyle(GAME_OPTIONS_LABEL),
1678 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),
1679 EndContainer(),
1683 EndContainer(),
1687 EndContainer(),
1688#ifdef HAS_TRUETYPE_FONT
1692 EndContainer(),
1696 EndContainer(),
1700 EndContainer(),
1701#endif /* HAS_TRUETYPE_FONT */
1702 EndContainer(),
1703 EndContainer(),
1704
1708 NWidget(WWT_TEXT, INVALID_COLOUR), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_RESOLUTION), SetTextStyle(GAME_OPTIONS_LABEL),
1709 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_RESOLUTION_DROPDOWN), SetFill(1, 0), SetToolTip(STR_GAME_OPTIONS_RESOLUTION_TOOLTIP),
1710 EndContainer(),
1712 NWidget(WWT_TEXT, INVALID_COLOUR), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_GAME_OPTIONS_REFRESH_RATE), SetTextStyle(GAME_OPTIONS_LABEL),
1713 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_REFRESH_RATE_DROPDOWN), SetFill(1, 0), SetToolTip(STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP),
1714 EndContainer(),
1718 EndContainer(),
1722 EndContainer(),
1723#ifndef __APPLE__
1727 EndContainer(),
1728#endif
1730 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_VIDEO_DRIVER_INFO), SetMinimalTextLines(1, 0), SetFill(1, 0), SetResize(1, 0),
1731 EndContainer(),
1732 EndContainer(),
1733 EndContainer(),
1734
1737 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_BASE_GRF_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1739 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_GRF_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1740 EndContainer(),
1741 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),
1744 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),
1745 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),
1746 EndContainer(),
1748 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),
1749 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),
1750 EndContainer(),
1751 EndContainer(),
1752 EndContainer(),
1753 EndContainer(),
1754 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1755 EndContainer(),
1756
1757 /* Sound/Music tab */
1762 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_TEXT_SFX_VOLUME), SetStringTip(STR_GAME_OPTIONS_SFX_VOLUME), SetTextStyle(GAME_OPTIONS_LABEL),
1763 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),
1764 EndContainer(),
1766 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_TEXT_MUSIC_VOLUME), SetStringTip(STR_GAME_OPTIONS_MUSIC_VOLUME), SetTextStyle(GAME_OPTIONS_LABEL),
1767 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),
1768 EndContainer(),
1769 EndContainer(),
1770
1773 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_BASE_SFX_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1774 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_SFX_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1775 EndContainer(),
1776 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),
1779 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),
1780 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),
1781 EndContainer(),
1783 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),
1784 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),
1785 EndContainer(),
1786 EndContainer(),
1787 EndContainer(),
1788
1791 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_DROPDOWN), SetToolTip(STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1792 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_CONTENT_DOWNLOAD), SetStringTip(STR_GAME_OPTIONS_ONLINE_CONTENT, STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP),
1793 EndContainer(),
1795 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),
1797 NWidget(WWT_PUSHIMGBTN, GAME_OPTIONS_BUTTON, WID_GO_BASE_MUSIC_JUKEBOX), SetToolbarMinimalSize(1), SetSpriteTip(SPR_IMG_MUSIC, STR_TOOLBAR_TOOLTIP_SHOW_SOUND_MUSIC_WINDOW),
1798 EndContainer(),
1799 EndContainer(),
1802 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),
1803 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),
1804 EndContainer(),
1806 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),
1807 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),
1808 EndContainer(),
1809 EndContainer(),
1810 EndContainer(),
1811 EndContainer(),
1812 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1813 EndContainer(),
1814
1815 /* Social tab */
1818 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(1, 1), // Allows this pane to resize
1819 EndContainer(),
1820
1821 /* Advanced settings tab */
1825 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_RESTRICT_CATEGORY), SetStringTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY), SetTextStyle(GAME_OPTIONS_LABEL),
1826 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_RESTRICT_DROPDOWN), SetToolTip(STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
1827 EndContainer(),
1829 NWidget(WWT_TEXT, INVALID_COLOUR, WID_GO_RESTRICT_TYPE), SetStringTip(STR_CONFIG_SETTING_RESTRICT_TYPE), SetTextStyle(GAME_OPTIONS_LABEL),
1830 NWidget(WWT_DROPDOWN, GAME_OPTIONS_BUTTON, WID_GO_TYPE_DROPDOWN), SetToolTip(STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
1831 EndContainer(),
1833 NWidget(WWT_TEXT, INVALID_COLOUR), SetFill(0, 1), SetStringTip(STR_CONFIG_SETTING_FILTER_TITLE), SetTextStyle(GAME_OPTIONS_LABEL),
1834 NWidget(WWT_EDITBOX, GAME_OPTIONS_BACKGROUND, WID_GO_FILTER), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
1835 EndContainer(),
1836 EndContainer(),
1837
1840 EndContainer(),
1842 EndContainer(),
1843
1845 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_EXPAND_ALL), SetStringTip(STR_CONFIG_SETTING_EXPAND_ALL), SetFill(1, 0), SetResize(1, 0),
1846 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_COLLAPSE_ALL), SetStringTip(STR_CONFIG_SETTING_COLLAPSE_ALL), SetFill(1, 0), SetResize(1, 0),
1847 NWidget(WWT_PUSHTXTBTN, GAME_OPTIONS_BUTTON, WID_GO_RESET_ALL), SetStringTip(STR_CONFIG_SETTING_RESET_ALL), SetFill(1, 0), SetResize(1, 0),
1848 EndContainer(),
1849
1850 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GO_SETTING_PROPERTIES), SetFill(1, 0), SetResize(1, 0),
1854 EndContainer(),
1855 EndContainer(),
1856 EndContainer(),
1857
1859 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1861 EndContainer(),
1862 EndContainer(),
1863};
1864
1865static WindowDesc _game_options_desc(
1866 WDP_CENTER, "game_options", 0, 0,
1868 {},
1869 _nested_game_options_widgets
1870);
1871
1874{
1876 new GameOptionsWindow(_game_options_desc);
1877}
1878
1888void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
1889{
1890 PixelColour colour = GetColourGradient(button_colour, SHADE_DARKER);
1891 Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
1892
1893 Rect lr = {x, y, x + (int)dim.width - 1, y + (int)dim.height - 1};
1894 Rect rr = {x + (int)dim.width, y, x + (int)dim.width * 2 - 1, y + (int)dim.height - 1};
1895
1896 DrawFrameRect(lr, button_colour, (state == 1) ? FrameFlag::Lowered : FrameFlags{});
1897 DrawFrameRect(rr, button_colour, (state == 2) ? FrameFlag::Lowered : FrameFlags{});
1898 DrawSpriteIgnorePadding(SPR_ARROW_LEFT, PAL_NONE, lr, SA_CENTER);
1899 DrawSpriteIgnorePadding(SPR_ARROW_RIGHT, PAL_NONE, rr, SA_CENTER);
1900
1901 /* Grey out the buttons that aren't clickable */
1902 bool rtl = _current_text_dir == TD_RTL;
1903 if (rtl ? !clickable_right : !clickable_left) {
1905 }
1906 if (rtl ? !clickable_left : !clickable_right) {
1908 }
1909}
1910
1920void DrawUpDownButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_up, bool clickable_down)
1921{
1922 PixelColour colour = GetColourGradient(button_colour, SHADE_DARKER);
1923
1924 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
1927
1928 DrawFrameRect(ur, button_colour, (state == 1) ? FrameFlag::Lowered : FrameFlags{});
1929 DrawFrameRect(dr, button_colour, (state == 2) ? FrameFlag::Lowered : FrameFlags{});
1930 DrawSpriteIgnorePadding(SPR_ARROW_UP, PAL_NONE, ur, SA_CENTER);
1931 DrawSpriteIgnorePadding(SPR_ARROW_DOWN, PAL_NONE, dr, SA_CENTER);
1932
1933 /* Grey out the buttons that aren't clickable */
1934 if (!clickable_up) GfxFillRect(ur.Shrink(WidgetDimensions::scaled.bevel), colour, FILLRECT_CHECKER);
1935 if (!clickable_down) GfxFillRect(dr.Shrink(WidgetDimensions::scaled.bevel), colour, FILLRECT_CHECKER);
1936}
1937
1946void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
1947{
1948 PixelColour colour = GetColourGradient(button_colour, SHADE_DARKER);
1949
1950 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
1951
1952 DrawFrameRect(r, button_colour, state ? FrameFlag::Lowered : FrameFlags{});
1953 DrawSpriteIgnorePadding(SPR_ARROW_DOWN, PAL_NONE, r, SA_CENTER);
1954
1955 if (!clickable) {
1957 }
1958}
1959
1969void DrawBoolButton(int x, int y, Colours button_colour, Colours background, bool state, bool clickable)
1970{
1971 Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
1972 DrawFrameRect(r, state ? COLOUR_GREEN : background, state ? FrameFlags{FrameFlag::Lowered} : FrameFlags{FrameFlag::Lowered, FrameFlag::BorderOnly});
1973 if (!clickable) {
1974 GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(state ? COLOUR_GREEN : background, SHADE_DARKER), FILLRECT_CHECKER);
1975 }
1976
1977 Rect button_rect = r.WithWidth(SETTING_BUTTON_WIDTH / 3, state ^ (_current_text_dir == TD_RTL));
1978 DrawFrameRect(button_rect, button_colour, {});
1979 if (!clickable) {
1980 GfxFillRect(button_rect.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(button_colour, SHADE_DARKER), FILLRECT_CHECKER);
1981 }
1982}
1983
1985 WidgetID query_widget{};
1986
1988 {
1989 this->InitNested();
1990
1991 SetButtonState();
1992 }
1993
1994 void SetButtonState()
1995 {
1997 this->SetWidgetDisabledState(WID_CC_RATE_UP, GetCustomCurrency().rate == UINT16_MAX);
2000 }
2001
2002 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
2003 {
2004 switch (widget) {
2005 case WID_CC_RATE: return GetString(STR_CURRENCY_EXCHANGE_RATE, 1, 1);
2006 case WID_CC_SEPARATOR: return GetString(STR_CURRENCY_SEPARATOR, GetCustomCurrency().separator);
2007 case WID_CC_PREFIX: return GetString(STR_CURRENCY_PREFIX, GetCustomCurrency().prefix);
2008 case WID_CC_SUFFIX: return GetString(STR_CURRENCY_SUFFIX, GetCustomCurrency().suffix);
2009 case WID_CC_YEAR:
2010 return GetString((GetCustomCurrency().to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER, GetCustomCurrency().to_euro);
2011
2012 case WID_CC_PREVIEW:
2013 return GetString(STR_CURRENCY_PREVIEW, 10000);
2014
2015 default:
2016 return this->Window::GetWidgetString(widget, stringid);
2017 }
2018 }
2019
2020 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
2021 {
2022 switch (widget) {
2023 /* Set the appropriate width for the up/down buttons. */
2024 case WID_CC_RATE_DOWN:
2025 case WID_CC_RATE_UP:
2026 case WID_CC_YEAR_DOWN:
2027 case WID_CC_YEAR_UP:
2028 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH / 2, (uint)SETTING_BUTTON_HEIGHT});
2029 break;
2030
2031 /* Set the appropriate width for the edit buttons. */
2033 case WID_CC_PREFIX_EDIT:
2034 case WID_CC_SUFFIX_EDIT:
2035 size = maxdim(size, {(uint)SETTING_BUTTON_WIDTH, (uint)SETTING_BUTTON_HEIGHT});
2036 break;
2037
2038 /* Make sure the window is wide enough for the widest exchange rate */
2039 case WID_CC_RATE:
2040 size = GetStringBoundingBox(GetString(STR_CURRENCY_EXCHANGE_RATE, 1, INT32_MAX));
2041 break;
2042 }
2043 }
2044
2045 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2046 {
2047 int line = 0;
2048 int len = 0;
2049 std::string str;
2051
2052 switch (widget) {
2053 case WID_CC_RATE_DOWN:
2054 if (GetCustomCurrency().rate > 1) GetCustomCurrency().rate--;
2055 if (GetCustomCurrency().rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2057 break;
2058
2059 case WID_CC_RATE_UP:
2060 if (GetCustomCurrency().rate < UINT16_MAX) GetCustomCurrency().rate++;
2061 if (GetCustomCurrency().rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2063 break;
2064
2065 case WID_CC_RATE:
2066 str = GetString(STR_JUST_INT, GetCustomCurrency().rate);
2067 len = 5;
2068 line = WID_CC_RATE;
2069 afilter = CS_NUMERAL;
2070 break;
2071
2073 case WID_CC_SEPARATOR:
2075 len = 7;
2076 line = WID_CC_SEPARATOR;
2077 break;
2078
2079 case WID_CC_PREFIX_EDIT:
2080 case WID_CC_PREFIX:
2081 str = GetCustomCurrency().prefix;
2082 len = 15;
2083 line = WID_CC_PREFIX;
2084 break;
2085
2086 case WID_CC_SUFFIX_EDIT:
2087 case WID_CC_SUFFIX:
2088 str = GetCustomCurrency().suffix;
2089 len = 15;
2090 line = WID_CC_SUFFIX;
2091 break;
2092
2093 case WID_CC_YEAR_DOWN:
2097 break;
2098
2099 case WID_CC_YEAR_UP:
2103 break;
2104
2105 case WID_CC_YEAR:
2106 str = GetString(STR_JUST_INT, GetCustomCurrency().to_euro);
2107 len = 7;
2108 line = WID_CC_YEAR;
2109 afilter = CS_NUMERAL;
2110 break;
2111 }
2112
2113 if (len != 0) {
2114 this->query_widget = line;
2115 ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, {});
2116 }
2117
2118 this->SetTimeout();
2119 this->SetDirty();
2120 }
2121
2122 void OnQueryTextFinished(std::optional<std::string> str) override
2123 {
2124 if (!str.has_value()) return;
2125
2126 switch (this->query_widget) {
2127 case WID_CC_RATE: {
2128 auto val = ParseInteger(*str, 10, true);
2129 if (!val.has_value()) return;
2130 GetCustomCurrency().rate = Clamp(*val, 1, UINT16_MAX);
2131 break;
2132 }
2133
2134 case WID_CC_SEPARATOR: // Thousands separator
2135 GetCustomCurrency().separator = std::move(*str);
2136 break;
2137
2138 case WID_CC_PREFIX:
2139 GetCustomCurrency().prefix = std::move(*str);
2140 break;
2141
2142 case WID_CC_SUFFIX:
2143 GetCustomCurrency().suffix = std::move(*str);
2144 break;
2145
2146 case WID_CC_YEAR: { // Year to switch to euro
2148 if (!str->empty()) {
2149 auto val = ParseInteger(*str, 10, true);
2150 if (!val.has_value()) return;
2152 }
2153 GetCustomCurrency().to_euro = year;
2154 break;
2155 }
2156 }
2158 SetButtonState();
2159 }
2160
2161 void OnTimeout() override
2162 {
2163 this->SetDirty();
2164 }
2165};
2166
2167static constexpr std::initializer_list<NWidgetPart> _nested_cust_currency_widgets = {
2169 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2170 NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2171 EndContainer(),
2172 NWidget(WWT_PANEL, COLOUR_GREY),
2177 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetArrowWidgetTypeTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
2178 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetArrowWidgetTypeTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
2179 EndContainer(),
2180 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_RATE), SetToolTip(STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2181 EndContainer(),
2183 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2184 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_SEPARATOR), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2185 EndContainer(),
2187 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2188 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_PREFIX), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2189 EndContainer(),
2191 NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2192 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_SUFFIX), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2193 EndContainer(),
2196 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetArrowWidgetTypeTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2197 NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetArrowWidgetTypeTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2198 EndContainer(),
2199 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CC_YEAR), SetToolTip(STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2200 EndContainer(),
2201 EndContainer(),
2202 NWidget(WWT_LABEL, INVALID_COLOUR, WID_CC_PREVIEW),
2203 SetToolTip(STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP),
2204 EndContainer(),
2205 EndContainer(),
2206};
2207
2208static WindowDesc _cust_currency_desc(
2209 WDP_CENTER, {}, 0, 0,
2211 {},
2212 _nested_cust_currency_widgets
2213);
2214
2216static void ShowCustCurrency()
2217{
2219 new CustomCurrencyWindow(_cust_currency_desc);
2220}
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()
Return the used set.
static int GetNumSets()
Count the number of available graphics sets.
static const GraphicsSet * GetSet(int index)
Get the name of the graphics set at the specified index.
static bool SetSet(const GraphicsSet *set)
Set the set to be used.
static bool NatSortFunc(std::unique_ptr< const DropDownListItem > const &first, std::unique_ptr< const DropDownListItem > const &second)
Natural sorting comparator function for DropDownList::sort().
Enum-as-bit-set wrapper.
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:1292
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:1508
Base class for a resizable nested widget.
bool UpdateVerticalSize(uint min_y)
Set absolute (post-scaling) minimal size of the widget.
Definition widget.cpp:1120
void Draw(const Window *w) override
Draw the widgets of the tree.
void SetupSmallestSize(Window *w) override
Compute smallest size needed by the widget.
std::string & GetWidestPlugin(T SocialIntegrationPlugin::*member) const
Find of all the plugins the one where the member is the widest (in pixels).
Vertical container.
void SetupSmallestSize(Window *w) override
Compute smallest size needed by the widget.
Definition widget.cpp:1718
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:2425
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:2499
size_type GetCount() const
Gets the number of elements in the list.
size_type GetPosition() const
Gets the position of the first visible element in the list.
std::string social_platform
Social platform this plugin is for.
std::string name
Name of the plugin.
std::string version
Version of the plugin.
@ PLATFORM_NOT_RUNNING
The plugin failed to initialize because the Social Platform is not running.
@ UNSUPPORTED_API
The plugin does not support the current API version.
@ RUNNING
The plugin is successfully loaded and running.
@ FAILED
The plugin failed to initialize.
@ DUPLICATE
Another plugin of the same Social Platform is already loaded.
@ INVALID_SIGNATURE
The signature of the plugin is invalid.
@ UNLOADED
The plugin is unloaded upon request.
static std::vector< SocialIntegrationPlugin * > GetPlugins()
Get the list of loaded social integration plugins.
static constexpr TimerGame< struct Calendar >::Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date,...
virtual void ToggleVsync(bool vsync)
Change the vsync setting.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
virtual std::vector< int > GetListOfMonitorRefreshRates()
Get a list of refresh rates of each available monitor.
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:40
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
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:38
int hsep_indent
Width of indentation for tree layouts.
Definition window_gui.h:63
Functions related to commands.
Definition of stuff that is very close to a company, like the company struct itself.
Functions related to companies.
Configuration options of the network stuff.
static const std::string NETWORK_SURVEY_DETAILS_LINK
Link with more details & privacy statement of the survey.
Definition config.h:30
std::array< CurrencySpec, CURRENCY_END > _currency_specs
Array of currencies used by the system.
Definition currency.cpp: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:402
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:418
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.
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:709
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:962
int GetStringLineCount(std::string_view str, int maxw)
Calculates number of lines of string.
Definition gfx.cpp:733
bool _left_button_down
Is left mouse button pressed?
Definition gfx.cpp:41
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:891
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:662
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
bool _left_button_clicked
Is left mouse button clicked?
Definition gfx.cpp:42
int _gui_scale_cfg
GUI scale in config.
Definition gfx.cpp:64
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:864
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:779
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:115
SwitchMode _switch_mode
The next mainloop command.
Definition gfx.cpp:49
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:1562
bool AdjustGUIZoom(bool automatic)
Resolve GUI zoom level and adjust GUI to new zoom, if auto-suggestion is requested.
Definition gfx.cpp:1812
int _gui_scale
GUI scale, 100 is 100%.
Definition gfx.cpp:63
void CheckBlitter()
Check whether we still use the right blitter, or use another (better) one.
Definition gfxinit.cpp: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:3374
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:966
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1543
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:2021
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
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:1314
@ 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.
SettingEntryFlag
Flags for SettingEntry.
@ 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_FONT_DEFAULT_TEXT
Text for default font toggle.
@ 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_GUI_FONT_DEFAULT
Toggle whether to prefer the default font over fallback fonts.
@ 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
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:2370
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:2270
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.
MusicSettings music
settings related to music/sound
NetworkSettings network
settings related to the network
GUISettings gui
settings related to the GUI
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
bool prefer_default
Prefer OpenTTD's default font over autodetected fallback fonts.
Definition fontcache.h:270
bool prefer_sprite
Whether to prefer the built-in sprite font over resizable fonts.
Definition fontcache.h:268
bool global_aa
Whether to anti alias all font sizes.
Definition fontcache.h:269
Information about GRF, used in the game and (part of it) in savegames.
void SetParameterDefaults()
Set the default value for all parameters as specified by action14.
std::vector< uint32_t > param
GRF parameters.
uint8_t settings_restriction_mode
selected restriction mode in adv. settings GUI.
uint16_t refresh_rate
How often we refresh the screen (time between draw-ticks).
uint32_t autosave_interval
how often should we do autosaves?
uint8_t missing_strings_threshold
the number of missing strings before showing the warning
bool scale_bevels
bevels are scaled with GUI scale.
void OnResize() override
Called after the window got resized.
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:476
int32_t GetDefaultValue() const
Get the default value of the setting.
Definition settings.cpp:467
StringID GetHelp() const
Get the help text of the setting.
Definition settings.cpp:436
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:445
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition settings.cpp:567
int32_t interval
the interval to use between settings in the 'settings' window. If interval is '0' the interval is dyn...
char own_name[32]
the localized name of this language
Definition language.h:30
uint8_t currency
currency we currently use
uint8_t effect_vol
The requested effects volume.
uint8_t music_vol
The requested music volume.
ParticipateSurvey participate_survey
Participate in the automated survey.
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.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
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:894
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:911
Standard setting.
void SetButtons(SettingEntryFlags new_val)
Set the button-depressed flags (#SettingsEntryFlag::LeftDepressed and #SettingsEntryFlag::RightDepres...
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.
Templated helper to make a type-safe 'typedef' representing a single POD value.
std::string_view GetText() const
Get the current text.
Definition textbuf.cpp:284
Window for displaying a textfile.
TextfileType file_type
Type of textfile to view.
virtual void LoadTextfile(const std::string &textfile, Subdirectory dir)
Loads the textfile text from file and setup lines.
High level window description.
Definition window_gui.h:168
Data structure for an opened window.
Definition window_gui.h:274
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:978
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1102
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1807
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:3234
Window * parent
Parent window.
Definition window_gui.h:329
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:556
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:504
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:1075
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:1797
void CloseChildWindowById(WindowClass wc, WindowNumber number) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1090
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:485
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:286
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition window_gui.h:356
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:1820
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:313
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)
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:1193
void ReInitAllWindows(bool zoom_changed)
Re-initialize all windows.
Definition window.cpp:3410
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1205
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition window.cpp:3202
Window functions not directly related to making/drawing windows.
@ BorderOnly
Draw border only, no background.
@ Lowered
If set the frame is lowered and the background colour brighter (ie. buttons when pressed)
@ Centred
Window is centered and shall stay centered after ReInit.
@ Timeout
Window timeout counter.
@ WDP_CENTER
Center the window.
Definition window_gui.h: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.