Author SHA1 Message Date
tobid7 39e91b588f reset layers and give menus a base layer to gather perfect ordered rendering 2026-09-06 15:58:20 +02:00
tobid7 7bb1406365 Add FontStack to UI7 and uncomment layer lines 2026-09-06 15:58:20 +02:00
tobid7 438584e4f2 move and fix scrolling to layout
Scrolling was hardcoded to 3ds sCrEeNhEiGhT wTh
2026-09-06 15:58:20 +02:00
tobid7 acc4fd11eb Layers are back 2026-09-06 15:58:19 +02:00
tobid7 72bb76dcbc hotfix 2026-09-06 15:58:19 +02:00
tobid7 272b66f7f0 Add Hid3DS 2026-09-06 15:58:19 +02:00
tobid7 6637a3692b 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-06 15:58:19 +02:00
tobid7 feeb3b1ba8 Add Drawlist Vertex and Indexcount geteter (for debugging usage only) 2026-09-06 15:58:19 +02:00
tobid7 5a56bf3986 Fix The rest of UI7 Mem leaks
Throw OneFrame living objs into a pool
2026-09-06 15:58:19 +02:00
tobid7 1dfc538ae3 stop leaking idobj memory (and coloredit layout mem) 2026-09-06 15:58:19 +02:00
tobid7 36c05a9138 dx9: update device size on window size change 2026-09-06 15:58:18 +02:00
tobid7 a8d841c63c format documents 2026-09-06 15:58:18 +02:00
tobid7 8983371806 unload debugfont and add Gfx debug menu 2026-09-06 15:58:18 +02:00
tobid7 2b4c4bacd6 fix random garbage ptr issues 2026-09-06 15:58:18 +02:00
tobid7 859a4c96ae Fix Indexorder issues and patchfixsomehow dx9 tex filtering 2026-09-06 15:58:18 +02:00
tobid7 0e0d576954 No big update without msvc compiler errors :/ 2026-09-06 15:58:18 +02:00
tobid7 4a29cb4330 More timings 2026-09-06 15:58:18 +02:00
tobid7 e0b86ee3f6 UI7 is BACK!
took me about a full week to get something to render again withour shared_ptrs
as of now this is very unstable, untested and lacking a lot of features due to lithium is lacking the base for that
Added JetBrainsMono font as debug font for the metrics
2026-09-06 15:58:17 +02:00
tobid7 b121001db7 Add missing GetDriverName to Os 2026-09-06 15:58:17 +02:00
tobid7 2059772ad1 Draw the line (oder so) 2026-09-06 15:58:17 +02:00
tobid7 81aa08485b Load the font async for now 2026-09-06 15:58:17 +02:00
tobid7 ecadf0a44c n3ds-boost 2026-09-06 15:58:17 +02:00
tobid7 6dfc04378a SDF & MONOSPACE FONT RENDERING 2026-09-06 15:58:17 +02:00
tobid7 e3ffcbb596 save 75% of font memory 2026-09-06 15:58:16 +02:00
tobid7 469cd535fd Upload pools once per Gfx::Draw and FIX DX9 2026-09-06 15:58:16 +02:00
tobid7 b594e09bdb reset pools on newframe 2026-09-06 15:58:16 +02:00
tobid7 41b25e4476 move global pools into gfx driver
prevents double copy problems
saves memory
(needs to be optimized...)
2026-09-06 15:58:16 +02:00
tobid7 25607b865c faster rect command creation 2026-09-06 15:58:16 +02:00
tobid7 1bf103c894 cache ascii chars directly 2026-09-06 15:58:16 +02:00
tobid7 11a480136b insane performance boost (on 3ds) 2026-09-06 15:58:16 +02:00
tobid7 e6fcfe0650 time trace is back 2026-09-06 15:58:15 +02:00
tobid7 a8a80cfa47 implement Image::Convert and Image::Flip 2026-09-06 15:58:15 +02:00
tobid7 b7f1037b18 pool append move and copy 2026-09-06 15:58:15 +02:00
tobid7 de51a35734 # small fixes
- Fix Os::GetTimeNano()
- only build tests on non vendored usage
2026-09-06 15:58:15 +02:00
tobid7 13152a317a Fix 2026-09-06 15:58:15 +02:00
tobid7 5dd5907c43 Fix 3ds build and update libpicasso 2026-09-06 15:58:15 +02:00
tobid7 673e53935a remove poc func 2026-09-06 15:58:15 +02:00
tobid7 dda8258064 Add support for rotated gradients 2026-09-06 15:58:14 +02:00
tobid7 0c55291f9c Add stick and trigger input support 2026-09-06 15:58:14 +02:00
tobid7 c5f6f0cb33 Fix clang warning 2026-09-06 15:58:14 +02:00
tobid7 391eea100a fix preset names for Selection Views 2026-09-06 15:58:14 +02:00
tobid7 d70a9970e9 Add NX Hid Driver Template
- Add WIP HidNX Driver (clangd not working with devkitpro for switch on windows)
- Add default-release as default search path for compile_commands.json
- remove mingw preset (casue its exactly the default target)
- Move Mouse pos cycle into HidDriver::Update
- Test around with HidGlfw on Nintendo switch
2026-09-06 15:58:14 +02:00
tobid7 0f044538cc Add proper Gamepad support (WIP) 2026-09-06 15:58:14 +02:00
tobid7 546940aa77 allo wPD::Color in Drawlist 2026-09-06 15:58:14 +02:00
tobid7 dc365bc658 Add Input functionality to Ultra
- Add point InSpace check to PD::Li::Math
- Add Universal AlignmentCenter flag for Horizontal and and Vertical Alignment
-  Add Fallbackfont to Layout (if you dont want to set font per object)
- Add Button Object WIP
- Rename OnHover to OnFocus and add OnUnfocus
- Move font and FontScale to ElementBase (for fallback logic etc)
- Add UpdateInput func to ElementBase
- Corectly Set fontScale in Text Rendering
- Update ecample
2026-09-06 15:58:13 +02:00
tobid7 1ccc7075fa Allow implicit usage of "#ffffffff" etc 2026-09-06 15:58:13 +02:00
tobid7 b069f10841 Add HidDriver base and small HidGLFW driver 2026-09-06 15:58:13 +02:00
tobid7 bf3eef8d28 rename PDBackendFlags to PDGfxBackendFlags 2026-09-06 15:58:13 +02:00
tobid7 6298d4c816 Implement VCanvas and Update TextElem
- Text now requires a font and is able to take an individual scale
- Container requires &ref for Elements to make sure they always exist
- SetViewport now sets the canvas as well
- SetBaseViewport Sets the Virtual Canvas Size
- Layout Now requires a Drawlist reference in Render function
- main.cpp: updated the template
2026-09-06 15:58:13 +02:00
tobid7 212ba0c617 Actually implement ultra-rendering 2026-09-06 15:58:13 +02:00
tobid7 b4a7260cf2 Rework Project Ultra
- Added container
- Made container the base of Layout
- Set Containers theirself as pParent for Elements on Push
2026-09-06 15:58:13 +02:00
tobid7 5cf9ff0109 Fix path rects 2026-09-06 15:58:12 +02:00
tobid7 69b5e74d91 Fixing riunded rects 2026-09-06 15:58:12 +02:00
tobid7 9b69d78118 Add a default preset (for linux/macos default builds) 2026-09-06 15:58:12 +02:00
tobid7 e573523511 Add cmake presets
- MSVC requires cmake for Windows
- mingw only builds when GLSLANG is excluded due to wrong header generation
2026-09-06 15:58:12 +02:00
tobid7 1317599475 build 3dsx and nro in ALL stage 2026-09-06 15:58:12 +02:00
tobid7 1876ab9365 More stuff done at Project Ultra
- Added renderspace
- Revision System (to not always update pRenderspace
- added some test scene
2026-09-06 15:58:12 +02:00
tobid7 ce2dc94121 WIP (Codename Ultra) UI lib 2026-09-06 15:58:12 +02:00
tobid7 bef8ced350 implement font deletion 2026-09-06 15:58:11 +02:00
tobid7 dd038883a0 Fix font bugs 2026-09-06 15:58:11 +02:00
tobid7 7ad2b8b0c5 Add debug getters (and somehow text is not rendering :/) 2026-09-06 15:58:11 +02:00
tobid7 63fb09189d Fix Vertex Alloc usage at Index Alloc 2026-09-06 15:58:11 +02:00
tobid7 306ddfed53 Readd font support (not workign yet) 2026-09-06 15:58:11 +02:00
tobid7 c2b0fa01db Update lazyvec / vec api as well as rect are mostly constexpr now 2026-09-06 15:58:11 +02:00
tobid7 594cf5cca4 Always disable glslang build for NintendoSwitch on Windows 2026-09-06 15:58:10 +02:00
tobid7 191bca26d5 Present DX9 Frames ... 2026-09-06 15:58:10 +02:00
tobid7 85a92f8371 Add a PositionTranslate func and add Errors for TextureSize mismatch 2026-09-06 15:58:10 +02:00
tobid7 f3d326c237 Add PD::Image and add a setter for logfilter 2026-09-06 15:58:10 +02:00
tobid7 fda39b3d36 Forgot about dx9 (UNTESTED!!!) 2026-09-06 15:58:10 +02:00
tobid7 8e09025c40 Add Os Bridge into test framework 2026-09-06 15:58:10 +02:00
tobid7 2a57b7c08c Refactor PD::Li Pools system, Upgrade PD::Pool and add better logging
- Add ResetFast to Pool using c++20 concept
- Add Put function to Pool
- Use Pool Index instead of pointers in Command
- Add accessor to Li Pools to prevent wrong command usage
- Add Command Formatter
- Use ResetFast for all Pools
- Add Reset func to Li::Vertex (for ResetFast)
- Add Pool Expandor and Put funcs to Lithium pools
- Add getters for GfxDriverBase to PD::Li Pools
2026-09-06 15:58:10 +02:00
tobid7 9d0565f60c Add nintendo switch support 2026-09-06 15:58:09 +02:00
tobid7 4691d158a9 Remove Gfx Driver Vertex and IndexBuffer size config 2026-09-06 15:58:09 +02:00
tobid7 57c376a822 Add Drawlist
- Add Pool iterator support
- Add Pool Expandability
- Add Pool::Push
- Add Lithium Maths API
- Remove InitPools
- update spirv-helper
2026-09-06 15:58:09 +02:00
tobid7 d72c447875 Replace spirv-helper stuff with a library that combines everything 2026-09-06 15:58:09 +02:00
tobid7 518015afb1 Add the shaders 2026-09-06 15:58:09 +02:00
tobid7 e6a60e90d1 Add pdsg (palladium spirv-generator)
- remove glslang from pd-system
- use spirv blobs instead of glsl 460
- Use Legacy shaders for OpenGL2 backend
- add devnotes
2026-09-06 15:58:09 +02:00
tobid7 9d63a17700 Add SpirvHelper (Shader cross compilation)
- Make OpenGL2 and OpenGL3 use the same base shaders (using SpirvHelper)
- Add Transpose func to Mat4
2026-09-06 15:58:09 +02:00
tobid7 fd498c5ea2 Add missing sources 2026-09-06 15:58:08 +02:00
tobid7 0cc886315d Full 3ds support and fix dx9 2026-09-06 15:58:08 +02:00
tobid7 1b9876f64b Work at 3ds support and backend upgrades
- Track textures (not sure if this is done tbh)
- Add lithium formatters and move TextureID, TextureFormat and TextureFilter to lithium
- Only include gl-helper if any glDriver is included
- Add Li::Rect for UV stuff
- Add Li::Texture as Info holder (still thinking of making them to ptrs
- Add Check if textures are still loaded on exit
2026-09-06 15:58:08 +02:00
tobid7 cd904ea544 Add backends
- Renamed GfxOpenGL to GfxOPenGL2
- Added GfxOpenGL3 backend for OpenGL 3.3+
- Added WIP DirectX9 backend
- Added structure for Citro3D
- Added linear Allocator
2026-09-06 15:58:08 +02:00
tobid7 e43cb41377 More work to drivers
- Add gfx_test
- add texture loading to GfxOpenGL
- add full submit code
- add debug logging
- add construct and destroy functionality to Pool
- add command functionality
- add vertex and index pools to lithium (static and not threadsafe yet)
- Update GfxDriver Matrix with SetViewPort
- Add glfw (only dependency of gfx_test) maybe later required for input driver
2026-09-06 15:58:08 +02:00
tobid7 b2d3d203a2 - Update pool to use template allocator directly instead of std::vector
- Add a GfxDriver config Template to be able to modify settings like allocators / Types for specific Drivers
- Add glad
2026-09-06 15:58:04 +02:00
tobid7 f1a63fe383 0.7.0 rewrite dev
- remove everyting
- keep core
-rename bit_utils to bits
- add formatter for  color
- add float getters to color
- start with new drivers api
2026-09-06 15:57:14 +02:00
3 changed files with 749 additions and 804 deletions
Executable → Regular
+400 -400
View File
@@ -1,400 +1,400 @@
/* /*
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 <algorithm> #include <algorithm>
#include <pd/ui7/containers.hpp> #include <pd/ui7/containers.hpp>
#include <pd/ui7/menu.hpp> #include <pd/ui7/menu.hpp>
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
Menu::Menu(const ID& id, IO& io) : pIO(io), pID(id), pLayout(id, io) { Menu::Menu(const ID& id, IO& io) : pIO(io), pID(id), pLayout(id, io) {
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y; TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
pLayout.WorkRect.y += TitleBarHeight; pLayout.WorkRect.y += TitleBarHeight;
pLayout.Flags |= UI7LayoutFlags_UseClipRect; pLayout.Flags |= UI7LayoutFlags_UseClipRect;
pLayout.CursorInit(); pLayout.CursorInit();
} }
PD_API void Menu::Label(const std::string& label) { PD_API void Menu::Label(const std::string& label) {
// Layout API // Layout API
auto r = pIO.LabelPool.Allocate(); auto r = pIO.LabelPool.Allocate();
*r = UI7::Label(label, pIO); *r = UI7::Label(label, pIO);
pLayout.AddObject(r); pLayout.AddObject(r);
} }
PD_API bool Menu::Button(const std::string& label) { PD_API bool Menu::Button(const std::string& label) {
bool ret = false; bool ret = false;
u32 id = u32 id =
Strings::FastHash("btn" + label + std::to_string(pLayout.Objects.size())); Strings::FastHash("btn" + label + std::to_string(pLayout.Objects.size()));
Container* r = pLayout.FindObject(id); Container* r = pLayout.FindObject(id);
if (!r) { if (!r) {
r = new UI7::Button(label, pIO); r = new UI7::Button(label, pIO);
r->SetID(id); r->SetID(id);
} }
pLayout.AddObject(r); pLayout.AddObject(r);
if (!r->Skippable()) { if (!r->Skippable()) {
ret = reinterpret_cast<UI7::Button*>(r)->IsPressed(); ret = reinterpret_cast<UI7::Button*>(r)->IsPressed();
} }
return ret; return ret;
} }
PD_API void Menu::Checkbox(const std::string& label, bool& v) { PD_API void Menu::Checkbox(const std::string& label, bool& v) {
u32 id = u32 id =
Strings::FastHash("cbx" + label + std::to_string(pLayout.Objects.size())); Strings::FastHash("cbx" + label + std::to_string(pLayout.Objects.size()));
Container* r = pLayout.FindObject(id); Container* r = pLayout.FindObject(id);
if (!r) { if (!r) {
r = new UI7::Checkbox(label, v, pIO); r = new UI7::Checkbox(label, v, pIO);
r->SetID(id); r->SetID(id);
} }
pLayout.AddObject(r); pLayout.AddObject(r);
} }
PD_API void Menu::Image(Li::Texture img, fvec2 size, Li::Rect uv) { PD_API void Menu::Image(Li::Texture img, fvec2 size, Li::Rect uv) {
auto r = pIO.ImagePool.Allocate(); auto r = pIO.ImagePool.Allocate();
*r = UI7::Image(img, size, uv); *r = UI7::Image(img, size, uv);
pLayout.AddObject(r); pLayout.AddObject(r);
} }
PD_API void Menu::ColorEdit(const std::string& label, u32& clr) { PD_API void Menu::ColorEdit(const std::string& label, u32& clr) {
u32 id = Strings::FastHash("drd" + label); u32 id = Strings::FastHash("drd" + label);
Container* r = pLayout.FindObject(id); Container* r = pLayout.FindObject(id);
if (!r) { if (!r) {
r = new UI7::ColorEdit(label, &clr, pIO); r = new UI7::ColorEdit(label, &clr, pIO);
r->SetID(id); r->SetID(id);
} }
pLayout.AddObject(r); pLayout.AddObject(r);
} }
PD_API void Menu::Separator() { PD_API void Menu::Separator() {
// Dynamic Objects are very simple... // Dynamic Objects are very simple...
DynObj* r = pIO.DynObjPool.Allocate(); DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj( *r = UI7::DynObj(
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) { [=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
l->DrawRectFilled(self->FinalPos(), self->GetSize(), l->DrawRectFilled(self->FinalPos(), self->GetSize(),
pIO.Theme.Get(UI7Color_TextDead)); pIO.Theme.Get(UI7Color_TextDead));
}); });
// Set size before pushing (cause Cursor Move will require it) // Set size before pushing (cause Cursor Move will require it)
r->SetSize(fvec2( r->SetSize(fvec2(
pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x, pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x,
1)); 1));
pLayout.AddObject(r); pLayout.AddObject(r);
} }
PD_API void Menu::SeparatorText(const std::string& label) { PD_API void Menu::SeparatorText(const std::string& label) {
// Also note to use [=] instead of [&] to not undefined access label // Also note to use [=] instead of [&] to not undefined access label
DynObj* r = pIO.DynObjPool.Allocate(); DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l, *r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
UI7::Container* self) { UI7::Container* self) {
l->SetFont(self->GetFont()); l->SetFont(self->GetFont());
fvec2 size = self->GetSize(); fvec2 size = self->GetSize();
fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale); fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale);
fvec2 pos = self->FinalPos(); fvec2 pos = self->FinalPos();
auto align = pLayout.GetAlignment(); auto align = pLayout.GetAlignment();
vec2 rpos = pLayout.AlignPosition(pos, tdim, vec2 rpos = pLayout.AlignPosition(pos, tdim,
fvec4(pLayout.Pos, pLayout.Size), align); fvec4(pLayout.Pos, pLayout.Size), align);
if (!(align & UI7Align_Left)) { if (!(align & UI7Align_Left)) {
l->DrawRectFilled(fvec2(rpos.x + io->FramePadding.x, tdim.y * 0.5), l->DrawRectFilled(fvec2(rpos.x + io->FramePadding.x, tdim.y * 0.5),
fvec2(pos.x - rpos.x - io->MenuPadding.x, 1), fvec2(pos.x - rpos.x - io->MenuPadding.x, 1),
io->Theme.Get(UI7Color_TextDead)); io->Theme.Get(UI7Color_TextDead));
} }
if (!(align & UI7Align_Right)) { if (!(align & UI7Align_Right)) {
l->DrawRectFilled(pos + fvec2(tdim.x + io->FramePadding.x, tdim.y * 0.5), l->DrawRectFilled(pos + fvec2(tdim.x + io->FramePadding.x, tdim.y * 0.5),
fvec2(size.x - tdim.x - io->MenuPadding.x, 1), fvec2(size.x - tdim.x - io->MenuPadding.x, 1),
io->Theme.Get(UI7Color_TextDead)); io->Theme.Get(UI7Color_TextDead));
} }
l->DrawTextEx(rpos, label.c_str(), io->Theme.Get(UI7Color_Text), 0, l->DrawTextEx(rpos, label.c_str(), io->Theme.Get(UI7Color_Text), 0,
fvec2(pLayout.Size.x, self->GetSize().y)); fvec2(pLayout.Size.x, self->GetSize().y));
}); });
// Set size before pushing (cause Cursor Move will require it) // Set size before pushing (cause Cursor Move will require it)
r->SetSize(fvec2( r->SetSize(fvec2(
pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x, pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x,
pIO.Font->PixelHeight * pIO.FontScale)); pIO.Font->PixelHeight * pIO.FontScale));
pLayout.AddObject(r); pLayout.AddObject(r);
} }
PD_API void Menu::HandleFocus() { PD_API void Menu::HandleFocus() {
// Check if menu can be focused for Selective Menu Input API // Check if menu can be focused for Selective Menu Input API
vec4 newarea = fvec4(pLayout.Pos, pLayout.Size); vec4 newarea = fvec4(pLayout.Pos, pLayout.Size);
if (!pIsOpen) { if (!pIsOpen) {
newarea = fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)); newarea = fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight));
} }
if ((PD::Hid::IsEvent(Hid::Event::Down, Hid::Gamepad::Touch) || if ((PD::Hid::IsEvent(Hid::Event::Down, Hid::Gamepad::Touch) ||
PD::Hid::IsEvent(Hid::Event::Down, Hid::Keyboard::MouseLeft)) && PD::Hid::IsEvent(Hid::Event::Down, Hid::Keyboard::MouseLeft)) &&
Li::Math::InBounds(PD::Hid::MousePos(), newarea) && Li::Math::InBounds(PD::Hid::MousePos(), newarea) &&
!Li::Math::InBounds(PD::Hid::MousePos(), !Li::Math::InBounds(PD::Hid::MousePos(),
pIO.InputHandler.FocusedMenuRect)) { pIO.InputHandler.FocusedMenuRect)) {
pIO.InputHandler.FocusedMenu = pID; pIO.InputHandler.FocusedMenu = pID;
} }
if (pIO.InputHandler.FocusedMenu == pID) { if (pIO.InputHandler.FocusedMenu == pID) {
pIO.InputHandler.FocusedMenuRect = newarea; pIO.InputHandler.FocusedMenuRect = newarea;
} }
} }
PD_API void Menu::HandleTitlebarActions() { PD_API void Menu::HandleTitlebarActions() {
// Collapse // Collapse
if (!(Flags & UI7MenuFlags_NoCollapse)) { if (!(Flags & UI7MenuFlags_NoCollapse)) {
vec2 cpos = pLayout.Pos + pIO.FramePadding; vec2 cpos = pLayout.Pos + pIO.FramePadding;
// clr_collapse_tri = UI7Color_FrameBackground; // clr_collapse_tri = UI7Color_FrameBackground;
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clbse"), if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clbse"),
fvec4(cpos, fvec2(18, TitleBarHeight)))) { fvec4(cpos, fvec2(18, TitleBarHeight)))) {
if (pIO.InputHandler.DragReleased) { if (pIO.InputHandler.DragReleased) {
pIsOpen = !pIsOpen; pIsOpen = !pIsOpen;
} }
// clr_collapse_tri = UI7Color_FrameBackgroundHovered; // clr_collapse_tri = UI7Color_FrameBackgroundHovered;
} }
} }
// Close Logic // Close Logic
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown != nullptr) { if (!(Flags & UI7MenuFlags_NoClose) && pIsShown != nullptr) {
fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2;
fvec2 cpos = fvec2 cpos =
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x, fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x,
pLayout.Pos.y + pIO.FramePadding.y); pLayout.Pos.y + pIO.FramePadding.y);
// clr_close_btn = UI7Color_FrameBackground; // clr_close_btn = UI7Color_FrameBackground;
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clse"), if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clse"),
fvec4(cpos, size))) { fvec4(cpos, size))) {
if (pIO.InputHandler.DragReleased) { if (pIO.InputHandler.DragReleased) {
*pIsShown = !(*pIsShown); *pIsShown = !(*pIsShown);
} }
// clr_close_btn = UI7Color_FrameBackgroundHovered; // clr_close_btn = UI7Color_FrameBackgroundHovered;
} }
} }
// Resize logic // Resize logic
if (!(Flags & UI7MenuFlags_NoResize)) { if (!(Flags & UI7MenuFlags_NoResize)) {
vec2 cpos = pLayout.Pos + pLayout.Size - fvec2(20); vec2 cpos = pLayout.Pos + pLayout.Size - fvec2(20);
// clr_close_btn = UI7Color_FrameBackground; // clr_close_btn = UI7Color_FrameBackground;
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "rszs"), if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "rszs"),
fvec4(cpos, fvec2(20)))) { fvec4(cpos, fvec2(20)))) {
fvec2 szs = pLayout.Size + (pIO.InputHandler.DragPosition - fvec2 szs = pLayout.Size + (pIO.InputHandler.DragPosition -
pIO.InputHandler.DragLastPosition); pIO.InputHandler.DragLastPosition);
if (szs.x < 30) szs.x = 30; if (szs.x < 30) szs.x = 30;
if (szs.y < 30) szs.y = 30; if (szs.y < 30) szs.y = 30;
pLayout.Size = szs; pLayout.Size = szs;
// clr_close_btn = UI7Color_FrameBackgroundHovered; // clr_close_btn = UI7Color_FrameBackgroundHovered;
} }
} }
// Menu Movement // Menu Movement
if (!(Flags & UI7MenuFlags_NoMove)) { if (!(Flags & UI7MenuFlags_NoMove)) {
if (pIO.InputHandler.DragObject( if (pIO.InputHandler.DragObject(
pID.GetName() + "tmv", pID.GetName() + "tmv",
fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)))) { fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)))) {
if (pIO.InputHandler.DragDoubleRelease) { if (pIO.InputHandler.DragDoubleRelease) {
pIsOpen = !pIsOpen; pIsOpen = !pIsOpen;
} }
pLayout.Pos = pLayout.Pos + (pIO.InputHandler.DragPosition - pLayout.Pos = pLayout.Pos + (pIO.InputHandler.DragPosition -
pIO.InputHandler.DragLastPosition); pIO.InputHandler.DragLastPosition);
// Keep Window In Viewport // Keep Window In Viewport
// Maybe i need to add some operators to vec // Maybe i need to add some operators to vec
pLayout.Pos.x = std::clamp<float>(pLayout.Pos.x, -pLayout.Size.x + 10, pLayout.Pos.x = std::clamp<float>(pLayout.Pos.x, -pLayout.Size.x + 10,
pIO.CurrentViewPort.pSize.z - 10); pIO.CurrentViewPort.pSize.z - 10);
pLayout.Pos.y = pLayout.Pos.y =
std::clamp<float>(pLayout.Pos.y, pIO.CurrentViewPort.pSize.y, std::clamp<float>(pLayout.Pos.y, pIO.CurrentViewPort.pSize.y,
pIO.CurrentViewPort.pSize.w - 10); pIO.CurrentViewPort.pSize.w - 10);
} }
} }
} }
PD_API void Menu::DrawBaseLayout() { PD_API void Menu::DrawBaseLayout() {
if (pIsOpen) { if (pIsOpen) {
/** Resize Sym (Render on Top of Everything) */ /** Resize Sym (Render on Top of Everything) */
if (!(Flags & UI7MenuFlags_NoResize)) { if (!(Flags & UI7MenuFlags_NoResize)) {
DynObj* r = pIO.DynObjPool.Allocate(); DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) { *r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
l->SetLayer(1); l->SetLayer(1);
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20)); l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20));
l->PathAdd(self->FinalPos() + self->GetSize()); l->PathAdd(self->FinalPos() + self->GetSize());
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0)); l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0));
l->PathFill(io->Theme.Get(UI7Color_Button)); l->PathFill(io->Theme.Get(UI7Color_Button));
l->SetLayer(0); l->SetLayer(0);
}); });
r->SetSize( r->SetSize(
fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight)); fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight));
r->SetPos(fvec2(0, TitleBarHeight)); r->SetPos(fvec2(0, TitleBarHeight));
pLayout.AddObjectEx(r, pLayout.AddObjectEx(r,
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
} }
/** Background */ /** Background */
DynObj* r = pIO.DynObjPool.Allocate(); DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) { *r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
l->SetLayer(0); l->SetLayer(0);
l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f, l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f,
LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot); LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot);
l->PathFill(io->Theme.Get(UI7Color_Background)); l->PathFill(io->Theme.Get(UI7Color_Background));
/*l->DrawRectFilled(self->FinalPos(), self->GetSize(), /*l->DrawRectFilled(self->FinalPos(), self->GetSize(),
io->Theme.Get(UI7Color_Background));*/ io->Theme.Get(UI7Color_Background));*/
}); });
// Set size before pushing (cause Cursor Move will require it) // Set size before pushing (cause Cursor Move will require it)
r->SetSize( r->SetSize(
fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight)); fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight));
r->SetPos(fvec2(0, TitleBarHeight)); r->SetPos(fvec2(0, TitleBarHeight));
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle | pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle |
UI7LytAdd_Front); UI7LytAdd_Front);
} }
if (!(Flags & UI7MenuFlags_NoTitlebar)) { if (!(Flags & UI7MenuFlags_NoTitlebar)) {
DynObj* r = pIO.DynObjPool.Allocate(); DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj( *r = UI7::DynObj(
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) { [=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
l->SetFont(self->GetFont()); l->SetFont(self->GetFont());
l->SetLayer(20); l->SetLayer(20);
/** Header Bar */ /** Header Bar */
l->DrawRectFilled(self->FinalPos(), self->GetSize(), l->DrawRectFilled(self->FinalPos(), self->GetSize(),
io->Theme.Get(UI7Color_Header)); io->Theme.Get(UI7Color_Header));
l->SetLayer(21); l->SetLayer(21);
/** Inline if statement to shift the Text if collapse sym is shown */ /** Inline if statement to shift the Text if collapse sym is shown */
/** What the hell is this code btw (didn't found a better way) */ /** What the hell is this code btw (didn't found a better way) */
l->DrawText(self->FinalPos() + l->DrawText(self->FinalPos() +
fvec2((Flags & UI7MenuFlags_NoCollapse) fvec2((Flags & UI7MenuFlags_NoCollapse)
? pIO.FramePadding.x ? pIO.FramePadding.x
: (TitleBarHeight - pIO.FramePadding.y * 2 + : (TitleBarHeight - pIO.FramePadding.y * 2 +
(io->FramePadding.x * 2)), (io->FramePadding.x * 2)),
2), 2),
pID.GetName().c_str(), io->Theme.Get(UI7Color_Text)); pID.GetName().c_str(), io->Theme.Get(UI7Color_Text));
l->SetLayer(0); l->SetLayer(0);
}); });
r->SetSize(fvec2(pLayout.GetSize().x, TitleBarHeight)); r->SetSize(fvec2(pLayout.GetSize().x, TitleBarHeight));
r->SetPos(0); r->SetPos(0);
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
/** Collapse Sym */ /** Collapse Sym */
if (!(Flags & UI7MenuFlags_NoCollapse)) { if (!(Flags & UI7MenuFlags_NoCollapse)) {
DynObj* r = pIO.DynObjPool.Allocate(); DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l, *r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
UI7::Container* self) { UI7::Container* self) {
/** This sym actually requires layer 21 (i dont know why) */ /** This sym actually requires layer 21 (i dont know why) */
l->SetLayer(21); l->SetLayer(21);
/** /**
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;) * Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
*/ */
l->DrawTriangleFilled( l->DrawTriangleFilled(
self->FinalPos(), self->FinalPos(),
self->FinalPos() + self->FinalPos() +
fvec2(self->GetSize().x, pIsOpen ? 0 : self->GetSize().y * 0.5), fvec2(self->GetSize().x, pIsOpen ? 0 : self->GetSize().y * 0.5),
self->FinalPos() + self->FinalPos() +
fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y), fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y),
io->Theme.Get(UI7Color_FrameBackground)); io->Theme.Get(UI7Color_FrameBackground));
l->SetLayer(0); l->SetLayer(0);
}); });
r->SetSize(TitleBarHeight - pIO.FramePadding.y * 2); r->SetSize(TitleBarHeight - pIO.FramePadding.y * 2);
r->SetPos(pIO.FramePadding); r->SetPos(pIO.FramePadding);
pLayout.AddObjectEx(r, pLayout.AddObjectEx(r,
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
} }
/** Close Sym (only shown if pIsShown is not nullptr) */ /** Close Sym (only shown if pIsShown is not nullptr) */
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) { if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) {
fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; // Fixed quad size fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; // Fixed quad size
// Need to clamp this way as the math lib lacks a less and greater // Need to clamp this way as the math lib lacks a less and greater
// operator in vec2 (don't checked if it would make sense yet) // operator in vec2 (don't checked if it would make sense yet)
size.x = std::clamp(size.x, 5.f, std::numeric_limits<float>::max()); size.x = std::clamp(size.x, 5.f, std::numeric_limits<float>::max());
size.y = std::clamp(size.y, 5.f, std::numeric_limits<float>::max()); size.y = std::clamp(size.y, 5.f, std::numeric_limits<float>::max());
// Probably should fix the minsize to be locked on y // Probably should fix the minsize to be locked on y
fvec2 cpos = fvec2 cpos =
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x, fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x,
pLayout.Pos.y + pIO.FramePadding.y); pLayout.Pos.y + pIO.FramePadding.y);
pLayout.DrawList.DrawLine(cpos, cpos + size, pLayout.DrawList.DrawLine(cpos, cpos + size,
pIO.Theme.Get(UI7Color_FrameBackground), 2); pIO.Theme.Get(UI7Color_FrameBackground), 2);
pLayout.DrawList.DrawLine(cpos + fvec2(0, size.y), pLayout.DrawList.DrawLine(cpos + fvec2(0, size.y),
cpos + fvec2(size.x, 0), cpos + fvec2(size.x, 0),
pIO.Theme.Get(UI7Color_FrameBackground), 2); pIO.Theme.Get(UI7Color_FrameBackground), 2);
} }
} }
} }
PD_API void Menu::Update() { PD_API void Menu::Update() {
HandleFocus(); HandleFocus();
if (pLayout.Size == fvec2(0.f) || Flags & UI7MenuFlags_AlwaysAutoSize) { if (pLayout.Size == fvec2(0.f) || Flags & UI7MenuFlags_AlwaysAutoSize) {
pLayout.Size = fvec2(pLayout.MaxPosition) + pIO.MenuPadding * 2; pLayout.Size = fvec2(pLayout.MaxPosition) + pIO.MenuPadding * 2;
} }
if (Flags & UI7MenuFlags_VtScrolling) if (Flags & UI7MenuFlags_VtScrolling)
pLayout.Flags |= UI7LayoutFlags_VtScrolling; pLayout.Flags |= UI7LayoutFlags_VtScrolling;
if (Flags & UI7MenuFlags_HzScrolling) if (Flags & UI7MenuFlags_HzScrolling)
pLayout.Flags |= UI7LayoutFlags_HzScrolling; pLayout.Flags |= UI7LayoutFlags_HzScrolling;
if (!(Flags & UI7MenuFlags_NoTitlebar)) { if (!(Flags & UI7MenuFlags_NoTitlebar)) {
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y; TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
pLayout.WorkRect.y = 5.f + TitleBarHeight; pLayout.WorkRect.y = 5.f + TitleBarHeight;
HandleTitlebarActions(); HandleTitlebarActions();
} else { } else {
TitleBarHeight = 0.f; TitleBarHeight = 0.f;
pLayout.WorkRect.y = 5.f; pLayout.WorkRect.y = 5.f;
} }
DrawBaseLayout(); DrawBaseLayout();
pLayout.Update(); pLayout.Update();
} }
PD_API bool Menu::BeginTreeNode(const ID& id) { PD_API bool Menu::BeginTreeNode(const ID& id) {
// As of some notes this should work: // As of some notes this should work:
auto n = pTreeNodes.find(id); auto n = pTreeNodes.find(id);
if (n == pTreeNodes.end()) { if (n == pTreeNodes.end()) {
pTreeNodes[id] = false; pTreeNodes[id] = false;
n = pTreeNodes.find(id); n = pTreeNodes.find(id);
} }
fvec2 pos = pLayout.Cursor; fvec2 pos = pLayout.Cursor;
fvec2 tdim = pIO.Font->GetTextBounds(id.GetName().c_str(), pIO.FontScale); fvec2 tdim = pIO.Font->GetTextBounds(id.GetName().c_str(), pIO.FontScale);
fvec2 szs = tdim + fvec2(pIO.ItemSpace.x + 10, 0); fvec2 szs = tdim + fvec2(pIO.ItemSpace.x + 10, 0);
if (n->second) { if (n->second) {
pLayout.InitialCursorOffset += 10.f; pLayout.InitialCursorOffset += 10.f;
} }
// Object // Object
DynObj* r = pIO.DynObjPool.Allocate(); DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([=, this](IO* io, Li::Drawlist* l, Container* self) { *r = UI7::DynObj([=, this](IO* io, Li::Drawlist* l, Container* self) {
l->SetFont(self->GetFont()); l->SetFont(self->GetFont());
fvec2 ts = self->FinalPos() + fvec2(0, 7); fvec2 ts = self->FinalPos() + fvec2(0, 7);
fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)}; fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)};
if (n->second) { if (n->second) {
float t = pl[0].y; float t = pl[0].y;
pl[0].y = pl[1].x; pl[0].y = pl[1].x;
pl[1].x = t; pl[1].x = t;
} }
l->DrawTriangleFilled(ts, ts + pl[0], ts + pl[1], l->DrawTriangleFilled(ts, ts + pl[0], ts + pl[1],
io->Theme.Get(UI7Color_FrameBackground)); io->Theme.Get(UI7Color_FrameBackground));
l->DrawText(self->FinalPos() + fvec2(10 + io->ItemSpace.x, 0), l->DrawText(self->FinalPos() + fvec2(10 + io->ItemSpace.x, 0),
id.GetName().c_str(), io->Theme.Get(UI7Color_Text)); id.GetName().c_str(), io->Theme.Get(UI7Color_Text));
}); });
/** Yes this new function handler was created for tree nodes */ /** Yes this new function handler was created for tree nodes */
r->AddInputHandler([=, this](IO* io, Container* self) { r->AddInputHandler([=, this](IO* io, Container* self) {
if (io->InputHandler.DragObject(ID(pID.GetName() + id.GetName()), if (io->InputHandler.DragObject(ID(pID.GetName() + id.GetName()),
fvec4(self->FinalPos(), self->GetSize()))) { fvec4(self->FinalPos(), self->GetSize()))) {
if (io->InputHandler.DragReleased) { if (io->InputHandler.DragReleased) {
n->second = !n->second; n->second = !n->second;
} }
} }
}); });
r->SetPos(pos); r->SetPos(pos);
r->SetSize(szs); r->SetSize(szs);
/** Use Add Object as it is faster */ /** Use Add Object as it is faster */
pLayout.AddObject(r); pLayout.AddObject(r);
return n->second; return n->second;
} }
PD_API void UI7::Menu::EndTreeNode() { PD_API void UI7::Menu::EndTreeNode() {
pLayout.InitialCursorOffset.x -= 10.f; pLayout.InitialCursorOffset.x -= 10.f;
pLayout.Cursor.x -= 10.f; pLayout.Cursor.x -= 10.f;
if (pLayout.InitialCursorOffset.x < 0.f) { if (pLayout.InitialCursorOffset.x < 0.f) {
pLayout.InitialCursorOffset.x = 0.f; pLayout.InitialCursorOffset.x = 0.f;
} }
} }
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD
+349 -349
View File
@@ -1,349 +1,349 @@
/* /*
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, bool* pShow) { PD_API Menu* Context::BeginMenu(const ID& id, UI7MenuFlags flags, 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; 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.SetLayer(base_layer); pIO.FDL.SetLayer(base_layer);
pIO.FDL.Merge(pMenus[FinalList[i]]->pLayout.GetDrawList()); pIO.FDL.Merge(pMenus[FinalList[i]]->pLayout.GetDrawList());
base_layer += 100; base_layer += 100;
} }
pCurrentMenus.clear(); pCurrentMenus.clear();
pIO.Update(); pIO.Update();
pIO.FDL.Optimize(); pIO.FDL.Optimize();
} }
PD_API void Context::AboutMenu(bool* show) { PD_API void Context::AboutMenu(bool* show) {
if (auto m = BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) { if (auto m = BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
m->Label("Palladium UI7 " + GetVersion()); m->Label("Palladium UI7 " + GetVersion());
m->Separator(); m->Separator();
m->Label("(c) 2023-2025 René Amthor"); m->Label("(c) 2023-2025 René Amthor");
m->Label("UI7 is licensed under the MIT License."); m->Label("UI7 is licensed under the MIT License.");
m->Label("See LICENSE for more information."); m->Label("See LICENSE for more information.");
static bool show_build; static bool show_build;
m->Checkbox("Show Build Info", show_build); m->Checkbox("Show Build Info", show_build);
if (show_build) { if (show_build) {
m->SeparatorText("Build Info"); m->SeparatorText("Build Info");
m->Label("Full Version -> " + GetVersion(true)); m->Label("Full Version -> " + GetVersion(true));
m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t))); m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t)));
m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(Li::Vertex))); m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(Li::Vertex)));
m->Label("__cplusplus -> " + std::to_string(__cplusplus)); m->Label("__cplusplus -> " + std::to_string(__cplusplus));
m->Label("Compiler -> {}", m->Label("Compiler -> {}",
Strings::GetCompilerVersion()); // + LibInfo::CompiledWith()); Strings::GetCompilerVersion()); // + LibInfo::CompiledWith());
} }
EndMenu(); EndMenu();
} }
} }
PD_API void Context::MetricsMenu(bool* show) { PD_API void Context::MetricsMenu(bool* show) {
if (auto m = BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) { if (auto m = BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
m->Label("Palladium - UI7 " + GetVersion()); m->Label("Palladium - UI7 " + GetVersion());
m->Separator(); m->Separator();
m->Label( m->Label(
std::format("Average {:.3f} ms/f ({:.1f} FPS)", std::format("Average {:.3f} ms/f ({:.1f} FPS)",
((float)pIO.DeltaStats.GetAverage() / 1000.f), ((float)pIO.DeltaStats.GetAverage() / 1000.f),
1000.f / ((float)pIO.DeltaStats.GetAverage() / 1000.f))); 1000.f / ((float)pIO.DeltaStats.GetAverage() / 1000.f)));
m->Label(std::format("NumVertices: {}", pIO.NumVertices)); m->Label(std::format("NumVertices: {}", pIO.NumVertices));
m->Label(std::format("NumIndices: {} -> {} Tris", pIO.NumIndices, m->Label(std::format("NumIndices: {} -> {} Tris", pIO.NumIndices,
pIO.NumIndices / 3)); pIO.NumIndices / 3));
m->Label("Menus: " + std::to_string(pMenus.size())); m->Label("Menus: " + std::to_string(pMenus.size()));
/** Section TimeTrace */ /** Section TimeTrace */
m->SeparatorText("TimeTrace"); m->SeparatorText("TimeTrace");
if (m->BeginTreeNode("Traces (" + if (m->BeginTreeNode("Traces (" +
std::to_string(PD::TT::GetTraceMap().size()) + ")")) { std::to_string(PD::TT::GetTraceMap().size()) + ")")) {
for (auto& it : PD::TT::GetTraceMap()) { for (auto& it : PD::TT::GetTraceMap()) {
if (m->BeginTreeNode(it.second.GetID())) { if (m->BeginTreeNode(it.second.GetID())) {
m->Label("Diff: " + UI7DTF(it.second.GetLastDiff())); m->Label("Diff: " + UI7DTF(it.second.GetLastDiff()));
m->Label("Protocol Len: " + m->Label("Protocol Len: " +
std::to_string(it.second.GetProtocol().GetLen())); std::to_string(it.second.GetProtocol().GetLen()));
m->Label("Average: " + UI7DTF(it.second.GetProtocol().GetAverage())); m->Label("Average: " + UI7DTF(it.second.GetProtocol().GetAverage()));
m->Label("Min: " + UI7DTF(it.second.GetProtocol().GetMin())); m->Label("Min: " + UI7DTF(it.second.GetProtocol().GetMin()));
m->Label("Max: " + UI7DTF(it.second.GetProtocol().GetMax())); m->Label("Max: " + UI7DTF(it.second.GetProtocol().GetMax()));
m->EndTreeNode(); m->EndTreeNode();
} }
} }
m->EndTreeNode(); m->EndTreeNode();
} }
m->SeparatorText("Palladium Info"); m->SeparatorText("Palladium Info");
m->Label("Os Driver: {}", PD::Os::GetDriverName()); m->Label("Os Driver: {}", PD::Os::GetDriverName());
m->Label("Renderer: {}", PD::Gfx::GetDriverName()); m->Label("Renderer: {}", PD::Gfx::GetDriverName());
if (m->BeginTreeNode( if (m->BeginTreeNode(
std::string(std::string("Input: ") + PD::Hid::GetDriverName()))) { std::string(std::string("Input: ") + PD::Hid::GetDriverName()))) {
/* if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasKeyboard) { /* if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasKeyboard) {
m->Label("- Keyboard Supported"); m->Label("- Keyboard Supported");
} }
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasMouse) { if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasMouse) {
m->Label("- Mouse Supported"); m->Label("- Mouse Supported");
} }
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasTouch) { if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasTouch) {
m->Label("- Touch Supported"); m->Label("- Touch Supported");
} }
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::FLags_HasGamepad) { if (pIO.pCtx.Hid()->Flags & PD::HidDriver::FLags_HasGamepad) {
m->Label("- Gamepad Supported"); m->Label("- Gamepad Supported");
}*/ }*/
m->EndTreeNode(); m->EndTreeNode();
} }
/** Section IO */ /** Section IO */
m->SeparatorText("IO"); m->SeparatorText("IO");
if (m->BeginTreeNode("Menus (" + std::to_string(pMenus.size()) + ")")) { if (m->BeginTreeNode("Menus (" + std::to_string(pMenus.size()) + ")")) {
for (auto& it : pMenus) { for (auto& it : pMenus) {
if (m->BeginTreeNode(it.second->pID.GetName())) { if (m->BeginTreeNode(it.second->pID.GetName())) {
m->Label("Name: " + it.second->pID.GetName()); m->Label("Name: " + it.second->pID.GetName());
m->Label(std::format("Pos: {}", it.second->pLayout.GetPosition())); m->Label(std::format("Pos: {}", it.second->pLayout.GetPosition()));
m->Label(std::format("Size: {}", it.second->pLayout.GetSize())); m->Label(std::format("Size: {}", it.second->pLayout.GetSize()));
m->Label(std::format("WorkRect: {}", it.second->pLayout.WorkRect)); m->Label(std::format("WorkRect: {}", it.second->pLayout.WorkRect));
m->Label(std::format("Cursor: {}", it.second->pLayout.Cursor)); m->Label(std::format("Cursor: {}", it.second->pLayout.Cursor));
if (m->BeginTreeNode( if (m->BeginTreeNode(
"ID Objects (" + "ID Objects (" +
std::to_string(it.second->pLayout.IDObjects.size()) + ")")) { std::to_string(it.second->pLayout.IDObjects.size()) + ")")) {
for (auto& jt : it.second->pLayout.IDObjects) { for (auto& jt : it.second->pLayout.IDObjects) {
m->Label(std::format("{:08X}", jt->GetID())); m->Label(std::format("{:08X}", jt->GetID()));
} }
m->EndTreeNode(); m->EndTreeNode();
} }
m->EndTreeNode(); m->EndTreeNode();
} }
} }
m->EndTreeNode(); m->EndTreeNode();
} }
if (m->BeginTreeNode("Active Menus (" + if (m->BeginTreeNode("Active Menus (" +
std::to_string(pCurrentMenus.size()) + ")")) { std::to_string(pCurrentMenus.size()) + ")")) {
for (auto& it : pCurrentMenus) { for (auto& it : pCurrentMenus) {
if (m->BeginTreeNode(pMenus[it]->pID.GetName())) { if (m->BeginTreeNode(pMenus[it]->pID.GetName())) {
m->Label("Name: " + pMenus[it]->pID.GetName()); m->Label("Name: " + pMenus[it]->pID.GetName());
m->Label(std::format("Pos: {}", pMenus[it]->pLayout.GetPosition())); m->Label(std::format("Pos: {}", pMenus[it]->pLayout.GetPosition()));
m->Label(std::format("Size: {}", pMenus[it]->pLayout.GetSize())); m->Label(std::format("Size: {}", pMenus[it]->pLayout.GetSize()));
m->Label(std::format("WorkRect: {}", pMenus[it]->pLayout.WorkRect)); m->Label(std::format("WorkRect: {}", pMenus[it]->pLayout.WorkRect));
m->Label(std::format("Cursor: {}", pMenus[it]->pLayout.Cursor)); m->Label(std::format("Cursor: {}", pMenus[it]->pLayout.Cursor));
if (m->BeginTreeNode( if (m->BeginTreeNode(
"ID Objects (" + "ID Objects (" +
std::to_string(pMenus[it]->pLayout.IDObjects.size()) + ")")) { std::to_string(pMenus[it]->pLayout.IDObjects.size()) + ")")) {
for (auto& jt : pMenus[it]->pLayout.IDObjects) { for (auto& jt : pMenus[it]->pLayout.IDObjects) {
m->Label(std::format("{:08X}", jt->GetID())); m->Label(std::format("{:08X}", jt->GetID()));
} }
m->EndTreeNode(); m->EndTreeNode();
} }
m->EndTreeNode(); m->EndTreeNode();
} }
} }
m->EndTreeNode(); m->EndTreeNode();
} }
// Well this are Li Drawlists now and they do not count their stats (yet) // Well this are Li Drawlists now and they do not count their stats (yet)
/*if (m->BeginTreeNode("DrawLists (" + /*if (m->BeginTreeNode("DrawLists (" +
std::to_string(pIO.DrawListRegestry.size()) + ")")) { std::to_string(pIO.DrawListRegestry.size()) + ")")) {
for (auto &it : pIO.DrawListRegestry) { for (auto &it : pIO.DrawListRegestry) {
if (m->BeginTreeNode(it.First.GetName())) { if (m->BeginTreeNode(it.First.GetName())) {
m->Label("Vertices: " + std::to_string(it.Second->NumVertices)); m->Label("Vertices: " + std::to_string(it.Second->NumVertices));
m->Label("Indices: " + std::to_string(it.Second->NumIndices)); m->Label("Indices: " + std::to_string(it.Second->NumIndices));
m->Label("Base Layer: " + std::to_string(it.Second->Base)); m->Label("Base Layer: " + std::to_string(it.Second->Base));
m->EndTreeNode(); m->EndTreeNode();
} }
} }
m->EndTreeNode(); m->EndTreeNode();
}*/ }*/
m->Label("io->Time: " + Strings::FormatMillis(pIO.Time.Get())); m->Label("io->Time: " + Strings::FormatMillis(pIO.Time.Get()));
m->Label(std::format("Delta: {:.3f}", pIO.Delta)); m->Label(std::format("Delta: {:.3f}", pIO.Delta));
m->Label(std::format("Framerate: {:.2f}", pIO.Framerate)); m->Label(std::format("Framerate: {:.2f}", pIO.Framerate));
m->Label(std::format("Focused Menu: {:08X}", pIO.InputHandler.FocusedMenu)); m->Label(std::format("Focused Menu: {:08X}", pIO.InputHandler.FocusedMenu));
m->Label( m->Label(
std::format("Dragged Object: {:08X}", pIO.InputHandler.DraggedObject)); std::format("Dragged Object: {:08X}", pIO.InputHandler.DraggedObject));
m->Label(std::format("DragTime: {:.2f}s", m->Label(std::format("DragTime: {:.2f}s",
pIO.InputHandler.DragTime.GetSeconds())); pIO.InputHandler.DragTime.GetSeconds()));
m->Label( m->Label(
std::format("DragDestination: [{}]", pIO.InputHandler.DragDestination)); std::format("DragDestination: [{}]", pIO.InputHandler.DragDestination));
m->Label(std::format("DragSource: [{}]", pIO.InputHandler.DragSourcePos)); m->Label(std::format("DragSource: [{}]", pIO.InputHandler.DragSourcePos));
m->Label(std::format("DragPos: [{}]", pIO.InputHandler.DragPosition)); m->Label(std::format("DragPos: [{}]", pIO.InputHandler.DragPosition));
m->Label( m->Label(
std::format("DragLastPos: [{}]", pIO.InputHandler.DragLastPosition)); std::format("DragLastPos: [{}]", pIO.InputHandler.DragLastPosition));
EndMenu(); EndMenu();
} }
} }
PD_API void UI7::Context::StyleEditor(bool* show) { PD_API void UI7::Context::StyleEditor(bool* show) {
if (auto m = BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) { if (auto m = BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) {
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor"); m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
m->Separator(); m->Separator();
m->DragData("MenuPadding", (float*)&pIO.MenuPadding, 2, 0.f, 100.f); m->DragData("MenuPadding", (float*)&pIO.MenuPadding, 2, 0.f, 100.f);
m->DragData("FramePadding", (float*)&pIO.FramePadding, 2, 0.f, 100.f); m->DragData("FramePadding", (float*)&pIO.FramePadding, 2, 0.f, 100.f);
m->DragData("ItemSpace", (float*)&pIO.ItemSpace, 2, 0.f, 100.f); m->DragData("ItemSpace", (float*)&pIO.ItemSpace, 2, 0.f, 100.f);
m->DragData("MinSliderSize", (float*)&pIO.MinSliderDragSize, 2, 1.f, 100.f); m->DragData("MinSliderSize", (float*)&pIO.MinSliderDragSize, 2, 1.f, 100.f);
m->DragData("OverScroll Modifier", &pIO.OverScrollMod, 1, 0.01f, m->DragData("OverScroll Modifier", &pIO.OverScrollMod, 1, 0.01f,
std::numeric_limits<float>::max(), 0.01f, 2); std::numeric_limits<float>::max(), 0.01f, 2);
m->Checkbox("Menu Border", pIO.ShowMenuBorder); m->Checkbox("Menu Border", pIO.ShowMenuBorder);
m->Checkbox("Frame Border", pIO.ShowFrameBorder); m->Checkbox("Frame Border", pIO.ShowFrameBorder);
m->SeparatorText("Theme"); m->SeparatorText("Theme");
if (m->Button("Dark")) { if (m->Button("Dark")) {
UI7::Theme::Default(pIO.Theme); UI7::Theme::Default(pIO.Theme);
} }
m->SameLine(); m->SameLine();
if (m->Button("Flashbang")) { if (m->Button("Flashbang")) {
UI7::Theme::Flashbang(pIO.Theme); UI7::Theme::Flashbang(pIO.Theme);
} }
/// Small trick to print without prefix /// Small trick to print without prefix
#define ts(x) m->ColorEdit(std::string(#x).substr(9), pIO.Theme.GetRef(x)); #define ts(x) m->ColorEdit(std::string(#x).substr(9), pIO.Theme.GetRef(x));
#define ts2(x) \ #define ts2(x) \
m->DragData(std::string(#x).substr(9), (u8*)&pIO.Theme.GetRef(x), 4, (u8)0, \ m->DragData(std::string(#x).substr(9), (u8*)&pIO.Theme.GetRef(x), 4, (u8)0, \
(u8)255); (u8)255);
ts(UI7Color_Background); ts(UI7Color_Background);
ts(UI7Color_Border); ts(UI7Color_Border);
ts(UI7Color_Button); ts(UI7Color_Button);
ts(UI7Color_ButtonDead); ts(UI7Color_ButtonDead);
ts(UI7Color_ButtonActive); ts(UI7Color_ButtonActive);
ts(UI7Color_ButtonHovered); ts(UI7Color_ButtonHovered);
ts(UI7Color_Text); ts(UI7Color_Text);
ts(UI7Color_TextDead); ts(UI7Color_TextDead);
ts(UI7Color_Header); ts(UI7Color_Header);
ts(UI7Color_HeaderDead); ts(UI7Color_HeaderDead);
ts(UI7Color_Selector); ts(UI7Color_Selector);
ts(UI7Color_Checkmark); ts(UI7Color_Checkmark);
ts(UI7Color_FrameBackground); ts(UI7Color_FrameBackground);
ts(UI7Color_FrameBackgroundHovered); ts(UI7Color_FrameBackgroundHovered);
ts(UI7Color_Progressbar); ts(UI7Color_Progressbar);
ts(UI7Color_ListEven); ts(UI7Color_ListEven);
ts(UI7Color_ListOdd); ts(UI7Color_ListOdd);
this->EndMenu(); this->EndMenu();
} }
} }
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD
-55
View File
@@ -1,55 +0,0 @@
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()