OpenTTD Source 20260311-master-g511d3794ce
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
27 std::array<std::vector<BadgeClassConfigItem>, GrfSpecFeature::GSF_END> features = {};
28
29 static constexpr GrfSpecFeatures CONFIGURABLE_FEATURES = {
30 GSF_TRAINS, GSF_ROADVEHICLES, GSF_SHIPS, GSF_AIRCRAFT, GSF_STATIONS, GSF_HOUSES, GSF_OBJECTS, GSF_ROADSTOPS,
31 };
32
33 static inline const std::array<std::string_view, GrfSpecFeature::GSF_END> sections = {
34 "badges_trains", // GSF_TRAINS
35 "badges_roadvehicles", // GSF_ROADVEHICLES
36 "badges_ships", // GSF_SHIPS
37 "badges_aircraft", // GSF_AIRCRAFT
38 "badges_stations", // GSF_STATIONS
39 {}, // GSF_CANALS
40 {}, // GSF_BRIDGES
41 "badges_houses", // GSF_HOUSES
42 {}, // GSF_GLOBALVAR
43 {}, // GSF_INDUSTRYTILES
44 {}, // GSF_INDUSTRIES
45 {}, // GSF_CARGOES
46 {}, // GSF_SOUNDFX
47 {}, // GSF_AIRPORTS
48 {}, // GSF_SIGNALS
49 "badges_objects", // GSF_OBJECTS
50 {}, // GSF_RAILTYPES
51 {}, // GSF_AIRPORTTILES
52 {}, // GSF_ROADTYPES
53 {}, // GSF_TRAMTYPES
54 "badges_roadstops", // GSF_ROADSTOPS
55 {}, // GSF_BADGES
56 };
57};
58
61
67std::span<BadgeClassConfigItem> GetBadgeClassConfiguration(GrfSpecFeature feature)
68{
69 assert(BadgeClassConfig::CONFIGURABLE_FEATURES.Test(feature));
70 assert(feature < std::size(_badge_config.features));
71 return _badge_config.features[to_underlying(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::GSF_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[to_underlying(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.
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:71
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