diff --git a/libstarlight/source/starlight/ThemeManager.cpp b/libstarlight/source/starlight/ThemeManager.cpp index ed5ac47..ba4fd22 100644 --- a/libstarlight/source/starlight/ThemeManager.cpp +++ b/libstarlight/source/starlight/ThemeManager.cpp @@ -181,10 +181,16 @@ void ThemeManager::End() { void ThemeManager::GC() { constexpr const int keepCycles = 5; // how many gc sweeps a drawable gets to stay loaded without being used + std::vector rem; // WIP for (auto& d : drawables) { - if (++d.second.lastAccess > keepCycles) d.second.Unload(); + if (++d.second.lastAccess > keepCycles) { + d.second.Unload(); + if (d.second.refCount <= 0) rem.push_back(d.first); // mark for full removal when no references exist + } } + + for (auto& s : rem) drawables.erase(s); // and remove everything queued } ThemeRef ThemeManager::GetAsset(const std::string& name) { @@ -268,28 +274,50 @@ string ThemeManager::ResolveAssetPath(const string& id) { //struct stat buf; //string path(id.length() + 64, ' '); // preallocate buffer space - static const string pfxLocal = "app:/"; - if (id.compare(0, pfxLocal.length(), pfxLocal) == 0) { + string pfx = ""; + + size_t cpos = id.find(":/"); + if (cpos != string::npos) { + pfx = id.substr(0, cpos); + cpos += 2; + } else cpos = 0; + + if (pfx == "app") { + string sid = id.substr(cpos); // strip off the "app:/" // app-local asset // check if present in theme/app/[appname]/, else check in romfs for (auto thm : themeData) { Path bp = thm.basePath.Combine("app").Combine(Application::AppName()); - Path p = bp.Combine(id+".json"); + Path p = bp.Combine(sid); if (p.IsFile()) return p; - p = bp.Combine(id+".png"); + p = bp.Combine(sid+".json"); + if (p.IsFile()) return p; + p = bp.Combine(sid+".png"); if (p.IsFile()) return p; } // TBD - directly in romfs, or in an assets folder? Path bp = Path("romfs:"); - Path p = bp.Combine(id+".json"); + Path p = bp.Combine(sid); if (p.IsFile()) return p; - p = bp.Combine(id+".png"); + p = bp.Combine(sid+".json"); + if (p.IsFile()) return p; + p = bp.Combine(sid+".png"); + if (p.IsFile()) return p; + } + else if (pfx == "sdmc" || pfx == "romfs") { + Path p = Path(id); + if (p.IsFile()) return p; + p = Path(id + ".json"); + if (p.IsFile()) return p; + p = Path(id + ".png"); if (p.IsFile()) return p; } else { // theme asset; check in each theme from selected to most-fallback for (auto thm : themeData) { - Path p = thm.basePath.Combine(id+".json"); + Path p = thm.basePath.Combine(id); + if (p.IsFile()) return p; + p = thm.basePath.Combine(id+".json"); if (p.IsFile()) return p; p = thm.basePath.Combine(id+".png"); if (p.IsFile()) return p; diff --git a/libstarlight/source/starlight/ThemeManager.h b/libstarlight/source/starlight/ThemeManager.h index 9c18142..2b6da0b 100644 --- a/libstarlight/source/starlight/ThemeManager.h +++ b/libstarlight/source/starlight/ThemeManager.h @@ -87,6 +87,17 @@ namespace starlight { TextConfig(const std::string& fontName, Color text, Color border = Color::transparent); ~TextConfig() = default; + TextConfig(const TextConfig& o) : textColor(o.textColor), borderColor(o.borderColor), justification(o.justification) { font = o.font; } + TextConfig(const TextConfig&& o) : textColor(o.textColor), borderColor(o.borderColor), justification(o.justification) { font = o.font; } + TextConfig& operator =(const TextConfig& o) { + font = o.font; textColor = o.textColor; borderColor = o.borderColor; justification = o.justification; + return *this; + } + TextConfig& operator =(const TextConfig&& o) { + font = o.font; textColor = o.textColor; borderColor = o.borderColor; justification = o.justification; + return *this; + } + void Print(Vector2 position, const std::string& text, Vector2 justification = Vector2::invalid); void Print(VRect rect, const std::string& text, Vector2 justification = Vector2::invalid); diff --git a/libstarlight/source/starlight/gfx/ThemeRef.h b/libstarlight/source/starlight/gfx/ThemeRef.h index d06d5e7..fea4e5c 100644 --- a/libstarlight/source/starlight/gfx/ThemeRef.h +++ b/libstarlight/source/starlight/gfx/ThemeRef.h @@ -18,6 +18,7 @@ namespace starlight { std::shared_ptr ptr = nullptr; ThemeRefContainer* redir = nullptr; unsigned int lastAccess = 0; // how many gc sweeps since last use + volatile int refCount = 0; void Unload(bool full = false) { ptr.reset(); if (full) redir = nullptr; @@ -54,12 +55,28 @@ namespace starlight { class ThemeRef { friend class starlight::ThemeManager; protected: - const ThemeRefContainer* cptr; + ThemeRefContainer* cptr; public: ThemeRef() : cptr(nullptr) { } - ThemeRef(ThemeRefContainer* c) : cptr(c) { } - ~ThemeRef() { } - inline const ThemeRefContainer& operator ->() const { return *cptr; } + ThemeRef(ThemeRefContainer* c) : cptr(c) { if (cptr) cptr->refCount++; } + ThemeRef(ThemeRef& o) : cptr(o.cptr) { if (cptr) cptr->refCount++; } + ThemeRef(ThemeRef&& o) : cptr(o.cptr) { if (cptr) cptr->refCount++; } + ~ThemeRef() { if (cptr) cptr->refCount--; } + + ThemeRef& operator =(const ThemeRef& o) { + if (cptr) cptr->refCount--; + cptr = o.cptr; + if (cptr) cptr->refCount++; + return *this; + } + ThemeRef& operator =(const ThemeRef&& o) { + if (cptr) cptr->refCount--; + cptr = o.cptr; + if (cptr) cptr->refCount++; + return *this; + } + + inline const ThemeRefContainer& operator ->() const { return const_cast&>(*cptr); } inline explicit operator bool() const { return cptr != nullptr; } inline std::shared_ptr GetShared() const { return (*cptr).getptr(); } inline const std::string& GetName() const { return (*cptr).name; }