OpenTTD Source 20260421-master-gc2fbc6fdeb
newgrf_badge_config.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"
12#include "ini_type.h"
13#include "newgrf.h"
14#include "newgrf_badge.h"
15#include "newgrf_badge_config.h"
16#include "newgrf_badge_type.h"
17
18#include "table/strings.h"
19
20#include "safeguards.h"
21
24public:
25 static inline const BadgeClassConfigItem EMPTY_CONFIG_ITEM{};
26
28
29 static constexpr GrfSpecFeatures CONFIGURABLE_FEATURES = {
31 };
32
33 static inline const EnumClassIndexContainer<std::array<std::string_view, to_underlying(GrfSpecFeature::End)>, GrfSpecFeature> sections = {
34 "badges_trains", // GrfSpecFeature::Trains
35 "badges_roadvehicles", // GrfSpecFeature::RoadVehicles
36 "badges_ships", // GrfSpecFeature::Ships
37 "badges_aircraft", // GrfSpecFeature::Aircraft
38 "badges_stations", // GrfSpecFeature::Stations
39 {}, // GrfSpecFeature::Canals
40 {}, // GrfSpecFeature::Bridges
41 "badges_houses", // GrfSpecFeature::Houses
42 {}, // GrfSpecFeature::GlobalVar
43 {}, // GrfSpecFeature::IndustryTiles
44 {}, // GrfSpecFeature::Industries
45 {}, // GrfSpecFeature::Cargoes
46 {}, // GrfSpecFeature::SoundEffects
47 {}, // GrfSpecFeature::Airports
48 {}, // GrfSpecFeature::Signals
49 "badges_objects", // GrfSpecFeature::Objects
50 {}, // GrfSpecFeature::RailTypes
51 {}, // GrfSpecFeature::AirportTiles
52 {}, // GrfSpecFeature::RoadTypes
53 {}, // GrfSpecFeature::TramTypes
54 "badges_roadstops", // GrfSpecFeature::RoadStops
55 {}, // GrfSpecFeature::Badges
56 };
57};
58
61
67std::span<BadgeClassConfigItem> GetBadgeClassConfiguration(GrfSpecFeature feature)
68{
69 assert(BadgeClassConfig::CONFIGURABLE_FEATURES.Test(feature));
70 assert(to_underlying(feature) < std::size(_badge_config.features));
71 return _badge_config.features[feature];
72}
73
78{
79 for (const GrfSpecFeature &feature : BadgeClassConfig::CONFIGURABLE_FEATURES) {
80 auto &config = _badge_config.features[feature];
81
82 for (const BadgeID &index : GetClassBadges()) {
83 const Badge &badge = *GetBadge(index);
84 if (badge.name == STR_NULL) continue;
85 if (!badge.features.Test(feature)) continue;
86
87 auto found = std::ranges::find(config, badge.label, &BadgeClassConfigItem::label);
88 if (found != std::end(config)) continue;
89
90 /* Not found, insert it. */
91 config.emplace_back(badge.label, 0, true, false);
92 }
93 }
94}
95
101{
102 assert(feature < GrfSpecFeature::End);
103
104 auto &config = _badge_config.features[feature];
105 config.clear();
106
107 for (const BadgeID &index : GetClassBadges()) {
108 const Badge &badge = *GetBadge(index);
109 if (badge.name == STR_NULL) continue;
110 config.emplace_back(badge.label, 0, true, false);
111 }
112}
113
120std::pair<const BadgeClassConfigItem &, int> GetBadgeClassConfigItem(GrfSpecFeature feature, std::string_view label)
121{
122 if (BadgeClassConfig::CONFIGURABLE_FEATURES.Test(feature)) {
123 auto config = GetBadgeClassConfiguration(feature);
124 auto found = std::ranges::find(config, label, &BadgeClassConfigItem::label);
125 if (found != std::end(config)) {
126 /* Sort order is simply the position in the configuration list. */
127 return {*found, static_cast<int>(std::distance(std::begin(config), found))};
128 }
129 }
130
131 return {BadgeClassConfig::EMPTY_CONFIG_ITEM, 0};
132}
133
139static void BadgeClassLoadConfigFeature(const IniFile &ini, GrfSpecFeature feature)
140{
141 assert(BadgeClassConfig::CONFIGURABLE_FEATURES.Test(feature));
142 assert(!BadgeClassConfig::sections[feature].empty());
143
144 auto &config = _badge_config.features[feature];
145 config.clear();
146
147 const IniGroup *group = ini.GetGroup(BadgeClassConfig::sections[feature]);
148 if (group == nullptr) return;
149
150 for (const IniItem &item : group->items) {
151 int column = 0;
152 bool show_icon = true;
153 bool show_filter = false;
154
155 if (item.value.has_value() && !item.value.value().empty()) {
156 StringConsumer consumer(item.value.value());
157 if (consumer.ReadCharIf('?')) show_filter = true;
158 if (consumer.ReadCharIf('!')) show_icon = false;
159 if (auto value = consumer.TryReadIntegerBase<int>(10); value.has_value()) column = *value;
160 }
161
162 config.emplace_back(item.name, column, show_icon, show_filter);
163 }
164}
165
171{
172 for (const GrfSpecFeature &feature : BadgeClassConfig::CONFIGURABLE_FEATURES) {
173 BadgeClassLoadConfigFeature(ini, feature);
174 }
175}
176
183{
184 assert(BadgeClassConfig::CONFIGURABLE_FEATURES.Test(feature));
185 assert(!BadgeClassConfig::sections[feature].empty());
186
187 IniGroup &group = ini.GetOrCreateGroup(BadgeClassConfig::sections[feature]);
188 group.Clear();
189
190 for (const auto &item : _badge_config.features[feature]) {
191 group.CreateItem(item.label).SetValue(fmt::format("{}{}{}", item.show_filter ? "?" : "", item.show_icon ? "" : "!", item.column));
192 }
193}
194
200{
201 for (const GrfSpecFeature &feature : BadgeClassConfig::CONFIGURABLE_FEATURES) {
202 BadgeClassSaveConfigFeature(ini, feature);
203 }
204}
std::string label
Class label.
Global state for badge class configuration.
std::string label
Label of badge.
GrfSpecFeatures features
Bitmask of which features use this badge.
StringID name
Short name.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
A sort-of mixin that implements 'at(pos)' and 'operator[](pos)' only for a specific enum class.
Parse data from a string / buffer.
bool ReadCharIf(char c)
Check whether the next 8-bit char matches 'c', and skip it.
std::optional< T > TryReadIntegerBase(int base, bool clamp=false)
Try to read and parse an integer in number 'base', and then advance the reader.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
Types related to reading/writing '*.ini' files.
Base for the NewGRF implementation.
GrfSpecFeature
Definition newgrf.h:72
@ RoadStops
Road stops feature.
Definition newgrf.h:93
@ Trains
Trains feature.
Definition newgrf.h:73
@ RoadVehicles
Road vehicles feature.
Definition newgrf.h:74
@ Ships
Ships feature.
Definition newgrf.h:75
@ Houses
Houses feature.
Definition newgrf.h:80
@ End
End marker.
Definition newgrf.h:95
@ Stations
Stations feature.
Definition newgrf.h:77
@ Aircraft
Aircraft feature.
Definition newgrf.h:76
@ Objects
Objects feature.
Definition newgrf.h:88
Badge * GetBadge(BadgeID index)
Get a badge if it exists.
std::span< const BadgeID > GetClassBadges()
Get a read-only view of class badge index.
Functions related to NewGRF badges.
void AddBadgeClassesToConfiguration()
Add current badge classes to user configuration.
void ResetBadgeClassConfiguration(GrfSpecFeature feature)
Reset badge class configuration for a feature.
static void BadgeClassSaveConfigFeature(IniFile &ini, GrfSpecFeature feature)
Save badge column preferences.
static void BadgeClassLoadConfigFeature(const IniFile &ini, GrfSpecFeature feature)
Load badge column preferences.
std::pair< const BadgeClassConfigItem &, int > GetBadgeClassConfigItem(GrfSpecFeature feature, std::string_view label)
Get configuration for a badge class.
void BadgeClassSaveConfig(IniFile &ini)
Save badge column preferences.
static BadgeClassConfig _badge_config
Static instance of badge class configuration state.
std::span< BadgeClassConfigItem > GetBadgeClassConfiguration(GrfSpecFeature feature)
Get the badge user configuration for a feature.
void BadgeClassLoadConfig(const IniFile &ini)
Load badge column preferences.
Functions related to NewGRF badge configuration.
Types related to NewGRF badges.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
Parse strings.
Ini file that supports both loading and saving.
Definition ini_type.h:87
A group within an ini file.
Definition ini_type.h:34
void Clear()
Clear all items in the group.
Definition ini_load.cpp:96
IniItem & CreateItem(std::string_view name)
Create an item with the given name.
Definition ini_load.cpp:79
std::list< IniItem > items
all items in the group
Definition ini_type.h:35
A single "line" in an ini file.
Definition ini_type.h:23
std::optional< std::string > value
The value of this item.
Definition ini_type.h:25
std::string name
The name of this item.
Definition ini_type.h:24
void SetValue(std::string_view value)
Replace the current value with another value.
Definition ini_load.cpp:30
const IniGroup * GetGroup(std::string_view name) const
Get the group with the given name.
Definition ini_load.cpp:117
IniGroup & GetOrCreateGroup(std::string_view name)
Get the group with the given name, and if it doesn't exist create a new group.
Definition ini_load.cpp:145