23 Commits
Author SHA1 Message Date
tobid7 6547f64d13 fix resize sym 2026-09-18 22:11:08 +02:00
tobid7 2b37204763 remove Font::LoadDefaultFont 2026-09-17 21:35:19 +02:00
tobid7 8c2bcedc93 Testing around 2026-09-16 21:20:45 +02:00
tobid7 01d3eb771e remove the 3ds ifdefs out of the core mat lib
need to find a way to handle mtx stuff in the gfx driver or another way
2026-09-15 07:20:00 +02:00
tobid7 6de3683818 3ds: move ui7 to bottom screne 2026-09-13 14:10:07 +02:00
tobid7 ec49f70c0b Add more gfx backend flags (available features) 2026-09-13 01:24:55 +02:00
tobid7 6284ff885d citro3d: clipping 2026-09-13 01:06:23 +02:00
tobid7 91c245c1a6 dx9 clipping 2026-09-12 17:29:48 +02:00
tobid7 c828166ce4 refactor UI7 clipping 2026-09-10 07:55:37 +02:00
tobid7 c7816ea170 fix close sym 2026-09-09 22:03:19 +02:00
tobid7 0dbf430c0c Implement clipping 2026-09-08 21:15:21 +02:00
tobid7 aec9083ebb small fixes 2026-09-07 22:05:51 +02:00
tobid7 9e6c6fd84d Merge dev-0.7-rewrite into stable 2026-09-06 16:23:08 +02:00
tobid7 7e0f3a6bf6 reset layers and give menus a base layer to gather perfect ordered rendering 2026-09-06 15:10:37 +02:00
tobid7 1ae4d0cd46 Add FontStack to UI7 and uncomment layer lines 2026-09-06 15:03:45 +02:00
tobid7 420edd0677 move and fix scrolling to layout
Scrolling was hardcoded to 3ds sCrEeNhEiGhT wTh
2026-09-06 14:46:22 +02:00
tobid7 e8a9055090 Layers are back 2026-09-06 14:39:28 +02:00
tobid7 9e27dfb0eb hotfix 2026-09-06 14:25:12 +02:00
tobid7 42c669de55 Add Hid3DS 2026-09-06 14:21:30 +02:00
tobid7 4488425a94 Bring back global lithium pools
why?
cause sorting around the global driver pool would basically use more cpu power then just copy data sequences into the right order
And sorting data references costs 0 performance at all
2026-09-05 22:52:59 +02:00
tobid7 0501a4f87c Make UI7::IO::CurrentViewPort a Reference (finally) 2026-03-18 21:33:35 +01:00
tobid7 3d8b57ead6 add .gitattributes file 2026-03-16 20:28:30 +01:00
tobid7 ac37ce9e12 Fix test 2026-03-14 21:15:40 +01:00
51 changed files with 1520 additions and 1076 deletions
+1
View File
@@ -52,6 +52,7 @@ set(PD_SOURCES
source/lithium/drawlist.cpp
source/lithium/font.cpp
source/lithium/math.cpp
source/lithium/pools.cpp
# UI7
source/ui7/io.cpp
+4
View File
@@ -9,6 +9,7 @@ option(PD_ENABLE_CITRO3D "Enable Citro3D Support (3DS)" OFF)
option(PD_ENABLE_VULKAN "Not implemented yet" OFF)
option(PD_ENABLE_HID_GLFW "Enable GLFW Input Driver" ON)
option(PD_ENABLE_HID_NX "Enable NX Input Driver" OFF)
option(PD_ENABLE_HID3DS "Enable 3ds Input Driver" OFF)
if(NOT WIN32) # cause we are not on windows...
set(PD_ENABLE_DIRECTX9 OFF)
@@ -21,6 +22,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS")
set(PD_ENABLE_CITRO3D ON)
set(PD_ENABLE_HID_GLFW OFF)
set(PD_ENABLE_HID_NX OFF)
set(PD_ENABLE_HID3DS ON)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "NintendoSwitch")
set(PD_ENABLE_OPENGL2 OFF)
set(PD_ENABLE_OPENGL3 ON)
@@ -36,6 +38,7 @@ add_library(pd-system STATIC
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl3.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_directx9.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_citro3d.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/hid_3ds.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/hid_glfw.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/hid_nx.cpp
)
@@ -64,6 +67,7 @@ target_compile_definitions(pd-system
$<$<BOOL:${PD_ENABLE_CITRO3D}>:PD_ENABLE_CITRO3D>
$<$<BOOL:${PD_ENABLE_HID_GLFW}>:PD_ENABLE_HID_GLFW>
$<$<BOOL:${PD_ENABLE_HID_NX}>:PD_ENABLE_HID_NX>
$<$<BOOL:${PD_ENABLE_HID3DS}>:PD_ENABLE_HID3DS>
)
# Palladium
@@ -29,6 +29,7 @@ class GfxCitro3D : public GfxDriverBase<GfxCitro3DConfig> {
TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const Li::Texture& tex) override;
void UploadPools() override;
void ClipRect() override;
private:
struct Impl;
@@ -29,6 +29,7 @@ class GfxDirectX9 : public GfxDriverBase<GfxDirectX9Config> {
TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const Li::Texture& tex) override;
void UploadPools() override;
void ClipRect() override;
private:
struct Impl;
@@ -28,6 +28,7 @@ class GfxOpenGL2 : public GfxDriverBase<GfxOpenGL2Config> {
TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const Li::Texture& tex) override;
void UploadPools() override;
void ClipRect() override;
private:
void pSetupShaderAttribs(u32 shader);
@@ -28,6 +28,7 @@ class GfxOpenGL3 : public GfxDriverBase<GfxOpenGL3Config> {
TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const Li::Texture& tex) override;
void UploadPools() override;
void ClipRect() override;
private:
u32 pShader = 0;
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <pd/drivers/hid.hpp>
namespace PD {
class Hid3DS : public HidDriver {
public:
Hid3DS();
~Hid3DS();
void Update() override;
private:
struct Impl;
Impl* impl;
};
} // namespace PD
+1
View File
@@ -7,4 +7,5 @@
#include <pd_system/gfx_opengl3.hpp>
// Hid
#include <pd_system/hid_3ds.hpp>
#include <pd_system/hid_glfw.hpp>
+12
View File
@@ -141,6 +141,9 @@ void GfxCitro3D::SysInit() {
PDLOG("GfxCitro3D::SysInit();");
impl = new Impl();
Flags |= PDGfxBackendFlags_FlipUV_Y;
Flags |= PDGfxBackendFlags_HasClipRect;
Flags |= PDGfxBackendFlags_ReqPow2;
Flags |= PDGfxBackendFlags_ApproxSDF;
impl->pShaderRaw = Pica::AssembleCode(LIShaderCTR);
impl->pCode = DVLB_ParseFile((uint32_t*)impl->pShaderRaw.data(),
impl->pShaderRaw.size());
@@ -264,6 +267,14 @@ void GfxCitro3D::UploadPools() {
BufInfo_Init(buf);
BufInfo_Add(buf, GetVertexBufPtr(0), sizeof(Li::Vertex), 3, 0x210);
}
void GfxCitro3D::ClipRect() {
// This is so cursed but it works
C3D_SetScissor(CurrentHasClip ? GPU_SCISSOR_NORMAL : GPU_SCISSOR_DISABLE,
ViewPort.y - CurrentClip.w - CurrentClip.y,
ViewPort.x - CurrentClip.z - CurrentClip.x,
ViewPort.y - CurrentClip.y, ViewPort.x - CurrentClip.x);
}
} // namespace PD
#else
namespace PD {
@@ -283,5 +294,6 @@ Li::Texture GfxCitro3D::LoadTexture(const std::vector<PD::u8>& pixels, int w,
}
void GfxCitro3D::DeleteTexture(const Li::Texture& tex) {}
void GfxCitro3D::UploadPools() {}
void GfxCitro3D::ClipRect() {}
} // namespace PD
#endif
+17
View File
@@ -112,6 +112,7 @@ void GfxDirectX9::SysInit() {
}
if (psBlob) psBlob->Release();
if (errBlob) errBlob->Release();
Flags |= PDGfxBackendFlags_HasClipRect;
} else {
PDERR(
"GfxDirectX9::SysInit Error: pDevice is not set!\nYOu need to include "
@@ -285,6 +286,21 @@ void GfxDirectX9::UploadPools() {
memcpy(iptr, GetIndexBufPtr(0), GetIndexPoolSize() * sizeof(u16));
impl->IBO->Unlock();
}
void GfxDirectX9::ClipRect() {
if (CurrentHasClip) {
RECT r;
r.left = CurrentClip.x;
r.top = CurrentClip.y;
r.right = CurrentClip.x + CurrentClip.z;
r.bottom = CurrentClip.y + CurrentClip.w;
impl->Device->SetScissorRect(&r);
impl->Device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
} else {
impl->Device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
}
}
} // namespace PD
#else
namespace PD {
@@ -304,5 +320,6 @@ Li::Texture GfxDirectX9::LoadTexture(const std::vector<PD::u8>& pixels, int w,
}
void GfxDirectX9::DeleteTexture(const Li::Texture& tex) {}
void GfxDirectX9::UploadPools() {}
void GfxDirectX9::ClipRect() {}
} // namespace PD
#endif
+12
View File
@@ -73,6 +73,7 @@ void GfxOpenGL2::pSetupShaderAttribs(u32 shader) {
}
void GfxOpenGL2::SysInit() {
Flags |= PDGfxBackendFlags_HasClipRect;
pShader = CreateShaderProgram(pVertCode, pFragCode);
glUseProgram(pShader);
glGenBuffers(1, &VBO);
@@ -183,6 +184,16 @@ void GfxOpenGL2::UploadPools() {
glBufferData(GL_ELEMENT_ARRAY_BUFFER, GetIndexPoolSize() * sizeof(u16),
GetIndexBufPtr(0), GL_DYNAMIC_DRAW);
}
void GfxOpenGL2::ClipRect() {
if (CurrentHasClip) {
glEnable(GL_SCISSOR_TEST);
glScissor(CurrentClip.x, ViewPort.y - (CurrentClip.y + CurrentClip.w),
CurrentClip.z, CurrentClip.w);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
} // namespace PD
#else
namespace PD {
@@ -203,5 +214,6 @@ Li::Texture GfxOpenGL2::LoadTexture(const std::vector<PD::u8>& pixels, int w,
void GfxOpenGL2::DeleteTexture(const Li::Texture& tex) {}
void GfxOpenGL2::pSetupShaderAttribs(u32 shader) {}
void GfxOpenGL2::UploadPools() {}
void GfxOpenGL2::ClipRect() {}
} // namespace PD
#endif
+12
View File
@@ -11,6 +11,7 @@
namespace PD {
void GfxOpenGL3::SysInit() {
Flags |= PDGfxBackendFlags_HasClipRect;
std::string vcode = SpirvHelper::SPV2GLSL(
std::vector<unsigned int>(
Shaders::VertexShader,
@@ -159,6 +160,16 @@ void GfxOpenGL3::UploadPools() {
glBindVertexArray(0);
}
void GfxOpenGL3::ClipRect() {
if (CurrentHasClip) {
glEnable(GL_SCISSOR_TEST);
glScissor(CurrentClip.x, ViewPort.y - (CurrentClip.y + CurrentClip.w),
CurrentClip.z, CurrentClip.w);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
} // namespace PD
#else
namespace PD {
@@ -178,5 +189,6 @@ Li::Texture GfxOpenGL3::LoadTexture(const std::vector<PD::u8>& pixels, int w,
}
void GfxOpenGL3::DeleteTexture(const Li::Texture& tex) {}
void GfxOpenGL3::UploadPools() {}
void GfxOpenGL3::ClipRect() {}
} // namespace PD
#endif
+82
View File
@@ -0,0 +1,82 @@
#include <pd_system/hid_3ds.hpp>
#if defined(PD_ENABLE_HID3DS) && defined(__3DS__)
#include <3ds.h>
namespace PD {
struct Hid3DS::Impl {
std::string* Text;
bool InTextMode = false;
};
Hid3DS::Hid3DS() : HidDriver("Hid3DS") {
impl = new Impl;
pFlags |= PDHidBackendFlags_HasGamepad;
pFlags |= PDHidBackendFlags_HasTouch;
pGamepad[KEY_A] = HidInternal::Gamepad::A;
pGamepad[KEY_B] = HidInternal::Gamepad::B;
pGamepad[KEY_X] = HidInternal::Gamepad::X;
pGamepad[KEY_Y] = HidInternal::Gamepad::Y;
pGamepad[KEY_START] = HidInternal::Gamepad::Start;
pGamepad[KEY_SELECT] = HidInternal::Gamepad::Select;
pGamepad[KEY_L] = HidInternal::Gamepad::L;
pGamepad[KEY_R] = HidInternal::Gamepad::R;
pGamepad[KEY_DUP] = HidInternal::Gamepad::DUp;
pGamepad[KEY_DDOWN] = HidInternal::Gamepad::DDown;
pGamepad[KEY_DLEFT] = HidInternal::Gamepad::DLeft;
pGamepad[KEY_DRIGHT] = HidInternal::Gamepad::DRight;
pGamepad[KEY_CPAD_UP] = HidInternal::Gamepad::CPUp;
pGamepad[KEY_CPAD_DOWN] = HidInternal::Gamepad::CPDown;
pGamepad[KEY_CPAD_LEFT] = HidInternal::Gamepad::CPLeft;
pGamepad[KEY_CPAD_RIGHT] = HidInternal::Gamepad::CPRight;
pGamepad[KEY_CSTICK_UP] = HidInternal::Gamepad::CSUp;
pGamepad[KEY_CSTICK_DOWN] = HidInternal::Gamepad::CSDown;
pGamepad[KEY_CSTICK_LEFT] = HidInternal::Gamepad::CSLeft;
pGamepad[KEY_CSTICK_RIGHT] = HidInternal::Gamepad::CSRight;
pGamepad[KEY_ZL] = HidInternal::Gamepad::ZL;
pGamepad[KEY_ZR] = HidInternal::Gamepad::ZR;
pGamepad[KEY_TOUCH] = HidInternal::Gamepad::Touch;
}
Hid3DS::~Hid3DS() { delete impl; }
void Hid3DS::Update() {
HidDriver::Update(); // clear stats
hidScanInput();
u32 kd = hidKeysDown();
u32 kh = hidKeysHeld();
u32 ku = hidKeysUp();
for (const auto& b : pGamepad) {
if (b.first & kd) {
pGamepadEvents[0][Event::Down] |= b.second;
}
if (b.first & kh) {
pGamepadEvents[0][Event::Held] |= b.second;
}
if (b.first & ku) {
pGamepadEvents[0][Event::Up] |= b.second;
}
}
/*if (pLocked) {
SwapTab();
}*/
touchPosition t;
hidTouchRead(&t);
pMouse[0] = fvec2(t.px, t.py);
}
} // namespace PD
#else
struct GLFWgamepadstate {};
namespace PD {
Hid3DS::Hid3DS() : HidDriver("Hid3DS") {}
Hid3DS::~Hid3DS() {}
void Hid3DS::Update() {
HidDriver::Update(); // clear stats
}
} // namespace PD
#endif
+1 -1
View File
@@ -65,7 +65,7 @@ HidGlfw::HidGlfw(GLFWwindow* win) : HidDriver("HidGlfw") {
}
}
HidGlfw::~HidGlfw() {}
HidGlfw::~HidGlfw() { delete impl; }
void HidGlfw::Update() {
HidDriver::Update(); // clear stats
+1 -1
View File
@@ -11,7 +11,7 @@ struct HidNX::Impl {
HidNX::HidNX() : HidDriver("HidNX") { impl = new Impl; }
HidNX::~HidNX() {}
HidNX::~HidNX() { delete impl; }
void HidNX::Update() {
HidDriver::Update(); // clear stats
+1 -22
View File
@@ -56,21 +56,9 @@ struct PD_API Mat4 {
constexpr float* Ptr() { return m.data(); }
constexpr const float* Ptr() const { return m.data(); }
constexpr float& operator()(int row, int col) {
#ifdef __3DS__
// 3ds is full reverse order iirc
return m[row * 4 + (3 - col)];
#else
return m[col * 4 + row];
#endif
}
constexpr float& operator()(int row, int col) { return m[col * 4 + row]; }
constexpr float operator()(int row, int col) const {
#ifdef __3DS__
// 3ds is full reverse order iirc
return m[row * 4 + (3 - col)];
#else
return m[col * 4 + row];
#endif
}
constexpr Mat4 operator*(const Mat4& v) const {
@@ -122,21 +110,12 @@ struct PD_API Mat4 {
constexpr static Mat4 Ortho(float l, float r, float b, float t, float n,
float f) {
Mat4 ret;
#ifdef __3DS__ // Patch to rotate the Matrix correctly
ret(0, 1) = 2.f / (t - b);
ret(0, 3) = (b + t) / (b - t);
ret(1, 0) = 2.f / (l - r);
ret(1, 3) = (l + r) / (r - l);
ret(2, 2) = 1.f / (n - f);
ret(2, 3) = 0.5f * (n + f) / (n - f) - 0.5f;
#else
ret(0, 0) = 2.0f / (r - l);
ret(0, 3) = -(r + l) / (r - l);
ret(1, 1) = 2.0f / (t - b);
ret(1, 3) = -(t + b) / (t - b);
ret(2, 2) = -2.0f / (f - n);
ret(2, 3) = -(f + n) / (f - n);
#endif
ret(3, 3) = 1.f;
return ret;
}
+60 -11
View File
@@ -2,14 +2,18 @@
#include <pd/core/mat.hpp>
#include <pd/drivers/interface.hpp>
#include <pd/lithium/command.hpp>
#include <pd/lithium/drawlist.hpp>
#include <pd/lithium/pools.hpp>
#include <pd/lithium/texture.hpp>
using PDGfxBackendFlags = PD::u32;
enum PDGfxBackendFlags_ {
PDGfxBackendFlags_None = 0,
PDGfxBackendFlags_FlipUV_Y = 1 << 0, // Essential for font loading
PDGfxBackendFlags_WindingCW = 1 << 0, // Use CW instead of CCW winding
PDGfxBackendFlags_WindingCW = 1 << 1, // Use CW instead of CCW winding
PDGfxBackendFlags_HasClipRect = 1 << 2, // Clip rects supported
PDGfxBackendFlags_ReqPow2 = 1 << 3, // Tex size must be pow of 2
PDGfxBackendFlags_ApproxSDF = 1 << 4, // Fake SDF for non smoothstep systems
};
namespace PD {
@@ -37,7 +41,7 @@ class PD_API GfxDriver : public DriverInterface {
return Li::Texture();
}
virtual void DeleteTexture(const Li::Texture& tex) {}
virtual void Draw(const Pool<Li::Command>& commands) {}
virtual void Draw(const Li::Drawlist& commands) {}
Li::Texture::Ptr GetWhiteTexture() { return &pWhite; }
PDGfxBackendFlags GetFlags() { return Flags; }
@@ -64,6 +68,7 @@ class PD_API GfxDriver : public DriverInterface {
virtual void SysReset() {}
virtual void Submit(size_t count, size_t start) {}
virtual void UploadPools() {} // not every driver requires it
virtual void ClipRect() {}
void RegisterTexture(const Li::Texture& tex);
void UnregisterTexture(const Li::Texture& tex);
@@ -79,6 +84,8 @@ class PD_API GfxDriver : public DriverInterface {
// State Variables oder so
TextureID CurrentTex = 0;
bool CurrentTexIsSDF = false;
bool CurrentHasClip = false;
fvec4 CurrentClip = 0;
Mat4 Projection;
ivec2 ViewPort;
std::unordered_map<TextureID, Li::Texture> pTextureRegestry;
@@ -110,30 +117,74 @@ class GfxDriverBase : public GfxDriver {
pWhite = LoadTexture(img, 16, 16);
}
void Draw(const Pool<Li::Command>& commands) override {
void Draw(const Li::Drawlist& dl) override {
const auto& commands = dl.Data();
if (commands.size() == 0) return;
pCountCommands += commands.size();
size_t index = 0;
size_t vtotal = dl.GetNumVertices();
size_t itotal = dl.GetNumIndices();
size_t start_vtx = pVtxPool.size();
pVtxPool.Allocate(vtotal);
CurrentVertex += vtotal;
size_t start_idx = pIdxPool.size();
pIdxPool.Allocate(itotal);
CurrentIndex += itotal;
size_t current_vtx = start_vtx;
size_t current_idx = start_idx;
const auto& vpool = Li::GetVertexPool();
const auto& ipool = Li::GetIndexPool();
/** Build Pools */
for (size_t i = 0; i < commands.size(); i++) {
const auto& cmd = commands[i];
if (cmd.VertexCount > 0) {
std::memcpy(reinterpret_cast<void*>(pVtxPool.begin() + current_vtx),
vpool.begin() + cmd.FirstVertex,
cmd.VertexCount * sizeof(Li::Vertex));
}
for (size_t idx = 0; idx < cmd.IndexCount; idx++) {
u16 local_idx = ipool[cmd.FirstIndex + idx];
pIdxPool[current_idx + idx] = static_cast<u16>(current_vtx + local_idx);
}
current_vtx += cmd.VertexCount;
current_idx += cmd.IndexCount;
}
UploadPools();
size_t index = 0;
size_t ioff = start_idx;
while (index < commands.size()) {
CurrentTex = commands[index].Tex;
CurrentTexIsSDF = commands[index].SDF;
CurrentHasClip = commands[index].ClipRectUsed;
CurrentClip = commands[index].ClipRect;
if (!CurrentTex) {
CurrentTex = pWhite.GetID();
}
size_t startidx = commands[index].FirstIndex;
size_t num_indices = 0;
ClipRect();
while (index < commands.size() &&
CurrentTexIsSDF == commands[index].SDF &&
(CurrentTex == commands[index].Tex ||
(CurrentTex == pWhite.GetID() && commands[index].Tex == 0)) &&
commands[index].FirstIndex == startidx + num_indices) {
CurrentClip == commands[index].ClipRect &&
CurrentHasClip == commands[index].ClipRectUsed) {
num_indices += commands[index].IndexCount;
index++;
}
Submit(num_indices, startidx);
if (num_indices > 0) {
Submit(num_indices, ioff);
ioff += num_indices;
pCountDrawcalls++;
}
}
}
size_t AllocateVertices(size_t count, PD::ptr accessor) override {
pVertexAccessor = accessor;
@@ -211,9 +262,7 @@ class PD_API Gfx {
static void SetViewPort(const ivec2& vp) { driver->SetViewPort(vp); }
static void SetViewPort(int w, int h) { driver->SetViewPort(w, h); }
static void Reset() { driver->Reset(); }
static void Draw(const Pool<Li::Command>& commands) {
driver->Draw(commands);
}
static void Draw(const Li::Drawlist& dl) { driver->Draw(dl); }
static Li::Texture LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h,
TextureFormat type = TextureFormat::RGBA32,
+3
View File
@@ -28,6 +28,9 @@ class Command {
// Todo: implement
size_t VertexCountMax = 0;
size_t IndexCountMax = 0;
// ClipRect
PD::fvec4 ClipRect;
bool ClipRectUsed = false;
};
} // namespace Li
} // namespace PD
+12 -2
View File
@@ -42,6 +42,10 @@ class PD_API Drawlist {
void Copy(Drawlist& other);
void Optimize();
void Clear();
void SetLayer(int layer) { pCurrentLayer = layer; }
void LayerUp() { pCurrentLayer++; }
void LayerDown() { pCurrentLayer--; }
int GetLayer() const { return pCurrentLayer; }
size_t GetNumVertices() const {
size_t count = 0;
@@ -124,12 +128,18 @@ class PD_API Drawlist {
void PrimTriangle(Command& cmd, const fvec2& a, const fvec2& b,
const fvec2& c, const PD::Color& color);
void PushClipRect(const fvec4& r) { pClipRects.push_back(r); }
void PopClipRect() {
if (!pClipRects.empty()) pClipRects.pop_back();
}
bool HasClipRect() { return !pClipRects.empty(); }
private:
Texture pCurrentTexture;
int pCurrentLayer = 0;
Pool<Command> pCommands;
Pool<fvec2> pPath;
Pool<Vertex> pVertices;
Pool<u16> pIndices;
std::vector<fvec4> pClipRects;
Font* pFont = nullptr;
float pFontScale = 1.f;
};
-6
View File
@@ -56,12 +56,6 @@ class PD_API Font {
*/
void LoadTTF(const std::vector<u8>& data, int px_height = 32,
LiFontFlags flags = LiFontFlags_None);
/**
* Function that loads a default integrated font...
* This will only work if PD_LI_INCLUDE_FONTS was set
* on lithium build cause otherwise the font data is not included
*/
void LoadDefaultFont(int id = 0, int pixel_height = 32);
/**
* Getter for Codepoint reference
* @return codepoint dataholder reference
+1
View File
@@ -4,4 +4,5 @@
#include <pd/lithium/drawlist.hpp>
#include <pd/lithium/font.hpp>
#include <pd/lithium/math.hpp>
#include <pd/lithium/pools.hpp>
#include <pd/lithium/vertex.hpp>
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <pd/core/core.hpp>
#include <pd/lithium/vertex.hpp>
namespace PD {
namespace Li {
PD_API PD::Pool<Vertex>& GetVertexPool();
PD_API PD::Pool<u16>& GetIndexPool();
PD_API void ResetPools();
} // namespace Li
} // namespace PD
+4 -1
View File
@@ -48,7 +48,7 @@ class PD_API Container {
*/
Container(const fvec4& box)
: pos(fvec2(box.x, box.y)), size(fvec2(box.z - box.x, box.w - box.y)) {}
~Container() = default;
virtual ~Container() = default;
/**
* Init Function Required by every Object that uses
@@ -59,6 +59,7 @@ class PD_API Container {
void Init(UI7::IO* io, Li::Drawlist* l) {
list = l;
this->io = io;
pFont = io->Font;
// this->screen = io->Ren->CurrentScreen();
}
@@ -75,6 +76,7 @@ class PD_API Container {
fvec2 GetPos() { return pos; }
/** Getter for Size */
fvec2 GetSize() { return size; }
Li::Font* GetFont() { return pFont; }
/**
* Get the Containers Final Position
* for Rendering and Input (if it has a parent Object)
@@ -193,6 +195,7 @@ class PD_API Container {
fvec4 pClipRect;
/** Clip Rect used */
bool pCLipRectUsed = false;
Li::Font* pFont = nullptr;
};
} // namespace UI7
} // namespace PD
+4
View File
@@ -58,6 +58,8 @@ enum UI7MenuFlags_ {
enum UI7LayoutFlags_ {
UI7LayoutFlags_None = 0, ///< No Flags used
UI7LayoutFlags_UseClipRect = 1 << 0, ///< Enable ClipRect
UI7LayoutFlags_HzScrolling = 1 << 1, ///< Scrolling Horizontal
UI7LayoutFlags_VtScrolling = 1 << 2, ///< Scrolling Vertical
};
/** UI7 Context Flags */
@@ -85,6 +87,8 @@ enum UI7LytAdd_ {
UI7LytAdd_NoCursorUpdate = 1 << 0, ///< Add without cursor alignment
UI7LytAdd_NoScrollHandle = 1 << 1, ///< Skip HandleScrolling
UI7LytAdd_Front = 1 << 2, ///< Add in front of the list
UI7LytAdd_NoGlobalClipping = 1 << 3, ///< Dont use global Layout clip rect
UI7LytAdd_NoClipTitlebar = 1 << 4, ///< Dont clip content behind the titlebar
};
/**
+13
View File
@@ -81,6 +81,7 @@ class PD_API IO {
u32 NumVertices = 0; ///< Debug Vertices Num
u32 NumIndices = 0; ///< Debug Indices Num
std::vector<u32> MenuOrder;
std::vector<Li::Font*> FontStack;
// Pools
PD::Pool<UI7::Label> LabelPool;
@@ -107,6 +108,18 @@ class PD_API IO {
return ViewPorts[id.RawID()];
}
void PushFont(Li::Font* f) {
FontStack.push_back(Font);
Font = f;
}
void PopFont() {
if (!FontStack.empty()) {
Font = FontStack.back();
FontStack.pop_back();
}
}
UI7::InputHandler InputHandler;
};
} // namespace UI7
+4
View File
@@ -127,6 +127,8 @@ class PD_API Layout {
void CursorInit();
void SameLine();
void CursorMove(const fvec2& size);
void PushFont(Li::Font* f) { IO.PushFont(f); }
void PopFont() { IO.PopFont(); }
bool ObjectWorkPos(fvec2& movpos);
@@ -163,6 +165,8 @@ class PD_API Layout {
void SetAlign(UI7Align a) { Alignment = a; }
void NextAlign(UI7Align a) { TempAlign = a; }
void HandleScrolling();
void Update();
fvec2 DbgScrollOffset() { return ScrollOffset; }
+3 -1
View File
@@ -110,7 +110,6 @@ class PD_API Menu {
void EndTreeNode();
void HandleFocus();
void HandleScrolling();
void HandleTitlebarActions();
void DrawBaseLayout();
@@ -120,6 +119,9 @@ class PD_API Menu {
}
Container* FindObject(u32 id) { return pLayout.FindObject(id); }
void PushFont(Li::Font* f) { pIO.PushFont(f); }
void PopFont() { pIO.PopFont(); }
void Update();
void SetSize(PD::fvec2 size) { pLayout.SetSize(size); }
-5
View File
@@ -85,13 +85,8 @@ PD_API Mat4 Mat4::Perspective(float fov, float aspect, float n, float f) {
Mat4 ret;
ret(0, 0) = 1.f / (aspect * _fov);
ret(1, 1) = 1.f / _fov;
#ifdef __3DS__
ret(2, 3) = f * n / (n - f);
ret(2, 2) = -(-1.f) * n / (n - f);
#else
ret(2, 2) = -(f + n) / (f - n);
ret(2, 3) = -(2.f * f * n) / (f - n);
#endif
ret(3, 2) = -1.f;
ret(3, 3) = 0.0f;
return ret;
+42 -12
View File
@@ -1,23 +1,48 @@
#include <pd/drivers/gfx.hpp>
#include <pd/lithium/command.hpp>
#include <pd/lithium/pools.hpp>
namespace PD {
namespace Li {
void Command::Reserve(size_t vtx, size_t idx) {
auto& vpool = GetVertexPool();
auto& ipool = GetIndexPool();
if (VertexCountMax == 0) {
FirstVertex = Gfx::AllocateVertices(vtx, (PD::ptr)this);
FirstVertex = vpool.size();
vpool.Allocate(vtx);
VertexCountMax = vtx;
} else {
Gfx::ExpandVertices(vtx, (PD::ptr)this);
if (vpool.size() == FirstVertex + VertexCountMax) {
vpool.Allocate(vtx);
VertexCountMax += vtx;
} else {
size_t tmp = FirstVertex;
FirstVertex = vpool.size();
vpool.Allocate(VertexCountMax + vtx);
for (size_t i = 0; i < VertexCount; i++) {
vpool[FirstVertex + i] = vpool[tmp + i];
}
VertexCountMax += vtx;
}
}
if (IndexCountMax == 0) {
FirstIndex = Gfx::AllocateIndices(idx, (PD::ptr)this);
FirstIndex = ipool.size();
ipool.Allocate(idx);
IndexCountMax = idx;
} else {
Gfx::ExpandIndices(idx, (PD::ptr)this);
if (ipool.size() == FirstIndex + IndexCountMax) {
ipool.Allocate(idx);
IndexCountMax += idx;
} else {
size_t tmp = FirstIndex;
FirstIndex = ipool.size();
ipool.Allocate(IndexCountMax + idx);
for (size_t i = 0; i < IndexCount; i++) {
ipool[FirstIndex + i] = ipool[tmp + i];
}
IndexCountMax += idx;
}
}
}
@@ -31,25 +56,30 @@ void Command::Reset() {
VertexCount = 0;
VertexCountMax = 0;
IndexCountMax = 0;
ClipRect = 0.f;
ClipRectUsed = false;
}
Command& Command::Add(const Vertex& vtx) {
if (VertexCount <= VertexCountMax)
Gfx::PutVertex(FirstVertex + VertexCount++, vtx, (PD::ptr)this);
if (VertexCount < VertexCountMax) {
GetVertexPool()[FirstVertex + VertexCount++] = vtx;
}
return *this;
}
Command& Command::Add(u16 idx) {
if (IndexCount <= IndexCountMax)
Gfx::PutIndex(FirstIndex + IndexCount++, FirstVertex + VertexCount + idx,
(PD::ptr)this);
if (IndexCount < IndexCountMax) {
GetIndexPool()[FirstIndex + IndexCount++] =
static_cast<u16>(VertexCount + idx);
}
return *this;
}
Command& Command::Add(u16 a, u16 b, u16 c) {
if (IndexCount + 3 <= IndexCountMax) {
auto& ip = GetIndexPool();
size_t idx = FirstIndex + IndexCount;
Gfx::PutIndex(idx + 0, FirstVertex + VertexCount + a, (PD::ptr)this);
Gfx::PutIndex(idx + 1, FirstVertex + VertexCount + b, (PD::ptr)this);
Gfx::PutIndex(idx + 2, FirstVertex + VertexCount + c, (PD::ptr)this);
ip[idx + 0] = static_cast<u16>(VertexCount + a);
ip[idx + 1] = static_cast<u16>(VertexCount + b);
ip[idx + 2] = static_cast<u16>(VertexCount + c);
IndexCount += 3;
}
return *this;
+27 -4
View File
@@ -1,3 +1,4 @@
#include <algorithm>
#include <iostream>
#include <pd/drivers/gfx.hpp>
#include <pd/lithium/drawlist.hpp>
@@ -11,28 +12,50 @@ PD_API Drawlist::Drawlist() { Clear(); }
PD_API Drawlist::~Drawlist() { Clear(); }
PD_API void Drawlist::Merge(Drawlist& other) {
size_t start = pCommands.size();
pCommands.AppendMove(other.pCommands);
for (size_t i = start; i < pCommands.size(); i++) {
pCommands[i].Layer += this->pCurrentLayer;
}
other.Clear();
}
PD_API void Drawlist::Copy(Drawlist& other) {
int start = pCommands.size();
pCommands.AppendCopy(other.pCommands);
for (size_t i = start; i < pCommands.size(); i++) {
pCommands[i].Layer += this->pCurrentLayer;
}
}
PD_API void Drawlist::Optimize() {}
PD_API void Drawlist::Optimize() {
if (pCommands.size() <= 1) return;
std::stable_sort(pCommands.begin(), pCommands.end(),
[](const Command& a, const Command& b) {
if (a.Layer != b.Layer) return a.Layer < b.Layer;
if (a.SDF != b.SDF) return a.SDF < b.SDF;
return a.Tex < b.Tex;
});
}
PD_API void Drawlist::Clear() {
UnbindTexture();
pPath.ResetFast();
pVertices.ResetFast();
pIndices.ResetFast();
pCommands.ResetFast();
pCommands.NoReset();
pCurrentLayer = 0;
pClipRects.clear();
}
/** Command Allocation */
PD_API Command& Drawlist::NewCommand() {
auto cmd = pCommands.Allocate(1);
cmd->Reset();
cmd->Layer = pCurrentLayer;
cmd->Tex = pCurrentTexture.GetID();
if (HasClipRect()) {
cmd->ClipRectUsed = HasClipRect();
cmd->ClipRect = pClipRects.back();
}
return *cmd;
}
+2 -3
View File
@@ -195,8 +195,6 @@ PD_API void Font::LoadTTF(const std::vector<u8>& data, int px_height,
}
}
PD_API void Font::LoadDefaultFont(int id, int pixel_height) {}
PD_API Font::Codepoint& Font::GetCodepoint(u32 c) {
if (c < 128) {
// Direct Access (~11% improvement)
@@ -288,7 +286,8 @@ PD_API void Font::CmdTextEx(Drawlist& dl, const fvec2& pos, u32 color,
}
if (cp.Size.x > 0 && cp.Size.y > 0) {
if (cmd == nullptr || cmd->Tex != Textures[cp.Tex]) {
if (cmd == nullptr || cmd->Tex != Textures[cp.Tex] ||
cmd->Layer != dl.GetLayer()) {
if (cp.Tex >= Textures.size()) continue;
cmd = &dl.NewCommand();
cmd->Tex = Textures[cp.Tex];
+16
View File
@@ -0,0 +1,16 @@
#include <pd/lithium/pools.hpp>
namespace PD {
namespace Li {
static PD::Pool<Vertex> gVertexPool;
static PD::Pool<u16> gIndexPool;
PD_API PD::Pool<Vertex>& GetVertexPool() { return gVertexPool; }
PD_API PD::Pool<u16>& GetIndexPool() { return gIndexPool; }
PD_API void ResetPools() {
gVertexPool.NoReset();
gIndexPool.NoReset();
}
} // namespace Li
} // namespace PD
+3 -2
View File
@@ -49,12 +49,13 @@ PD_API void Button::HandleInput() {
PD_API void Button::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->PathRect(FinalPos(), FinalPos() + size, io->FrameRounding);
list->PathFill(io->Theme.Get(color));
// list->LayerUp();
list->LayerUp();
list->DrawText(FinalPos() + size * 0.5 - tdim * 0.5, label.c_str(),
io->Theme.Get(UI7Color_Text));
// list->LayerDown();
list->LayerDown();
}
PD_API void Button::Update() {
+1
View File
@@ -48,6 +48,7 @@ PD_API void Checkbox::HandleInput() {
PD_API void Checkbox::Draw() {
// Assert(list.get() && io.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->PathRect(FinalPos(), FinalPos() + cbs, io->FrameRounding);
list->PathFill(io->Theme.Get(color));
if (usr_ref) {
+6
View File
@@ -44,6 +44,7 @@ PD_API void ColorEdit::HandleInput() {
PD_API void ColorEdit::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->PathRect(FinalPos(), FinalPos() + io->ItemRowHeight, io->FrameRounding);
list->PathFill(*color_ref);
list->DrawText(FinalPos() + fvec2(io->ItemSpace.x + io->ItemRowHeight, 0),
@@ -55,16 +56,19 @@ PD_API void ColorEdit::Draw() {
layout->SetPosition(FinalPos());
DynObj* r = io->DynObjPool.Allocate();
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) {
list->SetFont(thiz->GetFont());
thiz->SetSize(layout->GetSize());
// l->Layer(30);
l->PathRect(thiz->GetPos(), thiz->GetPos() + thiz->GetSize(),
io->FrameRounding);
l->PathFill(io->Theme.Get(UI7Color_FrameBackground));
l->SetLayer(0);
});
layout->AddObjectEx(r, UI7LytAdd_Front | UI7LytAdd_NoCursorUpdate |
UI7LytAdd_NoScrollHandle);
r = io->DynObjPool.Allocate();
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) {
list->SetFont(thiz->GetFont());
l->PathRect(thiz->FinalPos(), thiz->FinalPos() + io->ItemRowHeight,
io->FrameRounding);
l->PathFill(*color_ref);
@@ -84,7 +88,9 @@ PD_API void ColorEdit::Draw() {
layout->Slider<u8>("B", ((u8*)color_ref) + 2);
layout->Slider<u8>("A", ((u8*)color_ref) + 3);
layout->Update();
list->SetLayer(50);
list->Merge(layout->GetDrawList());
list->SetLayer(0);
// io->RegisterDrawList(GetID(), layout->GetDrawList());
}
}
+2 -2
View File
@@ -44,13 +44,13 @@ PD_API void Container::HandleInternalInput() {
/** Internal function */
PD_API void Container::PreDraw() {
if (pCLipRectUsed) {
// list->PushClipRect(pClipRect);
list->PushClipRect(pClipRect);
}
}
/** Internal function */
PD_API void Container::PostDraw() {
if (pCLipRectUsed) {
// list->PopClipRect();
list->PopClipRect();
}
}
} // namespace UI7
+3 -2
View File
@@ -86,11 +86,11 @@ PD_API void DragData<T>::Draw() {
FinalPos() + fvec2(off_x, 0) + td + io->FramePadding,
io->FrameRounding);
list->PathFill(io->Theme.Get(UI7Color_Button));
// list->LayerUp();
list->LayerUp();
list->DrawTextEx(FinalPos() + fvec2(off_x, 0), p.c_str(),
io->Theme.Get(UI7Color_Text), LiTextFlags_AlignMid,
td + io->FramePadding);
// list->LayerDown();
list->LayerDown();
off_x += td.x + io->ItemSpace.x + io->FramePadding.x;
}
list->DrawText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5),
@@ -101,6 +101,7 @@ template <typename T>
PD_API void DragData<T>::Update() {
// Assert(io.get(), "Did you run Container::Init correctly?");
// Probably need to find a faster solution (caching sizes calculated here)
list->SetFont(GetFont());
float off_x = 0;
for (size_t i = 0; i < elm_count; i++) {
std::string p;
+2 -2
View File
@@ -29,11 +29,11 @@ PD_API void Image::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// Assert(img.get(), "Image is nullptr!");
// io->Ren->OnScreen(screen);
// list->LayerUp();
list->LayerUp();
list->BindTexture(img);
list->DrawRectFilled(FinalPos(), newsize, 0xffffffff);
list->UnbindTexture();
// list->LayerDown();
list->LayerDown();
}
} // namespace UI7
} // namespace PD
+1
View File
@@ -28,6 +28,7 @@ namespace UI7 {
PD_API void Label::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->DrawTextEx(FinalPos(), label.c_str(), io->Theme.Get(UI7Color_Text),
LiTextFlags_NoOOS,
PD::fvec2(0, io->CurrentViewPort.pSize.w));
+3 -2
View File
@@ -70,6 +70,7 @@ template <typename T>
PD_API void Slider<T>::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", *data, precision);
@@ -84,10 +85,10 @@ PD_API void Slider<T>::Draw() {
FinalPos() + fvec2(slp + slw - 2, td.y - 2) + io->FramePadding,
io->FrameRounding);
list->PathFill(io->Theme.Get(UI7Color_ButtonActive));
// list->LayerUp();
list->LayerUp();
list->DrawTextEx(FinalPos(), p.c_str(), io->Theme.Get(UI7Color_Text),
LiTextFlags_AlignMid, fvec2(width, td.y) + io->FramePadding);
// list->LayerDown();
list->LayerDown();
list->DrawText(FinalPos() + fvec2(width + io->FramePadding.x * 2.f,
io->FramePadding.y * 0.5),
label.c_str(), io->Theme.Get(UI7Color_Text));
+1 -1
View File
@@ -28,7 +28,7 @@ SOFTWARE.
namespace PD {
PD_API UI7::IO::IO() : DeltaStats(60), CurrentViewPort("", 0) {
PD_API UI7::IO::IO() : CurrentViewPort("", 0), DeltaStats(60) {
/** Probably not the best solution i guess */
// CurrentViewPort =
// ViewPort::New("Default", ivec4(ivec2(0, 0), pCtx.Gfx()->ViewPort));
+52 -4
View File
@@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <algorithm>
#include <pd/ui7/containers.hpp>
#include <pd/ui7/layout.hpp>
@@ -76,6 +77,10 @@ PD_API void Layout::AddObject(Container* obj) {
obj->Update();
CursorMove(obj->GetSize());
obj->HandleScrolling(ScrollOffset, WorkRect);
if (Flags & UI7LayoutFlags_UseClipRect) {
obj->SetClipRect(
fvec4(Pos.x, Pos.y + WorkRect.y, Size.x, Size.y - WorkRect.y));
}
Objects.push_back(obj);
}
@@ -92,6 +97,15 @@ PD_API void Layout::AddObjectEx(Container* obj, u32 flags) {
if (!(flags & UI7LytAdd_NoScrollHandle)) {
obj->HandleScrolling(ScrollOffset, WorkRect);
}
if (Flags & UI7LayoutFlags_UseClipRect &&
!(flags & UI7LytAdd_NoGlobalClipping)) {
if (flags & UI7LytAdd_NoClipTitlebar) {
obj->SetClipRect(fvec4(Pos.x, Pos.y, Size.x, Size.y));
} else {
obj->SetClipRect(
fvec4(Pos.x, Pos.y + WorkRect.y, Size.x, Size.y - WorkRect.y));
}
}
if (flags & UI7LytAdd_Front) {
Objects.push_front(obj);
} else {
@@ -122,6 +136,42 @@ PD_API fvec2 Layout::AlignPosition(fvec2 pos, fvec2 size, fvec4 area,
return p;
}
PD_API void Layout::HandleScrolling() {
if (Flags & UI7LayoutFlags_VtScrolling) {
bool allowed = MaxPosition.y > WorkRect.w;
if (allowed) {
if (PD::Hid::IsEvent(Hid::Event::Down, PD::Hid::Gamepad::Touch) ||
PD::Hid::IsEvent(Hid::Event::Down, PD::Hid::Keyboard::MouseLeft)) {
ScrollStart = ScrollOffset;
}
if (IO.InputHandler.DragObject(UI7::ID("sbg" + ID.GetName()),
fvec4(Pos, fvec2(0.f)) + WorkRect)) {
if (!IO.InputHandler.DragReleasedAW) {
ScrollOffset.y =
std::clamp(ScrollStart.y + IO.InputHandler.DragSourcePos.y -
IO.InputHandler.DragPosition.y,
-20.f, MaxPosition.y - WorkRect.w + 20.f);
}
}
} else {
ScrollOffset.y = 0.f;
}
if (ScrollOffset.y > MaxPosition.y - WorkRect.w) {
ScrollOffset.y -= 1.5f;
if (ScrollOffset.y < MaxPosition.y - WorkRect.w) {
ScrollOffset.y = MaxPosition.y - WorkRect.w;
}
}
if (ScrollOffset.y < 0) {
ScrollOffset.y += 1.5f;
if (ScrollOffset.y > 0) {
ScrollOffset.y = 0;
}
}
}
}
PD_API void Layout::Update() {
if (Size == fvec2(0.f)) {
Size = fvec2(MaxPosition) + IO.MenuPadding * 2;
@@ -134,9 +184,6 @@ PD_API void Layout::Update() {
it->SetPos(it->GetPos() + Pos);
it->HandleInput();
it->UnlockInput();
if (Flags & UI7LayoutFlags_UseClipRect) {
it->SetClipRect(fvec4(Pos, Size));
}
it->PreDraw();
it->Draw();
it->PostDraw();
@@ -155,6 +202,7 @@ PD_API void Layout::Update() {
Objects.clear();
WorkRect = fvec4(fvec2(WorkRect.x, WorkRect.y), Size - IO.MenuPadding);
CursorInit();
HandleScrolling();
}
/** SECTION CONTAINERS (STOLEN FROM FORMER MENU) */
@@ -163,7 +211,7 @@ PD_API void Layout::Label(const std::string& label) {
// Layout API
auto r = IO.LabelPool.Allocate();
*r = UI7::Label(label, IO);
r->SetClipRect(fvec4(GetPosition(), GetPosition() + GetSize()));
// r->SetClipRect(fvec4(GetPosition(), GetSize()));
AddObject(r);
}
Regular → Executable
+24 -52
View File
@@ -27,7 +27,7 @@ SOFTWARE.
namespace PD {
namespace UI7 {
Menu::Menu(const ID& id, IO& io) : pIO(io), pID(id), pLayout(id, io) {
Menu::Menu(const ID& id, IO& io) : pLayout(id, io), pIO(io), pID(id) {
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
pLayout.WorkRect.y += TitleBarHeight;
pLayout.Flags |= UI7LayoutFlags_UseClipRect;
@@ -104,6 +104,7 @@ PD_API void Menu::SeparatorText(const std::string& label) {
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
UI7::Container* self) {
l->SetFont(self->GetFont());
fvec2 size = self->GetSize();
fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale);
fvec2 pos = self->FinalPos();
@@ -147,45 +148,6 @@ PD_API void Menu::HandleFocus() {
}
}
/** Todo: (func name is self describing) */
PD_API void Menu::HandleScrolling() {
if (Flags & UI7MenuFlags_VtScrolling) {
bool allowed =
pLayout.MaxPosition.y > (pLayout.WorkRect.w - pLayout.WorkRect.y);
if (allowed) {
if (PD::Hid::IsEvent(Hid::Event::Down, PD::Hid::Gamepad::Touch)) {
pLayout.ScrollStart = pLayout.ScrollOffset;
}
if (pIO.InputHandler.DragObject(
"sbg" + pID.GetName(),
fvec4(pLayout.Pos, fvec2(0.f)) + pLayout.WorkRect)) {
if (pIO.InputHandler.DragReleasedAW) {
} else {
pLayout.ScrollOffset.y = std::clamp(
pLayout.ScrollStart.y + pIO.InputHandler.DragSourcePos.y -
pIO.InputHandler.DragPosition.y,
-20.f, pLayout.MaxPosition.y - 220);
}
}
} else {
pLayout.ScrollOffset.y = 0.f;
}
if (pLayout.ScrollOffset.y > pLayout.MaxPosition.y - 240) {
pLayout.ScrollOffset.y -= 1.5;
if (pLayout.ScrollOffset.y < pLayout.MaxPosition.y - 240) {
pLayout.ScrollOffset.y = pLayout.MaxPosition.y - 240;
}
}
if (pLayout.ScrollOffset.y < 0) {
pLayout.ScrollOffset.y += 1.5;
if (pLayout.ScrollOffset.y > 0) {
pLayout.ScrollOffset.y = 0;
}
}
}
}
PD_API void Menu::HandleTitlebarActions() {
// Collapse
if (!(Flags & UI7MenuFlags_NoCollapse)) {
@@ -257,11 +219,12 @@ PD_API void Menu::DrawBaseLayout() {
if (!(Flags & UI7MenuFlags_NoResize)) {
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
// //l->Layer(1);
l->SetLayer(21);
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20));
l->PathAdd(self->FinalPos() + self->GetSize());
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0));
l->PathFill(io->Theme.Get(UI7Color_Button));
l->SetLayer(0);
});
r->SetSize(
fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight));
@@ -273,7 +236,7 @@ PD_API void Menu::DrawBaseLayout() {
/** Background */
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
// l->Layer(0);
l->SetLayer(0);
l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f,
LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot);
l->PathFill(io->Theme.Get(UI7Color_Background));
@@ -285,17 +248,18 @@ PD_API void Menu::DrawBaseLayout() {
fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight));
r->SetPos(fvec2(0, TitleBarHeight));
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle |
UI7LytAdd_Front);
UI7LytAdd_Front | UI7LytAdd_NoClipTitlebar);
}
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj(
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
// l->Layer(20);
l->SetFont(self->GetFont());
l->SetLayer(20);
/** Header Bar */
l->DrawRectFilled(self->FinalPos(), self->GetSize(),
io->Theme.Get(UI7Color_Header));
// l->Layer(21);
l->SetLayer(21);
/** Inline if statement to shift the Text if collapse sym is shown */
/** What the hell is this code btw (didn't found a better way) */
l->DrawText(self->FinalPos() +
@@ -305,10 +269,12 @@ PD_API void Menu::DrawBaseLayout() {
(io->FramePadding.x * 2)),
2),
pID.GetName().c_str(), io->Theme.Get(UI7Color_Text));
l->SetLayer(0);
});
r->SetSize(fvec2(pLayout.GetSize().x, TitleBarHeight));
r->SetPos(0);
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle |
UI7LytAdd_NoClipTitlebar);
/** Collapse Sym */
if (!(Flags & UI7MenuFlags_NoCollapse)) {
@@ -316,7 +282,7 @@ PD_API void Menu::DrawBaseLayout() {
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
UI7::Container* self) {
/** This sym actually requires layer 21 (i dont know why) */
// l->Layer(21);
l->SetLayer(21);
/**
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
*/
@@ -327,11 +293,13 @@ PD_API void Menu::DrawBaseLayout() {
self->FinalPos() +
fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y),
io->Theme.Get(UI7Color_FrameBackground));
l->SetLayer(0);
});
r->SetSize(TitleBarHeight - pIO.FramePadding.y * 2);
r->SetPos(pIO.FramePadding);
pLayout.AddObjectEx(r,
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate |
UI7LytAdd_NoScrollHandle |
UI7LytAdd_NoClipTitlebar);
}
/** Close Sym (only shown if pIsShown is not nullptr) */
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) {
@@ -344,11 +312,13 @@ PD_API void Menu::DrawBaseLayout() {
fvec2 cpos =
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x,
pLayout.Pos.y + pIO.FramePadding.y);
pLayout.DrawList.SetLayer(21);
pLayout.DrawList.DrawLine(cpos, cpos + size,
pIO.Theme.Get(UI7Color_FrameBackground), 2);
pLayout.DrawList.DrawLine(cpos + fvec2(0, size.y),
cpos + fvec2(size.x, 0),
pIO.Theme.Get(UI7Color_FrameBackground), 2);
pLayout.DrawList.SetLayer(0);
}
}
}
@@ -358,6 +328,10 @@ PD_API void Menu::Update() {
if (pLayout.Size == fvec2(0.f) || Flags & UI7MenuFlags_AlwaysAutoSize) {
pLayout.Size = fvec2(pLayout.MaxPosition) + pIO.MenuPadding * 2;
}
if (Flags & UI7MenuFlags_VtScrolling)
pLayout.Flags |= UI7LayoutFlags_VtScrolling;
if (Flags & UI7MenuFlags_HzScrolling)
pLayout.Flags |= UI7LayoutFlags_HzScrolling;
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
pLayout.WorkRect.y = 5.f + TitleBarHeight;
@@ -368,9 +342,6 @@ PD_API void Menu::Update() {
}
DrawBaseLayout();
pLayout.Update();
if (Flags & UI7MenuFlags_VtScrolling || Flags & UI7MenuFlags_HzScrolling) {
HandleScrolling();
}
}
PD_API bool Menu::BeginTreeNode(const ID& id) {
@@ -391,6 +362,7 @@ PD_API bool Menu::BeginTreeNode(const ID& id) {
// Object
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([=, this](IO* io, Li::Drawlist* l, Container* self) {
l->SetFont(self->GetFont());
fvec2 ts = self->FinalPos() + fvec2(0, 7);
fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)};
if (n->second) {
+15 -2
View File
@@ -143,8 +143,11 @@ PD_API void Context::Update() {
pMenus[it]->Update(); /** Render */
this->pIO.InputHandler.CurrentMenu = 0;
}
int base_layer = 0;
for (int i = (int)FinalList.size() - 1; i >= 0; i--) {
pIO.FDL.SetLayer(base_layer);
pIO.FDL.Merge(pMenus[FinalList[i]]->pLayout.GetDrawList());
base_layer += 100;
}
pCurrentMenus.clear();
pIO.Update();
@@ -155,7 +158,7 @@ PD_API void Context::AboutMenu(bool* show) {
if (auto m = BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
m->Label("Palladium UI7 " + GetVersion());
m->Separator();
m->Label("(c) 2023-2025 René Amthor");
m->Label("(c) 2023-2026 René Amthor");
m->Label("UI7 is licensed under the MIT License.");
m->Label("See LICENSE for more information.");
static bool show_build;
@@ -204,7 +207,17 @@ PD_API void Context::MetricsMenu(bool* show) {
}
m->SeparatorText("Palladium Info");
m->Label("Os Driver: {}", PD::Os::GetDriverName());
m->Label("Renderer: {}", PD::Gfx::GetDriverName());
if (m->BeginTreeNode(
std::format("Gfx Driver: {}", PD::Gfx::GetDriverName()))) {
m->SeparatorText("Features");
if (PD::Gfx::GetFlags() & PDGfxBackendFlags_HasClipRect)
m->Label("ClipRects");
if (PD::Gfx::GetFlags() & PDGfxBackendFlags_ReqPow2)
m->Label("Texture As Pow of 2");
if (PD::Gfx::GetFlags() & PDGfxBackendFlags_ApproxSDF)
m->Label("SDF Approximation");
m->EndTreeNode();
}
if (m->BeginTreeNode(
std::string(std::string("Input: ") + PD::Hid::GetDriverName()))) {
/* if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasKeyboard) {
+55
View File
@@ -0,0 +1,55 @@
cmake_minimum_required(VERSION 3.22)
project(test)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED true)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_EXPORT_COMPILE_COMMANDS true)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS")
if(${PD_BUILD_SHARED})
message(ERROR "3DS Only supports Static libraries")
endif()
endif()
add_subdirectory(../ palladium)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS")
add_subdirectory(../backends/3ds pd-3ds)
else()
add_subdirectory(../backends/desktop pd-desktop)
endif()
add_executable(test source/main.cpp
${BKND_SRC})
if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS")
target_link_libraries(test PUBLIC pd-3ds palladium)
else()
target_link_libraries(test PUBLIC pd-desktop palladium)
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS")
target_compile_options(palladium PRIVATE
$<$<COMPILE_LANGUAGE:C>:-Wall>
$<$<COMPILE_LANGUAGE:C>:-Wno-psabi>
$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
)
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Release")
target_compile_options(palladium PRIVATE
$<$<CONFIG:Debug>:-O0 -g>
$<$<CONFIG:Release>:-O3>
)
endif()
# set(RC_FILES
# testassets/ComicNeue.ttf
# testassets/logo.png
# testassets/test.png)
# install(FILES ${RC_FILES} DESTINATION ".")
# else()
# target_link_libraries(test PUBLIC pd-backend-3ds ctru citro3d)
# endif()
+17
View File
@@ -20,9 +20,26 @@ bool ColorTests() {
return true;
}
bool IDTests() {
std::cout << std::format("HashID32(\"1234\") -> {:016X}",
PD::HashID32("1234").Get())
<< std::endl;
std::cout << std::format("HashID32(\"1235\") -> {:016X}",
PD::HashID32("1235").Get())
<< std::endl;
std::cout << std::format("HashID64(\"1234\") -> {:016X}",
PD::HashID64("1234").Get())
<< std::endl;
std::cout << std::format("HashID64(\"1235\") -> {:016X}",
PD::HashID64("1235").Get())
<< std::endl;
return true;
}
int main() {
PD::Os::UseDriver<PD::OsDriver>();
ColorTests();
IDTests();
std::cout << PD::Os::GetTime() << std::endl;
PD::Pool<int> pool;
pool.Init(90);
+2
View File
@@ -21,6 +21,8 @@ class OsCtx {
virtual bool Mainloop() { return false; }
virtual void ClearViewPort() {}
virtual void SwapBuffers() {}
virtual int GetScreenCount() { return 1; }
virtual void DrawOnScreen(int s = 0) {}
PD::fvec2 PositionTranslate(PD::fvec2 in) {
return fvec2(in.x * pViewPort.x, in.y * pViewPort.y);
}
+2
View File
@@ -13,6 +13,8 @@ class HorizonCtr : public PD::OsCtx {
bool Mainloop() override;
void ClearViewPort() override;
void SwapBuffers() override;
int GetScreenCount() override { return 2; }
void DrawOnScreen(int s) override;
private:
struct Impl;
+17 -4
View File
@@ -208,15 +208,23 @@ int main(int argc, char** argv) {
RightStick.pColor = "#00ffff";
PD::UI7::Context ui7;
ui7.GetIO().Font = &font;
#ifdef __3DS__
ui7.AddViewPort("Default", PD::ivec4(0, 0, 320, 240));
ui7.GetIO().FontScale = 0.5f;
#else
ui7.AddViewPort("Default", PD::ivec4(0, 0, 1280, 720));
#endif
ui7.UseViewPort("Default");
bool pMetricsWin = true;
while (pOs->Mainloop()) {
PD::TT::End("OSCTX::MainLoop");
pOs->DrawOnScreen(0);
pOs->ClearViewPort();
PD::TT::Scope __st("MainLoop");
PD::TT::Beg("MainRaw");
PD::Hid::Update();
PD::Gfx::NewFrame();
PD::Li::ResetPools();
// app.Update(pOs->GetViewport(), pList);
pList.SetFontscale(0.7);
if (PD::Hid::IsEvent(PD::Hid::Event::Down, PD::Hid::Gamepad::CPLeft |
@@ -297,13 +305,14 @@ int main(int argc, char** argv) {
"#ff00ff");
}
pList.SetFont(&font);
#ifndef __3DS__
PD::TT::Beg("BuildUI7Menus");
if (auto m = ui7.BeginMenu("Test")) {
m->Label("Hello World!");
m->Image(pTex, 128.f);
ui7.EndMenu();
}
if (auto m = ui7.BeginMenu("LI DBG INFO")) {
m->PushFont(&debug_font);
m->Label("Gfx Driver: {}", PD::Gfx::GetDriverName());
m->Separator();
m->Label("LI Draw Comamnds: {}", PD::Gfx::GetNumCommands());
@@ -311,18 +320,22 @@ int main(int argc, char** argv) {
m->Label("GFX Vertices: {}", PD::Gfx::GetNumVertices());
m->Label("GFX Triangles: {}", PD::Gfx::GetNumVertices() / 3);
m->Label("GFX Indices: {}", PD::Gfx::GetNumIndices());
m->PopFont();
ui7.EndMenu();
}
ui7.MetricsMenu();
ui7.MetricsMenu(&pMetricsWin);
ui7.StyleEditor();
PD::TT::End("BuildUI7Menus");
PD::TT::Beg("UI7::Context::Update");
ui7.Update();
PD::TT::End("UI7::Context::Update");
#endif
PD::Gfx::Reset();
PD::TT::Beg("PD::Gfx::Draw");
PD::Gfx::Draw(pList);
pOs->DrawOnScreen(1);
pOs->ClearViewPort();
PD::Gfx::Draw(ui7.GetDrawData());
pOs->DrawOnScreen(0);
PD::Gfx::Draw(pList);
PD::TT::End("PD::Gfx::Draw");
pList.Clear();
PD::TT::End("MainRaw");
+18 -6
View File
@@ -16,6 +16,7 @@ struct HorizonCtr::Impl {
C3D_RenderTarget* Top = nullptr;
C3D_RenderTarget* Bottom = nullptr;
uint32_t* pSocBuf = nullptr;
int CurrentScreen = 0;
};
void HorizonCtr::Init() {
@@ -33,7 +34,7 @@ void HorizonCtr::Init() {
romfsInit();
osSetSpeedupEnable(true);
gfxInitDefault();
consoleInit(GFX_BOTTOM, nullptr);
// consoleInit(GFX_BOTTOM, nullptr);
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
impl->Top =
C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
@@ -43,7 +44,7 @@ void HorizonCtr::Init() {
C3D_RenderTargetSetOutput(impl->Bottom, GFX_BOTTOM, GFX_LEFT,
DisplayTransferFlags);
PD::Gfx::UseDriver<PD::GfxCitro3D>();
PD::Hid::UseDriver<PD::HidDriver>();
PD::Hid::UseDriver<PD::Hid3DS>();
}
void HorizonCtr::Deinit() {
@@ -61,16 +62,27 @@ void HorizonCtr::Deinit() {
bool HorizonCtr::Mainloop() {
pViewPort = ivec2(400, 240);
hidScanInput();
bool _kill = hidKeysUp() & KEY_START;
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
impl->CurrentScreen = 0;
return aptMainLoop() && !_kill;
}
void HorizonCtr::ClearViewPort() {
PD::Gfx::SetViewPort(pViewPort);
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
C3D_RenderTargetClear(impl->CurrentScreen ? impl->Bottom : impl->Top,
C3D_CLEAR_ALL, PD::Color(25, 25, 25, 25), 0);
}
void HorizonCtr::DrawOnScreen(int s) {
impl->CurrentScreen = s;
if (s == 0) {
C3D_FrameDrawOn(impl->Top);
C3D_RenderTargetClear(impl->Top, C3D_CLEAR_ALL, PD::Color(25, 25, 25, 25), 0);
pViewPort = PD::ivec2(400, 240);
} else if (s == 1) {
C3D_FrameDrawOn(impl->Bottom);
pViewPort = PD::ivec2(320, 240);
}
PD::Gfx::SetViewPort(pViewPort);
}
void HorizonCtr::SwapBuffers() { C3D_FrameEnd(0); }