Add FontStack to UI7 and uncomment layer lines

This commit is contained in:
2026-09-06 15:03:45 +02:00
parent 420edd0677
commit 1ae4d0cd46
13 changed files with 245 additions and 211 deletions
+201 -198
View File
@@ -1,198 +1,201 @@
#pragma once
/*
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/core/core.hpp>
#include <pd/pd_p_api.hpp>
#include <pd/ui7/io.hpp>
namespace PD {
namespace UI7 {
/**
* Container base class all Objects are based on
* @note this class can be used to create custom Objects as well
*/
class PD_API Container {
public:
Container() = default;
/**
* Constructor with pos and Size
* @param pos Container Position
* @param size Container Size
*/
Container(const fvec2& pos, const fvec2& size) : pos(pos), size(size) {}
/**
* Constructor by a vec4 box
* @param box Box containing top left and bottom right coords
*/
Container(const fvec4& box)
: pos(fvec2(box.x, box.y)), size(fvec2(box.z - box.x, box.w - box.y)) {}
~Container() = default;
/**
* Init Function Required by every Object that uses
* Render or Input functions
* @param io IO Reference
* @param l Drawlist Reference
*/
void Init(UI7::IO* io, Li::Drawlist* l) {
list = l;
this->io = io;
// this->screen = io->Ren->CurrentScreen();
}
void SetClipRect(fvec4 clip) {
pClipRect = clip;
pCLipRectUsed = true;
}
/** Setter for Position */
void SetPos(const fvec2& pos) { this->pos = pos; }
/** Setter for Size */
void SetSize(const fvec2& size) { this->size = size; }
/** Getter for Position */
fvec2 GetPos() { return pos; }
/** Getter for Size */
fvec2 GetSize() { return size; }
/**
* Get the Containers Final Position
* for Rendering and Input (if it has a parent Object)
*/
fvec2 FinalPos() {
vec2 res = pos;
if (parent) {
/// Probably should use parant->FinalPos here
res += parent->GetPos();
}
return res;
}
/** Setter for Parent Container */
void SetParent(Container* v) { parent = v; }
/** Getter for Parent Container */
Container* GetParent() { return parent; }
/** Check if Rendering can be skipped */
bool Skippable() const { return skippable; }
/** Check if the Object got a timeout (ID OBJ Relevant) */
bool Removable() const { return rem; }
/**
* Handles Scrolling by scrolling pos as well as
* Time for Remove for ID Objects
* @param scrolling Scrolling Position
* @param viewport Viewport to check if the Object is skippable
*/
void HandleScrolling(fvec2 scrolling, fvec4 viewport);
/** Template function for Input Handling */
virtual void HandleInput() {}
/** Tamplate function for Object rendering */
virtual void Draw() {}
/** Template function to update internal data (if needed) */
virtual void Update() {}
/** Template as well as base func for Pool based Containers */
virtual void Reset() {
pos = 0;
size = 0;
parent = nullptr;
id = 0;
pFlags = 0;
skippable = false;
rem = false;
inp_done = false;
pSelected = false;
pPressed = false;
pPressedTwice = false;
pCLipRectUsed = false;
pClipRect = 0;
io = nullptr;
list = nullptr;
last_use = 0;
}
/** Internal function */
void PreDraw();
/** Internal function */
void PostDraw();
/** Internal Input Handler */
void HandleInternalInput();
/**
* Function to unlock Input after Rendering is done in
* Menu::Update
* @note This is used if the Object got Input Handled directly after creation
* to not check for Inputs twice
*/
void UnlockInput() { inp_done = false; }
/** Get the Objects ID (if it is an ID object)*/
u32 GetID() const { return id; }
/**
* Set ID for ID Objects
* @param id Object ID (hashed prefix+objname+prefixed_counter)
*/
void SetID(u32 id) { this->id = id; }
/** Get a reference to IO */
UI7::IO* GetIO() { return io; }
protected:
/** used to skip Input/Render preocessing ot not*/
bool skippable = false;
/** value to check if an ID Object goes out of lifetime*/
bool rem = false;
/** Time of the last use (set by HandleScrolling)*/
u64 last_use = 0;
/** Input done or not for current frame*/
bool inp_done = false;
/** Reference to the Screen to draw the Object on*/
// Screen::Ref screen;
/** Container Position*/
fvec2 pos;
/** Container Size*/
fvec2 size;
/** Reference to the Drawlist to Draw to*/
Li::Drawlist* list = nullptr;
/** IO Reference for Renderer and Theme */
UI7::IO* io = nullptr;
/** Reference to the parent container*/
Container* parent = nullptr;
/** Object ID (0 if unused)*/
u32 id = 0;
/** Internal Flags */
u32 pFlags = 0;
/** Is Selected? */
bool pSelected = false;
/** Was Pressed */
bool pPressed = false;
/** Was Pressed Twice */
bool pPressedTwice = false;
/** ClipRect */
fvec4 pClipRect;
/** Clip Rect used */
bool pCLipRectUsed = false;
};
} // namespace UI7
} // namespace PD
#pragma once
/*
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/core/core.hpp>
#include <pd/pd_p_api.hpp>
#include <pd/ui7/io.hpp>
namespace PD {
namespace UI7 {
/**
* Container base class all Objects are based on
* @note this class can be used to create custom Objects as well
*/
class PD_API Container {
public:
Container() = default;
/**
* Constructor with pos and Size
* @param pos Container Position
* @param size Container Size
*/
Container(const fvec2& pos, const fvec2& size) : pos(pos), size(size) {}
/**
* Constructor by a vec4 box
* @param box Box containing top left and bottom right coords
*/
Container(const fvec4& box)
: pos(fvec2(box.x, box.y)), size(fvec2(box.z - box.x, box.w - box.y)) {}
~Container() = default;
/**
* Init Function Required by every Object that uses
* Render or Input functions
* @param io IO Reference
* @param l Drawlist Reference
*/
void Init(UI7::IO* io, Li::Drawlist* l) {
list = l;
this->io = io;
pFont = io->Font;
// this->screen = io->Ren->CurrentScreen();
}
void SetClipRect(fvec4 clip) {
pClipRect = clip;
pCLipRectUsed = true;
}
/** Setter for Position */
void SetPos(const fvec2& pos) { this->pos = pos; }
/** Setter for Size */
void SetSize(const fvec2& size) { this->size = size; }
/** Getter for Position */
fvec2 GetPos() { return pos; }
/** Getter for Size */
fvec2 GetSize() { return size; }
Li::Font* GetFont() { return pFont; }
/**
* Get the Containers Final Position
* for Rendering and Input (if it has a parent Object)
*/
fvec2 FinalPos() {
vec2 res = pos;
if (parent) {
/// Probably should use parant->FinalPos here
res += parent->GetPos();
}
return res;
}
/** Setter for Parent Container */
void SetParent(Container* v) { parent = v; }
/** Getter for Parent Container */
Container* GetParent() { return parent; }
/** Check if Rendering can be skipped */
bool Skippable() const { return skippable; }
/** Check if the Object got a timeout (ID OBJ Relevant) */
bool Removable() const { return rem; }
/**
* Handles Scrolling by scrolling pos as well as
* Time for Remove for ID Objects
* @param scrolling Scrolling Position
* @param viewport Viewport to check if the Object is skippable
*/
void HandleScrolling(fvec2 scrolling, fvec4 viewport);
/** Template function for Input Handling */
virtual void HandleInput() {}
/** Tamplate function for Object rendering */
virtual void Draw() {}
/** Template function to update internal data (if needed) */
virtual void Update() {}
/** Template as well as base func for Pool based Containers */
virtual void Reset() {
pos = 0;
size = 0;
parent = nullptr;
id = 0;
pFlags = 0;
skippable = false;
rem = false;
inp_done = false;
pSelected = false;
pPressed = false;
pPressedTwice = false;
pCLipRectUsed = false;
pClipRect = 0;
io = nullptr;
list = nullptr;
last_use = 0;
}
/** Internal function */
void PreDraw();
/** Internal function */
void PostDraw();
/** Internal Input Handler */
void HandleInternalInput();
/**
* Function to unlock Input after Rendering is done in
* Menu::Update
* @note This is used if the Object got Input Handled directly after creation
* to not check for Inputs twice
*/
void UnlockInput() { inp_done = false; }
/** Get the Objects ID (if it is an ID object)*/
u32 GetID() const { return id; }
/**
* Set ID for ID Objects
* @param id Object ID (hashed prefix+objname+prefixed_counter)
*/
void SetID(u32 id) { this->id = id; }
/** Get a reference to IO */
UI7::IO* GetIO() { return io; }
protected:
/** used to skip Input/Render preocessing ot not*/
bool skippable = false;
/** value to check if an ID Object goes out of lifetime*/
bool rem = false;
/** Time of the last use (set by HandleScrolling)*/
u64 last_use = 0;
/** Input done or not for current frame*/
bool inp_done = false;
/** Reference to the Screen to draw the Object on*/
// Screen::Ref screen;
/** Container Position*/
fvec2 pos;
/** Container Size*/
fvec2 size;
/** Reference to the Drawlist to Draw to*/
Li::Drawlist* list = nullptr;
/** IO Reference for Renderer and Theme */
UI7::IO* io = nullptr;
/** Reference to the parent container*/
Container* parent = nullptr;
/** Object ID (0 if unused)*/
u32 id = 0;
/** Internal Flags */
u32 pFlags = 0;
/** Is Selected? */
bool pSelected = false;
/** Was Pressed */
bool pPressed = false;
/** Was Pressed Twice */
bool pPressedTwice = false;
/** ClipRect */
fvec4 pClipRect;
/** Clip Rect used */
bool pCLipRectUsed = false;
Li::Font* pFont = nullptr;
};
} // namespace UI7
} // namespace PD
+13
View File
@@ -81,6 +81,7 @@ class PD_API IO {
u32 NumVertices = 0; ///< Debug Vertices Num
u32 NumIndices = 0; ///< Debug Indices Num
std::vector<u32> MenuOrder;
std::vector<Li::Font*> FontStack;
// Pools
PD::Pool<UI7::Label> LabelPool;
@@ -107,6 +108,18 @@ class PD_API IO {
return ViewPorts[id.RawID()];
}
void PushFont(Li::Font* f) {
FontStack.push_back(Font);
Font = f;
}
void PopFont() {
if (!FontStack.empty()) {
Font = FontStack.back();
FontStack.pop_back();
}
}
UI7::InputHandler InputHandler;
};
} // namespace UI7
+2
View File
@@ -127,6 +127,8 @@ class PD_API Layout {
void CursorInit();
void SameLine();
void CursorMove(const fvec2& size);
void PushFont(Li::Font* f) { IO.PushFont(f); }
void PopFont() { IO.PopFont(); }
bool ObjectWorkPos(fvec2& movpos);
+3
View File
@@ -119,6 +119,9 @@ class PD_API Menu {
}
Container* FindObject(u32 id) { return pLayout.FindObject(id); }
void PushFont(Li::Font* f) { pIO.PushFont(f); }
void PopFont() { pIO.PopFont(); }
void Update();
void SetSize(PD::fvec2 size) { pLayout.SetSize(size); }
+3 -2
View File
@@ -49,12 +49,13 @@ PD_API void Button::HandleInput() {
PD_API void Button::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->PathRect(FinalPos(), FinalPos() + size, io->FrameRounding);
list->PathFill(io->Theme.Get(color));
// list->LayerUp();
list->LayerUp();
list->DrawText(FinalPos() + size * 0.5 - tdim * 0.5, label.c_str(),
io->Theme.Get(UI7Color_Text));
// list->LayerDown();
list->LayerDown();
}
PD_API void Button::Update() {
+1
View File
@@ -48,6 +48,7 @@ PD_API void Checkbox::HandleInput() {
PD_API void Checkbox::Draw() {
// Assert(list.get() && io.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->PathRect(FinalPos(), FinalPos() + cbs, io->FrameRounding);
list->PathFill(io->Theme.Get(color));
if (usr_ref) {
+3
View File
@@ -44,6 +44,7 @@ PD_API void ColorEdit::HandleInput() {
PD_API void ColorEdit::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->PathRect(FinalPos(), FinalPos() + io->ItemRowHeight, io->FrameRounding);
list->PathFill(*color_ref);
list->DrawText(FinalPos() + fvec2(io->ItemSpace.x + io->ItemRowHeight, 0),
@@ -55,6 +56,7 @@ PD_API void ColorEdit::Draw() {
layout->SetPosition(FinalPos());
DynObj* r = io->DynObjPool.Allocate();
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) {
list->SetFont(thiz->GetFont());
thiz->SetSize(layout->GetSize());
// l->Layer(30);
l->PathRect(thiz->GetPos(), thiz->GetPos() + thiz->GetSize(),
@@ -65,6 +67,7 @@ PD_API void ColorEdit::Draw() {
UI7LytAdd_NoScrollHandle);
r = io->DynObjPool.Allocate();
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) {
list->SetFont(thiz->GetFont());
l->PathRect(thiz->FinalPos(), thiz->FinalPos() + io->ItemRowHeight,
io->FrameRounding);
l->PathFill(*color_ref);
+3 -2
View File
@@ -86,11 +86,11 @@ PD_API void DragData<T>::Draw() {
FinalPos() + fvec2(off_x, 0) + td + io->FramePadding,
io->FrameRounding);
list->PathFill(io->Theme.Get(UI7Color_Button));
// list->LayerUp();
list->LayerUp();
list->DrawTextEx(FinalPos() + fvec2(off_x, 0), p.c_str(),
io->Theme.Get(UI7Color_Text), LiTextFlags_AlignMid,
td + io->FramePadding);
// list->LayerDown();
list->LayerDown();
off_x += td.x + io->ItemSpace.x + io->FramePadding.x;
}
list->DrawText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5),
@@ -101,6 +101,7 @@ template <typename T>
PD_API void DragData<T>::Update() {
// Assert(io.get(), "Did you run Container::Init correctly?");
// Probably need to find a faster solution (caching sizes calculated here)
list->SetFont(GetFont());
float off_x = 0;
for (size_t i = 0; i < elm_count; i++) {
std::string p;
+2 -2
View File
@@ -29,11 +29,11 @@ PD_API void Image::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// Assert(img.get(), "Image is nullptr!");
// io->Ren->OnScreen(screen);
// list->LayerUp();
list->LayerUp();
list->BindTexture(img);
list->DrawRectFilled(FinalPos(), newsize, 0xffffffff);
list->UnbindTexture();
// list->LayerDown();
list->LayerDown();
}
} // namespace UI7
} // namespace PD
+1
View File
@@ -28,6 +28,7 @@ namespace UI7 {
PD_API void Label::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
list->DrawTextEx(FinalPos(), label.c_str(), io->Theme.Get(UI7Color_Text),
LiTextFlags_NoOOS,
PD::fvec2(0, io->CurrentViewPort.pSize.w));
+3 -2
View File
@@ -70,6 +70,7 @@ template <typename T>
PD_API void Slider<T>::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
list->SetFont(GetFont());
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", *data, precision);
@@ -84,10 +85,10 @@ PD_API void Slider<T>::Draw() {
FinalPos() + fvec2(slp + slw - 2, td.y - 2) + io->FramePadding,
io->FrameRounding);
list->PathFill(io->Theme.Get(UI7Color_ButtonActive));
// list->LayerUp();
list->LayerUp();
list->DrawTextEx(FinalPos(), p.c_str(), io->Theme.Get(UI7Color_Text),
LiTextFlags_AlignMid, fvec2(width, td.y) + io->FramePadding);
// list->LayerDown();
list->LayerDown();
list->DrawText(FinalPos() + fvec2(width + io->FramePadding.x * 2.f,
io->FramePadding.y * 0.5),
label.c_str(), io->Theme.Get(UI7Color_Text));
+8 -5
View File
@@ -104,6 +104,7 @@ PD_API void Menu::SeparatorText(const std::string& label) {
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
UI7::Container* self) {
l->SetFont(self->GetFont());
fvec2 size = self->GetSize();
fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale);
fvec2 pos = self->FinalPos();
@@ -218,7 +219,7 @@ PD_API void Menu::DrawBaseLayout() {
if (!(Flags & UI7MenuFlags_NoResize)) {
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
// //l->Layer(1);
l->SetLayer(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));
@@ -234,7 +235,7 @@ PD_API void Menu::DrawBaseLayout() {
/** Background */
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) {
// l->Layer(0);
l->SetLayer(0);
l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f,
LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot);
l->PathFill(io->Theme.Get(UI7Color_Background));
@@ -252,11 +253,12 @@ PD_API void Menu::DrawBaseLayout() {
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj(
[=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) {
// l->Layer(20);
l->SetFont(self->GetFont());
l->SetLayer(20);
/** Header Bar */
l->DrawRectFilled(self->FinalPos(), self->GetSize(),
io->Theme.Get(UI7Color_Header));
// l->Layer(21);
l->SetLayer(21);
/** Inline if statement to shift the Text if collapse sym is shown */
/** What the hell is this code btw (didn't found a better way) */
l->DrawText(self->FinalPos() +
@@ -277,7 +279,7 @@ PD_API void Menu::DrawBaseLayout() {
*r = UI7::DynObj([=, this](UI7::IO* io, Li::Drawlist* l,
UI7::Container* self) {
/** This sym actually requires layer 21 (i dont know why) */
// l->Layer(21);
l->SetLayer(21);
/**
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
*/
@@ -353,6 +355,7 @@ PD_API bool Menu::BeginTreeNode(const ID& id) {
// Object
DynObj* r = pIO.DynObjPool.Allocate();
*r = UI7::DynObj([=, this](IO* io, Li::Drawlist* l, Container* self) {
l->SetFont(self->GetFont());
fvec2 ts = self->FinalPos() + fvec2(0, 7);
fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)};
if (n->second) {
+2
View File
@@ -304,6 +304,7 @@ int main(int argc, char** argv) {
ui7.EndMenu();
}
if (auto m = ui7.BeginMenu("LI DBG INFO")) {
m->PushFont(&debug_font);
m->Label("Gfx Driver: {}", PD::Gfx::GetDriverName());
m->Separator();
m->Label("LI Draw Comamnds: {}", PD::Gfx::GetNumCommands());
@@ -311,6 +312,7 @@ int main(int argc, char** argv) {
m->Label("GFX Vertices: {}", PD::Gfx::GetNumVertices());
m->Label("GFX Triangles: {}", PD::Gfx::GetNumVertices() / 3);
m->Label("GFX Indices: {}", PD::Gfx::GetNumIndices());
m->PopFont();
ui7.EndMenu();
}
ui7.MetricsMenu();