diff --git a/src/data/dynamic.cpp b/src/data/dynamic.cpp index 2702ada0..62ab3c2b 100644 --- a/src/data/dynamic.cpp +++ b/src/data/dynamic.cpp @@ -353,6 +353,10 @@ Value::~Value() { } } +Value Value::of(bool value) { + return Value(valtype::boolean, value); +} + Value Value::of(number_u value) { if (std::holds_alternative(value)) { return Value(valtype::integer, std::get(value)); @@ -360,3 +364,7 @@ Value Value::of(number_u value) { return Value(valtype::number, std::get(value)); } } + +Value Value::of(const std::string& value) { + return Value(valtype::string, value); +} diff --git a/src/data/dynamic.h b/src/data/dynamic.h index 5031174c..c32e20e8 100644 --- a/src/data/dynamic.h +++ b/src/data/dynamic.h @@ -33,7 +33,9 @@ namespace dynamic { Value(valtype type, valvalue value); ~Value(); + static Value of(bool value); static Value of(number_u value); + static Value of(const std::string& value); }; class List { diff --git a/src/data/setting.cpp b/src/data/setting.cpp index 07af28e2..d4c78d39 100644 --- a/src/data/setting.cpp +++ b/src/data/setting.cpp @@ -2,19 +2,13 @@ #include "../util/stringutil.h" -template -std::string NumberSetting::toString() const { +std::string NumberSetting::toString() const { switch (getFormat()) { case setting_format::simple: return util::to_string(value); case setting_format::percent: - return std::to_string(static_cast(value * 100)) + "%"; + return std::to_string(static_cast(value * 100)) + "%"; default: return "invalid format"; } } - -template class NumberSetting; -template class NumberSetting; -template class NumberSetting; -template class NumberSetting; diff --git a/src/data/setting.h b/src/data/setting.h index 48c607ad..e51c1e18 100644 --- a/src/data/setting.h +++ b/src/data/setting.h @@ -4,6 +4,8 @@ #include #include +#include "../typedefs.h" + enum class setting_format { simple, percent }; @@ -26,47 +28,46 @@ public: virtual std::string toString() const = 0; }; -template class NumberSetting : public Setting { protected: - T initial; - T value; - T min; - T max; + number_t initial; + number_t value; + number_t min; + number_t max; public: NumberSetting( - T value, - T min=std::numeric_limits::min(), - T max=std::numeric_limits::max(), + number_t value, + number_t min=std::numeric_limits::min(), + number_t max=std::numeric_limits::max(), setting_format format=setting_format::simple ) : Setting(format), initial(value), value(value), min(min), - max(max) + max(max) {} - T& operator*() { + number_t& operator*() { return value; } - T get() const { + number_t get() const { return value; } - void set(T value) { + void set(number_t value) { this->value = value; } - T getMin() const { + number_t getMin() const { return min; } - T getMax() const { + number_t getMax() const { return max; } - T getT() const { + number_t getT() const { return (value - min) / (max - min); } @@ -76,7 +77,7 @@ public: virtual std::string toString() const override; - static inline NumberSetting createPercent(T def) { + static inline NumberSetting createPercent(number_t def) { return NumberSetting(def, 0.0, 1.0, setting_format::percent); } }; diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index 7ed660ce..a5960ec1 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -19,6 +19,41 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) { map.emplace("camera.sensitivity", &settings.camera.sensitivity); } +dynamic::Value SettingsHandler::getValue(const std::string& name) const { + auto found = map.find(name); + if (found == map.end()) { + throw std::runtime_error("setting '"+name+"' does not exist"); + } + auto setting = found->second; + if (auto number = dynamic_cast(setting)) { + return dynamic::Value::of((number_t)number->get()); + } else { + throw std::runtime_error("type is not implemented for '"+name+"'"); + } +} + +void SettingsHandler::setValue(const std::string& name, dynamic::Value value) { + auto found = map.find(name); + if (found == map.end()) { + throw std::runtime_error("setting '"+name+"' does not exist"); + } + auto setting = found->second; + if (auto number = dynamic_cast(setting)) { + switch (value.type) { + case dynamic::valtype::integer: + number->set(std::get(value.value)); + break; + case dynamic::valtype::number: + number->set(std::get(value.value)); + break; + default: + throw std::runtime_error("type error, numeric value expected"); + } + } else { + throw std::runtime_error("type is not implement - setting '"+name+"'"); + } +} + toml::Wrapper* create_wrapper(EngineSettings& settings) { auto wrapper = std::make_unique(); diff --git a/src/frontend/menu/menu_settings.cpp b/src/frontend/menu/menu_settings.cpp index 5510e4f9..37e1104e 100644 --- a/src/frontend/menu/menu_settings.cpp +++ b/src/frontend/menu/menu_settings.cpp @@ -15,7 +15,7 @@ using namespace gui; static void create_volume_trackbar( std::shared_ptr panel, const std::wstring& name, - NumberSetting* field + NumberSetting* field ) { panel->add(menus::create_label([=]() { return langs::get(name, L"settings")+L": " + diff --git a/src/logic/scripting/lua/LuaState.cpp b/src/logic/scripting/lua/LuaState.cpp index 1d7e2c94..fbffac37 100644 --- a/src/logic/scripting/lua/LuaState.cpp +++ b/src/logic/scripting/lua/LuaState.cpp @@ -205,6 +205,32 @@ int lua::LuaState::pushvalue(int idx) { return 1; } +int lua::LuaState::pushvalue(const dynamic::Value& value) { + using dynamic::valtype; + switch (value.type) { + case valtype::boolean: + pushboolean(std::get(value.value)); + break; + case valtype::integer: + pushinteger(std::get(value.value)); + break; + case valtype::number: + pushnumber(std::get(value.value)); + break; + case valtype::string: + pushstring(std::get(value.value).c_str()); + break; + case valtype::none: + pushnil(); + break; + case valtype::list: + throw std::runtime_error("type 'list' is not implemented"); + case valtype::map: + throw std::runtime_error("type 'map' is not implemented"); + } + return 1; +} + int lua::LuaState::pushglobals() { lua_pushvalue(L, LUA_GLOBALSINDEX); return 1; @@ -248,6 +274,31 @@ const char* lua::LuaState::tostring(int idx) { return lua_tostring(L, idx); } +dynamic::Value lua::LuaState::tovalue(int idx) { + using dynamic::valtype; + auto type = lua_type(L, idx); + switch (type) { + case LUA_TNIL: + case LUA_TNONE: + return dynamic::Value(valtype::none, 0); + case LUA_TBOOLEAN: + return dynamic::Value::of(lua_toboolean(L, idx) == 1); + case LUA_TNUMBER: { + auto number = lua_tonumber(L, idx); + auto integer = lua_tointeger(L, idx); + if (number == (lua_Number)integer) { + return dynamic::Value::of(integer); + } else { + return dynamic::Value::of(number); + } + } + case LUA_TSTRING: + return dynamic::Value::of(lua_tostring(L, idx)); + default: + throw std::runtime_error("lua type "+std::to_string(type)+" is not supported"); + } +} + bool lua::LuaState::isstring(int idx) { return lua_isstring(L, idx); } diff --git a/src/logic/scripting/lua/LuaState.h b/src/logic/scripting/lua/LuaState.h index 5e753bb1..87eae32e 100644 --- a/src/logic/scripting/lua/LuaState.h +++ b/src/logic/scripting/lua/LuaState.h @@ -5,6 +5,8 @@ #include #include +#include "../../../data/dynamic.h" + #ifndef LUAJIT_VERSION #error LuaJIT required #endif @@ -36,6 +38,7 @@ namespace lua { int pushstring(const std::string& str); int pushenv(int env); int pushvalue(int idx); + int pushvalue(const dynamic::Value& value); int pushnil(); int pushglobals(); void pop(int n=1); @@ -44,6 +47,7 @@ namespace lua { bool toboolean(int idx); luaint tointeger(int idx); luanumber tonumber(int idx); + dynamic::Value tovalue(int idx); const char* tostring(int idx); bool isstring(int idx); bool isfunction(int idx); diff --git a/src/settings.h b/src/settings.h index 2b74c4b8..95f755ad 100644 --- a/src/settings.h +++ b/src/settings.h @@ -12,11 +12,11 @@ struct AudioSettings { /// @brief try to initialize AL backend bool enabled = true; - NumberSetting volumeMaster {1.0f, 0.0f, 1.0f, setting_format::percent}; - NumberSetting volumeRegular {1.0f, 0.0f, 1.0f, setting_format::percent}; - NumberSetting volumeUI {1.0f, 0.0f, 1.0f, setting_format::percent}; - NumberSetting volumeAmbient {1.0f, 0.0f, 1.0f, setting_format::percent}; - NumberSetting volumeMusic {1.0f, 0.0f, 1.0f, setting_format::percent}; + NumberSetting volumeMaster {1.0f, 0.0f, 1.0f, setting_format::percent}; + NumberSetting volumeRegular {1.0f, 0.0f, 1.0f, setting_format::percent}; + NumberSetting volumeUI {1.0f, 0.0f, 1.0f, setting_format::percent}; + NumberSetting volumeAmbient {1.0f, 0.0f, 1.0f, setting_format::percent}; + NumberSetting volumeMusic {1.0f, 0.0f, 1.0f, setting_format::percent}; }; struct DisplaySettings { @@ -53,7 +53,7 @@ struct CameraSettings { /// @brief Camera field of view float fov = 90.0f; /// @brief Camera sensitivity - NumberSetting sensitivity {2.0f, 0.1f, 10.0f}; + NumberSetting sensitivity {2.0f, 0.1f, 10.0f}; }; struct GraphicsSettings {