ObservableSetting

This commit is contained in:
MihailRis
2024-04-26 02:43:10 +03:00
parent 4861fedf1e
commit 6650e27737
4 changed files with 47 additions and 99 deletions
+37 -91
View File
@@ -34,42 +34,66 @@ public:
using observer_handler = std::shared_ptr<int>; using observer_handler = std::shared_ptr<int>;
template<class T> template<class T>
class Observers { class ObservableSetting : public Setting {
int nextid = 1; int nextid = 1;
std::unordered_map<int, consumer<T>> observers; std::unordered_map<int, consumer<T>> observers;
protected:
T initial;
T value;
public: public:
observer_handler observe(consumer<T> callback) { ObservableSetting(T value, setting_format format)
: Setting(format), initial(value), value(value) {}
observer_handler observe(consumer<T> callback, bool callOnStart=false) {
const int id = nextid++; const int id = nextid++;
observers.emplace(id, callback); observers.emplace(id, callback);
if (callOnStart) {
callback(value);
}
return std::shared_ptr<int>(new int(id), [this](int* id) { return std::shared_ptr<int>(new int(id), [this](int* id) {
observers.erase(*id); observers.erase(*id);
delete id; delete id;
}); });
} }
T get() const {
return value;
}
T& operator*() {
return value;
}
void notify(T value) { void notify(T value) {
for (auto& entry : observers) { for (auto& entry : observers) {
entry.second(value); 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 Setting { class NumberSetting : public ObservableSetting<number_t> {
protected: protected:
number_t initial;
number_t value;
number_t min; number_t min;
number_t max; number_t max;
Observers<number_t> observers;
public: public:
NumberSetting( NumberSetting(
number_t value, number_t value,
number_t min=std::numeric_limits<number_t>::min(), number_t min=std::numeric_limits<number_t>::min(),
number_t max=std::numeric_limits<number_t>::max(), number_t max=std::numeric_limits<number_t>::max(),
setting_format format=setting_format::simple setting_format format=setting_format::simple
) : Setting(format), ) : ObservableSetting(value, format),
initial(value),
value(value),
min(min), min(min),
max(max) max(max)
{} {}
@@ -82,14 +106,6 @@ public:
return value; return value;
} }
void set(number_t value) {
if (value == this->value) {
return;
}
this->value = value;
observers.notify(value);
}
number_t getMin() const { number_t getMin() const {
return min; return min;
} }
@@ -102,14 +118,6 @@ public:
return (value - min) / (max - min); return (value - min) / (max - min);
} }
observer_handler observe(consumer<number_t> callback) {
return observers.observe(callback);
}
virtual void resetToDefault() override {
set(initial);
}
virtual std::string toString() const override; virtual std::string toString() const override;
static inline NumberSetting createPercent(number_t def) { static inline NumberSetting createPercent(number_t def) {
@@ -117,42 +125,21 @@ public:
} }
}; };
class IntegerSetting : public Setting { class IntegerSetting : public ObservableSetting<integer_t> {
protected: protected:
integer_t initial;
integer_t value;
integer_t min; integer_t min;
integer_t max; integer_t max;
Observers<integer_t> observers;
public: public:
IntegerSetting( IntegerSetting(
integer_t value, integer_t value,
integer_t min=std::numeric_limits<integer_t>::min(), integer_t min=std::numeric_limits<integer_t>::min(),
integer_t max=std::numeric_limits<integer_t>::max(), integer_t max=std::numeric_limits<integer_t>::max(),
setting_format format=setting_format::simple setting_format format=setting_format::simple
) : Setting(format), ) : ObservableSetting(value, format),
initial(value),
value(value),
min(min), min(min),
max(max) max(max)
{} {}
integer_t& operator*() {
return value;
}
integer_t get() const {
return value;
}
void set(integer_t value) {
if (value == this->value) {
return;
}
this->value = value;
observers.notify(value);
}
integer_t getMin() const { integer_t getMin() const {
return min; return min;
} }
@@ -165,62 +152,21 @@ public:
return (value - min) / (max - min); return (value - min) / (max - min);
} }
observer_handler observe(consumer<integer_t> callback) {
return observers.observe(callback);
}
virtual void resetToDefault() override {
set(initial);
}
virtual std::string toString() const override; virtual std::string toString() const override;
}; };
class FlagSetting : public Setting { class FlagSetting : public ObservableSetting<bool> {
protected:
bool initial;
bool value;
Observers<bool> observers;
public: public:
FlagSetting( FlagSetting(
bool value, bool value,
setting_format format=setting_format::simple setting_format format=setting_format::simple
) : Setting(format), ) : ObservableSetting(value, format)
initial(value),
value(value)
{} {}
bool& operator*() {
return value;
}
bool get() const {
return value;
}
void set(bool value) {
if (value == this->value) {
return;
}
this->value = value;
observers.notify(value);
}
void toggle() { void toggle() {
set(!get()); set(!get());
} }
observer_handler observe(consumer<bool> callback, bool callOnStart=false) {
if (callOnStart) {
callback(value);
}
return observers.observe(callback);
}
virtual void resetToDefault() override {
set(initial);
}
virtual std::string toString() const override; virtual std::string toString() const override;
}; };
+2 -2
View File
@@ -107,11 +107,11 @@ void Engine::updateHotkeys() {
} }
void Engine::saveScreenshot() { void Engine::saveScreenshot() {
std::unique_ptr<ImageData> image(Window::takeScreenshot()); auto image = Window::takeScreenshot();
image->flipY(); image->flipY();
fs::path filename = paths->getScreenshotFile("png"); fs::path filename = paths->getScreenshotFile("png");
imageio::write(filename.string(), image.get()); imageio::write(filename.string(), image.get());
logger.info() << "saved screenshot as "+filename.u8string(); logger.info() << "saved screenshot as " << filename.u8string();
} }
void Engine::mainloop() { void Engine::mainloop() {
+6 -4
View File
@@ -312,11 +312,13 @@ DisplaySettings* Window::getSettings() {
return settings; return settings;
} }
ImageData* Window::takeScreenshot() { std::unique_ptr<ImageData> Window::takeScreenshot() {
ubyte* data = new ubyte[width * height * 3]; auto data = std::make_unique<ubyte[]>(width * height * 3);
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data); glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data.get());
return new ImageData(ImageFormat::rgb888, width, height, data); return std::make_unique<ImageData>(
ImageFormat::rgb888, width, height, data.release()
);
} }
const char* Window::getClipboardText() { const char* Window::getClipboardText() {
+2 -2
View File
@@ -5,7 +5,7 @@
#include <stack> #include <stack>
#include <vector> #include <vector>
#include <memory>
#include <glm/glm.hpp> #include <glm/glm.hpp>
class ImageData; class ImageData;
@@ -58,7 +58,7 @@ public:
return glm::vec2(width, height); return glm::vec2(width, height);
} }
static ImageData* takeScreenshot(); static std::unique_ptr<ImageData> takeScreenshot();
}; };
#endif /* WINDOW_WINDOW_H_ */ #endif /* WINDOW_WINDOW_H_ */