Compare commits
85
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39e91b588f
|
||
|
|
7bb1406365
|
||
|
|
438584e4f2
|
||
|
|
acc4fd11eb
|
||
|
|
72bb76dcbc
|
||
|
|
272b66f7f0
|
||
|
|
6637a3692b
|
||
|
|
feeb3b1ba8
|
||
|
|
5a56bf3986
|
||
|
|
1dfc538ae3
|
||
|
|
36c05a9138
|
||
|
|
a8d841c63c
|
||
|
|
8983371806
|
||
|
|
2b4c4bacd6
|
||
|
|
859a4c96ae
|
||
|
|
0e0d576954
|
||
|
|
4a29cb4330
|
||
|
|
e0b86ee3f6
|
||
|
|
b121001db7
|
||
|
|
2059772ad1
|
||
|
|
81aa08485b
|
||
|
|
ecadf0a44c
|
||
|
|
6dfc04378a
|
||
|
|
e3ffcbb596
|
||
|
|
469cd535fd
|
||
|
|
b594e09bdb
|
||
|
|
41b25e4476
|
||
|
|
25607b865c
|
||
|
|
1bf103c894
|
||
|
|
11a480136b
|
||
|
|
e6fcfe0650
|
||
|
|
a8a80cfa47
|
||
|
|
b7f1037b18
|
||
|
|
de51a35734
|
||
|
|
13152a317a
|
||
|
|
5dd5907c43
|
||
|
|
673e53935a
|
||
|
|
dda8258064
|
||
|
|
0c55291f9c
|
||
|
|
c5f6f0cb33
|
||
|
|
391eea100a
|
||
|
|
d70a9970e9
|
||
|
|
0f044538cc
|
||
|
|
546940aa77
|
||
|
|
dc365bc658
|
||
|
|
1ccc7075fa
|
||
|
|
b069f10841
|
||
|
|
bf3eef8d28
|
||
|
|
6298d4c816
|
||
|
|
212ba0c617
|
||
|
|
b4a7260cf2
|
||
|
|
5cf9ff0109
|
||
|
|
69b5e74d91
|
||
|
|
9b69d78118
|
||
|
|
e573523511
|
||
|
|
1317599475
|
||
|
|
1876ab9365
|
||
|
|
ce2dc94121
|
||
|
|
bef8ced350
|
||
|
|
dd038883a0
|
||
|
|
7ad2b8b0c5
|
||
|
|
63fb09189d
|
||
|
|
306ddfed53
|
||
|
|
c2b0fa01db
|
||
|
|
594cf5cca4
|
||
|
|
191bca26d5
|
||
|
|
85a92f8371
|
||
|
|
f3d326c237
|
||
|
|
fda39b3d36
|
||
|
|
8e09025c40
|
||
|
|
2a57b7c08c
|
||
|
|
9d0565f60c
|
||
|
|
4691d158a9
|
||
|
|
57c376a822
|
||
|
|
d72c447875
|
||
|
|
518015afb1
|
||
|
|
e6a60e90d1
|
||
|
|
9d63a17700
|
||
|
|
fd498c5ea2
|
||
|
|
0cc886315d
|
||
|
|
1b9876f64b
|
||
|
|
cd904ea544
|
||
|
|
e43cb41377
|
||
|
|
b2d3d203a2
|
||
|
|
f1a63fe383
|
@@ -29,7 +29,6 @@ class GfxCitro3D : public GfxDriverBase<GfxCitro3DConfig> {
|
||||
TextureFilter filter = TextureFilter::Linear) override;
|
||||
void DeleteTexture(const Li::Texture& tex) override;
|
||||
void UploadPools() override;
|
||||
void ClipRect() override;
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
|
||||
@@ -29,7 +29,6 @@ class GfxDirectX9 : public GfxDriverBase<GfxDirectX9Config> {
|
||||
TextureFilter filter = TextureFilter::Linear) override;
|
||||
void DeleteTexture(const Li::Texture& tex) override;
|
||||
void UploadPools() override;
|
||||
void ClipRect() override;
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
|
||||
@@ -28,7 +28,6 @@ class GfxOpenGL2 : public GfxDriverBase<GfxOpenGL2Config> {
|
||||
TextureFilter filter = TextureFilter::Linear) override;
|
||||
void DeleteTexture(const Li::Texture& tex) override;
|
||||
void UploadPools() override;
|
||||
void ClipRect() override;
|
||||
|
||||
private:
|
||||
void pSetupShaderAttribs(u32 shader);
|
||||
|
||||
@@ -28,7 +28,6 @@ class GfxOpenGL3 : public GfxDriverBase<GfxOpenGL3Config> {
|
||||
TextureFilter filter = TextureFilter::Linear) override;
|
||||
void DeleteTexture(const Li::Texture& tex) override;
|
||||
void UploadPools() override;
|
||||
void ClipRect() override;
|
||||
|
||||
private:
|
||||
u32 pShader = 0;
|
||||
|
||||
@@ -141,9 +141,6 @@ void GfxCitro3D::SysInit() {
|
||||
PDLOG("GfxCitro3D::SysInit();");
|
||||
impl = new Impl();
|
||||
Flags |= PDGfxBackendFlags_FlipUV_Y;
|
||||
Flags |= PDGfxBackendFlags_HasClipRect;
|
||||
Flags |= PDGfxBackendFlags_ReqPow2;
|
||||
Flags |= PDGfxBackendFlags_ApproxSDF;
|
||||
impl->pShaderRaw = Pica::AssembleCode(LIShaderCTR);
|
||||
impl->pCode = DVLB_ParseFile((uint32_t*)impl->pShaderRaw.data(),
|
||||
impl->pShaderRaw.size());
|
||||
@@ -267,14 +264,6 @@ void GfxCitro3D::UploadPools() {
|
||||
BufInfo_Init(buf);
|
||||
BufInfo_Add(buf, GetVertexBufPtr(0), sizeof(Li::Vertex), 3, 0x210);
|
||||
}
|
||||
|
||||
void GfxCitro3D::ClipRect() {
|
||||
// This is so cursed but it works
|
||||
C3D_SetScissor(CurrentHasClip ? GPU_SCISSOR_NORMAL : GPU_SCISSOR_DISABLE,
|
||||
ViewPort.y - CurrentClip.w - CurrentClip.y,
|
||||
ViewPort.x - CurrentClip.z - CurrentClip.x,
|
||||
ViewPort.y - CurrentClip.y, ViewPort.x - CurrentClip.x);
|
||||
}
|
||||
} // namespace PD
|
||||
#else
|
||||
namespace PD {
|
||||
@@ -294,6 +283,5 @@ Li::Texture GfxCitro3D::LoadTexture(const std::vector<PD::u8>& pixels, int w,
|
||||
}
|
||||
void GfxCitro3D::DeleteTexture(const Li::Texture& tex) {}
|
||||
void GfxCitro3D::UploadPools() {}
|
||||
void GfxCitro3D::ClipRect() {}
|
||||
} // namespace PD
|
||||
#endif
|
||||
@@ -112,7 +112,6 @@ void GfxDirectX9::SysInit() {
|
||||
}
|
||||
if (psBlob) psBlob->Release();
|
||||
if (errBlob) errBlob->Release();
|
||||
Flags |= PDGfxBackendFlags_HasClipRect;
|
||||
} else {
|
||||
PDERR(
|
||||
"GfxDirectX9::SysInit Error: pDevice is not set!\nYOu need to include "
|
||||
@@ -286,21 +285,6 @@ void GfxDirectX9::UploadPools() {
|
||||
memcpy(iptr, GetIndexBufPtr(0), GetIndexPoolSize() * sizeof(u16));
|
||||
impl->IBO->Unlock();
|
||||
}
|
||||
|
||||
void GfxDirectX9::ClipRect() {
|
||||
if (CurrentHasClip) {
|
||||
RECT r;
|
||||
r.left = CurrentClip.x;
|
||||
r.top = CurrentClip.y;
|
||||
r.right = CurrentClip.x + CurrentClip.z;
|
||||
r.bottom = CurrentClip.y + CurrentClip.w;
|
||||
|
||||
impl->Device->SetScissorRect(&r);
|
||||
impl->Device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
} else {
|
||||
impl->Device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
} // namespace PD
|
||||
#else
|
||||
namespace PD {
|
||||
@@ -320,6 +304,5 @@ Li::Texture GfxDirectX9::LoadTexture(const std::vector<PD::u8>& pixels, int w,
|
||||
}
|
||||
void GfxDirectX9::DeleteTexture(const Li::Texture& tex) {}
|
||||
void GfxDirectX9::UploadPools() {}
|
||||
void GfxDirectX9::ClipRect() {}
|
||||
} // namespace PD
|
||||
#endif
|
||||
@@ -73,7 +73,6 @@ void GfxOpenGL2::pSetupShaderAttribs(u32 shader) {
|
||||
}
|
||||
|
||||
void GfxOpenGL2::SysInit() {
|
||||
Flags |= PDGfxBackendFlags_HasClipRect;
|
||||
pShader = CreateShaderProgram(pVertCode, pFragCode);
|
||||
glUseProgram(pShader);
|
||||
glGenBuffers(1, &VBO);
|
||||
@@ -184,16 +183,6 @@ void GfxOpenGL2::UploadPools() {
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, GetIndexPoolSize() * sizeof(u16),
|
||||
GetIndexBufPtr(0), GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
void GfxOpenGL2::ClipRect() {
|
||||
if (CurrentHasClip) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(CurrentClip.x, ViewPort.y - (CurrentClip.y + CurrentClip.w),
|
||||
CurrentClip.z, CurrentClip.w);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
} // namespace PD
|
||||
#else
|
||||
namespace PD {
|
||||
@@ -214,6 +203,5 @@ Li::Texture GfxOpenGL2::LoadTexture(const std::vector<PD::u8>& pixels, int w,
|
||||
void GfxOpenGL2::DeleteTexture(const Li::Texture& tex) {}
|
||||
void GfxOpenGL2::pSetupShaderAttribs(u32 shader) {}
|
||||
void GfxOpenGL2::UploadPools() {}
|
||||
void GfxOpenGL2::ClipRect() {}
|
||||
} // namespace PD
|
||||
#endif
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
namespace PD {
|
||||
void GfxOpenGL3::SysInit() {
|
||||
Flags |= PDGfxBackendFlags_HasClipRect;
|
||||
std::string vcode = SpirvHelper::SPV2GLSL(
|
||||
std::vector<unsigned int>(
|
||||
Shaders::VertexShader,
|
||||
@@ -160,16 +159,6 @@ void GfxOpenGL3::UploadPools() {
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void GfxOpenGL3::ClipRect() {
|
||||
if (CurrentHasClip) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(CurrentClip.x, ViewPort.y - (CurrentClip.y + CurrentClip.w),
|
||||
CurrentClip.z, CurrentClip.w);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
} // namespace PD
|
||||
#else
|
||||
namespace PD {
|
||||
@@ -189,6 +178,5 @@ Li::Texture GfxOpenGL3::LoadTexture(const std::vector<PD::u8>& pixels, int w,
|
||||
}
|
||||
void GfxOpenGL3::DeleteTexture(const Li::Texture& tex) {}
|
||||
void GfxOpenGL3::UploadPools() {}
|
||||
void GfxOpenGL3::ClipRect() {}
|
||||
} // namespace PD
|
||||
#endif
|
||||
@@ -9,11 +9,8 @@
|
||||
using PDGfxBackendFlags = PD::u32;
|
||||
enum PDGfxBackendFlags_ {
|
||||
PDGfxBackendFlags_None = 0,
|
||||
PDGfxBackendFlags_FlipUV_Y = 1 << 0, // Essential for font loading
|
||||
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
|
||||
PDGfxBackendFlags_FlipUV_Y = 1 << 0, // Essential for font loading
|
||||
PDGfxBackendFlags_WindingCW = 1 << 0, // Use CW instead of CCW winding
|
||||
};
|
||||
|
||||
namespace PD {
|
||||
@@ -68,7 +65,6 @@ class PD_API GfxDriver : public DriverInterface {
|
||||
virtual void SysReset() {}
|
||||
virtual void Submit(size_t count, size_t start) {}
|
||||
virtual void UploadPools() {} // not every driver requires it
|
||||
virtual void ClipRect() {}
|
||||
void RegisterTexture(const Li::Texture& tex);
|
||||
void UnregisterTexture(const Li::Texture& tex);
|
||||
|
||||
@@ -84,8 +80,6 @@ class PD_API GfxDriver : public DriverInterface {
|
||||
// State Variables oder so
|
||||
TextureID CurrentTex = 0;
|
||||
bool CurrentTexIsSDF = false;
|
||||
bool CurrentHasClip = false;
|
||||
fvec4 CurrentClip = 0;
|
||||
Mat4 Projection;
|
||||
ivec2 ViewPort;
|
||||
std::unordered_map<TextureID, Li::Texture> pTextureRegestry;
|
||||
@@ -142,7 +136,7 @@ class GfxDriverBase : public GfxDriver {
|
||||
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),
|
||||
std::memcpy(pVtxPool.begin() + current_vtx,
|
||||
vpool.begin() + cmd.FirstVertex,
|
||||
cmd.VertexCount * sizeof(Li::Vertex));
|
||||
}
|
||||
@@ -162,19 +156,14 @@ class GfxDriverBase : public GfxDriver {
|
||||
while (index < commands.size()) {
|
||||
CurrentTex = commands[index].Tex;
|
||||
CurrentTexIsSDF = commands[index].SDF;
|
||||
CurrentHasClip = commands[index].ClipRectUsed;
|
||||
CurrentClip = commands[index].ClipRect;
|
||||
if (!CurrentTex) {
|
||||
CurrentTex = pWhite.GetID();
|
||||
}
|
||||
size_t num_indices = 0;
|
||||
ClipRect();
|
||||
while (index < commands.size() &&
|
||||
CurrentTexIsSDF == commands[index].SDF &&
|
||||
(CurrentTex == commands[index].Tex ||
|
||||
(CurrentTex == pWhite.GetID() && commands[index].Tex == 0)) &&
|
||||
CurrentClip == commands[index].ClipRect &&
|
||||
CurrentHasClip == commands[index].ClipRectUsed) {
|
||||
(CurrentTex == pWhite.GetID() && commands[index].Tex == 0))) {
|
||||
num_indices += commands[index].IndexCount;
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,6 @@ class Command {
|
||||
// Todo: implement
|
||||
size_t VertexCountMax = 0;
|
||||
size_t IndexCountMax = 0;
|
||||
// ClipRect
|
||||
PD::fvec4 ClipRect;
|
||||
bool ClipRectUsed = false;
|
||||
};
|
||||
} // namespace Li
|
||||
} // namespace PD
|
||||
@@ -128,18 +128,13 @@ class PD_API Drawlist {
|
||||
void PrimTriangle(Command& cmd, const fvec2& a, const fvec2& b,
|
||||
const fvec2& c, const PD::Color& color);
|
||||
|
||||
void PushClipRect(const fvec4& r) { pClipRects.push_back(r); }
|
||||
void PopClipRect() {
|
||||
if (!pClipRects.empty()) pClipRects.pop_back();
|
||||
}
|
||||
bool HasClipRect() { return !pClipRects.empty(); }
|
||||
|
||||
private:
|
||||
Texture pCurrentTexture;
|
||||
int pCurrentLayer = 0;
|
||||
Pool<Command> pCommands;
|
||||
Pool<fvec2> pPath;
|
||||
std::vector<fvec4> pClipRects;
|
||||
Pool<Vertex> pVertices;
|
||||
Pool<u16> pIndices;
|
||||
Font* pFont = nullptr;
|
||||
float pFontScale = 1.f;
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@ class PD_API Container {
|
||||
*/
|
||||
Container(const fvec4& box)
|
||||
: pos(fvec2(box.x, box.y)), size(fvec2(box.z - box.x, box.w - box.y)) {}
|
||||
virtual ~Container() = default;
|
||||
~Container() = default;
|
||||
|
||||
/**
|
||||
* Init Function Required by every Object that uses
|
||||
|
||||
@@ -87,8 +87,6 @@ enum UI7LytAdd_ {
|
||||
UI7LytAdd_NoCursorUpdate = 1 << 0, ///< Add without cursor alignment
|
||||
UI7LytAdd_NoScrollHandle = 1 << 1, ///< Skip HandleScrolling
|
||||
UI7LytAdd_Front = 1 << 2, ///< Add in front of the list
|
||||
UI7LytAdd_NoGlobalClipping = 1 << 3, ///< Dont use global Layout clip rect
|
||||
UI7LytAdd_NoClipTitlebar = 1 << 4, ///< Dont clip content behind the titlebar
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,8 +56,6 @@ void Command::Reset() {
|
||||
VertexCount = 0;
|
||||
VertexCountMax = 0;
|
||||
IndexCountMax = 0;
|
||||
ClipRect = 0.f;
|
||||
ClipRectUsed = false;
|
||||
}
|
||||
|
||||
Command& Command::Add(const Vertex& vtx) {
|
||||
|
||||
@@ -43,7 +43,6 @@ PD_API void Drawlist::Clear() {
|
||||
pPath.ResetFast();
|
||||
pCommands.NoReset();
|
||||
pCurrentLayer = 0;
|
||||
pClipRects.clear();
|
||||
}
|
||||
|
||||
/** Command Allocation */
|
||||
@@ -52,10 +51,6 @@ PD_API Command& Drawlist::NewCommand() {
|
||||
cmd->Reset();
|
||||
cmd->Layer = pCurrentLayer;
|
||||
cmd->Tex = pCurrentTexture.GetID();
|
||||
if (HasClipRect()) {
|
||||
cmd->ClipRectUsed = HasClipRect();
|
||||
cmd->ClipRect = pClipRects.back();
|
||||
}
|
||||
return *cmd;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,13 +44,13 @@ PD_API void Container::HandleInternalInput() {
|
||||
/** Internal function */
|
||||
PD_API void Container::PreDraw() {
|
||||
if (pCLipRectUsed) {
|
||||
list->PushClipRect(pClipRect);
|
||||
// list->PushClipRect(pClipRect);
|
||||
}
|
||||
}
|
||||
/** Internal function */
|
||||
PD_API void Container::PostDraw() {
|
||||
if (pCLipRectUsed) {
|
||||
list->PopClipRect();
|
||||
// list->PopClipRect();
|
||||
}
|
||||
}
|
||||
} // namespace UI7
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ SOFTWARE.
|
||||
|
||||
namespace PD {
|
||||
|
||||
PD_API UI7::IO::IO() : CurrentViewPort("", 0), DeltaStats(60) {
|
||||
PD_API UI7::IO::IO() : DeltaStats(60), CurrentViewPort("", 0) {
|
||||
/** Probably not the best solution i guess */
|
||||
// CurrentViewPort =
|
||||
// ViewPort::New("Default", ivec4(ivec2(0, 0), pCtx.Gfx()->ViewPort));
|
||||
|
||||
+4
-14
@@ -77,10 +77,6 @@ PD_API void Layout::AddObject(Container* obj) {
|
||||
obj->Update();
|
||||
CursorMove(obj->GetSize());
|
||||
obj->HandleScrolling(ScrollOffset, WorkRect);
|
||||
if (Flags & UI7LayoutFlags_UseClipRect) {
|
||||
obj->SetClipRect(
|
||||
fvec4(Pos.x, Pos.y + WorkRect.y, Size.x, Size.y - WorkRect.y));
|
||||
}
|
||||
Objects.push_back(obj);
|
||||
}
|
||||
|
||||
@@ -97,15 +93,6 @@ PD_API void Layout::AddObjectEx(Container* obj, u32 flags) {
|
||||
if (!(flags & UI7LytAdd_NoScrollHandle)) {
|
||||
obj->HandleScrolling(ScrollOffset, WorkRect);
|
||||
}
|
||||
if (Flags & UI7LayoutFlags_UseClipRect &&
|
||||
!(flags & UI7LytAdd_NoGlobalClipping)) {
|
||||
if (flags & UI7LytAdd_NoClipTitlebar) {
|
||||
obj->SetClipRect(fvec4(Pos.x, Pos.y, Size.x, Size.y));
|
||||
} else {
|
||||
obj->SetClipRect(
|
||||
fvec4(Pos.x, Pos.y + WorkRect.y, Size.x, Size.y - WorkRect.y));
|
||||
}
|
||||
}
|
||||
if (flags & UI7LytAdd_Front) {
|
||||
Objects.push_front(obj);
|
||||
} else {
|
||||
@@ -184,6 +171,9 @@ PD_API void Layout::Update() {
|
||||
it->SetPos(it->GetPos() + Pos);
|
||||
it->HandleInput();
|
||||
it->UnlockInput();
|
||||
if (Flags & UI7LayoutFlags_UseClipRect) {
|
||||
it->SetClipRect(fvec4(Pos, Size));
|
||||
}
|
||||
it->PreDraw();
|
||||
it->Draw();
|
||||
it->PostDraw();
|
||||
@@ -211,7 +201,7 @@ PD_API void Layout::Label(const std::string& label) {
|
||||
// Layout API
|
||||
auto r = IO.LabelPool.Allocate();
|
||||
*r = UI7::Label(label, IO);
|
||||
// r->SetClipRect(fvec4(GetPosition(), GetSize()));
|
||||
r->SetClipRect(fvec4(GetPosition(), GetPosition() + GetSize()));
|
||||
AddObject(r);
|
||||
}
|
||||
|
||||
|
||||
Executable → Regular
+400
-404
@@ -1,404 +1,400 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2026 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <pd/ui7/containers.hpp>
|
||||
#include <pd/ui7/menu.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
Menu::Menu(const ID& id, IO& io) : pLayout(id, io), pIO(io), pID(id) {
|
||||
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
|
||||
pLayout.WorkRect.y += TitleBarHeight;
|
||||
pLayout.Flags |= UI7LayoutFlags_UseClipRect;
|
||||
pLayout.CursorInit();
|
||||
}
|
||||
|
||||
PD_API void Menu::Label(const std::string& label) {
|
||||
// Layout API
|
||||
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 =
|
||||
Strings::FastHash("btn" + label + std::to_string(pLayout.Objects.size()));
|
||||
Container* r = pLayout.FindObject(id);
|
||||
if (!r) {
|
||||
r = new UI7::Button(label, pIO);
|
||||
r->SetID(id);
|
||||
}
|
||||
pLayout.AddObject(r);
|
||||
if (!r->Skippable()) {
|
||||
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()));
|
||||
Container* r = pLayout.FindObject(id);
|
||||
if (!r) {
|
||||
r = new UI7::Checkbox(label, v, pIO);
|
||||
r->SetID(id);
|
||||
}
|
||||
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);
|
||||
pLayout.AddObject(r);
|
||||
}
|
||||
|
||||
PD_API void Menu::ColorEdit(const std::string& label, u32& clr) {
|
||||
u32 id = Strings::FastHash("drd" + label);
|
||||
Container* r = pLayout.FindObject(id);
|
||||
if (!r) {
|
||||
r = new UI7::ColorEdit(label, &clr, pIO);
|
||||
r->SetID(id);
|
||||
}
|
||||
pLayout.AddObject(r);
|
||||
}
|
||||
|
||||
PD_API void Menu::Separator() {
|
||||
// Dynamic Objects are very simple...
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj(
|
||||
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
|
||||
l->DrawRectFilled(self->FinalPos(), self->GetSize(),
|
||||
pIO.Theme.Get(UI7Color_TextDead));
|
||||
});
|
||||
// Set size before pushing (cause Cursor Move will require it)
|
||||
r->SetSize(fvec2(
|
||||
pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x,
|
||||
1));
|
||||
pLayout.AddObject(r);
|
||||
}
|
||||
|
||||
PD_API void Menu::SeparatorText(const std::string& label) {
|
||||
// Also note to use [=] instead of [&] to not undefined access label
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
|
||||
UI7::Container* self) {
|
||||
l->SetFont(self->GetFont());
|
||||
fvec2 size = self->GetSize();
|
||||
fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale);
|
||||
fvec2 pos = self->FinalPos();
|
||||
auto align = pLayout.GetAlignment();
|
||||
vec2 rpos = pLayout.AlignPosition(pos, tdim,
|
||||
fvec4(pLayout.Pos, pLayout.Size), align);
|
||||
if (!(align & UI7Align_Left)) {
|
||||
l->DrawRectFilled(fvec2(rpos.x + io->FramePadding.x, tdim.y * 0.5),
|
||||
fvec2(pos.x - rpos.x - io->MenuPadding.x, 1),
|
||||
io->Theme.Get(UI7Color_TextDead));
|
||||
}
|
||||
if (!(align & UI7Align_Right)) {
|
||||
l->DrawRectFilled(pos + fvec2(tdim.x + io->FramePadding.x, tdim.y * 0.5),
|
||||
fvec2(size.x - tdim.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));
|
||||
});
|
||||
// Set size before pushing (cause Cursor Move will require it)
|
||||
r->SetSize(fvec2(
|
||||
pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x,
|
||||
pIO.Font->PixelHeight * pIO.FontScale));
|
||||
pLayout.AddObject(r);
|
||||
}
|
||||
PD_API void Menu::HandleFocus() {
|
||||
// Check if menu can be focused for Selective Menu Input API
|
||||
vec4 newarea = fvec4(pLayout.Pos, pLayout.Size);
|
||||
if (!pIsOpen) {
|
||||
newarea = fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight));
|
||||
}
|
||||
if ((PD::Hid::IsEvent(Hid::Event::Down, Hid::Gamepad::Touch) ||
|
||||
PD::Hid::IsEvent(Hid::Event::Down, Hid::Keyboard::MouseLeft)) &&
|
||||
Li::Math::InBounds(PD::Hid::MousePos(), newarea) &&
|
||||
!Li::Math::InBounds(PD::Hid::MousePos(),
|
||||
pIO.InputHandler.FocusedMenuRect)) {
|
||||
pIO.InputHandler.FocusedMenu = pID;
|
||||
}
|
||||
if (pIO.InputHandler.FocusedMenu == pID) {
|
||||
pIO.InputHandler.FocusedMenuRect = newarea;
|
||||
}
|
||||
}
|
||||
|
||||
PD_API void Menu::HandleTitlebarActions() {
|
||||
// Collapse
|
||||
if (!(Flags & UI7MenuFlags_NoCollapse)) {
|
||||
vec2 cpos = pLayout.Pos + pIO.FramePadding;
|
||||
// clr_collapse_tri = UI7Color_FrameBackground;
|
||||
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clbse"),
|
||||
fvec4(cpos, fvec2(18, TitleBarHeight)))) {
|
||||
if (pIO.InputHandler.DragReleased) {
|
||||
pIsOpen = !pIsOpen;
|
||||
}
|
||||
// clr_collapse_tri = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
// Close Logic
|
||||
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown != nullptr) {
|
||||
fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2;
|
||||
fvec2 cpos =
|
||||
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x,
|
||||
pLayout.Pos.y + pIO.FramePadding.y);
|
||||
|
||||
// clr_close_btn = UI7Color_FrameBackground;
|
||||
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clse"),
|
||||
fvec4(cpos, size))) {
|
||||
if (pIO.InputHandler.DragReleased) {
|
||||
*pIsShown = !(*pIsShown);
|
||||
}
|
||||
// clr_close_btn = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
// Resize logic
|
||||
if (!(Flags & UI7MenuFlags_NoResize)) {
|
||||
vec2 cpos = pLayout.Pos + pLayout.Size - fvec2(20);
|
||||
|
||||
// clr_close_btn = UI7Color_FrameBackground;
|
||||
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "rszs"),
|
||||
fvec4(cpos, fvec2(20)))) {
|
||||
fvec2 szs = pLayout.Size + (pIO.InputHandler.DragPosition -
|
||||
pIO.InputHandler.DragLastPosition);
|
||||
if (szs.x < 30) szs.x = 30;
|
||||
if (szs.y < 30) szs.y = 30;
|
||||
pLayout.Size = szs;
|
||||
// clr_close_btn = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
// Menu Movement
|
||||
if (!(Flags & UI7MenuFlags_NoMove)) {
|
||||
if (pIO.InputHandler.DragObject(
|
||||
pID.GetName() + "tmv",
|
||||
fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)))) {
|
||||
if (pIO.InputHandler.DragDoubleRelease) {
|
||||
pIsOpen = !pIsOpen;
|
||||
}
|
||||
pLayout.Pos = pLayout.Pos + (pIO.InputHandler.DragPosition -
|
||||
pIO.InputHandler.DragLastPosition);
|
||||
// Keep Window In Viewport
|
||||
// Maybe i need to add some operators to vec
|
||||
pLayout.Pos.x = std::clamp<float>(pLayout.Pos.x, -pLayout.Size.x + 10,
|
||||
pIO.CurrentViewPort.pSize.z - 10);
|
||||
pLayout.Pos.y =
|
||||
std::clamp<float>(pLayout.Pos.y, pIO.CurrentViewPort.pSize.y,
|
||||
pIO.CurrentViewPort.pSize.w - 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_API void Menu::DrawBaseLayout() {
|
||||
if (pIsOpen) {
|
||||
/** Resize Sym (Render on Top of Everything) */
|
||||
if (!(Flags & UI7MenuFlags_NoResize)) {
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
|
||||
l->SetLayer(1);
|
||||
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20));
|
||||
l->PathAdd(self->FinalPos() + self->GetSize());
|
||||
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0));
|
||||
l->PathFill(io->Theme.Get(UI7Color_Button));
|
||||
l->SetLayer(0);
|
||||
});
|
||||
r->SetSize(
|
||||
fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight));
|
||||
r->SetPos(fvec2(0, TitleBarHeight));
|
||||
pLayout.AddObjectEx(r,
|
||||
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
|
||||
}
|
||||
|
||||
/** Background */
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
|
||||
l->SetLayer(0);
|
||||
l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f,
|
||||
LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot);
|
||||
l->PathFill(io->Theme.Get(UI7Color_Background));
|
||||
/*l->DrawRectFilled(self->FinalPos(), self->GetSize(),
|
||||
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));
|
||||
r->SetPos(fvec2(0, TitleBarHeight));
|
||||
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle |
|
||||
UI7LytAdd_Front | UI7LytAdd_NoClipTitlebar);
|
||||
}
|
||||
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj(
|
||||
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
|
||||
l->SetFont(self->GetFont());
|
||||
l->SetLayer(20);
|
||||
/** Header Bar */
|
||||
l->DrawRectFilled(self->FinalPos(), self->GetSize(),
|
||||
io->Theme.Get(UI7Color_Header));
|
||||
l->SetLayer(21);
|
||||
/** Inline if statement to shift the Text if collapse sym is shown */
|
||||
/** What the hell is this code btw (didn't found a better way) */
|
||||
l->DrawText(self->FinalPos() +
|
||||
fvec2((Flags & UI7MenuFlags_NoCollapse)
|
||||
? pIO.FramePadding.x
|
||||
: (TitleBarHeight - pIO.FramePadding.y * 2 +
|
||||
(io->FramePadding.x * 2)),
|
||||
2),
|
||||
pID.GetName().c_str(), io->Theme.Get(UI7Color_Text));
|
||||
l->SetLayer(0);
|
||||
});
|
||||
r->SetSize(fvec2(pLayout.GetSize().x, TitleBarHeight));
|
||||
r->SetPos(0);
|
||||
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle |
|
||||
UI7LytAdd_NoClipTitlebar);
|
||||
|
||||
/** Collapse Sym */
|
||||
if (!(Flags & UI7MenuFlags_NoCollapse)) {
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
|
||||
UI7::Container* self) {
|
||||
/** This sym actually requires layer 21 (i dont know why) */
|
||||
l->SetLayer(21);
|
||||
/**
|
||||
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
|
||||
*/
|
||||
l->DrawTriangleFilled(
|
||||
self->FinalPos(),
|
||||
self->FinalPos() +
|
||||
fvec2(self->GetSize().x, pIsOpen ? 0 : self->GetSize().y * 0.5),
|
||||
self->FinalPos() +
|
||||
fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y),
|
||||
io->Theme.Get(UI7Color_FrameBackground));
|
||||
l->SetLayer(0);
|
||||
});
|
||||
r->SetSize(TitleBarHeight - pIO.FramePadding.y * 2);
|
||||
r->SetPos(pIO.FramePadding);
|
||||
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate |
|
||||
UI7LytAdd_NoScrollHandle |
|
||||
UI7LytAdd_NoClipTitlebar);
|
||||
}
|
||||
/** Close Sym (only shown if pIsShown is not nullptr) */
|
||||
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) {
|
||||
fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; // Fixed quad size
|
||||
// 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)
|
||||
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());
|
||||
// Probably should fix the minsize to be locked on y
|
||||
fvec2 cpos =
|
||||
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x,
|
||||
pLayout.Pos.y + pIO.FramePadding.y);
|
||||
pLayout.DrawList.SetLayer(21);
|
||||
pLayout.DrawList.DrawLine(cpos, cpos + size,
|
||||
pIO.Theme.Get(UI7Color_FrameBackground), 2);
|
||||
pLayout.DrawList.DrawLine(cpos + fvec2(0, size.y),
|
||||
cpos + fvec2(size.x, 0),
|
||||
pIO.Theme.Get(UI7Color_FrameBackground), 2);
|
||||
pLayout.DrawList.SetLayer(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_API void Menu::Update() {
|
||||
HandleFocus();
|
||||
if (pLayout.Size == fvec2(0.f) || Flags & UI7MenuFlags_AlwaysAutoSize) {
|
||||
pLayout.Size = fvec2(pLayout.MaxPosition) + pIO.MenuPadding * 2;
|
||||
}
|
||||
if (Flags & UI7MenuFlags_VtScrolling)
|
||||
pLayout.Flags |= UI7LayoutFlags_VtScrolling;
|
||||
if (Flags & UI7MenuFlags_HzScrolling)
|
||||
pLayout.Flags |= UI7LayoutFlags_HzScrolling;
|
||||
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
|
||||
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
|
||||
pLayout.WorkRect.y = 5.f + TitleBarHeight;
|
||||
HandleTitlebarActions();
|
||||
} else {
|
||||
TitleBarHeight = 0.f;
|
||||
pLayout.WorkRect.y = 5.f;
|
||||
}
|
||||
DrawBaseLayout();
|
||||
pLayout.Update();
|
||||
}
|
||||
|
||||
PD_API bool Menu::BeginTreeNode(const ID& id) {
|
||||
// As of some notes this should work:
|
||||
auto n = pTreeNodes.find(id);
|
||||
if (n == pTreeNodes.end()) {
|
||||
pTreeNodes[id] = false;
|
||||
n = pTreeNodes.find(id);
|
||||
}
|
||||
fvec2 pos = pLayout.Cursor;
|
||||
fvec2 tdim = pIO.Font->GetTextBounds(id.GetName().c_str(), pIO.FontScale);
|
||||
fvec2 szs = tdim + fvec2(pIO.ItemSpace.x + 10, 0);
|
||||
|
||||
if (n->second) {
|
||||
pLayout.InitialCursorOffset += 10.f;
|
||||
}
|
||||
|
||||
// Object
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([=, this](IO* io, Li::Drawlist* l, Container* self) {
|
||||
l->SetFont(self->GetFont());
|
||||
fvec2 ts = self->FinalPos() + fvec2(0, 7);
|
||||
fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)};
|
||||
if (n->second) {
|
||||
float t = pl[0].y;
|
||||
pl[0].y = pl[1].x;
|
||||
pl[1].x = t;
|
||||
}
|
||||
l->DrawTriangleFilled(ts, ts + pl[0], ts + pl[1],
|
||||
io->Theme.Get(UI7Color_FrameBackground));
|
||||
|
||||
l->DrawText(self->FinalPos() + fvec2(10 + io->ItemSpace.x, 0),
|
||||
id.GetName().c_str(), io->Theme.Get(UI7Color_Text));
|
||||
});
|
||||
/** Yes this new function handler was created for tree nodes */
|
||||
r->AddInputHandler([=, this](IO* io, Container* self) {
|
||||
if (io->InputHandler.DragObject(ID(pID.GetName() + id.GetName()),
|
||||
fvec4(self->FinalPos(), self->GetSize()))) {
|
||||
if (io->InputHandler.DragReleased) {
|
||||
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
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2026 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <pd/ui7/containers.hpp>
|
||||
#include <pd/ui7/menu.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
Menu::Menu(const ID& id, IO& io) : pIO(io), pID(id), pLayout(id, io) {
|
||||
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
|
||||
pLayout.WorkRect.y += TitleBarHeight;
|
||||
pLayout.Flags |= UI7LayoutFlags_UseClipRect;
|
||||
pLayout.CursorInit();
|
||||
}
|
||||
|
||||
PD_API void Menu::Label(const std::string& label) {
|
||||
// Layout API
|
||||
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 =
|
||||
Strings::FastHash("btn" + label + std::to_string(pLayout.Objects.size()));
|
||||
Container* r = pLayout.FindObject(id);
|
||||
if (!r) {
|
||||
r = new UI7::Button(label, pIO);
|
||||
r->SetID(id);
|
||||
}
|
||||
pLayout.AddObject(r);
|
||||
if (!r->Skippable()) {
|
||||
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()));
|
||||
Container* r = pLayout.FindObject(id);
|
||||
if (!r) {
|
||||
r = new UI7::Checkbox(label, v, pIO);
|
||||
r->SetID(id);
|
||||
}
|
||||
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);
|
||||
pLayout.AddObject(r);
|
||||
}
|
||||
|
||||
PD_API void Menu::ColorEdit(const std::string& label, u32& clr) {
|
||||
u32 id = Strings::FastHash("drd" + label);
|
||||
Container* r = pLayout.FindObject(id);
|
||||
if (!r) {
|
||||
r = new UI7::ColorEdit(label, &clr, pIO);
|
||||
r->SetID(id);
|
||||
}
|
||||
pLayout.AddObject(r);
|
||||
}
|
||||
|
||||
PD_API void Menu::Separator() {
|
||||
// Dynamic Objects are very simple...
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj(
|
||||
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
|
||||
l->DrawRectFilled(self->FinalPos(), self->GetSize(),
|
||||
pIO.Theme.Get(UI7Color_TextDead));
|
||||
});
|
||||
// Set size before pushing (cause Cursor Move will require it)
|
||||
r->SetSize(fvec2(
|
||||
pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x,
|
||||
1));
|
||||
pLayout.AddObject(r);
|
||||
}
|
||||
|
||||
PD_API void Menu::SeparatorText(const std::string& label) {
|
||||
// Also note to use [=] instead of [&] to not undefined access label
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
|
||||
UI7::Container* self) {
|
||||
l->SetFont(self->GetFont());
|
||||
fvec2 size = self->GetSize();
|
||||
fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale);
|
||||
fvec2 pos = self->FinalPos();
|
||||
auto align = pLayout.GetAlignment();
|
||||
vec2 rpos = pLayout.AlignPosition(pos, tdim,
|
||||
fvec4(pLayout.Pos, pLayout.Size), align);
|
||||
if (!(align & UI7Align_Left)) {
|
||||
l->DrawRectFilled(fvec2(rpos.x + io->FramePadding.x, tdim.y * 0.5),
|
||||
fvec2(pos.x - rpos.x - io->MenuPadding.x, 1),
|
||||
io->Theme.Get(UI7Color_TextDead));
|
||||
}
|
||||
if (!(align & UI7Align_Right)) {
|
||||
l->DrawRectFilled(pos + fvec2(tdim.x + io->FramePadding.x, tdim.y * 0.5),
|
||||
fvec2(size.x - tdim.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));
|
||||
});
|
||||
// Set size before pushing (cause Cursor Move will require it)
|
||||
r->SetSize(fvec2(
|
||||
pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x,
|
||||
pIO.Font->PixelHeight * pIO.FontScale));
|
||||
pLayout.AddObject(r);
|
||||
}
|
||||
PD_API void Menu::HandleFocus() {
|
||||
// Check if menu can be focused for Selective Menu Input API
|
||||
vec4 newarea = fvec4(pLayout.Pos, pLayout.Size);
|
||||
if (!pIsOpen) {
|
||||
newarea = fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight));
|
||||
}
|
||||
if ((PD::Hid::IsEvent(Hid::Event::Down, Hid::Gamepad::Touch) ||
|
||||
PD::Hid::IsEvent(Hid::Event::Down, Hid::Keyboard::MouseLeft)) &&
|
||||
Li::Math::InBounds(PD::Hid::MousePos(), newarea) &&
|
||||
!Li::Math::InBounds(PD::Hid::MousePos(),
|
||||
pIO.InputHandler.FocusedMenuRect)) {
|
||||
pIO.InputHandler.FocusedMenu = pID;
|
||||
}
|
||||
if (pIO.InputHandler.FocusedMenu == pID) {
|
||||
pIO.InputHandler.FocusedMenuRect = newarea;
|
||||
}
|
||||
}
|
||||
|
||||
PD_API void Menu::HandleTitlebarActions() {
|
||||
// Collapse
|
||||
if (!(Flags & UI7MenuFlags_NoCollapse)) {
|
||||
vec2 cpos = pLayout.Pos + pIO.FramePadding;
|
||||
// clr_collapse_tri = UI7Color_FrameBackground;
|
||||
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clbse"),
|
||||
fvec4(cpos, fvec2(18, TitleBarHeight)))) {
|
||||
if (pIO.InputHandler.DragReleased) {
|
||||
pIsOpen = !pIsOpen;
|
||||
}
|
||||
// clr_collapse_tri = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
// Close Logic
|
||||
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown != nullptr) {
|
||||
fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2;
|
||||
fvec2 cpos =
|
||||
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x,
|
||||
pLayout.Pos.y + pIO.FramePadding.y);
|
||||
|
||||
// clr_close_btn = UI7Color_FrameBackground;
|
||||
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clse"),
|
||||
fvec4(cpos, size))) {
|
||||
if (pIO.InputHandler.DragReleased) {
|
||||
*pIsShown = !(*pIsShown);
|
||||
}
|
||||
// clr_close_btn = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
// Resize logic
|
||||
if (!(Flags & UI7MenuFlags_NoResize)) {
|
||||
vec2 cpos = pLayout.Pos + pLayout.Size - fvec2(20);
|
||||
|
||||
// clr_close_btn = UI7Color_FrameBackground;
|
||||
if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "rszs"),
|
||||
fvec4(cpos, fvec2(20)))) {
|
||||
fvec2 szs = pLayout.Size + (pIO.InputHandler.DragPosition -
|
||||
pIO.InputHandler.DragLastPosition);
|
||||
if (szs.x < 30) szs.x = 30;
|
||||
if (szs.y < 30) szs.y = 30;
|
||||
pLayout.Size = szs;
|
||||
// clr_close_btn = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
// Menu Movement
|
||||
if (!(Flags & UI7MenuFlags_NoMove)) {
|
||||
if (pIO.InputHandler.DragObject(
|
||||
pID.GetName() + "tmv",
|
||||
fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)))) {
|
||||
if (pIO.InputHandler.DragDoubleRelease) {
|
||||
pIsOpen = !pIsOpen;
|
||||
}
|
||||
pLayout.Pos = pLayout.Pos + (pIO.InputHandler.DragPosition -
|
||||
pIO.InputHandler.DragLastPosition);
|
||||
// Keep Window In Viewport
|
||||
// Maybe i need to add some operators to vec
|
||||
pLayout.Pos.x = std::clamp<float>(pLayout.Pos.x, -pLayout.Size.x + 10,
|
||||
pIO.CurrentViewPort.pSize.z - 10);
|
||||
pLayout.Pos.y =
|
||||
std::clamp<float>(pLayout.Pos.y, pIO.CurrentViewPort.pSize.y,
|
||||
pIO.CurrentViewPort.pSize.w - 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_API void Menu::DrawBaseLayout() {
|
||||
if (pIsOpen) {
|
||||
/** Resize Sym (Render on Top of Everything) */
|
||||
if (!(Flags & UI7MenuFlags_NoResize)) {
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
|
||||
l->SetLayer(1);
|
||||
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20));
|
||||
l->PathAdd(self->FinalPos() + self->GetSize());
|
||||
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0));
|
||||
l->PathFill(io->Theme.Get(UI7Color_Button));
|
||||
l->SetLayer(0);
|
||||
});
|
||||
r->SetSize(
|
||||
fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight));
|
||||
r->SetPos(fvec2(0, TitleBarHeight));
|
||||
pLayout.AddObjectEx(r,
|
||||
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
|
||||
}
|
||||
|
||||
/** Background */
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
|
||||
l->SetLayer(0);
|
||||
l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f,
|
||||
LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot);
|
||||
l->PathFill(io->Theme.Get(UI7Color_Background));
|
||||
/*l->DrawRectFilled(self->FinalPos(), self->GetSize(),
|
||||
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));
|
||||
r->SetPos(fvec2(0, TitleBarHeight));
|
||||
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle |
|
||||
UI7LytAdd_Front);
|
||||
}
|
||||
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj(
|
||||
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
|
||||
l->SetFont(self->GetFont());
|
||||
l->SetLayer(20);
|
||||
/** Header Bar */
|
||||
l->DrawRectFilled(self->FinalPos(), self->GetSize(),
|
||||
io->Theme.Get(UI7Color_Header));
|
||||
l->SetLayer(21);
|
||||
/** Inline if statement to shift the Text if collapse sym is shown */
|
||||
/** What the hell is this code btw (didn't found a better way) */
|
||||
l->DrawText(self->FinalPos() +
|
||||
fvec2((Flags & UI7MenuFlags_NoCollapse)
|
||||
? pIO.FramePadding.x
|
||||
: (TitleBarHeight - pIO.FramePadding.y * 2 +
|
||||
(io->FramePadding.x * 2)),
|
||||
2),
|
||||
pID.GetName().c_str(), io->Theme.Get(UI7Color_Text));
|
||||
l->SetLayer(0);
|
||||
});
|
||||
r->SetSize(fvec2(pLayout.GetSize().x, TitleBarHeight));
|
||||
r->SetPos(0);
|
||||
pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
|
||||
|
||||
/** Collapse Sym */
|
||||
if (!(Flags & UI7MenuFlags_NoCollapse)) {
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
|
||||
UI7::Container* self) {
|
||||
/** This sym actually requires layer 21 (i dont know why) */
|
||||
l->SetLayer(21);
|
||||
/**
|
||||
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
|
||||
*/
|
||||
l->DrawTriangleFilled(
|
||||
self->FinalPos(),
|
||||
self->FinalPos() +
|
||||
fvec2(self->GetSize().x, pIsOpen ? 0 : self->GetSize().y * 0.5),
|
||||
self->FinalPos() +
|
||||
fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y),
|
||||
io->Theme.Get(UI7Color_FrameBackground));
|
||||
l->SetLayer(0);
|
||||
});
|
||||
r->SetSize(TitleBarHeight - pIO.FramePadding.y * 2);
|
||||
r->SetPos(pIO.FramePadding);
|
||||
pLayout.AddObjectEx(r,
|
||||
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
|
||||
}
|
||||
/** Close Sym (only shown if pIsShown is not nullptr) */
|
||||
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) {
|
||||
fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; // Fixed quad size
|
||||
// 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)
|
||||
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());
|
||||
// Probably should fix the minsize to be locked on y
|
||||
fvec2 cpos =
|
||||
fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x,
|
||||
pLayout.Pos.y + pIO.FramePadding.y);
|
||||
pLayout.DrawList.DrawLine(cpos, cpos + size,
|
||||
pIO.Theme.Get(UI7Color_FrameBackground), 2);
|
||||
pLayout.DrawList.DrawLine(cpos + fvec2(0, size.y),
|
||||
cpos + fvec2(size.x, 0),
|
||||
pIO.Theme.Get(UI7Color_FrameBackground), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_API void Menu::Update() {
|
||||
HandleFocus();
|
||||
if (pLayout.Size == fvec2(0.f) || Flags & UI7MenuFlags_AlwaysAutoSize) {
|
||||
pLayout.Size = fvec2(pLayout.MaxPosition) + pIO.MenuPadding * 2;
|
||||
}
|
||||
if (Flags & UI7MenuFlags_VtScrolling)
|
||||
pLayout.Flags |= UI7LayoutFlags_VtScrolling;
|
||||
if (Flags & UI7MenuFlags_HzScrolling)
|
||||
pLayout.Flags |= UI7LayoutFlags_HzScrolling;
|
||||
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
|
||||
TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y;
|
||||
pLayout.WorkRect.y = 5.f + TitleBarHeight;
|
||||
HandleTitlebarActions();
|
||||
} else {
|
||||
TitleBarHeight = 0.f;
|
||||
pLayout.WorkRect.y = 5.f;
|
||||
}
|
||||
DrawBaseLayout();
|
||||
pLayout.Update();
|
||||
}
|
||||
|
||||
PD_API bool Menu::BeginTreeNode(const ID& id) {
|
||||
// As of some notes this should work:
|
||||
auto n = pTreeNodes.find(id);
|
||||
if (n == pTreeNodes.end()) {
|
||||
pTreeNodes[id] = false;
|
||||
n = pTreeNodes.find(id);
|
||||
}
|
||||
fvec2 pos = pLayout.Cursor;
|
||||
fvec2 tdim = pIO.Font->GetTextBounds(id.GetName().c_str(), pIO.FontScale);
|
||||
fvec2 szs = tdim + fvec2(pIO.ItemSpace.x + 10, 0);
|
||||
|
||||
if (n->second) {
|
||||
pLayout.InitialCursorOffset += 10.f;
|
||||
}
|
||||
|
||||
// Object
|
||||
DynObj* r = pIO.DynObjPool.Allocate();
|
||||
*r = UI7::DynObj([=, this](IO* io, Li::Drawlist* l, Container* self) {
|
||||
l->SetFont(self->GetFont());
|
||||
fvec2 ts = self->FinalPos() + fvec2(0, 7);
|
||||
fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)};
|
||||
if (n->second) {
|
||||
float t = pl[0].y;
|
||||
pl[0].y = pl[1].x;
|
||||
pl[1].x = t;
|
||||
}
|
||||
l->DrawTriangleFilled(ts, ts + pl[0], ts + pl[1],
|
||||
io->Theme.Get(UI7Color_FrameBackground));
|
||||
|
||||
l->DrawText(self->FinalPos() + fvec2(10 + io->ItemSpace.x, 0),
|
||||
id.GetName().c_str(), io->Theme.Get(UI7Color_Text));
|
||||
});
|
||||
/** Yes this new function handler was created for tree nodes */
|
||||
r->AddInputHandler([=, this](IO* io, Container* self) {
|
||||
if (io->InputHandler.DragObject(ID(pID.GetName() + id.GetName()),
|
||||
fvec4(self->FinalPos(), self->GetSize()))) {
|
||||
if (io->InputHandler.DragReleased) {
|
||||
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
|
||||
|
||||
+349
-359
@@ -1,359 +1,349 @@
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2026 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/ui7.hpp>
|
||||
|
||||
#include "pd/pd_p_api.hpp"
|
||||
#include "pd/ui7/flags.hpp"
|
||||
|
||||
#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x)
|
||||
#define UI7DTF(x) PD::Strings::FormatNanos(x)
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_API std::string GetVersion(bool show_build) {
|
||||
std::stringstream s;
|
||||
s << ((UI7_VERSION >> 24) & 0xFF) << ".";
|
||||
s << ((UI7_VERSION >> 16) & 0xFF) << ".";
|
||||
s << ((UI7_VERSION >> 8) & 0xFF);
|
||||
if (show_build) s << "-" << ((UI7_VERSION) & 0xFF);
|
||||
return s.str();
|
||||
}
|
||||
|
||||
PD_API void Context::AddViewPort(const ID& id, const ivec4& vp) {
|
||||
pIO.AddViewPort(id, vp);
|
||||
}
|
||||
|
||||
PD_API void Context::UseViewPort(const ID& id) {
|
||||
if (!pIO.ViewPorts.count(id)) {
|
||||
return;
|
||||
}
|
||||
pIO.CurrentViewPort = pIO.ViewPorts[id.RawID()];
|
||||
}
|
||||
|
||||
PD_API Menu* Context::BeginMenu(const ID& id, UI7MenuFlags flags, bool* pShow) {
|
||||
if (pCurrent) {
|
||||
PDERR("UI7: You are already in {} Menu!", pCurrent->pID.GetName());
|
||||
return nullptr;
|
||||
}
|
||||
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), (u32)id) !=
|
||||
pCurrentMenus.end()) {
|
||||
PDERR("UI7: Menu {} already exists!", id.GetName());
|
||||
return nullptr;
|
||||
}
|
||||
pCurrent = pGetOrCreateMenu(id);
|
||||
this->pCurrent->pIsShown = pShow;
|
||||
if (pCurrent->pIsShown != nullptr) {
|
||||
if (!*pCurrent->pIsShown) {
|
||||
pCurrent = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
/** Probably we dont even need Input Handling in this stage */
|
||||
// this->pIO.InputHandler.CurrentMenu = id;
|
||||
pCurrentMenus.push_back(id);
|
||||
pCurrent->Flags = flags;
|
||||
if (!pCurrent->pIsOpen) {
|
||||
pCurrent = nullptr;
|
||||
}
|
||||
return pCurrent;
|
||||
}
|
||||
|
||||
PD_API void Context::EndMenu() {
|
||||
/**
|
||||
* Currently it would be a better wy to handle menus as follows
|
||||
*
|
||||
* 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)
|
||||
* and after that it should simply out of scope
|
||||
* (This would probably require some wrapper class to find out if m goes
|
||||
* out of scope)
|
||||
* ```cpp
|
||||
* if(auto m = ui7->BeginMenu("Test")) {
|
||||
* m->Label("Show some Text");
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
if (!pCurrent) {
|
||||
return;
|
||||
}
|
||||
pCurrent = nullptr;
|
||||
// pIO.InputHandler.CurrentMenu = 0;
|
||||
}
|
||||
|
||||
PD_API void Context::Update() {
|
||||
/**
|
||||
* Cause Commenting each line looks carbage...
|
||||
* 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 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
|
||||
* 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
|
||||
* gets cleanup and io gets updated
|
||||
*
|
||||
* Very simple ...
|
||||
*/
|
||||
pIO.FDL.Clear();
|
||||
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(),
|
||||
pIO.InputHandler.FocusedMenu) == pCurrentMenus.end()) {
|
||||
pIO.InputHandler.FocusedMenu = 0;
|
||||
pIO.InputHandler.FocusedMenuRect = fvec4(0);
|
||||
}
|
||||
std::vector<u32> FinalList;
|
||||
for (auto it : pDFO) {
|
||||
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), it) !=
|
||||
pCurrentMenus.end() &&
|
||||
it != pIO.InputHandler.FocusedMenu) {
|
||||
FinalList.push_back(it);
|
||||
}
|
||||
}
|
||||
for (auto it : pCurrentMenus) {
|
||||
if (std::find(FinalList.begin(), FinalList.end(), it) == FinalList.end() &&
|
||||
it != pIO.InputHandler.FocusedMenu) {
|
||||
FinalList.push_back(it);
|
||||
}
|
||||
}
|
||||
if (pMenus.count(pIO.InputHandler.FocusedMenu)) {
|
||||
FinalList.insert(FinalList.begin(), pIO.InputHandler.FocusedMenu);
|
||||
}
|
||||
pDFO = FinalList;
|
||||
for (auto& it : FinalList) {
|
||||
this->pIO.InputHandler.CurrentMenu = it;
|
||||
pMenus[it]->Update(); /** Render */
|
||||
this->pIO.InputHandler.CurrentMenu = 0;
|
||||
}
|
||||
int base_layer = 0;
|
||||
for (int i = (int)FinalList.size() - 1; i >= 0; i--) {
|
||||
pIO.FDL.SetLayer(base_layer);
|
||||
pIO.FDL.Merge(pMenus[FinalList[i]]->pLayout.GetDrawList());
|
||||
base_layer += 100;
|
||||
}
|
||||
pCurrentMenus.clear();
|
||||
pIO.Update();
|
||||
pIO.FDL.Optimize();
|
||||
}
|
||||
|
||||
PD_API void Context::AboutMenu(bool* show) {
|
||||
if (auto m = BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
|
||||
m->Label("Palladium UI7 " + GetVersion());
|
||||
m->Separator();
|
||||
m->Label("(c) 2023-2026 René Amthor");
|
||||
m->Label("UI7 is licensed under the MIT License.");
|
||||
m->Label("See LICENSE for more information.");
|
||||
static bool show_build;
|
||||
m->Checkbox("Show Build Info", show_build);
|
||||
if (show_build) {
|
||||
m->SeparatorText("Build Info");
|
||||
m->Label("Full Version -> " + GetVersion(true));
|
||||
m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t)));
|
||||
m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(Li::Vertex)));
|
||||
m->Label("__cplusplus -> " + std::to_string(__cplusplus));
|
||||
m->Label("Compiler -> {}",
|
||||
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());
|
||||
m->Separator();
|
||||
m->Label(
|
||||
std::format("Average {:.3f} ms/f ({:.1f} FPS)",
|
||||
((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("NumIndices: {} -> {} Tris", pIO.NumIndices,
|
||||
pIO.NumIndices / 3));
|
||||
m->Label("Menus: " + std::to_string(pMenus.size()));
|
||||
/** Section TimeTrace */
|
||||
m->SeparatorText("TimeTrace");
|
||||
if (m->BeginTreeNode("Traces (" +
|
||||
std::to_string(PD::TT::GetTraceMap().size()) + ")")) {
|
||||
for (auto& it : PD::TT::GetTraceMap()) {
|
||||
if (m->BeginTreeNode(it.second.GetID())) {
|
||||
m->Label("Diff: " + UI7DTF(it.second.GetLastDiff()));
|
||||
m->Label("Protocol Len: " +
|
||||
std::to_string(it.second.GetProtocol().GetLen()));
|
||||
m->Label("Average: " + UI7DTF(it.second.GetProtocol().GetAverage()));
|
||||
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->Label("Os Driver: {}", PD::Os::GetDriverName());
|
||||
if (m->BeginTreeNode(
|
||||
std::format("Gfx Driver: {}", PD::Gfx::GetDriverName()))) {
|
||||
m->SeparatorText("Features");
|
||||
if (PD::Gfx::GetFlags() & PDGfxBackendFlags_HasClipRect)
|
||||
m->Label("ClipRects");
|
||||
if (PD::Gfx::GetFlags() & PDGfxBackendFlags_ReqPow2)
|
||||
m->Label("Texture As Pow of 2");
|
||||
if (PD::Gfx::GetFlags() & PDGfxBackendFlags_ApproxSDF)
|
||||
m->Label("SDF Approximation");
|
||||
m->EndTreeNode();
|
||||
}
|
||||
if (m->BeginTreeNode(
|
||||
std::string(std::string("Input: ") + PD::Hid::GetDriverName()))) {
|
||||
/* if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasKeyboard) {
|
||||
m->Label("- Keyboard Supported");
|
||||
}
|
||||
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasMouse) {
|
||||
m->Label("- Mouse Supported");
|
||||
}
|
||||
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasTouch) {
|
||||
m->Label("- Touch Supported");
|
||||
}
|
||||
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::FLags_HasGamepad) {
|
||||
m->Label("- Gamepad Supported");
|
||||
}*/
|
||||
m->EndTreeNode();
|
||||
}
|
||||
/** Section IO */
|
||||
m->SeparatorText("IO");
|
||||
if (m->BeginTreeNode("Menus (" + std::to_string(pMenus.size()) + ")")) {
|
||||
for (auto& it : pMenus) {
|
||||
if (m->BeginTreeNode(it.second->pID.GetName())) {
|
||||
m->Label("Name: " + it.second->pID.GetName());
|
||||
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->Label(std::format("Cursor: {}", it.second->pLayout.Cursor));
|
||||
if (m->BeginTreeNode(
|
||||
"ID Objects (" +
|
||||
std::to_string(it.second->pLayout.IDObjects.size()) + ")")) {
|
||||
for (auto& jt : it.second->pLayout.IDObjects) {
|
||||
m->Label(std::format("{:08X}", jt->GetID()));
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
if (m->BeginTreeNode("Active Menus (" +
|
||||
std::to_string(pCurrentMenus.size()) + ")")) {
|
||||
for (auto& it : pCurrentMenus) {
|
||||
if (m->BeginTreeNode(pMenus[it]->pID.GetName())) {
|
||||
m->Label("Name: " + pMenus[it]->pID.GetName());
|
||||
m->Label(std::format("Pos: {}", pMenus[it]->pLayout.GetPosition()));
|
||||
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));
|
||||
if (m->BeginTreeNode(
|
||||
"ID Objects (" +
|
||||
std::to_string(pMenus[it]->pLayout.IDObjects.size()) + ")")) {
|
||||
for (auto& jt : pMenus[it]->pLayout.IDObjects) {
|
||||
m->Label(std::format("{:08X}", jt->GetID()));
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
// Well this are Li Drawlists now and they do not count their stats (yet)
|
||||
/*if (m->BeginTreeNode("DrawLists (" +
|
||||
std::to_string(pIO.DrawListRegestry.size()) + ")")) {
|
||||
for (auto &it : pIO.DrawListRegestry) {
|
||||
if (m->BeginTreeNode(it.First.GetName())) {
|
||||
m->Label("Vertices: " + std::to_string(it.Second->NumVertices));
|
||||
m->Label("Indices: " + std::to_string(it.Second->NumIndices));
|
||||
m->Label("Base Layer: " + std::to_string(it.Second->Base));
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}*/
|
||||
m->Label("io->Time: " + Strings::FormatMillis(pIO.Time.Get()));
|
||||
m->Label(std::format("Delta: {:.3f}", pIO.Delta));
|
||||
m->Label(std::format("Framerate: {:.2f}", pIO.Framerate));
|
||||
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",
|
||||
pIO.InputHandler.DragTime.GetSeconds()));
|
||||
m->Label(
|
||||
std::format("DragDestination: [{}]", pIO.InputHandler.DragDestination));
|
||||
m->Label(std::format("DragSource: [{}]", pIO.InputHandler.DragSourcePos));
|
||||
m->Label(std::format("DragPos: [{}]", pIO.InputHandler.DragPosition));
|
||||
m->Label(
|
||||
std::format("DragLastPos: [{}]", pIO.InputHandler.DragLastPosition));
|
||||
EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
PD_API void UI7::Context::StyleEditor(bool* show) {
|
||||
if (auto m = BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) {
|
||||
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
|
||||
m->Separator();
|
||||
m->DragData("MenuPadding", (float*)&pIO.MenuPadding, 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("MinSliderSize", (float*)&pIO.MinSliderDragSize, 2, 1.f, 100.f);
|
||||
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);
|
||||
m->SeparatorText("Theme");
|
||||
if (m->Button("Dark")) {
|
||||
UI7::Theme::Default(pIO.Theme);
|
||||
}
|
||||
m->SameLine();
|
||||
if (m->Button("Flashbang")) {
|
||||
UI7::Theme::Flashbang(pIO.Theme);
|
||||
}
|
||||
/// Small trick to print without prefix
|
||||
#define ts(x) m->ColorEdit(std::string(#x).substr(9), pIO.Theme.GetRef(x));
|
||||
#define ts2(x) \
|
||||
m->DragData(std::string(#x).substr(9), (u8*)&pIO.Theme.GetRef(x), 4, (u8)0, \
|
||||
(u8)255);
|
||||
ts(UI7Color_Background);
|
||||
ts(UI7Color_Border);
|
||||
ts(UI7Color_Button);
|
||||
ts(UI7Color_ButtonDead);
|
||||
ts(UI7Color_ButtonActive);
|
||||
ts(UI7Color_ButtonHovered);
|
||||
ts(UI7Color_Text);
|
||||
ts(UI7Color_TextDead);
|
||||
ts(UI7Color_Header);
|
||||
ts(UI7Color_HeaderDead);
|
||||
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
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2026 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/ui7.hpp>
|
||||
|
||||
#include "pd/pd_p_api.hpp"
|
||||
#include "pd/ui7/flags.hpp"
|
||||
|
||||
#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x)
|
||||
#define UI7DTF(x) PD::Strings::FormatNanos(x)
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_API std::string GetVersion(bool show_build) {
|
||||
std::stringstream s;
|
||||
s << ((UI7_VERSION >> 24) & 0xFF) << ".";
|
||||
s << ((UI7_VERSION >> 16) & 0xFF) << ".";
|
||||
s << ((UI7_VERSION >> 8) & 0xFF);
|
||||
if (show_build) s << "-" << ((UI7_VERSION) & 0xFF);
|
||||
return s.str();
|
||||
}
|
||||
|
||||
PD_API void Context::AddViewPort(const ID& id, const ivec4& vp) {
|
||||
pIO.AddViewPort(id, vp);
|
||||
}
|
||||
|
||||
PD_API void Context::UseViewPort(const ID& id) {
|
||||
if (!pIO.ViewPorts.count(id)) {
|
||||
return;
|
||||
}
|
||||
pIO.CurrentViewPort = pIO.ViewPorts[id.RawID()];
|
||||
}
|
||||
|
||||
PD_API Menu* Context::BeginMenu(const ID& id, UI7MenuFlags flags, bool* pShow) {
|
||||
if (pCurrent) {
|
||||
PDERR("UI7: You are already in {} Menu!", pCurrent->pID.GetName());
|
||||
return nullptr;
|
||||
}
|
||||
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), (u32)id) !=
|
||||
pCurrentMenus.end()) {
|
||||
PDERR("UI7: Menu {} already exists!", id.GetName());
|
||||
return nullptr;
|
||||
}
|
||||
pCurrent = pGetOrCreateMenu(id);
|
||||
this->pCurrent->pIsShown = pShow;
|
||||
if (pCurrent->pIsShown != nullptr) {
|
||||
if (!*pCurrent->pIsShown) {
|
||||
pCurrent = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
/** Probably we dont even need Input Handling in this stage */
|
||||
// this->pIO.InputHandler.CurrentMenu = id;
|
||||
pCurrentMenus.push_back(id);
|
||||
pCurrent->Flags = flags;
|
||||
if (!pCurrent->pIsOpen) {
|
||||
pCurrent = nullptr;
|
||||
}
|
||||
return pCurrent;
|
||||
}
|
||||
|
||||
PD_API void Context::EndMenu() {
|
||||
/**
|
||||
* Currently it would be a better wy to handle menus as follows
|
||||
*
|
||||
* 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)
|
||||
* and after that it should simply out of scope
|
||||
* (This would probably require some wrapper class to find out if m goes
|
||||
* out of scope)
|
||||
* ```cpp
|
||||
* if(auto m = ui7->BeginMenu("Test")) {
|
||||
* m->Label("Show some Text");
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
if (!pCurrent) {
|
||||
return;
|
||||
}
|
||||
pCurrent = nullptr;
|
||||
// pIO.InputHandler.CurrentMenu = 0;
|
||||
}
|
||||
|
||||
PD_API void Context::Update() {
|
||||
/**
|
||||
* Cause Commenting each line looks carbage...
|
||||
* 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 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
|
||||
* 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
|
||||
* gets cleanup and io gets updated
|
||||
*
|
||||
* Very simple ...
|
||||
*/
|
||||
pIO.FDL.Clear();
|
||||
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(),
|
||||
pIO.InputHandler.FocusedMenu) == pCurrentMenus.end()) {
|
||||
pIO.InputHandler.FocusedMenu = 0;
|
||||
pIO.InputHandler.FocusedMenuRect = fvec4(0);
|
||||
}
|
||||
std::vector<u32> FinalList;
|
||||
for (auto it : pDFO) {
|
||||
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), it) !=
|
||||
pCurrentMenus.end() &&
|
||||
it != pIO.InputHandler.FocusedMenu) {
|
||||
FinalList.push_back(it);
|
||||
}
|
||||
}
|
||||
for (auto it : pCurrentMenus) {
|
||||
if (std::find(FinalList.begin(), FinalList.end(), it) == FinalList.end() &&
|
||||
it != pIO.InputHandler.FocusedMenu) {
|
||||
FinalList.push_back(it);
|
||||
}
|
||||
}
|
||||
if (pMenus.count(pIO.InputHandler.FocusedMenu)) {
|
||||
FinalList.insert(FinalList.begin(), pIO.InputHandler.FocusedMenu);
|
||||
}
|
||||
pDFO = FinalList;
|
||||
for (auto& it : FinalList) {
|
||||
this->pIO.InputHandler.CurrentMenu = it;
|
||||
pMenus[it]->Update(); /** Render */
|
||||
this->pIO.InputHandler.CurrentMenu = 0;
|
||||
}
|
||||
int base_layer = 0;
|
||||
for (int i = (int)FinalList.size() - 1; i >= 0; i--) {
|
||||
pIO.FDL.SetLayer(base_layer);
|
||||
pIO.FDL.Merge(pMenus[FinalList[i]]->pLayout.GetDrawList());
|
||||
base_layer += 100;
|
||||
}
|
||||
pCurrentMenus.clear();
|
||||
pIO.Update();
|
||||
pIO.FDL.Optimize();
|
||||
}
|
||||
|
||||
PD_API void Context::AboutMenu(bool* show) {
|
||||
if (auto m = BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
|
||||
m->Label("Palladium UI7 " + GetVersion());
|
||||
m->Separator();
|
||||
m->Label("(c) 2023-2025 René Amthor");
|
||||
m->Label("UI7 is licensed under the MIT License.");
|
||||
m->Label("See LICENSE for more information.");
|
||||
static bool show_build;
|
||||
m->Checkbox("Show Build Info", show_build);
|
||||
if (show_build) {
|
||||
m->SeparatorText("Build Info");
|
||||
m->Label("Full Version -> " + GetVersion(true));
|
||||
m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t)));
|
||||
m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(Li::Vertex)));
|
||||
m->Label("__cplusplus -> " + std::to_string(__cplusplus));
|
||||
m->Label("Compiler -> {}",
|
||||
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());
|
||||
m->Separator();
|
||||
m->Label(
|
||||
std::format("Average {:.3f} ms/f ({:.1f} FPS)",
|
||||
((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("NumIndices: {} -> {} Tris", pIO.NumIndices,
|
||||
pIO.NumIndices / 3));
|
||||
m->Label("Menus: " + std::to_string(pMenus.size()));
|
||||
/** Section TimeTrace */
|
||||
m->SeparatorText("TimeTrace");
|
||||
if (m->BeginTreeNode("Traces (" +
|
||||
std::to_string(PD::TT::GetTraceMap().size()) + ")")) {
|
||||
for (auto& it : PD::TT::GetTraceMap()) {
|
||||
if (m->BeginTreeNode(it.second.GetID())) {
|
||||
m->Label("Diff: " + UI7DTF(it.second.GetLastDiff()));
|
||||
m->Label("Protocol Len: " +
|
||||
std::to_string(it.second.GetProtocol().GetLen()));
|
||||
m->Label("Average: " + UI7DTF(it.second.GetProtocol().GetAverage()));
|
||||
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->Label("Os Driver: {}", PD::Os::GetDriverName());
|
||||
m->Label("Renderer: {}", PD::Gfx::GetDriverName());
|
||||
if (m->BeginTreeNode(
|
||||
std::string(std::string("Input: ") + PD::Hid::GetDriverName()))) {
|
||||
/* if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasKeyboard) {
|
||||
m->Label("- Keyboard Supported");
|
||||
}
|
||||
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasMouse) {
|
||||
m->Label("- Mouse Supported");
|
||||
}
|
||||
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasTouch) {
|
||||
m->Label("- Touch Supported");
|
||||
}
|
||||
if (pIO.pCtx.Hid()->Flags & PD::HidDriver::FLags_HasGamepad) {
|
||||
m->Label("- Gamepad Supported");
|
||||
}*/
|
||||
m->EndTreeNode();
|
||||
}
|
||||
/** Section IO */
|
||||
m->SeparatorText("IO");
|
||||
if (m->BeginTreeNode("Menus (" + std::to_string(pMenus.size()) + ")")) {
|
||||
for (auto& it : pMenus) {
|
||||
if (m->BeginTreeNode(it.second->pID.GetName())) {
|
||||
m->Label("Name: " + it.second->pID.GetName());
|
||||
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->Label(std::format("Cursor: {}", it.second->pLayout.Cursor));
|
||||
if (m->BeginTreeNode(
|
||||
"ID Objects (" +
|
||||
std::to_string(it.second->pLayout.IDObjects.size()) + ")")) {
|
||||
for (auto& jt : it.second->pLayout.IDObjects) {
|
||||
m->Label(std::format("{:08X}", jt->GetID()));
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
if (m->BeginTreeNode("Active Menus (" +
|
||||
std::to_string(pCurrentMenus.size()) + ")")) {
|
||||
for (auto& it : pCurrentMenus) {
|
||||
if (m->BeginTreeNode(pMenus[it]->pID.GetName())) {
|
||||
m->Label("Name: " + pMenus[it]->pID.GetName());
|
||||
m->Label(std::format("Pos: {}", pMenus[it]->pLayout.GetPosition()));
|
||||
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));
|
||||
if (m->BeginTreeNode(
|
||||
"ID Objects (" +
|
||||
std::to_string(pMenus[it]->pLayout.IDObjects.size()) + ")")) {
|
||||
for (auto& jt : pMenus[it]->pLayout.IDObjects) {
|
||||
m->Label(std::format("{:08X}", jt->GetID()));
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
// Well this are Li Drawlists now and they do not count their stats (yet)
|
||||
/*if (m->BeginTreeNode("DrawLists (" +
|
||||
std::to_string(pIO.DrawListRegestry.size()) + ")")) {
|
||||
for (auto &it : pIO.DrawListRegestry) {
|
||||
if (m->BeginTreeNode(it.First.GetName())) {
|
||||
m->Label("Vertices: " + std::to_string(it.Second->NumVertices));
|
||||
m->Label("Indices: " + std::to_string(it.Second->NumIndices));
|
||||
m->Label("Base Layer: " + std::to_string(it.Second->Base));
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}*/
|
||||
m->Label("io->Time: " + Strings::FormatMillis(pIO.Time.Get()));
|
||||
m->Label(std::format("Delta: {:.3f}", pIO.Delta));
|
||||
m->Label(std::format("Framerate: {:.2f}", pIO.Framerate));
|
||||
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",
|
||||
pIO.InputHandler.DragTime.GetSeconds()));
|
||||
m->Label(
|
||||
std::format("DragDestination: [{}]", pIO.InputHandler.DragDestination));
|
||||
m->Label(std::format("DragSource: [{}]", pIO.InputHandler.DragSourcePos));
|
||||
m->Label(std::format("DragPos: [{}]", pIO.InputHandler.DragPosition));
|
||||
m->Label(
|
||||
std::format("DragLastPos: [{}]", pIO.InputHandler.DragLastPosition));
|
||||
EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
PD_API void UI7::Context::StyleEditor(bool* show) {
|
||||
if (auto m = BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) {
|
||||
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
|
||||
m->Separator();
|
||||
m->DragData("MenuPadding", (float*)&pIO.MenuPadding, 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("MinSliderSize", (float*)&pIO.MinSliderDragSize, 2, 1.f, 100.f);
|
||||
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);
|
||||
m->SeparatorText("Theme");
|
||||
if (m->Button("Dark")) {
|
||||
UI7::Theme::Default(pIO.Theme);
|
||||
}
|
||||
m->SameLine();
|
||||
if (m->Button("Flashbang")) {
|
||||
UI7::Theme::Flashbang(pIO.Theme);
|
||||
}
|
||||
/// Small trick to print without prefix
|
||||
#define ts(x) m->ColorEdit(std::string(#x).substr(9), pIO.Theme.GetRef(x));
|
||||
#define ts2(x) \
|
||||
m->DragData(std::string(#x).substr(9), (u8*)&pIO.Theme.GetRef(x), 4, (u8)0, \
|
||||
(u8)255);
|
||||
ts(UI7Color_Background);
|
||||
ts(UI7Color_Border);
|
||||
ts(UI7Color_Button);
|
||||
ts(UI7Color_ButtonDead);
|
||||
ts(UI7Color_ButtonActive);
|
||||
ts(UI7Color_ButtonHovered);
|
||||
ts(UI7Color_Text);
|
||||
ts(UI7Color_TextDead);
|
||||
ts(UI7Color_Header);
|
||||
ts(UI7Color_HeaderDead);
|
||||
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
|
||||
@@ -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()
|
||||
@@ -210,7 +210,6 @@ int main(int argc, char** argv) {
|
||||
ui7.GetIO().Font = &font;
|
||||
ui7.AddViewPort("Default", PD::ivec4(0, 0, 1280, 720));
|
||||
ui7.UseViewPort("Default");
|
||||
bool pMetricsWin = true;
|
||||
while (pOs->Mainloop()) {
|
||||
PD::TT::End("OSCTX::MainLoop");
|
||||
pOs->ClearViewPort();
|
||||
@@ -316,8 +315,7 @@ int main(int argc, char** argv) {
|
||||
m->PopFont();
|
||||
ui7.EndMenu();
|
||||
}
|
||||
ui7.MetricsMenu(&pMetricsWin);
|
||||
ui7.StyleEditor();
|
||||
ui7.MetricsMenu();
|
||||
PD::TT::End("BuildUI7Menus");
|
||||
PD::TT::Beg("UI7::Context::Update");
|
||||
ui7.Update();
|
||||
|
||||
Reference in New Issue
Block a user