ObservableSetting
This commit is contained in:
+37
-91
@@ -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
@@ -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() {
|
||||||
|
|||||||
@@ -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
@@ -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_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user