flailing at VS

This commit is contained in:
zetaPRIME 2017-01-16 20:40:45 -05:00
parent a9d0768379
commit 47d93b8180
79 changed files with 24173 additions and 0 deletions

BIN
.vs/libstarlight/v14/.suo Normal file

Binary file not shown.

BIN
libstarlight.VC.db Normal file

Binary file not shown.

28
libstarlight.sln Normal file
View File

@ -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

View File

@ -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.

View File

@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="source\starlight\Application.cpp" />
<ClCompile Include="source\starlight\datatypes\Color.cpp" />
<ClCompile Include="source\starlight\datatypes\Vector2.cpp" />
<ClCompile Include="source\starlight\datatypes\VRect.cpp" />
<ClCompile Include="source\starlight\GFXManager.cpp" />
<ClCompile Include="source\starlight\gfx\BitmapFont.cpp" />
<ClCompile Include="source\starlight\gfx\DisplayList.cpp" />
<ClCompile Include="source\starlight\gfx\Drawable.cpp" />
<ClCompile Include="source\starlight\gfx\DrawableImage.cpp" />
<ClCompile Include="source\starlight\gfx\DrawableNinePatch.cpp" />
<ClCompile Include="source\starlight\gfx\DrawableTest.cpp" />
<ClCompile Include="source\starlight\gfx\DrawContext.cpp" />
<ClCompile Include="source\starlight\gfx\DrawContextCanvas.cpp" />
<ClCompile Include="source\starlight\gfx\DrawContextTopScreen.cpp" />
<ClCompile Include="source\starlight\gfx\DrawContextTouchscreen.cpp" />
<ClCompile Include="source\starlight\gfx\Font.cpp" />
<ClCompile Include="source\starlight\gfx\FontBMF.cpp" />
<ClCompile Include="source\starlight\gfx\RenderCore.cpp" />
<ClCompile Include="source\starlight\InputManager.cpp" />
<ClCompile Include="source\starlight\ThemeManager.cpp" />
<ClCompile Include="source\starlight\ui\Button.cpp" />
<ClCompile Include="source\starlight\ui\Image.cpp" />
<ClCompile Include="source\starlight\ui\Label.cpp" />
<ClCompile Include="source\starlight\ui\ParallaxLayer.cpp" />
<ClCompile Include="source\starlight\ui\ScrollField.cpp" />
<ClCompile Include="source\starlight\ui\TopScreenCanvas.cpp" />
<ClCompile Include="source\starlight\ui\TouchScreenCanvas.cpp" />
<ClCompile Include="source\starlight\ui\UICanvas.cpp" />
<ClCompile Include="source\starlight\ui\UIContainer.cpp" />
<ClCompile Include="source\starlight\ui\UIElement.cpp" />
<ClCompile Include="source\starlight\util\WorkerThread.cpp" />
<ClCompile Include="source\starlight\_incLib\lodepng.cpp" />
<ClCompile Include="vs_shim.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="source\starlight\Application.h" />
<ClInclude Include="source\starlight\datatypes\Color.h" />
<ClInclude Include="source\starlight\datatypes\OptRef.h" />
<ClInclude Include="source\starlight\datatypes\Vector2.h" />
<ClInclude Include="source\starlight\datatypes\VRect.h" />
<ClInclude Include="source\starlight\GFXManager.h" />
<ClInclude Include="source\starlight\gfx\BitmapFont.h" />
<ClInclude Include="source\starlight\gfx\DisplayList.h" />
<ClInclude Include="source\starlight\gfx\Drawable.h" />
<ClInclude Include="source\starlight\gfx\DrawableImage.h" />
<ClInclude Include="source\starlight\gfx\DrawableNinePatch.h" />
<ClInclude Include="source\starlight\gfx\DrawableTest.h" />
<ClInclude Include="source\starlight\gfx\DrawContext.h" />
<ClInclude Include="source\starlight\gfx\DrawContextCanvas.h" />
<ClInclude Include="source\starlight\gfx\DrawContextTopScreen.h" />
<ClInclude Include="source\starlight\gfx\DrawContextTouchscreen.h" />
<ClInclude Include="source\starlight\gfx\Font.h" />
<ClInclude Include="source\starlight\gfx\FontBMF.h" />
<ClInclude Include="source\starlight\gfx\RenderCore.h" />
<ClInclude Include="source\starlight\gfx\ThemeRef.h" />
<ClInclude Include="source\starlight\InputManager.h" />
<ClInclude Include="source\starlight\ThemeManager.h" />
<ClInclude Include="source\starlight\ui\Button.h" />
<ClInclude Include="source\starlight\ui\Image.h" />
<ClInclude Include="source\starlight\ui\Label.h" />
<ClInclude Include="source\starlight\ui\ParallaxLayer.h" />
<ClInclude Include="source\starlight\ui\ScrollField.h" />
<ClInclude Include="source\starlight\ui\TopScreenCanvas.h" />
<ClInclude Include="source\starlight\ui\TouchScreenCanvas.h" />
<ClInclude Include="source\starlight\ui\UICanvas.h" />
<ClInclude Include="source\starlight\ui\UIContainer.h" />
<ClInclude Include="source\starlight\ui\UIElement.h" />
<ClInclude Include="source\starlight\util\WorkerThread.h" />
<ClInclude Include="source\starlight\_global.h" />
<ClInclude Include="source\starlight\_incLib\json.hpp" />
<ClInclude Include="source\starlight\_incLib\json_fwd.hpp" />
<ClInclude Include="source\starlight\_incLib\lodepng.h" />
<ClInclude Include="source\starlight\_incLib\_stringfix.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{21A0624A-FE85-4D9C-ADDE-7E272B48E906}</ProjectGuid>
<Keyword>MakeFileProj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<NMakeBuildCommandLine>make</NMakeBuildCommandLine>
<NMakePreprocessorDefinitions>
</NMakePreprocessorDefinitions>
<NMakeCleanCommandLine>make clean</NMakeCleanCommandLine>
<ExecutablePath>$(PATH);</ExecutablePath>
<IncludePath>.\;$(ProjectDir)source\;$(DEVKITPROWIN)\libctru\include\;$(DEVKITARMWIN)\arm-none-eabi\include\;$(DEVKITARMWIN)\arm-none-eabi\include\c++\6.2.0\</IncludePath>
<ReferencePath />
<LibraryPath />
<LibraryWPath />
<ExcludePath />
<NMakeIncludeSearchPath>.\;$(ProjectDir)source\;$(DEVKITPROWIN)\libctru\include\;$(DEVKITARMWIN)\arm-none-eabi\include\;$(DEVKITARMWIN)\arm-none-eabi\include\c++\6.2.0\;</NMakeIncludeSearchPath>
<SourcePath />
<NMakeForcedIncludes>$(ProjectDir)/vs_shim.cpp</NMakeForcedIncludes>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<NMakeBuildCommandLine>make</NMakeBuildCommandLine>
<NMakePreprocessorDefinitions>
</NMakePreprocessorDefinitions>
<NMakeCleanCommandLine>make clean</NMakeCleanCommandLine>
<ExecutablePath>$(PATH);</ExecutablePath>
<IncludePath>.\;$(ProjectDir)source\;$(DEVKITPROWIN)\libctru\include\;$(DEVKITARMWIN)\arm-none-eabi\include\;$(DEVKITARMWIN)\arm-none-eabi\include\c++\6.2.0\</IncludePath>
<ReferencePath />
<LibraryPath />
<LibraryWPath />
<ExcludePath />
<NMakeIncludeSearchPath>.\;$(ProjectDir)source\;$(DEVKITPROWIN)\libctru\include\;$(DEVKITARMWIN)\arm-none-eabi\include\;$(DEVKITARMWIN)\arm-none-eabi\include\c++\6.2.0\;</NMakeIncludeSearchPath>
<SourcePath />
<NMakeForcedIncludes>$(ProjectDir)/vs_shim.cpp</NMakeForcedIncludes>
</PropertyGroup>
<ItemDefinitionGroup>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,234 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="source\starlight\Application.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\datatypes\Color.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\datatypes\Vector2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\datatypes\VRect.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\BitmapFont.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\DisplayList.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\Drawable.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\DrawableImage.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\DrawableNinePatch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\DrawableTest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\DrawContext.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\DrawContextCanvas.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\DrawContextTopScreen.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\DrawContextTouchscreen.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\Font.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\FontBMF.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\gfx\RenderCore.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\GFXManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\InputManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ThemeManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\Button.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\Image.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\Label.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\ParallaxLayer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\ScrollField.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\TopScreenCanvas.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\TouchScreenCanvas.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\UICanvas.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\UIContainer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\ui\UIElement.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\util\WorkerThread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="source\starlight\_incLib\lodepng.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="vs_shim.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="source\starlight\Application.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\datatypes\Color.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\datatypes\OptRef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\datatypes\Vector2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\datatypes\VRect.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\BitmapFont.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\DisplayList.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\Drawable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\DrawableImage.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\DrawableNinePatch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\DrawableTest.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\DrawContext.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\DrawContextCanvas.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\DrawContextTopScreen.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\DrawContextTouchscreen.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\Font.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\FontBMF.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\RenderCore.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\gfx\ThemeRef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\GFXManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\InputManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ThemeManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\Button.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\Image.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\Label.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\ParallaxLayer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\ScrollField.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\TopScreenCanvas.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\TouchScreenCanvas.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\UICanvas.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\UIContainer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\ui\UIElement.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\util\WorkerThread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\_global.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\_incLib\json.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\_incLib\json_fwd.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\_incLib\lodepng.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="source\starlight\_incLib\_stringfix.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>true</ShowAllFiles>
</PropertyGroup>
</Project>

View File

@ -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<TouchScreenCanvas>();
topScreen = std::make_shared<TopScreenCanvas>();
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();
}

View File

@ -0,0 +1,56 @@
#pragma once
#include "starlight/_global.h"
#include <string>
#include <memory>
#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<ui::TouchScreenCanvas> touchScreen = nullptr;
std::shared_ptr<ui::TopScreenCanvas> 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() { }
};
}

View File

@ -0,0 +1,51 @@
#include "GFXManager.h"
using starlight::Vector2;
using starlight::GFXManager;
using starlight::gfx::DrawContext;
std::forward_list<DrawContext*> GFXManager::ctxStack;
std::forward_list<Vector2> 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();
}

View File

@ -0,0 +1,31 @@
#pragma once
#include "starlight/_global.h"
#include <forward_list>
#include "starlight/gfx/DrawContext.h"
namespace starlight {
class GFXManager {
private:
static std::forward_list<gfx::DrawContext*> ctxStack;
static std::forward_list<Vector2> 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();
};
}

View File

@ -0,0 +1,122 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <time.h>
#include <math.h>
#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<UIElement>(nullptr);
e->OnDragRelease();
}

View File

@ -0,0 +1,104 @@
#pragma once
#include "starlight/_global.h"
#include <memory>
#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<starlight::ui::UIElement> 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() {}
};
}

View File

@ -0,0 +1,228 @@
#include <cstdlib>
#include <string>
#include <fstream>
#include <sys/stat.h>
#include <citro3d.h>
#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<u8*>(linearAlloc(bw*bh*4));
u8* src = static_cast<u8*>(imgbuf); u8* dst = static_cast<u8*>(gpubuf);
if (isPremult) {
// just convert endianness
for(unsigned iy = 0; iy<height; iy++) {
for (unsigned ix = 0; ix < height; ix++) {
int r = *src++;
int g = *src++;
int b = *src++;
int a = *src++;
*dst++ = a;
*dst++ = b;
*dst++ = g;
*dst++ = r;
}
dst += (bw - width) * 4; // skip the difference
}
} else {
// convert and premultiply
for(unsigned iy = 0; iy<height; iy++) {
for (unsigned ix = 0; ix < height; ix++) {
int r = *src++;
int g = *src++;
int b = *src++;
int a = *src++;
float aa = (1.0f / 255.0f) * a;
*dst++ = a;
*dst++ = b*aa;
*dst++ = g*aa;
*dst++ = r*aa;
}
dst += (bw - width) * 4; // skip the difference
}
}
// completely skipping over the difference instead of erasing might eventually lead to garbage outside of frame,
// but meh; that'll only be visible if you intentionally push the UVs outside the image proper
CTexture* tx = RenderCore::LoadTexture(static_cast<void*>(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<std::string, ThemeRefContainer<Drawable>> ThemeManager::drawables;
std::unordered_map<std::string, ThemeRefContainer<Font>> ThemeManager::fonts;
std::list<std::function<void()>> ThemeManager::tq;
ThemeRef<Drawable> ThemeManager::GetAsset(const std::string& name) {
auto const& itr = drawables.find(name);
if (itr == drawables.end()) {
return &drawables.insert(std::make_pair(name, ThemeRefContainer<Drawable>(name))).first->second;
} else return &itr->second;
}
ThemeRef<Font> ThemeManager::GetFont(const std::string& name) {
auto const& itr = fonts.find(name);
if (itr == fonts.end()) {
return &fonts.insert(std::make_pair(name, ThemeRefContainer<Font>(name))).first->second;
} else return &itr->second;
}
void ThemeManager::Fulfill(ThemeRefContainer<Drawable>& ref) {
string path = ResolveAssetPath(ref.name);
ref.ptr = LoadAsset(path);
}
shared_ptr<Drawable> ThemeManager::LoadAsset(string& path) {
static shared_ptr<Drawable> nulldrw = make_shared<starlight::gfx::DrawableTest>();
string ext = FindExtension(path);
printf("load: %s (%s)\n", path.c_str(), ext.c_str());
/**/ if (ext == "png") {
return make_shared<DrawableImage>(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<DrawableNinePatch>(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<Font>& ref) {
string path = ResolveFontPath(ref.name);
auto font = make_shared<starlight::gfx::FontBMF>();
{ // using:
json j;
std::ifstream fs(path);
fs >> j;
font->font = std::make_shared<BitmapFont>(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();
}

View File

@ -0,0 +1,45 @@
#pragma once
#include "starlight/_global.h"
#include <string>
#include <unordered_map>
#include <list>
#include <functional>
#include "starlight/gfx/Drawable.h"
#include "starlight/gfx/Font.h"
namespace starlight {
// forward declare
namespace gfx {
template <class T> class ThemeRefContainer;
template <class T> class ThemeRef;
}
class ThemeManager {
template <class T>
friend class starlight::gfx::ThemeRefContainer;
private:
static std::unordered_map<std::string, gfx::ThemeRefContainer<gfx::Drawable>> drawables;
static std::unordered_map<std::string, gfx::ThemeRefContainer<gfx::Font>> fonts;
static std::list<std::function<void()>> tq;
protected:
static void Fulfill(gfx::ThemeRefContainer<gfx::Drawable>& ref);
static void Fulfill(gfx::ThemeRefContainer<gfx::Font>& ref);
static std::shared_ptr<gfx::Drawable> LoadAsset(std::string& path);
public:
ThemeManager() = delete; // "static" class
static gfx::ThemeRef<gfx::Drawable> GetAsset(const std::string& name);
static gfx::ThemeRef<gfx::Font> 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"

View File

@ -0,0 +1,5 @@
#pragma once
// set up namespace shorthand
namespace starlight {}
namespace sl = starlight;

View File

@ -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 <string>
//#include <sstream>
// 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 <typename T>
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<<str;
ss>>N;
return N;
}
float strtof(const string& str) {
stringstream ss(str);
float N;
ss<<str;
ss>>N;
return N;
}
double strtod(const string& str) {
stringstream ss(str);
double N;
ss<<str;
ss>>N;
return N;
}
long double strtold(const string& str) {
stringstream ss(str);
long double N;
ss<<str;
ss>>N;
return N;
}
}//*/
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
#pragma once
#ifndef NLOHMANN_JSON_FWD_HPP
#define NLOHMANN_JSON_FWD_HPP
#include <cstdint>
#include <map>
#include <vector>
#include <string>
namespace nlohmann
{
template <
template<typename U, typename V, typename... Args> class ObjectType,
template<typename U, typename... Args> class ArrayType,
class StringType,
class BooleanType,
class NumberIntegerType,
class NumberUnsignedType,
class NumberFloatType,
template<typename U> class AllocatorType
>
class basic_json;
using json = basic_json<std::map,std::vector,std::string,bool,std::int64_t,
std::uint64_t,double,std::allocator>;
} // namespace nlohmann
#endif // NLOHMANN_JSON_FWD_HPP

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
#include "Color.h"
using starlight::Color;
//
//#define RGBA8(r, g, b, a) ((((a)&0xFF)<<24) | (((b)&0xFF)<<16) | (((g)&0xFF)<<8) | (((r)&0xFF)<<0))
//#define RGBA8_GET_R(c) (((c) >> 0) & 0xFF)
//#define RGBA8_GET_G(c) (((c) >> 8) & 0xFF)
//#define RGBA8_GET_B(c) (((c) >> 16) & 0xFF)
//#define RGBA8_GET_A(c) (((c) >> 24) & 0xFF)
const Color Color::transparent = Color(0.0f, 0.0f, 0.0f, 0.0f);
const Color Color::white = Color(1.0f, 1.0f, 1.0f);
const Color Color::black = Color(0.0f, 0.0f, 0.0f);
const Color Color::lightGray = Color(0.75f, 0.75f, 0.75f);
const Color Color::midGray = Color(0.5f, 0.5f, 0.5f);
const Color Color::darkGray = Color(0.25f, 0.25f, 0.25f);

View File

@ -0,0 +1,42 @@
#pragma once
#include "starlight/_global.h"
namespace starlight {
class Color {
private:
//
public:
float r = 1.0f;
float g = 1.0f;
float b = 1.0f;
float a = 1.0f;
constexpr Color() : r(0), g(0), b(0), a(0) { }
constexpr Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) { }
constexpr Color(float r, float g, float b) : r(r), g(g), b(b), a(1.0f) { }
~Color() = default;
inline Color Alpha(float alpha) const { return Color(r,g,b,alpha); }
inline Color Premultiplied() const { return Color(r*a,g*a,b*a,a); }
inline bool operator == (const Color& o) const { return r == o.r && g == o.g && b == o.b && a == o.a; }
inline bool operator != (const Color& o) const { return r != o.r || g != o.g || b != o.b || a != o.a; }
inline Color operator * (const Color& o) const { return Color(r * o.r, g * o.g, b * o.b, a * o.a); }
// hmm. I guess this will do ¯\_(ツ)_/¯ don't really want to force cstdint
inline operator unsigned int() const { return (((((int)(a*255))&0xFF)<<24) | ((((int)(b*255))&0xFF)<<16) | ((((int)(g*255))&0xFF)<<8) | ((((int)(r*255))&0xFF)<<0)); }
// premult: inline operator unsigned int() const { return (((((int)(a*255))&0xFF)<<24) | ((((int)(a*b*255))&0xFF)<<16) | ((((int)(a*g*255))&0xFF)<<8) | ((((int)(a*r*255))&0xFF)<<0)); }
static const Color transparent;
static const Color white;
static const Color black;
static const Color lightGray;
static const Color midGray;
static const Color darkGray;
//
};
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "starlight/_global.h"
namespace starlight {
template <class T>
class OptRef {
private:
T* ref;
public:
OptRef() : ref(nullptr) { }
OptRef(decltype(nullptr) nul) : ref(nullptr) { }
OptRef(const T& ref) : ref(const_cast<T*>(&ref)) { } // whatever, const cast, I know what I'm doing
~OptRef() { }
const T& get() { return *ref; } // ... I guess :(
inline explicit operator bool() const { return ref != nullptr; }
inline const T& operator ->() { return *ref; } // meh, technically unsafe but it's not meant to be used without explicit checking
inline operator const T&() { return *ref; } // same here
};
}

View File

@ -0,0 +1,65 @@
#include <stdlib.h>
#include <math.h>
#include <fastmath.h>
#include <algorithm>
#include "VRect.h"
using starlight::Vector2;
using starlight::VRect;
VRect::VRect() : pos(Vector2()), size(Vector2()) { }
VRect::~VRect() { }
VRect::VRect(float x, float y, float w, float h) : pos(x, y), size(w, h) { }
VRect::VRect(Vector2 pos, Vector2 size) : pos(pos), size(size) { }
Vector2 VRect::Center() const { return pos + (size * 0.5f); }
Vector2 VRect::TopLeft() const { return pos; }
Vector2 VRect::TopRight() const { return Vector2(pos.x + size.x, pos.y); }
Vector2 VRect::BottomLeft() const { return Vector2(pos.x, pos.y + size.y); }
Vector2 VRect::BottomRight() const { return pos + size; }
bool VRect::Overlaps(const VRect & o) const {
Vector2 c = Center();
Vector2 oc = o.Center();
return fabsf(c.x - oc.x) * 2.0f < size.x + o.size.x && fabsf(c.y - oc.y) * 2.0f < size.y + o.size.y;
}
bool VRect::Contains(const Vector2 & vec) const {
// not sure which implementation is faster
return (pos.x <= vec.x && vec.x <= pos.x + size.x && pos.y <= vec.y && vec.y <= pos.y + size.y);
//Vector2 c = Center();
//return fabsf(c.x - vec.x) < size.x * 0.5f && fabsf(c.y - vec.y) < size.y * 0.5f;
}
VRect VRect::IntSnap() const { return VRect(pos.IntSnap(), size.IntSnap()); }
VRect VRect::Intersect(const VRect & o) const {
Vector2 tl ( std::max(pos.x, o.pos.x), std::max(pos.y, o.pos.y) );
Vector2 br ( std::min(pos.x + size.x, o.pos.x + o.size.x), std::min(pos.y + size.y, o.pos.y + o.size.y) );
VRect res (tl, br - tl);
if (res.size.x <= 0.0f || res.size.y <= 0.0f) return VRect(); // invalid area represented as a zero-rect
return res;
}
VRect VRect::Expand(const Vector2& amount, const Vector2& bias) const {
return VRect(pos + amount * bias * -2, size + amount * 2);
}
VRect VRect::Include(const Vector2& point) const { // could probably be more optimized
Vector2 tl = TopLeft(), br = BottomRight();
if (point.x < tl.x) tl.x = point.x;
else if (point.x > br.x) br.x = point.x;
if (point.y < tl.y) tl.y = point.y;
else if (point.y > br.y) br.y = point.y;
return VRect(tl, br - tl);
}
VRect VRect::TopEdge(float width) const { return VRect(pos.x, pos.y, size.x, width); }
VRect VRect::BottomEdge(float width) const { return VRect(pos.x, pos.y + size.y - width, size.x, width); }
VRect VRect::LeftEdge(float width) const { return VRect(pos.x, pos.y, width, size.y); }
VRect VRect::RightEdge(float width) const { return VRect(pos.x + size.x - width, pos.y, width, size.y); }
// constants
const VRect VRect::zero = VRect(); // should initialize to 0,0,0,0

View File

@ -0,0 +1,59 @@
#pragma once
#include "starlight/_global.h"
#include "Vector2.h"
namespace starlight {
class VRect {
private:
//
public:
Vector2 pos;
Vector2 size;
VRect();
VRect(float x, float y, float w, float h);
VRect(Vector2 pos, Vector2 size);
~VRect();
Vector2 Center() const;
Vector2 TopLeft() const;
Vector2 TopRight() const;
Vector2 BottomLeft() const;
Vector2 BottomRight() const;
bool Overlaps(const VRect & o) const;
bool Contains(const Vector2 & vec) const;
inline float Area() const { return size.Area(); }
VRect IntSnap() const;
VRect Intersect(const VRect & o) const;
VRect Expand(const Vector2& amount, const Vector2& bias) const;
VRect Expand(const Vector2& amount) const { return Expand(amount, Vector2::half); }
VRect Expand(float x, float y) const { return Expand(Vector2(x, y )); }
VRect Include(const Vector2& point) const;
VRect TopEdge(float width) const;
VRect BottomEdge(float width) const;
VRect LeftEdge(float width) const;
VRect RightEdge(float width) const;
inline bool operator == (const VRect & o) const { return pos == o.pos && size == o.size; }
inline bool operator != (const VRect & o) const { return pos != o.pos || size != o.size; }
// add/sub to move...
inline VRect operator + (const Vector2 & vec) const { return VRect(pos + vec, size); }
inline VRect operator - (const Vector2 & vec) const { return VRect(pos - vec, size); }
// mul/div to scale to a different mapping
inline VRect operator * (const Vector2 & vec) const { return VRect(pos * vec, size * vec); }
inline VRect operator / (const Vector2 & vec) const { return VRect(pos / vec, size / vec); }
inline VRect & operator += (const Vector2 & vec) { pos += vec; return *this; }
inline VRect & operator -= (const Vector2 & vec) { pos -= vec; return *this; }
static const VRect zero;
};
}

View File

@ -0,0 +1,43 @@
#include <cstdlib>
#include <cmath>
#include <fastmath.h>
#include "Vector2.h"
using starlight::Vector2;
Vector2::Vector2() : x(0.0f), y(0.0f) { }
Vector2::~Vector2() { }
Vector2::Vector2(float x, float y) : x(x), y(y) { }
// maths
float Vector2::Length() const { return sqrtf(x * x + y * y); }
Vector2 Vector2::Normalized() const { float m = Length(); return m == 0.0f ? Vector2::zero : Vector2(x / m, y / m); }
Vector2 Vector2::Reciprocal() const { return Vector2(y, x); }
Vector2 Vector2::IntSnap() const { return Vector2(roundf(x), roundf(y)); }
Vector2 Vector2::CardinalAxis() const {
if (fabsf(x) > fabsf(y)) return h;
return v;
}
Vector2 Vector2::Cardinal() const { return *this * CardinalAxis(); }
Vector2 Vector2::Rotate(float angle) const {
float s = sin(angle), c = cos(angle);
return Vector2(x * c - y * s, x * s + y * c);
}
Vector2 Vector2::RotateAround(const Vector2& anchor, float angle) const { return (*this - anchor).Rotate(angle) + anchor; }
// operators!
//inline Vector2 operator *(const Vector2* vec, const float scalar) { return Vector2(vec.x * scalar, vec.y * scalar); }
// constants
const Vector2 Vector2::zero = Vector2(0.0f, 0.0f);
const Vector2 Vector2::one = Vector2(1.0f, 1.0f);
const Vector2 Vector2::half = Vector2(0.5f, 0.5f);
const Vector2 Vector2::h = Vector2(1, 0);
const Vector2 Vector2::v = Vector2(0, 1);

View File

@ -0,0 +1,56 @@
#pragma once
#include "starlight/_global.h"
namespace starlight {
class Vector2 {
private:
//
public:
float x = 0.0f;
float y = 0.0f;
Vector2();
Vector2(float x, float y);
~Vector2();
float Length() const;
Vector2 Normalized() const;
inline float Area() const { return x * y; }
Vector2 Reciprocal() const;
Vector2 IntSnap() const;
Vector2 CardinalAxis() const;
Vector2 Cardinal() const;
Vector2 Rotate(float angle) const;
Vector2 RotateAround(const Vector2& anchor, float angle) const;
inline bool operator == (const Vector2 & o) const { return x == o.x && y == o.y; }
inline bool operator != (const Vector2 & o) const { return x != o.x || y != o.y; }
inline Vector2 operator - () const { return *this * -1.0f; }
inline Vector2 operator * (const float scalar) const { return Vector2(x * scalar, y * scalar); }
inline Vector2 operator / (const float scalar) const { return Vector2(x / scalar, y / scalar); }
inline Vector2 operator + (const Vector2 & o) const { return Vector2(x + o.x, y + o.y); }
inline Vector2 operator - (const Vector2 & o) const { return Vector2(x - o.x, y - o.y); }
inline Vector2 operator * (const Vector2 & o) const { return Vector2(x * o.x, y * o.y); }
inline Vector2 operator / (const Vector2 & o) const { return Vector2(x / o.x, y / o.y); }
inline Vector2 & operator *= (const float scalar) { x *= scalar; y *= scalar; return *this; }
inline Vector2 & operator /= (const float scalar) { x /= scalar; y /= scalar; return *this; } // maybe reciprocate then multiply instead? maybe the compiler does that
inline Vector2 & operator += (const Vector2 & o) { x += o.x; y += o.y; return *this; }
inline Vector2 & operator -= (const Vector2 & o) { x -= o.x; y -= o.y; return *this; }
inline Vector2 & operator *= (const Vector2 & o) { x *= o.x; y *= o.y; return *this; }
static const Vector2 zero;
static const Vector2 one;
static const Vector2 half;
static const Vector2 h;
static const Vector2 v;
};
}

View File

@ -0,0 +1,116 @@
#include "BitmapFont.h"
#include <cstdlib>
#include <cmath>
#include <fastmath.h>
#include "starlight/_incLib/json.hpp"
using nlohmann::json;
using starlight::Vector2;
using starlight::VRect;
using starlight::Color;
using starlight::gfx::BitmapFont;
//using starlight::gfx::BitmapFont::CharInfo;
BitmapFont::BitmapFont(json& j) {
// populate global info
fontSize = fabsf(j["info"]["size"]);
lineHeight = j["common"]["lineHeight"];
baseY = j["common"]["base"];
padX = j["info"]["padding"][3];
padY = j["info"]["padding"][0];
// assemble charinfo structs
for (auto& c : json::iterator_wrapper(j["chars"])) {
auto& cc = c.value();
auto& def = chars.insert({static_cast<char>(std::stoi(c.key())), CharInfo()}).first->second; // well that's kind of a pain just to get back the instantiated value
def.imgX = cc["x"];
def.imgY = cc["y"];
def.width = cc["width"];
def.height = cc["height"];
def.offX = cc["xoffset"];
def.offY = cc["yoffset"];
def.advX = cc["xadvance"];
}
// fetch kerning info
for (auto& kl : json::iterator_wrapper(j["kernings"])) {
char cl = std::stoi(kl.key());
for (auto& kr : json::iterator_wrapper(kl.value())) {
char cr = std::stoi(kr.key());
kernings[KerningKey(cl, cr)] = kr.value();
}
}
}
float BitmapFont::GetKerning(char cl, char cr) {
auto f = kernings.find(KerningKey(cl, cr));
if (f == kernings.end()) return 0;
return f->second;
}
BitmapFont::CharInfo& BitmapFont::Char(char c) {
auto f = chars.find(c);
if (f != chars.end()) return f->second;
static CharInfo cdefault = []() -> CharInfo {
CharInfo def;
def.imgX = def.imgY = def.width = def.height = def.offX = def.offY = def.advX = 0.0f;
return def;
}();
return cdefault;
}
float BitmapFont::DrawText(const Vector2& penStart, std::string& msg, float scale, DisplayList* dl) {
Vector2 pen = penStart;
Vector2 pad(padX, 0);//-padY); // compensate for padding around glyphs
pen -= pad;
Vector2 uvScale = Vector2::one / txMain->txSize;
auto qn = dl ? dl->GetLastNode<DLNode_Quads>(true) : nullptr;
char cl = 0xFF;//' ';
for (auto c : msg) {
pen.x += GetKerning(cl, c) * scale;
auto& ci = Char(c);
//printf("%c w %f h %f adv %f sc %f\n", c, ci.width, ci.height, ci.advX, scale);
VRect crect(ci.imgX, ci.imgY, ci.width, ci.height);
if (dl) qn->Add(VRect(pen, crect.size * scale), crect * uvScale);
pen.x += ci.advX * scale;
cl = c;
}
pen += pad;
return pen.x - penStart.x;
}

View File

@ -0,0 +1,58 @@
#pragma once
#include "starlight/_global.h"
#include <memory>
#include <unordered_map>
#include <string>
#include "starlight/datatypes/Vector2.h"
#include "starlight/datatypes/VRect.h"
#include "starlight/datatypes/Color.h"
#include "starlight/datatypes/OptRef.h"
#include "starlight/gfx/RenderCore.h"
#include "starlight/gfx/DisplayList.h"
// we don't need the whole thing here
#include "starlight/_incLib/json_fwd.hpp"
namespace starlight {
namespace gfx {
class BitmapFont {
public:
struct CharInfo {
float imgX, imgY;
float width, height;
float offX, offY;
float advX;
};
float fontSize;
float lineHeight;
float baseY;
float padX, padY;
std::unordered_map<char, CharInfo> chars;
std::unordered_map<unsigned int, float> kernings;
std::unique_ptr<CTexture> txMain;
std::unique_ptr<CTexture> txBorder;
BitmapFont() { }
BitmapFont(nlohmann::json& j);
~BitmapFont() { }
float GetKerning(char cl, char cr);
CharInfo& Char(char c);
float DrawText(const Vector2& penStart, std::string& msg, float scale = 1, DisplayList* dl = nullptr);
// what to put in the bitmapfont class itself?
static inline constexpr unsigned int KerningKey(char cl, char cr) {
return (static_cast<unsigned int>(cl) | (static_cast<unsigned int>(cr) << 8));
}
};
}
}

View File

@ -0,0 +1,37 @@
#include "DisplayList.h"
#include "starlight/gfx/RenderCore.h"
#include "starlight/GFXManager.h"
using starlight::gfx::RenderCore;
using starlight::gfx::DLNodeType;
using starlight::gfx::DLNode;
using starlight::gfx::DLNode_Quads;
using starlight::gfx::DLNode_Func;
using starlight::gfx::DisplayList;
void DisplayList::Run(Vector2 offset) {
if (GFXManager::PrepareForDrawing()) {
offset = (offset + this->offset).IntSnap();
for (auto n : nodes) n->Apply(offset);
}
}
bool DisplayList::Valid() {
return !nodes.empty();
}
void DLNode_Quads::Apply(Vector2 offset) {
for (auto r : rects) RenderCore::DrawQuad(r.first + offset, r.second, true);
}
void DisplayList::AddQuad(const VRect& quad, const VRect& uv) {
auto node = (!nodes.empty() && nodes.back()->Type() == DLNodeType::Quads) ? std::static_pointer_cast<DLNode_Quads>(nodes.back()) : CreateNode<DLNode_Quads>();
node->Add(quad, uv);
}
void DLNode_Func::Apply(Vector2 offset) { func(offset); }
void DisplayList::AddFunc(std::function<void(Vector2)> func) { CreateNode<DLNode_Func>(func); }

View File

@ -0,0 +1,82 @@
#pragma once
#include "starlight/_global.h"
#include <vector>
#include <memory>
#include <type_traits>
#include <functional>
#include "starlight/datatypes/Vector2.h"
#include "starlight/datatypes/VRect.h"
#include "starlight/datatypes/Color.h"
namespace starlight {
namespace gfx {
enum DLNodeType {
Quads,
Func
};
class DLNode {
public:
virtual DLNodeType Type() = 0;
virtual void Apply(Vector2 offset) = 0;
};
class DLNode_Quads : public DLNode {
std::vector<std::pair<VRect, VRect>> rects;
public:
static constexpr DLNodeType NodeType = DLNodeType::Quads;
DLNodeType Type() { return NodeType; }
void Apply(Vector2 offset) override;
inline void Add(const VRect& quad, const VRect& uv) { rects.push_back(std::pair<VRect, VRect>(quad.IntSnap(), uv)); }
};
class DLNode_Func : public DLNode {
std::function<void(Vector2)> func;
public:
DLNode_Func(std::function<void(Vector2)> func) : func(func) { }
static constexpr DLNodeType NodeType = DLNodeType::Func;
DLNodeType Type() { return NodeType; }
void Apply(Vector2 offset) override;
};
class DisplayList {
private:
std::vector<std::shared_ptr<DLNode>> nodes;// = std::vector<std::shared_ptr<DLNode>>(8);
public:
Vector2 offset;
DisplayList() { }
~DisplayList() { }
void Run(Vector2 offset);
inline void AddNode(std::shared_ptr<DLNode> node) { nodes.push_back(std::static_pointer_cast<DLNode>(node)); }
template <typename T, typename... Ps>
inline std::shared_ptr<T> CreateNode(Ps... args) {
static_assert(std::is_base_of<DLNode, T>::value, "T is not a subtype of DLNode");
nodes.push_back(std::make_shared<T>(args...));
return std::static_pointer_cast<T>(nodes.back());
}
template <typename T>
inline std::shared_ptr<T> GetLastNode(bool create = false) {
static_assert(std::is_base_of<DLNode, T>::value, "T is not a subtype of DLNode");
if (nodes.empty() || nodes.back()->Type() != T::NodeType) {
if (!create) return nullptr;
nodes.push_back(std::make_shared<T>());
}
return std::static_pointer_cast<T>(nodes.back());
}
void AddQuad(const VRect& quad, const VRect& uv);
void AddFunc(std::function<void(Vector2)> func);
bool Valid();
//
};
}
}

View File

@ -0,0 +1,3 @@
#include "DrawContext.h"
//

View File

@ -0,0 +1,30 @@
#pragma once
#include "starlight/_global.h"
#include "starlight/datatypes/VRect.h"
#include "starlight/datatypes/Color.h"
#include "starlight/datatypes/OptRef.h"
namespace starlight {
class GFXManager;
namespace gfx {
class DrawContext {
friend class starlight::GFXManager;
protected:
virtual void Open() = 0;
virtual void Close() = 0;
virtual bool Prepare() = 0;
bool drawReady = false;
public:
const VRect rect;
DrawContext() : rect(VRect(0,0,1,1)) { }
DrawContext(VRect rect) : rect(rect) { }
virtual ~DrawContext() { }
virtual void Clear(Color color) { }
virtual void Clear() { Clear(Color(0,0,0,0)); }
};
}
}

View File

@ -0,0 +1,67 @@
#include <cmath>
#include <citro3d.h>
#include "starlight/datatypes/Color.h"
#include "starlight/GFXManager.h"
#include "DrawContextCanvas.h"
using starlight::Vector2;
using starlight::VRect;
using starlight::Color;
using starlight::GFXManager;
using starlight::gfx::DrawContextCanvas;
using starlight::gfx::RenderCore;
using starlight::gfx::CRenderTarget;
DrawContextCanvas::DrawContextCanvas(VRect rect) : DrawContext(rect) {
target = std::make_unique<CRenderTarget>(rect.size.x, rect.size.y);
}
DrawContextCanvas::DrawContextCanvas(Vector2 size) : DrawContextCanvas(VRect(Vector2::zero, size)) { }
DrawContextCanvas::~DrawContextCanvas() {
// hmm. don't think we need to do anything here anymore
}
// drawcontext stuff
void DrawContextCanvas::Open() { }
void DrawContextCanvas::Close() {
drawReady = false;
}
bool DrawContextCanvas::Prepare() {
if (drawReady) return true;
drawReady = true;
target->BindTarget();
return true;
}
void DrawContextCanvas::Clear(Color color) {
target->Clear(color);
}
void DrawContextCanvas::Clear() { Clear(Color(0,0,0,0)); }
// drawable stuff
void DrawContextCanvas::Draw(const Vector2& position, const Vector2& origin, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, const Vector2& scale) {
if (GFXManager::PrepareForDrawing()) {
target->Bind(color ? color.get() : Color(1,1,1,1));
const VRect& sr = sampleRect ? sampleRect.get() : this->rect;
VRect rect(position - origin * scale, sr.size * scale);
RenderCore::DrawQuad(rect, position, rotation, sr / target->txSize);
}
}
void DrawContextCanvas::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color) {
if (GFXManager::PrepareForDrawing()) {
target->Bind(color ? color.get() : Color(1,1,1,1));
const VRect& sr = sampleRect ? sampleRect.get() : this->rect;
RenderCore::DrawQuad(rect, sr / target->txSize);
}
}
Vector2 DrawContextCanvas::Size() {
return target->size;
}

View File

@ -0,0 +1,35 @@
#pragma once
#include "starlight/_global.h"
#include <memory>
#include "starlight/gfx/RenderCore.h"
#include "starlight/gfx/Drawable.h"
#include "starlight/gfx/DrawContext.h"
namespace starlight {
namespace gfx {
class DrawContextCanvas : public DrawContext, public Drawable {
private:
std::unique_ptr<CRenderTarget> target;
protected:
void Open() override;
void Close() override;
bool Prepare() override;
public:
DrawContextCanvas(VRect rect);
DrawContextCanvas(Vector2 size);
~DrawContextCanvas();
void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override;
void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) override;
Vector2 Size() override;
void Clear(Color color) override;
void Clear() override;
};
}
}

View File

@ -0,0 +1,27 @@
#include "DrawContextTopScreen.h"
#include "starlight/gfx/RenderCore.h"
#include "starlight/GFXManager.h"
using starlight::GFXManager;
using starlight::gfx::DrawContextTopScreen;
void DrawContextTopScreen::Open() {
// meh
}
void DrawContextTopScreen::Close() {
drawReady = false;
}
bool DrawContextTopScreen::Prepare() {
if (drawReady) return true;
drawReady = true;
if (GFXManager::parallax > 0) // I think this is right?
RenderCore::targetTopRight->BindTarget();
else
RenderCore::targetTopLeft->BindTarget();
return true;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "starlight/_global.h"
#include "starlight/gfx/DrawContext.h"
namespace starlight {
namespace gfx {
class DrawContextTopScreen : public DrawContext {
protected:
void Open() override;
void Close() override;
bool Prepare() override;
public:
DrawContextTopScreen() : DrawContext(VRect(0, 0, 320, 240)) { }
~DrawContextTopScreen() { }
};
}
}

View File

@ -0,0 +1,22 @@
#include "starlight/gfx/RenderCore.h"
#include "DrawContextTouchscreen.h"
using starlight::gfx::DrawContextTouchscreen;
void DrawContextTouchscreen::Open() {
// meh
}
void DrawContextTouchscreen::Close() {
drawReady = false;
}
bool DrawContextTouchscreen::Prepare() {
if (drawReady) return true;
drawReady = true;
RenderCore::targetBottom->BindTarget();
return true;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "starlight/_global.h"
#include "starlight/gfx/DrawContext.h"
namespace starlight {
namespace gfx {
class DrawContextTouchscreen : public DrawContext {
protected:
void Open() override;
void Close() override;
bool Prepare() override;
public:
DrawContextTouchscreen() : DrawContext(VRect(0, 0, 320, 240)) { }
~DrawContextTouchscreen() { }
};
}
}

View File

@ -0,0 +1,5 @@
#include "Drawable.h"
using starlight::gfx::Drawable;
//

View File

@ -0,0 +1,32 @@
#pragma once
#include "starlight/_global.h"
#include "starlight/datatypes/Vector2.h"
#include "starlight/datatypes/VRect.h"
#include "starlight/datatypes/Color.h"
#include "starlight/datatypes/OptRef.h"
namespace starlight {
namespace gfx {
class Drawable {
public:
Drawable() { }
virtual ~Drawable() { }
// pattern after:
// public abstract void Draw(DrawContext context, PxRect rect, PxRect? sampleRect = null, DrawColor? color = null);
// public abstract void Draw(DrawContext context, FxVector position, FxVector? align = null, PxRect? sampleRect = null, DrawColor? color = null, float rotation = 0, FxVector? scale = null);
virtual void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) = 0;
void Draw(const Vector2& position, OptRef<Vector2> hotspot, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, float scale) {
Draw(position, hotspot, sampleRect, color, rotation, Vector2(scale, scale));
}
virtual void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) = 0;
virtual Vector2 Size() = 0;
};
}
}

View File

@ -0,0 +1,37 @@
#include <cstdio>
#include <cmath>
#include "starlight/datatypes/Color.h"
#include "starlight/GFXManager.h"
#include "DrawableImage.h"
using starlight::Vector2;
using starlight::VRect;
using starlight::Color;
using starlight::GFXManager;
using starlight::gfx::DrawableImage;
using starlight::gfx::RenderCore;
using starlight::gfx::CRenderTarget;
void DrawableImage::Draw(const Vector2& position, const Vector2& origin, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, const Vector2& scale) {
if (GFXManager::PrepareForDrawing()) {
texture->Bind(color ? color.get() : Color(1,1,1,1));
const VRect& sr = sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size);
VRect rect(position - origin * scale, sr.size * scale);
RenderCore::DrawQuad(rect, position, rotation, sr / texture->txSize);
}
}
void DrawableImage::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color) {
if (GFXManager::PrepareForDrawing()) {
texture->Bind(color ? color.get() : Color(1,1,1,1));
const VRect& sr = sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size);
RenderCore::DrawQuad(rect, sr / texture->txSize);
}
}
Vector2 DrawableImage::Size() {
return texture->size;
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "starlight/_global.h"
#include <memory>
#include "starlight/gfx/Drawable.h"
#include "starlight/gfx/RenderCore.h"
namespace starlight {
namespace gfx {
class DrawableImage : public Drawable {
public:
std::unique_ptr<CTexture> texture;
DrawableImage(CTexture* texture) : texture(texture) { }
~DrawableImage() override { }
void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override;
void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) override;
Vector2 Size() override;
};
}
}

View File

@ -0,0 +1,47 @@
#include <cstdio>
#include <cmath>
#include "starlight/datatypes/Color.h"
#include "starlight/GFXManager.h"
#include "DrawableNinePatch.h"
using starlight::Vector2;
using starlight::VRect;
using starlight::Color;
using starlight::GFXManager;
using starlight::gfx::DrawableNinePatch;
using starlight::gfx::RenderCore;
using starlight::gfx::CRenderTarget;
void DrawableNinePatch::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color) {
if (GFXManager::PrepareForDrawing()) {
texture->Bind(color ? color.get() : Color(1,1,1,1));
VRect rr = rect.IntSnap();
const VRect& sr = (sampleRect ? sampleRect.get() : VRect(Vector2::zero, texture->size)).IntSnap();
// here comes the fun, doo doot doo doo~
Vector2 m = Vector2::one / texture->txSize;
// top left
RenderCore::DrawQuad(rr.TopEdge(margin.y).LeftEdge(margin.x), sr.TopEdge(margin.y).LeftEdge(margin.x) * m);
// top
RenderCore::DrawQuad(rr.TopEdge(margin.y).Expand(-margin.x, 0), sr.TopEdge(margin.y).Expand(-margin.x, 0) * m);
// top right
RenderCore::DrawQuad(rr.TopEdge(margin.y).RightEdge(margin.x), sr.TopEdge(margin.y).RightEdge(margin.x) * m);
// left
RenderCore::DrawQuad(rr.Expand(0, -margin.y).LeftEdge(margin.x), sr.Expand(0, -margin.y).LeftEdge(margin.x) * m);
// center
RenderCore::DrawQuad(rr.Expand(-margin.x, -margin.y), sr.Expand(-margin.x, -margin.y) * m);
// right
RenderCore::DrawQuad(rr.Expand(0, -margin.y).RightEdge(margin.x), sr.Expand(0, -margin.y).RightEdge(margin.x) * m);
// bottom left
RenderCore::DrawQuad(rr.BottomEdge(margin.y).LeftEdge(margin.x), sr.BottomEdge(margin.y).LeftEdge(margin.x) * m);
// bottom
RenderCore::DrawQuad(rr.BottomEdge(margin.y).Expand(-margin.x, 0), sr.BottomEdge(margin.y).Expand(-margin.x, 0) * m);
// bottom right
RenderCore::DrawQuad(rr.BottomEdge(margin.y).RightEdge(margin.x), sr.BottomEdge(margin.y).RightEdge(margin.x) * m);
// probably could be done with a bit less math, but preoptimization etc. etc.
}
}//*/

View File

@ -0,0 +1,22 @@
#pragma once
#include "starlight/_global.h"
#include <memory>
#include "starlight/gfx/Drawable.h"
#include "starlight/gfx/DrawableImage.h"
#include "starlight/gfx/RenderCore.h"
namespace starlight {
namespace gfx {
class DrawableNinePatch : public DrawableImage {
public:
Vector2 margin;
DrawableNinePatch(CTexture* texture) : DrawableImage (texture) { }
~DrawableNinePatch() override { }
//void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override;
void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) override;
};
}
}

View File

@ -0,0 +1,27 @@
#include "starlight/datatypes/Color.h"
#include "starlight/GFXManager.h"
#include "starlight/gfx/RenderCore.h"
#include "DrawableTest.h"
using starlight::Color;
using starlight::GFXManager;
using starlight::gfx::DrawableTest;
using starlight::gfx::RenderCore;
void DrawableTest::Draw(const Vector2& position, const Vector2& origin, OptRef<VRect> sampleRect, OptRef<Color> color, float rotation, const Vector2& scale) {
if (GFXManager::PrepareForDrawing()) {
//static u32 col = Color(0, 0.5f, 1);
//sf2d_draw_rectangle_rotate(position.x, position.y, 16, 16, col, rotation);
}
}
void DrawableTest::Draw(const VRect& rect, OptRef<VRect> sampleRect, OptRef<Color> color) {
if (GFXManager::PrepareForDrawing()) {
RenderCore::BindColor(color ? color.get() : Color(1,1,1,1));
RenderCore::DrawQuad(rect, VRect());
}
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "starlight/_global.h"
#include "starlight/gfx/Drawable.h"
namespace starlight {
namespace gfx {
class DrawableTest : public Drawable {
public:
DrawableTest() { }
~DrawableTest() override { }
void Draw(const Vector2& position, const Vector2& origin = Vector2::zero, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr, float rotation = 0, const Vector2& scale = Vector2::one) override;
void Draw(const VRect& rect, OptRef<VRect> sampleRect = nullptr, OptRef<Color> color = nullptr) override;
Vector2 Size() override { return Vector2::zero; }
};
}
}

View File

@ -0,0 +1,5 @@
#include "Font.h"
using starlight::gfx::Font;
//

View File

@ -0,0 +1,31 @@
#pragma once
#include "starlight/_global.h"
#include <string>
#include "starlight/datatypes/Vector2.h"
#include "starlight/datatypes/VRect.h"
#include "starlight/datatypes/Color.h"
#include "starlight/datatypes/OptRef.h"
#include "starlight/gfx/DisplayList.h"
namespace starlight {
namespace gfx {
class Font {
public:
static constexpr const int defaultSize = 16;
Font() { }
virtual ~Font() { }
virtual Vector2 Measure(std::string& text, float scale = 1, float maxWidth = 400) = 0;
virtual void Print(Vector2 position, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0;
virtual void Print(VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0;
virtual void PrintDisplayList(DisplayList* dl, Vector2 position, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0;
virtual void PrintDisplayList(DisplayList* dl, VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0;
};
}
}

View File

@ -0,0 +1,138 @@
#include <string>
#include <sstream>
#include <vector>
#include <list>
#include <cmath>
#include "starlight/GFXManager.h"
#include "FontBMF.h"
using starlight::Vector2;
using starlight::VRect;
using starlight::GFXManager;
using starlight::gfx::Font;
using starlight::gfx::FontBMF;
#define err(nth, wat) *((unsigned int*)0x00100000+(nth))=wat;
#define ded(wat) err(0,wat)
Vector2 FontBMF::Measure(std::string& text, float scale, float maxWidth) {
Vector2 v;
PrintOp(Vector2(), text, scale, Color(), Vector2(), nullptr, maxWidth, &v, static_cast<DisplayList*>(nullptr));
return v;
}
void FontBMF::Print(Vector2 position, std::string& text, float scale, Color color, Vector2 justification, OptRef<Color> borderColor) {
if (GFXManager::PrepareForDrawing()) {
DisplayList dl = DisplayList();
PrintOp(position, text, scale, color, justification, borderColor, 2147483647, static_cast<Vector2*>(nullptr), &dl);
if (borderColor && borderColor.get() != Color::transparent && font->txBorder) {
font->txBorder->Bind(borderColor.get());
dl.Run(position);
}
font->txMain->Bind(color);
dl.Run(position);
}
}
void FontBMF::Print(VRect rect, std::string& text, float scale, Color color, Vector2 justification, OptRef<Color> borderColor) {
if (GFXManager::PrepareForDrawing()) {
if (borderColor && borderColor.get() != Color::transparent) rect = rect.Expand(-1, -1);
Vector2 pos = rect.pos + rect.size * justification;
DisplayList dl = DisplayList();
PrintOp(pos, text, scale, color, justification, borderColor, rect.size.x, static_cast<Vector2*>(nullptr), &dl);
if (borderColor && borderColor.get() != Color::transparent && font->txBorder) {
font->txBorder->Bind(borderColor.get());
dl.Run(pos);
}
font->txMain->Bind(color);
dl.Run(pos);
}
}
void FontBMF::PrintDisplayList(DisplayList* dl, Vector2 position, std::string& text, float scale, Color color, Vector2 justification, OptRef<Color> borderColor) {
}
void FontBMF::PrintDisplayList(DisplayList* dl, VRect rect, std::string& text, float scale, Color color, Vector2 justification, OptRef<Color> borderColor) {
// this bind is super kludge ;.;
bool drawBorder = (borderColor && borderColor.get() != Color::transparent);
if (drawBorder) rect = rect.Expand(-1, -1);
Vector2 pos = rect.pos + rect.size * justification;
dl->offset = pos - rect.pos;
if (drawBorder) dl->AddFunc([fnt = std::weak_ptr<BitmapFont>(font), c = borderColor.get()](Vector2 offset) mutable {
if (auto f = fnt.lock()) f->txBorder->Bind(c);
});
else dl->AddFunc([fnt = std::weak_ptr<BitmapFont>(font), c = color](Vector2 offset) mutable {
if (auto f = fnt.lock()) f->txMain->Bind(c);
});
PrintOp(pos, text, scale, color, justification, borderColor, rect.size.x, static_cast<Vector2*>(nullptr), dl);
if (drawBorder) {
auto vlist = dl->GetLastNode<DLNode_Quads>();
dl->AddFunc([fnt = std::weak_ptr<BitmapFont>(font), c = color](Vector2 offset) mutable {
if (auto f = fnt.lock()) f->txMain->Bind(c);
});
dl->AddNode(vlist);
}
}
void FontBMF::PrintOp(Vector2 position, std::string& text, float scale, const Color& color, Vector2 justification, OptRef<Color> borderColor, float maxWidth, Vector2* measure, DisplayList* dl) {
float lineHeight = font->lineHeight * scale;
float spaceWidth = font->Char(' ').advX * scale;
float longest = 0;
std::vector<std::list<std::string>> ptree;
std::vector<float> lwidth;
{
std::stringstream ss(text);
std::string line, word;
// prepare line buffer
ptree.push_back(std::list<std::string>());
auto* cline = &ptree.back();
float cLineLen = -spaceWidth;
// split into words and lines
while(getline(ss, line, '\n')) {
std::stringstream ls(line);
while (getline(ls, word, ' ')) {
float ww = spaceWidth + font->DrawText(Vector2(), word, scale);
if (cLineLen + ww > maxWidth) {
lwidth.push_back(cLineLen);
ptree.push_back(std::list<std::string>());
cline = &ptree.back();
if (cLineLen > longest) longest = cLineLen;
cLineLen = -spaceWidth;
}
cLineLen += ww;
cline->push_back(word);
//
}
lwidth.push_back(cLineLen);
ptree.push_back(std::list<std::string>());
cline = &ptree.back();
if (cLineLen > longest) longest = cLineLen;
cLineLen = -spaceWidth;
}
}
if (measure) { // measurement operation
*measure = Vector2(longest, lwidth.size() * lineHeight);
}
if (!dl) return;
//Vector2 lp = position - Vector2(0, lwidth.size() * lineHeight) * justification;
Vector2 lp = -Vector2(0, lwidth.size() * lineHeight) * justification;
lp.y -= lineHeight - font->baseY * scale;
lp.x = floor(lp.x); lp.y = floor(lp.y); // normalize across zero-crossings
int li = 0;
for (auto& line : ptree) {
Vector2 wp = lp - Vector2(lwidth[li], 0) * justification;
for (auto& word : line) {
wp.x += spaceWidth + font->DrawText(wp, word, scale, dl);
}
lp += Vector2(0, lineHeight);
li++;
}
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "starlight/_global.h"
#include <memory>
#include "starlight/gfx/BitmapFont.h"
#include "starlight/gfx/Font.h"
namespace starlight {
namespace gfx {
class FontBMF : public Font {
private:
void PrintOp(Vector2 position, std::string& text, float scale, const Color& color, Vector2 justification, OptRef<Color> borderColor, float maxWidth, Vector2* measure, DisplayList* dl);
public:
std::shared_ptr<BitmapFont> font;
FontBMF() { }
~FontBMF() { }
Vector2 Measure(std::string& text, float scale = 1, float maxWidth = 400) override;
void Print(Vector2 position, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override;
void Print(VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override;
void PrintDisplayList(DisplayList* dl, Vector2 position, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override;
void PrintDisplayList(DisplayList* dl, VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override;
};
}
}

View File

@ -0,0 +1,274 @@
#include <cstdio>
#include <cmath>
#include <3ds.h>
#include <citro3d.h>
#include "starlight/datatypes/Vector2.h"
#include "starlight/datatypes/VRect.h"
#include "starlight/datatypes/Color.h"
#include "basic_shader_shbin.h"
#include "RenderCore.h"
using starlight::Vector2;
using starlight::VRect;
using starlight::Color;
using starlight::util::WorkerThread;
using starlight::gfx::CTexture;
using starlight::gfx::CRenderTarget;
using starlight::gfx::RenderCore;
namespace { // internals
typedef struct {
float x, y, z, u, v;
} vbo_xyzuv;
void setXYZUV(vbo_xyzuv& vbo, float x, float y, float z, float u, float v) {
vbo.x = x;
vbo.y = y;
vbo.z = z;
vbo.u = u;
vbo.v = v;
}
void setXYZUV(vbo_xyzuv& vbo, Vector2 xy, Vector2 uv) { setXYZUV(vbo, xy.x, xy.y, 0, uv.x, uv.y); }
void* bufferStart = nullptr;
size_t bufferInd = 0;
size_t bufferSize = 0;
DVLB_s* dvlb = nullptr;
shaderProgram_s shader;
int sLocProjection = -1;
void ResetBuffer() { bufferInd = 0; }
void* AllocBuffer(size_t size, size_t align = 1) {
bufferInd += align - (bufferInd % align); // prealign
void* b = reinterpret_cast<void*>(reinterpret_cast<size_t>(bufferStart) + bufferInd);
bufferInd += size;
if (bufferInd > bufferSize) return nullptr;
return b;
}
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
}
class CRawTexture : public CTexture {
friend class starlight::gfx::RenderCore;
protected:
C3D_Tex* texture;
public:
CRawTexture(int width, int height) {
size = Vector2(width, height);
auto w = NextPow2(width), h = NextPow2(height);
txSize = Vector2(w, h);
texture = new C3D_Tex();
C3D_TexInit(texture, w, h, GPU_RGBA8);
}
~CRawTexture() override {
C3D_TexDelete(texture);
delete texture;
}
void Bind(Color color = Color::white) override {
RenderCore::BindTexture(texture, color);
}
};
}
//WorkerThread RenderCore::loadingThread;
std::unique_ptr<CRenderTarget> RenderCore::targetTopLeft = nullptr;
std::unique_ptr<CRenderTarget> RenderCore::targetTopRight = nullptr;
std::unique_ptr<CRenderTarget> RenderCore::targetBottom = nullptr;
void RenderCore::Open() {
gfxInitDefault();
gfxSet3D(true);
C3D_Init(0x80000*8);
bufferSize = 0x80000;
bufferStart = linearAlloc(bufferSize);
bufferInd = 0;
// set up screen targets
targetTopLeft = std::make_unique<CRenderTarget>(240, 400, true);
targetTopRight = std::make_unique<CRenderTarget>(240, 400, true);
targetBottom = std::make_unique<CRenderTarget>(240, 320, true);
C3D_RenderTargetSetOutput(targetTopLeft->tgt, GFX_TOP, GFX_LEFT, 0x1000);
C3D_RenderTargetSetOutput(targetTopRight->tgt, GFX_TOP, GFX_RIGHT, 0x1000);
C3D_RenderTargetSetOutput(targetBottom->tgt, GFX_BOTTOM, GFX_LEFT, 0x1000);
Mtx_OrthoTilt(&targetTopLeft->projection, 0.0f, 400, 240, 0.0f, 0.0f, 1.0f, true);
Mtx_OrthoTilt(&targetTopRight->projection, 0.0f, 400, 240, 0.0f, 0.0f, 1.0f, true);
Mtx_OrthoTilt(&targetBottom->projection, 0.0f, 320, 240, 0.0f, 0.0f, 1.0f, true);
// shader and company
dvlb = DVLB_ParseFile((u32*)basic_shader_shbin, basic_shader_shbin_size);
shaderProgramInit(&shader);
shaderProgramSetVsh(&shader, &dvlb->DVLE[0]);
C3D_BindProgram(&shader);
sLocProjection = shaderInstanceGetUniformLocation(shader.vertexShader, "projection");
// set up mode defaults
C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); // premult
C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL); // hmm.
C3D_CullFace(GPU_CULL_NONE);
}
void RenderCore::Close() {
targetTopLeft.reset(nullptr);
targetTopRight.reset(nullptr);
targetBottom.reset(nullptr);
linearFree(bufferStart);
C3D_Fini();
gfxExit();
}
void RenderCore::BeginFrame() {
ResetBuffer();
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
}
void RenderCore::EndFrame() {
C3D_FrameEnd(0);
}
void RenderCore::BindTexture(C3D_Tex* tex, const Color& color) {
C3D_TexBind(0, tex); // 0 should be correct
C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0, GPU_CONSTANT, 0);
C3D_TexEnvOp(env, C3D_RGB, 0, 0, 0);
C3D_TexEnvOp(env, C3D_Alpha, GPU_TEVOP_A_SRC_ALPHA, GPU_TEVOP_A_SRC_ALPHA, 0);
C3D_TexEnvFunc(env, C3D_RGB, GPU_MODULATE);//REPLACE); // let's see...
C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE);
C3D_TexEnvColor(env, color.Premultiplied());
}
void RenderCore::BindColor(const Color& color) {
C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvSrc(env, C3D_Both, GPU_CONSTANT, 0, 0);
C3D_TexEnvOp(env, C3D_RGB, 0, 0, 0);
C3D_TexEnvOp(env, C3D_Alpha, GPU_TEVOP_A_SRC_ALPHA, 0, 0);
C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);//REPLACE); // let's see...
C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE);
C3D_TexEnvColor(env, color.Premultiplied());
}
void RenderCore::DrawQuad(const VRect& rect, const VRect& src, bool noSnap) {
vbo_xyzuv* verts = static_cast<vbo_xyzuv*>(AllocBuffer(4 * sizeof(vbo_xyzuv), 8));
VRect r = noSnap ? rect : rect.IntSnap(); // screen-space snap
/*setXYZUV(verts[0], r.TopLeft(), src.TopLeft());
setXYZUV(verts[1], r.TopRight(), src.TopRight());
setXYZUV(verts[2], r.BottomLeft(), src.BottomLeft());
setXYZUV(verts[3], r.BottomRight(), src.BottomRight());*/
// let's make this recalculate things a bit less
float rl = r.pos.x, rr = rl + r.size.x, rt = r.pos.y, rb = rt + r.size.y;
float srl = src.pos.x, srr = srl + src.size.x, srt = src.pos.y, srb = srt + src.size.y;
setXYZUV(verts[0], rl, rt, 0, srl, srt);
setXYZUV(verts[1], rr, rt, 0, srr, srt);
setXYZUV(verts[2], rl, rb, 0, srl, srb);
setXYZUV(verts[3], rr, rb, 0, srr, srb);
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
AttrInfo_Init(attrInfo);
AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2);
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo);
BufInfo_Add(bufInfo, verts, sizeof(vbo_xyzuv), 2, 0x10);
C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 4);
}
void RenderCore::DrawQuad(const VRect& rect, const Vector2& anchor, float angle, const VRect& src) {
vbo_xyzuv* verts = static_cast<vbo_xyzuv*>(AllocBuffer(4 * sizeof(vbo_xyzuv), 8));
setXYZUV(verts[0], rect.TopLeft().RotateAround(anchor, angle), src.TopLeft());
setXYZUV(verts[1], rect.TopRight().RotateAround(anchor, angle), src.TopRight());
setXYZUV(verts[2], rect.BottomLeft().RotateAround(anchor, angle), src.BottomLeft());
setXYZUV(verts[3], rect.BottomRight().RotateAround(anchor, angle), src.BottomRight());
C3D_AttrInfo* attrInfo = C3D_GetAttrInfo();
AttrInfo_Init(attrInfo);
AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3);
AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2);
C3D_BufInfo* bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo);
BufInfo_Add(bufInfo, verts, sizeof(vbo_xyzuv), 2, 0x10);
C3D_DrawArrays(GPU_TRIANGLE_STRIP, 0, 4);
}
// specifically RGBA
CTexture* RenderCore::LoadTexture(void* src, int width, int height) {
// flush to FCRAM
GSPGPU_FlushDataCache(src, width*height*4);
// assemble texture
CRawTexture* tex = new CRawTexture(width, height);
int owidth = tex->txSize.x, oheight = tex->txSize.y;
constexpr u32 flags = (GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | \
GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO));
//C3D_SafeDisplayTransfer(static_cast<u32*>(src), GX_BUFFER_DIM(width, height), static_cast<u32*>(tex->texture->data), GX_BUFFER_DIM(owidth, oheight), flags);
C3D_SafeDisplayTransfer(static_cast<u32*>(src), GX_BUFFER_DIM(width, height), static_cast<u32*>(tex->texture->data), GX_BUFFER_DIM(owidth, oheight), flags);
gspWaitForPPF();
//C3D_TexSetFilter(tex->texture, GPU_LINEAR, GPU_NEAREST);
C3D_TexSetFilter(tex->texture, GPU_LINEAR, GPU_LINEAR); // nearest causes artifacts on ninepatches
C3D_TexSetWrap(tex->texture, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER);
C3D_TexBind(0, tex->texture);
printf("loaded image w %i (%i) h %i (%i)\n", width, owidth, height, oheight);
return tex;
}
///////////////////
// CRenderTarget //
///////////////////
CRenderTarget::CRenderTarget(int width, int height, bool forceExact) {
size = Vector2(width, height);
auto w = forceExact ? width : NextPow2(width),
h = forceExact ? height : NextPow2(height);
txSize = Vector2(w, h);
tgt = C3D_RenderTargetCreate(w, h, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); // though actually, do we really need stenciling? could drop to 16 if we don't
Mtx_Ortho(&projection, 0.0f, w, 0.0f, h, 0.0f, 1.0f, true);
//Mtx_OrthoTilt(&projection, 0.0f, h, 0.0f, w, 0.0f, 1.0f, true);
}
CRenderTarget::~CRenderTarget() {
C3D_RenderTargetDelete(tgt);
}
void CRenderTarget::Clear(Color color) {
unsigned int c = color;
c = ((c>>24)&0x000000FF) | ((c>>8)&0x0000FF00) | ((c<<8)&0x00FF0000) | ((c<<24)&0xFF000000); // reverse endianness
C3D_RenderTargetSetClear(tgt, C3D_CLEAR_ALL, c, 0);
}
void CRenderTarget::BindTarget() {
C3D_FrameDrawOn(tgt);
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, sLocProjection, &projection);
}
void CRenderTarget::Bind(Color color) {
C3D_RenderTargetSetClear(tgt, 0, 0, 0); // don't clear again until marked to
RenderCore::BindTexture(&(tgt->renderBuf.colorBuf), color);
}

View File

@ -0,0 +1,71 @@
#pragma once
#include "starlight/_global.h"
#include <memory>
#include <3ds.h>
#include <citro3d.h>
#include "starlight/datatypes/Vector2.h"
#include "starlight/datatypes/VRect.h"
#include "starlight/datatypes/Color.h"
#include "starlight/util/WorkerThread.h"
namespace starlight {
namespace gfx {
class RenderCore;
class CTexture {
protected:
CTexture() = default;
public:
Vector2 size;
Vector2 txSize;
virtual ~CTexture() = default;
virtual void Bind(Color color = Color::white) = 0;
};
class CRenderTarget : public CTexture {
friend class starlight::gfx::RenderCore;
protected:
C3D_RenderTarget* tgt;
public:
C3D_Mtx projection;
CRenderTarget(int width, int height, bool forceExact = false);
~CRenderTarget();
void Clear(Color color);
void BindTarget();
void Bind(Color color = Color::white) override;
};
class RenderCore {
public:
//static util::WorkerThread loadingThread;
static std::unique_ptr<CRenderTarget> targetTopLeft;
static std::unique_ptr<CRenderTarget> targetTopRight;
static std::unique_ptr<CRenderTarget> targetBottom;
RenderCore() = delete; // static
static void Open();
static void Close();
static void BeginFrame();
static void EndFrame();
static void BindTexture(C3D_Tex* tex, const Color& color);
static void BindColor(const Color& color);
static void DrawQuad(const VRect& rect, const VRect& src, bool noSnap = false);
static void DrawQuad(const VRect& rect, const Vector2& anchor, float angle, const VRect& src);
static CTexture* LoadTexture(void* src, int width, int height);
};
}
}

View File

@ -0,0 +1,58 @@
#pragma once
#include "starlight/_global.h"
#include <string>
#include <memory>
#include "starlight/ThemeManager.h"
namespace starlight {
namespace gfx {
template <class T> class ThemeRef;
template <class T>
class ThemeRefContainer {
friend class starlight::ThemeManager;
friend class ThemeRef<T>;
protected:
const std::string name;
std::shared_ptr<T> ptr = nullptr;
void Unload() {
ptr.reset();
}
ThemeRefContainer(std::string name, std::shared_ptr<T> ptr) : name(name), ptr(ptr) { }
ThemeRefContainer(std::string name, T* ptr) : name(name), ptr(ptr) { }
ThemeRefContainer(std::string name) : name(name) { }
public:
~ThemeRefContainer() { }
T* operator ->() const {
if (ptr == nullptr) {
ThemeManager::Fulfill(const_cast<ThemeRefContainer<T>&>(*this)); // call thememanager to grab things
}
return &*ptr;
}
/*T& operator *() const {
if (ptr == nullptr) {
ThemeManager::Fulfill(const_cast<ThemeRef<T>&>(*this)); // call thememanager to grab things
}
return *ptr;
}*/
};
template <class T>
class ThemeRef {
private:
const ThemeRefContainer<T>* cptr;
public:
ThemeRef() : cptr(nullptr) { }
ThemeRef(ThemeRefContainer<T>* c) : cptr(c) { }
~ThemeRef() { }
inline const ThemeRefContainer<T>& operator ->() const { return *cptr; }
inline explicit operator bool() const { return cptr != nullptr; }
inline std::shared_ptr<T> GetShared() const { return (*cptr).ptr; }
};
}
}

View File

@ -0,0 +1,34 @@
; Uniforms
.fvec projection[4]
; Constants
.constf myconst(0.0, 1.0, -1.0, 0.1)
.constf myconst2(0.3, 0.0, 0.0, 0.0)
.alias zeros myconst.xxxx ; Vector full of zeros
.alias ones myconst.yyyy ; Vector full of ones
; Outputs
.out outpos position
.out outtc0 texcoord0
; Inputs (defined as aliases for convenience)
.alias inpos v0
.alias intex v1
.bool test
.proc main
; Force the w component of inpos to be 1.0
mov r0.xyz, inpos
mov r0.w, ones
; outpos = projectionMatrix * inpos
dp4 outpos.x, projection[0], r0
dp4 outpos.y, projection[1], r0
dp4 outpos.z, projection[2], r0
dp4 outpos.w, projection[3], r0
mov outtc0, intex
end
.end

View File

@ -0,0 +1,67 @@
#include "Button.h"
#include "starlight/InputManager.h"
#include "starlight/GFXManager.h"
#include "starlight/ThemeManager.h"
using starlight::Vector2;
using starlight::Color;
using starlight::gfx::Font;
using starlight::InputManager;
using starlight::GFXManager;
using starlight::ThemeManager;
using starlight::ui::Button;
void Button::SetText(const std::string& text) {
label = text;
MarkForRedraw();
}
void Button::Draw() {
static auto font = ThemeManager::GetFont("default.12");
static auto idle = ThemeManager::GetAsset("button.idle");
static auto press = ThemeManager::GetAsset("button.press");
auto rect = (this->rect + GFXManager::GetOffset()).IntSnap();
if (InputManager::GetDragHandle() == this) {
press->Draw(rect);
} else {
idle->Draw(rect);
}
font->Print(rect, label, 1, Color::white, Vector2(0.5f, 0.5f), Color::black);
}
void Button::OnTouchOn() {
if (InputManager::Pressed(KEY_TOUCH)) {
InputManager::GetDragHandle().Grab(this);
MarkForRedraw();
}
}
void Button::OnTouchOff() {
auto& drag = InputManager::GetDragHandle();
if (drag == this) drag.Release();
}
void Button::OnDragStart() {
// do we need to do anything here?
}
void Button::OnDragHold() {
if (InputManager::TouchDragDist().Length() > InputManager::dragThreshold) {
InputManager::GetDragHandle().PassUp();
}
}
void Button::OnDragRelease() {
if (InputManager::Released(KEY_TOUCH)) {
if (eOnTap) eOnTap(*this);
}
MarkForRedraw();
}

View File

@ -0,0 +1,38 @@
#pragma once
#include "starlight/_global.h"
#include <string>
#include <functional>
#include "starlight/ui/UIElement.h"
namespace starlight {
namespace ui {
class Button : public UIElement {
private:
//
public:
std::string label;
std::function<void(Button&)> eOnTap;
Button(VRect rect) { this->rect = rect; }
Button(Vector2 pos) { this->rect = VRect(pos, Vector2(128, 32)); }
~Button() { }
void SetText(const std::string& text);
void Draw() override;
// events
void OnTouchOn() override;
void OnTouchOff() override;
void OnDragStart() override;
void OnDragRelease() override;
void OnDragHold() override;
};
}
}

View File

@ -0,0 +1,29 @@
#include "Image.h"
#include "starlight/GFXManager.h"
using std::string;
using starlight::GFXManager;
using starlight::ui::Image;
Image::Image(VRect rect, const string& imgPath) {
this->rect = rect;
SetImage(imgPath, false);
}
Image::Image(Vector2 pos, const string& imgPath) {
this->rect = VRect(pos, Vector2::zero);
SetImage(imgPath, true);
}
void Image::SetImage(const string& imgPath, bool resize) {
image = ThemeManager::GetAsset(imgPath);
if (resize) this->Resize(image->Size());
MarkForRedraw();
}
void Image::Draw() {
image->Draw(rect + GFXManager::GetOffset());
}

View File

@ -0,0 +1,32 @@
#pragma once
#include "starlight/_global.h"
#include <string>
#include <memory>
#include "starlight/ThemeManager.h"
#include "starlight/gfx/ThemeRef.h"
#include "starlight/gfx/DrawContextCanvas.h"
#include "starlight/ui/UIElement.h"
namespace starlight {
namespace ui {
class Image : public UIElement {
private:
//
public:
gfx::ThemeRef<gfx::Drawable> image;
Color tint = Color::white;
Image(VRect rect, const std::string& imgPath);
Image(Vector2 pos, const std::string& imgPath);
~Image() override { }
void SetImage(const std::string& imgPath, bool resize = true);
void Draw() override;
};
}
}

View File

@ -0,0 +1,57 @@
#include "Label.h"
#include "starlight/GFXManager.h"
using starlight::GFXManager;
using starlight::ui::Label;
Label::Label(VRect rect) {
this->rect = rect;
font = ThemeManager::GetFont("default.12");
}
void Label::AutoSize() {
if (autoSizeV) {
float h = font->Measure(text, 1, rect.size.x).y;
Resize(rect.size.x, h);
}
buffer.reset();
MarkForRedraw();
}
void Label::SetText(const std::string& text) {
this->text = text;
AutoSize();
}
void Label::SetFont(const std::string& fontName) {
font = ThemeManager::GetFont(fontName);
AutoSize();
}
void Label::PreDrawOffscreen() {
buffer.reset(); // I guess?
}
void Label::PreDraw() {
if (!buffer && text.length() > 64) {
buffer = std::make_unique<gfx::DrawContextCanvas>(rect.size + Vector2(0, 8));
buffer->Clear();
GFXManager::PushContext(buffer.get());
font->Print(buffer->rect, text, 1, color, justification, borderColor);
GFXManager::PopContext();
}
}
void Label::Draw() {
auto rect = (this->rect + GFXManager::GetOffset()).IntSnap();
if (buffer) {
buffer->Draw(VRect(rect.pos, buffer->rect.size));
} else {
font->Print(rect, text, 1, color, justification, borderColor);
}
}

View File

@ -0,0 +1,43 @@
#pragma once
#include "starlight/_global.h"
#include <string>
#include <memory>
#include "starlight/ThemeManager.h"
#include "starlight/gfx/ThemeRef.h"
#include "starlight/gfx/DrawContextCanvas.h"
#include "starlight/ui/UIElement.h"
namespace starlight {
namespace ui {
class Label : public UIElement {
private:
void AutoSize();
public:
std::string text = "";
gfx::ThemeRef<gfx::Font> font;
std::unique_ptr<gfx::DrawContextCanvas> buffer;
Color color = Color::white;
Color borderColor = Color::transparent;
bool autoSizeV = false;
Vector2 justification = Vector2::half;
Label(VRect rect);
~Label() override { }
void SetText(const std::string& text);
void SetFont(const std::string& fontName);
void PreDrawOffscreen() override;
void PreDraw() override;
void Draw() override;
};
}
}

View File

@ -0,0 +1,15 @@
#include "ParallaxLayer.h"
#include "starlight/GFXManager.h"
using starlight::Vector2;
using starlight::GFXManager;
using starlight::ui::UIContainer;
using starlight::ui::ParallaxLayer;
void ParallaxLayer::Draw() {
scrollOffset = Vector2(GFXManager::parallax * -depth, 0);
this->UIContainer::Draw();
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "starlight/_global.h"
#include "starlight/ui/UIContainer.h"
namespace starlight {
namespace ui {
class ParallaxLayer : public UIContainer {
public:
float depth = 0;
ParallaxLayer() { this->rect = VRect(0,0,400,240); } // screen size
~ParallaxLayer() { }
void Draw() override;
};
}
}

View File

@ -0,0 +1,75 @@
#include "ScrollField.h"
#include <algorithm>
#include "starlight/InputManager.h"
#include "starlight/GFXManager.h"
#include "starlight/ThemeManager.h"
using starlight::Vector2;
using starlight::Color;
using starlight::gfx::Font;
using starlight::InputManager;
using starlight::GFXManager;
using starlight::ThemeManager;
using starlight::ui::ScrollField;
void ScrollField::Update() {
VRect contents(0,0,0,0);
for (auto& it : children) {
it->Update();
contents = contents.Include(it->rect.BottomRight());
}
scrollMax = contents.size - rect.size;
scrollMax.x = std::max(0.0f, scrollMax.x);
scrollMax.y = std::max(0.0f, scrollMax.y);
scrollOffset += scrollVel;
scrollVel *= 0.932f;
if (scrollVel.Length() < 0.1f) {
scrollVel = Vector2::zero;
scrollOffset = scrollOffset.IntSnap();
} else MarkForRedraw();
scrollOffset.x = std::max(0.0f, std::min(scrollOffset.x, scrollMax.x));
scrollOffset.y = std::max(0.0f, std::min(scrollOffset.y, scrollMax.y));
}
void ScrollField::OnProcessTouchEvent() { // stop when child element touched
if (InputManager::Pressed(KEY_TOUCH)) scrollVel = Vector2::zero;
}
void ScrollField::OnTouchOn() {
if (InputManager::Pressed(KEY_TOUCH)) {
InputManager::GetDragHandle().Grab(this);
}
}
bool ScrollField::OnDragPassed() {
scrollOffset -= InputManager::TouchDragDist() - InputManager::TouchDelta();
return true;
}
void ScrollField::OnDragStart() {
scrollPreVel = Vector2::zero;
}
void ScrollField::OnDragHold() {
scrollVel = Vector2::zero;
scrollPreVel = -InputManager::TouchDelta();
scrollOffset -= InputManager::TouchDelta();
if (InputManager::TouchDelta().Length() > 0) MarkForRedraw();
//printf("scroll? (%f, %f); (%f, %f)\n", scrollOffset.x, scrollOffset.y, scrollMax.x, scrollMax.y);
}
void ScrollField::OnDragRelease() {
if (InputManager::Released(KEY_TOUCH)) {
if (scrollPreVel.Length() < InputManager::flingThreshold) scrollPreVel = Vector2::zero;
scrollVel = scrollPreVel;
}
}

View File

@ -0,0 +1,36 @@
#pragma once
#include "starlight/_global.h"
#include "starlight/ui/UICanvas.h"
namespace starlight {
namespace ui {
class ScrollField : public UICanvas {
public:
Vector2 scrollMax = Vector2::zero;
Vector2 scrollVel = Vector2::zero;
Vector2 scrollPreVel = Vector2::zero;
ScrollField(VRect rect) : UICanvas(rect) { }
~ScrollField() { }
void Update() override;
// events
void OnTouchOn() override;
void OnTouchOff() override { }
void OnTouchHold() override { }
void OnProcessTouchEvent() override;
bool InterceptsTouch(Vector2 where) override { return true; }
bool OnDragPassed() override;
void OnDragStart() override;
void OnDragRelease() override;
void OnDragHold() override;
};
}
}

View File

@ -0,0 +1,55 @@
#include "starlight/InputManager.h"
#include "starlight/GFXManager.h"
#include "starlight/ThemeManager.h"
#include "starlight/gfx/DrawContextTopScreen.h"
#include "TopScreenCanvas.h"
using starlight::Vector2;
using starlight::VRect;
//using starlight::gfx::Drawable;
using starlight::gfx::DrawContext;
using starlight::gfx::DrawContextTopScreen;
using starlight::ui::UIElement;
using starlight::ui::UIContainer;
using starlight::ui::UICanvas;
using starlight::ui::TopScreenCanvas;
TopScreenCanvas::TopScreenCanvas() {
rect = VRect(0, 0, 320, 240);
drawContext = std::make_unique<DrawContextTopScreen>();
}
void TopScreenCanvas::Update() {
// for now just update children
this->UIContainer::Update();
}
void TopScreenCanvas::PreDraw() {
this->UIContainer::PreDraw();
}
void TopScreenCanvas::Draw() {
float depth = InputManager::DepthSlider();
// left frame
GFXManager::parallax = depth;
GFXManager::PushContext(drawContext.get());
this->UIContainer::Draw();
GFXManager::PrepareForDrawing(); // force clear if not drawn to
GFXManager::PopContext();
if (depth > 0) { // right frame
GFXManager::parallax = -depth;
GFXManager::PushContext(drawContext.get());
this->UIContainer::Draw();
GFXManager::PrepareForDrawing(); // force clear if not drawn to
GFXManager::PopContext();
}
// reset parallax
GFXManager::parallax = 0;
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "starlight/_global.h"
#include "starlight/ui/UICanvas.h"
namespace starlight {
namespace ui {
class TopScreenCanvas : public UICanvas {
public:
TopScreenCanvas();
~TopScreenCanvas() { }
void Update() override;
void PreDraw() override;
void Draw() override;
};
}
}

View File

@ -0,0 +1,87 @@
#include "starlight/InputManager.h"
#include "starlight/GFXManager.h"
#include "starlight/ThemeManager.h"
#include "starlight/gfx/DrawContextTouchscreen.h"
#include "TouchScreenCanvas.h"
using starlight::Vector2;
using starlight::VRect;
//using starlight::gfx::Drawable;
using starlight::gfx::DrawContext;
using starlight::gfx::DrawContextTouchscreen;
using starlight::ui::UIElement;
using starlight::ui::UIContainer;
using starlight::ui::UICanvas;
using starlight::ui::TouchScreenCanvas;
TouchScreenCanvas::TouchScreenCanvas() : touchedNow(&this->_touched1), touchedLast(&this->_touched2) {
rect = VRect(0, 0, 320, 240);
drawContext = std::make_unique<DrawContextTouchscreen>();
//touchedNow = _touched1;
//touchedLast = _touched2;
}
void TouchScreenCanvas::Update() {
std::swap(touchedLast, touchedNow);
touchedNow->clear();
// scan input
Vector2 tpos = InputManager::TouchPos();
auto& drag = InputManager::GetDragHandle();
if (!drag.valid() && InputManager::Held(KEY_TOUCH)) {
Dive(
[&tpos](UIElement* e){
if (e->ScreenRect().Contains(tpos)) {
e->OnProcessTouchEvent();
return true;
} return false;
},
[&tpos, this](UIElement* e){
touchedNow->insert({e, std::weak_ptr<UIElement>(e->shared_from_this())});
return e->InterceptsTouch(tpos - e->ScreenRect().pos);
}, true, true);
} else if (drag.valid()) {
UIElement* e = drag.get();
if (InputManager::Held(KEY_TOUCH) && e != nullptr) {
if (e->ScreenRect().Contains(tpos)) {
touchedNow->insert({e, std::weak_ptr<UIElement>(e->shared_from_this())});
}
e->OnDragHold();
} else {
drag.Release();
}
}
for (auto& it : *touchedLast) {
if (touchedNow->find(it.first) == touchedNow->end()) { // released
if (auto e = it.second.lock()) {
e->OnTouchOff();
}
}
}
for (auto& it : *touchedNow) {
if (auto e = it.second.lock()) {
if (touchedLast->find(it.first) == touchedLast->end()) e->OnTouchOn();
else e->OnTouchHold();
}
}
// and update children
this->UIContainer::Update();
}
void TouchScreenCanvas::PreDraw() {
this->UIContainer::PreDraw();
}
void TouchScreenCanvas::Draw() {
GFXManager::PushContext(drawContext.get());
this->UIContainer::Draw();
GFXManager::PrepareForDrawing(); // force clear if not drawn to
GFXManager::PopContext();
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "starlight/_global.h"
#include <unordered_map>
#include <memory>
#include "starlight/ui/UICanvas.h"
namespace starlight {
namespace ui {
class TouchScreenCanvas : public UICanvas {
private:
std::unordered_map<UIElement*, std::weak_ptr<UIElement>> _touched1 = std::unordered_map<UIElement*, std::weak_ptr<UIElement>>();
std::unordered_map<UIElement*, std::weak_ptr<UIElement>> _touched2 = std::unordered_map<UIElement*, std::weak_ptr<UIElement>>();
std::unordered_map<UIElement*, std::weak_ptr<UIElement>>* touchedNow = &this->_touched1;
std::unordered_map<UIElement*, std::weak_ptr<UIElement>>* touchedLast = &this->_touched2;
public:
TouchScreenCanvas();
~TouchScreenCanvas() { }
void Update() override;
void PreDraw() override;
void Draw() override;
};
}
}

View File

@ -0,0 +1,54 @@
#include "starlight/GFXManager.h"
#include "starlight/gfx/DrawContextCanvas.h"
#include "UICanvas.h"
using starlight::gfx::Drawable;
using starlight::gfx::DrawContext;
using starlight::gfx::DrawContextCanvas;
using starlight::ui::UIElement;
using starlight::ui::UIContainer;
using starlight::ui::UICanvas;
UICanvas::UICanvas(VRect rect) {
this->rect = rect;
}
void UICanvas::MarkForRedraw() {
needsRedraw = true;
this->UIElement::MarkForRedraw();
}
void UICanvas::PreDrawOffscreen() {
if (drawContext) {
drawContext.reset();
for (auto& it : children) { it->PreDrawOffscreen(); }
}
}
void UICanvas::PreDraw() {
if (!drawContext) drawContext = std::make_unique<starlight::gfx::DrawContextCanvas>(rect.size);
else if (!needsRedraw) return;
drawContext->Clear();
GFXManager::PushContext(drawContext.get());
GFXManager::PushOffsetAdd(-scrollOffset);
VRect vr = ViewportRect();
// both passes here so as not to mix things; one rendertarget at a time, please
for (auto& it : children) { if (it->rect.Overlaps(vr)) it->PreDraw(); else it->PreDrawOffscreen(); }
for (auto& it : children) { if (it->rect.Overlaps(vr)) it->Draw(); }
GFXManager::PopOffset();
GFXManager::PopContext();
needsRedraw = false;
}
void UICanvas::Draw() {
static_cast<DrawContextCanvas*>(drawContext.get())->Draw(rect + GFXManager::GetOffset());
}

View File

@ -0,0 +1,31 @@
#pragma once
#include "starlight/_global.h"
#include "starlight/gfx/DrawContext.h"
#include "starlight/ui/UIContainer.h"
namespace starlight {
namespace ui {
class UICanvas : public UIContainer {
private:
//
protected:
std::unique_ptr<gfx::DrawContext> drawContext;
UICanvas() { }
public:
bool needsRedraw = true;
UICanvas(VRect rect);
~UICanvas() { }
void MarkForRedraw() override;
void PreDrawOffscreen() override;
void PreDraw() override;
void Draw() override;
};
}
}

View File

@ -0,0 +1,85 @@
#include <algorithm>
#include "starlight/GFXManager.h"
#include "UIContainer.h"
using starlight::GFXManager;
using starlight::ui::UIElement;
using starlight::ui::UIContainer;
UIContainer::UIContainer() { }
UIContainer::~UIContainer() { }
void UIContainer::Dive(std::function<bool(UIElement*)> check, std::function<bool(UIElement*)> func, bool consumable, bool frontFirst) {
bool finished = false;
_Dive(check, func, consumable, frontFirst, finished);
}
void UIContainer::Dive(std::function<bool(UIElement*)> func, bool consumable, bool frontFirst) {
bool finished = false;
_Dive(func, consumable, frontFirst, finished);
}
void UIContainer::_Dive(std::function<bool(UIElement*)>& check, std::function<bool(UIElement*)>& func, bool consumable, bool frontFirst, bool& finished) {
if (!check(this)) return; // early out, don't bother checking further branches
if (frontFirst) for (auto itr = children.rbegin(); itr != children.rend(); ++itr) {
(*itr)->_Dive(check, func, consumable, frontFirst, finished);
if (finished) return;
} else for (auto itr = children.begin(); itr != children.end(); ++itr) {
(*itr)->_Dive(check, func, consumable, frontFirst, finished);
if (finished) return;
}
// same thing as plain UIElement's version
finished = func(this) && consumable;
}
void UIContainer::_Dive(std::function<bool(UIElement*)>& func, bool consumable, bool frontFirst, bool& finished) {
if (frontFirst) for (auto itr = children.rbegin(); itr != children.rend(); ++itr) {
(*itr)->_Dive(func, consumable, frontFirst, finished);
if (finished) return;
} else for (auto itr = children.begin(); itr != children.end(); ++itr) {
(*itr)->_Dive(func, consumable, frontFirst, finished);
if (finished) return;
}
// same thing as plain UIElement's version
finished = func(this) && consumable;
}
void UIContainer::Add(std::shared_ptr<UIElement> elem) {
children.push_back(elem);
elem->parent = std::weak_ptr<UIContainer>(std::static_pointer_cast<UIContainer>(this->shared_from_this()));
MarkForRedraw();
}
//void UIContainer::Add(UIElement* elem) {
// as it turns out, you *have* to immediately encapsulate because herp derp shared_from_this doesn't even bother to check
//if (std::shared_ptr<UIElement> ptr = elem->shared_from_this()) this->Add(ptr);
//else this->Add(std::shared_ptr<UIElement>(elem)); // support initial encapsulation
//}
void UIContainer::Remove(std::shared_ptr<UIElement> elem) {
if (elem->parent.lock().get() != this) return;
elem->parent = std::weak_ptr<UIContainer>(); // explicit null expressed in a slightly silly way
//children.remove_if([&elem](std::shared_ptr<UIElement> ie){return ie == elem;});
children.remove(elem); // I think this uses operator ==()?
MarkForRedraw();
}
void UIContainer::Update() {
for (auto& it : children) { it->Update(); }
}
void UIContainer::PreDraw() {
VRect vr = ViewportRect();
for (auto& it : children) { if (it->rect.Overlaps(vr)) it->PreDraw(); else it->PreDrawOffscreen(); }
}
void UIContainer::Draw() {
GFXManager::PushOffsetAdd(rect.pos - scrollOffset);
VRect vr = ViewportRect();
for (auto& it : children) { if (it->rect.Overlaps(vr)) it->Draw(); }
GFXManager::PopOffset();
}

View File

@ -0,0 +1,48 @@
#pragma once
#include "starlight/_global.h"
#include <memory>
#include <list>
#include <functional>
#include "starlight/datatypes/Vector2.h"
#include "starlight/datatypes/VRect.h"
#include "starlight/ui/UIElement.h"
// no forward declaration in this header
namespace starlight {
namespace ui {
class UIContainer : public UIElement {
private:
protected:
std::list<std::shared_ptr<UIElement>> children;
void _Dive(std::function<bool(UIElement*)>& check, std::function<bool(UIElement*)>& func, bool consumable, bool frontFirst, bool& finished);
void _Dive(std::function<bool(UIElement*)>& func, bool consumable, bool frontFirst, bool& finished);
public:
Vector2 scrollOffset = Vector2::zero;
VRect ViewportRect() { return VRect(scrollOffset, rect.size); }
UIContainer();
UIContainer(VRect rect) { this->rect = rect; }
~UIContainer();
void Dive(std::function<bool(UIElement*)> check, std::function<bool(UIElement*)> func, bool consumable = true, bool frontFirst = true);
void Dive(std::function<bool(UIElement*)> func, bool consumable = true, bool frontFirst = true);
void Add(std::shared_ptr<UIElement> elem);
//void Add(UIElement* elem);
void Remove(std::shared_ptr<UIElement> elem);
void Update() override;
void PreDraw() override;
void Draw() override;
virtual void OnChildResize(UIElement& child) { }
};
}
}

View File

@ -0,0 +1,46 @@
#include "UIElement.h"
using starlight::Vector2;
using starlight::VRect;
using starlight::ui::UIElement;
using starlight::ui::UIContainer;
UIElement::UIElement() { }
UIElement::~UIElement() { }
void UIElement::_Dive(std::function<bool(UIElement*)>& check, std::function<bool(UIElement*)>& func, bool consumable, bool frontFirst, bool& finished) {
if (!check(this)) return;
finished = func(this) && consumable;
}
void UIElement::_Dive(std::function<bool(UIElement*)>& func, bool consumable, bool frontFirst, bool& finished) {
finished = func(this) && consumable;
}
VRect UIElement::ViewRect() {
if (auto p = parent.lock()) {
return rect - p->scrollOffset;
}
return rect;
}
VRect UIElement::ScreenRect() {
if (auto p = parent.lock()) {
return ViewRect() + p->ScreenRect().pos;
}
return rect;
}
VRect& UIElement::Resize(Vector2 size) {
if (size == rect.size) return rect; // don't trigger events on false alarm
rect.size = size;
OnResize();
if (auto p = parent.lock()) {
p->OnChildResize(*this);
}
return rect;
}
void UIElement::MarkForRedraw() {
if (auto p = parent.lock()) p->MarkForRedraw();
}

View File

@ -0,0 +1,65 @@
#pragma once
#include "starlight/_global.h"
#include <memory>
#include <functional>
#include "starlight/datatypes/Vector2.h"
#include "starlight/datatypes/VRect.h"
namespace starlight {
namespace ui {
// forward declare to uncirclify
class UIContainer;
class UIElement : public std::enable_shared_from_this<UIElement> {
friend class UIContainer;
private:
//
protected:
virtual void _Dive(std::function<bool(UIElement*)>& check, std::function<bool(UIElement*)>& func, bool consumable, bool frontFirst, bool& finished);
virtual void _Dive(std::function<bool(UIElement*)>& func, bool consumable, bool frontFirst, bool& finished);
public:
std::weak_ptr<UIContainer> parent;
VRect rect;
virtual VRect ViewRect();
virtual VRect ScreenRect();
VRect& Resize(Vector2 size);
inline VRect& Resize(float w, float h) { return Resize(Vector2(w, h)); }
UIElement();
virtual ~UIElement();
virtual void Update() { }
virtual void PreDraw() { }
virtual void PreDrawOffscreen() { }
virtual void Draw() { }
virtual void MarkForRedraw();
// events
virtual void OnTouchOn() { }
virtual void OnTouchOff() { }
virtual void OnTouchHold() { }
virtual void OnProcessTouchEvent() { } // name?
virtual bool InterceptsTouch(Vector2 where) { return false; }
virtual bool OnDragPassed() { return false; }
virtual void OnDragStart() { }
virtual void OnDragRelease() { }
virtual void OnDragHold() { }
virtual void OnResize() { }
};
}
}
// autoinclude after declaration since these two are pretty inextricably linked
#include "UIContainer.h"

View File

@ -0,0 +1,77 @@
#include "WorkerThread.h"
using starlight::util::WorkerThread;
namespace { // helpers
void EnterNew(void* arg) {
static_cast<WorkerThread*>(arg)->ThreadMain();
}
}
WorkerThread::WorkerThread() {
svcCreateEvent(&sync, RESET_ONESHOT);
s32 priority = 0;
svcGetThreadPriority(&priority, CUR_THREAD_HANDLE);
thread = threadCreate(EnterNew, static_cast<void*>(this), 4*1024, priority-1, -2, false);
}
WorkerThread::~WorkerThread() {
kill = true;
threadJoin(thread, U64_MAX);
threadFree(thread);
}
void WorkerThread::ThreadMain() {
if (running) return; // wait, how did you get here twice?
running = true;
while (!kill) {
svcWaitSynchronization(sync, U64_MAX);
while (lock) { }
lock = true;
while (!queue.empty()) {
auto func = queue.front();
queue.pop_front();
lock = false;
auto cfunc = (*func)();
delete func;
if (cfunc) {
while (c_lock) { }
c_lock = true;
cqueue.push_back(cfunc);
c_lock = false;
}
while (lock) { }
lock = true;
}
lock = false;
}
running = false;
}
void WorkerThread::RunCompleteQueue() {
while (c_lock) { }
c_lock = true;
while (!cqueue.empty()) {
auto cfunc = cqueue.front();
cqueue.pop_front();
c_lock = false;
(*cfunc)();
delete cfunc;
while (c_lock) { }
c_lock = true;
}
c_lock = false;
}
void WorkerThread::PushTask(std::function<std::function<void()>*()>* func) {
while (lock) { }
lock = true;
queue.push_back(func);
lock = false;
svcSignalEvent(sync);
}

View File

@ -0,0 +1,34 @@
#pragma once
#include "starlight/_global.h"
#include <3ds.h>
#include <functional>
#include <list>
namespace starlight {
namespace util {
class WorkerThread {
private:
Thread thread;
Handle sync;
volatile bool lock = false;
volatile bool c_lock = false;
volatile bool kill = false;
volatile bool running = false;
std::list<std::function<std::function<void()>*()>*> queue;
std::list<std::function<void()>*> cqueue;
public:
WorkerThread();
~WorkerThread();
void ThreadMain();
void PushTask(std::function<std::function<void()>*()>* func);
void RunCompleteQueue();
};
}
}

10
libstarlight/vs_shim.cpp Normal file
View File

@ -0,0 +1,10 @@
// various stuff to force Visual Studio to play nice
// not used in compilation, thankfully
#undef __cplusplus
#define __cplusplus 201103L
// whee, silly macro bullshit
#define _GLIBCXX_VISIBILITY(a)
#define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#define _GLIBCXX_END_NAMESPACE_CONTAINER