From b9ea88b988ded8d8a667d14ea512293ebf9a645a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 20 Apr 2024 15:52:55 +0300 Subject: [PATCH] settings page completely moved to xml --- res/layouts/pages/settings.xml | 1 + res/layouts/pages/settings.xml.lua | 14 ++++++ src/data/setting.cpp | 9 ++++ src/data/setting.h | 43 +++++++++++++++++ src/engine.cpp | 2 +- src/files/settings_io.cpp | 53 +++++++++++--------- src/frontend/menu/menu.h | 3 -- src/frontend/menu/menu_settings.cpp | 67 -------------------------- src/frontend/screens.cpp | 6 +-- src/graphics/render/BlocksRenderer.cpp | 2 +- src/graphics/ui/gui_xml.cpp | 2 +- src/logic/PlayerController.cpp | 2 +- src/logic/scripting/lua/libcore.cpp | 4 +- src/settings.h | 8 +-- src/window/Window.cpp | 2 +- 15 files changed, 111 insertions(+), 107 deletions(-) delete mode 100644 src/frontend/menu/menu_settings.cpp diff --git a/res/layouts/pages/settings.xml b/res/layouts/pages/settings.xml index b5fb3225..0dcf5fcc 100644 --- a/res/layouts/pages/settings.xml +++ b/res/layouts/pages/settings.xml @@ -1,6 +1,7 @@ + diff --git a/res/layouts/pages/settings.xml.lua b/res/layouts/pages/settings.xml.lua index 62f35f01..67039482 100644 --- a/res/layouts/pages/settings.xml.lua +++ b/res/layouts/pages/settings.xml.lua @@ -23,9 +23,23 @@ function update_setting(x, id, name, postfix) ) end +function create_checkbox(id, name) + document.settings_panel:add(string.format( + "%s", + id, core.str_setting(id), gui.str(name, "settings") + )) +end + function on_open() create_setting("chunks.load-distance", "Load Distance", 1, 3) create_setting("chunks.load-speed", "Load Speed", 1, 1) create_setting("graphics.fog-curve", "Fog Curve", 0.1, 2) create_setting("camera.fov", "FOV", 1, 4, "°") + create_checkbox("display.vsync", "V-Sync") + create_checkbox("graphics.backlight", "Backlight") + create_checkbox("camera.shaking", "Camera Shaking") + document.langs_btn.text = string.format( + "%s: %s", gui.str("Language", "settings"), + gui.get_locales_info()[gui.get_locale()].name + ) end diff --git a/src/data/setting.cpp b/src/data/setting.cpp index 33dddae4..d39f2c08 100644 --- a/src/data/setting.cpp +++ b/src/data/setting.cpp @@ -23,3 +23,12 @@ std::string IntegerSetting::toString() const { return "invalid format"; } } + +std::string FlagSetting::toString() const { + switch (getFormat()) { + case setting_format::simple: + return value ? "true" : "false"; + default: + return "invalid format"; + } +} diff --git a/src/data/setting.h b/src/data/setting.h index 59cf372c..1146b8ac 100644 --- a/src/data/setting.h +++ b/src/data/setting.h @@ -156,4 +156,47 @@ public: virtual std::string toString() const override; }; +class FlagSetting : public Setting { +protected: + bool initial; + bool value; + std::vector> consumers; +public: + FlagSetting( + bool value, + setting_format format=setting_format::simple + ) : Setting(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; + for (auto& callback : consumers) { + callback(value); + } + } + + void observe(consumer callback) { + consumers.push_back(callback); + } + + virtual void resetToDefault() override { + value = initial; + } + + virtual std::string toString() const override; +}; + #endif // DATA_SETTING_H_ diff --git a/src/engine.cpp b/src/engine.cpp index 3c957507..49a5ba27 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -149,7 +149,7 @@ void Engine::mainloop() { if (!Window::isIconified()) { renderFrame(batch); } - Window::swapInterval(Window::isIconified() ? 1 : settings.display.swapInterval); + Window::swapInterval(Window::isIconified() ? 1 : settings.display.vsync.get()); processPostRunnables(); diff --git a/src/files/settings_io.cpp b/src/files/settings_io.cpp index 28c69b90..987c33f6 100644 --- a/src/files/settings_io.cpp +++ b/src/files/settings_io.cpp @@ -17,13 +17,17 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) { map.emplace("audio.volume-ambient", &settings.audio.volumeAmbient); map.emplace("audio.volume-music", &settings.audio.volumeMusic); + map.emplace("display.vsync", &settings.display.vsync); + map.emplace("camera.sensitivity", &settings.camera.sensitivity); map.emplace("camera.fov", &settings.camera.fov); + map.emplace("camera.shaking", &settings.camera.shaking); map.emplace("chunks.load-distance", &settings.chunks.loadDistance); map.emplace("chunks.load-speed", &settings.chunks.loadSpeed); map.emplace("graphics.fog-curve", &settings.graphics.fogCurve); + map.emplace("graphics.backlight", &settings.graphics.backlight); } dynamic::Value SettingsHandler::getValue(const std::string& name) const { @@ -36,6 +40,8 @@ dynamic::Value SettingsHandler::getValue(const std::string& name) const { return dynamic::Value::of((number_t)number->get()); } else if (auto integer = dynamic_cast(setting)) { return dynamic::Value::of((integer_t)integer->get()); + } else if (auto flag = dynamic_cast(setting)) { + return dynamic::Value::boolean(flag->get()); } else { throw std::runtime_error("type is not implemented for '"+name+"'"); } @@ -58,6 +64,23 @@ Setting* SettingsHandler::getSetting(const std::string& name) const { return found->second; } +template +static void set_numeric_value(T* setting, dynamic::Value& value) { + switch (value.type) { + case dynamic::valtype::integer: + setting->set(std::get(value.value)); + break; + case dynamic::valtype::number: + setting->set(std::get(value.value)); + break; + case dynamic::valtype::boolean: + setting->set(std::get(value.value)); + break; + default: + throw std::runtime_error("type error, numeric value expected"); + } +} + void SettingsHandler::setValue(const std::string& name, dynamic::Value value) { auto found = map.find(name); if (found == map.end()) { @@ -65,27 +88,11 @@ void SettingsHandler::setValue(const std::string& name, dynamic::Value value) { } auto setting = found->second; if (auto number = dynamic_cast(setting)) { - switch (value.type) { - case dynamic::valtype::integer: - number->set(std::get(value.value)); - break; - case dynamic::valtype::number: - number->set(std::get(value.value)); - break; - default: - throw std::runtime_error("type error, numeric value expected"); - } + set_numeric_value(number, value); } else if (auto integer = dynamic_cast(setting)) { - switch (value.type) { - case dynamic::valtype::integer: - integer->set(std::get(value.value)); - break; - case dynamic::valtype::number: - integer->set(std::get(value.value)); - break; - default: - throw std::runtime_error("type error, numeric value expected"); - } + set_numeric_value(number, value); + } else if (auto flag = dynamic_cast(setting)) { + set_numeric_value(flag, value); } else { throw std::runtime_error("type is not implement - setting '"+name+"'"); } @@ -107,7 +114,7 @@ toml::Wrapper* create_wrapper(EngineSettings& settings) { display.add("width", &settings.display.width); display.add("height", &settings.display.height); display.add("samples", &settings.display.samples); - display.add("swap-interval", &settings.display.swapInterval); + display.add("vsync", &*settings.display.vsync); toml::Section& chunks = wrapper->add("chunks"); chunks.add("load-distance", &*settings.chunks.loadDistance); @@ -117,13 +124,13 @@ toml::Wrapper* create_wrapper(EngineSettings& settings) { toml::Section& camera = wrapper->add("camera"); camera.add("fov-effects", &settings.camera.fovEvents); camera.add("fov", &*settings.camera.fov); - camera.add("shaking", &settings.camera.shaking); + camera.add("shaking", &*settings.camera.shaking); camera.add("sensitivity", &*settings.camera.sensitivity); toml::Section& graphics = wrapper->add("graphics"); graphics.add("gamma", &settings.graphics.gamma); graphics.add("fog-curve", &*settings.graphics.fogCurve); - graphics.add("backlight", &settings.graphics.backlight); + graphics.add("backlight", &*settings.graphics.backlight); graphics.add("frustum-culling", &settings.graphics.frustumCulling); graphics.add("skybox-resolution", &settings.graphics.skyboxResolution); diff --git a/src/frontend/menu/menu.h b/src/frontend/menu/menu.h index 6896401e..c395c816 100644 --- a/src/frontend/menu/menu.h +++ b/src/frontend/menu/menu.h @@ -17,9 +17,6 @@ class LevelController; using packconsumer = std::function; namespace menus { - // implemented in menu_settings.cpp - extern void create_settings_panel(Engine* engine); - extern std::shared_ptr create_packs_panel( const std::vector& packs, Engine* engine, diff --git a/src/frontend/menu/menu_settings.cpp b/src/frontend/menu/menu_settings.cpp deleted file mode 100644 index 7b317de1..00000000 --- a/src/frontend/menu/menu_settings.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "menu.h" -#include "menu_commons.h" - -#include "../locale/langs.h" -#include "../../graphics/ui/GUI.h" -#include "../../graphics/ui/gui_util.h" -#include "../../engine.h" -#include "../../util/stringutil.h" -#include "../../window/Events.h" - -#include - -using namespace gui; - -void menus::create_settings_panel(Engine* engine) { - auto menu = engine->getGUI()->getMenu(); - auto panel = menus::create_page(engine, "settings", 400, 0.0f, 1); - - /* V-Sync checkbox */{ - auto checkbox = std::make_shared( - langs::get(L"V-Sync", L"settings"), glm::vec2(400, 32) - ); - checkbox->setSupplier([=]() { - return engine->getSettings().display.swapInterval != 0; - }); - checkbox->setConsumer([=](bool checked) { - engine->getSettings().display.swapInterval = checked; - }); - panel->add(checkbox); - } - - /* Backlight checkbox */{ - auto checkbox = std::make_shared( - langs::get(L"Backlight", L"settings"), glm::vec2(400, 32) - ); - checkbox->setSupplier([=]() { - return engine->getSettings().graphics.backlight; - }); - checkbox->setConsumer([=](bool checked) { - engine->getSettings().graphics.backlight = checked; - }); - panel->add(checkbox); - } - - /* Camera shaking checkbox */ { - auto checkbox = std::make_shared( - langs::get(L"Camera Shaking", L"settings"), glm::vec2(400, 32) - ); - checkbox->setSupplier([=]() { - return engine->getSettings().camera.shaking; - }); - checkbox->setConsumer([=](bool checked) { - engine->getSettings().camera.shaking = checked; - }); - panel->add(checkbox); - } - - std::string langName = langs::locales_info.at(langs::current->getId()).name; - panel->add(guiutil::gotoButton( - langs::get(L"Language", L"settings")+L": "+ - util::str2wstr_utf8(langName), - "languages", menu)); - - panel->add(guiutil::gotoButton(L"Audio", "settings_audio", menu)); - panel->add(guiutil::gotoButton(L"Controls", "controls", menu)); - panel->add(guiutil::backButton(menu)); -} diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index e1720114..87dfa75c 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -102,7 +102,7 @@ LevelScreen::LevelScreen(Engine* engine, Level* level) : Screen(engine) { hud = std::make_unique(engine, frontend.get(), controller->getPlayer()); - backlight = settings.graphics.backlight; + backlight = settings.graphics.backlight.get(); animator = std::make_unique(); animator->addAnimations(assets->getAnimations()); @@ -167,9 +167,9 @@ void LevelScreen::update(float delta) { // TODO: subscribe for setting change EngineSettings& settings = engine->getSettings(); controller->getPlayer()->camera->setFov(glm::radians(settings.camera.fov.get())); - if (settings.graphics.backlight != backlight) { + if (settings.graphics.backlight.get() != backlight) { controller->getLevel()->chunks->saveAndClear(); - backlight = settings.graphics.backlight; + backlight = settings.graphics.backlight.get(); } if (!hud->isPause()) { diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 318ae0c3..f1e455ca 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -449,7 +449,7 @@ void BlocksRenderer::render(const voxel* voxels) { void BlocksRenderer::build(const Chunk* chunk, const ChunksStorage* chunks) { this->chunk = chunk; voxelsBuffer->setPosition(chunk->x * CHUNK_W - 1, 0, chunk->z * CHUNK_D - 1); - chunks->getVoxels(voxelsBuffer, settings.graphics.backlight); + chunks->getVoxels(voxelsBuffer, settings.graphics.backlight.get()); overflow = false; vertexOffset = 0; indexOffset = indexSize = 0; diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 166f2480..f0b0df9f 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -254,7 +254,7 @@ static std::shared_ptr readButton(UiXmlReader& reader, xml::xmlelement e static std::shared_ptr readCheckBox(UiXmlReader& reader, xml::xmlelement element) { auto text = readAndProcessInnerText(element, reader.getContext()); bool checked = element->attr("checked", "false").asBool(); - auto checkbox = std::make_shared(text, glm::vec2(), checked); + auto checkbox = std::make_shared(text, glm::vec2(32), checked); _readPanel(reader, element, *checkbox); if (element->has("consumer")) { diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 6917d784..08431a95 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -139,7 +139,7 @@ void CameraControl::switchCamera() { void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) { offset = glm::vec3(0.0f, 0.7f, 0.0f); - if (settings.shaking && !input.cheat) { + if (settings.shaking.get() && !input.cheat) { offset += updateCameraShaking(delta); } if (settings.fovEvents){ diff --git a/src/logic/scripting/lua/libcore.cpp b/src/logic/scripting/lua/libcore.cpp index 97216639..c11e776d 100644 --- a/src/logic/scripting/lua/libcore.cpp +++ b/src/logic/scripting/lua/libcore.cpp @@ -133,8 +133,8 @@ static int l_str_setting(lua_State* L) { static int l_get_setting_info(lua_State* L) { auto name = lua_tostring(L, 1); auto setting = scripting::engine->getSettingsHandler().getSetting(name); + lua_createtable(L, 0, 1); if (auto number = dynamic_cast(setting)) { - lua_createtable(L, 0, 1); lua_pushnumber(L, number->getMin()); lua_setfield(L, -2, "min"); lua_pushnumber(L, number->getMax()); @@ -142,13 +142,13 @@ static int l_get_setting_info(lua_State* L) { return 1; } if (auto integer = dynamic_cast(setting)) { - lua_createtable(L, 0, 1); lua_pushinteger(L, integer->getMin()); lua_setfield(L, -2, "min"); lua_pushinteger(L, integer->getMax()); lua_setfield(L, -2, "max"); return 1; } + lua_pop(L, 1); luaL_error(L, "unsupported setting type"); return 0; } diff --git a/src/settings.h b/src/settings.h index 50c84477..05c06e9e 100644 --- a/src/settings.h +++ b/src/settings.h @@ -28,8 +28,8 @@ struct DisplaySettings { int height = 720; /// @brief Anti-aliasing samples int samples = 0; - /// @brief GLFW swap interval value, 0 - unlimited fps, 1 - vsync - int swapInterval = 1; + /// @brief VSync on + FlagSetting vsync = {true}; /// @brief Window title */ std::string title = "VoxelEngine-Cpp v" + std::to_string(ENGINE_VERSION_MAJOR) + "." + @@ -49,7 +49,7 @@ struct CameraSettings { /// @brief Camera dynamic field of view effects bool fovEvents = true; /// @brief Camera movement shake - bool shaking = true; + FlagSetting shaking = {true}; /// @brief Camera field of view NumberSetting fov {90.0f, 10, 120}; /// @brief Camera sensitivity @@ -62,7 +62,7 @@ struct GraphicsSettings { NumberSetting fogCurve {1.6f, 1.0f, 6.0f}; float gamma = 1.0f; /// @brief Enable blocks backlight to prevent complete darkness - bool backlight = true; + FlagSetting backlight = {true}; /// @brief Enable chunks frustum culling bool frustumCulling = true; int skyboxResolution = 64 + 32; diff --git a/src/window/Window.cpp b/src/window/Window.cpp index ed571790..7a00edf7 100644 --- a/src/window/Window.cpp +++ b/src/window/Window.cpp @@ -164,7 +164,7 @@ int Window::initialize(DisplaySettings& settings){ const GLFWvidmode* mode = glfwGetVideoMode(monitor); glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, GLFW_DONT_CARE); } - glfwSwapInterval(settings.swapInterval); + glfwSwapInterval(settings.vsync.get()); const GLubyte* vendor = glGetString(GL_VENDOR); const GLubyte* renderer = glGetString(GL_RENDERER); logger.info() << "GL Vendor: " << (char*)vendor;