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/>.
8 /** @file settings_internal.h Functions and types used internally for the settings configurations. */
10 #ifndef SETTINGS_INTERNAL_H
11 #define SETTINGS_INTERNAL_H
14 #include "saveload/saveload.h"
16 enum SettingFlag
: uint16
{
18 SF_GUI_0_IS_SPECIAL
= 1 << 0, ///< A value of zero is possible and has a custom string (the one after "strval").
19 SF_GUI_NEGATIVE_IS_SPECIAL
= 1 << 1, ///< A negative value has another string (the one after "strval").
20 SF_GUI_DROPDOWN
= 1 << 2, ///< The value represents a limited number of string-options (internally integer) presented as dropdown.
21 SF_GUI_CURRENCY
= 1 << 3, ///< The number represents money, so when reading value multiply by exchange rate.
22 SF_NETWORK_ONLY
= 1 << 4, ///< This setting only applies to network games.
23 SF_NO_NETWORK
= 1 << 5, ///< This setting does not apply to network games; it may not be changed during the game.
24 SF_NEWGAME_ONLY
= 1 << 6, ///< This setting cannot be changed in a game.
25 SF_SCENEDIT_TOO
= 1 << 7, ///< This setting can be changed in the scenario editor (only makes sense when SF_NEWGAME_ONLY is set).
26 SF_SCENEDIT_ONLY
= 1 << 8, ///< This setting can only be changed in the scenario editor.
27 SF_PER_COMPANY
= 1 << 9, ///< This setting can be different for each company (saved in company struct).
28 SF_NOT_IN_SAVE
= 1 << 10, ///< Do not save with savegame, basically client-based.
29 SF_NOT_IN_CONFIG
= 1 << 11, ///< Do not save to config file.
30 SF_NO_NETWORK_SYNC
= 1 << 12, ///< Do not synchronize over network (but it is saved if SF_NOT_IN_SAVE is not set).
32 DECLARE_ENUM_AS_BIT_SET(SettingFlag
)
35 * A SettingCategory defines a grouping of the settings.
36 * The group #SC_BASIC is intended for settings which also a novice player would like to change and is able to understand.
37 * The group #SC_ADVANCED is intended for settings which an experienced player would like to use. This is the case for most settings.
38 * Finally #SC_EXPERT settings only few people want to see in rare cases.
39 * The grouping is meant to be inclusive, i.e. all settings in #SC_BASIC also will be included
40 * in the set of settings in #SC_ADVANCED. The group #SC_EXPERT contains all settings.
42 enum SettingCategory
{
45 /* Filters for the list */
46 SC_BASIC_LIST
= 1 << 0, ///< Settings displayed in the list of basic settings.
47 SC_ADVANCED_LIST
= 1 << 1, ///< Settings displayed in the list of advanced settings.
48 SC_EXPERT_LIST
= 1 << 2, ///< Settings displayed in the list of expert settings.
50 /* Setting classification */
51 SC_BASIC
= SC_BASIC_LIST
| SC_ADVANCED_LIST
| SC_EXPERT_LIST
, ///< Basic settings are part of all lists.
52 SC_ADVANCED
= SC_ADVANCED_LIST
| SC_EXPERT_LIST
, ///< Advanced settings are part of advanced and expert list.
53 SC_EXPERT
= SC_EXPERT_LIST
, ///< Expert settings can only be seen in the expert list.
59 * Type of settings for filtering.
62 ST_GAME
, ///< Game setting.
63 ST_COMPANY
, ///< Company setting.
64 ST_CLIENT
, ///< Client setting.
66 ST_ALL
, ///< Used in setting filter to match all types.
71 /** Properties of config file settings. */
73 SettingDesc(SaveLoad save
, SettingFlag flags
, bool startup
) :
74 flags(flags
), startup(startup
), save(save
) {}
75 virtual ~SettingDesc() {}
77 SettingFlag flags
; ///< Handles how a setting would show up in the GUI (text/currency, etc.).
78 bool startup
; ///< Setting has to be loaded directly at startup?.
79 SaveLoad save
; ///< Internal structure (going to savegame, parts to config).
81 bool IsEditable(bool do_command
= false) const;
82 SettingType
GetType() const;
85 * Get the name of this setting.
86 * @return The name of the setting.
88 constexpr const std::string
&GetName() const
90 return this->save
.name
;
94 * Check whether this setting is an integer type setting.
95 * @return True when the underlying type is an integer.
97 virtual bool IsIntSetting() const { return false; }
100 * Check whether this setting is an string type setting.
101 * @return True when the underlying type is a string.
103 virtual bool IsStringSetting() const { return false; }
105 const struct IntSettingDesc
*AsIntSetting() const;
106 const struct StringSettingDesc
*AsStringSetting() const;
109 * Format the value of the setting associated with this object.
110 * @param buf The before of the buffer to format into.
111 * @param last The end of the buffer to format into.
112 * @param object The object the setting is in.
114 virtual void FormatValue(char *buf
, const char *last
, const void *object
) const = 0;
117 * Parse/read the value from the Ini item into the setting associated with this object.
118 * @param item The Ini item with the content of this setting.
119 * @param object The object the setting is in.
121 virtual void ParseValue(const IniItem
*item
, void *object
) const = 0;
124 * Check whether the value in the Ini item is the same as is saved in this setting in the object.
125 * It might be that determining whether the value is the same is way more expensive than just
126 * writing the value. In those cases this function may unconditionally return false even though
127 * the value might be the same as in the Ini item.
128 * @param item The Ini item with the content of this setting.
129 * @param object The object the setting is in.
130 * @return True if the value is definitely the same (might be false when the same).
132 virtual bool IsSameValue(const IniItem
*item
, void *object
) const = 0;
135 /** Base integer type, including boolean, settings. Only these are shown in the settings UI. */
136 struct IntSettingDesc
: SettingDesc
{
138 * A check to be performed before the setting gets changed. The passed integer may be
139 * changed by the check if that is important, for example to remove some unwanted bit.
140 * The return value denotes whether the value, potentially after the changes,
141 * is allowed to be used/set in the configuration.
142 * @param value The prospective new value for the setting.
143 * @return True when the setting is accepted.
145 typedef bool PreChangeCheck(int32
&value
);
147 * A callback to denote that a setting has been changed.
148 * @param The new value for the setting.
150 typedef void PostChangeCallback(int32 value
);
152 IntSettingDesc(SaveLoad save
, SettingFlag flags
, bool startup
, int32 def
,
153 int32 min
, uint32 max
, int32 interval
, StringID str
, StringID str_help
, StringID str_val
,
154 SettingCategory cat
, PreChangeCheck pre_check
, PostChangeCallback post_callback
) :
155 SettingDesc(save
, flags
, startup
), def(def
), min(min
), max(max
), interval(interval
),
156 str(str
), str_help(str_help
), str_val(str_val
), cat(cat
), pre_check(pre_check
),
157 post_callback(post_callback
) {}
158 virtual ~IntSettingDesc() {}
160 int32 def
; ///< default value given when none is present
161 int32 min
; ///< minimum values
162 uint32 max
; ///< maximum values
163 int32 interval
; ///< the interval to use between settings in the 'settings' window. If interval is '0' the interval is dynamically determined
164 StringID str
; ///< (translated) string with descriptive text; gui and console
165 StringID str_help
; ///< (Translated) string with help text; gui only.
166 StringID str_val
; ///< (Translated) first string describing the value.
167 SettingCategory cat
; ///< assigned categories of the setting
168 PreChangeCheck
*pre_check
; ///< Callback to check for the validity of the setting.
169 PostChangeCallback
*post_callback
; ///< Callback when the setting has been changed.
172 * Check whether this setting is a boolean type setting.
173 * @return True when the underlying type is an integer.
175 virtual bool IsBoolSetting() const { return false; }
176 bool IsIntSetting() const override
{ return true; }
178 void ChangeValue(const void *object
, int32 newvalue
) const;
179 void MakeValueValidAndWrite(const void *object
, int32 value
) const;
181 virtual size_t ParseValue(const char *str
) const;
182 void FormatValue(char *buf
, const char *last
, const void *object
) const override
;
183 void ParseValue(const IniItem
*item
, void *object
) const override
;
184 bool IsSameValue(const IniItem
*item
, void *object
) const override
;
185 int32
Read(const void *object
) const;
188 void MakeValueValid(int32
&value
) const;
189 void Write(const void *object
, int32 value
) const;
192 /** Boolean setting. */
193 struct BoolSettingDesc
: IntSettingDesc
{
194 BoolSettingDesc(SaveLoad save
, SettingFlag flags
, bool startup
, bool def
,
195 StringID str
, StringID str_help
, StringID str_val
, SettingCategory cat
,
196 PreChangeCheck pre_check
, PostChangeCallback post_callback
) :
197 IntSettingDesc(save
, flags
, startup
, def
, 0, 1, 0, str
, str_help
, str_val
, cat
,
198 pre_check
, post_callback
) {}
199 virtual ~BoolSettingDesc() {}
201 bool IsBoolSetting() const override
{ return true; }
202 size_t ParseValue(const char *str
) const override
;
203 void FormatValue(char *buf
, const char *last
, const void *object
) const override
;
206 /** One of many setting. */
207 struct OneOfManySettingDesc
: IntSettingDesc
{
208 typedef size_t OnConvert(const char *value
); ///< callback prototype for conversion error
210 OneOfManySettingDesc(SaveLoad save
, SettingFlag flags
, bool startup
, int32 def
,
211 int32 max
, StringID str
, StringID str_help
, StringID str_val
, SettingCategory cat
,
212 PreChangeCheck pre_check
, PostChangeCallback post_callback
,
213 std::initializer_list
<const char *> many
, OnConvert
*many_cnvt
) :
214 IntSettingDesc(save
, flags
, startup
, def
, 0, max
, 0, str
, str_help
, str_val
, cat
,
215 pre_check
, post_callback
), many_cnvt(many_cnvt
)
217 for (auto one
: many
) this->many
.push_back(one
);
220 virtual ~OneOfManySettingDesc() {}
222 std::vector
<std::string
> many
; ///< possible values for this type
223 OnConvert
*many_cnvt
; ///< callback procedure when loading value mechanism fails
225 static size_t ParseSingleValue(const char *str
, size_t len
, const std::vector
<std::string
> &many
);
226 char *FormatSingleValue(char *buf
, const char *last
, uint id
) const;
228 size_t ParseValue(const char *str
) const override
;
229 void FormatValue(char *buf
, const char *last
, const void *object
) const override
;
232 /** Many of many setting. */
233 struct ManyOfManySettingDesc
: OneOfManySettingDesc
{
234 ManyOfManySettingDesc(SaveLoad save
, SettingFlag flags
, bool startup
,
235 int32 def
, StringID str
, StringID str_help
, StringID str_val
, SettingCategory cat
,
236 PreChangeCheck pre_check
, PostChangeCallback post_callback
,
237 std::initializer_list
<const char *> many
, OnConvert
*many_cnvt
) :
238 OneOfManySettingDesc(save
, flags
, startup
, def
, (1 << many
.size()) - 1, str
, str_help
,
239 str_val
, cat
, pre_check
, post_callback
, many
, many_cnvt
) {}
240 virtual ~ManyOfManySettingDesc() {}
242 size_t ParseValue(const char *str
) const override
;
243 void FormatValue(char *buf
, const char *last
, const void *object
) const override
;
246 /** String settings. */
247 struct StringSettingDesc
: SettingDesc
{
249 * A check to be performed before the setting gets changed. The passed string may be
250 * changed by the check if that is important, for example to remove unwanted white
251 * space. The return value denotes whether the value, potentially after the changes,
252 * is allowed to be used/set in the configuration.
253 * @param value The prospective new value for the setting.
254 * @return True when the setting is accepted.
256 typedef bool PreChangeCheck(std::string
&value
);
258 * A callback to denote that a setting has been changed.
259 * @param The new value for the setting.
261 typedef void PostChangeCallback(const std::string
&value
);
263 StringSettingDesc(SaveLoad save
, SettingFlag flags
, bool startup
, const char *def
,
264 uint32 max_length
, PreChangeCheck pre_check
, PostChangeCallback post_callback
) :
265 SettingDesc(save
, flags
, startup
), def(def
== nullptr ? "" : def
), max_length(max_length
),
266 pre_check(pre_check
), post_callback(post_callback
) {}
267 virtual ~StringSettingDesc() {}
269 std::string def
; ///< Default value given when none is present
270 uint32 max_length
; ///< Maximum length of the string, 0 means no maximum length
271 PreChangeCheck
*pre_check
; ///< Callback to check for the validity of the setting.
272 PostChangeCallback
*post_callback
; ///< Callback when the setting has been changed.
274 bool IsStringSetting() const override
{ return true; }
275 void ChangeValue(const void *object
, std::string
&newval
) const;
277 void FormatValue(char *buf
, const char *last
, const void *object
) const override
;
278 void ParseValue(const IniItem
*item
, void *object
) const override
;
279 bool IsSameValue(const IniItem
*item
, void *object
) const override
;
280 const std::string
&Read(const void *object
) const;
283 void MakeValueValid(std::string
&str
) const;
284 void Write(const void *object
, const std::string
&str
) const;
287 /** List/array settings. */
288 struct ListSettingDesc
: SettingDesc
{
289 ListSettingDesc(SaveLoad save
, SettingFlag flags
, bool startup
, const char *def
) :
290 SettingDesc(save
, flags
, startup
), def(def
) {}
291 virtual ~ListSettingDesc() {}
293 const char *def
; ///< default value given when none is present
295 void FormatValue(char *buf
, const char *last
, const void *object
) const override
;
296 void ParseValue(const IniItem
*item
, void *object
) const override
;
297 bool IsSameValue(const IniItem
*item
, void *object
) const override
;
300 /** Placeholder for settings that have been removed, but might still linger in the savegame. */
301 struct NullSettingDesc
: SettingDesc
{
302 NullSettingDesc(SaveLoad save
) :
303 SettingDesc(save
, SF_NOT_IN_CONFIG
, false) {}
304 virtual ~NullSettingDesc() {}
306 void FormatValue(char *buf
, const char *last
, const void *object
) const override
{ NOT_REACHED(); }
307 void ParseValue(const IniItem
*item
, void *object
) const override
{ NOT_REACHED(); }
308 bool IsSameValue(const IniItem
*item
, void *object
) const override
{ NOT_REACHED(); }
311 typedef std::variant
<IntSettingDesc
, BoolSettingDesc
, OneOfManySettingDesc
, ManyOfManySettingDesc
, StringSettingDesc
, ListSettingDesc
, NullSettingDesc
> SettingVariant
;
314 * Helper to convert the type of the iterated settings description to a pointer to it.
315 * @param desc The type of the iterator of the value in SettingTable.
316 * @return The actual pointer to SettingDesc.
318 static constexpr const SettingDesc
*GetSettingDesc(const SettingVariant
&desc
)
320 return std::visit([](auto&& arg
) -> const SettingDesc
* { return &arg
; }, desc
);
323 typedef span
<const SettingVariant
> SettingTable
;
325 const SettingDesc
*GetSettingFromName(const std::string_view name
);
326 void GetSaveLoadFromSettingTable(SettingTable settings
, std::vector
<SaveLoad
> &saveloads
);
327 bool SetSettingValue(const IntSettingDesc
*sd
, int32 value
, bool force_newgame
= false);
328 bool SetSettingValue(const StringSettingDesc
*sd
, const std::string value
, bool force_newgame
= false);
330 #endif /* SETTINGS_INTERNAL_H */