diff --git a/.vs/libstarlight/v14/.suo b/.vs/libstarlight/v14/.suo
new file mode 100644
index 0000000..4184b8d
Binary files /dev/null and b/.vs/libstarlight/v14/.suo differ
diff --git a/libstarlight.VC.db b/libstarlight.VC.db
new file mode 100644
index 0000000..12372eb
Binary files /dev/null and b/libstarlight.VC.db differ
diff --git a/libstarlight.sln b/libstarlight.sln
new file mode 100644
index 0000000..032f2b0
--- /dev/null
+++ b/libstarlight.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libstarlight", "libstarlight\libstarlight.vcxproj", "{21A0624A-FE85-4D9C-ADDE-7E272B48E906}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {21A0624A-FE85-4D9C-ADDE-7E272B48E906}.Debug|x64.ActiveCfg = Debug|x64
+ {21A0624A-FE85-4D9C-ADDE-7E272B48E906}.Debug|x64.Build.0 = Debug|x64
+ {21A0624A-FE85-4D9C-ADDE-7E272B48E906}.Debug|x86.ActiveCfg = Debug|Win32
+ {21A0624A-FE85-4D9C-ADDE-7E272B48E906}.Debug|x86.Build.0 = Debug|Win32
+ {21A0624A-FE85-4D9C-ADDE-7E272B48E906}.Release|x64.ActiveCfg = Release|x64
+ {21A0624A-FE85-4D9C-ADDE-7E272B48E906}.Release|x64.Build.0 = Release|x64
+ {21A0624A-FE85-4D9C-ADDE-7E272B48E906}.Release|x86.ActiveCfg = Release|Win32
+ {21A0624A-FE85-4D9C-ADDE-7E272B48E906}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/libstarlight/Debug/libstarlight.log b/libstarlight/Debug/libstarlight.log
new file mode 100644
index 0000000..cd3e301
--- /dev/null
+++ b/libstarlight/Debug/libstarlight.log
@@ -0,0 +1,2 @@
+ make: *** No targets specified and no makefile found. Stop.
+C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.MakeFile.Targets(41,5): error MSB3073: The command "make" exited with code 2.
diff --git a/libstarlight/libstarlight.vcxproj b/libstarlight/libstarlight.vcxproj
new file mode 100644
index 0000000..30d573e
--- /dev/null
+++ b/libstarlight/libstarlight.vcxproj
@@ -0,0 +1,174 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {21A0624A-FE85-4D9C-ADDE-7E272B48E906}
+ MakeFileProj
+
+
+
+ Makefile
+ true
+ v140
+
+
+ Makefile
+ false
+ v140
+
+
+ Application
+ true
+ v140
+
+
+ Application
+ false
+ v140
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ make
+
+
+ make clean
+ $(PATH);
+ .\;$(ProjectDir)source\;$(DEVKITPROWIN)\libctru\include\;$(DEVKITARMWIN)\arm-none-eabi\include\;$(DEVKITARMWIN)\arm-none-eabi\include\c++\6.2.0\
+
+
+
+
+ .\;$(ProjectDir)source\;$(DEVKITPROWIN)\libctru\include\;$(DEVKITARMWIN)\arm-none-eabi\include\;$(DEVKITARMWIN)\arm-none-eabi\include\c++\6.2.0\;
+
+ $(ProjectDir)/vs_shim.cpp
+
+
+ make
+
+
+ make clean
+ $(PATH);
+ .\;$(ProjectDir)source\;$(DEVKITPROWIN)\libctru\include\;$(DEVKITARMWIN)\arm-none-eabi\include\;$(DEVKITARMWIN)\arm-none-eabi\include\c++\6.2.0\
+
+
+
+
+ .\;$(ProjectDir)source\;$(DEVKITPROWIN)\libctru\include\;$(DEVKITARMWIN)\arm-none-eabi\include\;$(DEVKITARMWIN)\arm-none-eabi\include\c++\6.2.0\;
+
+ $(ProjectDir)/vs_shim.cpp
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libstarlight/libstarlight.vcxproj.filters b/libstarlight/libstarlight.vcxproj.filters
new file mode 100644
index 0000000..c146dc9
--- /dev/null
+++ b/libstarlight/libstarlight.vcxproj.filters
@@ -0,0 +1,234 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/libstarlight/libstarlight.vcxproj.user b/libstarlight/libstarlight.vcxproj.user
new file mode 100644
index 0000000..a11cd7f
--- /dev/null
+++ b/libstarlight/libstarlight.vcxproj.user
@@ -0,0 +1,6 @@
+
+
+
+ true
+
+
\ No newline at end of file
diff --git a/libstarlight/source/starlight/Application.cpp b/libstarlight/source/starlight/Application.cpp
new file mode 100644
index 0000000..28ff274
--- /dev/null
+++ b/libstarlight/source/starlight/Application.cpp
@@ -0,0 +1,86 @@
+#include "Application.h"
+
+#include <3ds.h>
+
+#include "starlight/GFXManager.h"
+#include "starlight/ThemeManager.h"
+#include "starlight/InputManager.h"
+#include "starlight/gfx/RenderCore.h"
+
+using starlight::GFXManager;
+using starlight::ThemeManager;
+using starlight::InputManager;
+using starlight::gfx::RenderCore;
+
+using starlight::ui::TouchScreenCanvas;
+using starlight::ui::TopScreenCanvas;
+
+using starlight::Application;
+
+ ////////////////////
+ // STATIC MEMBERS //
+////////////////////
+
+Application* Application::_currentApp = nullptr;
+
+bool Application::Quit() {
+ if (_currentApp == nullptr) return false;
+ _currentApp->_appQuit = true;
+ return _currentApp->_appQuit;
+}
+
+ //////////////////////
+ // INSTANCE MEMBERS //
+//////////////////////
+
+void Application::Run() {
+ if (_currentApp != nullptr) return; // don't run two at once!
+ _currentApp = this;
+
+ _init();
+ while (!_appQuit && aptMainLoop()) _mainLoop();
+ _end();
+
+ _currentApp = nullptr;
+}
+
+void Application::_init() {
+ srand(time(NULL));
+ romfsInit();
+ RenderCore::Open();
+
+ touchScreen = std::make_shared();
+ topScreen = std::make_shared();
+
+ Init();
+}
+
+void Application::_end() {
+ End();
+
+ RenderCore::Close();
+}
+
+void Application::_mainLoop() {
+ // update step
+ InputManager::Update();
+ Update();
+ touchScreen->Update();
+ topScreen->Update();
+ PostUpdate();
+
+ // draw step
+ RenderCore::BeginFrame();
+ RenderCore::targetBottom->Clear(clearColor);
+ RenderCore::targetTopLeft->Clear(clearColor);
+ RenderCore::targetTopRight->Clear(clearColor);
+
+ Draw();
+ touchScreen->PreDraw();
+ topScreen->PreDraw();
+ touchScreen->Draw();
+ topScreen->Draw();
+ PostDraw();
+ RenderCore::EndFrame();
+}
+
diff --git a/libstarlight/source/starlight/Application.h b/libstarlight/source/starlight/Application.h
new file mode 100644
index 0000000..500c429
--- /dev/null
+++ b/libstarlight/source/starlight/Application.h
@@ -0,0 +1,56 @@
+#pragma once
+#include "starlight/_global.h"
+
+#include
+#include
+
+#include "starlight/datatypes/Vector2.h"
+#include "starlight/datatypes/VRect.h"
+#include "starlight/datatypes/Color.h"
+
+#include "starlight/ui/TouchScreenCanvas.h"
+#include "starlight/ui/TopScreenCanvas.h"
+
+namespace starlight {
+ class Application {
+ ////////////////////
+ // STATIC MEMBERS //
+ ////////////////////
+ private:
+ static Application* _currentApp;
+
+ public:
+ static bool Quit();
+
+ //////////////////////
+ // INSTANCE MEMBERS //
+ //////////////////////
+ private:
+ bool _appQuit = false;
+ void _init();
+ void _mainLoop();
+ void _end();
+
+ public:
+ const std::string appId;
+
+ Color clearColor = Color::black;
+
+ std::shared_ptr touchScreen = nullptr;
+ std::shared_ptr topScreen = nullptr;
+
+ Application() = delete;
+ Application(std::string id) : appId(id) { }
+ virtual ~Application() = default;
+
+ void Run();
+
+ virtual void Init() { }
+ virtual void Update() { }
+ virtual void PostUpdate() { }
+ virtual void Draw() { }
+ virtual void PostDraw() { }
+ virtual void End() { }
+ };
+}
+
diff --git a/libstarlight/source/starlight/GFXManager.cpp b/libstarlight/source/starlight/GFXManager.cpp
new file mode 100644
index 0000000..1b84ca3
--- /dev/null
+++ b/libstarlight/source/starlight/GFXManager.cpp
@@ -0,0 +1,51 @@
+#include "GFXManager.h"
+
+using starlight::Vector2;
+using starlight::GFXManager;
+using starlight::gfx::DrawContext;
+
+std::forward_list GFXManager::ctxStack;
+std::forward_list GFXManager::offsetStack;
+
+float GFXManager::parallax = 0;
+
+void GFXManager::PushContext(DrawContext* context) {
+ if (!ctxStack.empty()) ctxStack.front()->Close();
+ ctxStack.push_front(context);
+ context->Open();
+ PushOffset(Vector2::zero);
+}
+
+DrawContext* GFXManager::PopContext() {
+ //if (ctxStack.empty()) return nullptr;
+ DrawContext* context = ctxStack.front();
+ PopOffset();
+ context->Close();
+ ctxStack.pop_front();
+ if (!ctxStack.empty()) ctxStack.front()->Open();
+ return context;
+}
+
+DrawContext* GFXManager::GetContext() { return !ctxStack.empty() ? ctxStack.front() : nullptr; }
+
+void GFXManager::PushOffset(Vector2 offset) { offsetStack.push_front(offset); }
+void GFXManager::PushOffsetAdd(Vector2 add) { offsetStack.push_front(GetOffset() + add); }
+Vector2 GFXManager::PopOffset() {
+ Vector2 r = GetOffset();
+ offsetStack.pop_front();
+ return r;
+}
+Vector2 GFXManager::GetOffset() { return !offsetStack.empty() ? offsetStack.front() : Vector2::zero; }
+
+void GFXManager::Reset() {
+ ctxStack.clear();
+ offsetStack.clear();
+}
+
+bool GFXManager::PrepareForDrawing() {
+ if (ctxStack.empty()) return false;
+ auto context = ctxStack.front();
+ if (context->drawReady) return true;
+ return context->Prepare();
+}
+
diff --git a/libstarlight/source/starlight/GFXManager.h b/libstarlight/source/starlight/GFXManager.h
new file mode 100644
index 0000000..5b1f16b
--- /dev/null
+++ b/libstarlight/source/starlight/GFXManager.h
@@ -0,0 +1,31 @@
+#pragma once
+#include "starlight/_global.h"
+
+#include
+
+#include "starlight/gfx/DrawContext.h"
+
+namespace starlight {
+ class GFXManager {
+ private:
+ static std::forward_list ctxStack;
+ static std::forward_list offsetStack;
+ public:
+ static float parallax;
+
+ GFXManager() = delete;
+
+ static void PushContext(gfx::DrawContext* context);
+ static gfx::DrawContext* PopContext();
+ static gfx::DrawContext* GetContext();
+
+ static void PushOffset(Vector2 offset);
+ static void PushOffsetAdd(Vector2 add);
+ static Vector2 PopOffset();
+ static Vector2 GetOffset();
+
+ static void Reset();
+
+ static bool PrepareForDrawing();
+ };
+}
diff --git a/libstarlight/source/starlight/InputManager.cpp b/libstarlight/source/starlight/InputManager.cpp
new file mode 100644
index 0000000..1a60aa3
--- /dev/null
+++ b/libstarlight/source/starlight/InputManager.cpp
@@ -0,0 +1,122 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include <3ds.h>
+
+#include "datatypes/Vector2.h"
+
+#include "InputManager.h"
+
+using starlight::Vector2;
+using starlight::ui::UIElement;
+using starlight::DragHandle;
+using starlight::InputManager;
+
+namespace {
+ unsigned int heldLast = 0;
+ unsigned int heldNow = 0;
+
+ Vector2 stickLeftLast;
+ Vector2 stickLeftNow;
+ Vector2 stickRightLast;
+ Vector2 stickRightNow;
+
+ Vector2 touchLast;
+ Vector2 touchNow;
+ Vector2 touchStart;
+ int touchTime;
+
+ Vector2 stickVec(circlePosition cpos) {
+ Vector2 v (cpos.dx, -cpos.dy);
+
+ float mag = std::min(v.Length() / 150.0f, 1.0f);
+ mag = std::max(mag * 1.1f - 0.1f, 0.0f);
+
+ v = v.Normalized() * mag;
+
+ return v;
+ }
+}
+
+void InputManager::Update() {
+ hidScanInput();
+ circlePosition cp;
+ touchPosition tp;
+
+ heldLast = heldNow;
+ heldNow = hidKeysHeld();
+
+ stickLeftLast = stickLeftNow;
+ hidCircleRead(&cp);
+ stickLeftNow = stickVec(cp);
+ stickRightLast = stickRightNow;
+ hidCstickRead(&cp);
+ stickRightNow = stickVec(cp);
+
+ touchLast = touchNow;
+ hidTouchRead(&tp);
+ if (Held(KEY_TOUCH)) touchNow = Vector2(tp.px, tp.py);
+
+ if (Pressed(KEY_TOUCH)) touchStart = touchLast = touchNow;
+
+ if (!Held(KEY_TOUCH) && !Released(KEY_TOUCH)) touchTime = 0;
+ else touchTime++;
+
+}
+
+float InputManager::DepthSlider() { return (*(float*)0x1FF81080); }
+
+Vector2 InputManager::CirclePad() { return stickLeftNow; }
+Vector2 InputManager::CStick() { return stickRightNow; }
+
+bool InputManager::Held(unsigned int mask) { return heldNow & mask; }
+bool InputManager::Pressed(unsigned int mask) { return (heldNow & ~heldLast) & mask; }
+bool InputManager::Released(unsigned int mask) { return (heldLast & ~heldNow) & mask; }
+
+Vector2 InputManager::TouchPos() { return touchNow; }
+Vector2 InputManager::TouchDelta() { return touchNow - touchLast; }
+Vector2 InputManager::TouchStart() { return touchStart; }
+Vector2 InputManager::TouchDragDist() { return touchNow - touchStart; }
+int InputManager::TouchTime() { return touchTime; }
+
+// drag stuff!
+DragHandle InputManager::drag;
+DragHandle& DragHandle::Grab(UIElement* e) {
+ if (rptr == e) return *this;
+ Release();
+ rptr = e;
+ wptr = e->shared_from_this();
+ e->OnDragStart();
+ return *this;
+}
+
+DragHandle& DragHandle::PassUp(bool releaseOnFail) {
+ if (!valid()) return *this; // invalid
+ UIElement* e = rptr;
+ while (true) {
+ if (auto p = e->parent.lock()) {
+ e = p.get();
+ if (e->OnDragPassed()) {
+ return Grab(e);
+ }
+ continue;
+ } else {
+ if (releaseOnFail) Release();
+ return *this;
+ }
+ break;
+ }
+}
+
+#define err(nth, wat) *((unsigned int*)0x00100000+(nth))=wat;
+#define ded(wat) err(0,wat)
+void DragHandle::Release() {
+ if (!valid()) return; // nothing to release
+ UIElement* e = rptr;
+ rptr = nullptr;
+ wptr = std::shared_ptr(nullptr);
+ e->OnDragRelease();
+}
\ No newline at end of file
diff --git a/libstarlight/source/starlight/InputManager.h b/libstarlight/source/starlight/InputManager.h
new file mode 100644
index 0000000..b2bf241
--- /dev/null
+++ b/libstarlight/source/starlight/InputManager.h
@@ -0,0 +1,104 @@
+#pragma once
+#include "starlight/_global.h"
+
+#include
+
+#include "starlight/datatypes/Vector2.h"
+
+#include "starlight/ui/UIElement.h"
+
+// borrow this from ctrulib
+#ifndef BIT
+#define BIT(n) (1U<<(n))
+enum {
+ KEY_A = BIT(0), ///< A
+ KEY_B = BIT(1), ///< B
+ KEY_SELECT = BIT(2), ///< Select
+ KEY_START = BIT(3), ///< Start
+ KEY_DRIGHT = BIT(4), ///< D-Pad Right
+ KEY_DLEFT = BIT(5), ///< D-Pad Left
+ KEY_DUP = BIT(6), ///< D-Pad Up
+ KEY_DDOWN = BIT(7), ///< D-Pad Down
+ KEY_R = BIT(8), ///< R
+ KEY_L = BIT(9), ///< L
+ KEY_X = BIT(10), ///< X
+ KEY_Y = BIT(11), ///< Y
+ KEY_ZL = BIT(14), ///< ZL (New 3DS only)
+ KEY_ZR = BIT(15), ///< ZR (New 3DS only)
+ KEY_TOUCH = BIT(20), ///< Touch (Not actually provided by HID)
+ KEY_CSTICK_RIGHT = BIT(24), ///< C-Stick Right (New 3DS only)
+ KEY_CSTICK_LEFT = BIT(25), ///< C-Stick Left (New 3DS only)
+ KEY_CSTICK_UP = BIT(26), ///< C-Stick Up (New 3DS only)
+ KEY_CSTICK_DOWN = BIT(27), ///< C-Stick Down (New 3DS only)
+ KEY_CPAD_RIGHT = BIT(28), ///< Circle Pad Right
+ KEY_CPAD_LEFT = BIT(29), ///< Circle Pad Left
+ KEY_CPAD_UP = BIT(30), ///< Circle Pad Up
+ KEY_CPAD_DOWN = BIT(31), ///< Circle Pad Down
+
+ // Generic catch-all directions
+ KEY_UP = KEY_DUP | KEY_CPAD_UP, ///< D-Pad Up or Circle Pad Up
+ KEY_DOWN = KEY_DDOWN | KEY_CPAD_DOWN, ///< D-Pad Down or Circle Pad Down
+ KEY_LEFT = KEY_DLEFT | KEY_CPAD_LEFT, ///< D-Pad Left or Circle Pad Left
+ KEY_RIGHT = KEY_DRIGHT | KEY_CPAD_RIGHT, ///< D-Pad Right or Circle Pad Right
+};
+#endif
+
+namespace starlight {
+ class InputManager;
+ class DragHandle {
+ friend class starlight::InputManager;
+ private:
+
+ protected:
+
+ public:
+ std::weak_ptr wptr;
+ starlight::ui::UIElement* rptr = nullptr;
+
+ DragHandle() { }
+ DragHandle(const DragHandle&) = delete;
+ ~DragHandle() { }
+
+ DragHandle& Grab(starlight::ui::UIElement* e);
+ DragHandle& PassUp(bool releaseOnFail = false);
+ void Release();
+
+ inline starlight::ui::UIElement* get() const { if (wptr.expired()) return nullptr; return rptr; }
+ inline bool valid() const { return rptr != nullptr && !wptr.expired(); };
+
+ inline explicit operator bool() const { return rptr != nullptr && !wptr.expired(); }
+ inline bool operator ==(starlight::ui::UIElement* e) const { return rptr == e; }
+ //starlight::ui::UIElement& operator *() const { return *rptr; } // as with optref, do *not* call without checking first
+ };
+
+ class InputManager {
+ private:
+ static DragHandle drag;
+
+ public:
+ static constexpr const float dragThreshold = 8.0f;
+ static constexpr const float flingThreshold = 5.0f;
+
+ static void Update();
+
+ static float DepthSlider();
+
+ static Vector2 CirclePad();
+ static Vector2 CStick();
+
+ static bool Held(unsigned int mask);
+ static bool Pressed(unsigned int mask);
+ static bool Released(unsigned int mask);
+
+ static Vector2 TouchPos();
+ static Vector2 TouchDelta();
+ static Vector2 TouchStart();
+ static Vector2 TouchDragDist();
+ static int TouchTime();
+
+ static DragHandle& GetDragHandle() { return InputManager::drag; }
+
+ private:
+ InputManager() {}
+ };
+}
diff --git a/libstarlight/source/starlight/ThemeManager.cpp b/libstarlight/source/starlight/ThemeManager.cpp
new file mode 100644
index 0000000..4dddb0e
--- /dev/null
+++ b/libstarlight/source/starlight/ThemeManager.cpp
@@ -0,0 +1,228 @@
+#include
+#include
+#include
+#include
+
+#include
+
+#include "starlight/_incLib/lodepng.h"
+#include "starlight/_incLib/json.hpp"
+
+#include "ThemeManager.h"
+#include "starlight/gfx/ThemeRef.h"
+
+#include "starlight/gfx/DrawableImage.h"
+#include "starlight/gfx/DrawableNinePatch.h"
+#include "starlight/gfx/DrawableTest.h"
+#include "starlight/gfx/FontBMF.h"
+
+#include "starlight/gfx/RenderCore.h"
+#include "starlight/gfx/BitmapFont.h"
+
+using std::string;
+using std::shared_ptr;
+using std::make_shared;
+
+using nlohmann::json;
+
+using starlight::Vector2;
+
+using starlight::ThemeManager;
+using starlight::gfx::Drawable;
+using starlight::gfx::Font;
+using starlight::gfx::ThemeRef;
+using starlight::gfx::ThemeRefContainer;
+
+using starlight::gfx::DrawableImage;
+using starlight::gfx::DrawableNinePatch;
+
+using starlight::gfx::RenderCore;
+using starlight::gfx::CTexture;
+using starlight::gfx::BitmapFont;
+
+namespace {
+ inline int NextPow2(unsigned int x) {
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+ return ++x >= 64 ? x : 64; // min size to keep gpu from locking
+ }
+
+ inline string FindExtension(const string& path) {
+ auto idot = path.rfind('.');
+ if (idot == string::npos || idot == 0) return string(); // no dot found, or .hiddenfile? return empty
+ auto idir = path.rfind('/');
+ if (idir != string::npos && idir >= idot-1) return string(); // last dot in containing directory, or dir/.hiddenfile? return empty
+ return path.substr(idot+1); // return extension without dot
+ }
+
+ CTexture* LoadPNG(const std::string& path, bool isPremult = false) {
+ unsigned char* imgbuf;
+ unsigned width, height;
+ lodepng_decode32_file(&imgbuf, &width, &height, path.c_str());
+
+ unsigned bw = NextPow2(width), bh = NextPow2(height);
+
+ u8* gpubuf = static_cast(linearAlloc(bw*bh*4));
+
+ u8* src = static_cast(imgbuf); u8* dst = static_cast(gpubuf);
+
+ if (isPremult) {
+ // just convert endianness
+ for(unsigned iy = 0; iy(gpubuf), bw, bh);
+ tx->size = Vector2(width, height); // and for now just fix the size after the fact
+
+ std::free(imgbuf);
+ linearFree(gpubuf);
+
+ return tx;
+ }
+}
+
+std::unordered_map> ThemeManager::drawables;
+std::unordered_map> ThemeManager::fonts;
+std::list> ThemeManager::tq;
+
+ThemeRef ThemeManager::GetAsset(const std::string& name) {
+ auto const& itr = drawables.find(name);
+ if (itr == drawables.end()) {
+ return &drawables.insert(std::make_pair(name, ThemeRefContainer(name))).first->second;
+ } else return &itr->second;
+}
+
+ThemeRef ThemeManager::GetFont(const std::string& name) {
+ auto const& itr = fonts.find(name);
+ if (itr == fonts.end()) {
+ return &fonts.insert(std::make_pair(name, ThemeRefContainer(name))).first->second;
+ } else return &itr->second;
+}
+
+void ThemeManager::Fulfill(ThemeRefContainer& ref) {
+ string path = ResolveAssetPath(ref.name);
+ ref.ptr = LoadAsset(path);
+}
+
+shared_ptr ThemeManager::LoadAsset(string& path) {
+ static shared_ptr nulldrw = make_shared();
+
+ string ext = FindExtension(path);
+ printf("load: %s (%s)\n", path.c_str(), ext.c_str());
+ /**/ if (ext == "png") {
+ return make_shared(LoadPNG(path));
+ }
+ else if (ext == "json") {
+ json j;
+ { // using:
+ std::ifstream fs(path);
+ fs >> j;
+ }
+ auto st = j.dump();
+ printf("file contents: %s\n", st.c_str());
+
+ string type = j["assetType"];
+ /**/ if (type == "ninepatch") {
+ path.erase(path.end()-5, path.end()); path.append(".png");
+ auto d = make_shared(LoadPNG(path));
+ d->margin = Vector2(j["margin"][0], j["margin"][1]);
+ return d;
+ }
+ // else if (type == "") { }
+ else if (type == "link") {
+ string npath = ResolveAssetPath(j["path"]);
+ //return LoadAsset(npath);
+ return GetAsset(npath).GetShared(); // I guess this works; may need to be altered for asynchronity if I do that later
+ // (perhaps by--wait no, making it the same ThemeRefContainer would require a full rearchitecture of this part @.@)
+ }
+ return nulldrw;
+ }
+ return nulldrw;
+}
+
+void ThemeManager::Fulfill(ThemeRefContainer& ref) {
+ string path = ResolveFontPath(ref.name);
+ auto font = make_shared();
+ { // using:
+ json j;
+ std::ifstream fs(path);
+ fs >> j;
+ font->font = std::make_shared(j);
+ }
+ path.erase(path.end()-5, path.end()); path.append(".png");
+ font->font->txMain.reset(LoadPNG(path));
+ path.erase(path.end()-4, path.end()); path.append(".border.png");
+ font->font->txBorder.reset(LoadPNG(path));
+ ref.ptr = font;
+}
+
+void ThemeManager::LoadProc() {
+ while (!tq.empty()) {
+ tq.front()();
+ tq.pop_front();
+ }
+}
+
+string ThemeManager::ResolveAssetPath(const string& id) {
+ struct stat buf;
+ string path(id.length() + 64, ' '); // preallocate buffer space
+ path.clear(); path.append("romfs:/"); path.append(id); path.append(".json");
+ printf("attempt: %s\n", path.c_str());
+ if (stat(path.c_str(), &buf) == 0) return path;
+ path.erase(path.end()-5, path.end()); path.append(".png");
+ printf("attempt: %s\n", path.c_str());
+ if (stat(path.c_str(), &buf) == 0) return path;
+
+ return string();
+}
+
+string ThemeManager::ResolveFontPath(const string& id) { // this needs redone, but whatever
+ struct stat buf;
+ string path(id.length() + 64, ' '); // preallocate buffer space
+ path.clear(); path.append("romfs:/fonts/"); path.append(id); path.append(".json");
+ printf("attempt: %s\n", path.c_str());
+ if (stat(path.c_str(), &buf) == 0) return path;
+ path.erase(path.end()-5, path.end()); path.append(".png");
+ printf("attempt: %s\n", path.c_str());
+ if (stat(path.c_str(), &buf) == 0) return path;
+
+ return string();
+}
+
diff --git a/libstarlight/source/starlight/ThemeManager.h b/libstarlight/source/starlight/ThemeManager.h
new file mode 100644
index 0000000..ade598a
--- /dev/null
+++ b/libstarlight/source/starlight/ThemeManager.h
@@ -0,0 +1,45 @@
+#pragma once
+#include "starlight/_global.h"
+
+#include
+#include
+#include
+#include
+
+#include "starlight/gfx/Drawable.h"
+#include "starlight/gfx/Font.h"
+
+namespace starlight {
+ // forward declare
+ namespace gfx {
+ template class ThemeRefContainer;
+ template class ThemeRef;
+ }
+
+ class ThemeManager {
+ template
+ friend class starlight::gfx::ThemeRefContainer;
+ private:
+ static std::unordered_map> drawables;
+ static std::unordered_map> fonts;
+ static std::list> tq;
+ protected:
+ static void Fulfill(gfx::ThemeRefContainer& ref);
+ static void Fulfill(gfx::ThemeRefContainer& ref);
+
+ static std::shared_ptr LoadAsset(std::string& path);
+ public:
+ ThemeManager() = delete; // "static" class
+
+ static gfx::ThemeRef GetAsset(const std::string& name);
+ static gfx::ThemeRef GetFont(const std::string& name);
+
+ static void LoadProc();
+
+ static std::string ResolveAssetPath(const std::string& id);
+ static std::string ResolveFontPath(const std::string& id);
+ };
+}
+
+// post-include dependency
+#include "starlight/gfx/ThemeRef.h"
diff --git a/libstarlight/source/starlight/_global.h b/libstarlight/source/starlight/_global.h
new file mode 100644
index 0000000..e76eda3
--- /dev/null
+++ b/libstarlight/source/starlight/_global.h
@@ -0,0 +1,5 @@
+#pragma once
+
+// set up namespace shorthand
+namespace starlight {}
+namespace sl = starlight;
diff --git a/libstarlight/source/starlight/_incLib/_stringfix.h b/libstarlight/source/starlight/_incLib/_stringfix.h
new file mode 100644
index 0000000..01b1f4b
--- /dev/null
+++ b/libstarlight/source/starlight/_incLib/_stringfix.h
@@ -0,0 +1,48 @@
+// okay, this is super ugly, but as of right now devkitARM seems to be missing some string conversion functions :(
+
+#pragma once
+
+// !! UNCOMMENT if using devkitARM r45 or earlier !!
+//#include
+//#include
+
+// add in missing string functions
+#if defined(_GLIBCXX_STRING) && !defined(_GLIBCXX_USE_C99)
+// !! UNCOMMENT if using devkitARM r45 or earlier !!
+/*namespace std { // whee ugly hacks!
+ template
+ std::string to_string(T value) {
+ std::ostringstream os;
+ os << value;
+ return os.str();
+ }
+ int stoi(const string& str) {
+ stringstream ss(str);
+ int N;
+ ss<>N;
+ return N;
+ }
+ float strtof(const string& str) {
+ stringstream ss(str);
+ float N;
+ ss<>N;
+ return N;
+ }
+ double strtod(const string& str) {
+ stringstream ss(str);
+ double N;
+ ss<>N;
+ return N;
+ }
+ long double strtold(const string& str) {
+ stringstream ss(str);
+ long double N;
+ ss<>N;
+ return N;
+ }
+}//*/
+#endif
diff --git a/libstarlight/source/starlight/_incLib/json.hpp b/libstarlight/source/starlight/_incLib/json.hpp
new file mode 100644
index 0000000..b60dd20
--- /dev/null
+++ b/libstarlight/source/starlight/_incLib/json.hpp
@@ -0,0 +1,12206 @@
+// zp edit: let's just save some disk I/O here
+#pragma once
+// and fix missing string functions
+#include "_stringfix.h"
+
+/*
+ __ _____ _____ _____
+ __| | __| | | | JSON for Modern C++
+| | |__ | | | | | | version 2.0.9
+|_____|_____|_____|_|___| https://github.com/nlohmann/json
+
+Licensed under the MIT License .
+Copyright (c) 2013-2016 Niels Lohmann .
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef NLOHMANN_JSON_HPP
+#define NLOHMANN_JSON_HPP
+
+#include // all_of, for_each, transform
+#include // array
+#include // assert
+#include // isdigit
+#include // and, not, or
+#include // isfinite, ldexp, signbit
+#include // nullptr_t, ptrdiff_t, size_t
+#include // int64_t, uint64_t
+#include // strtod, strtof, strtold, strtoul
+#include // strlen
+#include // function, hash, less
+#include // initializer_list
+#include // setw
+#include // istream, ostream
+#include // advance, begin, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
+#include // numeric_limits
+#include // locale
+#include