OpenTTD Source 20260218-master-g2123fca5ea
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
132
134{
135 SetSettingValue(this->setting, this->setting->GetDefaultValue());
136}
137
144{
145 assert((new_val & SEF_BUTTONS_MASK) == new_val); // Should not touch any flags outside the buttons
148}
149
151{
152 return this->IsFiltered() ? 0 : 1;
153}
154
156{
157 return GetStringHeight(this->setting->GetHelp(), maxw);
158}
159
166{
167 /* There shall not be any restriction, i.e. all settings shall be visible. */
168 if (mode == RM_ALL) return true;
169
170 const IntSettingDesc *sd = this->setting;
171
172 if (mode == RM_BASIC) return (this->setting->cat & SC_BASIC_LIST) != 0;
173 if (mode == RM_ADVANCED) return (this->setting->cat & SC_ADVANCED_LIST) != 0;
174
175 /* Read the current value. */
176 const void *object = ResolveObject(&GetGameSettings(), sd);
177 int64_t current_value = sd->Read(object);
178 int64_t filter_value;
179
180 if (mode == RM_CHANGED_AGAINST_DEFAULT) {
181 /* This entry shall only be visible, if the value deviates from its default value. */
182
183 /* Read the default value. */
184 filter_value = sd->GetDefaultValue();
185 } else {
186 assert(mode == RM_CHANGED_AGAINST_NEW);
187 /* This entry shall only be visible, if the value deviates from
188 * its value is used when starting a new game. */
189
190 /* Make sure we're not comparing the new game settings against itself. */
191 assert(&GetGameSettings() != &_settings_newgame);
192
193 /* Read the new game's value. */
194 filter_value = sd->Read(ResolveObject(&_settings_newgame, sd));
195 }
196
197 return current_value != filter_value;
198}
199
206bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
207{
209
210 bool visible = true;
211
212 const IntSettingDesc *sd = this->setting;
213 if (!force_visible && !filter.string.IsEmpty()) {
214 /* Process the search text filter for this item. */
215 filter.string.ResetState();
216
217 filter.string.AddLine(GetString(sd->GetTitle(), STR_EMPTY));
218 filter.string.AddLine(GetString(sd->GetHelp()));
219
220 visible = filter.string.GetState();
221 }
222
223 if (visible) {
224 if (filter.type != ST_ALL && sd->GetType() != filter.type) {
225 filter.type_hides = true;
226 visible = false;
227 }
228 if (!this->IsVisibleByRestrictionMode(filter.mode)) {
229 while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
230 visible = false;
231 }
232 }
233
234 if (!visible) this->flags.Set(SettingEntryFlag::Filtered);
235 return visible;
236}
237
246const void *ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd)
247{
249 if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
250 return &Company::Get(_local_company)->settings;
251 }
252 return &_settings_client.company;
253 }
254 return settings_ptr;
255}
256
257void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
258{
259 const IntSettingDesc *sd = this->setting;
260 int state = (this->flags & SEF_BUTTONS_MASK).base();
261
262 bool rtl = _current_text_dir == TD_RTL;
263 uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
264 uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide);
265 uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide : 0);
266 uint button_y = y + (BaseSettingEntry::line_height - SETTING_BUTTON_HEIGHT) / 2;
267
268 /* We do not allow changes of some items when we are a client in a networkgame */
269 bool editable = sd->IsEditable();
270
271 auto [min_val, max_val] = sd->GetRange();
272 int32_t value = sd->Read(ResolveObject(settings_ptr, sd));
273 if (sd->IsBoolSetting()) {
274 /* Draw checkbox for boolean-value either on/off */
275 DrawBoolButton(buttons_left, button_y, COLOUR_YELLOW, COLOUR_MAUVE, value != 0, editable);
276 } else if (sd->flags.Test(SettingFlag::GuiDropdown)) {
277 /* Draw [v] button for settings of an enum-type */
278 DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
279 } else {
280 /* Draw [<][>] boxes for settings of an integer-type */
281 DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
282 editable && value != (sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val), editable && static_cast<uint32_t>(value) != max_val);
283 }
284 auto [param1, param2] = sd->GetValueParams(value);
285 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);
286}
287
288/* == SettingsContainer methods == */
289
294void SettingsContainer::Init(uint8_t level)
295{
296 for (auto &it : this->entries) {
297 it->Init(level);
298 }
299}
300
303{
304 for (auto settings_entry : this->entries) {
305 settings_entry->ResetAll();
306 }
307}
308
311{
312 for (auto &it : this->entries) {
313 it->FoldAll();
314 }
315}
316
319{
320 for (auto &it : this->entries) {
321 it->UnFoldAll();
322 }
323}
324
330void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
331{
332 for (auto &it : this->entries) {
333 it->GetFoldingState(all_folded, all_unfolded);
334 }
335}
336
344{
345 bool visible = false;
346 bool first_visible = true;
347 for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
348 visible |= (*it)->UpdateFilterState(filter, force_visible);
349 (*it)->SetLastField(first_visible);
350 if (visible && first_visible) first_visible = false;
351 }
352 return visible;
353}
354
355
363{
364 for (const auto &it : this->entries) {
365 if (it->IsVisible(item)) return true;
366 }
367 return false;
368}
369
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
456
458{
459 for (auto settings_entry : this->entries) {
460 settings_entry->ResetAll();
461 }
462}
463
465{
466 if (this->IsFiltered()) return;
467 this->folded = true;
468
470}
471
473{
474 if (this->IsFiltered()) return;
475 this->folded = false;
476
478}
479
480void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
481{
482 if (this->IsFiltered()) return;
483
484 if (this->folded) {
485 all_unfolded = false;
486 } else {
487 all_folded = false;
488 }
489
490 SettingsContainer::GetFoldingState(all_folded, all_unfolded);
491}
492
493bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
494{
495 if (!force_visible && !filter.string.IsEmpty()) {
496 filter.string.ResetState();
497 filter.string.AddLine(GetString(this->title));
498 force_visible = filter.string.GetState();
499 }
500
501 bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
502 this->flags.Set(SettingEntryFlag::Filtered, !visible);
503 return visible;
504}
505
506bool SettingsPage::IsVisible(const BaseSettingEntry *item) const
507{
508 if (this->IsFiltered()) return false;
509 if (this == item) return true;
510 if (this->folded) return false;
511
512 return SettingsContainer::IsVisible(item);
513}
514
516{
517 if (this->IsFiltered()) return 0;
518 if (this->folded) return 1; // Only displaying the title
519
520 return 1 + SettingsContainer::Length();
521}
522
529BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
530{
531 if (this->IsFiltered()) return nullptr;
532 if (row_num == *cur_row) return this;
533 (*cur_row)++;
534 if (this->folded) return nullptr;
535
536 return SettingsContainer::FindEntry(row_num, cur_row);
537}
538
539uint 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
540{
541 if (this->IsFiltered()) return cur_row;
542 if (cur_row >= max_row) return cur_row;
543
544 cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
545
546 if (!this->folded) {
547 if (this->flags.Test(SettingEntryFlag::LastField)) {
548 assert(this->level < 8 * sizeof(parent_last));
549 SetBit(parent_last, this->level); // Add own last-field state
550 }
551
552 cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
553 }
554
555 return cur_row;
556}
557
558void SettingsPage::DrawSetting(GameSettings *, int left, int right, int y, bool) const
559{
560 bool rtl = _current_text_dir == TD_RTL;
561 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);
562 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);
563}
564
570{
571 static SettingsContainer *main = nullptr;
572
573 if (main == nullptr) {
574 /* Build up the dynamic settings-array only once per OpenTTD session */
575 main = new SettingsContainer();
576
577 SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
578 {
579 localisation->Add(new SettingEntry("locale.units_velocity"));
580 localisation->Add(new SettingEntry("locale.units_velocity_nautical"));
581 localisation->Add(new SettingEntry("locale.units_power"));
582 localisation->Add(new SettingEntry("locale.units_weight"));
583 localisation->Add(new SettingEntry("locale.units_volume"));
584 localisation->Add(new SettingEntry("locale.units_force"));
585 localisation->Add(new SettingEntry("locale.units_height"));
586 localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
587 }
588
589 SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
590 {
591 graphics->Add(new SettingEntry("gui.zoom_min"));
592 graphics->Add(new SettingEntry("gui.zoom_max"));
593 graphics->Add(new SettingEntry("gui.sprite_zoom_min"));
594 graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
595 graphics->Add(new SettingEntry("gui.linkgraph_colours"));
596 graphics->Add(new SettingEntry("gui.graph_line_thickness"));
597 }
598
599 SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
600 {
601 sound->Add(new SettingEntry("sound.click_beep"));
602 sound->Add(new SettingEntry("sound.confirm"));
603 sound->Add(new SettingEntry("sound.news_ticker"));
604 sound->Add(new SettingEntry("sound.news_full"));
605 sound->Add(new SettingEntry("sound.new_year"));
606 sound->Add(new SettingEntry("sound.disaster"));
607 sound->Add(new SettingEntry("sound.vehicle"));
608 sound->Add(new SettingEntry("sound.ambient"));
609 }
610
611 SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
612 {
613 SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
614 {
615 general->Add(new SettingEntry("gui.osk_activation"));
616 general->Add(new SettingEntry("gui.hover_delay_ms"));
617 general->Add(new SettingEntry("gui.errmsg_duration"));
618 general->Add(new SettingEntry("gui.window_snap_radius"));
619 general->Add(new SettingEntry("gui.window_soft_limit"));
620 general->Add(new SettingEntry("gui.right_click_wnd_close"));
621 general->Add(new SettingEntry("gui.toolbar_dropdown_autoselect"));
622 }
623
624 SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
625 {
626 viewports->Add(new SettingEntry("gui.auto_scrolling"));
627 viewports->Add(new SettingEntry("gui.scroll_mode"));
628 viewports->Add(new SettingEntry("gui.smooth_scroll"));
629 /* While the horizontal scrollwheel scrolling is written as general code, only
630 * the cocoa (OSX) driver generates input for it.
631 * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
632 viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
633 viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
634#ifdef __APPLE__
635 /* We might need to emulate a right mouse button on mac */
636 viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
637#endif
638 viewports->Add(new SettingEntry("gui.population_in_label"));
639 viewports->Add(new SettingEntry("gui.liveries"));
640 viewports->Add(new SettingEntry("construction.train_signal_side"));
641 viewports->Add(new SettingEntry("gui.measure_tooltip"));
642 viewports->Add(new SettingEntry("gui.loading_indicators"));
643 viewports->Add(new SettingEntry("gui.show_track_reservation"));
644 }
645
646 SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
647 {
648 construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
649 construction->Add(new SettingEntry("gui.persistent_buildingtools"));
650 construction->Add(new SettingEntry("gui.default_rail_type"));
651 construction->Add(new SettingEntry("gui.semaphore_build_before"));
652 construction->Add(new SettingEntry("gui.signal_gui_mode"));
653 construction->Add(new SettingEntry("gui.cycle_signal_types"));
654 construction->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
655 construction->Add(new SettingEntry("gui.auto_remove_signals"));
656 }
657
658 interface->Add(new SettingEntry("gui.toolbar_pos"));
659 interface->Add(new SettingEntry("gui.statusbar_pos"));
660 interface->Add(new SettingEntry("gui.prefer_teamchat"));
661 interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
662 interface->Add(new SettingEntry("gui.timetable_mode"));
663 interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
664 interface->Add(new SettingEntry("gui.show_newgrf_name"));
665 interface->Add(new SettingEntry("gui.show_cargo_in_vehicle_lists"));
666 }
667
668 SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
669 {
670 advisors->Add(new SettingEntry("gui.coloured_news_year"));
671 advisors->Add(new SettingEntry("news_display.general"));
672 advisors->Add(new SettingEntry("news_display.new_vehicles"));
673 advisors->Add(new SettingEntry("news_display.accident"));
674 advisors->Add(new SettingEntry("news_display.accident_other"));
675 advisors->Add(new SettingEntry("news_display.company_info"));
676 advisors->Add(new SettingEntry("news_display.acceptance"));
677 advisors->Add(new SettingEntry("news_display.arrival_player"));
678 advisors->Add(new SettingEntry("news_display.arrival_other"));
679 advisors->Add(new SettingEntry("news_display.advice"));
680 advisors->Add(new SettingEntry("gui.order_review_system"));
681 advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
682 advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
683 advisors->Add(new SettingEntry("gui.old_vehicle_warn"));
684 advisors->Add(new SettingEntry("gui.show_finances"));
685 advisors->Add(new SettingEntry("news_display.economy"));
686 advisors->Add(new SettingEntry("news_display.subsidies"));
687 advisors->Add(new SettingEntry("news_display.open"));
688 advisors->Add(new SettingEntry("news_display.close"));
689 advisors->Add(new SettingEntry("news_display.production_player"));
690 advisors->Add(new SettingEntry("news_display.production_other"));
691 advisors->Add(new SettingEntry("news_display.production_nobody"));
692 }
693
694 SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
695 {
696 company->Add(new SettingEntry("gui.starting_colour"));
697 company->Add(new SettingEntry("gui.starting_colour_secondary"));
698 company->Add(new SettingEntry("company.engine_renew"));
699 company->Add(new SettingEntry("company.engine_renew_months"));
700 company->Add(new SettingEntry("company.engine_renew_money"));
701 company->Add(new SettingEntry("vehicle.servint_ispercent"));
702 company->Add(new SettingEntry("vehicle.servint_trains"));
703 company->Add(new SettingEntry("vehicle.servint_roadveh"));
704 company->Add(new SettingEntry("vehicle.servint_ships"));
705 company->Add(new SettingEntry("vehicle.servint_aircraft"));
706 }
707
708 SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
709 {
710 accounting->Add(new SettingEntry("difficulty.infinite_money"));
711 accounting->Add(new SettingEntry("economy.inflation"));
712 accounting->Add(new SettingEntry("difficulty.initial_interest"));
713 accounting->Add(new SettingEntry("difficulty.max_loan"));
714 accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
715 accounting->Add(new SettingEntry("difficulty.subsidy_duration"));
716 accounting->Add(new SettingEntry("economy.feeder_payment_share"));
717 accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
718 accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
719 accounting->Add(new SettingEntry("difficulty.construction_cost"));
720 }
721
722 SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
723 {
724 SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
725 {
726 physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
727 physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
728 physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
729 physics->Add(new SettingEntry("vehicle.freight_trains"));
730 physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
731 physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
732 physics->Add(new SettingEntry("vehicle.smoke_amount"));
733 physics->Add(new SettingEntry("vehicle.plane_speed"));
734 }
735
736 SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
737 {
738 routing->Add(new SettingEntry("vehicle.road_side"));
739 routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
740 routing->Add(new SettingEntry("pf.reverse_at_signals"));
741 routing->Add(new SettingEntry("pf.forbid_90_deg"));
742 }
743
744 SettingsPage *orders = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ORDERS));
745 {
746 orders->Add(new SettingEntry("gui.new_nonstop"));
747 orders->Add(new SettingEntry("gui.quick_goto"));
748 orders->Add(new SettingEntry("gui.stop_location"));
749 }
750 }
751
752 SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
753 {
754 limitations->Add(new SettingEntry("construction.command_pause_level"));
755 limitations->Add(new SettingEntry("construction.autoslope"));
756 limitations->Add(new SettingEntry("construction.extra_dynamite"));
757 limitations->Add(new SettingEntry("construction.map_height_limit"));
758 limitations->Add(new SettingEntry("construction.max_bridge_length"));
759 limitations->Add(new SettingEntry("construction.max_bridge_height"));
760 limitations->Add(new SettingEntry("construction.max_tunnel_length"));
761 limitations->Add(new SettingEntry("station.never_expire_airports"));
762 limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
763 limitations->Add(new SettingEntry("vehicle.max_trains"));
764 limitations->Add(new SettingEntry("vehicle.max_roadveh"));
765 limitations->Add(new SettingEntry("vehicle.max_aircraft"));
766 limitations->Add(new SettingEntry("vehicle.max_ships"));
767 limitations->Add(new SettingEntry("vehicle.max_train_length"));
768 limitations->Add(new SettingEntry("station.station_spread"));
769 limitations->Add(new SettingEntry("station.distant_join_stations"));
770 limitations->Add(new SettingEntry("station.modified_catchment"));
771 limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
772 limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
773 limitations->Add(new SettingEntry("construction.crossing_with_competitor"));
774 limitations->Add(new SettingEntry("vehicle.disable_elrails"));
775 limitations->Add(new SettingEntry("order.station_length_loading_penalty"));
776 }
777
778 SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
779 {
780 disasters->Add(new SettingEntry("difficulty.disasters"));
781 disasters->Add(new SettingEntry("difficulty.economy"));
782 disasters->Add(new SettingEntry("vehicle.plane_crashes"));
783 disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
784 disasters->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
785 disasters->Add(new SettingEntry("order.serviceathelipad"));
786 }
787
788 SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
789 {
790 genworld->Add(new SettingEntry("game_creation.landscape"));
791 genworld->Add(new SettingEntry("game_creation.land_generator"));
792 genworld->Add(new SettingEntry("difficulty.terrain_type"));
793 genworld->Add(new SettingEntry("game_creation.average_height"));
794 genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
795 genworld->Add(new SettingEntry("game_creation.variety"));
796 genworld->Add(new SettingEntry("game_creation.snow_coverage"));
797 genworld->Add(new SettingEntry("game_creation.snow_line_height"));
798 genworld->Add(new SettingEntry("game_creation.desert_coverage"));
799 genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
800 }
801
802 SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
803 {
804 SettingsPage *time = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TIME));
805 {
806 time->Add(new SettingEntry("economy.timekeeping_units"));
807 time->Add(new SettingEntry("economy.minutes_per_calendar_year"));
808 time->Add(new SettingEntry("game_creation.ending_year"));
809 time->Add(new SettingEntry("gui.pause_on_newgame"));
810 time->Add(new SettingEntry("gui.fast_forward_speed_limit"));
811 }
812
813 SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
814 {
815 authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
816 authorities->Add(new SettingEntry("economy.bribe"));
817 authorities->Add(new SettingEntry("economy.exclusive_rights"));
818 authorities->Add(new SettingEntry("economy.fund_roads"));
819 authorities->Add(new SettingEntry("economy.fund_buildings"));
820 authorities->Add(new SettingEntry("economy.station_noise_level"));
821 }
822
823 SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
824 {
825 towns->Add(new SettingEntry("economy.town_cargo_scale"));
826 towns->Add(new SettingEntry("economy.town_growth_rate"));
827 towns->Add(new SettingEntry("economy.allow_town_roads"));
828 towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
829 towns->Add(new SettingEntry("economy.found_town"));
830 towns->Add(new SettingEntry("economy.place_houses"));
831 towns->Add(new SettingEntry("economy.town_layout"));
832 towns->Add(new SettingEntry("economy.larger_towns"));
833 towns->Add(new SettingEntry("economy.initial_city_size"));
834 towns->Add(new SettingEntry("economy.town_min_distance"));
835 towns->Add(new SettingEntry("economy.town_cargogen_mode"));
836 }
837
838 SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
839 {
840 industries->Add(new SettingEntry("economy.industry_cargo_scale"));
841 industries->Add(new SettingEntry("difficulty.industry_density"));
842 industries->Add(new SettingEntry("construction.raw_industry_construction"));
843 industries->Add(new SettingEntry("construction.industry_platform"));
844 industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
845 industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
846 industries->Add(new SettingEntry("economy.type"));
847 industries->Add(new SettingEntry("station.serve_neutral_industries"));
848 }
849
850 SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
851 {
852 cdist->Add(new SettingEntry("linkgraph.recalc_time"));
853 cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
854 cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
855 cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
856 cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
857 cdist->Add(new SettingEntry("linkgraph.distribution_default"));
858 cdist->Add(new SettingEntry("linkgraph.accuracy"));
859 cdist->Add(new SettingEntry("linkgraph.demand_distance"));
860 cdist->Add(new SettingEntry("linkgraph.demand_size"));
861 cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
862 }
863
864 SettingsPage *trees = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TREES));
865 {
866 trees->Add(new SettingEntry("game_creation.tree_placer"));
867 trees->Add(new SettingEntry("construction.extra_tree_placement"));
868 }
869 }
870
871 SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
872 {
873 SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
874 {
875 npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
876 npc->Add(new SettingEntry("script.script_max_memory_megabytes"));
877 npc->Add(new SettingEntry("difficulty.competitor_speed"));
878 npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
879 npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
880 npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
881 npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
882 npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
883 }
884
885 ai->Add(new SettingEntry("economy.give_money"));
886 }
887
888 SettingsPage *network = main->Add(new SettingsPage(STR_CONFIG_SETTING_NETWORK));
889 {
890 network->Add(new SettingEntry("network.use_relay_service"));
891 }
892
893 main->Init();
894 }
895 return *main;
896}
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.
const void * ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd)
Resolve the underlying object where to dynamically load/save a setting to.
SettingsContainer & GetSettingsTree()
Construct settings tree.
Declarations of classes for handling display of individual configuration settings.
const void * ResolveObject(const GameSettings *settings_ptr, const IntSettingDesc *sd)
Resolve the underlying object where to dynamically load/save a setting to.
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.
EnumBitSet< SettingEntryFlag, uint8_t > SettingEntryFlags
Bitset of the SettingEntryFlag elements.
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
Get the number of rows needed to show this 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.
void ResetAll() override
Resets all settings to their default values.
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.
T * Add(T *item)
Add an item to the container.
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 folds of sub-pages.
void FoldAll() override
Recursively close all folds of sub-pages.
uint Length() const override
Get the number of rows needed to show this 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 a setting entry.
void GetFoldingState(bool &all_folded, bool &all_unfolded) const override
Recursively accumulate the folding state of the 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.