OpenTTD Source 20250524-master-gc366e6a48e
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 <http://www.gnu.org/licenses/>.
6 */
7
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
31void BaseSettingEntry::Init(uint8_t level)
32{
33 this->level = level;
34}
35
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 ? -(int)_setting_circle_size.width : (int)_setting_circle_size.width) / 2;
99
100 int x = rtl ? right : left;
101 if (cur_row >= first_row) {
102 int colour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
103 y += (cur_row - first_row) * SETTING_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 + SETTING_HEIGHT - 1, colour);
108 x += level_width;
109 }
110 /* draw own |- prefix */
111 int halfway_y = y + SETTING_HEIGHT / 2;
112 int bottom_y = flags.Test(SettingEntryFlag::LastField) ? halfway_y : y + SETTING_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
131void SettingEntry::Init(uint8_t level)
132{
135}
136
137/* Sets the given setting entry to its default value */
138void SettingEntry::ResetAll()
139{
141}
142
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 }
256 }
257 return settings_ptr;
258}
259
268void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
269{
270 const IntSettingDesc *sd = this->setting;
271 int state = (this->flags & SEF_BUTTONS_MASK).base();
272
273 bool rtl = _current_text_dir == TD_RTL;
274 uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
275 uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide);
276 uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide : 0);
277 uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
278
279 /* We do not allow changes of some items when we are a client in a networkgame */
280 bool editable = sd->IsEditable();
281
282 auto [min_val, max_val] = sd->GetRange();
283 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
284 if (sd->IsBoolSetting()) {
285 /* Draw checkbox for boolean-value either on/off */
286 DrawBoolButton(buttons_left, button_y, COLOUR_YELLOW, COLOUR_MAUVE, value != 0, editable);
287 } else if (sd->flags.Test(SettingFlag::GuiDropdown)) {
288 /* Draw [v] button for settings of an enum-type */
289 DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
290 } else {
291 /* Draw [<][>] boxes for settings of an integer-type */
292 DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
293 editable && value != (sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val), editable && static_cast<uint32_t>(value) != max_val);
294 }
295 auto [param1, param2] = sd->GetValueParams(value);
296 DrawString(text_left, text_right, y + (SETTING_HEIGHT - GetCharacterHeight(FS_NORMAL)) / 2, GetString(sd->GetTitle(), STR_CONFIG_SETTING_VALUE, param1, param2), highlight ? TC_WHITE : TC_LIGHT_BLUE);
297}
298
299/* == SettingsContainer methods == */
300
305void SettingsContainer::Init(uint8_t level)
306{
307 for (auto &it : this->entries) {
308 it->Init(level);
309 }
310}
311
314{
315 for (auto settings_entry : this->entries) {
316 settings_entry->ResetAll();
317 }
318}
319
322{
323 for (auto &it : this->entries) {
324 it->FoldAll();
325 }
326}
327
330{
331 for (auto &it : this->entries) {
332 it->UnFoldAll();
333 }
334}
335
341void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
342{
343 for (auto &it : this->entries) {
344 it->GetFoldingState(all_folded, all_unfolded);
345 }
346}
347
355{
356 bool visible = false;
357 bool first_visible = true;
358 for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
359 visible |= (*it)->UpdateFilterState(filter, force_visible);
360 (*it)->SetLastField(first_visible);
361 if (visible && first_visible) first_visible = false;
362 }
363 return visible;
364}
365
366
374{
375 for (const auto &it : this->entries) {
376 if (it->IsVisible(item)) return true;
377 }
378 return false;
379}
380
383{
384 uint length = 0;
385 for (const auto &it : this->entries) {
386 length += it->Length();
387 }
388 return length;
389}
390
398{
399 BaseSettingEntry *pe = nullptr;
400 for (const auto &it : this->entries) {
401 pe = it->FindEntry(row_num, cur_row);
402 if (pe != nullptr) {
403 break;
404 }
405 }
406 return pe;
407}
408
415{
416 uint biggest = 0;
417 for (const auto &it : this->entries) {
418 biggest = std::max(biggest, it->GetMaxHelpHeight(maxw));
419 }
420 return biggest;
421}
422
423
438uint 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
439{
440 for (const auto &it : this->entries) {
441 cur_row = it->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
442 if (cur_row >= max_row) break;
443 }
444 return cur_row;
445}
446
447/* == SettingsPage methods == */
448
454{
455 this->title = title;
456 this->folded = true;
457}
458
468
471{
472 for (auto settings_entry : this->entries) {
473 settings_entry->ResetAll();
474 }
475}
476
479{
480 if (this->IsFiltered()) return;
481 this->folded = true;
482
484}
485
488{
489 if (this->IsFiltered()) return;
490 this->folded = false;
491
493}
494
500void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
501{
502 if (this->IsFiltered()) return;
503
504 if (this->folded) {
505 all_unfolded = false;
506 } else {
507 all_folded = false;
508 }
509
510 SettingsContainer::GetFoldingState(all_folded, all_unfolded);
511}
512
519bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
520{
521 if (!force_visible && !filter.string.IsEmpty()) {
522 filter.string.ResetState();
523 filter.string.AddLine(GetString(this->title));
524 force_visible = filter.string.GetState();
525 }
526
527 bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
528 this->flags.Set(SettingEntryFlag::Filtered, !visible);
529 return visible;
530}
531
539{
540 if (this->IsFiltered()) return false;
541 if (this == item) return true;
542 if (this->folded) return false;
543
544 return SettingsContainer::IsVisible(item);
545}
546
549{
550 if (this->IsFiltered()) return 0;
551 if (this->folded) return 1; // Only displaying the title
552
553 return 1 + SettingsContainer::Length();
554}
555
562BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
563{
564 if (this->IsFiltered()) return nullptr;
565 if (row_num == *cur_row) return this;
566 (*cur_row)++;
567 if (this->folded) return nullptr;
568
569 return SettingsContainer::FindEntry(row_num, cur_row);
570}
571
586uint 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
587{
588 if (this->IsFiltered()) return cur_row;
589 if (cur_row >= max_row) return cur_row;
590
591 cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
592
593 if (!this->folded) {
595 assert(this->level < 8 * sizeof(parent_last));
596 SetBit(parent_last, this->level); // Add own last-field state
597 }
598
599 cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
600 }
601
602 return cur_row;
603}
604
611void SettingsPage::DrawSetting(GameSettings *, int left, int right, int y, bool) const
612{
613 bool rtl = _current_text_dir == TD_RTL;
614 DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _setting_circle_size.width : left, y + (SETTING_HEIGHT - _setting_circle_size.height) / 2);
616}
617
620{
621 static SettingsContainer *main = nullptr;
622
623 if (main == nullptr)
624 {
625 /* Build up the dynamic settings-array only once per OpenTTD session */
626 main = new SettingsContainer();
627
628 SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
629 {
630 localisation->Add(new SettingEntry("locale.units_velocity"));
631 localisation->Add(new SettingEntry("locale.units_velocity_nautical"));
632 localisation->Add(new SettingEntry("locale.units_power"));
633 localisation->Add(new SettingEntry("locale.units_weight"));
634 localisation->Add(new SettingEntry("locale.units_volume"));
635 localisation->Add(new SettingEntry("locale.units_force"));
636 localisation->Add(new SettingEntry("locale.units_height"));
637 localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
638 }
639
640 SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
641 {
642 graphics->Add(new SettingEntry("gui.zoom_min"));
643 graphics->Add(new SettingEntry("gui.zoom_max"));
644 graphics->Add(new SettingEntry("gui.sprite_zoom_min"));
645 graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
646 graphics->Add(new SettingEntry("gui.linkgraph_colours"));
647 graphics->Add(new SettingEntry("gui.graph_line_thickness"));
648 }
649
650 SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
651 {
652 sound->Add(new SettingEntry("sound.click_beep"));
653 sound->Add(new SettingEntry("sound.confirm"));
654 sound->Add(new SettingEntry("sound.news_ticker"));
655 sound->Add(new SettingEntry("sound.news_full"));
656 sound->Add(new SettingEntry("sound.new_year"));
657 sound->Add(new SettingEntry("sound.disaster"));
658 sound->Add(new SettingEntry("sound.vehicle"));
659 sound->Add(new SettingEntry("sound.ambient"));
660 }
661
662 SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
663 {
664 SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
665 {
666 general->Add(new SettingEntry("gui.osk_activation"));
667 general->Add(new SettingEntry("gui.hover_delay_ms"));
668 general->Add(new SettingEntry("gui.errmsg_duration"));
669 general->Add(new SettingEntry("gui.window_snap_radius"));
670 general->Add(new SettingEntry("gui.window_soft_limit"));
671 general->Add(new SettingEntry("gui.right_click_wnd_close"));
672 }
673
674 SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
675 {
676 viewports->Add(new SettingEntry("gui.auto_scrolling"));
677 viewports->Add(new SettingEntry("gui.scroll_mode"));
678 viewports->Add(new SettingEntry("gui.smooth_scroll"));
679 /* While the horizontal scrollwheel scrolling is written as general code, only
680 * the cocoa (OSX) driver generates input for it.
681 * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
682 viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
683 viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
684#ifdef __APPLE__
685 /* We might need to emulate a right mouse button on mac */
686 viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
687#endif
688 viewports->Add(new SettingEntry("gui.population_in_label"));
689 viewports->Add(new SettingEntry("gui.liveries"));
690 viewports->Add(new SettingEntry("construction.train_signal_side"));
691 viewports->Add(new SettingEntry("gui.measure_tooltip"));
692 viewports->Add(new SettingEntry("gui.loading_indicators"));
693 viewports->Add(new SettingEntry("gui.show_track_reservation"));
694 }
695
696 SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
697 {
698 construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
699 construction->Add(new SettingEntry("gui.persistent_buildingtools"));
700 construction->Add(new SettingEntry("gui.default_rail_type"));
701 construction->Add(new SettingEntry("gui.semaphore_build_before"));
702 construction->Add(new SettingEntry("gui.signal_gui_mode"));
703 construction->Add(new SettingEntry("gui.cycle_signal_types"));
704 construction->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
705 construction->Add(new SettingEntry("gui.auto_remove_signals"));
706 }
707
708 interface->Add(new SettingEntry("gui.toolbar_pos"));
709 interface->Add(new SettingEntry("gui.statusbar_pos"));
710 interface->Add(new SettingEntry("gui.prefer_teamchat"));
711 interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
712 interface->Add(new SettingEntry("gui.timetable_mode"));
713 interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
714 interface->Add(new SettingEntry("gui.show_newgrf_name"));
715 interface->Add(new SettingEntry("gui.show_cargo_in_vehicle_lists"));
716 }
717
718 SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
719 {
720 advisors->Add(new SettingEntry("gui.coloured_news_year"));
721 advisors->Add(new SettingEntry("news_display.general"));
722 advisors->Add(new SettingEntry("news_display.new_vehicles"));
723 advisors->Add(new SettingEntry("news_display.accident"));
724 advisors->Add(new SettingEntry("news_display.accident_other"));
725 advisors->Add(new SettingEntry("news_display.company_info"));
726 advisors->Add(new SettingEntry("news_display.acceptance"));
727 advisors->Add(new SettingEntry("news_display.arrival_player"));
728 advisors->Add(new SettingEntry("news_display.arrival_other"));
729 advisors->Add(new SettingEntry("news_display.advice"));
730 advisors->Add(new SettingEntry("gui.order_review_system"));
731 advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
732 advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
733 advisors->Add(new SettingEntry("gui.old_vehicle_warn"));
734 advisors->Add(new SettingEntry("gui.show_finances"));
735 advisors->Add(new SettingEntry("news_display.economy"));
736 advisors->Add(new SettingEntry("news_display.subsidies"));
737 advisors->Add(new SettingEntry("news_display.open"));
738 advisors->Add(new SettingEntry("news_display.close"));
739 advisors->Add(new SettingEntry("news_display.production_player"));
740 advisors->Add(new SettingEntry("news_display.production_other"));
741 advisors->Add(new SettingEntry("news_display.production_nobody"));
742 }
743
744 SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
745 {
746 company->Add(new SettingEntry("gui.starting_colour"));
747 company->Add(new SettingEntry("gui.starting_colour_secondary"));
748 company->Add(new SettingEntry("company.engine_renew"));
749 company->Add(new SettingEntry("company.engine_renew_months"));
750 company->Add(new SettingEntry("company.engine_renew_money"));
751 company->Add(new SettingEntry("vehicle.servint_ispercent"));
752 company->Add(new SettingEntry("vehicle.servint_trains"));
753 company->Add(new SettingEntry("vehicle.servint_roadveh"));
754 company->Add(new SettingEntry("vehicle.servint_ships"));
755 company->Add(new SettingEntry("vehicle.servint_aircraft"));
756 }
757
758 SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
759 {
760 accounting->Add(new SettingEntry("difficulty.infinite_money"));
761 accounting->Add(new SettingEntry("economy.inflation"));
762 accounting->Add(new SettingEntry("difficulty.initial_interest"));
763 accounting->Add(new SettingEntry("difficulty.max_loan"));
764 accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
765 accounting->Add(new SettingEntry("difficulty.subsidy_duration"));
766 accounting->Add(new SettingEntry("economy.feeder_payment_share"));
767 accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
768 accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
769 accounting->Add(new SettingEntry("difficulty.construction_cost"));
770 }
771
772 SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
773 {
774 SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
775 {
776 physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
777 physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
778 physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
779 physics->Add(new SettingEntry("vehicle.freight_trains"));
780 physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
781 physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
782 physics->Add(new SettingEntry("vehicle.smoke_amount"));
783 physics->Add(new SettingEntry("vehicle.plane_speed"));
784 }
785
786 SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
787 {
788 routing->Add(new SettingEntry("vehicle.road_side"));
789 routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
790 routing->Add(new SettingEntry("pf.reverse_at_signals"));
791 routing->Add(new SettingEntry("pf.forbid_90_deg"));
792 }
793
794 SettingsPage *orders = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ORDERS));
795 {
796 orders->Add(new SettingEntry("gui.new_nonstop"));
797 orders->Add(new SettingEntry("gui.quick_goto"));
798 orders->Add(new SettingEntry("gui.stop_location"));
799 }
800 }
801
802 SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
803 {
804 limitations->Add(new SettingEntry("construction.command_pause_level"));
805 limitations->Add(new SettingEntry("construction.autoslope"));
806 limitations->Add(new SettingEntry("construction.extra_dynamite"));
807 limitations->Add(new SettingEntry("construction.map_height_limit"));
808 limitations->Add(new SettingEntry("construction.max_bridge_length"));
809 limitations->Add(new SettingEntry("construction.max_bridge_height"));
810 limitations->Add(new SettingEntry("construction.max_tunnel_length"));
811 limitations->Add(new SettingEntry("station.never_expire_airports"));
812 limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
813 limitations->Add(new SettingEntry("vehicle.max_trains"));
814 limitations->Add(new SettingEntry("vehicle.max_roadveh"));
815 limitations->Add(new SettingEntry("vehicle.max_aircraft"));
816 limitations->Add(new SettingEntry("vehicle.max_ships"));
817 limitations->Add(new SettingEntry("vehicle.max_train_length"));
818 limitations->Add(new SettingEntry("station.station_spread"));
819 limitations->Add(new SettingEntry("station.distant_join_stations"));
820 limitations->Add(new SettingEntry("station.modified_catchment"));
821 limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
822 limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
823 limitations->Add(new SettingEntry("construction.crossing_with_competitor"));
824 limitations->Add(new SettingEntry("vehicle.disable_elrails"));
825 limitations->Add(new SettingEntry("order.station_length_loading_penalty"));
826 }
827
828 SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
829 {
830 disasters->Add(new SettingEntry("difficulty.disasters"));
831 disasters->Add(new SettingEntry("difficulty.economy"));
832 disasters->Add(new SettingEntry("vehicle.plane_crashes"));
833 disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
834 disasters->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
835 disasters->Add(new SettingEntry("order.serviceathelipad"));
836 }
837
838 SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
839 {
840 genworld->Add(new SettingEntry("game_creation.landscape"));
841 genworld->Add(new SettingEntry("game_creation.land_generator"));
842 genworld->Add(new SettingEntry("difficulty.terrain_type"));
843 genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
844 genworld->Add(new SettingEntry("game_creation.variety"));
845 genworld->Add(new SettingEntry("game_creation.snow_coverage"));
846 genworld->Add(new SettingEntry("game_creation.snow_line_height"));
847 genworld->Add(new SettingEntry("game_creation.desert_coverage"));
848 genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
849 }
850
851 SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
852 {
853 SettingsPage *time = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TIME));
854 {
855 time->Add(new SettingEntry("economy.timekeeping_units"));
856 time->Add(new SettingEntry("economy.minutes_per_calendar_year"));
857 time->Add(new SettingEntry("game_creation.ending_year"));
858 time->Add(new SettingEntry("gui.pause_on_newgame"));
859 time->Add(new SettingEntry("gui.fast_forward_speed_limit"));
860 }
861
862 SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
863 {
864 authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
865 authorities->Add(new SettingEntry("economy.bribe"));
866 authorities->Add(new SettingEntry("economy.exclusive_rights"));
867 authorities->Add(new SettingEntry("economy.fund_roads"));
868 authorities->Add(new SettingEntry("economy.fund_buildings"));
869 authorities->Add(new SettingEntry("economy.station_noise_level"));
870 }
871
872 SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
873 {
874 towns->Add(new SettingEntry("economy.town_cargo_scale"));
875 towns->Add(new SettingEntry("economy.town_growth_rate"));
876 towns->Add(new SettingEntry("economy.allow_town_roads"));
877 towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
878 towns->Add(new SettingEntry("economy.found_town"));
879 towns->Add(new SettingEntry("economy.place_houses"));
880 towns->Add(new SettingEntry("economy.town_layout"));
881 towns->Add(new SettingEntry("economy.larger_towns"));
882 towns->Add(new SettingEntry("economy.initial_city_size"));
883 towns->Add(new SettingEntry("economy.town_cargogen_mode"));
884 }
885
886 SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
887 {
888 industries->Add(new SettingEntry("economy.industry_cargo_scale"));
889 industries->Add(new SettingEntry("difficulty.industry_density"));
890 industries->Add(new SettingEntry("construction.raw_industry_construction"));
891 industries->Add(new SettingEntry("construction.industry_platform"));
892 industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
893 industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
894 industries->Add(new SettingEntry("economy.type"));
895 industries->Add(new SettingEntry("station.serve_neutral_industries"));
896 }
897
898 SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
899 {
900 cdist->Add(new SettingEntry("linkgraph.recalc_time"));
901 cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
902 cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
903 cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
904 cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
905 cdist->Add(new SettingEntry("linkgraph.distribution_default"));
906 cdist->Add(new SettingEntry("linkgraph.accuracy"));
907 cdist->Add(new SettingEntry("linkgraph.demand_distance"));
908 cdist->Add(new SettingEntry("linkgraph.demand_size"));
909 cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
910 }
911
912 SettingsPage *trees = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TREES));
913 {
914 trees->Add(new SettingEntry("game_creation.tree_placer"));
915 trees->Add(new SettingEntry("construction.extra_tree_placement"));
916 }
917 }
918
919 SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
920 {
921 SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
922 {
923 npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
924 npc->Add(new SettingEntry("script.script_max_memory_megabytes"));
925 npc->Add(new SettingEntry("difficulty.competitor_speed"));
926 npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
927 npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
928 npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
929 npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
930 npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
931 }
932
933 ai->Add(new SettingEntry("economy.give_money"));
934 }
935
936 SettingsPage *network = main->Add(new SettingsPage(STR_CONFIG_SETTING_NETWORK));
937 {
938 network->Add(new SettingEntry("network.use_relay_service"));
939 }
940
941 main->Init();
942 }
943 return *main;
944}
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Reset()
Reset all bits.
constexpr Timpl & Set()
Set all bits.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
int hsep_wide
Wide horizontal spacing.
Definition window_gui.h:62
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
int hsep_indent
Width of indentation for tree layouts.
Definition window_gui.h:63
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:77
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:705
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:658
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:1024
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:251
uint8_t 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.
int SETTING_HEIGHT
Height of a single setting in the tree view in pixels.
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.
Dimension _setting_circle_size
Dimension of the circle +/- icon. This is here as not all users are within the class of the settings ...
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:61
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:59
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:415
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:57
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.
virtual void Init(uint8_t level=0)
Initialization of a setting entry.
virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
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.
CompanySettings company
default values for per-company settings
All settings together for the game.
Base integer type, including boolean, settings.
SettingCategory cat
assigned categories of the setting
std::tuple< int32_t, uint32_t > GetRange() const
Get the min/max range for the setting.
Definition settings.cpp:475
StringID GetTitle() const
Get the title of the setting.
Definition settings.cpp:426
int32_t GetDefaultValue() const
Get the default value of the setting.
Definition settings.cpp:466
StringID GetHelp() const
Get the help text of the setting.
Definition settings.cpp:435
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:444
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition settings.cpp:566
static Titem * Get(auto index)
Returns Titem with given index.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
bool IsEditable(bool do_command=false) const
Check whether the setting is editable in the current gamemode.
Definition settings.cpp:893
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:910
const struct IntSettingDesc * AsIntSetting() const
Get the setting description of this setting as an integer setting.
Definition settings.cpp:920
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::RightDepres...
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.