settings observers lifecycle

This commit is contained in:
MihailRis
2024-04-22 19:10:36 +03:00
parent 201209887f
commit 5b82b18c6f
6 changed files with 75 additions and 43 deletions
+38 -21
View File
@@ -4,6 +4,7 @@
#include <limits> #include <limits>
#include <string> #include <string>
#include <vector> #include <vector>
#include <unordered_map>
#include "../typedefs.h" #include "../typedefs.h"
#include "../delegates.h" #include "../delegates.h"
@@ -30,13 +31,35 @@ public:
virtual std::string toString() const = 0; virtual std::string toString() const = 0;
}; };
using observer_handler = std::shared_ptr<int>;
template<class T>
class Observers {
int nextid = 1;
std::unordered_map<int, consumer<T>> observers;
public:
observer_handler observe(consumer<T> callback) {
const int id = nextid++;
observers.emplace(id, callback);
return std::shared_ptr<int>(new int(id), [this](int* id) {
observers.erase(*id);
});
}
void notify(T value) {
for (auto& entry : observers) {
entry.second(value);
}
}
};
class NumberSetting : public Setting { class NumberSetting : public Setting {
protected: protected:
number_t initial; number_t initial;
number_t value; number_t value;
number_t min; number_t min;
number_t max; number_t max;
std::vector<consumer<number_t>> consumers; Observers<number_t> observers;
public: public:
NumberSetting( NumberSetting(
number_t value, number_t value,
@@ -63,9 +86,7 @@ public:
return; return;
} }
this->value = value; this->value = value;
for (auto& callback : consumers) { observers.notify(value);
callback(value);
}
} }
number_t getMin() const { number_t getMin() const {
@@ -80,12 +101,12 @@ public:
return (value - min) / (max - min); return (value - min) / (max - min);
} }
void observe(consumer<number_t> callback) { observer_handler observe(consumer<number_t> callback) {
consumers.push_back(callback); return observers.observe(callback);
} }
virtual void resetToDefault() override { virtual void resetToDefault() override {
value = initial; set(initial);
} }
virtual std::string toString() const override; virtual std::string toString() const override;
@@ -101,7 +122,7 @@ protected:
integer_t value; integer_t value;
integer_t min; integer_t min;
integer_t max; integer_t max;
std::vector<consumer<integer_t>> consumers; Observers<integer_t> observers;
public: public:
IntegerSetting( IntegerSetting(
integer_t value, integer_t value,
@@ -128,9 +149,7 @@ public:
return; return;
} }
this->value = value; this->value = value;
for (auto& callback : consumers) { observers.notify(value);
callback(value);
}
} }
integer_t getMin() const { integer_t getMin() const {
@@ -145,12 +164,12 @@ public:
return (value - min) / (max - min); return (value - min) / (max - min);
} }
void observe(consumer<integer_t> callback) { observer_handler observe(consumer<integer_t> callback) {
consumers.push_back(callback); return observers.observe(callback);
} }
virtual void resetToDefault() override { virtual void resetToDefault() override {
value = initial; set(initial);
} }
virtual std::string toString() const override; virtual std::string toString() const override;
@@ -160,7 +179,7 @@ class FlagSetting : public Setting {
protected: protected:
bool initial; bool initial;
bool value; bool value;
std::vector<consumer<bool>> consumers; Observers<bool> observers;
public: public:
FlagSetting( FlagSetting(
bool value, bool value,
@@ -183,17 +202,15 @@ public:
return; return;
} }
this->value = value; this->value = value;
for (auto& callback : consumers) { observers.notify(value);
callback(value);
}
} }
void observe(consumer<bool> callback) { observer_handler observe(consumer<bool> callback) {
consumers.push_back(callback); return observers.observe(callback);
} }
virtual void resetToDefault() override { virtual void resetToDefault() override {
value = initial; set(initial);
} }
virtual std::string toString() const override; virtual std::string toString() const override;
+8 -8
View File
@@ -47,13 +47,13 @@ void addWorldGenerators() {
WorldGenerators::addGenerator<FlatWorldGenerator>("core:flat"); WorldGenerators::addGenerator<FlatWorldGenerator>("core:flat");
} }
inline void create_channel(std::string name, NumberSetting& setting) { inline void create_channel(Engine* engine, std::string name, NumberSetting& setting) {
if (name != "master") { if (name != "master") {
audio::create_channel(name); audio::create_channel(name);
} }
setting.observe([=](auto value) { engine->keepAlive(setting.observe([=](auto value) {
audio::get_channel(name)->setVolume(value*value); audio::get_channel(name)->setVolume(value*value);
}); }));
} }
Engine::Engine(EngineSettings& settings, EnginePaths* paths) Engine::Engine(EngineSettings& settings, EnginePaths* paths)
@@ -64,11 +64,11 @@ Engine::Engine(EngineSettings& settings, EnginePaths* paths)
throw initialize_error("could not initialize window"); throw initialize_error("could not initialize window");
} }
audio::initialize(settings.audio.enabled); audio::initialize(settings.audio.enabled);
create_channel("master", settings.audio.volumeMaster); create_channel(this, "master", settings.audio.volumeMaster);
create_channel("regular", settings.audio.volumeRegular); create_channel(this, "regular", settings.audio.volumeRegular);
create_channel("music", settings.audio.volumeMusic); create_channel(this, "music", settings.audio.volumeMusic);
create_channel("ambient", settings.audio.volumeAmbient); create_channel(this, "ambient", settings.audio.volumeAmbient);
create_channel("ui", settings.audio.volumeUI); create_channel(this, "ui", settings.audio.volumeUI);
auto resdir = paths->getResources(); auto resdir = paths->getResources();
+2 -1
View File
@@ -11,6 +11,7 @@
#include "content/PacksManager.h" #include "content/PacksManager.h"
#include "files/engine_paths.h" #include "files/engine_paths.h"
#include "files/settings_io.h" #include "files/settings_io.h"
#include "util/ObjectsKeeper.hpp"
#include <filesystem> #include <filesystem>
#include <memory> #include <memory>
@@ -38,7 +39,7 @@ public:
initialize_error(const std::string& message) : std::runtime_error(message) {} initialize_error(const std::string& message) : std::runtime_error(message) {}
}; };
class Engine { class Engine : public util::ObjectsKeeper {
EngineSettings& settings; EngineSettings& settings;
SettingsHandler settingsHandler; SettingsHandler settingsHandler;
EnginePaths* paths; EnginePaths* paths;
+6 -12
View File
@@ -86,8 +86,6 @@ void MenuScreen::draw(float delta) {
batch->flush(); batch->flush();
} }
static bool backlight;
LevelScreen::LevelScreen(Engine* engine, Level* level) : Screen(engine) { LevelScreen::LevelScreen(Engine* engine, Level* level) : Screen(engine) {
auto& settings = engine->getSettings(); auto& settings = engine->getSettings();
auto assets = engine->getAssets(); auto assets = engine->getAssets();
@@ -100,8 +98,12 @@ LevelScreen::LevelScreen(Engine* engine, Level* level) : Screen(engine) {
worldRenderer = std::make_unique<WorldRenderer>(engine, frontend.get(), controller->getPlayer()); worldRenderer = std::make_unique<WorldRenderer>(engine, frontend.get(), controller->getPlayer());
hud = std::make_unique<Hud>(engine, frontend.get(), controller->getPlayer()); hud = std::make_unique<Hud>(engine, frontend.get(), controller->getPlayer());
keepAlive(settings.graphics.backlight.observe([=](bool flag) {
backlight = settings.graphics.backlight.get(); controller->getLevel()->chunks->saveAndClear();
}));
keepAlive(settings.camera.fov.observe([=](double value) {
controller->getPlayer()->camera->setFov(glm::radians(value));
}));
animator = std::make_unique<TextureAnimator>(); animator = std::make_unique<TextureAnimator>();
animator->addAnimations(assets->getAnimations()); animator->addAnimations(assets->getAnimations());
@@ -163,14 +165,6 @@ void LevelScreen::update(float delta) {
camera->up camera->up
); );
// TODO: subscribe for setting change
EngineSettings& settings = engine->getSettings();
controller->getPlayer()->camera->setFov(glm::radians(settings.camera.fov.get()));
if (settings.graphics.backlight.get() != backlight) {
controller->getLevel()->chunks->saveAndClear();
backlight = settings.graphics.backlight.get();
}
if (!hud->isPause()) { if (!hud->isPause()) {
controller->getLevel()->getWorld()->updateTimers(delta); controller->getLevel()->getWorld()->updateTimers(delta);
animator->update(delta); animator->update(delta);
+2 -1
View File
@@ -3,6 +3,7 @@
#include <memory> #include <memory>
#include "../settings.h" #include "../settings.h"
#include "../util/ObjectsKeeper.hpp"
class Assets; class Assets;
class Level; class Level;
@@ -16,7 +17,7 @@ class LevelController;
class TextureAnimator; class TextureAnimator;
/// @brief Screen is a mainloop state /// @brief Screen is a mainloop state
class Screen { class Screen : public util::ObjectsKeeper {
protected: protected:
Engine* engine; Engine* engine;
std::unique_ptr<Batch2D> batch; std::unique_ptr<Batch2D> batch;
+19
View File
@@ -0,0 +1,19 @@
#ifndef UTIL_OBJECTS_KEEPER_HPP_
#define UTIL_OBJECTS_KEEPER_HPP_
#include <vector>
#include <memory>
namespace util {
class ObjectsKeeper {
std::vector<std::shared_ptr<void>> ptrs;
public:
virtual ~ObjectsKeeper() {}
virtual void keepAlive(std::shared_ptr<void> ptr) {
ptrs.push_back(ptr);
}
};
}
#endif // UTIL_OBJECTS_KEEPER_HPP_