From 02554e469aeb45fbcbaeecead4c5b4db558ee2c2 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 22 Jan 2025 08:18:17 +0300 Subject: [PATCH 1/7] refactor --- src/audio/audio.cpp | 29 ++++++++++++++++++---- src/audio/audio.hpp | 3 ++- src/engine/Engine.cpp | 49 +++++++++++++++++++------------------ src/engine/Engine.hpp | 10 ++++++-- src/graphics/ui/gui_xml.cpp | 5 ++-- src/main.cpp | 6 ++++- 6 files changed, 67 insertions(+), 35 deletions(-) diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index 522e37053..8ac8b713d 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -9,19 +9,21 @@ #include "AL/ALAudio.hpp" #include "NoAudio.hpp" #include "debug/Logger.hpp" +#include "util/ObjectsKeeper.hpp" static debug::Logger logger("audio"); -namespace audio { +using namespace audio; + +namespace { static speakerid_t nextId = 1; static Backend* backend; static std::unordered_map> speakers; static std::unordered_map> streams; static std::vector> channels; + static util::ObjectsKeeper objects_keeper {}; } -using namespace audio; - Channel::Channel(std::string name) : name(std::move(name)) { } @@ -148,7 +150,8 @@ class PCMVoidSource : public PCMStream { } }; -void audio::initialize(bool enabled) { +void audio::initialize(bool enabled, AudioSettings& settings) { + enabled = enabled && settings.enabled.get(); if (enabled) { logger.info() << "initializing ALAudio backend"; backend = ALAudio::create().release(); @@ -160,7 +163,22 @@ void audio::initialize(bool enabled) { logger.info() << "initializing NoAudio backend"; backend = NoAudio::create().release(); } - create_channel("master"); + struct { + std::string name; + NumberSetting* setting; + } builtin_channels[] { + {"master", &settings.volumeMaster}, + {"regular", &settings.volumeRegular}, + {"music", &settings.volumeMusic}, + {"ambient", &settings.volumeAmbient}, + {"ui", &settings.volumeUI} + }; + for (auto& channel : builtin_channels) { + create_channel(channel.name); + objects_keeper.keepAlive(channel.setting->observe([=](auto value) { + audio::get_channel(channel.name)->setVolume(value * value); + }, true)); + } } std::unique_ptr audio::load_PCM(const fs::path& file, bool headerOnly) { @@ -442,4 +460,5 @@ void audio::close() { speakers.clear(); delete backend; backend = nullptr; + objects_keeper.clearKeepedObjects(); } diff --git a/src/audio/audio.hpp b/src/audio/audio.hpp index a37ebeea5..37ae8e002 100644 --- a/src/audio/audio.hpp +++ b/src/audio/audio.hpp @@ -6,6 +6,7 @@ #include #include "typedefs.hpp" +#include "settings.hpp" namespace fs = std::filesystem; @@ -357,7 +358,7 @@ namespace audio { /// @brief Initialize audio system or use no audio mode /// @param enabled try to initialize actual audio - void initialize(bool enabled); + void initialize(bool enabled, AudioSettings& settings); /// @brief Load audio file info and PCM data /// @param file audio file diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index c9de5a64f..737044685 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -52,15 +52,6 @@ static debug::Logger logger("engine"); namespace fs = std::filesystem; -static void create_channel(Engine* engine, std::string name, NumberSetting& setting) { - if (name != "master") { - audio::create_channel(name); - } - engine->keepAlive(setting.observe([=](auto value) { - audio::get_channel(name)->setVolume(value*value); - }, true)); -} - static std::unique_ptr load_icon(const fs::path& resdir) { try { auto file = resdir / fs::u8path("textures/misc/icon.png"); @@ -73,12 +64,23 @@ static std::unique_ptr load_icon(const fs::path& resdir) { return nullptr; } -Engine::Engine(CoreParameters coreParameters) - : params(std::move(coreParameters)), - settings(), - settingsHandler({settings}), - interpreter(std::make_unique()), - network(network::Network::create(settings.network)) { +Engine::Engine() = default; + +static std::unique_ptr engine; + +Engine& Engine::getInstance() { + if (!engine) { + engine = std::make_unique(); + } + return *engine; +} + +void Engine::initialize(CoreParameters coreParameters) { + params = std::move(coreParameters); + settingsHandler = std::make_unique(settings); + interpreter = std::make_unique(); + network = network::Network::create(settings.network); + logger.info() << "engine version: " << ENGINE_VERSION_STRING; if (params.headless) { logger.info() << "headless mode is enabled"; @@ -110,12 +112,7 @@ Engine::Engine(CoreParameters coreParameters) menus::create_version_label(*this); } } - audio::initialize(settings.audio.enabled.get() && !params.headless); - create_channel(this, "master", settings.audio.volumeMaster); - create_channel(this, "regular", settings.audio.volumeRegular); - create_channel(this, "music", settings.audio.volumeMusic); - create_channel(this, "ambient", settings.audio.volumeAmbient); - create_channel(this, "ui", settings.audio.volumeUI); + audio::initialize(!params.headless, settings.audio); bool langNotSet = settings.ui.language.get() == "auto"; if (langNotSet) { @@ -140,7 +137,7 @@ void Engine::loadSettings() { logger.info() << "loading settings"; std::string text = files::read_string(settings_file); try { - toml::parse(settingsHandler, settings_file.string(), text); + toml::parse(*settingsHandler, settings_file.string(), text); } catch (const parsing_error& err) { logger.error() << err.errorLog(); throw; @@ -222,7 +219,7 @@ void Engine::renderFrame() { void Engine::saveSettings() { logger.info() << "saving settings"; - files::write_string(paths.getSettingsFile(), toml::stringify(settingsHandler)); + files::write_string(paths.getSettingsFile(), toml::stringify(*settingsHandler)); if (!params.headless) { logger.info() << "saving bindings"; files::write_string(paths.getControlsFile(), Events::writeBindings()); @@ -255,6 +252,10 @@ Engine::~Engine() { logger.info() << "engine finished"; } +void Engine::terminate() { + engine.reset(); +} + EngineController* Engine::getController() { return controller.get(); } @@ -511,7 +512,7 @@ std::shared_ptr Engine::getScreen() { } SettingsHandler& Engine::getSettingsHandler() { - return settingsHandler; + return *settingsHandler; } network::Network& Engine::getNetwork() { diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp index 406d420a0..d4cbf40a3 100644 --- a/src/engine/Engine.hpp +++ b/src/engine/Engine.hpp @@ -58,9 +58,9 @@ using OnWorldOpen = std::function, int64_t)>; class Engine : public util::ObjectsKeeper { CoreParameters params; EngineSettings settings; - SettingsHandler settingsHandler; EnginePaths paths; + std::unique_ptr settingsHandler; std::unique_ptr assets; std::shared_ptr screen; std::vector contentPacks; @@ -82,9 +82,15 @@ class Engine : public util::ObjectsKeeper { void updateHotkeys(); void loadAssets(); public: - Engine(CoreParameters coreParameters); + Engine(); ~Engine(); + static Engine& getInstance(); + + void initialize(CoreParameters coreParameters); + + static void terminate(); + /// @brief Start the engine void run(); diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 6bae272da..d52431535 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -637,8 +637,9 @@ static std::shared_ptr readInventory(UiXmlReader& reader, const xml::xml static std::shared_ptr readPageBox(UiXmlReader& reader, const xml::xmlelement& element) { auto menu = std::make_shared(); - // FIXME - menu->setPageLoader(scripting::engine->getGUI()->getMenu()->getPageLoader()); + menu->setPageLoader( + Engine::getInstance().getGUI()->getMenu()->getPageLoader() + ); _readContainer(reader, element, *menu); return menu; diff --git a/src/main.cpp b/src/main.cpp index b36232587..49825243c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,11 +21,15 @@ int main(int argc, char** argv) { debug::Logger::init(coreParameters.userFolder.string()+"/latest.log"); platform::configure_encoding(); + + auto& engine = Engine::getInstance(); try { - Engine(std::move(coreParameters)).run(); + engine.initialize(std::move(coreParameters)); + engine.run(); } catch (const initialize_error& err) { logger.error() << "could not to initialize engine\n" << err.what(); } + Engine::terminate(); #if defined(NDEBUG) and defined(_WIN32) catch (const std::exception& err) { logger.error() << "uncaught exception: " << err.what(); From b2cda8070bb54ccf453fed7d641d171fd48a423c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 22 Jan 2025 08:20:21 +0300 Subject: [PATCH 2/7] add SIGTERM handler --- src/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 49825243c..524a8c03b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,11 +3,16 @@ #include "util/command_line.hpp" #include "debug/Logger.hpp" +#include #include #include static debug::Logger logger("main"); +static void sigterm_handler(int signum) { + Engine::getInstance().quit(); +} + int main(int argc, char** argv) { CoreParameters coreParameters; try { @@ -18,7 +23,8 @@ int main(int argc, char** argv) { std::cerr << err.what() << std::endl; return EXIT_FAILURE; } - + std::signal(SIGTERM, sigterm_handler); + debug::Logger::init(coreParameters.userFolder.string()+"/latest.log"); platform::configure_encoding(); From 6d1cacb5128aa94e272dc527e96def44b0a46922 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 22 Jan 2025 08:38:19 +0300 Subject: [PATCH 3/7] fix --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 524a8c03b..40e9665a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,7 +35,6 @@ int main(int argc, char** argv) { } catch (const initialize_error& err) { logger.error() << "could not to initialize engine\n" << err.what(); } - Engine::terminate(); #if defined(NDEBUG) and defined(_WIN32) catch (const std::exception& err) { logger.error() << "uncaught exception: " << err.what(); @@ -43,5 +42,6 @@ int main(int argc, char** argv) { throw; } #endif + Engine::terminate(); return EXIT_SUCCESS; } From a0210c82cedbdd06c09daccb66093a82213f1d12 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 22 Jan 2025 08:38:37 +0300 Subject: [PATCH 4/7] reformat gui_xml.cpp --- src/graphics/ui/gui_xml.cpp | 133 +++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 55 deletions(-) diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index d52431535..ee0b74897 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -82,8 +82,8 @@ static onaction create_action( return [callback](GUI*) {callback();}; } -/* Read basic UINode properties */ -static void _readUINode( +/// @brief Read basic UINode properties +static void read_uinode( const UiXmlReader& reader, const xml::xmlelement& element, UINode& node ) { if (element.has("id")) { @@ -177,8 +177,8 @@ static void _readUINode( } } -static void _readContainer(UiXmlReader& reader, const xml::xmlelement& element, Container& container) { - _readUINode(reader, element, container); +static void read_container_impl(UiXmlReader& reader, const xml::xmlelement& element, Container& container) { + read_uinode(reader, element, container); if (element.has("scrollable")) { container.setScrollable(element.attr("scrollable").asBool()); @@ -197,17 +197,22 @@ static void _readContainer(UiXmlReader& reader, const xml::xmlelement& element, } void UiXmlReader::readUINode(UiXmlReader& reader, const xml::xmlelement& element, Container& container) { - _readContainer(reader, element, container); + read_container_impl(reader, element, container); } void UiXmlReader::readUINode( const UiXmlReader& reader, const xml::xmlelement& element, UINode& node ) { - _readUINode(reader, element, node); + read_uinode(reader, element, node); } -static void _readPanel(UiXmlReader& reader, const xml::xmlelement& element, Panel& panel, bool subnodes=true) { - _readUINode(reader, element, panel); +static void read_panel_impl( + UiXmlReader& reader, + const xml::xmlelement& element, + Panel& panel, + bool subnodes = true +) { + read_uinode(reader, element, panel); if (element.has("padding")) { glm::vec4 padding = element.attr("padding").asVec4(); @@ -245,7 +250,9 @@ static void _readPanel(UiXmlReader& reader, const xml::xmlelement& element, Pane } } -static std::wstring readAndProcessInnerText(const xml::xmlelement& element, const std::string& context) { +static std::wstring parse_inner_text( + const xml::xmlelement& element, const std::string& context +) { std::wstring text = L""; if (element.size() == 1) { std::string source = element.sub(0).attr("#").getText(); @@ -265,9 +272,9 @@ static std::wstring readAndProcessInnerText(const xml::xmlelement& element, cons static std::shared_ptr readLabel( const UiXmlReader& reader, const xml::xmlelement& element ) { - std::wstring text = readAndProcessInnerText(element, reader.getContext()); + std::wstring text = parse_inner_text(element, reader.getContext()); auto label = std::make_shared