diff --git a/src/coders/toml.cpp b/src/coders/toml.cpp index b772cbe0..eb294f74 100644 --- a/src/coders/toml.cpp +++ b/src/coders/toml.cpp @@ -38,6 +38,10 @@ void Section::add(string name, float* ptr) { add(name, {fieldtype::ftfloat, ptr}); } +void Section::add(string name, double* ptr) { + add(name, {fieldtype::ftdouble, ptr}); +} + void Section::add(string name, string* ptr) { add(name, {fieldtype::ftstring, ptr}); } @@ -98,6 +102,7 @@ std::string Wrapper::write() const { case fieldtype::ftint: ss << *((int*)field->ptr); break; case fieldtype::ftuint: ss << *((uint*)field->ptr); break; case fieldtype::ftfloat: ss << *((float*)field->ptr); break; + case fieldtype::ftdouble: ss << *((double*)field->ptr); break; case fieldtype::ftstring: ss << escape_string(*((const string*)field->ptr)); break; @@ -130,10 +135,6 @@ void Reader::read() { readSection(nullptr); } -inline bool is_numeric_type(fieldtype type) { - return type == fieldtype::ftint || type == fieldtype::ftfloat; -} - void Section::set(string name, double value) { const Field* field = this->field(name); if (field == nullptr) { @@ -144,6 +145,7 @@ void Section::set(string name, double value) { case fieldtype::ftint: *(int*)(field->ptr) = value; break; case fieldtype::ftuint: *(uint*)(field->ptr) = value; break; case fieldtype::ftfloat: *(float*)(field->ptr) = value; break; + case fieldtype::ftdouble: *(double*)(field->ptr) = value; break; case fieldtype::ftstring: *(string*)(field->ptr) = std::to_string(value); break; default: std::cerr << "error: type error for key '" << name << "'" << std::endl; @@ -161,6 +163,7 @@ void Section::set(std::string name, bool value) { case fieldtype::ftint: *(int*)(field->ptr) = (int)value; break; case fieldtype::ftuint: *(uint*)(field->ptr) = (uint)value; break; case fieldtype::ftfloat: *(float*)(field->ptr) = (float)value; break; + case fieldtype::ftdouble: *(double*)(field->ptr) = (double)value; break; case fieldtype::ftstring: *(string*)(field->ptr) = value ? "true" : "false"; break; default: std::cerr << "error: type error for key '" << name << "'" << std::endl; @@ -246,4 +249,4 @@ void Reader::readSection(Section* section /*nullable*/) { } expectNewLine(); } -} \ No newline at end of file +} diff --git a/src/coders/toml.h b/src/coders/toml.h index 80fa85ca..3bf1791e 100644 --- a/src/coders/toml.h +++ b/src/coders/toml.h @@ -13,6 +13,7 @@ namespace toml { ftint, ftuint, ftfloat, + ftdouble, ftstring, }; @@ -32,6 +33,7 @@ namespace toml { void add(std::string name, int* ptr); void add(std::string name, uint* ptr); void add(std::string name, float* ptr); + void add(std::string name, double* ptr); void add(std::string name, std::string* ptr); const Field* field(std::string name) const; @@ -65,4 +67,4 @@ namespace toml { }; } -#endif // CODERS_TOML_H_ \ No newline at end of file +#endif // CODERS_TOML_H_ diff --git a/src/data/setting.cpp b/src/data/setting.cpp new file mode 100644 index 00000000..2b35dc78 --- /dev/null +++ b/src/data/setting.cpp @@ -0,0 +1,14 @@ +#include "setting.h" + +#include "../util/stringutil.h" + +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)) + "%"; + default: + return "invalid format"; + } +} diff --git a/src/data/setting.h b/src/data/setting.h new file mode 100644 index 00000000..6d3313fe --- /dev/null +++ b/src/data/setting.h @@ -0,0 +1,71 @@ +#ifndef DATA_SETTING_H_ +#define DATA_SETTING_H_ + +#include + +enum class setting_format { + simple, percent +}; + +template +class Setting { +protected: + T value; + setting_format format; +public: + Setting(T value, setting_format format) : value(value), format(format) { + } + + virtual ~Setting() {} + + T& operator*() { + return value; + } + + virtual const T& get() const { + return value; + } + + virtual void set(const T& value) { + this->value = value; + } + + virtual setting_format getFormat() const { + return format; + } + + virtual std::string toString() const = 0; +}; + +class NumberSetting : public Setting { +protected: + double min; + double max; +public: + NumberSetting(double value, double min, double max, setting_format format) + : Setting(value, format), min(min), max(max) {} + + double& operator*() { + return value; + } + + double getMin() const { + return min; + } + + double getMax() const { + return max; + } + + double getT() const { + return (value - min) / (max - min); + } + + virtual std::string toString() const override; + + static inline NumberSetting createPercent(double def) { + return NumberSetting(def, 0.0, 1.0, setting_format::percent); + } +}; + +#endif // DATA_SETTING_H_ diff --git a/src/engine.cpp b/src/engine.cpp index 302bbc81..1ae9fe06 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -130,11 +130,11 @@ inline constexpr float sqr(float x) { } static void updateAudio(double delta, const AudioSettings& settings) { - audio::get_channel("master")->setVolume(sqr(settings.volumeMaster)); - audio::get_channel("regular")->setVolume(sqr(settings.volumeRegular)); - audio::get_channel("ui")->setVolume(sqr(settings.volumeUI)); - audio::get_channel("ambient")->setVolume(sqr(settings.volumeAmbient)); - audio::get_channel("music")->setVolume(sqr(settings.volumeMusic)); + audio::get_channel("master")->setVolume(sqr(settings.volumeMaster.get())); + audio::get_channel("regular")->setVolume(sqr(settings.volumeRegular.get())); + audio::get_channel("ui")->setVolume(sqr(settings.volumeUI.get())); + audio::get_channel("ambient")->setVolume(sqr(settings.volumeAmbient.get())); + audio::get_channel("music")->setVolume(sqr(settings.volumeMusic.get())); audio::update(delta); } diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index 92184d2d..db31dc35 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -16,11 +16,11 @@ toml::Wrapper* create_wrapper(EngineSettings& settings) { toml::Section& audio = wrapper->add("audio"); audio.add("enabled", &settings.audio.enabled); - audio.add("volume-master", &settings.audio.volumeMaster); - audio.add("volume-regular", &settings.audio.volumeRegular); - audio.add("volume-ui", &settings.audio.volumeUI); - audio.add("volume-ambient", &settings.audio.volumeAmbient); - audio.add("volume-music", &settings.audio.volumeMusic); + audio.add("volume-master", &*settings.audio.volumeMaster); + audio.add("volume-regular", &*settings.audio.volumeRegular); + audio.add("volume-ui", &*settings.audio.volumeUI); + audio.add("volume-ambient", &*settings.audio.volumeAmbient); + audio.add("volume-music", &*settings.audio.volumeMusic); toml::Section& display = wrapper->add("display"); display.add("fullscreen", &settings.display.fullscreen); diff --git a/src/frontend/menu/menu_settings.cpp b/src/frontend/menu/menu_settings.cpp index 7d15570f..51acf1b0 100644 --- a/src/frontend/menu/menu_settings.cpp +++ b/src/frontend/menu/menu_settings.cpp @@ -15,19 +15,19 @@ using namespace gui; static void create_volume_trackbar( std::shared_ptr panel, const std::wstring& name, - float* field + NumberSetting* field ) { panel->add(menus::create_label([=]() { return langs::get(name, L"settings")+L": " + - std::to_wstring(int(*field*100))+L"%"; + util::str2wstr_utf8(field->toString()); })); auto trackbar = std::make_shared(0.0, 1.0, 1.0, 0.01, 5); trackbar->setSupplier([=]() { - return *field; + return field->get(); }); trackbar->setConsumer([=](double value) { - *field = value; + field->set(value); }); panel->add(trackbar); } diff --git a/src/settings.h b/src/settings.h index 10893782..b859f6a4 100644 --- a/src/settings.h +++ b/src/settings.h @@ -3,6 +3,7 @@ #include +#include "data/setting.h" #include "constants.h" #include "typedefs.h" @@ -10,11 +11,11 @@ struct AudioSettings { /// @brief try to initialize AL backend bool enabled = true; - float volumeMaster = 1.0f; - float volumeRegular = 1.0f; - float volumeUI = 1.0f; - float volumeAmbient = 1.0f; - float volumeMusic = 1.0f; + NumberSetting volumeMaster = NumberSetting::createPercent(1.0); + NumberSetting volumeRegular = NumberSetting::createPercent(1.0); + NumberSetting volumeUI = NumberSetting::createPercent(1.0); + NumberSetting volumeAmbient = NumberSetting::createPercent(1.0); + NumberSetting volumeMusic = NumberSetting::createPercent(1.0); }; struct DisplaySettings { @@ -87,4 +88,4 @@ struct EngineSettings { UiSettings ui; }; -#endif // SRC_SETTINGS_H_ \ No newline at end of file +#endif // SRC_SETTINGS_H_ diff --git a/src/util/stringutil.cpp b/src/util/stringutil.cpp index 3eb3d225..a40b9251 100644 --- a/src/util/stringutil.cpp +++ b/src/util/stringutil.cpp @@ -164,6 +164,12 @@ void util::trim(std::string &s) { ltrim(s); } +std::string util::to_string(double x) { + std::stringstream ss; + ss << x; + return ss.str(); +} + std::wstring util::to_wstring(double x, int precision) { std::wstringstream ss; ss << std::fixed << std::setprecision(precision) << x; diff --git a/src/util/stringutil.h b/src/util/stringutil.h index ad260de5..93b1ff19 100644 --- a/src/util/stringutil.h +++ b/src/util/stringutil.h @@ -21,6 +21,7 @@ namespace util { extern void rtrim(std::string &s); extern void trim(std::string &s); + extern std::string to_string(double x); extern std::wstring to_wstring(double x, int precision); extern std::string base64_encode(const ubyte* data, size_t size); @@ -49,4 +50,4 @@ namespace util { extern std::vector split(const std::wstring& str, char delimiter); } -#endif // UTIL_STRINGUTIL_H_ \ No newline at end of file +#endif // UTIL_STRINGUTIL_H_