OpenTTD Source 20260206-master-g4d4e37dbf1
settingentry_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11#include "company_base.h"
12#include "company_func.h"
13#include "settingentry_gui.h"
14#include "settings_gui.h"
15#include "settings_internal.h"
16#include "stringfilter_type.h"
17#include "strings_func.h"
18
19#include "table/sprites.h"
20#include "table/strings.h"
21
22#include "safeguards.h"
23
24
25/* == BaseSettingEntry methods == */
26
32{
33 this->level = level;
34}
35
42bool BaseSettingEntry::IsVisible(const BaseSettingEntry *item) const
43{
44 if (this->IsFiltered()) return false;
45 return this == item;
46}
47
54BaseSettingEntry *BaseSettingEntry::FindEntry(uint row_num, uint *cur_row)
55{
56 if (this->IsFiltered()) return nullptr;
57 if (row_num == *cur_row) return this;
58 (*cur_row)++;
59 return nullptr;
60}
61
91uint BaseSettingEntry::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
92{
93 if (this->IsFiltered()) return cur_row;
94 if (cur_row >= max_row) return cur_row;
95
96 bool rtl = _current_text_dir == TD_RTL;
97 int offset = (rtl ? -static_cast<int>(BaseSettingEntry::circle_size.width) : static_cast<int>(BaseSettingEntry::circle_size.width)) / 2;
98 int level_width = rtl ? -WidgetDimensions::scaled.hsep_indent : WidgetDimensions::scaled.hsep_indent;
99
100 int x = rtl ? right : left;
101 if (cur_row >= first_row) {
102 PixelColour colour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
103 y += (cur_row - first_row) * BaseSettingEntry::line_height; // Compute correct y start position
104
105 /* Draw vertical for parent nesting levels */
106 for (uint lvl = 0; lvl < this->level; lvl++) {
107 if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + BaseSettingEntry::line_height - 1, colour);
108 x += level_width;
109 }
110 /* draw own |- prefix */
111 int halfway_y = y + BaseSettingEntry::line_height / 2;
112 int bottom_y = flags.Test(SettingEntryFlag::LastField) ? halfway_y : y + BaseSettingEntry::line_height - 1;
113 GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
114 /* Small horizontal line from the last vertical line */
115 GfxDrawLine(x + offset, halfway_y, x + level_width - (rtl ? -WidgetDimensions::scaled.hsep_normal : WidgetDimensions::scaled.hsep_normal), halfway_y, colour);
116 x += level_width;
117
118 this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
119 }
120 cur_row++;
121
122 return cur_row;
123}
124
125/* == SettingEntry methods == */
126
136
137/* Sets the given setting entry to its default value */
138void SettingEntry::ResetAll()
139{
141}
142
148void SettingEntry::SetButtons(SettingEntryFlags new_val)
149{
150 assert((new_val & SEF_BUTTONS_MASK) == new_val); // Should not touch any flags outside the buttons
153}
154
157{
158 return this->IsFiltered() ? 0 : 1;
159}
160
167{
168 return GetStringHeight(this->setting->GetHelp(), maxw);
169}
170
177{
178 /* There shall not be any restriction, i.e. all settings shall be visible. */
179 if (mode == RM_ALL) return true;
180
181 const IntSettingDesc *sd = this->setting;
182
183 if (mode == RM_BASIC) return (this->setting->cat & SC_BASIC_LIST) != 0;
184 if (mode == RM_ADVANCED) return (this->setting->cat & SC_ADVANCED_LIST) != 0;
185
186 /* Read the current value. */
187 const void *object = ResolveObject(&GetGameSettings(), sd);
188 int64_t current_value = sd->Read(object);
189 int64_t filter_value;
190
191 if (mode == RM_CHANGED_AGAINST_DEFAULT) {
192 /* This entry shall only be visible, if the value deviates from its default value. */
193
194 /* Read the default value. */
195 filter_value = sd->GetDefaultValue();
196 } else {
197 assert(mode == RM_CHANGED_AGAINST_NEW);
198 /* This entry shall only be visible, if the value deviates from
199 * its value is used when starting a new game. */
200
201 /* Make sure we're not comparing the new game settings against itself. */
202 assert(&GetGameSettings() != &_settings_newgame);
203
204 /* Read the new game's value. */
205 filter_value = sd->Read(ResolveObject(&_settings_newgame, sd));
206 }
207
208 return current_value != filter_value;
209}
210
217bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
218{
220
221 bool visible = true;
222
223 const IntSettingDesc *sd = this->setting;
224 if (!force_visible && !filter.string.IsEmpty()) {
225 /* Process the search text filter for this item. */
226 filter.string.ResetState();
227
228 filter.string.AddLine(GetString(sd->GetTitle(), STR_EMPTY));
229 filter.string.AddLine(GetString(sd->GetHelp()));
230
231 visible = filter.string.GetState();
232 }
233
234 if (visible) {
235 if (filter.type != ST_ALL && sd->GetType() != filter.type) {
236 filter.type_hides = true;
237 visible = false;
238 }
239 if (!this->IsVisibleByRestrictionMode(filter.mode)) {
240 while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
241 visible = false;
242 }
243 }
244
245 if (!visible) this->flags.Set(SettingEntryFlag::Filtered);
246 return visible;
247}
248
249const void *ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd)
250{
252 if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
253 return &Company::Get(_local_company)->settings;
254 }
255 return &_settings_client.company;
256 }
257 return settings_ptr;
258}
259
260void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
261{
262 const IntSettingDesc *sd = this->setting;
263 int state = (this->flags & SEF_BUTTONS_MASK).base();
264
265 bool rtl = _current_text_dir == TD_RTL;
266 uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
267 uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide);
268 uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide : 0);
269 uint button_y = y + (BaseSettingEntry::line_height - SETTING_BUTTON_HEIGHT) / 2;
270
271 /* We do not allow changes of some items when we are a client in a networkgame */
272 bool editable = sd->IsEditable();
273
274 auto [min_val, max_val] = sd->GetRange();
275 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
276 if (sd->IsBoolSetting()) {
277 /* Draw checkbox for boolean-value either on/off */
278 DrawBoolButton(buttons_left, button_y, COLOUR_YELLOW, COLOUR_MAUVE, value != 0, editable);
279 } else if (sd->flags.Test(SettingFlag::GuiDropdown)) {
280 /* Draw [v] button for settings of an enum-type */
281 DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
282 } else {
283 /* Draw [<][>] boxes for settings of an integer-type */
284 DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
285 editable && value != (sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val), editable && static_cast<uint32_t>(value) != max_val);
286 }
287 auto [param1, param2] = sd->GetValueParams(value);
288 DrawString(text_left, text_right, y + (BaseSettingEntry::line_height - GetCharacterHeight(FS_NORMAL)) / 2, GetString(sd->GetTitle(), STR_CONFIG_SETTING_VALUE, param1, param2), highlight ? TC_WHITE : TC_LIGHT_BLUE);
289}
290
291/* == SettingsContainer methods == */
292
297void SettingsContainer::Init(uint8_t level)
298{
299 for (auto &it : this->entries) {
300 it->Init(level);
301 }
302}
303
306{
307 for (auto settings_entry : this->entries) {
308 settings_entry->ResetAll();
309 }
310}
311
314{
315 for (auto &it : this->entries) {
316 it->FoldAll();
317 }
318}
319
322{
323 for (auto &it : this->entries) {
324 it->UnFoldAll();
325 }
326}
327
333void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
334{
335 for (auto &it : this->entries) {
336 it->GetFoldingState(all_folded, all_unfolded);
337 }
338}
339
347{
348 bool visible = false;
349 bool first_visible = true;
350 for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
351 visible |= (*it)->UpdateFilterState(filter, force_visible);
352 (*it)->SetLastField(first_visible);
353 if (visible && first_visible) first_visible = false;
354 }
355 return visible;
356}
357
358
366{
367 for (const auto &it : this->entries) {
368 if (it->IsVisible(item)) return true;
369 }
370 return false;
371}
372
375{
376 uint length = 0;
377 for (const auto &it : this->entries) {
378 length += it->Length();
379 }
380 return length;
381}
382
390{
391 BaseSettingEntry *pe = nullptr;
392 for (const auto &it : this->entries) {
393 pe = it->FindEntry(row_num, cur_row);
394 if (pe != nullptr) {
395 break;
396 }
397 }
398 return pe;
399}
400
407{
408 uint biggest = 0;
409 for (const auto &it : this->entries) {
410 biggest = std::max(biggest, it->GetMaxHelpHeight(maxw));
411 }
412 return biggest;
413}
414
415
430uint SettingsContainer::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
431{
432 for (const auto &it : this->entries) {
433 cur_row = it->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
434 if (cur_row >= max_row) break;
435 }
436 return cur_row;
437}
438
439/* == SettingsPage methods == */
440
446{
447 this->title = title;
448 this->folded = true;
449}
450
460
463{
464 for (auto settings_entry : this->entries) {
465 settings_entry->ResetAll();
466 }
467}
468
471{
472 if (this->IsFiltered()) return;
473 this->folded = true;
474
476}
477
480{
481 if (this->IsFiltered()) return;
482 this->folded = false;
483
485}
486
492void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
493{
494 if (this->IsFiltered()) return;
495
496 if (this->folded) {
497 all_unfolded = false;
498 } else {
499 all_folded = false;
500 }
501
502 SettingsContainer::GetFoldingState(all_folded, all_unfolded);
503}
504
511bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
512{
513 if (!force_visible && !filter.string.IsEmpty()) {
514 filter.string.ResetState();
515 filter.string.AddLine(GetString(this->title));
516 force_visible = filter.string.GetState();
517 }
518
519 bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
520 this->flags.Set(SettingEntryFlag::Filtered, !visible);
521 return visible;
522}
523
530bool SettingsPage::IsVisible(const BaseSettingEntry *item) const
531{
532 if (this->IsFiltered()) return false;
533 if (this == item) return true;
534 if (this->folded) return false;
535
536 return SettingsContainer::IsVisible(item);
537}
538
541{
542 if (this->IsFiltered()) return 0;
543 if (this->folded) return 1; // Only displaying the title
544
545 return 1 + SettingsContainer::Length();
546}
547
554BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
555{
556 if (this->IsFiltered()) return nullptr;
557 if (row_num == *cur_row) return this;
558 (*cur_row)++;
559 if (this->folded) return nullptr;
560
561 return SettingsContainer::FindEntry(row_num, cur_row);
562}
563
578uint SettingsPage::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
579{
580 if (this->IsFiltered()) return cur_row;
581 if (cur_row >= max_row) return cur_row;
582
583 cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
584
585 if (!this->folded) {
586 if (this->flags.Test(SettingEntryFlag::LastField)) {
587 assert(this->level < 8 * sizeof(parent_last));
588 SetBit(parent_last, this->level); // Add own last-field state
589 }
590
591 cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
592 }
593
594 return cur_row;
595}
596
597void SettingsPage::DrawSetting(GameSettings *, int left, int right, int y, bool) const
598{
599 bool rtl = _current_text_dir == TD_RTL;
600 DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - BaseSettingEntry::circle_size.width : left, y + (BaseSettingEntry::line_height - BaseSettingEntry::circle_size.height) / 2);
601 DrawString(rtl ? left : left + BaseSettingEntry::circle_size.width + WidgetDimensions::scaled.hsep_normal, rtl ? right - BaseSettingEntry::circle_size.width - WidgetDimensions::scaled.hsep_normal : right, y + (BaseSettingEntry::line_height - GetCharacterHeight(FS_NORMAL)) / 2, this->title, TC_ORANGE);
602}
603
606{
607 static SettingsContainer *main = nullptr;
608
609 if (main == nullptr)
610 {
611 /* Build up the dynamic settings-array only once per OpenTTD session */
612 main = new SettingsContainer();
613
614 SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
615 {
616 localisation->Add(new SettingEntry("locale.units_velocity"));
617 localisation->Add(new SettingEntry("locale.units_velocity_nautical"));
618 localisation->Add(new SettingEntry("locale.units_power"));
619 localisation->Add(new SettingEntry("locale.units_weight"));
620 localisation->Add(new SettingEntry("locale.units_volume"));
621 localisation->Add(new SettingEntry("locale.units_force"));
622 localisation->Add(new SettingEntry("locale.units_height"));
623 localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
624 }
625
626 SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
627 {
628 graphics->Add(new SettingEntry("gui.zoom_min"));
629 graphics->Add(new SettingEntry("gui.zoom_max"));
630 graphics->Add(new SettingEntry("gui.sprite_zoom_min"));
631 graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
632 graphics->Add(new SettingEntry("gui.linkgraph_colours"));
633 graphics->Add(new SettingEntry("gui.graph_line_thickness"));
634 }
635
636 SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
637 {
638 sound->Add(new SettingEntry("sound.click_beep"));
639 sound->Add(new SettingEntry("sound.confirm"));
640 sound->Add(new SettingEntry("sound.news_ticker"));
641 sound->Add(new SettingEntry("sound.news_full"));
642 sound->Add(new SettingEntry("sound.new_year"));
643 sound->Add(new SettingEntry("sound.disaster"));
644 sound->Add(new SettingEntry("sound.vehicle"));
645 sound->Add(new SettingEntry("sound.ambient"));
646 }
647
648 SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
649 {
650 SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
651 {
652 general->Add(new SettingEntry("gui.osk_activation"));
653 general->Add(new SettingEntry("gui.hover_delay_ms"));
654 general->Add(new SettingEntry("gui.errmsg_duration"));
655 general->Add(new SettingEntry("gui.window_snap_radius"));
656 general->Add(new SettingEntry("gui.window_soft_limit"));
657 general->Add(new SettingEntry("gui.right_click_wnd_close"));
658 general->Add(new SettingEntry("gui.toolbar_dropdown_autoselect"));
659 }
660
661 SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
662 {
663 viewports->Add(new SettingEntry("gui.auto_scrolling"));
664 viewports->Add(new SettingEntry("gui.scroll_mode"));
665 viewports->Add(new SettingEntry("gui.smooth_scroll"));
666 /* While the horizontal scrollwheel scrolling is written as general code, only
667 * the cocoa (OSX) driver generates input for it.
668 * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
669 viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
670 viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
671#ifdef __APPLE__
672 /* We might need to emulate a right mouse button on mac */
673 viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
674#endif
675 viewports->Add(new SettingEntry("gui.population_in_label"));
676 viewports->Add(new SettingEntry("gui.liveries"));
677 viewports->Add(new SettingEntry("construction.train_signal_side"));
678 viewports->Add(new SettingEntry("gui.measure_tooltip"));
679 viewports->Add(new SettingEntry("gui.loading_indicators"));
680 viewports->Add(new SettingEntry("gui.show_track_reservation"));
681 }
682
683 SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
684 {
685 construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
686 construction->Add(new SettingEntry("gui.persistent_buildingtools"));
687 construction->Add(new SettingEntry("gui.default_rail_type"));
688 construction->Add(new SettingEntry("gui.semaphore_build_before"));
689 construction->Add(new SettingEntry("gui.signal_gui_mode"));
690 construction->Add(new SettingEntry("gui.cycle_signal_types"));
691 construction->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
692 construction->Add(new SettingEntry("gui.auto_remove_signals"));
693 }
694
695 interface->Add(new SettingEntry("gui.toolbar_pos"));
696 interface->Add(new SettingEntry("gui.statusbar_pos"));
697 interface->Add(new SettingEntry("gui.prefer_teamchat"));
698 interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
699 interface->Add(new SettingEntry("gui.timetable_mode"));
700 interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
701 interface->Add(new SettingEntry("gui.show_newgrf_name"));
702 interface->Add(new SettingEntry("gui.show_cargo_in_vehicle_lists"));
703 }
704
705 SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
706 {
707 advisors->Add(new SettingEntry("gui.coloured_news_year"));
708 advisors->Add(new SettingEntry("news_display.general"));
709 advisors->Add(new SettingEntry("news_display.new_vehicles"));
710 advisors->Add(new SettingEntry("news_display.accident"));
711 advisors->Add(new SettingEntry("news_display.accident_other"));
712 advisors->Add(new SettingEntry("news_display.company_info"));
713 advisors->Add(new SettingEntry("news_display.acceptance"));
714 advisors->Add(new SettingEntry("news_display.arrival_player"));
715 advisors->Add(new SettingEntry("news_display.arrival_other"));
716 advisors->Add(new SettingEntry("news_display.advice"));
717 advisors->Add(new SettingEntry("gui.order_review_system"));
718 advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
719 advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
720 advisors->Add(new SettingEntry("gui.old_vehicle_warn"));
721 advisors->Add(new SettingEntry("gui.show_finances"));
722 advisors->Add(new SettingEntry("news_display.economy"));
723 advisors->Add(new SettingEntry("news_display.subsidies"));
724 advisors->Add(new SettingEntry("news_display.open"));
725 advisors->Add(new SettingEntry("news_display.close"));
726 advisors->Add(new SettingEntry("news_display.production_player"));
727 advisors->Add(new SettingEntry("news_display.production_other"));
728 advisors->Add(new SettingEntry("news_display.production_nobody"));
729 }
730
731 SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
732 {
733 company->Add(new SettingEntry("gui.starting_colour"));
734 company->Add(new SettingEntry("gui.starting_colour_secondary"));
735 company->Add(new SettingEntry("company.engine_renew"));
736 company->Add(new SettingEntry("company.engine_renew_months"));
737 company->Add(new SettingEntry("company.engine_renew_money"));
738 company->Add(new SettingEntry("vehicle.servint_ispercent"));
739 company->Add(new SettingEntry("vehicle.servint_trains"));
740 company->Add(new SettingEntry("vehicle.servint_roadveh"));
741 company->Add(new SettingEntry("vehicle.servint_ships"));
742 company->Add(new SettingEntry("vehicle.servint_aircraft"));
743 }
744
745 SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
746 {
747 accounting->Add(new SettingEntry("difficulty.infinite_money"));
748 accounting->Add(new SettingEntry("economy.inflation"));
749 accounting->Add(new SettingEntry("difficulty.initial_interest"));
750 accounting->Add(new SettingEntry("difficulty.max_loan"));
751 accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
752 accounting->Add(new SettingEntry("difficulty.subsidy_duration"));
753 accounting->Add(new SettingEntry("economy.feeder_payment_share"));
754 accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
755 accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
756 accounting->Add(new SettingEntry("difficulty.construction_cost"));
757 }
758
759 SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
760 {
761 SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
762 {
763 physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
764 physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
765 physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
766 physics->Add(new SettingEntry("vehicle.freight_trains"));
767 physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
768 physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
769 physics->Add(new SettingEntry("vehicle.smoke_amount"));
770 physics->Add(new SettingEntry("vehicle.plane_speed"));
771 }
772
773 SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
774 {
775 routing->Add(new SettingEntry("vehicle.road_side"));
776 routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
777 routing->Add(new SettingEntry("pf.reverse_at_signals"));
778 routing->Add(new SettingEntry("pf.forbid_90_deg"));
779 }
780
781 SettingsPage *orders = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ORDERS));
782 {
783 orders->Add(new SettingEntry("gui.new_nonstop"));
784 orders->Add(new SettingEntry("gui.quick_goto"));
785 orders->Add(new SettingEntry("gui.stop_location"));
786 }
787 }
788
789 SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
790 {
791 limitations->Add(new SettingEntry("construction.command_pause_level"));
792 limitations->Add(new SettingEntry("construction.autoslope"));
793 limitations->Add(new SettingEntry("construction.extra_dynamite"));
794 limitations->Add(new SettingEntry("construction.map_height_limit"));
795 limitations->Add(new SettingEntry("construction.max_bridge_length"));
796 limitations->Add(new SettingEntry("construction.max_bridge_height"));
797 limitations->Add(new SettingEntry("construction.max_tunnel_length"));
798 limitations->Add(new SettingEntry("station.never_expire_airports"));
799 limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
800 limitations->Add(new SettingEntry("vehicle.max_trains"));
801 limitations->Add(new SettingEntry("vehicle.max_roadveh"));
802 limitations->Add(new SettingEntry("vehicle.max_aircraft"));
803 limitations->Add(new SettingEntry("vehicle.max_ships"));
804 limitations->Add(new SettingEntry("vehicle.max_train_length"));
805 limitations->Add(new SettingEntry("station.station_spread"));
806 limitations->Add(new SettingEntry("station.distant_join_stations"));
807 limitations->Add(new SettingEntry("station.modified_catchment"));
808 limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
809 limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
810 limitations->Add(new SettingEntry("construction.crossing_with_competitor"));
811 limitations->Add(new SettingEntry("vehicle.disable_elrails"));
812 limitations->Add(new SettingEntry("order.station_length_loading_penalty"));
813 }
814
815 SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
816 {
817 disasters->Add(new SettingEntry("difficulty.disasters"));
818 disasters->Add(new SettingEntry("difficulty.economy"));
819 disasters->Add(new SettingEntry("vehicle.plane_crashes"));
820 disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
821 disasters->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
822 disasters->Add(new SettingEntry("order.serviceathelipad"));
823 }
824
825 SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
826 {
827 genworld->Add(new SettingEntry("game_creation.landscape"));
828 genworld->Add(new SettingEntry("game_creation.land_generator"));
829 genworld->Add(new SettingEntry("difficulty.terrain_type"));
830 genworld->Add(new SettingEntry("game_creation.average_height"));
831 genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
832 genworld->Add(new SettingEntry("game_creation.variety"));
833 genworld->Add(new SettingEntry("game_creation.snow_coverage"));
834 genworld->Add(new SettingEntry("game_creation.snow_line_height"));
835 genworld->Add(new SettingEntry("game_creation.desert_coverage"));
836 genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
837 }
838
839 SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
840 {
841 SettingsPage *time = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TIME));
842 {
843 time->Add(new SettingEntry("economy.timekeeping_units"));
844 time->Add(new SettingEntry("economy.minutes_per_calendar_year"));
845 time->Add(new SettingEntry("game_creation.ending_year"));
846 time->Add(new SettingEntry("gui.pause_on_newgame"));
847 time->Add(new SettingEntry("gui.fast_forward_speed_limit"));
848 }
849
850 SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
851 {
852 authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
853 authorities->Add(new SettingEntry("economy.bribe"));
854 authorities->Add(new SettingEntry("economy.exclusive_rights"));
855 authorities->Add(new SettingEntry("economy.fund_roads"));
856 authorities->Add(new SettingEntry("economy.fund_buildings"));
857 authorities->Add(new SettingEntry("economy.station_noise_level"));
858 }
859
860 SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
861 {
862 towns->Add(new SettingEntry("economy.town_cargo_scale"));
863 towns->Add(new SettingEntry("economy.town_growth_rate"));
864 towns->Add(new SettingEntry("economy.allow_town_roads"));
865 towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
866 towns->Add(new SettingEntry("economy.found_town"));
867 towns->Add(new SettingEntry("economy.place_houses"));
868 towns->Add(new SettingEntry("economy.town_layout"));
869 towns->Add(new SettingEntry("economy.larger_towns"));
870 towns->Add(new SettingEntry("economy.initial_city_size"));
871 towns->Add(new SettingEntry("economy.town_min_distance"));
872 towns->Add(new SettingEntry("economy.town_cargogen_mode"));
873 }
874
875 SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
876 {
877 industries->Add(new SettingEntry("economy.industry_cargo_scale"));
878 industries->Add(new SettingEntry("difficulty.industry_density"));
879 industries->Add(new SettingEntry("construction.raw_industry_construction"));
880 industries->Add(new SettingEntry("construction.industry_platform"));
881 industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
882 industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
883 industries->Add(new SettingEntry("economy.type"));
884 industries->Add(new SettingEntry("station.serve_neutral_industries"));
885 }
886
887 SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
888 {
889 cdist->Add(new SettingEntry("linkgraph.recalc_time"));
890 cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
891 cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
892 cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
893 cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
894 cdist->Add(new SettingEntry("linkgraph.distribution_default"));
895 cdist->Add(new SettingEntry("linkgraph.accuracy"));
896 cdist->Add(new SettingEntry("linkgraph.demand_distance"));
897 cdist->Add(new SettingEntry("linkgraph.demand_size"));
898 cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
899 }
900
901 SettingsPage *trees = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TREES));
902 {
903 trees->Add(new SettingEntry("game_creation.tree_placer"));
904 trees->Add(new SettingEntry("construction.extra_tree_placement"));
905 }
906 }
907
908 SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
909 {
910 SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
911 {
912 npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
913 npc->Add(new SettingEntry("script.script_max_memory_megabytes"));
914 npc->Add(new SettingEntry("difficulty.competitor_speed"));
915 npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
916 npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
917 npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
918 npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
919 npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
920 }
921
922 ai->Add(new SettingEntry("economy.give_money"));
923 }
924
925 SettingsPage *network = main->Add(new SettingsPage(STR_CONFIG_SETTING_NETWORK));
926 {
927 network->Add(new SettingEntry("network.use_relay_service"));
928 }
929
930 main->Init();
931 }
932 return *main;
933}
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
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 WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:87
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:717
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:669
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:1038
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:249
PixelColour GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:388
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_ADVANCED
Display settings associated to the "advanced" list.
@ RM_ALL
List all settings regardless of the default/newgame/... values.
@ RM_CHANGED_AGAINST_NEW
Show only settings which are different compared to the user's new game setting values.
@ RM_BASIC
Display settings associated to the "basic" list.
static constexpr SettingEntryFlags SEF_BUTTONS_MASK
Mask for button flags.
@ LeftDepressed
Of a numeric setting entry, the left button is depressed.
@ LastField
This entry is the last one in a (sub-)page.
@ RightDepressed
Of a numeric setting entry, the right button is depressed.
@ Filtered
Entry is hidden by the string filter.
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
static const SettingDesc * GetSettingFromName(std::string_view name, const SettingTable &settings)
Given a name of setting, return a setting description from the table.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
Draw [<][>] boxes.
void DrawBoolButton(int x, int y, Colours button_colour, Colours background, bool state, bool clickable)
Draw a toggle button.
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
Draw a dropdown button.
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.
@ PerCompany
This setting can be different for each company (saved in company struct).
@ GuiZeroIsSpecial
A value of zero is possible and has a custom string (the one after "strval").
@ GuiDropdown
The value represents a limited number of string-options (internally integer) presented as dropdown.
@ ST_ALL
Used in setting filter to match all types.
@ SC_ADVANCED_LIST
Settings displayed in the list of advanced settings.
@ SC_BASIC_LIST
Settings displayed in the list of basic settings.
GameSettings & GetGameSettings()
Get the settings-object applicable for the current situation: the newgame settings when we're in the ...
This file contains all sprite-related enums and defines.
Definition of base types and functions in a cross-platform compatible way.
Searching and filtering using a stringterm.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
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.
@ TD_RTL
Text is written right-to-left by default.
Data structure describing a single setting in a tab.
bool IsFiltered() const
Check whether an entry is hidden due to filters.
virtual BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find setting entry at row row_num.
static Dimension circle_size
Dimension of the circle +/- icon.
virtual void Init(uint8_t level=0)
Initialization of a setting entry.
static int line_height
Height of a single setting.
virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const =0
Function to draw setting value (button + text + current value).
SettingEntryFlags flags
Flags of the setting entry.
virtual bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
uint8_t level
Nesting level of this setting entry.
All settings together for the game.
Base integer type, including boolean, settings.
std::tuple< int32_t, uint32_t > GetRange() const
Get the min/max range for the setting.
Definition settings.cpp:473
StringID GetTitle() const
Get the title of the setting.
Definition settings.cpp:424
int32_t GetDefaultValue() const
Get the default value of the setting.
Definition settings.cpp:464
StringID GetHelp() const
Get the help text of the setting.
Definition settings.cpp:433
virtual bool IsBoolSetting() const
Check whether this setting is a boolean type setting.
std::pair< StringParameter, StringParameter > GetValueParams(int32_t value) const
Get parameters for drawing the value of the setting.
Definition settings.cpp:442
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition settings.cpp:564
Colour for pixel/line drawing.
Definition gfx_type.h:405
static Company * Get(auto index)
bool IsEditable(bool do_command=false) const
Check whether the setting is editable in the current gamemode.
Definition settings.cpp:891
SettingFlags flags
Handles how a setting would show up in the GUI (text/currency, etc.).
SettingType GetType() const
Return the type of the setting.
Definition settings.cpp:908
const struct IntSettingDesc * AsIntSetting() const
Get the setting description of this setting as an integer setting.
Definition settings.cpp:918
Standard setting.
uint Length() const override
Return number of rows needed to display the (filtered) entry.
void SetButtons(SettingEntryFlags new_val)
Set the button-depressed flags (SettingsEntryFlag::LeftDepressed and SettingsEntryFlag::RightDepresse...
void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const override
Function to draw setting value (button + text + current value).
bool IsVisibleByRestrictionMode(RestrictionMode mode) const
Checks whether an entry shall be made visible based on the restriction mode.
const std::string_view name
Name of the setting.
uint GetMaxHelpHeight(int maxw) override
Get the biggest height of the help text(s), if the width is at least maxw.
void Init(uint8_t level=0) override
Initialization of a setting entry.
const IntSettingDesc * setting
Setting description of the setting.
bool UpdateFilterState(SettingFilter &filter, bool force_visible) override
Update the filter state.
Filter for settings list.
SettingType type
Filter based on type.
bool type_hides
Whether the type hides filtered strings.
RestrictionMode mode
Filter based on category.
RestrictionMode min_cat
Minimum category needed to display all filtered strings (RM_BASIC, RM_ADVANCED, or RM_ALL).
StringFilter string
Filter string.
Containers for BaseSettingEntry.
bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
void GetFoldingState(bool &all_folded, bool &all_unfolded) const
Recursively accumulate the folding state of the tree.
uint GetMaxHelpHeight(int maxw)
Get the biggest height of the help texts, if the width is at least maxw.
void ResetAll()
Resets all settings to their default values.
bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
void FoldAll()
Recursively close all folds of sub-pages.
void UnFoldAll()
Recursively open all folds of sub-pages.
BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find the setting entry at row number row_num.
EntryVector entries
Settings on this page.
uint Length() const
Return number of rows needed to display the whole page.
uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
void Init(uint8_t level=0)
Initialization of an entire setting page.
Data structure describing one page of settings in the settings window.
StringID title
Title of the sub-page.
bool IsVisible(const BaseSettingEntry *item) const override
Check whether an entry is visible and not folded or filtered away.
SettingsPage(StringID title)
Constructor for a sub-page in the 'advanced settings' window.
void UnFoldAll() override
Recursively open all (filtered) folds of sub-pages.
void FoldAll() override
Recursively close all (filtered) folds of sub-pages.
uint Length() const override
Return number of rows needed to display the (filtered) entry.
BaseSettingEntry * FindEntry(uint row, uint *cur_row) override
Find setting entry at row row_num.
uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const override
Draw a row in the settings panel.
void Init(uint8_t level=0) override
Initialization of an entire setting page.
void GetFoldingState(bool &all_folded, bool &all_unfolded) const override
Recursively accumulate the folding state of the (filtered) tree.
void ResetAll() override
Resets all settings to their default values.
bool folded
Sub-page is folded (not visible except for its title).
bool UpdateFilterState(SettingFilter &filter, bool force_visible) override
Update the filter state.
void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const override
Function to draw setting value (button + text + current value).
bool IsEmpty() const
Check whether any filter words were entered.
void ResetState()
Reset the matching state to process a new item.
bool GetState() const
Get the matching state of the current item.