#pragma once #include #include #include #include #include "delegates.hpp" #include "typedefs.hpp" enum class setting_format { simple, percent }; class Setting { protected: setting_format format; public: Setting(setting_format format) : format(format) { } virtual ~Setting() { } virtual void resetToDefault() = 0; virtual setting_format getFormat() const { return format; } virtual std::string toString() const = 0; }; template class ObservableSetting : public Setting { int nextid = 1; std::unordered_map> observers; protected: T initial; T value; public: ObservableSetting(T value, setting_format format) : Setting(format), initial(value), value(value) { } observer_handler observe(consumer callback, bool callOnStart = false) { const int id = nextid++; observers.emplace(id, callback); if (callOnStart) { callback(value); } return std::shared_ptr(new int(id), [this](int* id) { //-V508 observers.erase(*id); delete id; }); } const T& get() const { return value; } T& operator*() { return value; } void notify(T value) { for (auto& entry : observers) { entry.second(value); } } void set(T value) { if (value == this->value) { return; } this->value = value; notify(value); } virtual void resetToDefault() override { set(initial); } }; class NumberSetting : public ObservableSetting { protected: number_t min; number_t max; public: NumberSetting( number_t value, number_t min = std::numeric_limits::min(), number_t max = std::numeric_limits::max(), setting_format format = setting_format::simple ) : ObservableSetting(value, format), min(min), max(max) { } number_t& operator*() { return value; } number_t get() const { return value; } number_t getMin() const { return min; } number_t getMax() const { return max; } number_t getT() const { return (value - min) / (max - min); } virtual std::string toString() const override; static inline NumberSetting createPercent(number_t def) { return NumberSetting(def, 0.0, 1.0, setting_format::percent); } }; class IntegerSetting : public ObservableSetting { protected: integer_t min; integer_t max; public: IntegerSetting( integer_t value, integer_t min = std::numeric_limits::min(), integer_t max = std::numeric_limits::max(), setting_format format = setting_format::simple ) : ObservableSetting(value, format), min(min), max(max) { } integer_t getMin() const { return min; } integer_t getMax() const { return max; } integer_t getT() const { return (value - min) / (max - min); } virtual std::string toString() const override; }; class FlagSetting : public ObservableSetting { public: FlagSetting(bool value, setting_format format = setting_format::simple) : ObservableSetting(value, format) { } void toggle() { set(!get()); } virtual std::string toString() const override; }; class StringSetting : public ObservableSetting { public: StringSetting( std::string value, setting_format format = setting_format::simple ) : ObservableSetting(value, format) { } virtual std::string toString() const override; };