settings: allow setting_enum to parse numeric representation of enums

use it for light forumla. disallow enums in setting_numeric.
This commit is contained in:
Eric Wasylishen 2022-05-10 22:55:41 -06:00
parent d390ac2030
commit e9abb212bb
4 changed files with 60 additions and 4 deletions

View File

@ -34,6 +34,12 @@ setting_base::setting_base(
}
}
bool setting_base::parseString(const std::string &string, bool locked)
{
parser_t p{string};
return parse("", p, locked);
}
setting_group performance_group{"Performance", 10};
setting_group logging_group{"Logging", 5};
setting_group game_group{"Game", 15};

View File

@ -174,6 +174,9 @@ public:
// copies value and source
virtual bool copyFrom(const setting_base& other) = 0;
// convenience form of parse() that constructs a temporary parser_t
bool parseString(const std::string &string, bool locked = false);
// resets value to default, and source to source::DEFAULT
virtual void reset() = 0;
virtual bool parse(const std::string &settingName, parser_base_t &parser, bool locked = false) = 0;
@ -387,6 +390,7 @@ public:
template<typename T>
class setting_numeric : public setting_value<T>
{
static_assert(!std::is_enum_v<T>, "use setting_enum for enums");
protected:
T _min, _max;
@ -415,7 +419,6 @@ public:
Q_assert(this->_value <= _max);
}
template<typename T1 = T, typename = std::enable_if_t<!std::is_enum_v<T1>>>
inline setting_numeric(setting_container *dictionary, const nameset &names, T v,
const setting_group *group = nullptr, const char *description = "")
: setting_numeric(
@ -423,7 +426,6 @@ public:
{
}
template<typename T1 = T, typename = std::enable_if_t<!std::is_enum_v<T1>>>
inline bool boolValue() const
{
return this->_value > 0;
@ -507,11 +509,22 @@ public:
return false;
}
// see if it's a string enum case label
if (auto it = _values.find(parser.token); it != _values.end()) {
this->setValueFromParse(it->second, locked);
return true;
}
// see if it's an integer
try {
const int i = std::stoi(parser.token);
this->setValueFromParse(static_cast<T>(i), locked);
return true;
} catch (std::invalid_argument &) {
} catch (std::out_of_range &) {
}
return false;
}
};

View File

@ -70,7 +70,8 @@ public:
settings::setting_scalar light{this, "light", DEFAULTLIGHTLEVEL};
settings::setting_scalar atten{this, "wait", 1.0, 0.0, std::numeric_limits<vec_t>::max()};
settings::setting_numeric<light_formula_t> formula{this, "delay", LF_LINEAR, LF_LINEAR, LF_INVERSE2A};
settings::setting_enum<light_formula_t> formula{this, "delay", LF_LINEAR,
{{"linear", LF_LINEAR}, {"inverse", LF_INVERSE}, {"inverse2", LF_INVERSE2}, {"infinite", LF_INFINITE}, {"localmin", LF_LOCALMIN}, {"inverse2a", LF_INVERSE2A}}};
settings::setting_scalar spotangle{this, "angle", 40.0};
settings::setting_scalar spotangle2{this, "softangle", 0.0};
settings::setting_numeric<int32_t> style{this, "style", 0, 0, 254};

View File

@ -1,6 +1,7 @@
#include "gtest/gtest.h"
#include <light/light.hh>
#include <light/entities.hh>
#include <random>
#include <algorithm> // for std::sort
@ -917,4 +918,39 @@ TEST(trace, clamp_texcoord)
EXPECT_EQ(0, clamp_texcoord(-127.5f, 128));
EXPECT_EQ(0, clamp_texcoord(-128.0f, 128));
EXPECT_EQ(127, clamp_texcoord(-129.0f, 128));
}
}
TEST(settings, delayDefault)
{
light_t light;
EXPECT_EQ(LF_LINEAR, light.formula.value());
}
TEST(settings, delayParseInt)
{
light_t light;
EXPECT_TRUE(light.formula.parseString("2"));
EXPECT_EQ(LF_INVERSE2, light.formula.value());
}
TEST(settings, delayParseIntUnknown)
{
light_t light;
EXPECT_TRUE(light.formula.parseString("500"));
// not sure if we should be strict and reject parsing this?
EXPECT_EQ(500, light.formula.value());
}
TEST(settings, delayParseFloat)
{
light_t light;
EXPECT_TRUE(light.formula.parseString("2.0"));
EXPECT_EQ(LF_INVERSE2, light.formula.value());
}
TEST(settings, delayParseString)
{
light_t light;
EXPECT_TRUE(light.formula.parseString("inverse2"));
EXPECT_EQ(LF_INVERSE2, light.formula.value());
}