Setting: Add support for enum type settings

pull/88/head
Jonathan G Rennison 5 years ago
parent f54f549632
commit 8b1ee39ace

@ -419,6 +419,16 @@ static const void *StringToVal(const SettingDescBase *desc, const char *orig_str
return nullptr;
}
static bool ValidateEnumSetting(const SettingDescBase *sdb, int32 val)
{
for (const SettingDescEnumEntry *enumlist = sdb->enumlist; enumlist != nullptr && enumlist->str != STR_NULL; enumlist++) {
if (enumlist->val == val) {
return true;
}
}
return false;
}
/**
* Set the value of a setting and if needed clamp the value to
* the preset minimum and maximum.
@ -456,7 +466,9 @@ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val)
case SLE_VAR_I32: {
/* Override the minimum value. No value below sdb->min, except special value 0 */
if (!(sdb->flags & SGF_0ISDISABLED) || val != 0) {
if (!(sdb->flags & SGF_MULTISTRING)) {
if (sdb->flags & SGF_ENUM) {
if (!ValidateEnumSetting(sdb, val)) val = (int32)(size_t)sdb->def;
} else if (!(sdb->flags & SGF_MULTISTRING)) {
/* Clamp value-type setting to its valid range */
val = Clamp(val, sdb->min, sdb->max);
} else if (val < sdb->min || val > (int32)sdb->max) {
@ -470,7 +482,9 @@ static void Write_ValidateSetting(void *ptr, const SettingDesc *sd, int32 val)
/* Override the minimum value. No value below sdb->min, except special value 0 */
uint32 uval = (uint32)val;
if (!(sdb->flags & SGF_0ISDISABLED) || uval != 0) {
if (!(sdb->flags & SGF_MULTISTRING)) {
if (sdb->flags & SGF_ENUM) {
if (!ValidateEnumSetting(sdb, val)) uval = (uint32)(size_t)sdb->def;
} else if (!(sdb->flags & SGF_MULTISTRING)) {
/* Clamp value-type setting to its valid range */
uval = ClampU(uval, sdb->min, sdb->max);
} else if (uval < (uint)sdb->min || uval > sdb->max) {

@ -1111,7 +1111,16 @@ void SettingEntry::SetValueDParams(uint first_param, int32 value) const
if (sdb->cmd == SDT_BOOLX) {
SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
} else {
if ((sdb->flags & SGF_MULTISTRING) != 0) {
if ((sdb->flags & SGF_ENUM) != 0) {
StringID str = STR_UNDEFINED;
for (const SettingDescEnumEntry *enumlist = sdb->enumlist; enumlist != nullptr && enumlist->str != STR_NULL; enumlist++) {
if (enumlist->val == value) {
str = enumlist->str;
break;
}
}
SetDParam(first_param++, str);
} else if ((sdb->flags & SGF_MULTISTRING) != 0) {
SetDParam(first_param++, sdb->str_val - sdb->min + value);
} else if ((sdb->flags & SGF_DISPLAY_ABS) != 0) {
SetDParam(first_param++, sdb->str_val + ((value >= 0) ? 1 : 0));
@ -1152,7 +1161,7 @@ void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right,
if (sdb->cmd == SDT_BOOLX) {
/* Draw checkbox for boolean-value either on/off */
DrawBoolButton(buttons_left, button_y, value != 0, editable);
} else if ((sdb->flags & SGF_MULTISTRING) != 0) {
} else if ((sdb->flags & (SGF_MULTISTRING | SGF_ENUM)) != 0) {
/* Draw [v] button for settings of an enum-type */
DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
} else {
@ -2209,7 +2218,7 @@ struct GameSettingsWindow : Window {
int32 value = (int32)ReadValue(var, sd->save.conv);
/* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & SGF_MULTISTRING)) {
if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & (SGF_MULTISTRING | SGF_ENUM))) {
const SettingDescBase *sdb = &sd->desc;
this->SetDisplayedHelpText(pe);
@ -2238,10 +2247,16 @@ struct GameSettingsWindow : Window {
this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
DropDownList list;
for (int i = sdb->min; i <= (int)sdb->max; i++) {
int val = sd->orderproc ? sd->orderproc(i - sdb->min) : i;
assert_msg(val >= sdb->min && val <= (int)sdb->max, "min: %d, max: %d, val: %d", sdb->min, sdb->max, val);
list.emplace_back(new DropDownListStringItem(sdb->str_val + val - sdb->min, val, false));
if (sd->desc.flags & SGF_MULTISTRING) {
for (int i = sdb->min; i <= (int)sdb->max; i++) {
int val = sd->orderproc ? sd->orderproc(i - sdb->min) : i;
assert_msg(val >= sdb->min && val <= (int)sdb->max, "min: %d, max: %d, val: %d", sdb->min, sdb->max, val);
list.emplace_back(new DropDownListStringItem(sdb->str_val + val - sdb->min, val, false));
}
} else if ((sd->desc.flags & SGF_ENUM)) {
for (const SettingDescEnumEntry *enumlist = sd->desc.enumlist; enumlist != nullptr && enumlist->str != STR_NULL; enumlist++) {
list.emplace_back(new DropDownListStringItem(enumlist->str, enumlist->val, false));
}
}
ShowDropDownListAt(this, std::move(list), value, -1, wi_rect, COLOUR_ORANGE, true);
@ -2311,7 +2326,7 @@ struct GameSettingsWindow : Window {
}
} else {
/* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & SGF_MULTISTRING)) {
if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & (SGF_MULTISTRING | SGF_ENUM))) {
/* Show the correct currency-translated value */
if (sd->desc.flags & SGF_CURRENCY) value *= _currency->rate;
@ -2397,7 +2412,7 @@ struct GameSettingsWindow : Window {
/* Deal with drop down boxes on the panel. */
assert(this->valuedropdown_entry != nullptr);
const SettingDesc *sd = this->valuedropdown_entry->setting;
assert(sd->desc.flags & SGF_MULTISTRING);
assert(sd->desc.flags & (SGF_MULTISTRING | SGF_ENUM));
if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
SetCompanySetting(this->valuedropdown_entry->index, index);

@ -49,6 +49,7 @@ enum SettingGuiFlagLong {
SGF_SCENEDIT_TOO = 1 << 7, ///< this setting can be changed in the scenario editor (only makes sense when SGF_NEWGAME_ONLY is set)
SGF_PER_COMPANY = 1 << 8, ///< this setting can be different for each company (saved in company struct)
SGF_DECIMAL1 = 1 << 9, ///< display a decimal representation of the setting value divided by 10
SGF_ENUM = 1 << 10,///< the setting can take one of the values given by an array of struct SettingDescEnumEntry
};
DECLARE_ENUM_AS_BIT_SET(SettingGuiFlagLong)
typedef SimpleTinyEnumT<SettingGuiFlagLong, uint16> SettingGuiFlag;
@ -92,6 +93,12 @@ typedef bool OnChange(int32 var); ///< callback prototype on data modi
typedef size_t OnConvert(const char *value); ///< callback prototype for conversion error
typedef int OnGuiOrder(uint nth); ///< callback prototype for GUI ordering
/** The last entry in an array of struct SettingDescEnumEntry must use STR_NULL. */
struct SettingDescEnumEntry {
int32 val;
StringID str;
};
/** Properties of config file settings. */
struct SettingDescBase {
const char *name; ///< name of the setting. Used in configuration file and for console
@ -108,6 +115,7 @@ struct SettingDescBase {
OnChange *proc; ///< callback procedure for when the value is changed
OnConvert *proc_cnvt; ///< callback procedure when loading value mechanism fails
SettingCategory cat; ///< assigned categories of the setting
const SettingDescEnumEntry *enumlist; ///< For SGF_ENUM. The last entry must use STR_NULL
};
struct SettingDesc {

@ -56,19 +56,22 @@ static size_t ConvertLandscape(const char *value);
* on the appropriate macro.
*/
#define NSD_GENERAL(name, def, cmd, guiflags, min, max, interval, many, str, strhelp, strval, proc, load, cat)\
{name, (const void*)(size_t)(def), {(byte)cmd}, {(uint16)guiflags}, min, max, interval, many, str, strhelp, strval, proc, load, cat}
#define NSD_GENERAL(name, def, cmd, guiflags, min, max, interval, many, str, strhelp, strval, proc, load, cat, enumlist)\
{name, (const void*)(size_t)(def), {(byte)cmd}, {(uint16)guiflags}, min, max, interval, many, str, strhelp, strval, proc, load, cat, enumlist}
/* Macros for various objects to go in the configuration file.
* This section is for global variables */
#define SDTG_GENERAL2(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat, extver, patxname, orderproc)\
{NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, nullptr, cat), SLEG_GENERAL_X(sle_cmd, var, type | flags, length, from, to, extver), patxname, nullptr, orderproc}
#define SDTG_GENERAL2(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat, extver, patxname, orderproc, enumlist)\
{NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, nullptr, cat, enumlist), SLEG_GENERAL_X(sle_cmd, var, type | flags, length, from, to, extver), patxname, nullptr, orderproc}
#define SDTG_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat, extver, patxname)\
SDTG_GENERAL2(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat, extver, patxname, nullptr)
SDTG_GENERAL2(name, sdt_cmd, sle_cmd, type, flags, guiflags, var, length, def, min, max, interval, full, str, strhelp, strval, proc, from, to, cat, extver, patxname, nullptr, nullptr)
#define SDTG_VAR(name, type, flags, guiflags, var, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extver, patxname, orderproc)\
SDTG_GENERAL2(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat, extver, patxname, orderproc)
SDTG_GENERAL2(name, SDT_NUMX, SL_VAR, type, flags, guiflags, var, 0, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat, extver, patxname, orderproc, nullptr)
#define SDTG_ENUM(name, type, flags, guiflags, var, def, str, strhelp, proc, from, to, cat, extver, patxname, enumlist)\
SDTG_GENERAL2(name, SDT_NUMX, SL_VAR, type, flags, guiflags | SGF_ENUM, var, 0, def, 0, 0, 0, nullptr, str, strhelp, STR_NULL, proc, nullptr, from, to, cat, extver, patxname, nullptr, enumlist)
#define SDTG_BOOL(name, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat, extver, patxname)\
SDTG_GENERAL(name, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, var, 0, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extver, patxname)
@ -86,20 +89,23 @@ static size_t ConvertLandscape(const char *value);
SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, strhelp, strval, proc, from, to, cat, extver, patxname)
#define SDTG_NULL(length, from, to, extver)\
{{"", nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE}, SLEG_NULL_X(length, from, to, extver), nullptr, nullptr, nullptr}
{{"", nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, nullptr}, SLEG_NULL_X(length, from, to, extver), nullptr, nullptr, nullptr}
#define SDTG_END() {{nullptr, nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE}, SLEG_END(), nullptr, nullptr, nullptr}
#define SDTG_END() {{nullptr, nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, nullptr}, SLEG_END(), nullptr, nullptr, nullptr}
/* Macros for various objects to go in the configuration file.
* This section is for structures where their various members are saved */
#define SDT_GENERAL2(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extver, patxname, orderproc)\
{NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, load, cat), SLE_GENERAL_X(sle_cmd, base, var, type | flags, length, from, to, extver), patxname, nullptr, orderproc}
#define SDT_GENERAL2(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extver, patxname, orderproc, enumlist)\
{NSD_GENERAL(name, def, sdt_cmd, guiflags, min, max, interval, full, str, strhelp, strval, proc, load, cat, enumlist), SLE_GENERAL_X(sle_cmd, base, var, type | flags, length, from, to, extver), patxname, nullptr, orderproc}
#define SDT_GENERAL(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extver, patxname)\
SDT_GENERAL2(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extver, patxname, nullptr)
SDT_GENERAL2(name, sdt_cmd, sle_cmd, type, flags, guiflags, base, var, length, def, min, max, interval, full, str, strhelp, strval, proc, load, from, to, cat, extver, patxname, nullptr, nullptr)
#define SDT_VAR(base, var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extver, patxname, orderproc)\
SDT_GENERAL2(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, base, var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extver, patxname, orderproc)
SDT_GENERAL2(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, base, var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extver, patxname, orderproc, nullptr)
#define SDT_ENUM(base, var, type, flags, guiflags, def, str, strhelp, proc, from, to, cat, extver, patxname, enumlist)\
SDT_GENERAL2(#var, SDT_NUMX, SL_VAR, type, flags, guiflags | SGF_ENUM, base, var, 1, def, 0, 0, 0, nullptr, str, strhelp, STR_NULL, proc, nullptr, from, to, cat, extver, patxname, nullptr, enumlist)
#define SDT_BOOL(base, var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extver, patxname)\
SDT_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, base, var, 1, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, nullptr, from, to, cat, extver, patxname)
@ -120,11 +126,14 @@ static size_t ConvertLandscape(const char *value);
SDT_GENERAL(#var, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, base, var, 1, def, 0, 0, 0, full, str, strhelp, strval, proc, nullptr, from, to, cat, extver, patxname)
#define SDT_NULL(length, from, to, extver)\
{{"", nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE}, SLE_CONDNULL_X(length, from, to, extver), nullptr, nullptr, nullptr}
{{"", nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, nullptr}, SLE_CONDNULL_X(length, from, to, extver), nullptr, nullptr, nullptr}
#define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, strhelp, strval, proc, from, to, cat, extver, patxname, orderproc)\
SDTG_GENERAL2(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat, extver, patxname, orderproc)
SDTG_GENERAL2(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, min, max, interval, nullptr, str, strhelp, strval, proc, from, to, cat, extver, patxname, orderproc, nullptr)
#define SDTC_ENUM(var, type, flags, guiflags, def, str, strhelp, proc, from, to, cat, extver, patxname, enumlist)\
SDTG_GENERAL2(#var, SDT_NUMX, SL_VAR, type, flags, guiflags | SGF_ENUM, _settings_client.var, 1, def, 0, 0, 0, nullptr, str, strhelp, STR_NULL, proc, nullptr, from, to, cat, extver, patxname, nullptr, enumlist)
#define SDTC_BOOL(var, flags, guiflags, def, str, strhelp, strval, proc, from, to, cat, extver, patxname)\
SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 1, def, 0, 1, 0, nullptr, str, strhelp, strval, proc, from, to, cat, extver, patxname)
@ -139,7 +148,7 @@ static size_t ConvertLandscape(const char *value);
SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat, extver, patxname)
#define SDT_XREF(from, to, extver, xref)\
{{"", nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE}, SLE_CONDNULL_X(0, from, to, extver), nullptr, xref, nullptr}
{{"", nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, nullptr}, SLE_CONDNULL_X(0, from, to, extver), nullptr, xref, nullptr}
#define SDT_END() {{nullptr, nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE}, SLE_END(), nullptr, nullptr, nullptr}
#define SDT_END() {{nullptr, nullptr, {0}, {0}, 0, 0, 0, nullptr, STR_NULL, STR_NULL, STR_NULL, nullptr, nullptr, SC_NONE, nullptr}, SLE_END(), nullptr, nullptr, nullptr}

@ -81,6 +81,7 @@ const SettingDesc _settings[] = {
[templates]
SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname),
SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname, $orderproc),
SDTG_ENUM = SDTG_ENUM($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $proc, $from, $to, $cat, $extver, $patxname, $enumlist),
SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname),
SDTC_BOOL = SDTC_BOOL( $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname),
SDTC_LIST = SDTC_LIST( $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname),
@ -91,6 +92,7 @@ SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def,
SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extver, $patxname),
SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname),
SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extver, $patxname, $orderproc),
SDT_ENUM = SDT_ENUM($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $proc, $from, $to, $cat, $extver, $patxname, $enumlist),
SDT_NULL = SDT_NULL($length, $from, $to, $extver),
SDT_XREF = SDT_XREF( $from, $to, $extver, $xref),
SDT_END = SDT_END()
@ -111,6 +113,7 @@ extver = SlXvFeatureTest()
patxname = nullptr
xref = <this parameter must be set>
orderproc = nullptr
enumlist = <this parameter must be set>

Loading…
Cancel
Save