OpenTTD Source 20250312-master-gcdcc6b491d
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
21#include "safeguards.h"
22
23
24/* == BaseSettingEntry methods == */
25
30void BaseSettingEntry::Init(uint8_t level)
31{
32 this->level = level;
33}
34
42{
43 if (this->IsFiltered()) return false;
44 return this == item;
45}
46
53BaseSettingEntry *BaseSettingEntry::FindEntry(uint row_num, uint *cur_row)
54{
55 if (this->IsFiltered()) return nullptr;
56 if (row_num == *cur_row) return this;
57 (*cur_row)++;
58 return nullptr;
59}
60
90uint 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
91{
92 if (this->IsFiltered()) return cur_row;
93 if (cur_row >= max_row) return cur_row;
94
95 bool rtl = _current_text_dir == TD_RTL;
96 int offset = (rtl ? -(int)_circle_size.width : (int)_circle_size.width) / 2;
98
99 int x = rtl ? right : left;
100 if (cur_row >= first_row) {
101 int colour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL);
102 y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
103
104 /* Draw vertical for parent nesting levels */
105 for (uint lvl = 0; lvl < this->level; lvl++) {
106 if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
107 x += level_width;
108 }
109 /* draw own |- prefix */
110 int halfway_y = y + SETTING_HEIGHT / 2;
111 int bottom_y = flags.Test(SettingEntryFlag::LastField) ? halfway_y : y + SETTING_HEIGHT - 1;
112 GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
113 /* Small horizontal line from the last vertical line */
114 GfxDrawLine(x + offset, halfway_y, x + level_width - (rtl ? -WidgetDimensions::scaled.hsep_normal : WidgetDimensions::scaled.hsep_normal), halfway_y, colour);
115 x += level_width;
116
117 this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
118 }
119 cur_row++;
120
121 return cur_row;
122}
123
124/* == SettingEntry methods == */
125
131{
132 this->name = name;
133 this->setting = nullptr;
134}
135
140void SettingEntry::Init(uint8_t level)
141{
144}
145
146/* Sets the given setting entry to its default value */
147void SettingEntry::ResetAll()
148{
150}
151
158{
159 assert((new_val & SEF_BUTTONS_MASK) == new_val); // Should not touch any flags outside the buttons
162}
163
166{
167 return this->IsFiltered() ? 0 : 1;
168}
169
176{
177 return GetStringHeight(this->setting->GetHelp(), maxw);
178}
179
186{
187 /* There shall not be any restriction, i.e. all settings shall be visible. */
188 if (mode == RM_ALL) return true;
189
190 const IntSettingDesc *sd = this->setting;
191
192 if (mode == RM_BASIC) return (this->setting->cat & SC_BASIC_LIST) != 0;
193 if (mode == RM_ADVANCED) return (this->setting->cat & SC_ADVANCED_LIST) != 0;
194
195 /* Read the current value. */
196 const void *object = ResolveObject(&GetGameSettings(), sd);
197 int64_t current_value = sd->Read(object);
198 int64_t filter_value;
199
200 if (mode == RM_CHANGED_AGAINST_DEFAULT) {
201 /* This entry shall only be visible, if the value deviates from its default value. */
202
203 /* Read the default value. */
204 filter_value = sd->GetDefaultValue();
205 } else {
206 assert(mode == RM_CHANGED_AGAINST_NEW);
207 /* This entry shall only be visible, if the value deviates from
208 * its value is used when starting a new game. */
209
210 /* Make sure we're not comparing the new game settings against itself. */
211 assert(&GetGameSettings() != &_settings_newgame);
212
213 /* Read the new game's value. */
214 filter_value = sd->Read(ResolveObject(&_settings_newgame, sd));
215 }
216
217 return current_value != filter_value;
218}
219
226bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
227{
229
230 bool visible = true;
231
232 const IntSettingDesc *sd = this->setting;
233 if (!force_visible && !filter.string.IsEmpty()) {
234 /* Process the search text filter for this item. */
235 filter.string.ResetState();
236
237 filter.string.AddLine(GetString(sd->GetTitle(), STR_EMPTY));
238 filter.string.AddLine(GetString(sd->GetHelp()));
239
240 visible = filter.string.GetState();
241 }
242
243 if (visible) {
244 if (filter.type != ST_ALL && sd->GetType() != filter.type) {
245 filter.type_hides = true;
246 visible = false;
247 }
248 if (!this->IsVisibleByRestrictionMode(filter.mode)) {
249 while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
250 visible = false;
251 }
252 }
253
254 if (!visible) this->flags.Set(SettingEntryFlag::Filtered);
255 return visible;
256}
257
258const void *ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd)
259{
261 if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
262 return &Company::Get(_local_company)->settings;
263 }
265 }
266 return settings_ptr;
267}
268
277void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
278{
279 const IntSettingDesc *sd = this->setting;
280 int state = (this->flags & SEF_BUTTONS_MASK).base();
281
282 bool rtl = _current_text_dir == TD_RTL;
283 uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
284 uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide);
285 uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide : 0);
286 uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
287
288 /* We do not allow changes of some items when we are a client in a networkgame */
289 bool editable = sd->IsEditable();
290
291 auto [min_val, max_val] = sd->GetRange();
292 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
293 if (sd->IsBoolSetting()) {
294 /* Draw checkbox for boolean-value either on/off */
295 DrawBoolButton(buttons_left, button_y, value != 0, editable);
296 } else if (sd->flags.Test(SettingFlag::GuiDropdown)) {
297 /* Draw [v] button for settings of an enum-type */
298 DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
299 } else {
300 /* Draw [<][>] boxes for settings of an integer-type */
301 DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
302 editable && value != (sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val), editable && static_cast<uint32_t>(value) != max_val);
303 }
304 auto [param1, param2] = sd->GetValueParams(value);
305 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);
306}
307
308/* == SettingsContainer methods == */
309
314void SettingsContainer::Init(uint8_t level)
315{
316 for (auto &it : this->entries) {
317 it->Init(level);
318 }
319}
320
323{
324 for (auto settings_entry : this->entries) {
325 settings_entry->ResetAll();
326 }
327}
328
331{
332 for (auto &it : this->entries) {
333 it->FoldAll();
334 }
335}
336
339{
340 for (auto &it : this->entries) {
341 it->UnFoldAll();
342 }
343}
344
350void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
351{
352 for (auto &it : this->entries) {
353 it->GetFoldingState(all_folded, all_unfolded);
354 }
355}
356
364{
365 bool visible = false;
366 bool first_visible = true;
367 for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
368 visible |= (*it)->UpdateFilterState(filter, force_visible);
369 (*it)->SetLastField(first_visible);
370 if (visible && first_visible) first_visible = false;
371 }
372 return visible;
373}
374
375
383{
384 for (const auto &it : this->entries) {
385 if (it->IsVisible(item)) return true;
386 }
387 return false;
388}
389
392{
393 uint length = 0;
394 for (const auto &it : this->entries) {
395 length += it->Length();
396 }
397 return length;
398}
399
407{
408 BaseSettingEntry *pe = nullptr;
409 for (const auto &it : this->entries) {
410 pe = it->FindEntry(row_num, cur_row);
411 if (pe != nullptr) {
412 break;
413 }
414 }
415 return pe;
416}
417
424{
425 uint biggest = 0;
426 for (const auto &it : this->entries) {
427 biggest = std::max(biggest, it->GetMaxHelpHeight(maxw));
428 }
429 return biggest;
430}
431
432
447uint 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
448{
449 for (const auto &it : this->entries) {
450 cur_row = it->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
451 if (cur_row >= max_row) break;
452 }
453 return cur_row;
454}
455
456/* == SettingsPage methods == */
457
463{
464 this->title = title;
465 this->folded = true;
466}
467
477
480{
481 for (auto settings_entry : this->entries) {
482 settings_entry->ResetAll();
483 }
484}
485
488{
489 if (this->IsFiltered()) return;
490 this->folded = true;
491
493}
494
497{
498 if (this->IsFiltered()) return;
499 this->folded = false;
500
502}
503
509void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
510{
511 if (this->IsFiltered()) return;
512
513 if (this->folded) {
514 all_unfolded = false;
515 } else {
516 all_folded = false;
517 }
518
519 SettingsContainer::GetFoldingState(all_folded, all_unfolded);
520}
521
528bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
529{
530 if (!force_visible && !filter.string.IsEmpty()) {
531 filter.string.ResetState();
532 filter.string.AddLine(GetString(this->title));
533 force_visible = filter.string.GetState();
534 }
535
536 bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
537 this->flags.Set(SettingEntryFlag::Filtered, !visible);
538 return visible;
539}
540
548{
549 if (this->IsFiltered()) return false;
550 if (this == item) return true;
551 if (this->folded) return false;
552
553 return SettingsContainer::IsVisible(item);
554}
555
558{
559 if (this->IsFiltered()) return 0;
560 if (this->folded) return 1; // Only displaying the title
561
562 return 1 + SettingsContainer::Length();
563}
564
571BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
572{
573 if (this->IsFiltered()) return nullptr;
574 if (row_num == *cur_row) return this;
575 (*cur_row)++;
576 if (this->folded) return nullptr;
577
578 return SettingsContainer::FindEntry(row_num, cur_row);
579}
580
595uint 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
596{
597 if (this->IsFiltered()) return cur_row;
598 if (cur_row >= max_row) return cur_row;
599
600 cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
601
602 if (!this->folded) {
604 assert(this->level < 8 * sizeof(parent_last));
605 SetBit(parent_last, this->level); // Add own last-field state
606 }
607
608 cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
609 }
610
611 return cur_row;
612}
613
620void SettingsPage::DrawSetting(GameSettings *, int left, int right, int y, bool) const
621{
622 bool rtl = _current_text_dir == TD_RTL;
623 DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
624 DrawString(rtl ? left : left + _circle_size.width + WidgetDimensions::scaled.hsep_normal, rtl ? right - _circle_size.width - WidgetDimensions::scaled.hsep_normal : right, y + (SETTING_HEIGHT - GetCharacterHeight(FS_NORMAL)) / 2, this->title, TC_ORANGE);
625}
626
629{
630 static SettingsContainer *main = nullptr;
631
632 if (main == nullptr)
633 {
634 /* Build up the dynamic settings-array only once per OpenTTD session */
635 main = new SettingsContainer();
636
637 SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
638 {
639 localisation->Add(new SettingEntry("locale.units_velocity"));
640 localisation->Add(new SettingEntry("locale.units_velocity_nautical"));
641 localisation->Add(new SettingEntry("locale.units_power"));
642 localisation->Add(new SettingEntry("locale.units_weight"));
643 localisation->Add(new SettingEntry("locale.units_volume"));
644 localisation->Add(new SettingEntry("locale.units_force"));
645 localisation->Add(new SettingEntry("locale.units_height"));
646 localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
647 }
648
649 SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
650 {
651 graphics->Add(new SettingEntry("gui.zoom_min"));
652 graphics->Add(new SettingEntry("gui.zoom_max"));
653 graphics->Add(new SettingEntry("gui.sprite_zoom_min"));
654 graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
655 graphics->Add(new SettingEntry("gui.linkgraph_colours"));
656 graphics->Add(new SettingEntry("gui.graph_line_thickness"));
657 }
658
659 SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
660 {
661 sound->Add(new SettingEntry("sound.click_beep"));
662 sound->Add(new SettingEntry("sound.confirm"));
663 sound->Add(new SettingEntry("sound.news_ticker"));
664 sound->Add(new SettingEntry("sound.news_full"));
665 sound->Add(new SettingEntry("sound.new_year"));
666 sound->Add(new SettingEntry("sound.disaster"));
667 sound->Add(new SettingEntry("sound.vehicle"));
668 sound->Add(new SettingEntry("sound.ambient"));
669 }
670
671 SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
672 {
673 SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
674 {
675 general->Add(new SettingEntry("gui.osk_activation"));
676 general->Add(new SettingEntry("gui.hover_delay_ms"));
677 general->Add(new SettingEntry("gui.errmsg_duration"));
678 general->Add(new SettingEntry("gui.window_snap_radius"));
679 general->Add(new SettingEntry("gui.window_soft_limit"));
680 general->Add(new SettingEntry("gui.right_click_wnd_close"));
681 }
682
683 SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
684 {
685 viewports->Add(new SettingEntry("gui.auto_scrolling"));
686 viewports->Add(new SettingEntry("gui.scroll_mode"));
687 viewports->Add(new SettingEntry("gui.smooth_scroll"));
688 /* While the horizontal scrollwheel scrolling is written as general code, only
689 * the cocoa (OSX) driver generates input for it.
690 * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
691 viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
692 viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
693#ifdef __APPLE__
694 /* We might need to emulate a right mouse button on mac */
695 viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
696#endif
697 viewports->Add(new SettingEntry("gui.population_in_label"));
698 viewports->Add(new SettingEntry("gui.liveries"));
699 viewports->Add(new SettingEntry("construction.train_signal_side"));
700 viewports->Add(new SettingEntry("gui.measure_tooltip"));
701 viewports->Add(new SettingEntry("gui.loading_indicators"));
702 viewports->Add(new SettingEntry("gui.show_track_reservation"));
703 }
704
705 SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
706 {
707 construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
708 construction->Add(new SettingEntry("gui.persistent_buildingtools"));
709 construction->Add(new SettingEntry("gui.default_rail_type"));
710 construction->Add(new SettingEntry("gui.semaphore_build_before"));
711 construction->Add(new SettingEntry("gui.signal_gui_mode"));
712 construction->Add(new SettingEntry("gui.cycle_signal_types"));
713 construction->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
714 construction->Add(new SettingEntry("gui.auto_remove_signals"));
715 }
716
717 interface->Add(new SettingEntry("gui.toolbar_pos"));
718 interface->Add(new SettingEntry("gui.statusbar_pos"));
719 interface->Add(new SettingEntry("gui.prefer_teamchat"));
720 interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
721 interface->Add(new SettingEntry("gui.timetable_mode"));
722 interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
723 interface->Add(new SettingEntry("gui.show_newgrf_name"));
724 interface->Add(new SettingEntry("gui.show_cargo_in_vehicle_lists"));
725 }
726
727 SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
728 {
729 advisors->Add(new SettingEntry("gui.coloured_news_year"));
730 advisors->Add(new SettingEntry("news_display.general"));
731 advisors->Add(new SettingEntry("news_display.new_vehicles"));
732 advisors->Add(new SettingEntry("news_display.accident"));
733 advisors->Add(new SettingEntry("news_display.accident_other"));
734 advisors->Add(new SettingEntry("news_display.company_info"));
735 advisors->Add(new SettingEntry("news_display.acceptance"));
736 advisors->Add(new SettingEntry("news_display.arrival_player"));
737 advisors->Add(new SettingEntry("news_display.arrival_other"));
738 advisors->Add(new SettingEntry("news_display.advice"));
739 advisors->Add(new SettingEntry("gui.order_review_system"));
740 advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
741 advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
742 advisors->Add(new SettingEntry("gui.old_vehicle_warn"));
743 advisors->Add(new SettingEntry("gui.show_finances"));
744 advisors->Add(new SettingEntry("news_display.economy"));
745 advisors->Add(new SettingEntry("news_display.subsidies"));
746 advisors->Add(new SettingEntry("news_display.open"));
747 advisors->Add(new SettingEntry("news_display.close"));
748 advisors->Add(new SettingEntry("news_display.production_player"));
749 advisors->Add(new SettingEntry("news_display.production_other"));
750 advisors->Add(new SettingEntry("news_display.production_nobody"));
751 }
752
753 SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
754 {
755 company->Add(new SettingEntry("gui.starting_colour"));
756 company->Add(new SettingEntry("gui.starting_colour_secondary"));
757 company->Add(new SettingEntry("company.engine_renew"));
758 company->Add(new SettingEntry("company.engine_renew_months"));
759 company->Add(new SettingEntry("company.engine_renew_money"));
760 company->Add(new SettingEntry("vehicle.servint_ispercent"));
761 company->Add(new SettingEntry("vehicle.servint_trains"));
762 company->Add(new SettingEntry("vehicle.servint_roadveh"));
763 company->Add(new SettingEntry("vehicle.servint_ships"));
764 company->Add(new SettingEntry("vehicle.servint_aircraft"));
765 }
766
767 SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
768 {
769 accounting->Add(new SettingEntry("difficulty.infinite_money"));
770 accounting->Add(new SettingEntry("economy.inflation"));
771 accounting->Add(new SettingEntry("difficulty.initial_interest"));
772 accounting->Add(new SettingEntry("difficulty.max_loan"));
773 accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
774 accounting->Add(new SettingEntry("difficulty.subsidy_duration"));
775 accounting->Add(new SettingEntry("economy.feeder_payment_share"));
776 accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
777 accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
778 accounting->Add(new SettingEntry("difficulty.construction_cost"));
779 }
780
781 SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
782 {
783 SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
784 {
785 physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
786 physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
787 physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
788 physics->Add(new SettingEntry("vehicle.freight_trains"));
789 physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
790 physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
791 physics->Add(new SettingEntry("vehicle.smoke_amount"));
792 physics->Add(new SettingEntry("vehicle.plane_speed"));
793 }
794
795 SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
796 {
797 routing->Add(new SettingEntry("vehicle.road_side"));
798 routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
799 routing->Add(new SettingEntry("pf.reverse_at_signals"));
800 routing->Add(new SettingEntry("pf.forbid_90_deg"));
801 }
802
803 SettingsPage *orders = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ORDERS));
804 {
805 orders->Add(new SettingEntry("gui.new_nonstop"));
806 orders->Add(new SettingEntry("gui.quick_goto"));
807 orders->Add(new SettingEntry("gui.stop_location"));
808 }
809 }
810
811 SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
812 {
813 limitations->Add(new SettingEntry("construction.command_pause_level"));
814 limitations->Add(new SettingEntry("construction.autoslope"));
815 limitations->Add(new SettingEntry("construction.extra_dynamite"));
816 limitations->Add(new SettingEntry("construction.map_height_limit"));
817 limitations->Add(new SettingEntry("construction.max_bridge_length"));
818 limitations->Add(new SettingEntry("construction.max_bridge_height"));
819 limitations->Add(new SettingEntry("construction.max_tunnel_length"));
820 limitations->Add(new SettingEntry("station.never_expire_airports"));
821 limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
822 limitations->Add(new SettingEntry("vehicle.max_trains"));
823 limitations->Add(new SettingEntry("vehicle.max_roadveh"));
824 limitations->Add(new SettingEntry("vehicle.max_aircraft"));
825 limitations->Add(new SettingEntry("vehicle.max_ships"));
826 limitations->Add(new SettingEntry("vehicle.max_train_length"));
827 limitations->Add(new SettingEntry("station.station_spread"));
828 limitations->Add(new SettingEntry("station.distant_join_stations"));
829 limitations->Add(new SettingEntry("station.modified_catchment"));
830 limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
831 limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
832 limitations->Add(new SettingEntry("construction.crossing_with_competitor"));
833 limitations->Add(new SettingEntry("vehicle.disable_elrails"));
834 limitations->Add(new SettingEntry("order.station_length_loading_penalty"));
835 }
836
837 SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
838 {
839 disasters->Add(new SettingEntry("difficulty.disasters"));
840 disasters->Add(new SettingEntry("difficulty.economy"));
841 disasters->Add(new SettingEntry("vehicle.plane_crashes"));
842 disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
843 disasters->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
844 disasters->Add(new SettingEntry("order.serviceathelipad"));
845 }
846
847 SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
848 {
849 genworld->Add(new SettingEntry("game_creation.landscape"));
850 genworld->Add(new SettingEntry("game_creation.land_generator"));
851 genworld->Add(new SettingEntry("difficulty.terrain_type"));
852 genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
853 genworld->Add(new SettingEntry("game_creation.variety"));
854 genworld->Add(new SettingEntry("game_creation.snow_coverage"));
855 genworld->Add(new SettingEntry("game_creation.snow_line_height"));
856 genworld->Add(new SettingEntry("game_creation.desert_coverage"));
857 genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
858 }
859
860 SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
861 {
862 SettingsPage *time = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TIME));
863 {
864 time->Add(new SettingEntry("economy.timekeeping_units"));
865 time->Add(new SettingEntry("economy.minutes_per_calendar_year"));
866 time->Add(new SettingEntry("game_creation.ending_year"));
867 time->Add(new SettingEntry("gui.pause_on_newgame"));
868 time->Add(new SettingEntry("gui.fast_forward_speed_limit"));
869 }
870
871 SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
872 {
873 authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
874 authorities->Add(new SettingEntry("economy.bribe"));
875 authorities->Add(new SettingEntry("economy.exclusive_rights"));
876 authorities->Add(new SettingEntry("economy.fund_roads"));
877 authorities->Add(new SettingEntry("economy.fund_buildings"));
878 authorities->Add(new SettingEntry("economy.station_noise_level"));
879 }
880
881 SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
882 {
883 towns->Add(new SettingEntry("economy.town_cargo_scale"));
884 towns->Add(new SettingEntry("economy.town_growth_rate"));
885 towns->Add(new SettingEntry("economy.allow_town_roads"));
886 towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
887 towns->Add(new SettingEntry("economy.found_town"));
888 towns->Add(new SettingEntry("economy.place_houses"));
889 towns->Add(new SettingEntry("economy.town_layout"));
890 towns->Add(new SettingEntry("economy.larger_towns"));
891 towns->Add(new SettingEntry("economy.initial_city_size"));
892 towns->Add(new SettingEntry("economy.town_cargogen_mode"));
893 }
894
895 SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
896 {
897 industries->Add(new SettingEntry("economy.industry_cargo_scale"));
898 industries->Add(new SettingEntry("difficulty.industry_density"));
899 industries->Add(new SettingEntry("construction.raw_industry_construction"));
900 industries->Add(new SettingEntry("construction.industry_platform"));
901 industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
902 industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
903 industries->Add(new SettingEntry("economy.type"));
904 industries->Add(new SettingEntry("station.serve_neutral_industries"));
905 }
906
907 SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
908 {
909 cdist->Add(new SettingEntry("linkgraph.recalc_time"));
910 cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
911 cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
912 cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
913 cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
914 cdist->Add(new SettingEntry("linkgraph.distribution_default"));
915 cdist->Add(new SettingEntry("linkgraph.accuracy"));
916 cdist->Add(new SettingEntry("linkgraph.demand_distance"));
917 cdist->Add(new SettingEntry("linkgraph.demand_size"));
918 cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
919 }
920
921 SettingsPage *trees = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TREES));
922 {
923 trees->Add(new SettingEntry("game_creation.tree_placer"));
924 trees->Add(new SettingEntry("construction.extra_tree_placement"));
925 }
926 }
927
928 SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
929 {
930 SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
931 {
932 npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
933 npc->Add(new SettingEntry("script.script_max_memory_megabytes"));
934 npc->Add(new SettingEntry("difficulty.competitor_speed"));
935 npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
936 npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
937 npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
938 npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
939 npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
940 }
941
942 ai->Add(new SettingEntry("economy.give_money"));
943 }
944
945 SettingsPage *network = main->Add(new SettingsPage(STR_CONFIG_SETTING_NETWORK));
946 {
947 network->Add(new SettingEntry("network.use_relay_service"));
948 }
949
950 main->Init();
951 }
952 return *main;
953}
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 & Set()
Set all bits.
constexpr Timpl & Reset(Tvalue_type value)
Reset the value-th bit.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
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:989
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:243
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:387
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.
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.
Dimension _circle_size
Dimension of the circle +/- icon. This is here as not all users are within the class of the settings ...
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.
static const SettingDesc * GetSettingFromName(const std::string_view name, const SettingTable &settings)
Given a name of setting, return a setting description from the table.
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition settings.cpp:59
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:57
void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
Draw [<][>] boxes.
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
Draw a dropdown button.
void DrawBoolButton(int x, int y, bool state, bool clickable)
Draw a toggle 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:426
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.
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:488
StringID GetTitle() const
Get the title of the setting.
Definition settings.cpp:439
int32_t GetDefaultValue() const
Get the default value of the setting.
Definition settings.cpp:479
StringID GetHelp() const
Get the help text of the setting.
Definition settings.cpp:448
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:457
int32_t Read(const void *object) const
Read the integer from the the actual setting.
Definition settings.cpp:579
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:901
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:918
const struct IntSettingDesc * AsIntSetting() const
Get the setting description of this setting as an integer setting.
Definition settings.cpp:928
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.
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.
SettingEntry(const char *name)
Constructor for a single setting in the 'advanced settings' window.
bool UpdateFilterState(SettingFilter &filter, bool force_visible) override
Update the filter state.
const char * name
Name 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.
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.
void AddLine(const char *str)
Pass another text line from the current item to the filter.
bool GetState() const
Get the matching state of the current item.