diff --git a/libstarlight/source/starlight/Application.cpp b/libstarlight/source/starlight/Application.cpp index 080a6ce..9d86785 100644 --- a/libstarlight/source/starlight/Application.cpp +++ b/libstarlight/source/starlight/Application.cpp @@ -3,11 +3,16 @@ #include <3ds.h> #include "starlight/GFXManager.h" +#include "starlight/ConfigManager.h" #include "starlight/ThemeManager.h" #include "starlight/InputManager.h" #include "starlight/gfx/RenderCore.h" +using std::string; + using starlight::GFXManager; +using starlight::ConfigManager; +using starlight::Config; using starlight::ThemeManager; using starlight::InputManager; using starlight::gfx::RenderCore; @@ -29,6 +34,18 @@ bool Application::Quit() { return _currentApp->_appQuit; } +Config& Application::GetConfig(const string& path) { + const string& appId = (_currentApp != nullptr) ? _currentApp->appId : "null"; + string np(path.length() + appId.length() + 4 + 1, ' '); + np.clear(); + np.append("app/"); np.append(appId); np.append("/"); np.append(path); + return ConfigManager::Get(np); +} + +string Application::AppName() { + return (_currentApp != nullptr) ? _currentApp->appId : "null"; +} + ////////////////////// // INSTANCE MEMBERS // ////////////////////// @@ -47,6 +64,7 @@ void Application::Run() { void Application::_init() { srand(time(NULL)); romfsInit(); + ConfigManager::Init(); RenderCore::Open(); touchScreen = std::make_shared(); @@ -59,6 +77,7 @@ void Application::_end() { End(); RenderCore::Close(); + ConfigManager::End(); } void Application::_mainLoop() { diff --git a/libstarlight/source/starlight/Application.h b/libstarlight/source/starlight/Application.h index 500c429..31415c2 100644 --- a/libstarlight/source/starlight/Application.h +++ b/libstarlight/source/starlight/Application.h @@ -11,6 +11,8 @@ #include "starlight/ui/TouchScreenCanvas.h" #include "starlight/ui/TopScreenCanvas.h" +#include "starlight/ConfigManager.h" + namespace starlight { class Application { //////////////////// @@ -21,6 +23,8 @@ namespace starlight { public: static bool Quit(); + static Config& GetConfig(const std::string& path); + static std::string AppName(); ////////////////////// // INSTANCE MEMBERS // @@ -53,4 +57,3 @@ namespace starlight { virtual void End() { } }; } - diff --git a/libstarlight/source/starlight/ConfigManager.cpp b/libstarlight/source/starlight/ConfigManager.cpp new file mode 100644 index 0000000..8e59dc3 --- /dev/null +++ b/libstarlight/source/starlight/ConfigManager.cpp @@ -0,0 +1,93 @@ +#include "ConfigManager.h" + +#include +#include + +#include +#include + +#include "starlight/_incLib/json.hpp" + +#include "starlight/Application.h" + +using std::string; +using std::ifstream; +using std::ofstream; + +using starlight::Application; + +using starlight::Config; +using starlight::ConfigManager; + +// helper stuff +namespace { + void ensureDirectory(const char* path, bool hidden = false) { + struct stat st; + if (stat(path, &st) != 0) { + mkdir(path, 0); + if (hidden) { + // NYI; no idea how to do this, actually :( + } + } + } + void ensureDirectory(const string& path, bool hidden = false) { ensureDirectory(path.c_str(), hidden); } + +} + + //////////// + // Config // +//////////// + +Config::Config(const string& path) : path(path) { + static const constexpr char* cpfx = "sdmc:/.starlight/config/"; + constexpr std::size_t cpfx_s = std::strlen(cpfx); + // reserve string size + fsPath = string(path.length() + cpfx_s + 5, ' '); fsPath.clear(); + // and build + fsPath.append(cpfx); fsPath.append(path); fsPath.append(".json"); + + // init json + this->json = std::make_shared(); + + Reload(); +} +Config::~Config() { } + +void Config::Reload() { + ifstream load(fsPath); + if (load.good()) load >> *json; +} + +void Config::Save() { + ofstream save(fsPath); + if (save.good()) save << *json; +} + + /////////////////// + // ConfigManager // +/////////////////// + +std::unordered_map> ConfigManager::cfg; + +void ConfigManager::Init() { + ensureDirectory("sdmc:/.starlight/"); + ensureDirectory("sdmc:/.starlight/config/"); + ensureDirectory("sdmc:/.starlight/config/app/"); + ensureDirectory("sdmc:/.starlight/config/app/" + Application::AppName()); +} + +void ConfigManager::End() { + for (auto it : cfg) { + auto& c = *it.second.get(); + if (c.autoSave) c.Save(); + } + // actualy, don't clear in case something uses a static get + // in the future, perhaps discard contents +} + +Config& ConfigManager::Get(const string& path) { + auto const& itr = cfg.find(path); + if (itr == cfg.end()) { + return *cfg.insert(std::make_pair(path, std::make_shared(path))).first->second; + } else return *itr->second; +} diff --git a/libstarlight/source/starlight/ConfigManager.h b/libstarlight/source/starlight/ConfigManager.h new file mode 100644 index 0000000..3b82ba1 --- /dev/null +++ b/libstarlight/source/starlight/ConfigManager.h @@ -0,0 +1,41 @@ +#pragma once +#include "starlight/_global.h" + +#include +#include + +#include "starlight/_incLib/json_fwd.hpp" + +//#include "starlight/gfx/DrawContext.h" + +namespace starlight { + class Config { + private: + std::string fsPath; + std::shared_ptr json; + public: + const std::string path; + bool autoSave = false; + + Config(const std::string& path); + ~Config(); + + void Reload(); + void Save(); + + nlohmann::json& Json() { return *json; } + }; + + class ConfigManager { + private: + static std::unordered_map> cfg; + + public: + ConfigManager() = delete; + + static void Init(); + static void End(); + + static Config& Get(const std::string& path); + }; +} diff --git a/maketest.sh b/maketest.sh index 8e91a58..aa826a8 100644 --- a/maketest.sh +++ b/maketest.sh @@ -1,6 +1,6 @@ #!/bin/bash function abort { - echo Make failed + echo Make or send failed exit } cd libstarlight diff --git a/testbed/source/Core.cpp b/testbed/source/Core.cpp index 084ee1f..bd57645 100644 --- a/testbed/source/Core.cpp +++ b/testbed/source/Core.cpp @@ -2,7 +2,10 @@ #include <3ds.h> +#include "starlight/_incLib/json.hpp" + #include "starlight/InputManager.h" +#include "starlight/ConfigManager.h" #include "starlight/ThemeManager.h" #include "starlight/GFXManager.h" #include "starlight/gfx/RenderCore.h" @@ -16,8 +19,9 @@ using starlight::Vector2; using starlight::VRect; using starlight::Color; using starlight::InputManager; -using starlight::GFXManager; +using starlight::ConfigManager; using starlight::ThemeManager; +using starlight::GFXManager; using starlight::gfx::RenderCore; using starlight::Application; @@ -67,6 +71,11 @@ void Core::Init() { clearColor = Color(0.0f, 0.5f, 0.5f); + // test config + auto& cc = Application::GetConfig("test"); + cc.Json()["panini"] = "yes please!"; + cc.Save(); + // } @@ -77,4 +86,3 @@ void Core::End() { void Core::Update() { if (InputManager::Held(KEY_Y) || InputManager::Pressed(KEY_START)) Application::Quit(); } - diff --git a/testbed/source/Core.h b/testbed/source/Core.h index a48dc8e..a19ddf5 100644 --- a/testbed/source/Core.h +++ b/testbed/source/Core.h @@ -6,7 +6,7 @@ using starlight::Application; class Core : public Application { public: - Core() : Application("starlauncher") { } + Core() : Application("testbed") { } ~Core() override = default; void Init() override; @@ -14,4 +14,3 @@ public: void Update() override; }; -