From 7a18cce60c3d34814d1a86b249e9cc8ee13bf054 Mon Sep 17 00:00:00 2001 From: Patrick Wuttke Date: Sun, 2 Mar 2025 18:41:27 +0100 Subject: [PATCH] Write ImGui config to an appropriate folder instead of the current one. --- private/raid/application.cpp | 88 +++++++++++++++++++++++++++++++++++- private/raid_test/main.cpp | 4 ++ public/raid/raid.hpp | 8 ++++ 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/private/raid/application.cpp b/private/raid/application.cpp index 11f8a05..9c14548 100644 --- a/private/raid/application.cpp +++ b/private/raid/application.cpp @@ -6,7 +6,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -27,6 +30,37 @@ int Application::run(int argc, char** argv) MIJIN_SCOPE_EXIT { cleanup(); }; + + using namespace mijin::vfs_pipe; + mFS.addAdapter(os() + | relative_to(mijin::getKnownFolder(mijin::KnownFolder::USER_CONFIG_ROOT) / getFolderName()) + | map_to("/config") + ); + mFS.addAdapter(os() + | relative_to(mijin::getKnownFolder(mijin::KnownFolder::USER_DATA_ROOT) / getFolderName()) + | map_to("/data") + ); + + auto createUserDir = [&](const fs::path& virtualPath) + { + mijin::Optional pathOpt = mFS.getNativePath(virtualPath); + if (!pathOpt.empty()) + { + const fs::path path = std::move(*pathOpt); + if (!fs::exists(path)) + { + const bool result = fs::create_directories(path); + MIJIN_ASSERT(result, "Error creating user folder."); + } + } + else + { + MIJIN_ERROR("User folder path shouldn't be empty."); + } + }; + createUserDir("/config"); + createUserDir("/data"); + if (!initSDL()) { return ERR_INIT_FAILED; @@ -50,12 +84,14 @@ int Application::run(int argc, char** argv) continue; } + ImGuiIO& imguiIO = ImGui::GetIO(); + ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplSDL3_NewFrame(); ImGui::NewFrame(); ImGui::SetNextWindowPos({0, 0}); - ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize); + ImGui::SetNextWindowSize(imguiIO.DisplaySize); ImGui::Begin("##main", nullptr, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration); render(); @@ -68,6 +104,12 @@ int Application::run(int argc, char** argv) ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); SDL_GL_SwapWindow(mWindow); + + if (imguiIO.WantSaveIniSettings) + { + saveImGuiConfig(); + imguiIO.WantSaveIniSettings = false; + } } return 0; @@ -160,9 +202,12 @@ bool Application::initImGui() return false; } + loadImGuiConfig(); + ImGuiIO& imguiIO = ImGui::GetIO(); imguiIO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; imguiIO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; + imguiIO.IniFilename = nullptr; // disable automatic saving of settings // default style ImGui::StyleColorsDark(); @@ -189,6 +234,8 @@ void Application::cleanup() { if (ImGui::GetCurrentContext() != nullptr) { + saveImGuiConfig(); + const ImGuiIO& imguiIO = ImGui::GetIO(); if (imguiIO.BackendRendererUserData != nullptr) { @@ -220,6 +267,40 @@ void Application::handleSDLEvents() } } +void Application::loadImGuiConfig() +{ + std::unique_ptr iniFile; + if (mFS.open("/config/imgui.ini", mijin::FileOpenMode::READ, iniFile) != mijin::StreamError::SUCCESS) + { + return; + } + std::string config; + if (iniFile->readAsString(config) != mijin::StreamError::SUCCESS) + { + msgWarning("IO error reading ImGui config."); + return; + } + ImGui::LoadIniSettingsFromMemory(config.c_str()); +} + +void Application::saveImGuiConfig() +{ + std::unique_ptr iniFile; + if (const mijin::StreamError error = mFS.open("/config/imgui.ini", mijin::FileOpenMode::WRITE, iniFile); + error != mijin::StreamError::SUCCESS) + { + msgError("Error opening ImGui config file for writing: {}.", mijin::errorName(error)); + return; + } + + std::size_t length = 0; + const char* config = ImGui::SaveIniSettingsToMemory(&length); + if (const mijin::StreamError error = iniFile->writeText(config); error != mijin::StreamError::SUCCESS) + { + msgError("Error writing ImGui config: {}.", mijin::errorName(error)); + } +} + void QuickApp::init(QuickAppOptions options) { MIJIN_ASSERT_FATAL(options.callbacks.render, "Missing render callback."); @@ -231,6 +312,11 @@ void QuickApp::render() mOptions.callbacks.render(); } +std::string QuickApp::getFolderName() +{ + return mOptions.folderName; +} + int runQuick(int argc, char* argv[], QuickAppOptions options) { QuickApp app; diff --git a/private/raid_test/main.cpp b/private/raid_test/main.cpp index a24bac5..2fee16b 100644 --- a/private/raid_test/main.cpp +++ b/private/raid_test/main.cpp @@ -8,6 +8,10 @@ namespace void render() { ImGui::Text("hi"); + + ImGui::Begin("Test"); + ImGui::Text("Test Content"); + ImGui::End(); } } diff --git a/public/raid/raid.hpp b/public/raid/raid.hpp index a937fda..e39bdf3 100644 --- a/public/raid/raid.hpp +++ b/public/raid/raid.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include namespace raid @@ -33,6 +34,8 @@ private: SDL_Window* mWindow = nullptr; SDL_GLContext mGLContext = nullptr; + mijin::StackedFileSystemAdapter mFS; + using glClear_fn_t = void (*)(std::uint32_t); using glClearColor_fn_t = void (*)(float, float, float, float); @@ -46,6 +49,7 @@ public: protected: virtual void render() = 0; + virtual std::string getFolderName() = 0; virtual void handleMessage(const Message& message); virtual void handleSDLEvent(const SDL_Event& event); @@ -106,6 +110,8 @@ private: bool initImGui(); void cleanup(); void handleSDLEvents(); + void loadImGuiConfig(); + void saveImGuiConfig(); }; using render_cb_t = std::function; @@ -115,6 +121,7 @@ struct QuickAppOptions { render_cb_t render; } callbacks; + std::string folderName = "raid"; }; class QuickApp : public Application @@ -124,6 +131,7 @@ private: public: void init(QuickAppOptions options); void render() override; + std::string getFolderName() override; }; [[nodiscard]]