32 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 eafe5c9be5 Add Drawlist Vertex and Indexcount geteter (for debugging usage only) 2026-09-05 21:28:09 +02:00
tobid7 d18e397eaf Fix The rest of UI7 Mem leaks
Throw OneFrame living objs into a pool
2026-09-05 18:06:59 +02:00
tobid7 fc5a357caa stop leaking idobj memory (and coloredit layout mem) 2026-09-05 18:06:12 +02:00
tobid7 a1cb3bf290 dx9: update device size on window size change 2026-09-05 17:18:21 +02:00
tobid7 8c1063640c format documents 2026-09-05 17:04:28 +02:00
tobid7 85f50df154 unload debugfont and add Gfx debug menu 2026-09-05 17:03:17 +02:00
tobid7 32c94e0776 fix random garbage ptr issues 2026-09-05 17:02:58 +02:00
tobid7 6b5f30b334 Fix Indexorder issues and patchfixsomehow dx9 tex filtering 2026-09-05 17:02:37 +02:00
tobid7 42cb7ce2ed No big update without msvc compiler errors :/ 2026-09-05 16:29:53 +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
57 changed files with 1759 additions and 1194 deletions
+1 -1
View File
@@ -1 +1 @@
vendor/* linguist-vendored vendor/* linguist-vendored
+1
View File
@@ -52,6 +52,7 @@ set(PD_SOURCES
source/lithium/drawlist.cpp source/lithium/drawlist.cpp
source/lithium/font.cpp source/lithium/font.cpp
source/lithium/math.cpp source/lithium/math.cpp
source/lithium/pools.cpp
# UI7 # UI7
source/ui7/io.cpp 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_VULKAN "Not implemented yet" OFF)
option(PD_ENABLE_HID_GLFW "Enable GLFW Input Driver" ON) option(PD_ENABLE_HID_GLFW "Enable GLFW Input Driver" ON)
option(PD_ENABLE_HID_NX "Enable NX Input Driver" OFF) 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... if(NOT WIN32) # cause we are not on windows...
set(PD_ENABLE_DIRECTX9 OFF) set(PD_ENABLE_DIRECTX9 OFF)
@@ -21,6 +22,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS")
set(PD_ENABLE_CITRO3D ON) set(PD_ENABLE_CITRO3D ON)
set(PD_ENABLE_HID_GLFW OFF) set(PD_ENABLE_HID_GLFW OFF)
set(PD_ENABLE_HID_NX OFF) set(PD_ENABLE_HID_NX OFF)
set(PD_ENABLE_HID3DS ON)
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "NintendoSwitch") elseif(${CMAKE_SYSTEM_NAME} STREQUAL "NintendoSwitch")
set(PD_ENABLE_OPENGL2 OFF) set(PD_ENABLE_OPENGL2 OFF)
set(PD_ENABLE_OPENGL3 ON) 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_opengl3.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_directx9.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_directx9.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_citro3d.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_glfw.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/hid_nx.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_CITRO3D}>:PD_ENABLE_CITRO3D>
$<$<BOOL:${PD_ENABLE_HID_GLFW}>:PD_ENABLE_HID_GLFW> $<$<BOOL:${PD_ENABLE_HID_GLFW}>:PD_ENABLE_HID_GLFW>
$<$<BOOL:${PD_ENABLE_HID_NX}>:PD_ENABLE_HID_NX> $<$<BOOL:${PD_ENABLE_HID_NX}>:PD_ENABLE_HID_NX>
$<$<BOOL:${PD_ENABLE_HID3DS}>:PD_ENABLE_HID3DS>
) )
# Palladium # Palladium
@@ -29,6 +29,7 @@ class GfxCitro3D : public GfxDriverBase<GfxCitro3DConfig> {
TextureFilter filter = TextureFilter::Linear) override; TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const Li::Texture& tex) override; void DeleteTexture(const Li::Texture& tex) override;
void UploadPools() override; void UploadPools() override;
void ClipRect() override;
private: private:
struct Impl; struct Impl;
@@ -29,6 +29,7 @@ class GfxDirectX9 : public GfxDriverBase<GfxDirectX9Config> {
TextureFilter filter = TextureFilter::Linear) override; TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const Li::Texture& tex) override; void DeleteTexture(const Li::Texture& tex) override;
void UploadPools() override; void UploadPools() override;
void ClipRect() override;
private: private:
struct Impl; struct Impl;
@@ -28,6 +28,7 @@ class GfxOpenGL2 : public GfxDriverBase<GfxOpenGL2Config> {
TextureFilter filter = TextureFilter::Linear) override; TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const Li::Texture& tex) override; void DeleteTexture(const Li::Texture& tex) override;
void UploadPools() override; void UploadPools() override;
void ClipRect() override;
private: private:
void pSetupShaderAttribs(u32 shader); void pSetupShaderAttribs(u32 shader);
@@ -28,6 +28,7 @@ class GfxOpenGL3 : public GfxDriverBase<GfxOpenGL3Config> {
TextureFilter filter = TextureFilter::Linear) override; TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const Li::Texture& tex) override; void DeleteTexture(const Li::Texture& tex) override;
void UploadPools() override; void UploadPools() override;
void ClipRect() override;
private: private:
u32 pShader = 0; 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
+2 -1
View File
@@ -7,4 +7,5 @@
#include <pd_system/gfx_opengl3.hpp> #include <pd_system/gfx_opengl3.hpp>
// Hid // Hid
#include <pd_system/hid_glfw.hpp> #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();"); PDLOG("GfxCitro3D::SysInit();");
impl = new Impl(); impl = new Impl();
Flags |= PDGfxBackendFlags_FlipUV_Y; Flags |= PDGfxBackendFlags_FlipUV_Y;
Flags |= PDGfxBackendFlags_HasClipRect;
Flags |= PDGfxBackendFlags_ReqPow2;
Flags |= PDGfxBackendFlags_ApproxSDF;
impl->pShaderRaw = Pica::AssembleCode(LIShaderCTR); impl->pShaderRaw = Pica::AssembleCode(LIShaderCTR);
impl->pCode = DVLB_ParseFile((uint32_t*)impl->pShaderRaw.data(), impl->pCode = DVLB_ParseFile((uint32_t*)impl->pShaderRaw.data(),
impl->pShaderRaw.size()); impl->pShaderRaw.size());
@@ -264,6 +267,14 @@ void GfxCitro3D::UploadPools() {
BufInfo_Init(buf); BufInfo_Init(buf);
BufInfo_Add(buf, GetVertexBufPtr(0), sizeof(Li::Vertex), 3, 0x210); 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 } // namespace PD
#else #else
namespace PD { 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::DeleteTexture(const Li::Texture& tex) {}
void GfxCitro3D::UploadPools() {} void GfxCitro3D::UploadPools() {}
void GfxCitro3D::ClipRect() {}
} // namespace PD } // namespace PD
#endif #endif
+28 -7
View File
@@ -112,6 +112,7 @@ void GfxDirectX9::SysInit() {
} }
if (psBlob) psBlob->Release(); if (psBlob) psBlob->Release();
if (errBlob) errBlob->Release(); if (errBlob) errBlob->Release();
Flags |= PDGfxBackendFlags_HasClipRect;
} else { } else {
PDERR( PDERR(
"GfxDirectX9::SysInit Error: pDevice is not set!\nYOu need to include " "GfxDirectX9::SysInit Error: pDevice is not set!\nYOu need to include "
@@ -175,6 +176,10 @@ void GfxDirectX9::SysReset() {
impl->Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); impl->Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
impl->Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); impl->Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
impl->Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); impl->Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
impl->Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
impl->Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
impl->Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
} }
Li::Texture GfxDirectX9::LoadTexture(const std::vector<PD::u8>& pixels, int w, Li::Texture GfxDirectX9::LoadTexture(const std::vector<PD::u8>& pixels, int w,
@@ -257,30 +262,45 @@ void GfxDirectX9::UploadPools() {
if (!impl->VBO || impl->VertexBufferSize != GetVertexPoolSize()) { if (!impl->VBO || impl->VertexBufferSize != GetVertexPoolSize()) {
if (impl->VBO) impl->VBO->Release(); if (impl->VBO) impl->VBO->Release();
impl->Device->CreateVertexBuffer(GetVertexPoolSize() * sizeof(Li::Vertex), impl->Device->CreateVertexBuffer(GetVertexPoolSize() * sizeof(Li::Vertex),
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED,
D3DPOOL_DEFAULT, &impl->VBO, nullptr); &impl->VBO, nullptr);
impl->VertexBufferSize = GetVertexPoolSize(); impl->VertexBufferSize = GetVertexPoolSize();
} }
if (!impl->IBO || impl->IndexBufferSize != GetIndexPoolSize()) { if (!impl->IBO || impl->IndexBufferSize != GetIndexPoolSize()) {
if (impl->IBO) impl->IBO->Release(); if (impl->IBO) impl->IBO->Release();
impl->Device->CreateIndexBuffer( impl->Device->CreateIndexBuffer(GetIndexPoolSize() * sizeof(u16),
GetIndexPoolSize() * sizeof(u16), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,
D3DFMT_INDEX16, D3DPOOL_DEFAULT, &impl->IBO, nullptr); D3DPOOL_MANAGED, &impl->IBO, nullptr);
impl->IndexBufferSize = GetIndexPoolSize(); impl->IndexBufferSize = GetIndexPoolSize();
} }
void* vptr; void* vptr;
impl->VBO->Lock(0, 0, &vptr, D3DLOCK_DISCARD); impl->VBO->Lock(0, 0, &vptr, 0);
memcpy(vptr, GetVertexBufPtr(0), memcpy(vptr, GetVertexBufPtr(0),
GetVertexPoolSize() * sizeof(PD::Li::Vertex)); GetVertexPoolSize() * sizeof(PD::Li::Vertex));
impl->VBO->Unlock(); impl->VBO->Unlock();
void* iptr; void* iptr;
impl->IBO->Lock(0, 0, &iptr, D3DLOCK_DISCARD); impl->IBO->Lock(0, 0, &iptr, 0);
memcpy(iptr, GetIndexBufPtr(0), GetIndexPoolSize() * sizeof(u16)); memcpy(iptr, GetIndexBufPtr(0), GetIndexPoolSize() * sizeof(u16));
impl->IBO->Unlock(); 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 } // namespace PD
#else #else
namespace PD { namespace PD {
@@ -300,5 +320,6 @@ Li::Texture GfxDirectX9::LoadTexture(const std::vector<PD::u8>& pixels, int w,
} }
void GfxDirectX9::DeleteTexture(const Li::Texture& tex) {} void GfxDirectX9::DeleteTexture(const Li::Texture& tex) {}
void GfxDirectX9::UploadPools() {} void GfxDirectX9::UploadPools() {}
void GfxDirectX9::ClipRect() {}
} // namespace PD } // namespace PD
#endif #endif
+12
View File
@@ -73,6 +73,7 @@ void GfxOpenGL2::pSetupShaderAttribs(u32 shader) {
} }
void GfxOpenGL2::SysInit() { void GfxOpenGL2::SysInit() {
Flags |= PDGfxBackendFlags_HasClipRect;
pShader = CreateShaderProgram(pVertCode, pFragCode); pShader = CreateShaderProgram(pVertCode, pFragCode);
glUseProgram(pShader); glUseProgram(pShader);
glGenBuffers(1, &VBO); glGenBuffers(1, &VBO);
@@ -183,6 +184,16 @@ void GfxOpenGL2::UploadPools() {
glBufferData(GL_ELEMENT_ARRAY_BUFFER, GetIndexPoolSize() * sizeof(u16), glBufferData(GL_ELEMENT_ARRAY_BUFFER, GetIndexPoolSize() * sizeof(u16),
GetIndexBufPtr(0), GL_DYNAMIC_DRAW); 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 } // namespace PD
#else #else
namespace PD { 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::DeleteTexture(const Li::Texture& tex) {}
void GfxOpenGL2::pSetupShaderAttribs(u32 shader) {} void GfxOpenGL2::pSetupShaderAttribs(u32 shader) {}
void GfxOpenGL2::UploadPools() {} void GfxOpenGL2::UploadPools() {}
void GfxOpenGL2::ClipRect() {}
} // namespace PD } // namespace PD
#endif #endif
+12
View File
@@ -11,6 +11,7 @@
namespace PD { namespace PD {
void GfxOpenGL3::SysInit() { void GfxOpenGL3::SysInit() {
Flags |= PDGfxBackendFlags_HasClipRect;
std::string vcode = SpirvHelper::SPV2GLSL( std::string vcode = SpirvHelper::SPV2GLSL(
std::vector<unsigned int>( std::vector<unsigned int>(
Shaders::VertexShader, Shaders::VertexShader,
@@ -159,6 +160,16 @@ void GfxOpenGL3::UploadPools() {
glBindVertexArray(0); 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 } // namespace PD
#else #else
namespace PD { 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::DeleteTexture(const Li::Texture& tex) {}
void GfxOpenGL3::UploadPools() {} void GfxOpenGL3::UploadPools() {}
void GfxOpenGL3::ClipRect() {}
} // namespace PD } // namespace PD
#endif #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() { void HidGlfw::Update() {
HidDriver::Update(); // clear stats HidDriver::Update(); // clear stats
+1 -1
View File
@@ -11,7 +11,7 @@ struct HidNX::Impl {
HidNX::HidNX() : HidDriver("HidNX") { impl = new Impl; } HidNX::HidNX() : HidDriver("HidNX") { impl = new Impl; }
HidNX::~HidNX() {} HidNX::~HidNX() { delete impl; }
void HidNX::Update() { void HidNX::Update() {
HidDriver::Update(); // clear stats HidDriver::Update(); // clear stats
+1 -22
View File
@@ -56,21 +56,9 @@ struct PD_API Mat4 {
constexpr float* Ptr() { return m.data(); } constexpr float* Ptr() { return m.data(); }
constexpr const float* Ptr() const { return m.data(); } constexpr const float* Ptr() const { return m.data(); }
constexpr float& operator()(int row, int col) { constexpr float& operator()(int row, int col) { return m[col * 4 + row]; }
#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) const { 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]; return m[col * 4 + row];
#endif
} }
constexpr Mat4 operator*(const Mat4& v) const { 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, constexpr static Mat4 Ortho(float l, float r, float b, float t, float n,
float f) { float f) {
Mat4 ret; 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, 0) = 2.0f / (r - l);
ret(0, 3) = -(r + l) / (r - l); ret(0, 3) = -(r + l) / (r - l);
ret(1, 1) = 2.0f / (t - b); ret(1, 1) = 2.0f / (t - b);
ret(1, 3) = -(t + b) / (t - b); ret(1, 3) = -(t + b) / (t - b);
ret(2, 2) = -2.0f / (f - n); ret(2, 2) = -2.0f / (f - n);
ret(2, 3) = -(f + n) / (f - n); ret(2, 3) = -(f + n) / (f - n);
#endif
ret(3, 3) = 1.f; ret(3, 3) = 1.f;
return ret; return ret;
} }
+63 -13
View File
@@ -2,14 +2,18 @@
#include <pd/core/mat.hpp> #include <pd/core/mat.hpp>
#include <pd/drivers/interface.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> #include <pd/lithium/texture.hpp>
using PDGfxBackendFlags = PD::u32; using PDGfxBackendFlags = PD::u32;
enum PDGfxBackendFlags_ { enum PDGfxBackendFlags_ {
PDGfxBackendFlags_None = 0, PDGfxBackendFlags_None = 0,
PDGfxBackendFlags_FlipUV_Y = 1 << 0, // Essential for font loading 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 { namespace PD {
@@ -37,7 +41,7 @@ class PD_API GfxDriver : public DriverInterface {
return Li::Texture(); return Li::Texture();
} }
virtual void DeleteTexture(const Li::Texture& tex) {} 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; } Li::Texture::Ptr GetWhiteTexture() { return &pWhite; }
PDGfxBackendFlags GetFlags() { return Flags; } PDGfxBackendFlags GetFlags() { return Flags; }
@@ -64,6 +68,7 @@ class PD_API GfxDriver : public DriverInterface {
virtual void SysReset() {} virtual void SysReset() {}
virtual void Submit(size_t count, size_t start) {} virtual void Submit(size_t count, size_t start) {}
virtual void UploadPools() {} // not every driver requires it virtual void UploadPools() {} // not every driver requires it
virtual void ClipRect() {}
void RegisterTexture(const Li::Texture& tex); void RegisterTexture(const Li::Texture& tex);
void UnregisterTexture(const Li::Texture& tex); void UnregisterTexture(const Li::Texture& tex);
@@ -79,6 +84,8 @@ class PD_API GfxDriver : public DriverInterface {
// State Variables oder so // State Variables oder so
TextureID CurrentTex = 0; TextureID CurrentTex = 0;
bool CurrentTexIsSDF = false; bool CurrentTexIsSDF = false;
bool CurrentHasClip = false;
fvec4 CurrentClip = 0;
Mat4 Projection; Mat4 Projection;
ivec2 ViewPort; ivec2 ViewPort;
std::unordered_map<TextureID, Li::Texture> pTextureRegestry; std::unordered_map<TextureID, Li::Texture> pTextureRegestry;
@@ -110,27 +117,72 @@ class GfxDriverBase : public GfxDriver {
pWhite = LoadTexture(img, 16, 16); 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(); 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(); UploadPools();
size_t index = 0;
size_t ioff = start_idx;
while (index < commands.size()) { while (index < commands.size()) {
CurrentTex = commands[index].Tex; CurrentTex = commands[index].Tex;
CurrentTexIsSDF = commands[index].SDF; CurrentTexIsSDF = commands[index].SDF;
CurrentHasClip = commands[index].ClipRectUsed;
CurrentClip = commands[index].ClipRect;
if (!CurrentTex) { if (!CurrentTex) {
CurrentTex = pWhite.GetID(); CurrentTex = pWhite.GetID();
} }
size_t startidx = commands[index].FirstIndex;
size_t num_indices = 0; size_t num_indices = 0;
ClipRect();
while (index < commands.size() && while (index < commands.size() &&
CurrentTexIsSDF == commands[index].SDF && CurrentTexIsSDF == commands[index].SDF &&
(CurrentTex == commands[index].Tex || (CurrentTex == commands[index].Tex ||
(CurrentTex == pWhite.GetID() && commands[index].Tex == 0))) { (CurrentTex == pWhite.GetID() && commands[index].Tex == 0)) &&
CurrentClip == commands[index].ClipRect &&
CurrentHasClip == commands[index].ClipRectUsed) {
num_indices += commands[index].IndexCount; num_indices += commands[index].IndexCount;
index++; index++;
} }
Submit(num_indices, startidx); if (num_indices > 0) {
pCountDrawcalls++; Submit(num_indices, ioff);
ioff += num_indices;
pCountDrawcalls++;
}
} }
} }
@@ -210,9 +262,7 @@ class PD_API Gfx {
static void SetViewPort(const ivec2& vp) { driver->SetViewPort(vp); } static void SetViewPort(const ivec2& vp) { driver->SetViewPort(vp); }
static void SetViewPort(int w, int h) { driver->SetViewPort(w, h); } static void SetViewPort(int w, int h) { driver->SetViewPort(w, h); }
static void Reset() { driver->Reset(); } static void Reset() { driver->Reset(); }
static void Draw(const Pool<Li::Command>& commands) { static void Draw(const Li::Drawlist& dl) { driver->Draw(dl); }
driver->Draw(commands);
}
static Li::Texture LoadTexture(const std::vector<PD::u8>& pixels, int w, static Li::Texture LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h, int h,
TextureFormat type = TextureFormat::RGBA32, TextureFormat type = TextureFormat::RGBA32,
+3
View File
@@ -28,6 +28,9 @@ class Command {
// Todo: implement // Todo: implement
size_t VertexCountMax = 0; size_t VertexCountMax = 0;
size_t IndexCountMax = 0; size_t IndexCountMax = 0;
// ClipRect
PD::fvec4 ClipRect;
bool ClipRectUsed = false;
}; };
} // namespace Li } // namespace Li
} // namespace PD } // namespace PD
+24 -2
View File
@@ -42,6 +42,22 @@ class PD_API Drawlist {
void Copy(Drawlist& other); void Copy(Drawlist& other);
void Optimize(); void Optimize();
void Clear(); 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;
for (const auto& cmd : pCommands) count += cmd.VertexCount;
return count;
}
size_t GetNumIndices() const {
size_t count = 0;
for (const auto& cmd : pCommands) count += cmd.IndexCount;
return count;
}
/** Command Allocation */ /** Command Allocation */
Command& NewCommand(); Command& NewCommand();
@@ -112,12 +128,18 @@ class PD_API Drawlist {
void PrimTriangle(Command& cmd, const fvec2& a, const fvec2& b, void PrimTriangle(Command& cmd, const fvec2& a, const fvec2& b,
const fvec2& c, const PD::Color& color); 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: private:
Texture pCurrentTexture; Texture pCurrentTexture;
int pCurrentLayer = 0;
Pool<Command> pCommands; Pool<Command> pCommands;
Pool<fvec2> pPath; Pool<fvec2> pPath;
Pool<Vertex> pVertices; std::vector<fvec4> pClipRects;
Pool<u16> pIndices;
Font* pFont = nullptr; Font* pFont = nullptr;
float pFontScale = 1.f; 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, void LoadTTF(const std::vector<u8>& data, int px_height = 32,
LiFontFlags flags = LiFontFlags_None); 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 * Getter for Codepoint reference
* @return codepoint dataholder reference * @return codepoint dataholder reference
+2 -1
View File
@@ -4,4 +4,5 @@
#include <pd/lithium/drawlist.hpp> #include <pd/lithium/drawlist.hpp>
#include <pd/lithium/font.hpp> #include <pd/lithium/font.hpp>
#include <pd/lithium/math.hpp> #include <pd/lithium/math.hpp>
#include <pd/lithium/vertex.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
+76 -74
View File
@@ -1,75 +1,77 @@
#pragma once #pragma once
/* /*
MIT License MIT License
Copyright (c) 2024 - 2026 René Amthor (tobid7) Copyright (c) 2024 - 2026 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <pd/ui7/container/container.hpp> #include <pd/ui7/container/container.hpp>
#include <pd/ui7/io.hpp> #include <pd/ui7/io.hpp>
#include <pd/ui7/layout.hpp> #include <pd/ui7/layout.hpp>
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
/** /**
* Color Editor (Creating a PopUP when clicking) * Color Editor (Creating a PopUP when clicking)
*/ */
class PD_API ColorEdit : public Container { class PD_API ColorEdit : public Container {
public: public:
/** /**
* Constructor * Constructor
* @param label Label of the Button * @param label Label of the Button
* @param pos Base Position * @param pos Base Position
* @param lr Reference to the Renderer * @param lr Reference to the Renderer
*/ */
ColorEdit(const std::string& label, u32* color, UI7::IO& io) { ColorEdit(const std::string& label, u32* color, UI7::IO& io) {
// PD::Assert(color != nullptr, "Input Color Address is null!"); // PD::Assert(color != nullptr, "Input Color Address is null!");
this->label = label; this->label = label;
this->color_ref = color; this->color_ref = color;
this->initial_color = *color; this->initial_color = *color;
this->tdim = io.Font->GetTextBounds(label.c_str(), io.FontScale); this->tdim = io.Font->GetTextBounds(label.c_str(), io.FontScale);
} }
~ColorEdit() = default; ~ColorEdit() {
if (layout) delete layout;
/** }
* Override for the Input Handler
* @note This function is usally called by Menu::Update /**
*/ * Override for the Input Handler
void HandleInput() override; * @note This function is usally called by Menu::Update
/** */
* Override for the Rendering Handler void HandleInput() override;
* @note This function is usally called by Menu::Update /**
* */ * Override for the Rendering Handler
void Draw() override; * @note This function is usally called by Menu::Update
* */
/** Function to Update Size if framepadding changes */ void Draw() override;
void Update() override;
/** Function to Update Size if framepadding changes */
private: void Update() override;
fvec2 tdim; ///< Text size
u32* color_ref = nullptr; ///< Color Reference private:
u32 initial_color; ///< Initial Color fvec2 tdim; ///< Text size
std::string label; ///< Label of the Button u32* color_ref = nullptr; ///< Color Reference
Layout* layout; ///< Layout to open u32 initial_color; ///< Initial Color
bool is_shown = false; ///< AHow Layout Editor std::string label; ///< Label of the Button
}; Layout* layout = nullptr; ///< Layout to open
} // namespace UI7 bool is_shown = false; ///< AHow Layout Editor
};
} // namespace UI7
} // namespace PD } // namespace PD
+201 -179
View File
@@ -1,179 +1,201 @@
#pragma once #pragma once
/* /*
MIT License MIT License
Copyright (c) 2024 - 2026 René Amthor (tobid7) Copyright (c) 2024 - 2026 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <pd/core/core.hpp> #include <pd/core/core.hpp>
#include <pd/pd_p_api.hpp> #include <pd/pd_p_api.hpp>
#include <pd/ui7/io.hpp> #include <pd/ui7/io.hpp>
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
/** /**
* Container base class all Objects are based on * Container base class all Objects are based on
* @note this class can be used to create custom Objects as well * @note this class can be used to create custom Objects as well
*/ */
class PD_API Container { class PD_API Container {
public: public:
Container() = default; Container() = default;
/** /**
* Constructor with pos and Size * Constructor with pos and Size
* @param pos Container Position * @param pos Container Position
* @param size Container Size * @param size Container Size
*/ */
Container(const fvec2& pos, const fvec2& size) : pos(pos), size(size) {} Container(const fvec2& pos, const fvec2& size) : pos(pos), size(size) {}
/** /**
* Constructor by a vec4 box * Constructor by a vec4 box
* @param box Box containing top left and bottom right coords * @param box Box containing top left and bottom right coords
*/ */
Container(const fvec4& box) Container(const fvec4& box)
: pos(fvec2(box.x, box.y)), size(fvec2(box.z - box.x, box.w - box.y)) {} : 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 * Init Function Required by every Object that uses
* Render or Input functions * Render or Input functions
* @param io IO Reference * @param io IO Reference
* @param l Drawlist Reference * @param l Drawlist Reference
*/ */
void Init(UI7::IO* io, Li::Drawlist* l) { void Init(UI7::IO* io, Li::Drawlist* l) {
list = l; list = l;
this->io = io; this->io = io;
// this->screen = io->Ren->CurrentScreen(); pFont = io->Font;
} // this->screen = io->Ren->CurrentScreen();
}
void SetClipRect(fvec4 clip) {
pClipRect = clip; void SetClipRect(fvec4 clip) {
pCLipRectUsed = true; pClipRect = clip;
} pCLipRectUsed = true;
}
/** Setter for Position */
void SetPos(const fvec2& pos) { this->pos = pos; } /** Setter for Position */
/** Setter for Size */ void SetPos(const fvec2& pos) { this->pos = pos; }
void SetSize(const fvec2& size) { this->size = size; } /** Setter for Size */
/** Getter for Position */ void SetSize(const fvec2& size) { this->size = size; }
fvec2 GetPos() { return pos; } /** Getter for Position */
/** Getter for Size */ fvec2 GetPos() { return pos; }
fvec2 GetSize() { return size; } /** Getter for Size */
/** fvec2 GetSize() { return size; }
* Get the Containers Final Position Li::Font* GetFont() { return pFont; }
* for Rendering and Input (if it has a parent Object) /**
*/ * Get the Containers Final Position
fvec2 FinalPos() { * for Rendering and Input (if it has a parent Object)
vec2 res = pos; */
if (parent) { fvec2 FinalPos() {
/// Probably should use parant->FinalPos here vec2 res = pos;
res += parent->GetPos(); if (parent) {
} /// Probably should use parant->FinalPos here
return res; res += parent->GetPos();
} }
return res;
/** Setter for Parent Container */ }
void SetParent(Container* v) { parent = v; }
/** Getter for Parent Container */ /** Setter for Parent Container */
Container* GetParent() { return parent; } void SetParent(Container* v) { parent = v; }
/** Getter for Parent Container */
/** Check if Rendering can be skipped */ Container* GetParent() { return parent; }
bool Skippable() const { return skippable; }
/** Check if the Object got a timeout (ID OBJ Relevant) */ /** Check if Rendering can be skipped */
bool Removable() const { return rem; } bool Skippable() const { return skippable; }
/** Check if the Object got a timeout (ID OBJ Relevant) */
/** bool Removable() const { return rem; }
* Handles Scrolling by scrolling pos as well as
* Time for Remove for ID Objects /**
* @param scrolling Scrolling Position * Handles Scrolling by scrolling pos as well as
* @param viewport Viewport to check if the Object is skippable * Time for Remove for ID Objects
*/ * @param scrolling Scrolling Position
void HandleScrolling(fvec2 scrolling, fvec4 viewport); * @param viewport Viewport to check if the Object is skippable
/** Template function for Input Handling */ */
virtual void HandleInput() {} void HandleScrolling(fvec2 scrolling, fvec4 viewport);
/** Tamplate function for Object rendering */ /** Template function for Input Handling */
virtual void Draw() {} virtual void HandleInput() {}
/** Template function to update internal data (if needed) */ /** Tamplate function for Object rendering */
virtual void Update() {} virtual void Draw() {}
/** Template function to update internal data (if needed) */
/** Internal function */ virtual void Update() {}
void PreDraw(); /** Template as well as base func for Pool based Containers */
/** Internal function */ virtual void Reset() {
void PostDraw(); pos = 0;
size = 0;
/** Internal Input Handler */ parent = nullptr;
void HandleInternalInput(); id = 0;
pFlags = 0;
/** skippable = false;
* Function to unlock Input after Rendering is done in rem = false;
* Menu::Update inp_done = false;
* @note This is used if the Object got Input Handled directly after creation pSelected = false;
* to not check for Inputs twice pPressed = false;
*/ pPressedTwice = false;
void UnlockInput() { inp_done = false; } pCLipRectUsed = false;
pClipRect = 0;
/** Get the Objects ID (if it is an ID object)*/ io = nullptr;
u32 GetID() const { return id; } list = nullptr;
/** last_use = 0;
* Set ID for ID Objects }
* @param id Object ID (hashed prefix+objname+prefixed_counter)
*/ /** Internal function */
void SetID(u32 id) { this->id = id; } void PreDraw();
/** Internal function */
/** Get a reference to IO */ void PostDraw();
UI7::IO* GetIO() { return io; }
/** Internal Input Handler */
protected: void HandleInternalInput();
/** used to skip Input/Render preocessing ot not*/
bool skippable = false; /**
/** value to check if an ID Object goes out of lifetime*/ * Function to unlock Input after Rendering is done in
bool rem = false; * Menu::Update
/** Time of the last use (set by HandleScrolling)*/ * @note This is used if the Object got Input Handled directly after creation
u64 last_use = 0; * to not check for Inputs twice
/** Input done or not for current frame*/ */
bool inp_done = false; void UnlockInput() { inp_done = false; }
/** Reference to the Screen to draw the Object on*/
// Screen::Ref screen; /** Get the Objects ID (if it is an ID object)*/
/** Container Position*/ u32 GetID() const { return id; }
fvec2 pos; /**
/** Container Size*/ * Set ID for ID Objects
fvec2 size; * @param id Object ID (hashed prefix+objname+prefixed_counter)
/** Reference to the Drawlist to Draw to*/ */
Li::Drawlist* list; void SetID(u32 id) { this->id = id; }
/** IO Reference for Renderer and Theme */
UI7::IO* io; /** Get a reference to IO */
/** Reference to the parent container*/ UI7::IO* GetIO() { return io; }
Container* parent;
/** Object ID (0 if unused)*/ protected:
u32 id = 0; /** used to skip Input/Render preocessing ot not*/
/** Internal Flags */ bool skippable = false;
u32 pFlags = 0; /** value to check if an ID Object goes out of lifetime*/
/** Is Selected? */ bool rem = false;
bool pSelected = false; /** Time of the last use (set by HandleScrolling)*/
/** Was Pressed */ u64 last_use = 0;
bool pPressed = false; /** Input done or not for current frame*/
/** Was Pressed Twice */ bool inp_done = false;
bool pPressedTwice = false; /** Reference to the Screen to draw the Object on*/
/** ClipRect */ // Screen::Ref screen;
fvec4 pClipRect; /** Container Position*/
/** Clip Rect used */ fvec2 pos;
bool pCLipRectUsed = false; /** Container Size*/
}; fvec2 size;
} // namespace UI7 /** Reference to the Drawlist to Draw to*/
} // namespace PD Li::Drawlist* list = nullptr;
/** IO Reference for Renderer and Theme */
UI7::IO* io = nullptr;
/** Reference to the parent container*/
Container* parent = nullptr;
/** Object ID (0 if unused)*/
u32 id = 0;
/** Internal Flags */
u32 pFlags = 0;
/** Is Selected? */
bool pSelected = false;
/** Was Pressed */
bool pPressed = false;
/** Was Pressed Twice */
bool pPressedTwice = false;
/** ClipRect */
fvec4 pClipRect;
/** Clip Rect used */
bool pCLipRectUsed = false;
Li::Font* pFont = nullptr;
};
} // namespace UI7
} // namespace PD
+10 -1
View File
@@ -23,9 +23,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <functional>
#include <pd/ui7/container/container.hpp> #include <pd/ui7/container/container.hpp>
#include <pd/ui7/io.hpp> #include <pd/ui7/io.hpp>
#include <functional>
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
@@ -38,6 +38,7 @@ namespace UI7 {
*/ */
class PD_API DynObj : public Container { class PD_API DynObj : public Container {
public: public:
DynObj() {}
/** /**
* Button Object constructor * Button Object constructor
* @param label Label of the Button * @param label Label of the Button
@@ -69,6 +70,14 @@ class PD_API DynObj : public Container {
/** Function to Update Size if framepadding changes */ /** Function to Update Size if framepadding changes */
void Update() override; void Update() override;
void Reset() override {
Container::Reset();
color = UI7Color_Button;
pressed = false;
pRenFun = nullptr;
pInp = nullptr;
}
private: private:
UI7Color color = UI7Color_Button; ///< current button color UI7Color color = UI7Color_Button; ///< current button color
bool pressed = false; ///< ispressed value bool pressed = false; ///< ispressed value
+8
View File
@@ -32,6 +32,7 @@ namespace UI7 {
*/ */
class PD_API Image : public Container { class PD_API Image : public Container {
public: public:
Image() {}
/** /**
* Constructor for the Image Object * Constructor for the Image Object
* @param img Image Texture Reference * @param img Image Texture Reference
@@ -57,6 +58,13 @@ class PD_API Image : public Container {
* */ * */
void Draw() override; void Draw() override;
void Reset() override {
Container::Reset();
img = Li::Texture();
newsize = 0.f;
cuv = Li::Rect();
}
private: private:
Li::Texture img; ///< Texture Li::Texture img; ///< Texture
fvec2 newsize = 0.f; ///< New Size fvec2 newsize = 0.f; ///< New Size
+8
View File
@@ -32,6 +32,7 @@ namespace UI7 {
*/ */
class PD_API Label : public Container { class PD_API Label : public Container {
public: public:
Label() {}
/** /**
* Constructor for Label Object * Constructor for Label Object
* @param label Label [Text] to Draw * @param label Label [Text] to Draw
@@ -54,6 +55,13 @@ class PD_API Label : public Container {
*/ */
void Update() override; void Update() override;
void Reset() override {
Container::Reset();
tdim = 0;
color = UI7Color_Text;
label.clear();
}
private: private:
fvec2 tdim; ///< Text Size fvec2 tdim; ///< Text Size
UI7Color color = UI7Color_Text; ///< Color UI7Color color = UI7Color_Text; ///< Color
+4
View File
@@ -58,6 +58,8 @@ enum UI7MenuFlags_ {
enum UI7LayoutFlags_ { enum UI7LayoutFlags_ {
UI7LayoutFlags_None = 0, ///< No Flags used UI7LayoutFlags_None = 0, ///< No Flags used
UI7LayoutFlags_UseClipRect = 1 << 0, ///< Enable ClipRect UI7LayoutFlags_UseClipRect = 1 << 0, ///< Enable ClipRect
UI7LayoutFlags_HzScrolling = 1 << 1, ///< Scrolling Horizontal
UI7LayoutFlags_VtScrolling = 1 << 2, ///< Scrolling Vertical
}; };
/** UI7 Context Flags */ /** UI7 Context Flags */
@@ -85,6 +87,8 @@ enum UI7LytAdd_ {
UI7LytAdd_NoCursorUpdate = 1 << 0, ///< Add without cursor alignment UI7LytAdd_NoCursorUpdate = 1 << 0, ///< Add without cursor alignment
UI7LytAdd_NoScrollHandle = 1 << 1, ///< Skip HandleScrolling UI7LytAdd_NoScrollHandle = 1 << 1, ///< Skip HandleScrolling
UI7LytAdd_Front = 1 << 2, ///< Add in front of the list 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
}; };
/** /**
+23 -7
View File
@@ -31,16 +31,14 @@ SOFTWARE.
#include <pd/ui7/viewport.hpp> #include <pd/ui7/viewport.hpp>
namespace PD { namespace PD {
class Context;
namespace UI7 { namespace UI7 {
class Label;
class Image;
class DynObj;
class PD_API IO { class PD_API IO {
public: public:
IO() : DeltaStats(60), CurrentViewPort("", 0) { IO();
/** Probably not the best solution i guess */ ~IO();
// CurrentViewPort =
// ViewPort::New("Default", ivec4(ivec2(0, 0), pCtx.Gfx()->ViewPort));
}
~IO() {}
/** /**
* IO Update Internal Variables * IO Update Internal Variables
@@ -83,6 +81,12 @@ class PD_API IO {
u32 NumVertices = 0; ///< Debug Vertices Num u32 NumVertices = 0; ///< Debug Vertices Num
u32 NumIndices = 0; ///< Debug Indices Num u32 NumIndices = 0; ///< Debug Indices Num
std::vector<u32> MenuOrder; std::vector<u32> MenuOrder;
std::vector<Li::Font*> FontStack;
// Pools
PD::Pool<UI7::Label> LabelPool;
PD::Pool<UI7::Image> ImagePool;
PD::Pool<UI7::DynObj> DynObjPool;
// DrawlistApi // DrawlistApi
void RegisterDrawlist(const UI7::ID& id, Li::Drawlist* v) { void RegisterDrawlist(const UI7::ID& id, Li::Drawlist* v) {
@@ -104,6 +108,18 @@ class PD_API IO {
return ViewPorts[id.RawID()]; 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; UI7::InputHandler InputHandler;
}; };
} // namespace UI7 } // namespace UI7
+5 -1
View File
@@ -47,7 +47,7 @@ class PD_API Layout {
Size = 0; Size = 0;
WorkRect = fvec4(IO.MenuPadding, Size - (fvec2(2) * IO.MenuPadding)); WorkRect = fvec4(IO.MenuPadding, Size - (fvec2(2) * IO.MenuPadding));
} }
~Layout() = default; ~Layout();
/** SECTION CONTAINERS */ /** SECTION CONTAINERS */
/** /**
@@ -127,6 +127,8 @@ class PD_API Layout {
void CursorInit(); void CursorInit();
void SameLine(); void SameLine();
void CursorMove(const fvec2& size); void CursorMove(const fvec2& size);
void PushFont(Li::Font* f) { IO.PushFont(f); }
void PopFont() { IO.PopFont(); }
bool ObjectWorkPos(fvec2& movpos); bool ObjectWorkPos(fvec2& movpos);
@@ -163,6 +165,8 @@ class PD_API Layout {
void SetAlign(UI7Align a) { Alignment = a; } void SetAlign(UI7Align a) { Alignment = a; }
void NextAlign(UI7Align a) { TempAlign = a; } void NextAlign(UI7Align a) { TempAlign = a; }
void HandleScrolling();
void Update(); void Update();
fvec2 DbgScrollOffset() { return ScrollOffset; } fvec2 DbgScrollOffset() { return ScrollOffset; }
+4 -2
View File
@@ -82,7 +82,7 @@ class PD_API Menu {
Container* r = pLayout.FindObject(id); Container* r = pLayout.FindObject(id);
if (!r) { if (!r) {
r = new UI7::DragData<T>(label, data, num_elms, pIO, min, max, step, r = new UI7::DragData<T>(label, data, num_elms, pIO, min, max, step,
precision); precision);
// Isnt This exactly the same line??? // Isnt This exactly the same line???
// r = UI7::DragData<T>::New(label, data, num_elms, pIO, min, max, step, // r = UI7::DragData<T>::New(label, data, num_elms, pIO, min, max, step,
// precision); // precision);
@@ -110,7 +110,6 @@ class PD_API Menu {
void EndTreeNode(); void EndTreeNode();
void HandleFocus(); void HandleFocus();
void HandleScrolling();
void HandleTitlebarActions(); void HandleTitlebarActions();
void DrawBaseLayout(); void DrawBaseLayout();
@@ -120,6 +119,9 @@ class PD_API Menu {
} }
Container* FindObject(u32 id) { return pLayout.FindObject(id); } Container* FindObject(u32 id) { return pLayout.FindObject(id); }
void PushFont(Li::Font* f) { pIO.PushFont(f); }
void PopFont() { pIO.PopFont(); }
void Update(); void Update();
void SetSize(PD::fvec2 size) { pLayout.SetSize(size); } void SetSize(PD::fvec2 size) { pLayout.SetSize(size); }
+1 -2
View File
@@ -56,8 +56,7 @@ class PD_API Context {
void AddViewPort(const ID& id, const ivec4& vp); void AddViewPort(const ID& id, const ivec4& vp);
void UseViewPort(const ID& id); void UseViewPort(const ID& id);
void Update(); void Update();
Menu* BeginMenu(const ID& id, UI7MenuFlags flags = 0, Menu* BeginMenu(const ID& id, UI7MenuFlags flags = 0, bool* pShow = nullptr);
bool* pShow = nullptr);
Menu* CurrentMenu() { return pCurrent; } Menu* CurrentMenu() { return pCurrent; }
void EndMenu(); void EndMenu();
void AboutMenu(bool* show = nullptr); void AboutMenu(bool* show = nullptr);
-5
View File
@@ -85,13 +85,8 @@ PD_API Mat4 Mat4::Perspective(float fov, float aspect, float n, float f) {
Mat4 ret; Mat4 ret;
ret(0, 0) = 1.f / (aspect * _fov); ret(0, 0) = 1.f / (aspect * _fov);
ret(1, 1) = 1.f / _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, 2) = -(f + n) / (f - n);
ret(2, 3) = -(2.f * f * n) / (f - n); ret(2, 3) = -(2.f * f * n) / (f - n);
#endif
ret(3, 2) = -1.f; ret(3, 2) = -1.f;
ret(3, 3) = 0.0f; ret(3, 3) = 0.0f;
return ret; return ret;
+44 -14
View File
@@ -1,23 +1,48 @@
#include <pd/drivers/gfx.hpp> #include <pd/drivers/gfx.hpp>
#include <pd/lithium/command.hpp> #include <pd/lithium/command.hpp>
#include <pd/lithium/pools.hpp>
namespace PD { namespace PD {
namespace Li { namespace Li {
void Command::Reserve(size_t vtx, size_t idx) { void Command::Reserve(size_t vtx, size_t idx) {
auto& vpool = GetVertexPool();
auto& ipool = GetIndexPool();
if (VertexCountMax == 0) { if (VertexCountMax == 0) {
FirstVertex = Gfx::AllocateVertices(vtx, (PD::ptr)this); FirstVertex = vpool.size();
vpool.Allocate(vtx);
VertexCountMax = vtx; VertexCountMax = vtx;
} else { } else {
Gfx::ExpandVertices(vtx, (PD::ptr)this); if (vpool.size() == FirstVertex + VertexCountMax) {
VertexCountMax += vtx; 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) { if (IndexCountMax == 0) {
FirstIndex = Gfx::AllocateIndices(idx, (PD::ptr)this); FirstIndex = ipool.size();
ipool.Allocate(idx);
IndexCountMax = idx; IndexCountMax = idx;
} else { } else {
Gfx::ExpandIndices(idx, (PD::ptr)this); if (ipool.size() == FirstIndex + IndexCountMax) {
IndexCountMax += idx; 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; VertexCount = 0;
VertexCountMax = 0; VertexCountMax = 0;
IndexCountMax = 0; IndexCountMax = 0;
ClipRect = 0.f;
ClipRectUsed = false;
} }
Command& Command::Add(const Vertex& vtx) { Command& Command::Add(const Vertex& vtx) {
if (VertexCount <= VertexCountMax) if (VertexCount < VertexCountMax) {
Gfx::PutVertex(FirstVertex + VertexCount++, vtx, (PD::ptr)this); GetVertexPool()[FirstVertex + VertexCount++] = vtx;
}
return *this; return *this;
} }
Command& Command::Add(u16 idx) { Command& Command::Add(u16 idx) {
if (IndexCount <= IndexCountMax) if (IndexCount < IndexCountMax) {
Gfx::PutIndex(FirstIndex + IndexCount++, FirstVertex + VertexCount + idx, GetIndexPool()[FirstIndex + IndexCount++] =
(PD::ptr)this); static_cast<u16>(VertexCount + idx);
}
return *this; return *this;
} }
Command& Command::Add(u16 a, u16 b, u16 c) { Command& Command::Add(u16 a, u16 b, u16 c) {
if (IndexCount + 3 <= IndexCountMax) { if (IndexCount + 3 <= IndexCountMax) {
auto& ip = GetIndexPool();
size_t idx = FirstIndex + IndexCount; size_t idx = FirstIndex + IndexCount;
Gfx::PutIndex(idx + 0, FirstVertex + VertexCount + a, (PD::ptr)this); ip[idx + 0] = static_cast<u16>(VertexCount + a);
Gfx::PutIndex(idx + 1, FirstVertex + VertexCount + b, (PD::ptr)this); ip[idx + 1] = static_cast<u16>(VertexCount + b);
Gfx::PutIndex(idx + 2, FirstVertex + VertexCount + c, (PD::ptr)this); ip[idx + 2] = static_cast<u16>(VertexCount + c);
IndexCount += 3; IndexCount += 3;
} }
return *this; return *this;
+27 -4
View File
@@ -1,3 +1,4 @@
#include <algorithm>
#include <iostream> #include <iostream>
#include <pd/drivers/gfx.hpp> #include <pd/drivers/gfx.hpp>
#include <pd/lithium/drawlist.hpp> #include <pd/lithium/drawlist.hpp>
@@ -11,28 +12,50 @@ PD_API Drawlist::Drawlist() { Clear(); }
PD_API Drawlist::~Drawlist() { Clear(); } PD_API Drawlist::~Drawlist() { Clear(); }
PD_API void Drawlist::Merge(Drawlist& other) { PD_API void Drawlist::Merge(Drawlist& other) {
size_t start = pCommands.size();
pCommands.AppendMove(other.pCommands); pCommands.AppendMove(other.pCommands);
for (size_t i = start; i < pCommands.size(); i++) {
pCommands[i].Layer += this->pCurrentLayer;
}
other.Clear(); other.Clear();
} }
PD_API void Drawlist::Copy(Drawlist& other) { PD_API void Drawlist::Copy(Drawlist& other) {
int start = pCommands.size();
pCommands.AppendCopy(other.pCommands); 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() { PD_API void Drawlist::Clear() {
UnbindTexture(); UnbindTexture();
pPath.ResetFast(); pPath.ResetFast();
pVertices.ResetFast(); pCommands.NoReset();
pIndices.ResetFast(); pCurrentLayer = 0;
pCommands.ResetFast(); pClipRects.clear();
} }
/** Command Allocation */ /** Command Allocation */
PD_API Command& Drawlist::NewCommand() { PD_API Command& Drawlist::NewCommand() {
auto cmd = pCommands.Allocate(1); auto cmd = pCommands.Allocate(1);
cmd->Reset();
cmd->Layer = pCurrentLayer;
cmd->Tex = pCurrentTexture.GetID(); cmd->Tex = pCurrentTexture.GetID();
if (HasClipRect()) {
cmd->ClipRectUsed = HasClipRect();
cmd->ClipRect = pClipRects.back();
}
return *cmd; 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) { PD_API Font::Codepoint& Font::GetCodepoint(u32 c) {
if (c < 128) { if (c < 128) {
// Direct Access (~11% improvement) // 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 (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; if (cp.Tex >= Textures.size()) continue;
cmd = &dl.NewCommand(); cmd = &dl.NewCommand();
cmd->Tex = Textures[cp.Tex]; 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() { PD_API void Button::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->PathRect(FinalPos(), FinalPos() + size, io->FrameRounding); list->PathRect(FinalPos(), FinalPos() + size, io->FrameRounding);
list->PathFill(io->Theme.Get(color)); list->PathFill(io->Theme.Get(color));
// list->LayerUp(); list->LayerUp();
list->DrawText(FinalPos() + size * 0.5 - tdim * 0.5, label.c_str(), list->DrawText(FinalPos() + size * 0.5 - tdim * 0.5, label.c_str(),
io->Theme.Get(UI7Color_Text)); io->Theme.Get(UI7Color_Text));
// list->LayerDown(); list->LayerDown();
} }
PD_API void Button::Update() { PD_API void Button::Update() {
+1
View File
@@ -48,6 +48,7 @@ PD_API void Checkbox::HandleInput() {
PD_API void Checkbox::Draw() { PD_API void Checkbox::Draw() {
// Assert(list.get() && io.get(), "Did you run Container::Init correctly?"); // Assert(list.get() && io.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->PathRect(FinalPos(), FinalPos() + cbs, io->FrameRounding); list->PathRect(FinalPos(), FinalPos() + cbs, io->FrameRounding);
list->PathFill(io->Theme.Get(color)); list->PathFill(io->Theme.Get(color));
if (usr_ref) { if (usr_ref) {
+28 -23
View File
@@ -33,8 +33,7 @@ PD_API void ColorEdit::HandleInput() {
} }
// Assert(screen.get(), "Screen is not set up!"); // Assert(screen.get(), "Screen is not set up!");
// if (screen->ScreenType() == Screen::Bottom) { // if (screen->ScreenType() == Screen::Bottom) {
if (io->InputHandler.DragObject(this->GetID() + 2, if (io->InputHandler.DragObject(this->GetID() + 2, fvec4(FinalPos(), size))) {
fvec4(FinalPos(), size))) {
if (io->InputHandler.DragReleasedAW) { if (io->InputHandler.DragReleasedAW) {
is_shown = !is_shown; is_shown = !is_shown;
} }
@@ -45,6 +44,7 @@ PD_API void ColorEdit::HandleInput() {
PD_API void ColorEdit::Draw() { PD_API void ColorEdit::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->PathRect(FinalPos(), FinalPos() + io->ItemRowHeight, io->FrameRounding); list->PathRect(FinalPos(), FinalPos() + io->ItemRowHeight, io->FrameRounding);
list->PathFill(*color_ref); list->PathFill(*color_ref);
list->DrawText(FinalPos() + fvec2(io->ItemSpace.x + io->ItemRowHeight, 0), list->DrawText(FinalPos() + fvec2(io->ItemSpace.x + io->ItemRowHeight, 0),
@@ -54,27 +54,30 @@ PD_API void ColorEdit::Draw() {
layout = new UI7::Layout(GetID(), *io); layout = new UI7::Layout(GetID(), *io);
} }
layout->SetPosition(FinalPos()); layout->SetPosition(FinalPos());
layout->AddObjectEx( DynObj* r = io->DynObjPool.Allocate();
new DynObj( *r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) {
[=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) { list->SetFont(thiz->GetFont());
thiz->SetSize(layout->GetSize()); thiz->SetSize(layout->GetSize());
// l->Layer(30); // l->Layer(30);
l->PathRect(thiz->GetPos(), thiz->GetPos() + thiz->GetSize(), l->PathRect(thiz->GetPos(), thiz->GetPos() + thiz->GetSize(),
io->FrameRounding); io->FrameRounding);
l->PathFill(io->Theme.Get(UI7Color_FrameBackground)); l->PathFill(io->Theme.Get(UI7Color_FrameBackground));
}), l->SetLayer(0);
UI7LytAdd_Front | UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); });
auto obj = new DynObj( layout->AddObjectEx(r, UI7LytAdd_Front | UI7LytAdd_NoCursorUpdate |
[=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) { UI7LytAdd_NoScrollHandle);
l->PathRect(thiz->FinalPos(), thiz->FinalPos() + io->ItemRowHeight, r = io->DynObjPool.Allocate();
io->FrameRounding); *r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) {
l->PathFill(*color_ref); list->SetFont(thiz->GetFont());
l->DrawText( l->PathRect(thiz->FinalPos(), thiz->FinalPos() + io->ItemRowHeight,
thiz->FinalPos() + fvec2(io->ItemSpace.x + io->ItemRowHeight, 0), io->FrameRounding);
label.c_str(), io->Theme.Get(UI7Color_Text)); l->PathFill(*color_ref);
}); l->DrawText(
obj->SetSize(PD::fvec2(200, io->ItemRowHeight)); thiz->FinalPos() + fvec2(io->ItemSpace.x + io->ItemRowHeight, 0),
layout->AddObject(obj); label.c_str(), io->Theme.Get(UI7Color_Text));
});
r->SetSize(PD::fvec2(200, io->ItemRowHeight));
layout->AddObject(r);
layout->Label("RGBA: ({}, {}, {}, {})", *((u8*)color_ref), layout->Label("RGBA: ({}, {}, {}, {})", *((u8*)color_ref),
*(((u8*)color_ref) + 1), *(((u8*)color_ref) + 2), *(((u8*)color_ref) + 1), *(((u8*)color_ref) + 2),
*(((u8*)color_ref) + 3)); *(((u8*)color_ref) + 3));
@@ -85,7 +88,9 @@ PD_API void ColorEdit::Draw() {
layout->Slider<u8>("B", ((u8*)color_ref) + 2); layout->Slider<u8>("B", ((u8*)color_ref) + 2);
layout->Slider<u8>("A", ((u8*)color_ref) + 3); layout->Slider<u8>("A", ((u8*)color_ref) + 3);
layout->Update(); layout->Update();
list->SetLayer(50);
list->Merge(layout->GetDrawList()); list->Merge(layout->GetDrawList());
list->SetLayer(0);
// io->RegisterDrawList(GetID(), layout->GetDrawList()); // io->RegisterDrawList(GetID(), layout->GetDrawList());
} }
} }
+6 -6
View File
@@ -31,10 +31,10 @@ PD_API void Container::HandleScrolling(fvec2 scrolling, fvec4 viewport) {
} }
last_use = PD::Os::GetTime(); last_use = PD::Os::GetTime();
pos -= fvec2(0, scrolling.y); pos -= fvec2(0, scrolling.y);
skippable = !Li::Math::InBounds( skippable =
pos, size, !Li::Math::InBounds(pos, size,
fvec4(viewport.x, viewport.y, viewport.x + viewport.z, fvec4(viewport.x, viewport.y, viewport.x + viewport.z,
viewport.y + viewport.w)); viewport.y + viewport.w));
} }
PD_API void Container::HandleInternalInput() { PD_API void Container::HandleInternalInput() {
@@ -44,13 +44,13 @@ PD_API void Container::HandleInternalInput() {
/** Internal function */ /** Internal function */
PD_API void Container::PreDraw() { PD_API void Container::PreDraw() {
if (pCLipRectUsed) { if (pCLipRectUsed) {
// list->PushClipRect(pClipRect); list->PushClipRect(pClipRect);
} }
} }
/** Internal function */ /** Internal function */
PD_API void Container::PostDraw() { PD_API void Container::PostDraw() {
if (pCLipRectUsed) { if (pCLipRectUsed) {
// list->PopClipRect(); list->PopClipRect();
} }
} }
} // namespace UI7 } // namespace UI7
+6 -4
View File
@@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <algorithm>
#include <pd/ui7/container/dragdata.hpp> #include <pd/ui7/container/dragdata.hpp>
#include <pd/ui7/container/label.hpp> #include <pd/ui7/container/label.hpp>
#include <type_traits> #include <type_traits>
@@ -85,21 +86,22 @@ PD_API void DragData<T>::Draw() {
FinalPos() + fvec2(off_x, 0) + td + io->FramePadding, FinalPos() + fvec2(off_x, 0) + td + io->FramePadding,
io->FrameRounding); io->FrameRounding);
list->PathFill(io->Theme.Get(UI7Color_Button)); list->PathFill(io->Theme.Get(UI7Color_Button));
// list->LayerUp(); list->LayerUp();
list->DrawTextEx(FinalPos() + fvec2(off_x, 0), p.c_str(), list->DrawTextEx(FinalPos() + fvec2(off_x, 0), p.c_str(),
io->Theme.Get(UI7Color_Text), LiTextFlags_AlignMid, io->Theme.Get(UI7Color_Text), LiTextFlags_AlignMid,
td + io->FramePadding); td + io->FramePadding);
// list->LayerDown(); list->LayerDown();
off_x += td.x + io->ItemSpace.x + io->FramePadding.x; off_x += td.x + io->ItemSpace.x + io->FramePadding.x;
} }
list->DrawText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5), label.c_str(), list->DrawText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5),
io->Theme.Get(UI7Color_Text)); label.c_str(), io->Theme.Get(UI7Color_Text));
} }
template <typename T> template <typename T>
PD_API void DragData<T>::Update() { PD_API void DragData<T>::Update() {
// Assert(io.get(), "Did you run Container::Init correctly?"); // Assert(io.get(), "Did you run Container::Init correctly?");
// Probably need to find a faster solution (caching sizes calculated here) // Probably need to find a faster solution (caching sizes calculated here)
list->SetFont(GetFont());
float off_x = 0; float off_x = 0;
for (size_t i = 0; i < elm_count; i++) { for (size_t i = 0; i < elm_count; i++) {
std::string p; 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(io.get() && list.get(), "Did you run Container::Init correctly?");
// Assert(img.get(), "Image is nullptr!"); // Assert(img.get(), "Image is nullptr!");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
// list->LayerUp(); list->LayerUp();
list->BindTexture(img); list->BindTexture(img);
list->DrawRectFilled(FinalPos(), newsize, 0xffffffff); list->DrawRectFilled(FinalPos(), newsize, 0xffffffff);
list->UnbindTexture(); list->UnbindTexture();
//list->LayerDown(); list->LayerDown();
} }
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD
+1
View File
@@ -28,6 +28,7 @@ namespace UI7 {
PD_API void Label::Draw() { PD_API void Label::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->DrawTextEx(FinalPos(), label.c_str(), io->Theme.Get(UI7Color_Text), list->DrawTextEx(FinalPos(), label.c_str(), io->Theme.Get(UI7Color_Text),
LiTextFlags_NoOOS, LiTextFlags_NoOOS,
PD::fvec2(0, io->CurrentViewPort.pSize.w)); PD::fvec2(0, io->CurrentViewPort.pSize.w));
+7 -5
View File
@@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <algorithm>
#include <pd/ui7/container/label.hpp> #include <pd/ui7/container/label.hpp>
#include <pd/ui7/container/slider.hpp> #include <pd/ui7/container/slider.hpp>
#include <type_traits> #include <type_traits>
@@ -56,9 +57,9 @@ PD_API void Slider<T>::HandleInput() {
fvec4(FinalPos() + fvec2(2, 0), fvec2(width, GetSize().y)))) { fvec4(FinalPos() + fvec2(2, 0), fvec2(width, GetSize().y)))) {
if (!io->InputHandler.DragReleasedAW) { if (!io->InputHandler.DragReleasedAW) {
*data = std::clamp( *data = std::clamp(
T(max * (std::clamp(io->InputHandler.DragLastPosition.x - xps, 0.f, T(max *
width) / (std::clamp(io->InputHandler.DragLastPosition.x - xps, 0.f, width) /
width)), width)),
this->min, this->max); this->min, this->max);
} }
} }
@@ -69,6 +70,7 @@ template <typename T>
PD_API void Slider<T>::Draw() { PD_API void Slider<T>::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->SetFont(GetFont());
std::string p; std::string p;
if constexpr (std::is_floating_point_v<T>) { if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", *data, precision); p = std::format("{:.{}f}", *data, precision);
@@ -83,10 +85,10 @@ PD_API void Slider<T>::Draw() {
FinalPos() + fvec2(slp + slw - 2, td.y - 2) + io->FramePadding, FinalPos() + fvec2(slp + slw - 2, td.y - 2) + io->FramePadding,
io->FrameRounding); io->FrameRounding);
list->PathFill(io->Theme.Get(UI7Color_ButtonActive)); list->PathFill(io->Theme.Get(UI7Color_ButtonActive));
// list->LayerUp(); list->LayerUp();
list->DrawTextEx(FinalPos(), p.c_str(), io->Theme.Get(UI7Color_Text), list->DrawTextEx(FinalPos(), p.c_str(), io->Theme.Get(UI7Color_Text),
LiTextFlags_AlignMid, fvec2(width, td.y) + io->FramePadding); LiTextFlags_AlignMid, fvec2(width, td.y) + io->FramePadding);
// list->LayerDown(); list->LayerDown();
list->DrawText(FinalPos() + fvec2(width + io->FramePadding.x * 2.f, list->DrawText(FinalPos() + fvec2(width + io->FramePadding.x * 2.f,
io->FramePadding.y * 0.5), io->FramePadding.y * 0.5),
label.c_str(), io->Theme.Get(UI7Color_Text)); label.c_str(), io->Theme.Get(UI7Color_Text));
+19 -3
View File
@@ -22,10 +22,23 @@ SOFTWARE.
*/ */
#include <pd/core/core.hpp> #include <pd/core/core.hpp>
#include <pd/ui7/io.hpp>
#include <pd/drivers/drivers.hpp> #include <pd/drivers/drivers.hpp>
#include <pd/ui7/containers.hpp>
#include <pd/ui7/io.hpp>
namespace PD { namespace PD {
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));
// Start a little larger on these
LabelPool.Init(512);
DynObjPool.Init(512);
}
PD_API UI7::IO::~IO() {}
PD_API void UI7::IO::Update() { PD_API void UI7::IO::Update() {
/** Todo: find out if we even still use the Drawlist regestry */ /** Todo: find out if we even still use the Drawlist regestry */
u64 current = PD::Os::GetTimeNano(); u64 current = PD::Os::GetTimeNano();
@@ -39,7 +52,10 @@ PD_API void UI7::IO::Update() {
DrawlistRegestry.push_front(std::make_pair("CtxBackList", &Back)); DrawlistRegestry.push_front(std::make_pair("CtxBackList", &Back));
if (Font) ItemRowHeight = FontScale * Font->PixelHeight; if (Font) ItemRowHeight = FontScale * Font->PixelHeight;
// RegisterDrawList("CtxBackList", Back); // RegisterDrawList("CtxBackList", Back);
NumIndices = 0;//FDL.pNumIndices; NumIndices = FDL.GetNumIndices();
NumVertices = 0;//FDL.pNumVertices; NumVertices = FDL.GetNumVertices();
LabelPool.ResetFast();
DynObjPool.ResetFast();
ImagePool.ResetFast();
} }
} // namespace PD } // namespace PD
+66 -6
View File
@@ -21,11 +21,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <algorithm>
#include <pd/ui7/containers.hpp> #include <pd/ui7/containers.hpp>
#include <pd/ui7/layout.hpp> #include <pd/ui7/layout.hpp>
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
PD_API Layout::~Layout() {
// We all love managing memory i guess
for (Container* obj : IDObjects) {
delete obj;
}
IDObjects.clear();
}
PD_API void Layout::CursorInit() { Cursor = fvec2(WorkRect.x, WorkRect.y); } PD_API void Layout::CursorInit() { Cursor = fvec2(WorkRect.x, WorkRect.y); }
PD_API void Layout::SameLine() { PD_API void Layout::SameLine() {
@@ -67,6 +77,10 @@ PD_API void Layout::AddObject(Container* obj) {
obj->Update(); obj->Update();
CursorMove(obj->GetSize()); CursorMove(obj->GetSize());
obj->HandleScrolling(ScrollOffset, WorkRect); 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); Objects.push_back(obj);
} }
@@ -83,6 +97,15 @@ PD_API void Layout::AddObjectEx(Container* obj, u32 flags) {
if (!(flags & UI7LytAdd_NoScrollHandle)) { if (!(flags & UI7LytAdd_NoScrollHandle)) {
obj->HandleScrolling(ScrollOffset, WorkRect); 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) { if (flags & UI7LytAdd_Front) {
Objects.push_front(obj); Objects.push_front(obj);
} else { } else {
@@ -113,6 +136,42 @@ PD_API fvec2 Layout::AlignPosition(fvec2 pos, fvec2 size, fvec4 area,
return p; 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() { PD_API void Layout::Update() {
if (Size == fvec2(0.f)) { if (Size == fvec2(0.f)) {
Size = fvec2(MaxPosition) + IO.MenuPadding * 2; Size = fvec2(MaxPosition) + IO.MenuPadding * 2;
@@ -125,9 +184,6 @@ PD_API void Layout::Update() {
it->SetPos(it->GetPos() + Pos); it->SetPos(it->GetPos() + Pos);
it->HandleInput(); it->HandleInput();
it->UnlockInput(); it->UnlockInput();
if (Flags & UI7LayoutFlags_UseClipRect) {
it->SetClipRect(fvec4(Pos, Size));
}
it->PreDraw(); it->PreDraw();
it->Draw(); it->Draw();
it->PostDraw(); it->PostDraw();
@@ -136,6 +192,7 @@ PD_API void Layout::Update() {
for (auto it = IDObjects.begin(); it != IDObjects.end();) { for (auto it = IDObjects.begin(); it != IDObjects.end();) {
if ((*it)->Removable()) { if ((*it)->Removable()) {
delete *it;
it = IDObjects.erase(it); it = IDObjects.erase(it);
} else { } else {
it++; it++;
@@ -145,14 +202,16 @@ PD_API void Layout::Update() {
Objects.clear(); Objects.clear();
WorkRect = fvec4(fvec2(WorkRect.x, WorkRect.y), Size - IO.MenuPadding); WorkRect = fvec4(fvec2(WorkRect.x, WorkRect.y), Size - IO.MenuPadding);
CursorInit(); CursorInit();
HandleScrolling();
} }
/** SECTION CONTAINERS (STOLEN FROM FORMER MENU) */ /** SECTION CONTAINERS (STOLEN FROM FORMER MENU) */
PD_API void Layout::Label(const std::string& label) { PD_API void Layout::Label(const std::string& label) {
// Layout API // Layout API
auto r = new UI7::Label(label, IO); auto r = IO.LabelPool.Allocate();
r->SetClipRect(fvec4(GetPosition(), GetPosition() + GetSize())); *r = UI7::Label(label, IO);
// r->SetClipRect(fvec4(GetPosition(), GetSize()));
AddObject(r); AddObject(r);
} }
@@ -182,7 +241,8 @@ PD_API void Layout::Checkbox(const std::string& label, bool& v) {
} }
PD_API void Layout::Image(Li::Texture img, fvec2 size, Li::Rect uv) { PD_API void Layout::Image(Li::Texture img, fvec2 size, Li::Rect uv) {
Container* r = new UI7::Image(img, size, uv); auto r = IO.ImagePool.Allocate();
*r = UI7::Image(img, size, uv);
AddObject(r); AddObject(r);
} }
Regular → Executable
+404 -425
View File
@@ -1,425 +1,404 @@
/* /*
MIT License MIT License
Copyright (c) 2024 - 2026 René Amthor (tobid7) Copyright (c) 2024 - 2026 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <pd/ui7/containers.hpp> #include <algorithm>
#include <pd/ui7/menu.hpp> #include <pd/ui7/containers.hpp>
#include <pd/ui7/menu.hpp>
namespace PD {
namespace UI7 { namespace PD {
Menu::Menu(const ID& id, IO& io) : pIO(io), pID(id), pLayout(id, io) { namespace UI7 {
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y; Menu::Menu(const ID& id, IO& io) : pLayout(id, io), pIO(io), pID(id) {
pLayout.WorkRect.y += TitleBarHeight; TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
pLayout.Flags |= UI7LayoutFlags_UseClipRect; pLayout.WorkRect.y += TitleBarHeight;
pLayout.CursorInit(); pLayout.Flags |= UI7LayoutFlags_UseClipRect;
} pLayout.CursorInit();
}
PD_API void Menu::Label(const std::string& label) {
// Layout API PD_API void Menu::Label(const std::string& label) {
auto r = new UI7::Label(label, pIO); // Layout API
pLayout.AddObject(r); auto r = pIO.LabelPool.Allocate();
} *r = UI7::Label(label, pIO);
pLayout.AddObject(r);
PD_API bool Menu::Button(const std::string& label) { }
bool ret = false;
u32 id = PD_API bool Menu::Button(const std::string& label) {
Strings::FastHash("btn" + label + std::to_string(pLayout.Objects.size())); bool ret = false;
Container* r = pLayout.FindObject(id); u32 id =
if (!r) { Strings::FastHash("btn" + label + std::to_string(pLayout.Objects.size()));
r = new UI7::Button(label, pIO); Container* r = pLayout.FindObject(id);
r->SetID(id); if (!r) {
} r = new UI7::Button(label, pIO);
pLayout.AddObject(r); r->SetID(id);
if (!r->Skippable()) { }
ret = reinterpret_cast<UI7::Button*>(r)->IsPressed(); pLayout.AddObject(r);
} if (!r->Skippable()) {
return ret; ret = reinterpret_cast<UI7::Button*>(r)->IsPressed();
} }
return ret;
PD_API void Menu::Checkbox(const std::string& label, bool& v) { }
u32 id =
Strings::FastHash("cbx" + label + std::to_string(pLayout.Objects.size())); PD_API void Menu::Checkbox(const std::string& label, bool& v) {
Container* r = pLayout.FindObject(id); u32 id =
if (!r) { Strings::FastHash("cbx" + label + std::to_string(pLayout.Objects.size()));
r = new UI7::Checkbox(label, v, pIO); Container* r = pLayout.FindObject(id);
r->SetID(id); if (!r) {
} r = new UI7::Checkbox(label, v, pIO);
pLayout.AddObject(r); r->SetID(id);
} }
pLayout.AddObject(r);
PD_API void Menu::Image(Li::Texture img, fvec2 size, Li::Rect uv) { }
Container* r = new UI7::Image(img, size, uv);
pLayout.AddObject(r); PD_API void Menu::Image(Li::Texture img, fvec2 size, Li::Rect uv) {
} auto r = pIO.ImagePool.Allocate();
*r = UI7::Image(img, size, uv);
PD_API void Menu::ColorEdit(const std::string& label, u32& clr) { pLayout.AddObject(r);
u32 id = Strings::FastHash("drd" + label); }
Container* r = pLayout.FindObject(id);
if (!r) { PD_API void Menu::ColorEdit(const std::string& label, u32& clr) {
r = new UI7::ColorEdit(label, &clr, pIO); u32 id = Strings::FastHash("drd" + label);
r->SetID(id); Container* r = pLayout.FindObject(id);
} if (!r) {
pLayout.AddObject(r); r = new UI7::ColorEdit(label, &clr, pIO);
} r->SetID(id);
}
PD_API void Menu::Separator() { pLayout.AddObject(r);
// Dynamic Objects are very simple... }
Container* r = new DynObj(
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) { PD_API void Menu::Separator() {
l->DrawRectFilled(self->FinalPos(), self->GetSize(), // Dynamic Objects are very simple...
pIO.Theme.Get(UI7Color_TextDead)); DynObj* r = pIO.DynObjPool.Allocate();
}); *r = UI7::DynObj(
// Set size before pushing (cause Cursor Move will require it) [=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
r->SetSize(fvec2( l->DrawRectFilled(self->FinalPos(), self->GetSize(),
pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x, pIO.Theme.Get(UI7Color_TextDead));
1)); });
pLayout.AddObject(r); // Set size before pushing (cause Cursor Move will require it)
} r->SetSize(fvec2(
pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x,
PD_API void Menu::SeparatorText(const std::string& label) { 1));
// Also note to use [=] instead of [&] to not undefined access label pLayout.AddObject(r);
Container* r = new DynObj([=, this](UI7::IO* io, Li::Drawlist* l, }
UI7::Container* self) {
fvec2 size = self->GetSize(); PD_API void Menu::SeparatorText(const std::string& label) {
fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale); // Also note to use [=] instead of [&] to not undefined access label
fvec2 pos = self->FinalPos(); DynObj* r = pIO.DynObjPool.Allocate();
auto align = pLayout.GetAlignment(); *r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
vec2 rpos = pLayout.AlignPosition(pos, tdim, UI7::Container* self) {
fvec4(pLayout.Pos, pLayout.Size), align); l->SetFont(self->GetFont());
if (!(align & UI7Align_Left)) { fvec2 size = self->GetSize();
l->DrawRectFilled(fvec2(rpos.x + io->FramePadding.x, tdim.y * 0.5), fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale);
fvec2(pos.x - rpos.x - io->MenuPadding.x, 1), fvec2 pos = self->FinalPos();
io->Theme.Get(UI7Color_TextDead)); auto align = pLayout.GetAlignment();
} vec2 rpos = pLayout.AlignPosition(pos, tdim,
if (!(align & UI7Align_Right)) { fvec4(pLayout.Pos, pLayout.Size), align);
l->DrawRectFilled(pos + fvec2(tdim.x + io->FramePadding.x, tdim.y * 0.5), if (!(align & UI7Align_Left)) {
fvec2(size.x - tdim.x - io->MenuPadding.x, 1), l->DrawRectFilled(fvec2(rpos.x + io->FramePadding.x, tdim.y * 0.5),
io->Theme.Get(UI7Color_TextDead)); fvec2(pos.x - rpos.x - io->MenuPadding.x, 1),
} io->Theme.Get(UI7Color_TextDead));
l->DrawTextEx(rpos, label.c_str(), io->Theme.Get(UI7Color_Text), 0, }
fvec2(pLayout.Size.x, self->GetSize().y)); if (!(align & UI7Align_Right)) {
}); l->DrawRectFilled(pos + fvec2(tdim.x + io->FramePadding.x, tdim.y * 0.5),
// Set size before pushing (cause Cursor Move will require it) fvec2(size.x - tdim.x - io->MenuPadding.x, 1),
r->SetSize(fvec2( io->Theme.Get(UI7Color_TextDead));
pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x, }
pIO.Font->PixelHeight * pIO.FontScale)); l->DrawTextEx(rpos, label.c_str(), io->Theme.Get(UI7Color_Text), 0,
pLayout.AddObject(r); fvec2(pLayout.Size.x, self->GetSize().y));
} });
PD_API void Menu::HandleFocus() { // Set size before pushing (cause Cursor Move will require it)
// Check if menu can be focused for Selective Menu Input API r->SetSize(fvec2(
vec4 newarea = fvec4(pLayout.Pos, pLayout.Size); pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x,
if (!pIsOpen) { pIO.Font->PixelHeight * pIO.FontScale));
newarea = fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)); pLayout.AddObject(r);
} }
if ((PD::Hid::IsEvent(Hid::Event::Down, Hid::Gamepad::Touch) || PD_API void Menu::HandleFocus() {
PD::Hid::IsEvent(Hid::Event::Down, Hid::Keyboard::MouseLeft)) && // Check if menu can be focused for Selective Menu Input API
Li::Math::InBounds(PD::Hid::MousePos(), newarea) && vec4 newarea = fvec4(pLayout.Pos, pLayout.Size);
!Li::Math::InBounds(PD::Hid::MousePos(), if (!pIsOpen) {
pIO.InputHandler.FocusedMenuRect)) { newarea = fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight));
pIO.InputHandler.FocusedMenu = pID; }
} if ((PD::Hid::IsEvent(Hid::Event::Down, Hid::Gamepad::Touch) ||
if (pIO.InputHandler.FocusedMenu == pID) { PD::Hid::IsEvent(Hid::Event::Down, Hid::Keyboard::MouseLeft)) &&
pIO.InputHandler.FocusedMenuRect = newarea; Li::Math::InBounds(PD::Hid::MousePos(), newarea) &&
} !Li::Math::InBounds(PD::Hid::MousePos(),
} pIO.InputHandler.FocusedMenuRect)) {
pIO.InputHandler.FocusedMenu = pID;
/** Todo: (func name is self describing) */ }
PD_API void Menu::HandleScrolling() { if (pIO.InputHandler.FocusedMenu == pID) {
if (Flags & UI7MenuFlags_VtScrolling) { pIO.InputHandler.FocusedMenuRect = newarea;
bool allowed = }
pLayout.MaxPosition.y > (pLayout.WorkRect.w - pLayout.WorkRect.y); }
if (allowed) {
if (PD::Hid::IsEvent(Hid::Event::Down, PD::Hid::Gamepad::Touch)) { PD_API void Menu::HandleTitlebarActions() {
pLayout.ScrollStart = pLayout.ScrollOffset; // Collapse
} if (!(Flags & UI7MenuFlags_NoCollapse)) {
if (pIO.InputHandler.DragObject( vec2 cpos = pLayout.Pos + pIO.FramePadding;
"sbg" + pID.GetName(), // clr_collapse_tri = UI7Color_FrameBackground;
fvec4(pLayout.Pos, fvec2(0.f)) + pLayout.WorkRect)) { if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clbse"),
if (pIO.InputHandler.DragReleasedAW) { fvec4(cpos, fvec2(18, TitleBarHeight)))) {
} else { if (pIO.InputHandler.DragReleased) {
pLayout.ScrollOffset.y = std::clamp( pIsOpen = !pIsOpen;
pLayout.ScrollStart.y + pIO.InputHandler.DragSourcePos.y - }
pIO.InputHandler.DragPosition.y, // clr_collapse_tri = UI7Color_FrameBackgroundHovered;
-20.f, pLayout.MaxPosition.y - 220); }
} }
} // Close Logic
} else { if (!(Flags & UI7MenuFlags_NoClose) && pIsShown != nullptr) {
pLayout.ScrollOffset.y = 0.f; fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2;
} fvec2 cpos =
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x,
if (pLayout.ScrollOffset.y > pLayout.MaxPosition.y - 240) { pLayout.Pos.y + pIO.FramePadding.y);
pLayout.ScrollOffset.y -= 1.5;
if (pLayout.ScrollOffset.y < pLayout.MaxPosition.y - 240) { // clr_close_btn = UI7Color_FrameBackground;
pLayout.ScrollOffset.y = pLayout.MaxPosition.y - 240; if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clse"),
} fvec4(cpos, size))) {
} if (pIO.InputHandler.DragReleased) {
if (pLayout.ScrollOffset.y < 0) { *pIsShown = !(*pIsShown);
pLayout.ScrollOffset.y += 1.5; }
if (pLayout.ScrollOffset.y > 0) { // clr_close_btn = UI7Color_FrameBackgroundHovered;
pLayout.ScrollOffset.y = 0; }
} }
} // Resize logic
} if (!(Flags & UI7MenuFlags_NoResize)) {
} vec2 cpos = pLayout.Pos + pLayout.Size - fvec2(20);
PD_API void Menu::HandleTitlebarActions() { // clr_close_btn = UI7Color_FrameBackground;
// Collapse if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "rszs"),
if (!(Flags & UI7MenuFlags_NoCollapse)) { fvec4(cpos, fvec2(20)))) {
vec2 cpos = pLayout.Pos + pIO.FramePadding; fvec2 szs = pLayout.Size + (pIO.InputHandler.DragPosition -
// clr_collapse_tri = UI7Color_FrameBackground; pIO.InputHandler.DragLastPosition);
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clbse"), if (szs.x < 30) szs.x = 30;
fvec4(cpos, fvec2(18, TitleBarHeight)))) { if (szs.y < 30) szs.y = 30;
if (pIO.InputHandler.DragReleased) { pLayout.Size = szs;
pIsOpen = !pIsOpen; // clr_close_btn = UI7Color_FrameBackgroundHovered;
} }
// clr_collapse_tri = UI7Color_FrameBackgroundHovered; }
} // Menu Movement
} if (!(Flags & UI7MenuFlags_NoMove)) {
// Close Logic if (pIO.InputHandler.DragObject(
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown != nullptr) { pID.GetName() + "tmv",
fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)))) {
fvec2 cpos = if (pIO.InputHandler.DragDoubleRelease) {
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x, pIsOpen = !pIsOpen;
pLayout.Pos.y + pIO.FramePadding.y); }
pLayout.Pos = pLayout.Pos + (pIO.InputHandler.DragPosition -
// clr_close_btn = UI7Color_FrameBackground; pIO.InputHandler.DragLastPosition);
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clse"), // Keep Window In Viewport
fvec4(cpos, size))) { // Maybe i need to add some operators to vec
if (pIO.InputHandler.DragReleased) { pLayout.Pos.x = std::clamp<float>(pLayout.Pos.x, -pLayout.Size.x + 10,
*pIsShown = !(*pIsShown); pIO.CurrentViewPort.pSize.z - 10);
} pLayout.Pos.y =
// clr_close_btn = UI7Color_FrameBackgroundHovered; std::clamp<float>(pLayout.Pos.y, pIO.CurrentViewPort.pSize.y,
} pIO.CurrentViewPort.pSize.w - 10);
} }
// Resize logic }
if (!(Flags & UI7MenuFlags_NoResize)) { }
vec2 cpos = pLayout.Pos + pLayout.Size - fvec2(20);
PD_API void Menu::DrawBaseLayout() {
// clr_close_btn = UI7Color_FrameBackground; if (pIsOpen) {
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "rszs"), /** Resize Sym (Render on Top of Everything) */
fvec4(cpos, fvec2(20)))) { if (!(Flags & UI7MenuFlags_NoResize)) {
fvec2 szs = pLayout.Size + (pIO.InputHandler.DragPosition - DynObj* r = pIO.DynObjPool.Allocate();
pIO.InputHandler.DragLastPosition); *r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
if (szs.x < 30) szs.x = 30; l->SetLayer(21);
if (szs.y < 30) szs.y = 30; l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20));
pLayout.Size = szs; l->PathAdd(self->FinalPos() + self->GetSize());
// clr_close_btn = UI7Color_FrameBackgroundHovered; l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0));
} l->PathFill(io->Theme.Get(UI7Color_Button));
} l->SetLayer(0);
// Menu Movement });
if (!(Flags & UI7MenuFlags_NoMove)) { r->SetSize(
if (pIO.InputHandler.DragObject( fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight));
pID.GetName() + "tmv", r->SetPos(fvec2(0, TitleBarHeight));
fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)))) { pLayout.AddObjectEx(r,
if (pIO.InputHandler.DragDoubleRelease) { UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
pIsOpen = !pIsOpen; }
}
pLayout.Pos = pLayout.Pos + (pIO.InputHandler.DragPosition - /** Background */
pIO.InputHandler.DragLastPosition); DynObj* r = pIO.DynObjPool.Allocate();
// Keep Window In Viewport *r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
// Maybe i need to add some operators to vec l->SetLayer(0);
pLayout.Pos.x = std::clamp<float>(pLayout.Pos.x, -pLayout.Size.x + 10, l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f,
pIO.CurrentViewPort.pSize.z - 10); LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot);
pLayout.Pos.y = l->PathFill(io->Theme.Get(UI7Color_Background));
std::clamp<float>(pLayout.Pos.y, pIO.CurrentViewPort.pSize.y, /*l->DrawRectFilled(self->FinalPos(), self->GetSize(),
pIO.CurrentViewPort.pSize.w - 10); io->Theme.Get(UI7Color_Background));*/
} });
} // Set size before pushing (cause Cursor Move will require it)
} r->SetSize(
fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight));
PD_API void Menu::DrawBaseLayout() { r->SetPos(fvec2(0, TitleBarHeight));
if (pIsOpen) { pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle |
/** Resize Sym (Render on Top of Everything) */ UI7LytAdd_Front | UI7LytAdd_NoClipTitlebar);
if (!(Flags & UI7MenuFlags_NoResize)) { }
Container* r = if (!(Flags & UI7MenuFlags_NoTitlebar)) {
new DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) { DynObj* r = pIO.DynObjPool.Allocate();
// //l->Layer(1); *r = UI7::DynObj(
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20)); [=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
l->PathAdd(self->FinalPos() + self->GetSize()); l->SetFont(self->GetFont());
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0)); l->SetLayer(20);
l->PathFill(io->Theme.Get(UI7Color_Button)); /** Header Bar */
}); l->DrawRectFilled(self->FinalPos(), self->GetSize(),
r->SetSize( io->Theme.Get(UI7Color_Header));
fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight)); l->SetLayer(21);
r->SetPos(fvec2(0, TitleBarHeight)); /** Inline if statement to shift the Text if collapse sym is shown */
pLayout.AddObjectEx(r, /** What the hell is this code btw (didn't found a better way) */
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); l->DrawText(self->FinalPos() +
} fvec2((Flags & UI7MenuFlags_NoCollapse)
? pIO.FramePadding.x
/** Background */ : (TitleBarHeight - pIO.FramePadding.y * 2 +
Container* r = new DynObj([](IO* io, Li::Drawlist* l, (io->FramePadding.x * 2)),
UI7::Container* self) { 2),
//l->Layer(0); pID.GetName().c_str(), io->Theme.Get(UI7Color_Text));
l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f, l->SetLayer(0);
LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot); });
l->PathFill(io->Theme.Get(UI7Color_Background)); r->SetSize(fvec2(pLayout.GetSize().x, TitleBarHeight));
/*l->DrawRectFilled(self->FinalPos(), self->GetSize(), r->SetPos(0);
io->Theme.Get(UI7Color_Background));*/ pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle |
}); UI7LytAdd_NoClipTitlebar);
// Set size before pushing (cause Cursor Move will require it)
r->SetSize( /** Collapse Sym */
fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight)); if (!(Flags & UI7MenuFlags_NoCollapse)) {
r->SetPos(fvec2(0, TitleBarHeight)); DynObj* r = pIO.DynObjPool.Allocate();
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle | *r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
UI7LytAdd_Front); UI7::Container* self) {
} /** This sym actually requires layer 21 (i dont know why) */
if (!(Flags & UI7MenuFlags_NoTitlebar)) { l->SetLayer(21);
Container* r = new DynObj( /**
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) { * Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
//l->Layer(20); */
/** Header Bar */ l->DrawTriangleFilled(
l->DrawRectFilled(self->FinalPos(), self->GetSize(), self->FinalPos(),
io->Theme.Get(UI7Color_Header)); self->FinalPos() +
//l->Layer(21); fvec2(self->GetSize().x, pIsOpen ? 0 : self->GetSize().y * 0.5),
/** Inline if statement to shift the Text if collapse sym is shown */ self->FinalPos() +
/** What the hell is this code btw (didn't found a better way) */ fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y),
l->DrawText(self->FinalPos() + io->Theme.Get(UI7Color_FrameBackground));
fvec2((Flags & UI7MenuFlags_NoCollapse) l->SetLayer(0);
? pIO.FramePadding.x });
: (TitleBarHeight - pIO.FramePadding.y * 2 + r->SetSize(TitleBarHeight - pIO.FramePadding.y * 2);
(io->FramePadding.x * 2)), r->SetPos(pIO.FramePadding);
2), pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate |
pID.GetName().c_str(), io->Theme.Get(UI7Color_Text)); UI7LytAdd_NoScrollHandle |
}); UI7LytAdd_NoClipTitlebar);
r->SetSize(fvec2(pLayout.GetSize().x, TitleBarHeight)); }
r->SetPos(0); /** Close Sym (only shown if pIsShown is not nullptr) */
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) {
fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; // Fixed quad size
/** Collapse Sym */ // Need to clamp this way as the math lib lacks a less and greater
if (!(Flags & UI7MenuFlags_NoCollapse)) { // operator in vec2 (don't checked if it would make sense yet)
r = new DynObj([=, this](UI7::IO* io, Li::Drawlist* l, size.x = std::clamp(size.x, 5.f, std::numeric_limits<float>::max());
UI7::Container* self) { size.y = std::clamp(size.y, 5.f, std::numeric_limits<float>::max());
/** This sym actually requires layer 21 (i dont know why) */ // Probably should fix the minsize to be locked on y
//l->Layer(21); fvec2 cpos =
/** fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x,
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;) pLayout.Pos.y + pIO.FramePadding.y);
*/ pLayout.DrawList.SetLayer(21);
l->DrawTriangleFilled( pLayout.DrawList.DrawLine(cpos, cpos + size,
self->FinalPos(), pIO.Theme.Get(UI7Color_FrameBackground), 2);
self->FinalPos() + pLayout.DrawList.DrawLine(cpos + fvec2(0, size.y),
fvec2(self->GetSize().x, pIsOpen ? 0 : self->GetSize().y * 0.5), cpos + fvec2(size.x, 0),
self->FinalPos() + pIO.Theme.Get(UI7Color_FrameBackground), 2);
fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y), pLayout.DrawList.SetLayer(0);
io->Theme.Get(UI7Color_FrameBackground)); }
}); }
r->SetSize(TitleBarHeight - pIO.FramePadding.y * 2); }
r->SetPos(pIO.FramePadding);
pLayout.AddObjectEx(r, PD_API void Menu::Update() {
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); HandleFocus();
} if (pLayout.Size == fvec2(0.f) || Flags & UI7MenuFlags_AlwaysAutoSize) {
/** Close Sym (only shown if pIsShown is not nullptr) */ pLayout.Size = fvec2(pLayout.MaxPosition) + pIO.MenuPadding * 2;
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) { }
fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; // Fixed quad size if (Flags & UI7MenuFlags_VtScrolling)
// Need to clamp this way as the math lib lacks a less and greater pLayout.Flags |= UI7LayoutFlags_VtScrolling;
// operator in vec2 (don't checked if it would make sense yet) if (Flags & UI7MenuFlags_HzScrolling)
size.x = std::clamp(size.x, 5.f, std::numeric_limits<float>::max()); pLayout.Flags |= UI7LayoutFlags_HzScrolling;
size.y = std::clamp(size.y, 5.f, std::numeric_limits<float>::max()); if (!(Flags & UI7MenuFlags_NoTitlebar)) {
// Probably should fix the minsize to be locked on y TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
fvec2 cpos = pLayout.WorkRect.y = 5.f + TitleBarHeight;
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x, HandleTitlebarActions();
pLayout.Pos.y + pIO.FramePadding.y); } else {
pLayout.DrawList.DrawLine(cpos, cpos + size, TitleBarHeight = 0.f;
pIO.Theme.Get(UI7Color_FrameBackground), 2); pLayout.WorkRect.y = 5.f;
pLayout.DrawList.DrawLine(cpos + fvec2(0, size.y), }
cpos + fvec2(size.x, 0), DrawBaseLayout();
pIO.Theme.Get(UI7Color_FrameBackground), 2); pLayout.Update();
} }
}
} PD_API bool Menu::BeginTreeNode(const ID& id) {
// As of some notes this should work:
PD_API void Menu::Update() { auto n = pTreeNodes.find(id);
HandleFocus(); if (n == pTreeNodes.end()) {
if (pLayout.Size == fvec2(0.f) || Flags & UI7MenuFlags_AlwaysAutoSize) { pTreeNodes[id] = false;
pLayout.Size = fvec2(pLayout.MaxPosition) + pIO.MenuPadding * 2; n = pTreeNodes.find(id);
} }
if (!(Flags & UI7MenuFlags_NoTitlebar)) { fvec2 pos = pLayout.Cursor;
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y; fvec2 tdim = pIO.Font->GetTextBounds(id.GetName().c_str(), pIO.FontScale);
pLayout.WorkRect.y = 5.f + TitleBarHeight; fvec2 szs = tdim + fvec2(pIO.ItemSpace.x + 10, 0);
HandleTitlebarActions();
} else { if (n->second) {
TitleBarHeight = 0.f; pLayout.InitialCursorOffset += 10.f;
pLayout.WorkRect.y = 5.f; }
}
DrawBaseLayout(); // Object
pLayout.Update(); DynObj* r = pIO.DynObjPool.Allocate();
if (Flags & UI7MenuFlags_VtScrolling || Flags & UI7MenuFlags_HzScrolling) { *r = UI7::DynObj([=, this](IO* io, Li::Drawlist* l, Container* self) {
HandleScrolling(); l->SetFont(self->GetFont());
} fvec2 ts = self->FinalPos() + fvec2(0, 7);
} fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)};
if (n->second) {
PD_API bool Menu::BeginTreeNode(const ID& id) { float t = pl[0].y;
// As of some notes this should work: pl[0].y = pl[1].x;
auto n = pTreeNodes.find(id); pl[1].x = t;
if (n == pTreeNodes.end()) { }
pTreeNodes[id] = false; l->DrawTriangleFilled(ts, ts + pl[0], ts + pl[1],
n = pTreeNodes.find(id); io->Theme.Get(UI7Color_FrameBackground));
}
fvec2 pos = pLayout.Cursor; l->DrawText(self->FinalPos() + fvec2(10 + io->ItemSpace.x, 0),
fvec2 tdim = pIO.Font->GetTextBounds(id.GetName().c_str(), pIO.FontScale); id.GetName().c_str(), io->Theme.Get(UI7Color_Text));
fvec2 szs = tdim + fvec2(pIO.ItemSpace.x + 10, 0); });
/** Yes this new function handler was created for tree nodes */
if (n->second) { r->AddInputHandler([=, this](IO* io, Container* self) {
pLayout.InitialCursorOffset += 10.f; if (io->InputHandler.DragObject(ID(pID.GetName() + id.GetName()),
} fvec4(self->FinalPos(), self->GetSize()))) {
if (io->InputHandler.DragReleased) {
// Object n->second = !n->second;
auto r = new DynObj([=, this](IO* io, Li::Drawlist* l, Container* self) { }
fvec2 ts = self->FinalPos() + fvec2(0, 7); }
fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)}; });
if (n->second) { r->SetPos(pos);
float t = pl[0].y; r->SetSize(szs);
pl[0].y = pl[1].x; /** Use Add Object as it is faster */
pl[1].x = t; pLayout.AddObject(r);
}
l->DrawTriangleFilled(ts, ts + pl[0], ts + pl[1], return n->second;
io->Theme.Get(UI7Color_FrameBackground)); }
l->DrawText(self->FinalPos() + fvec2(10 + io->ItemSpace.x, 0), id.GetName().c_str(), PD_API void UI7::Menu::EndTreeNode() {
io->Theme.Get(UI7Color_Text)); pLayout.InitialCursorOffset.x -= 10.f;
}); pLayout.Cursor.x -= 10.f;
/** Yes this new function handler was created for tree nodes */ if (pLayout.InitialCursorOffset.x < 0.f) {
r->AddInputHandler([=, this](IO* io, Container* self) { pLayout.InitialCursorOffset.x = 0.f;
if (io->InputHandler.DragObject( }
ID(pID.GetName() + id.GetName()), }
fvec4(self->FinalPos(), self->GetSize()))) { } // namespace UI7
if (io->InputHandler.DragReleased) { } // namespace PD
n->second = !n->second;
}
}
});
r->SetPos(pos);
r->SetSize(szs);
/** Use Add Object as it is faster */
pLayout.AddObject(r);
return n->second;
}
PD_API void UI7::Menu::EndTreeNode() {
pLayout.InitialCursorOffset.x -= 10.f;
pLayout.Cursor.x -= 10.f;
if (pLayout.InitialCursorOffset.x < 0.f) {
pLayout.InitialCursorOffset.x = 0.f;
}
}
} // namespace UI7
} // namespace PD
+359 -348
View File
@@ -1,348 +1,359 @@
/* /*
MIT License MIT License
Copyright (c) 2024 - 2026 René Amthor (tobid7) Copyright (c) 2024 - 2026 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <pd/ui7/ui7.hpp> #include <pd/ui7/ui7.hpp>
#include "pd/pd_p_api.hpp" #include "pd/pd_p_api.hpp"
#include "pd/ui7/flags.hpp" #include "pd/ui7/flags.hpp"
#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x) #define UI7DHX32(x) std::format("{}: {:#08x}", #x, x)
#define UI7DTF(x) PD::Strings::FormatNanos(x) #define UI7DTF(x) PD::Strings::FormatNanos(x)
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
PD_API std::string GetVersion(bool show_build) { PD_API std::string GetVersion(bool show_build) {
std::stringstream s; std::stringstream s;
s << ((UI7_VERSION >> 24) & 0xFF) << "."; s << ((UI7_VERSION >> 24) & 0xFF) << ".";
s << ((UI7_VERSION >> 16) & 0xFF) << "."; s << ((UI7_VERSION >> 16) & 0xFF) << ".";
s << ((UI7_VERSION >> 8) & 0xFF); s << ((UI7_VERSION >> 8) & 0xFF);
if (show_build) s << "-" << ((UI7_VERSION) & 0xFF); if (show_build) s << "-" << ((UI7_VERSION) & 0xFF);
return s.str(); return s.str();
} }
PD_API void Context::AddViewPort(const ID& id, const ivec4& vp) { PD_API void Context::AddViewPort(const ID& id, const ivec4& vp) {
pIO.AddViewPort(id, vp); pIO.AddViewPort(id, vp);
} }
PD_API void Context::UseViewPort(const ID& id) { PD_API void Context::UseViewPort(const ID& id) {
if (!pIO.ViewPorts.count(id)) { if (!pIO.ViewPorts.count(id)) {
return; return;
} }
pIO.CurrentViewPort = pIO.ViewPorts[id.RawID()]; pIO.CurrentViewPort = pIO.ViewPorts[id.RawID()];
} }
PD_API Menu* Context::BeginMenu(const ID& id, UI7MenuFlags flags, PD_API Menu* Context::BeginMenu(const ID& id, UI7MenuFlags flags, bool* pShow) {
bool* pShow) { if (pCurrent) {
if (pCurrent) { PDERR("UI7: You are already in {} Menu!", pCurrent->pID.GetName());
PDERR("UI7: You are already in {} Menu!", pCurrent->pID.GetName()); return nullptr;
return nullptr; }
} if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), (u32)id) !=
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), (u32)id) != pCurrentMenus.end()) {
pCurrentMenus.end()) { PDERR("UI7: Menu {} already exists!", id.GetName());
PDERR("UI7: Menu {} already exists!", id.GetName()); return nullptr;
return nullptr; }
} pCurrent = pGetOrCreateMenu(id);
pCurrent = pGetOrCreateMenu(id); this->pCurrent->pIsShown = pShow;
this->pCurrent->pIsShown = pShow; if (pCurrent->pIsShown != nullptr) {
if (pCurrent->pIsShown != nullptr) { if (!*pCurrent->pIsShown) {
if (!*pCurrent->pIsShown) { pCurrent = nullptr;
pCurrent = nullptr; return nullptr;
return nullptr; }
} }
} /** Probably we dont even need Input Handling in this stage */
/** Probably we dont even need Input Handling in this stage */ // this->pIO.InputHandler.CurrentMenu = id;
// this->pIO.InputHandler.CurrentMenu = id; pCurrentMenus.push_back(id);
pCurrentMenus.push_back(id); pCurrent->Flags = flags;
pCurrent->Flags = flags; if (!pCurrent->pIsOpen) {
if (!pCurrent->pIsOpen) { pCurrent = nullptr;
pCurrent = nullptr; }
} return pCurrent;
return pCurrent; }
}
PD_API void Context::EndMenu() {
PD_API void Context::EndMenu() { /**
/** * Currently it would be a better wy to handle menus as follows
* Currently it would be a better wy to handle menus as follows *
* * The folowing context will generate a new menu as normally but instead
* The folowing context will generate a new menu as normally but instead * of true or false we have m is false (nullptr) or true (some ptr returned)
* of true or false we have m is false (nullptr) or true (some ptr returned) * and after that it should simply out of scope
* and after that it should simply out of scope * (This would probably require some wrapper class to find out if m goes
* (This would probably require some wrapper class to find out if m goes * out of scope)
* out of scope) * ```cpp
* ```cpp * if(auto m = ui7->BeginMenu("Test")) {
* if(auto m = ui7->BeginMenu("Test")) { * m->Label("Show some Text");
* m->Label("Show some Text"); * }
* } * ```
* ``` */
*/ if (!pCurrent) {
if (!pCurrent) { return;
return; }
} pCurrent = nullptr;
pCurrent = nullptr; // pIO.InputHandler.CurrentMenu = 0;
// pIO.InputHandler.CurrentMenu = 0; }
}
PD_API void Context::Update() {
PD_API void Context::Update() { /**
/** * Cause Commenting each line looks carbage...
* Cause Commenting each line looks carbage... * This function simply clears the FinalDrawList, Searches for Menu ID's in
* This function simply clears the FinalDrawList, Searches for Menu ID's in * The sorted menu List from last frame to insert them as same order into
* The sorted menu List from last frame to insert them as same order into * the final list. After that it adds new menus to the begin to 'add' new
* the final list. After that it adds new menus to the begin to 'add' new * menus on top. As final step the focused menu gets add to begin
* menus on top. As final step the focused menu gets add to begin * Then the menus update their Input and DraeList Generation in List Order
* Then the menus update their Input and DraeList Generation in List Order * and the DrawLists get Merged into the FDL in reverse Order. At end the List
* and the DrawLists get Merged into the FDL in reverse Order. At end the List * gets cleanup and io gets updated
* gets cleanup and io gets updated *
* * Very simple ...
* Very simple ... */
*/ pIO.FDL.Clear();
pIO.FDL.Clear(); if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(),
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), pIO.InputHandler.FocusedMenu) == pCurrentMenus.end()) {
pIO.InputHandler.FocusedMenu) == pCurrentMenus.end()) { pIO.InputHandler.FocusedMenu = 0;
pIO.InputHandler.FocusedMenu = 0; pIO.InputHandler.FocusedMenuRect = fvec4(0);
pIO.InputHandler.FocusedMenuRect = fvec4(0); }
} std::vector<u32> FinalList;
std::vector<u32> FinalList; for (auto it : pDFO) {
for (auto it : pDFO) { if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), it) !=
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), it) != pCurrentMenus.end() &&
pCurrentMenus.end() && it != pIO.InputHandler.FocusedMenu) {
it != pIO.InputHandler.FocusedMenu) { FinalList.push_back(it);
FinalList.push_back(it); }
} }
} for (auto it : pCurrentMenus) {
for (auto it : pCurrentMenus) { if (std::find(FinalList.begin(), FinalList.end(), it) == FinalList.end() &&
if (std::find(FinalList.begin(), FinalList.end(), it) == FinalList.end() && it != pIO.InputHandler.FocusedMenu) {
it != pIO.InputHandler.FocusedMenu) { FinalList.push_back(it);
FinalList.push_back(it); }
} }
} if (pMenus.count(pIO.InputHandler.FocusedMenu)) {
if (pMenus.count(pIO.InputHandler.FocusedMenu)) { FinalList.insert(FinalList.begin(), pIO.InputHandler.FocusedMenu);
FinalList.insert(FinalList.begin(), pIO.InputHandler.FocusedMenu); }
} pDFO = FinalList;
pDFO = FinalList; for (auto& it : FinalList) {
for (auto& it : FinalList) { this->pIO.InputHandler.CurrentMenu = it;
this->pIO.InputHandler.CurrentMenu = it; pMenus[it]->Update(); /** Render */
pMenus[it]->Update(); /** Render */ this->pIO.InputHandler.CurrentMenu = 0;
this->pIO.InputHandler.CurrentMenu = 0; }
} int base_layer = 0;
for (int i = (int)FinalList.size() - 1; i >= 0; i--) { for (int i = (int)FinalList.size() - 1; i >= 0; i--) {
pIO.FDL.Merge(pMenus[FinalList[i]]->pLayout.GetDrawList()); pIO.FDL.SetLayer(base_layer);
} pIO.FDL.Merge(pMenus[FinalList[i]]->pLayout.GetDrawList());
pCurrentMenus.clear(); base_layer += 100;
pIO.Update(); }
pIO.FDL.Optimize(); pCurrentMenus.clear();
} pIO.Update();
pIO.FDL.Optimize();
PD_API void Context::AboutMenu(bool* show) { }
if (auto m = BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
m->Label("Palladium UI7 " + GetVersion()); PD_API void Context::AboutMenu(bool* show) {
m->Separator(); if (auto m = BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
m->Label("(c) 2023-2025 René Amthor"); m->Label("Palladium UI7 " + GetVersion());
m->Label("UI7 is licensed under the MIT License."); m->Separator();
m->Label("See LICENSE for more information."); m->Label("(c) 2023-2026 René Amthor");
static bool show_build; m->Label("UI7 is licensed under the MIT License.");
m->Checkbox("Show Build Info", show_build); m->Label("See LICENSE for more information.");
if (show_build) { static bool show_build;
m->SeparatorText("Build Info"); m->Checkbox("Show Build Info", show_build);
m->Label("Full Version -> " + GetVersion(true)); if (show_build) {
m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t))); m->SeparatorText("Build Info");
m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(Li::Vertex))); m->Label("Full Version -> " + GetVersion(true));
m->Label("__cplusplus -> " + std::to_string(__cplusplus)); m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t)));
m->Label("Compiler -> {}", m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(Li::Vertex)));
Strings::GetCompilerVersion()); // + LibInfo::CompiledWith()); m->Label("__cplusplus -> " + std::to_string(__cplusplus));
} m->Label("Compiler -> {}",
EndMenu(); Strings::GetCompilerVersion()); // + LibInfo::CompiledWith());
} }
} EndMenu();
}
PD_API void Context::MetricsMenu(bool* show) { }
if (auto m = BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
m->Label("Palladium - UI7 " + GetVersion()); PD_API void Context::MetricsMenu(bool* show) {
m->Separator(); if (auto m = BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
m->Label( m->Label("Palladium - UI7 " + GetVersion());
std::format("Average {:.3f} ms/f ({:.1f} FPS)", m->Separator();
((float)pIO.DeltaStats.GetAverage() / 1000.f), m->Label(
1000.f / ((float)pIO.DeltaStats.GetAverage() / 1000.f))); std::format("Average {:.3f} ms/f ({:.1f} FPS)",
m->Label(std::format("NumVertices: {}", pIO.NumVertices)); ((float)pIO.DeltaStats.GetAverage() / 1000.f),
m->Label(std::format("NumIndices: {} -> {} Tris", pIO.NumIndices, 1000.f / ((float)pIO.DeltaStats.GetAverage() / 1000.f)));
pIO.NumIndices / 3)); m->Label(std::format("NumVertices: {}", pIO.NumVertices));
m->Label("Menus: " + std::to_string(pMenus.size())); m->Label(std::format("NumIndices: {} -> {} Tris", pIO.NumIndices,
/** Section TimeTrace */ pIO.NumIndices / 3));
m->SeparatorText("TimeTrace"); m->Label("Menus: " + std::to_string(pMenus.size()));
if (m->BeginTreeNode("Traces (" + /** Section TimeTrace */
std::to_string(PD::TT::GetTraceMap().size()) + ")")) { m->SeparatorText("TimeTrace");
for (auto& it : PD::TT::GetTraceMap()) { if (m->BeginTreeNode("Traces (" +
if (m->BeginTreeNode(it.second.GetID())) { std::to_string(PD::TT::GetTraceMap().size()) + ")")) {
m->Label("Diff: " + UI7DTF(it.second.GetLastDiff())); for (auto& it : PD::TT::GetTraceMap()) {
m->Label("Protocol Len: " + if (m->BeginTreeNode(it.second.GetID())) {
std::to_string(it.second.GetProtocol().GetLen())); m->Label("Diff: " + UI7DTF(it.second.GetLastDiff()));
m->Label("Average: " + UI7DTF(it.second.GetProtocol().GetAverage())); m->Label("Protocol Len: " +
m->Label("Min: " + UI7DTF(it.second.GetProtocol().GetMin())); std::to_string(it.second.GetProtocol().GetLen()));
m->Label("Max: " + UI7DTF(it.second.GetProtocol().GetMax())); m->Label("Average: " + UI7DTF(it.second.GetProtocol().GetAverage()));
m->EndTreeNode(); m->Label("Min: " + UI7DTF(it.second.GetProtocol().GetMin()));
} m->Label("Max: " + UI7DTF(it.second.GetProtocol().GetMax()));
} m->EndTreeNode();
m->EndTreeNode(); }
} }
m->SeparatorText("Palladium Info"); m->EndTreeNode();
m->Label("Os Driver: {}", PD::Os::GetDriverName()); }
m->Label("Renderer: {}", PD::Gfx::GetDriverName()); m->SeparatorText("Palladium Info");
if (m->BeginTreeNode( m->Label("Os Driver: {}", PD::Os::GetDriverName());
std::string(std::string("Input: ") + PD::Hid::GetDriverName()))) { if (m->BeginTreeNode(
/* if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasKeyboard) { std::format("Gfx Driver: {}", PD::Gfx::GetDriverName()))) {
m->Label("- Keyboard Supported"); m->SeparatorText("Features");
} if (PD::Gfx::GetFlags() & PDGfxBackendFlags_HasClipRect)
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasMouse) { m->Label("ClipRects");
m->Label("- Mouse Supported"); if (PD::Gfx::GetFlags() & PDGfxBackendFlags_ReqPow2)
} m->Label("Texture As Pow of 2");
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasTouch) { if (PD::Gfx::GetFlags() & PDGfxBackendFlags_ApproxSDF)
m->Label("- Touch Supported"); m->Label("SDF Approximation");
} m->EndTreeNode();
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::FLags_HasGamepad) { }
m->Label("- Gamepad Supported"); if (m->BeginTreeNode(
}*/ std::string(std::string("Input: ") + PD::Hid::GetDriverName()))) {
m->EndTreeNode(); /* if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasKeyboard) {
} m->Label("- Keyboard Supported");
/** Section IO */ }
m->SeparatorText("IO"); if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasMouse) {
if (m->BeginTreeNode("Menus (" + std::to_string(pMenus.size()) + ")")) { m->Label("- Mouse Supported");
for (auto& it : pMenus) { }
if (m->BeginTreeNode(it.second->pID.GetName())) { if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasTouch) {
m->Label("Name: " + it.second->pID.GetName()); m->Label("- Touch Supported");
m->Label(std::format("Pos: {}", it.second->pLayout.GetPosition())); }
m->Label(std::format("Size: {}", it.second->pLayout.GetSize())); if (pIO.pCtx.Hid()->Flags & PD::HidDriver::FLags_HasGamepad) {
m->Label(std::format("WorkRect: {}", it.second->pLayout.WorkRect)); m->Label("- Gamepad Supported");
m->Label(std::format("Cursor: {}", it.second->pLayout.Cursor)); }*/
if (m->BeginTreeNode( m->EndTreeNode();
"ID Objects (" + }
std::to_string(it.second->pLayout.IDObjects.size()) + ")")) { /** Section IO */
for (auto& jt : it.second->pLayout.IDObjects) { m->SeparatorText("IO");
m->Label(std::format("{:08X}", jt->GetID())); if (m->BeginTreeNode("Menus (" + std::to_string(pMenus.size()) + ")")) {
} for (auto& it : pMenus) {
m->EndTreeNode(); if (m->BeginTreeNode(it.second->pID.GetName())) {
} m->Label("Name: " + it.second->pID.GetName());
m->EndTreeNode(); m->Label(std::format("Pos: {}", it.second->pLayout.GetPosition()));
} m->Label(std::format("Size: {}", it.second->pLayout.GetSize()));
} m->Label(std::format("WorkRect: {}", it.second->pLayout.WorkRect));
m->EndTreeNode(); m->Label(std::format("Cursor: {}", it.second->pLayout.Cursor));
} if (m->BeginTreeNode(
if (m->BeginTreeNode("Active Menus (" + "ID Objects (" +
std::to_string(pCurrentMenus.size()) + ")")) { std::to_string(it.second->pLayout.IDObjects.size()) + ")")) {
for (auto& it : pCurrentMenus) { for (auto& jt : it.second->pLayout.IDObjects) {
if (m->BeginTreeNode(pMenus[it]->pID.GetName())) { m->Label(std::format("{:08X}", jt->GetID()));
m->Label("Name: " + pMenus[it]->pID.GetName()); }
m->Label(std::format("Pos: {}", pMenus[it]->pLayout.GetPosition())); m->EndTreeNode();
m->Label(std::format("Size: {}", pMenus[it]->pLayout.GetSize())); }
m->Label(std::format("WorkRect: {}", pMenus[it]->pLayout.WorkRect)); m->EndTreeNode();
m->Label(std::format("Cursor: {}", pMenus[it]->pLayout.Cursor)); }
if (m->BeginTreeNode( }
"ID Objects (" + m->EndTreeNode();
std::to_string(pMenus[it]->pLayout.IDObjects.size()) + }
")")) { if (m->BeginTreeNode("Active Menus (" +
for (auto& jt : pMenus[it]->pLayout.IDObjects) { std::to_string(pCurrentMenus.size()) + ")")) {
m->Label(std::format("{:08X}", jt->GetID())); for (auto& it : pCurrentMenus) {
} if (m->BeginTreeNode(pMenus[it]->pID.GetName())) {
m->EndTreeNode(); m->Label("Name: " + pMenus[it]->pID.GetName());
} m->Label(std::format("Pos: {}", pMenus[it]->pLayout.GetPosition()));
m->EndTreeNode(); m->Label(std::format("Size: {}", pMenus[it]->pLayout.GetSize()));
} m->Label(std::format("WorkRect: {}", pMenus[it]->pLayout.WorkRect));
} m->Label(std::format("Cursor: {}", pMenus[it]->pLayout.Cursor));
m->EndTreeNode(); if (m->BeginTreeNode(
} "ID Objects (" +
// Well this are Li Drawlists now and they do not count their stats (yet) std::to_string(pMenus[it]->pLayout.IDObjects.size()) + ")")) {
/*if (m->BeginTreeNode("DrawLists (" + for (auto& jt : pMenus[it]->pLayout.IDObjects) {
std::to_string(pIO.DrawListRegestry.size()) + ")")) { m->Label(std::format("{:08X}", jt->GetID()));
for (auto &it : pIO.DrawListRegestry) { }
if (m->BeginTreeNode(it.First.GetName())) { m->EndTreeNode();
m->Label("Vertices: " + std::to_string(it.Second->NumVertices)); }
m->Label("Indices: " + std::to_string(it.Second->NumIndices)); m->EndTreeNode();
m->Label("Base Layer: " + std::to_string(it.Second->Base)); }
m->EndTreeNode(); }
} m->EndTreeNode();
} }
m->EndTreeNode(); // Well this are Li Drawlists now and they do not count their stats (yet)
}*/ /*if (m->BeginTreeNode("DrawLists (" +
m->Label("io->Time: " + Strings::FormatMillis(pIO.Time.Get())); std::to_string(pIO.DrawListRegestry.size()) + ")")) {
m->Label(std::format("Delta: {:.3f}", pIO.Delta)); for (auto &it : pIO.DrawListRegestry) {
m->Label(std::format("Framerate: {:.2f}", pIO.Framerate)); if (m->BeginTreeNode(it.First.GetName())) {
m->Label(std::format("Focused Menu: {:08X}", pIO.InputHandler.FocusedMenu)); m->Label("Vertices: " + std::to_string(it.Second->NumVertices));
m->Label( m->Label("Indices: " + std::to_string(it.Second->NumIndices));
std::format("Dragged Object: {:08X}", pIO.InputHandler.DraggedObject)); m->Label("Base Layer: " + std::to_string(it.Second->Base));
m->Label(std::format("DragTime: {:.2f}s", m->EndTreeNode();
pIO.InputHandler.DragTime.GetSeconds())); }
m->Label( }
std::format("DragDestination: [{}]", pIO.InputHandler.DragDestination)); m->EndTreeNode();
m->Label(std::format("DragSource: [{}]", pIO.InputHandler.DragSourcePos)); }*/
m->Label(std::format("DragPos: [{}]", pIO.InputHandler.DragPosition)); m->Label("io->Time: " + Strings::FormatMillis(pIO.Time.Get()));
m->Label( m->Label(std::format("Delta: {:.3f}", pIO.Delta));
std::format("DragLastPos: [{}]", pIO.InputHandler.DragLastPosition)); m->Label(std::format("Framerate: {:.2f}", pIO.Framerate));
EndMenu(); m->Label(std::format("Focused Menu: {:08X}", pIO.InputHandler.FocusedMenu));
} m->Label(
} std::format("Dragged Object: {:08X}", pIO.InputHandler.DraggedObject));
m->Label(std::format("DragTime: {:.2f}s",
PD_API void UI7::Context::StyleEditor(bool* show) { pIO.InputHandler.DragTime.GetSeconds()));
if (auto m = BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) { m->Label(
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor"); std::format("DragDestination: [{}]", pIO.InputHandler.DragDestination));
m->Separator(); m->Label(std::format("DragSource: [{}]", pIO.InputHandler.DragSourcePos));
m->DragData("MenuPadding", (float*)&pIO.MenuPadding, 2, 0.f, 100.f); m->Label(std::format("DragPos: [{}]", pIO.InputHandler.DragPosition));
m->DragData("FramePadding", (float*)&pIO.FramePadding, 2, 0.f, 100.f); m->Label(
m->DragData("ItemSpace", (float*)&pIO.ItemSpace, 2, 0.f, 100.f); std::format("DragLastPos: [{}]", pIO.InputHandler.DragLastPosition));
m->DragData("MinSliderSize", (float*)&pIO.MinSliderDragSize, 2, 1.f, 100.f); EndMenu();
m->DragData("OverScroll Modifier", &pIO.OverScrollMod, 1, 0.01f, }
std::numeric_limits<float>::max(), 0.01f, 2); }
m->Checkbox("Menu Border", pIO.ShowMenuBorder);
m->Checkbox("Frame Border", pIO.ShowFrameBorder); PD_API void UI7::Context::StyleEditor(bool* show) {
m->SeparatorText("Theme"); if (auto m = BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) {
if (m->Button("Dark")) { m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
UI7::Theme::Default(pIO.Theme); m->Separator();
} m->DragData("MenuPadding", (float*)&pIO.MenuPadding, 2, 0.f, 100.f);
m->SameLine(); m->DragData("FramePadding", (float*)&pIO.FramePadding, 2, 0.f, 100.f);
if (m->Button("Flashbang")) { m->DragData("ItemSpace", (float*)&pIO.ItemSpace, 2, 0.f, 100.f);
UI7::Theme::Flashbang(pIO.Theme); m->DragData("MinSliderSize", (float*)&pIO.MinSliderDragSize, 2, 1.f, 100.f);
} m->DragData("OverScroll Modifier", &pIO.OverScrollMod, 1, 0.01f,
/// Small trick to print without prefix std::numeric_limits<float>::max(), 0.01f, 2);
#define ts(x) m->ColorEdit(std::string(#x).substr(9), pIO.Theme.GetRef(x)); m->Checkbox("Menu Border", pIO.ShowMenuBorder);
#define ts2(x) \ m->Checkbox("Frame Border", pIO.ShowFrameBorder);
m->DragData(std::string(#x).substr(9), (u8*)&pIO.Theme.GetRef(x), 4, (u8)0, \ m->SeparatorText("Theme");
(u8)255); if (m->Button("Dark")) {
ts(UI7Color_Background); UI7::Theme::Default(pIO.Theme);
ts(UI7Color_Border); }
ts(UI7Color_Button); m->SameLine();
ts(UI7Color_ButtonDead); if (m->Button("Flashbang")) {
ts(UI7Color_ButtonActive); UI7::Theme::Flashbang(pIO.Theme);
ts(UI7Color_ButtonHovered); }
ts(UI7Color_Text); /// Small trick to print without prefix
ts(UI7Color_TextDead); #define ts(x) m->ColorEdit(std::string(#x).substr(9), pIO.Theme.GetRef(x));
ts(UI7Color_Header); #define ts2(x) \
ts(UI7Color_HeaderDead); m->DragData(std::string(#x).substr(9), (u8*)&pIO.Theme.GetRef(x), 4, (u8)0, \
ts(UI7Color_Selector); (u8)255);
ts(UI7Color_Checkmark); ts(UI7Color_Background);
ts(UI7Color_FrameBackground); ts(UI7Color_Border);
ts(UI7Color_FrameBackgroundHovered); ts(UI7Color_Button);
ts(UI7Color_Progressbar); ts(UI7Color_ButtonDead);
ts(UI7Color_ListEven); ts(UI7Color_ButtonActive);
ts(UI7Color_ListOdd); ts(UI7Color_ButtonHovered);
this->EndMenu(); ts(UI7Color_Text);
} ts(UI7Color_TextDead);
} ts(UI7Color_Header);
} // namespace UI7 ts(UI7Color_HeaderDead);
} // namespace PD ts(UI7Color_Selector);
ts(UI7Color_Checkmark);
ts(UI7Color_FrameBackground);
ts(UI7Color_FrameBackgroundHovered);
ts(UI7Color_Progressbar);
ts(UI7Color_ListEven);
ts(UI7Color_ListOdd);
this->EndMenu();
}
}
} // namespace UI7
} // namespace PD
+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; 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() { int main() {
PD::Os::UseDriver<PD::OsDriver>(); PD::Os::UseDriver<PD::OsDriver>();
ColorTests(); ColorTests();
IDTests();
std::cout << PD::Os::GetTime() << std::endl; std::cout << PD::Os::GetTime() << std::endl;
PD::Pool<int> pool; PD::Pool<int> pool;
pool.Init(90); pool.Init(90);
+2
View File
@@ -21,6 +21,8 @@ class OsCtx {
virtual bool Mainloop() { return false; } virtual bool Mainloop() { return false; }
virtual void ClearViewPort() {} virtual void ClearViewPort() {}
virtual void SwapBuffers() {} virtual void SwapBuffers() {}
virtual int GetScreenCount() { return 1; }
virtual void DrawOnScreen(int s = 0) {}
PD::fvec2 PositionTranslate(PD::fvec2 in) { PD::fvec2 PositionTranslate(PD::fvec2 in) {
return fvec2(in.x * pViewPort.x, in.y * pViewPort.y); 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; bool Mainloop() override;
void ClearViewPort() override; void ClearViewPort() override;
void SwapBuffers() override; void SwapBuffers() override;
int GetScreenCount() override { return 2; }
void DrawOnScreen(int s) override;
private: private:
struct Impl; struct Impl;
+31 -7
View File
@@ -198,9 +198,9 @@ int main(int argc, char** argv) {
auto pTex = PD::Gfx::LoadTexture(img, img.Width(), img.Height()); auto pTex = PD::Gfx::LoadTexture(img, img.Width(), img.Height());
PD::Li::Font font; PD::Li::Font font;
PD::Li::Font debug_font; PD::Li::Font debug_font;
font.LoadTTF(ResourcePath("default.ttf"), 32, LiFontFlags_SDF); font.LoadTTF(ResourcePath("default.ttf"), 32, LiFontFlags_SDF);
debug_font.LoadTTF(ResourcePath("JetBrainsMono-Medium.ttf"), 32, debug_font.LoadTTF(ResourcePath("JetBrainsMono-Medium.ttf"), 32,
LiFontFlags_SDF | LiFontFlags_Monospace); LiFontFlags_SDF | LiFontFlags_Monospace);
pList.SetFont(&font); pList.SetFont(&font);
App app(font); App app(font);
Cursor LeftStick; Cursor LeftStick;
@@ -208,15 +208,23 @@ int main(int argc, char** argv) {
RightStick.pColor = "#00ffff"; RightStick.pColor = "#00ffff";
PD::UI7::Context ui7; PD::UI7::Context ui7;
ui7.GetIO().Font = &font; 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)); ui7.AddViewPort("Default", PD::ivec4(0, 0, 1280, 720));
#endif
ui7.UseViewPort("Default"); ui7.UseViewPort("Default");
bool pMetricsWin = true;
while (pOs->Mainloop()) { while (pOs->Mainloop()) {
PD::TT::End("OSCTX::MainLoop"); PD::TT::End("OSCTX::MainLoop");
pOs->DrawOnScreen(0);
pOs->ClearViewPort(); pOs->ClearViewPort();
PD::TT::Scope __st("MainLoop"); PD::TT::Scope __st("MainLoop");
PD::TT::Beg("MainRaw"); PD::TT::Beg("MainRaw");
PD::Hid::Update(); PD::Hid::Update();
PD::Gfx::NewFrame(); PD::Gfx::NewFrame();
PD::Li::ResetPools();
// app.Update(pOs->GetViewport(), pList); // app.Update(pOs->GetViewport(), pList);
pList.SetFontscale(0.7); pList.SetFontscale(0.7);
if (PD::Hid::IsEvent(PD::Hid::Event::Down, PD::Hid::Gamepad::CPLeft | if (PD::Hid::IsEvent(PD::Hid::Event::Down, PD::Hid::Gamepad::CPLeft |
@@ -297,22 +305,37 @@ int main(int argc, char** argv) {
"#ff00ff"); "#ff00ff");
} }
pList.SetFont(&font); pList.SetFont(&font);
#ifndef __3DS__
PD::TT::Beg("BuildUI7Menus"); PD::TT::Beg("BuildUI7Menus");
if (auto m = ui7.BeginMenu("Test")) { if (auto m = ui7.BeginMenu("Test")) {
m->Label("Hello World!"); m->Label("Hello World!");
m->Image(pTex, 128.f);
ui7.EndMenu(); ui7.EndMenu();
} }
ui7.MetricsMenu(); 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());
m->Label("GFX Draw Calls: {}", PD::Gfx::GetNumDrawcalls());
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(&pMetricsWin);
ui7.StyleEditor();
PD::TT::End("BuildUI7Menus"); PD::TT::End("BuildUI7Menus");
PD::TT::Beg("UI7::Context::Update"); PD::TT::Beg("UI7::Context::Update");
ui7.Update(); ui7.Update();
PD::TT::End("UI7::Context::Update"); PD::TT::End("UI7::Context::Update");
#endif
PD::Gfx::Reset(); PD::Gfx::Reset();
PD::TT::Beg("PD::Gfx::Draw"); PD::TT::Beg("PD::Gfx::Draw");
PD::Gfx::Draw(pList); pOs->DrawOnScreen(1);
pOs->ClearViewPort();
PD::Gfx::Draw(ui7.GetDrawData()); PD::Gfx::Draw(ui7.GetDrawData());
pOs->DrawOnScreen(0);
PD::Gfx::Draw(pList);
PD::TT::End("PD::Gfx::Draw"); PD::TT::End("PD::Gfx::Draw");
pList.Clear(); pList.Clear();
PD::TT::End("MainRaw"); PD::TT::End("MainRaw");
@@ -320,6 +343,7 @@ int main(int argc, char** argv) {
PD::TT::Beg("OSCTX::MainLoop"); PD::TT::Beg("OSCTX::MainLoop");
} }
font.Delete(); font.Delete();
debug_font.Delete();
PD::Gfx::DeleteTexture(pTex); PD::Gfx::DeleteTexture(pTex);
PD::Gfx::Deinit(); PD::Gfx::Deinit();
pOs->Deinit(); pOs->Deinit();
+21 -10
View File
@@ -18,6 +18,7 @@ struct DesktopOS::Impl {
#if WIN32 #if WIN32
IDirect3D9* d3d = nullptr; IDirect3D9* d3d = nullptr;
IDirect3DDevice9* dx9_device = nullptr; IDirect3DDevice9* dx9_device = nullptr;
D3DPRESENT_PARAMETERS d3dpp = {};
#endif #endif
}; };
@@ -56,17 +57,18 @@ void DesktopOS::Init() {
if (pDriver == Driver::DirectX9) { if (pDriver == Driver::DirectX9) {
impl->d3d = Direct3DCreate9(D3D_SDK_VERSION); impl->d3d = Direct3DCreate9(D3D_SDK_VERSION);
auto hwnd = glfwGetWin32Window(impl->win); auto hwnd = glfwGetWin32Window(impl->win);
D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.Windowed = TRUE; impl->d3dpp = D3DPRESENT_PARAMETERS{};
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; impl->d3dpp.Windowed = TRUE;
d3dpp.hDeviceWindow = hwnd; impl->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; impl->d3dpp.hDeviceWindow = hwnd;
d3dpp.EnableAutoDepthStencil = TRUE; impl->d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; impl->d3dpp.EnableAutoDepthStencil = TRUE;
impl->d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
HRESULT hr = impl->d3d->CreateDevice( HRESULT hr = impl->d3d->CreateDevice(
D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &impl->dx9_device); D3DCREATE_HARDWARE_VERTEXPROCESSING, &impl->d3dpp, &impl->dx9_device);
if (FAILED(hr)) { if (FAILED(hr)) {
MessageBoxW(nullptr, L"Failed to create D3D9 device", L"Error", MB_OK); MessageBoxW(nullptr, L"Failed to create D3D9 device", L"Error", MB_OK);
std::abort(); std::abort();
@@ -100,7 +102,15 @@ void DesktopOS::ClearViewPort() {
glViewport(0, 0, pViewPort.x, pViewPort.y); glViewport(0, 0, pViewPort.x, pViewPort.y);
} else if (pDriver == Driver::DirectX9) { } else if (pDriver == Driver::DirectX9) {
#ifdef _WIN32 #ifdef _WIN32
if (impl->dx9_device) { // Resize the swapchain to match the window size
if (impl->dx9_device && pViewPort.x > 0 && pViewPort.y > 0) {
if (impl->d3dpp.BackBufferWidth != (UINT)pViewPort.x ||
impl->d3dpp.BackBufferHeight != (UINT)pViewPort.y) {
impl->d3dpp.BackBufferWidth = pViewPort.x;
impl->d3dpp.BackBufferHeight = pViewPort.y;
impl->dx9_device->Reset(&impl->d3dpp);
}
impl->dx9_device->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, impl->dx9_device->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(25, 25, 25), 1.0f, 0); D3DCOLOR_XRGB(25, 25, 25), 1.0f, 0);
impl->dx9_device->BeginScene(); impl->dx9_device->BeginScene();
@@ -112,7 +122,8 @@ void DesktopOS::ClearViewPort() {
void DesktopOS::SwapBuffers() { void DesktopOS::SwapBuffers() {
if (pDriver == Driver::DirectX9) { if (pDriver == Driver::DirectX9) {
#ifdef _WIN32 #ifdef _WIN32
if (impl->dx9_device) { // yes we schould use some safetey checks
if (impl->dx9_device && pViewPort.x > 0 && pViewPort.y > 0) {
impl->dx9_device->EndScene(); impl->dx9_device->EndScene();
impl->dx9_device->Present(nullptr, nullptr, nullptr, nullptr); impl->dx9_device->Present(nullptr, nullptr, nullptr, nullptr);
} }
+18 -6
View File
@@ -16,6 +16,7 @@ struct HorizonCtr::Impl {
C3D_RenderTarget* Top = nullptr; C3D_RenderTarget* Top = nullptr;
C3D_RenderTarget* Bottom = nullptr; C3D_RenderTarget* Bottom = nullptr;
uint32_t* pSocBuf = nullptr; uint32_t* pSocBuf = nullptr;
int CurrentScreen = 0;
}; };
void HorizonCtr::Init() { void HorizonCtr::Init() {
@@ -33,7 +34,7 @@ void HorizonCtr::Init() {
romfsInit(); romfsInit();
osSetSpeedupEnable(true); osSetSpeedupEnable(true);
gfxInitDefault(); gfxInitDefault();
consoleInit(GFX_BOTTOM, nullptr); // consoleInit(GFX_BOTTOM, nullptr);
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
impl->Top = impl->Top =
C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); 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, C3D_RenderTargetSetOutput(impl->Bottom, GFX_BOTTOM, GFX_LEFT,
DisplayTransferFlags); DisplayTransferFlags);
PD::Gfx::UseDriver<PD::GfxCitro3D>(); PD::Gfx::UseDriver<PD::GfxCitro3D>();
PD::Hid::UseDriver<PD::HidDriver>(); PD::Hid::UseDriver<PD::Hid3DS>();
} }
void HorizonCtr::Deinit() { void HorizonCtr::Deinit() {
@@ -61,16 +62,27 @@ void HorizonCtr::Deinit() {
bool HorizonCtr::Mainloop() { bool HorizonCtr::Mainloop() {
pViewPort = ivec2(400, 240); pViewPort = ivec2(400, 240);
hidScanInput();
bool _kill = hidKeysUp() & KEY_START; bool _kill = hidKeysUp() & KEY_START;
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
impl->CurrentScreen = 0;
return aptMainLoop() && !_kill; return aptMainLoop() && !_kill;
} }
void HorizonCtr::ClearViewPort() { void HorizonCtr::ClearViewPort() {
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);
pViewPort = PD::ivec2(400, 240);
} else if (s == 1) {
C3D_FrameDrawOn(impl->Bottom);
pViewPort = PD::ivec2(320, 240);
}
PD::Gfx::SetViewPort(pViewPort); PD::Gfx::SetViewPort(pViewPort);
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
C3D_FrameDrawOn(impl->Top);
C3D_RenderTargetClear(impl->Top, C3D_CLEAR_ALL, PD::Color(25, 25, 25, 25), 0);
} }
void HorizonCtr::SwapBuffers() { C3D_FrameEnd(0); } void HorizonCtr::SwapBuffers() { C3D_FrameEnd(0); }