6 Commits
Author SHA1 Message Date
tobid7 e03670a0c5 Add a Drag Slider to UI7 2026-01-22 06:31:45 +01:00
tobid7 931e02aefb Move CmdPool code to a source file 2026-01-22 19:25:01 +01:00
tobid7 0db4953125 Reimplement list sorting and Fix UI7 Layers 2026-01-22 16:34:46 +01:00
tobid7 2b7d25cf06 Update
- Added DestroyTex to 3ds backend
- Added Size() -> ivec2 to PD::Image
- Added CmdPool Copy as well as DrawList Copy (Static rendering)
- Added == ooperator for Rect
- Added UI7 Frame Rounding
- Fix UI7 Image usage withour size or uv
- Added New way to use BeginMenu
2026-01-18 19:25:50 +01:00
tobid7 0ef6d34435 Refactor the Command / DrawList System
Use Command Pool instead of always allocating.
This gives us e big performance diffrence on the 3ds
Fixed IDS of ui7 for now
2026-01-16 12:13:48 +01:00
tobid7 eb5d5f9974 backend updates
pd-3ds:
Add support for RGB565 textures
pd-desktop:
Add support for A8 textures
Add glfw callback chain to not break other libs using the same callback
2026-01-05 14:37:57 +01:00
35 changed files with 529 additions and 151 deletions
+2 -2
View File
@@ -42,13 +42,13 @@ class GfxC3D : public GfxDriver {
void Deinit() override; void Deinit() override;
void NewFrame() override; void NewFrame() override;
void BindTex(PD::Li::TexAddress addr) override; void BindTex(PD::Li::TexAddress addr) override;
void RenderDrawData( void RenderDrawData(const PD::Li::CmdPool& Commands) override;
const std::vector<PD::Li::Command::Ref>& Commands) override;
PD::Li::Texture::Ref LoadTex( PD::Li::Texture::Ref LoadTex(
const std::vector<PD::u8>& pixels, int w, int h, const std::vector<PD::u8>& pixels, int w, int h,
PD::Li::Texture::Type type = PD::Li::Texture::Type::RGBA32, PD::Li::Texture::Type type = PD::Li::Texture::Type::RGBA32,
PD::Li::Texture::Filter filter = PD::Li::Texture::Filter filter =
PD::Li::Texture::Filter::LINEAR) override; PD::Li::Texture::Filter::LINEAR) override;
void DestroyTex(PD::Li::Texture::Ref tex) override;
std::vector<Li::Vertex, LinearAllocator<Li::Vertex>> VertexBuffer; std::vector<Li::Vertex, LinearAllocator<Li::Vertex>> VertexBuffer;
std::vector<u16, LinearAllocator<u16>> IndexBuffer; std::vector<u16, LinearAllocator<u16>> IndexBuffer;
+21 -9
View File
@@ -95,6 +95,11 @@ void FragCfg(GPU_TEXCOLOR clr) {
C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE); C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE); C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE);
break; break;
case GPU_RGB565:
C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0);
C3D_TexEnvFunc(env, C3D_RGB, GPU_MODULATE);
C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE);
break;
default: default:
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0); C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0);
@@ -142,7 +147,7 @@ void GfxC3D::BindTex(PD::Li::TexAddress addr) {
C3D_TexBind(0, reinterpret_cast<C3D_Tex*>(addr)); C3D_TexBind(0, reinterpret_cast<C3D_Tex*>(addr));
} }
void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) { void GfxC3D::RenderDrawData(const PD::Li::CmdPool& Commands) {
shaderProgramUse(&Shader); shaderProgramUse(&Shader);
C3D_SetAttrInfo(&ShaderInfo); C3D_SetAttrInfo(&ShaderInfo);
C3D_Mtx proj; C3D_Mtx proj;
@@ -151,20 +156,20 @@ void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
// Mat4 proj = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f); // Mat4 proj = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f);
// C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, (C3D_Mtx*)&proj); // C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, (C3D_Mtx*)&proj);
size_t index = 0; size_t index = 0;
while (index < Commands.size()) { while (index < Commands.Size()) {
PD::Li::Texture::Ref Tex = Commands[index]->Tex; PD::Li::Texture::Ref Tex = Commands.GetCmd(index)->Tex;
if (!Tex) { if (!Tex) {
index++; index++;
continue; continue;
} }
bool ScissorEnabled = Commands[index]->ScissorOn; bool ScissorEnabled = Commands.GetCmd(index)->ScissorOn;
ivec4 ScissorRect = Commands[index]->ScissorRect; ivec4 ScissorRect = Commands.GetCmd(index)->ScissorRect;
size_t StartIndex = CurrentIndex; size_t StartIndex = CurrentIndex;
while (index < Commands.size() && Commands[index]->Tex == Tex && while (index < Commands.Size() && Commands.GetCmd(index)->Tex == Tex &&
Commands[index]->ScissorOn == ScissorEnabled && Commands.GetCmd(index)->ScissorOn == ScissorEnabled &&
Commands[index]->ScissorRect == ScissorRect) { Commands.GetCmd(index)->ScissorRect == ScissorRect) {
auto c = Commands[index].get(); auto c = Commands.GetCmd(index);
for (size_t i = 0; i < c->IndexBuffer.size(); i++) { for (size_t i = 0; i < c->IndexBuffer.size(); i++) {
IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.at(i); IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.at(i);
} }
@@ -255,4 +260,11 @@ PD::Li::Texture::Ref GfxC3D::LoadTex(const std::vector<PD::u8>& pixels, int w,
<< std::endl; << std::endl;
return res; return res;
} }
void GfxC3D::DestroyTex(PD::Li::Texture::Ref tex) {
C3D_Tex* t = reinterpret_cast<C3D_Tex*>(tex->Address);
C3D_TexDelete(t);
delete t;
tex->Address = 0;
}
} // namespace PD } // namespace PD
@@ -44,8 +44,7 @@ class GfxGL2 : public GfxDriver {
void Deinit() override; void Deinit() override;
void NewFrame() override; void NewFrame() override;
void BindTex(PD::Li::TexAddress addr) override; void BindTex(PD::Li::TexAddress addr) override;
void RenderDrawData( void RenderDrawData(const Li::CmdPool& Commands) override;
const std::vector<PD::Li::Command::Ref>& Commands) override;
PD::Li::Texture::Ref LoadTex( PD::Li::Texture::Ref LoadTex(
const std::vector<PD::u8>& pixels, int w, int h, const std::vector<PD::u8>& pixels, int w, int h,
PD::Li::Texture::Type type = PD::Li::Texture::Type::RGBA32, PD::Li::Texture::Type type = PD::Li::Texture::Type::RGBA32,
@@ -57,6 +56,7 @@ class GfxGL2 : public GfxDriver {
GLuint Shader; GLuint Shader;
GLuint pLocProjection; GLuint pLocProjection;
GLuint pLocTex; GLuint pLocTex;
GLuint pLocAlfa;
GLuint VBO, IBO; GLuint VBO, IBO;
}; };
} // namespace PD } // namespace PD
@@ -64,6 +64,7 @@ class HidGLFW : public HidDriver {
GLFWwindow* Window; GLFWwindow* Window;
int PrevState; int PrevState;
std::unordered_map<int, int> PrevStates; std::unordered_map<int, int> PrevStates;
static GLFWcharfun pOldTextCB;
static std::string* pText; static std::string* pText;
bool pInTextMode = false; bool pInTextMode = false;
PD::u64 pLastUpdate = 0; PD::u64 pLastUpdate = 0;
+20 -11
View File
@@ -53,10 +53,15 @@ const char* frag_shader = R"(
varying vec4 oColor; varying vec4 oColor;
uniform sampler2D tex; uniform sampler2D tex;
uniform bool alfa;
void main() { void main() {
vec4 tc = texture2D(tex, oUV); vec4 tc = texture2D(tex, oUV);
gl_FragColor = tc*oColor; if (alfa) {
gl_FragColor = vec4(oColor.rgb, tc.a * oColor.a);
} else {
gl_FragColor = tc * oColor;
}
} }
)"; )";
@@ -138,6 +143,7 @@ void GfxGL2::Init() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
pLocTex = glGetUniformLocation(Shader, "tex"); pLocTex = glGetUniformLocation(Shader, "tex");
pLocAlfa = glGetUniformLocation(Shader, "alfa");
pLocProjection = glGetUniformLocation(Shader, "projection"); pLocProjection = glGetUniformLocation(Shader, "projection");
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -172,24 +178,27 @@ void GfxGL2::BindTex(PD::Li::TexAddress addr) {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, (GLuint)addr); glBindTexture(GL_TEXTURE_2D, (GLuint)addr);
glUniform1i(pLocTex, 0); glUniform1i(pLocTex, 0);
GLint fmt = 0;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
glUniform1i(pLocAlfa, fmt == GL_ALPHA);
} }
void GfxGL2::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) { void GfxGL2::RenderDrawData(const Li::CmdPool& Commands) {
size_t index = 0; size_t index = 0;
while (index < Commands.size()) { while (index < Commands.Size()) {
PD::Li::Texture::Ref Tex = Commands[index]->Tex; PD::Li::Texture::Ref Tex = Commands.GetCmd(index)->Tex;
if (!Tex) { if (!Tex) {
index++; index++;
continue; continue;
} }
size_t StartIndex = CurrentIndex; size_t StartIndex = CurrentIndex;
bool ScissorOn = Commands[index]->ScissorOn; bool ScissorOn = Commands.GetCmd(index)->ScissorOn;
ivec4 ScissorRect = Commands[index]->ScissorRect; ivec4 ScissorRect = Commands.GetCmd(index)->ScissorRect;
while (index < Commands.size() && Commands[index]->Tex == Tex && while (index < Commands.Size() && Commands.GetCmd(index)->Tex == Tex &&
Commands[index]->ScissorOn == ScissorOn && Commands.GetCmd(index)->ScissorOn == ScissorOn &&
Commands[index]->ScissorRect == ScissorRect) { Commands.GetCmd(index)->ScissorRect == ScissorRect) {
auto c = Commands[index].get(); auto c = Commands.GetCmd(index);
for (size_t i = 0; i < c->IndexBuffer.size(); i++) { for (size_t i = 0; i < c->IndexBuffer.size(); i++) {
IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.at(i); IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.at(i);
} }
+13 -3
View File
@@ -24,11 +24,21 @@ SOFTWARE.
#include <pd-desktop/bknd-hid.hpp> #include <pd-desktop/bknd-hid.hpp>
namespace PD { namespace PD {
std::string* HidGLFW::pText; std::string* HidGLFW::pText = nullptr;
GLFWcharfun HidGLFW::pOldTextCB = nullptr;
// Default Call back (If no Text input is requsted) // Default Call back (If no Text input is requsted)
void NullTextCB(GLFWwindow* win, unsigned int c) {} void NullTextCB(GLFWwindow* win, unsigned int c) {
// Chain
if (HidGLFW::pOldTextCB) {
HidGLFW::pOldTextCB(win, c);
}
}
// Text callback if requested // Text callback if requested
void TextCB(GLFWwindow* win, unsigned int c) { void TextCB(GLFWwindow* win, unsigned int c) {
// Chain
if (HidGLFW::pOldTextCB) {
HidGLFW::pOldTextCB(win, c);
}
if (!HidGLFW::pText) { if (!HidGLFW::pText) {
return; return;
} }
@@ -36,7 +46,7 @@ void TextCB(GLFWwindow* win, unsigned int c) {
} }
HidGLFW::HidGLFW(GLFWwindow* win) : HidDriver("HidGLFW") { HidGLFW::HidGLFW(GLFWwindow* win) : HidDriver("HidGLFW") {
Window = win; Window = win;
glfwSetCharCallback(Window, NullTextCB); HidGLFW::pOldTextCB = glfwSetCharCallback(Window, NullTextCB);
Flags |= Flags_HasKeyboard; Flags |= Flags_HasKeyboard;
Flags |= Flags_HasMouse; Flags |= Flags_HasMouse;
pBinds[GLFW_MOUSE_BUTTON_LEFT] = Touch; pBinds[GLFW_MOUSE_BUTTON_LEFT] = Touch;
+10
View File
@@ -53,6 +53,16 @@ SOFTWARE.
return std::make_shared<x>(std::forward<Args>(args)...); \ return std::make_shared<x>(std::forward<Args>(args)...); \
} }
#define PD_RAW(x) \
using Ref = x*; \
template <typename... Args> \
static Ref New(Args&&... args) { \
x* v = new x; \
new (v) x(std::forward<Args>(args)...); \
return v; \
} \
static void Delete(Ref ref) { delete ref; }
#define PD_UNIQUE(x) \ #define PD_UNIQUE(x) \
using Ref = std::unique_ptr<x>; \ using Ref = std::unique_ptr<x>; \
template <typename... Args> \ template <typename... Args> \
+6 -2
View File
@@ -49,7 +49,7 @@ class GfxDriver {
virtual void BindTex(Li::TexAddress addr) {} virtual void BindTex(Li::TexAddress addr) {}
virtual void RenderDrawData(const std::vector<Li::Command::Ref>& Commands) {} virtual void RenderDrawData(const Li::CmdPool& Commands) {}
void SetViewPort(const ivec2& vp) { ViewPort = vp; } void SetViewPort(const ivec2& vp) { ViewPort = vp; }
@@ -61,6 +61,8 @@ class GfxDriver {
return nullptr; return nullptr;
} }
virtual void DestroyTex(PD::Li::Texture::Ref tex) {}
Li::Texture::Ref GetSolidTex() { return pSolid; } Li::Texture::Ref GetSolidTex() { return pSolid; }
const std::string pName = "NullGfx"; const std::string pName = "NullGfx";
@@ -96,7 +98,7 @@ class Gfx {
static void SetViewPort(const ivec2& vp) { pGfx->SetViewPort(vp); } static void SetViewPort(const ivec2& vp) { pGfx->SetViewPort(vp); }
static void SetViewPort(int w, int h) { pGfx->SetViewPort(PD::ivec2(w, h)); } static void SetViewPort(int w, int h) { pGfx->SetViewPort(PD::ivec2(w, h)); }
static void RenderDrawData(const std::vector<Li::Command::Ref>& Commands) { static void RenderDrawData(const Li::CmdPool& Commands) {
pGfx->RenderDrawData(Commands); pGfx->RenderDrawData(Commands);
} }
@@ -108,6 +110,8 @@ class Gfx {
return pGfx->LoadTex(pixels, w, h, type, filter); return pGfx->LoadTex(pixels, w, h, type, filter);
} }
static void DestroyTex(Li::Texture::Ref tex) { pGfx->DestroyTex(tex); }
static Li::Texture::Ref GetSolidTex() { return pGfx->GetSolidTex(); } static Li::Texture::Ref GetSolidTex() { return pGfx->GetSolidTex(); }
static GfxDriver::Ref pGfx; static GfxDriver::Ref pGfx;
+1
View File
@@ -57,6 +57,7 @@ class PD_IMAGE_API Image {
int Width() const { return pWidth; } int Width() const { return pWidth; }
int Height() const { return pHeight; } int Height() const { return pHeight; }
ivec2 Size() const { return ivec2(pWidth, pHeight); }
Format Fmt() const { return pFmt; } Format Fmt() const { return pFmt; }
void FlipVertical(); void FlipVertical();
+40 -1
View File
@@ -24,6 +24,7 @@ SOFTWARE.
*/ */
#include <pd/core/core.hpp> #include <pd/core/core.hpp>
#include <pd/lithium/pd_p_api.hpp>
#include <pd/lithium/texture.hpp> #include <pd/lithium/texture.hpp>
#include <pd/lithium/vertex.hpp> #include <pd/lithium/vertex.hpp>
@@ -34,7 +35,7 @@ class Command {
Command() = default; Command() = default;
~Command() = default; ~Command() = default;
PD_UNIQUE(Command); PD_RAW(Command);
Command& AddIdx(const u16& idx) { Command& AddIdx(const u16& idx) {
IndexBuffer.push_back(VertexBuffer.size() + idx); IndexBuffer.push_back(VertexBuffer.size() + idx);
@@ -52,6 +53,16 @@ class Command {
return *this; return *this;
} }
void Clear() {
VertexBuffer.clear();
IndexBuffer.clear();
Index = 0;
Layer = 0;
Tex = 0;
ScissorOn = false;
ScissorRect = ivec4();
}
std::vector<Vertex> VertexBuffer; std::vector<Vertex> VertexBuffer;
std::vector<u16> IndexBuffer; std::vector<u16> IndexBuffer;
ivec4 ScissorRect; ivec4 ScissorRect;
@@ -60,5 +71,33 @@ class Command {
int Index; int Index;
Texture::Ref Tex; Texture::Ref Tex;
}; };
class PD_LITHIUM_API CmdPool {
public:
CmdPool() {}
~CmdPool() {}
Command::Ref NewCmd();
void Init(size_t initial_size);
void Deinit();
void Resize(size_t nulen);
void Reset();
Command::Ref GetCmd(size_t idx) const;
Command::Ref GetCmd(size_t idx);
size_t Size() const;
size_t Cap() const;
void Merge(CmdPool& p);
void Copy(CmdPool& p);
void Sort();
private:
static bool pTheOrder(const Command::Ref& a, const Command::Ref& b);
friend class DrawList;
Command::Ref* begin() { return &pPool[0]; }
Command::Ref* end() { return &pPool[pPoolIdx]; }
std::vector<Command::Ref> pPool;
u32 pPoolIdx = 0;
int Layer = 0;
};
} // namespace Li } // namespace Li
} // namespace PD } // namespace PD
+9 -11
View File
@@ -48,8 +48,8 @@ namespace PD {
namespace Li { namespace Li {
class PD_LITHIUM_API DrawList { class PD_LITHIUM_API DrawList {
public: public:
DrawList() { DrawSolid(); } DrawList(int initial_size = 64);
~DrawList() { pDrawList.clear(); } ~DrawList();
/** Require Copy and Move Constructors */ /** Require Copy and Move Constructors */
@@ -81,13 +81,12 @@ class PD_LITHIUM_API DrawList {
*/ */
void Optimize(); void Optimize();
Command::Ref PreGenerateCmd(); Command::Ref GetNewCmd();
void AddCommand(Command::Ref v);
void Clear(); void Clear();
void Layer(int l) { this->pLayer = l; } void Layer(int l) { this->pPool.Layer = l; }
int Layer() { return this->pLayer; } int Layer() { return this->pPool.Layer; }
void LayerUp() { this->pLayer++; } void LayerUp() { this->pPool.Layer++; }
void LayerDown() { this->pLayer--; } void LayerDown() { this->pPool.Layer--; }
void SetFont(Font::Ref font) { pCurrentFont = font; } void SetFont(Font::Ref font) { pCurrentFont = font; }
void SetFontScale(float scale) { pFontScale = scale; } void SetFontScale(float scale) { pFontScale = scale; }
@@ -206,18 +205,17 @@ class PD_LITHIUM_API DrawList {
} }
pClipRects.pop(); pClipRects.pop();
} }
const std::vector<Command::Ref>& Data() const { return pDrawList; } const CmdPool& Data() const { return pPool; }
/** One linear Clip rect Setup */ /** One linear Clip rect Setup */
void pClipCmd(Command* cmd); void pClipCmd(Command* cmd);
/** Data Section */ /** Data Section */
std::stack<fvec4> pClipRects; std::stack<fvec4> pClipRects;
int pLayer;
float pFontScale = 0.7f; float pFontScale = 0.7f;
Font::Ref pCurrentFont; Font::Ref pCurrentFont;
Texture::Ref CurrentTex; Texture::Ref CurrentTex;
std::vector<Command::Ref> pDrawList; CmdPool pPool;
std::vector<fvec2> pPath; std::vector<fvec2> pPath;
u32 pNumIndices = 0; u32 pNumIndices = 0;
u32 pNumVertices = 0; u32 pNumVertices = 0;
+2 -2
View File
@@ -93,8 +93,8 @@ class PD_LITHIUM_API Font {
/** /**
* Extended Draw Text Function that vreates a Command List * Extended Draw Text Function that vreates a Command List
*/ */
void CmdTextEx(std::vector<Command::Ref>& cmds, const fvec2& pos, u32 color, void CmdTextEx(CmdPool& cmds, const fvec2& pos, u32 color, float scale,
float scale, const std::string& text, LiTextFlags flags = 0, const std::string& text, LiTextFlags flags = 0,
const fvec2& box = 0); const fvec2& box = 0);
/** /**
+2
View File
@@ -131,6 +131,8 @@ class Rect {
return *this; return *this;
} }
bool operator==(Rect& r) { return Top == r.Top && Bot == r.Bot; }
void SwapVec2XY() { void SwapVec2XY() {
Top.SwapXY(); Top.SwapXY();
Top.SwapZW(); Top.SwapZW();
+7 -6
View File
@@ -39,13 +39,14 @@ class PD_UI7_API Image : public Container {
*/ */
Image(Li::Texture::Ref img, fvec2 size = 0.f, Li::Rect uv = fvec4(0.f)) { Image(Li::Texture::Ref img, fvec2 size = 0.f, Li::Rect uv = fvec4(0.f)) {
this->img = img; this->img = img;
this->newsize = size; if (size == fvec2(0.f)) {
this->cuv = uv; size = img->GetSize();
if (size.x != 0 || size.y != 0) {
this->SetSize(size);
} else {
this->SetSize(fvec2(img->GetSize().x, img->GetSize().y));
} }
if (uv == Li::Rect(fvec4(0.f))) {
uv = img->GetUV();
}
this->cuv = uv;
this->newsize = size;
} }
~Image() = default; ~Image() = default;
+91
View File
@@ -0,0 +1,91 @@
#pragma once
/*
MIT License
Copyright (c) 2024 - 2025 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/container/container.hpp>
#include <pd/ui7/io.hpp>
namespace PD {
namespace UI7 {
/**
* Slider Object can take a datatype or a list
* and modifys these by moving left or right when dragging
*/
template <typename T>
class PD_UI7_API Slider : public Container {
public:
/**
* Constructor
* @param label Label of the Button
* @param data Data reference (Supported types can be seen in Slider.cpp)
* @param num_elms Number of Array elements (for exaple with use ofvec4)
* @param io IO Reference
* @param min minimum number using Minimum limit
* @param max Maximum number set by max limit by default
* @param step To set the modifier for drag movement
* @param precision for float and double to set precision
*/
Slider(const std::string& label, T* data, UI7::IO::Ref io,
T min = std::numeric_limits<T>::min(),
T max = std::numeric_limits<T>::max(), int precision = 1) {
// PD::Assert(data != nullptr, "Input Data Address is null!");
this->label = label;
this->data = data;
this->min = min;
this->max = max;
this->precision = precision;
this->width = io->CurrentViewPort.z * 0.3f;
this->tdim = io->Font->GetTextBounds(label, io->FontScale);
}
~Slider() = default;
/** Als ob das funktioniert... */
PD_SHARED(Slider<T>);
/**
* Override for the Input Handler
* @note This function is usally called by Menu::Update
*/
void HandleInput() override;
/**
* Override for the Rendering Handler
* @note This function is usally called by Menu::Update
* */
void Draw() override;
/** Function to Update Size if framepadding changes */
void Update() override;
private:
fvec2 tdim; ///< Text size
float width; ///< Size
std::string label; ///< Label of the Button
T* data;
T min;
T max;
int precision = 1;
float slw = 0.f; // silider drag width (calculated in update)
float slp = 0.f; // silider drag pos (calculated in update)
};
} // namespace UI7
} // namespace PD
+1
View File
@@ -30,3 +30,4 @@ SOFTWARE.
#include <pd/ui7/container/dynobj.hpp> #include <pd/ui7/container/dynobj.hpp>
#include <pd/ui7/container/image.hpp> #include <pd/ui7/container/image.hpp>
#include <pd/ui7/container/label.hpp> #include <pd/ui7/container/label.hpp>
#include <pd/ui7/container/slider.hpp>
+5 -3
View File
@@ -38,6 +38,7 @@ class ID {
*/ */
ID(const std::string& text) { ID(const std::string& text) {
pID = PD::Strings::FastHash(text); pID = PD::Strings::FastHash(text);
// pStrName = text;
pName = text; pName = text;
} }
/** /**
@@ -56,7 +57,7 @@ class ID {
~ID() = default; ~ID() = default;
/** Get The ID Initial Name */ /** Get The ID Initial Name */
constexpr const std::string_view& GetNameView() const { return pName; } // constexpr const std::string_view& GetNameView() const { return pName; }
const std::string GetName() const { return std::string(pName); } const std::string GetName() const { return std::string(pName); }
/** Getter for the raw 32bit int id */ /** Getter for the raw 32bit int id */
@@ -65,8 +66,9 @@ class ID {
/** Return the ID when casting to u32 */ /** Return the ID when casting to u32 */
constexpr operator u32() const { return pID; } constexpr operator u32() const { return pID; }
u32 pID; ///< Hash of the name u32 pID; ///< Hash of the name
std::string_view pName; ///< Name std::string pName; ///< Name
// std::string pStrName; ///< Keep this stringview alive
}; };
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD
+1
View File
@@ -73,6 +73,7 @@ class PD_UI7_API IO {
UI7::Theme::Ref Theme; UI7::Theme::Ref Theme;
fvec2 MenuPadding = 5.f; fvec2 MenuPadding = 5.f;
fvec2 FramePadding = 5.f; fvec2 FramePadding = 5.f;
float FrameRounding = 0.f;
fvec2 ItemSpace = vec2(5.f, 2.f); fvec2 ItemSpace = vec2(5.f, 2.f);
fvec2 MinSliderDragSize = 10.f; // Min height (Vt) and Min Width (Hz) fvec2 MinSliderDragSize = 10.f; // Min height (Vt) and Min Width (Hz)
bool ShowMenuBorder = true; bool ShowMenuBorder = true;
+14
View File
@@ -25,6 +25,7 @@ SOFTWARE.
*/ */
#include <pd/core/core.hpp> #include <pd/core/core.hpp>
#include <pd/ui7/containers.hpp>
#include <pd/ui7/io.hpp> #include <pd/ui7/io.hpp>
#include <pd/ui7/layout.hpp> #include <pd/ui7/layout.hpp>
#include <pd/ui7/pd_p_api.hpp> #include <pd/ui7/pd_p_api.hpp>
@@ -92,6 +93,18 @@ class PD_UI7_API Menu {
} }
pLayout->AddObject(r); pLayout->AddObject(r);
} }
template <typename T>
void Slider(const std::string &label, T *data,
T min = std::numeric_limits<T>::min(),
T max = std::numeric_limits<T>::max(), int precision = 1) {
u32 id = Strings::FastHash("drd" + label + std::to_string((uintptr_t)data));
Container::Ref r = pLayout->FindObject(id);
if (!r) {
r = UI7::Slider<T>::New(label, data, pIO, min, max, precision);
r->SetID(id);
}
pLayout->AddObject(r);
}
void SameLine() { pLayout->SameLine(); } void SameLine() { pLayout->SameLine(); }
void Separator(); void Separator();
void SeparatorText(const std::string &label); void SeparatorText(const std::string &label);
@@ -107,6 +120,7 @@ class PD_UI7_API Menu {
void AddObjectEx(PD::UI7::Container::Ref obj, PD::u32 flags) { void AddObjectEx(PD::UI7::Container::Ref obj, PD::u32 flags) {
pLayout->AddObjectEx(obj, flags); pLayout->AddObjectEx(obj, flags);
} }
Container::Ref FindObject(u32 id) { return pLayout->FindObject(id); }
void Update(); void Update();
+2 -1
View File
@@ -59,7 +59,8 @@ class PD_UI7_API Context {
void AddViewPort(const ID& id, const ivec4& vp); void AddViewPort(const ID& id, const ivec4& vp);
void UseViewPort(const ID& id); void UseViewPort(const ID& id);
void Update(); void Update();
bool BeginMenu(const ID& id, UI7MenuFlags flags = 0, bool* pShow = nullptr); Menu::Ref BeginMenu(const ID& id, UI7MenuFlags flags = 0,
bool* pShow = nullptr);
Menu::Ref CurrentMenu() { return pCurrent; } Menu::Ref CurrentMenu() { return pCurrent; }
void EndMenu(); void EndMenu();
void AboutMenu(bool* show = nullptr); void AboutMenu(bool* show = nullptr);
+1
View File
@@ -5,6 +5,7 @@ project(pd-lithium LANGUAGES CXX VERSION 0.6.0)
option(PD_LI_INCLUDE_FONTS "Include Fonts" OFF) option(PD_LI_INCLUDE_FONTS "Include Fonts" OFF)
set(SRC set(SRC
source/command.cpp
source/drawlist.cpp source/drawlist.cpp
source/font.cpp source/font.cpp
source/fonts.cpp source/fonts.cpp
+80
View File
@@ -0,0 +1,80 @@
#include <pd/lithium/command.hpp>
PD_LITHIUM_API PD::Li::Command::Ref PD::Li::CmdPool::NewCmd() {
if (pPoolIdx >= pPool.size()) {
Resize(pPool.size() + 128);
}
Command::Ref nu = pPool[pPoolIdx++];
nu->Layer = Layer;
nu->Index = pPoolIdx - 1;
return nu;
}
PD_LITHIUM_API void PD::Li::CmdPool::Init(size_t initial_size) {
Resize(initial_size);
}
PD_LITHIUM_API void PD::Li::CmdPool::Deinit() {
for (auto it : pPool) {
Command::Delete(it);
}
pPool.clear();
}
PD_LITHIUM_API void PD::Li::CmdPool::Resize(size_t nulen) {
if (nulen <= pPool.size()) {
return; // no idea yet
}
size_t oldlen = pPool.size();
pPool.resize(nulen);
for (size_t i = oldlen; i < pPool.size(); i++) {
pPool[i] = Command::New();
}
}
PD_LITHIUM_API void PD::Li::CmdPool::Reset() {
for (u32 i = 0; i < pPoolIdx; i++) {
pPool[i]->Clear();
}
pPoolIdx = 0;
}
PD::Li::Command::Ref PD::Li::CmdPool::GetCmd(size_t idx) const {
return pPool[idx];
}
PD::Li::Command::Ref PD::Li::CmdPool::GetCmd(size_t idx) { return pPool[idx]; }
size_t PD::Li::CmdPool::Size() const { return pPoolIdx; }
size_t PD::Li::CmdPool::Cap() const { return pPool.size(); }
PD_LITHIUM_API void PD::Li::CmdPool::Merge(CmdPool& p) {
Copy(p);
p.Reset();
}
PD_LITHIUM_API void PD::Li::CmdPool::Copy(CmdPool& p) {
if (pPoolIdx + p.Size() > pPool.size()) {
Resize(pPoolIdx + p.Size());
}
for (size_t i = 0; i < p.Size(); i++) {
size_t idx = pPoolIdx++;
*pPool[idx] = *p.GetCmd(i);
pPool[idx]->Index = idx;
pPool[idx]->Layer += Layer;
}
}
PD_LITHIUM_API void PD::Li::CmdPool::Sort() {
std::sort(begin(), end(), pTheOrder);
}
PD_LITHIUM_API bool PD::Li::CmdPool::pTheOrder(const Command::Ref& a,
const Command::Ref& b) {
if (a->Layer == b->Layer) {
if (a->Tex == b->Tex) {
return a->Index < b->Index;
}
return a->Tex < b->Tex;
}
return a->Layer < b->Layer;
}
+33 -38
View File
@@ -31,12 +31,22 @@ SOFTWARE.
namespace PD { namespace PD {
namespace Li { namespace Li {
PD_LITHIUM_API DrawList::DrawList(int initial_size) {
DrawSolid();
pPool.Init(initial_size);
}
PD_LITHIUM_API DrawList::~DrawList() {
Clear();
pPool.Deinit();
}
PD_LITHIUM_API void DrawList::DrawSolid() { CurrentTex = Gfx::GetSolidTex(); } PD_LITHIUM_API void DrawList::DrawSolid() { CurrentTex = Gfx::GetSolidTex(); }
PD_LITHIUM_API void DrawList::Clear() { PD_LITHIUM_API void DrawList::Clear() {
pNumIndices = 0; pNumIndices = 0;
pNumVertices = 0; pNumVertices = 0;
pDrawList.clear(); pPool.Reset();
pPath.clear(); pPath.clear();
if (pCurrentFont) { if (pCurrentFont) {
pCurrentFont->CleanupTMS(); pCurrentFont->CleanupTMS();
@@ -46,27 +56,27 @@ PD_LITHIUM_API void DrawList::Clear() {
} }
} }
PD_LITHIUM_API void DrawList::AddCommand(Command::Ref v) {
pNumIndices += v->IndexBuffer.size();
pNumVertices += v->VertexBuffer.size();
pDrawList.push_back(std::move(v));
}
PD_LITHIUM_API void DrawList::Merge(DrawList::Ref list) { PD_LITHIUM_API void DrawList::Merge(DrawList::Ref list) {
for (size_t i = 0; i < list->pDrawList.size(); i++) { pPool.Merge(list->pPool);
/*for (size_t i = 0; i < list->pDrawList.size(); i++) {
pNumIndices += list->pDrawList[i]->IndexBuffer.size(); pNumIndices += list->pDrawList[i]->IndexBuffer.size();
pNumVertices += list->pDrawList[i]->VertexBuffer.size(); pNumVertices += list->pDrawList[i]->VertexBuffer.size();
pDrawList.push_back(std::move(list->pDrawList[i])); auto cmd = pPool.NewCmd();
} pDrawList.push_back(list->pDrawList[i]);
}*/
/** Make sure The list gets cleared */ /** Make sure The list gets cleared */
list->Clear(); list->Clear();
} }
PD_LITHIUM_API void DrawList::Copy(DrawList::Ref list) {
pPool.Copy(list->pPool);
}
PD_LITHIUM_API void DrawList::Optimize() { PD_LITHIUM_API void DrawList::Optimize() {
#ifndef NDEBUG #ifndef NDEBUG
PD::TT::Scope s("Optimize"); PD::TT::Scope s("Optimize");
#endif #endif
std::sort(pDrawList.begin(), pDrawList.end(), /*std::sort(pDrawList.begin(), pDrawList.end(),
[](const PD::Li::Command::Ref &a, const PD::Li::Command::Ref &b) { [](const PD::Li::Command::Ref &a, const PD::Li::Command::Ref &b) {
if (a->Layer == b->Layer) { // Same layer if (a->Layer == b->Layer) { // Same layer
if (a->Tex == b->Tex) { // same tex if (a->Tex == b->Tex) { // same tex
@@ -75,19 +85,18 @@ PD_LITHIUM_API void DrawList::Optimize() {
return a->Tex < b->Tex; // order by address return a->Tex < b->Tex; // order by address
} }
return a->Layer < b->Layer; // Order by layer return a->Layer < b->Layer; // Order by layer
}); });*/
} }
PD_LITHIUM_API Command::Ref DrawList::PreGenerateCmd() { PD_LITHIUM_API Command::Ref DrawList::GetNewCmd() {
Command::Ref cmd = Command::New(); Command::Ref cmd = pPool.NewCmd();
cmd->Layer = pLayer; cmd->Index = pPool.Size() - 1;
cmd->Index = pDrawList.size();
cmd->Tex = CurrentTex; cmd->Tex = CurrentTex;
pClipCmd(cmd.get()); pClipCmd(cmd);
return cmd; return cmd;
} }
PD_LITHIUM_API void DrawList::pClipCmd(Command *cmd) { PD_LITHIUM_API void DrawList::pClipCmd(Command::Ref cmd) {
if (!pClipRects.empty()) { if (!pClipRects.empty()) {
cmd->ScissorOn = true; cmd->ScissorOn = true;
cmd->ScissorRect = ivec4(pClipRects.top()); cmd->ScissorRect = ivec4(pClipRects.top());
@@ -260,7 +269,7 @@ PD_LITHIUM_API void DrawList::DrawPolyLine(const std::vector<fvec2> &points,
return; return;
} }
DrawSolid(); DrawSolid();
auto cmd = PreGenerateCmd(); auto cmd = GetNewCmd();
bool close = (flags & (1 << 0)); bool close = (flags & (1 << 0));
int num_points = close ? (int)points.size() : (int)points.size() - 1; int num_points = close ? (int)points.size() : (int)points.size() - 1;
if (flags & (1 << 1)) { if (flags & (1 << 1)) {
@@ -270,10 +279,9 @@ PD_LITHIUM_API void DrawList::DrawPolyLine(const std::vector<fvec2> &points,
for (int i = 0; i < num_points; i++) { for (int i = 0; i < num_points; i++) {
int j = (i + 1) == (int)points.size() ? 0 : (i + 1); int j = (i + 1) == (int)points.size() ? 0 : (i + 1);
auto line = Renderer::PrimLine(points[i], points[j], thickness); auto line = Renderer::PrimLine(points[i], points[j], thickness);
Renderer::CmdQuad(cmd.get(), line, vec4(0.f, 1.f, 1.f, 0.f), clr); Renderer::CmdQuad(cmd, line, vec4(0.f, 1.f, 1.f, 0.f), clr);
} }
} }
AddCommand(std::move(cmd));
} }
PD_LITHIUM_API void DrawList::DrawConvexPolyFilled( PD_LITHIUM_API void DrawList::DrawConvexPolyFilled(
@@ -281,9 +289,8 @@ PD_LITHIUM_API void DrawList::DrawConvexPolyFilled(
if (points.size() < 3) { if (points.size() < 3) {
return; // Need at least three points return; // Need at least three points
} }
auto cmd = PreGenerateCmd(); auto cmd = GetNewCmd();
Renderer::CmdConvexPolyFilled(cmd.get(), points, clr, CurrentTex); Renderer::CmdConvexPolyFilled(cmd, points, clr, CurrentTex);
AddCommand(std::move(cmd));
} }
PD_LITHIUM_API void DrawList::DrawText(const fvec2 &pos, PD_LITHIUM_API void DrawList::DrawText(const fvec2 &pos,
@@ -291,13 +298,7 @@ PD_LITHIUM_API void DrawList::DrawText(const fvec2 &pos,
if (!pCurrentFont) { if (!pCurrentFont) {
return; return;
} }
std::vector<Command::Ref> cmds; pCurrentFont->CmdTextEx(pPool, pos, color, pFontScale, text);
pCurrentFont->CmdTextEx(cmds, pos, color, pFontScale, text);
for (size_t i = 0; i < cmds.size(); i++) {
cmds[i]->Index = pDrawList.size() + i;
cmds[i]->Layer = pLayer;
AddCommand(std::move(cmds[i]));
}
} }
PD_LITHIUM_API void DrawList::DrawTextEx(const fvec2 &p, PD_LITHIUM_API void DrawList::DrawTextEx(const fvec2 &p,
@@ -306,13 +307,7 @@ PD_LITHIUM_API void DrawList::DrawTextEx(const fvec2 &p,
if (!pCurrentFont) { if (!pCurrentFont) {
return; return;
} }
std::vector<Command::Ref> cmds; pCurrentFont->CmdTextEx(pPool, p, color, pFontScale, text, flags, box);
pCurrentFont->CmdTextEx(cmds, p, color, pFontScale, text, flags, box);
for (size_t i = 0; i < cmds.size(); i++) {
cmds[i]->Index = pDrawList.size() + i;
cmds[i]->Layer = pLayer;
AddCommand(std::move(cmds[i]));
}
} }
PD_LITHIUM_API void DrawList::DrawLine(const fvec2 &a, const fvec2 &b, PD_LITHIUM_API void DrawList::DrawLine(const fvec2 &a, const fvec2 &b,
+7 -10
View File
@@ -248,10 +248,9 @@ PD_LITHIUM_API fvec2 Font::GetTextBounds(const std::string &text, float scale) {
return res; return res;
} }
PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds, PD_LITHIUM_API void Font::CmdTextEx(CmdPool &cmds, const fvec2 &pos, u32 color,
const fvec2 &pos, u32 color, float scale, float scale, const std::string &text,
const std::string &text, LiTextFlags flags, LiTextFlags flags, const fvec2 &box) {
const fvec2 &box) {
fvec2 off; fvec2 off;
float cfs = (DefaultPixelHeight * scale) / (float)PixelHeight; float cfs = (DefaultPixelHeight * scale) / (float)PixelHeight;
float lh = (float)PixelHeight * cfs; float lh = (float)PixelHeight * cfs;
@@ -294,7 +293,7 @@ PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds,
it = pShortText(it, scale, box - pos, tmp_dim); it = pShortText(it, scale, box - pos, tmp_dim);
} }
auto wline = Strings::MakeWstring(it); auto wline = Strings::MakeWstring(it);
auto cmd = Command::New(); auto cmd = cmds.NewCmd();
auto Tex = GetCodepoint(wline[0]).Tex; auto Tex = GetCodepoint(wline[0]).Tex;
cmd->Tex = Tex; cmd->Tex = Tex;
for (auto &jt : wline) { for (auto &jt : wline) {
@@ -304,8 +303,7 @@ PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds,
continue; continue;
} }
if (Tex != cp.Tex) { if (Tex != cp.Tex) {
cmds.push_back(std::move(cmd)); cmd = cmds.NewCmd();
cmd = Command::New();
Tex = cp.Tex; Tex = cp.Tex;
cmd->Tex = Tex; cmd->Tex = Tex;
} }
@@ -318,19 +316,18 @@ PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds,
Rect rec = Renderer::PrimRect( Rect rec = Renderer::PrimRect(
rpos + vec2(off.x + 1, off.y + (cp.Offset * cfs)) + 1, rpos + vec2(off.x + 1, off.y + (cp.Offset * cfs)) + 1,
cp.Size * cfs, 0.f); cp.Size * cfs, 0.f);
Renderer::CmdQuad(cmd.get(), rec, cp.SimpleUV, 0xff111111); Renderer::CmdQuad(cmd, rec, cp.SimpleUV, 0xff111111);
} }
// Draw // Draw
Rect rec = Renderer::PrimRect( Rect rec = Renderer::PrimRect(
rpos + off + fvec2(0, (cp.Offset * cfs)), cp.Size * cfs, 0.f); rpos + off + fvec2(0, (cp.Offset * cfs)), cp.Size * cfs, 0.f);
Renderer::CmdQuad(cmd.get(), rec, cp.SimpleUV, color); Renderer::CmdQuad(cmd, rec, cp.SimpleUV, color);
off.x += cp.Size.x * cfs + 2 * cfs; off.x += cp.Size.x * cfs + 2 * cfs;
} else { } else {
off.x += 4 * cfs; off.x += 4 * cfs;
} }
} }
} }
cmds.push_back(std::move(cmd));
off.y += lh; off.y += lh;
off.x = 0; off.x = 0;
} }
+4 -3
View File
@@ -88,7 +88,7 @@ PD_LITHIUM_API Rect Renderer::PrimLine(const fvec2& a, const fvec2& b,
return Rect(a + off, b + off, a - off, b - off); return Rect(a + off, b + off, a - off, b - off);
} }
PD_LITHIUM_API void Renderer::CmdQuad(Command* cmd, const Rect& quad, PD_LITHIUM_API void Renderer::CmdQuad(Command::Ref cmd, const Rect& quad,
const Rect& uv, u32 color) { const Rect& uv, u32 color) {
cmd->AddIdx(0).AddIdx(1).AddIdx(2); cmd->AddIdx(0).AddIdx(1).AddIdx(2);
cmd->AddIdx(0).AddIdx(2).AddIdx(3); cmd->AddIdx(0).AddIdx(2).AddIdx(3);
@@ -98,7 +98,7 @@ PD_LITHIUM_API void Renderer::CmdQuad(Command* cmd, const Rect& quad,
cmd->AddVtx(Vertex(quad.BotLeft(), uv.BotLeft(), color)); cmd->AddVtx(Vertex(quad.BotLeft(), uv.BotLeft(), color));
} }
PD_LITHIUM_API void Renderer::CmdTriangle(Command* cmd, const fvec2 a, PD_LITHIUM_API void Renderer::CmdTriangle(Command::Ref cmd, const fvec2 a,
const fvec2 b, const fvec2 c, const fvec2 b, const fvec2 c,
u32 clr) { u32 clr) {
cmd->AddIdx(2).AddIdx(1).AddIdx(0); cmd->AddIdx(2).AddIdx(1).AddIdx(0);
@@ -111,7 +111,8 @@ PD_LITHIUM_API void Renderer::CmdTriangle(Command* cmd, const fvec2 a,
// would probably be faster to render out of screen than checking if // would probably be faster to render out of screen than checking if
// it could be skipped) // it could be skipped)
PD_LITHIUM_API void Renderer::CmdConvexPolyFilled( PD_LITHIUM_API void Renderer::CmdConvexPolyFilled(
Command* cmd, const std::vector<fvec2>& points, u32 clr, Texture::Ref tex) { Command::Ref cmd, const std::vector<fvec2>& points, u32 clr,
Texture::Ref tex) {
if (points.size() < 3 || tex == nullptr) { if (points.size() < 3 || tex == nullptr) {
return; // Need at least three points return; // Need at least three points
} }
+2 -1
View File
@@ -17,6 +17,7 @@ set(SRC
source/container/dynobj.cpp source/container/dynobj.cpp
source/container/image.cpp source/container/image.cpp
source/container/label.cpp source/container/label.cpp
source/container/slider.cpp
) )
if(PD_BUILD_SHARED) if(PD_BUILD_SHARED)
@@ -25,4 +26,4 @@ else()
pd_add_lib(pd-ui7 SRC_FILES ${SRC}) pd_add_lib(pd-ui7 SRC_FILES ${SRC})
endif() endif()
target_link_libraries(pd-ui7 PUBLIC pd-lithium pd-core) target_link_libraries(pd-ui7 PUBLIC pd-lithium pd-core)
+4 -3
View File
@@ -49,11 +49,12 @@ PD_UI7_API void Button::HandleInput() {
PD_UI7_API void Button::Draw() { PD_UI7_API void Button::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->DrawRectFilled(FinalPos(), size, io->Theme->Get(color)); list->PathRect(FinalPos(), FinalPos() + size, io->FrameRounding);
list->pLayer++; list->PathFill(io->Theme->Get(color));
list->LayerUp();
list->DrawText(FinalPos() + size * 0.5 - tdim * 0.5, label, list->DrawText(FinalPos() + size * 0.5 - tdim * 0.5, label,
io->Theme->Get(UI7Color_Text)); io->Theme->Get(UI7Color_Text));
list->pLayer--; list->LayerDown();
} }
PD_UI7_API void Button::Update() { PD_UI7_API void Button::Update() {
+4 -3
View File
@@ -48,10 +48,11 @@ PD_UI7_API void Checkbox::HandleInput() {
PD_UI7_API void Checkbox::Draw() { PD_UI7_API void Checkbox::Draw() {
// Assert(list.get() && io.get(), "Did you run Container::Init correctly?"); // Assert(list.get() && io.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->DrawRectFilled(FinalPos(), cbs, io->Theme->Get(color)); list->PathRect(FinalPos(), FinalPos() + cbs, io->FrameRounding);
list->PathFill(io->Theme->Get(color));
if (usr_ref) { if (usr_ref) {
list->DrawRectFilled(FinalPos() + 2, cbs - 4, list->PathRect(FinalPos() + 2, FinalPos() + cbs - 2, io->FrameRounding);
io->Theme->Get(UI7Color_Checkmark)); list->PathFill(io->Theme->Get(UI7Color_Checkmark));
} }
list->DrawText( list->DrawText(
FinalPos() + fvec2(cbs.x + io->ItemSpace.x, cbs.y * 0.5 - tdim.y * 0.5), FinalPos() + fvec2(cbs.x + io->ItemSpace.x, cbs.y * 0.5 - tdim.y * 0.5),
+6 -4
View File
@@ -44,8 +44,9 @@ PD_UI7_API void ColorEdit::HandleInput() {
PD_UI7_API void ColorEdit::Draw() { PD_UI7_API void ColorEdit::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->DrawRectFilled(FinalPos(), fvec2(20, 20), *color_ref); list->PathRect(FinalPos(), FinalPos() + 18, io->FrameRounding);
list->DrawText(FinalPos() + fvec2(io->ItemSpace.x + 20, 0), label, list->PathFill(*color_ref);
list->DrawText(FinalPos() + fvec2(io->ItemSpace.x + 18, 0), label,
io->Theme->Get(UI7Color_Text)); io->Theme->Get(UI7Color_Text));
if (is_shown) { if (is_shown) {
if (!layout) { if (!layout) {
@@ -53,13 +54,14 @@ PD_UI7_API void ColorEdit::Draw() {
} }
layout->AddObject(Label::New("Hello World!", io)); layout->AddObject(Label::New("Hello World!", io));
layout->Update(); layout->Update();
io->RegisterDrawList(GetID(), layout->GetDrawList()); list->Merge(layout->GetDrawList());
// io->RegisterDrawList(GetID(), layout->GetDrawList());
} }
} }
PD_UI7_API void ColorEdit::Update() { PD_UI7_API void ColorEdit::Update() {
// Assert(io.get(), "Did you run Container::Init correctly?"); // Assert(io.get(), "Did you run Container::Init correctly?");
this->SetSize(fvec2(tdim.x + io->ItemSpace.x + 20, 20)); this->SetSize(fvec2(tdim.x + io->ItemSpace.x + 18, 18));
} }
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD
+5 -4
View File
@@ -81,13 +81,14 @@ PD_UI7_API void DragData<T>::Draw() {
p = std::format("{}", data[i]); p = std::format("{}", data[i]);
} }
vec2 td = io->Font->GetTextBounds(p, io->FontScale); vec2 td = io->Font->GetTextBounds(p, io->FontScale);
list->DrawRectFilled(FinalPos() + fvec2(off_x, 0), td + io->FramePadding, list->PathRect(FinalPos() + fvec2(off_x, 0),
io->Theme->Get(UI7Color_Button)); FinalPos() + td + io->FramePadding, io->FrameRounding);
list->pLayer++; list->PathFill(io->Theme->Get(UI7Color_Button));
list->LayerUp();
list->DrawTextEx(FinalPos() + fvec2(off_x, 0), p, list->DrawTextEx(FinalPos() + fvec2(off_x, 0), p,
io->Theme->Get(UI7Color_Text), LiTextFlags_AlignMid, io->Theme->Get(UI7Color_Text), LiTextFlags_AlignMid,
td + io->FramePadding); td + io->FramePadding);
list->pLayer--; list->LayerDown();
off_x += td.x + io->ItemSpace.x + io->FramePadding.x; off_x += td.x + io->ItemSpace.x + io->FramePadding.x;
} }
list->DrawText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5), label, list->DrawText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5), label,
+2 -2
View File
@@ -29,11 +29,11 @@ PD_UI7_API void Image::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// Assert(img.get(), "Image is nullptr!"); // Assert(img.get(), "Image is nullptr!");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->pLayer++; list->LayerUp();
list->DrawTexture(img); list->DrawTexture(img);
list->DrawRectFilled(FinalPos(), newsize, 0xffffffff); list->DrawRectFilled(FinalPos(), newsize, 0xffffffff);
list->DrawSolid(); list->DrawSolid();
list->pLayer--; list->LayerDown();
} }
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD
+107
View File
@@ -0,0 +1,107 @@
/*
MIT License
Copyright (c) 2024 - 2025 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/container/label.hpp>
#include <pd/ui7/container/slider.hpp>
#include <type_traits>
namespace PD {
namespace UI7 {
// Setup Supported Datatypes (Probably making this Object
// header only to not care about datatype support)
template class PD_UI7_API Slider<float>;
template class PD_UI7_API Slider<int>;
template class PD_UI7_API Slider<double>;
template class PD_UI7_API Slider<u8>;
template class PD_UI7_API Slider<u16>;
template class PD_UI7_API Slider<u32>;
template class PD_UI7_API Slider<u64>;
template <typename T>
PD_UI7_API void Slider<T>::HandleInput() {
/// Ensure to only check input once
if (inp_done) {
return;
}
// Assert(screen.get(), "Screen is not set up!");
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", *data, precision);
} else {
p = std::format("{}", *data);
}
// Unsafe but is the fastest solution
float xps = FinalPos().x;
if (io->InputHandler->DragObject(
this->GetID(),
fvec4(FinalPos() + fvec2(2, 0), fvec2(width, GetSize().y)))) {
if (!io->InputHandler->DragReleasedAW) {
*data = std::clamp(
T(max * (std::clamp(io->InputHandler->DragLastPosition.x - xps, 0.f,
width) /
width)),
this->min, this->max);
}
}
inp_done = true;
}
template <typename T>
PD_UI7_API void Slider<T>::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen);
std::string p;
if constexpr (std::is_floating_point_v<T>) {
p = std::format("{:.{}f}", *data, precision);
} else {
p = std::format("{}", *data);
}
fvec2 td = io->Font->GetTextBounds(p, io->FontScale);
list->PathRect(FinalPos(), FinalPos() + fvec2(width, td.y) + io->FramePadding,
io->FrameRounding);
list->PathFill(io->Theme->Get(UI7Color_Button));
list->PathRect(FinalPos() + 2 + PD::fvec2(slp, 0),
FinalPos() + fvec2(slp + slw - 2, td.y - 2) + io->FramePadding,
io->FrameRounding);
list->PathFill(io->Theme->Get(UI7Color_ButtonActive));
list->LayerUp();
list->DrawTextEx(FinalPos(), p, io->Theme->Get(UI7Color_Text),
LiTextFlags_AlignMid, fvec2(width, td.y) + io->FramePadding);
list->LayerDown();
list->DrawText(FinalPos() + fvec2(width + io->FramePadding.x * 2.f,
io->FramePadding.y * 0.5),
label, io->Theme->Get(UI7Color_Text));
}
template <typename T>
PD_UI7_API void Slider<T>::Update() {
// Assert(io.get(), "Did you run Container::Init correctly?");
// Probably need to find a faster solution (caching sizes calculated here)
slw = std::clamp(static_cast<float>(width / max), 3.f, width);
slp = static_cast<float>((float)*data / (float)max) * (width - slw);
fvec2 tdim = io->Font->GetTextBounds(label, io->FontScale);
this->SetSize(
fvec2(width + tdim.x + io->ItemSpace.x * 2, tdim.y + io->FramePadding.y));
}
} // namespace UI7
} // namespace PD
+5 -5
View File
@@ -242,7 +242,7 @@ PD_UI7_API void Menu::DrawBaseLayout() {
if (!(Flags & UI7MenuFlags_NoResize)) { if (!(Flags & UI7MenuFlags_NoResize)) {
Container::Ref r = DynObj::New( Container::Ref r = DynObj::New(
[](IO::Ref io, Li::DrawList::Ref l, UI7::Container* self) { [](IO::Ref io, Li::DrawList::Ref l, UI7::Container* self) {
l->pLayer = 1; l->Layer(1);
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20)); l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20));
l->PathAdd(self->FinalPos() + self->GetSize()); l->PathAdd(self->FinalPos() + self->GetSize());
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0)); l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0));
@@ -258,7 +258,7 @@ PD_UI7_API void Menu::DrawBaseLayout() {
/** Background */ /** Background */
Container::Ref r = DynObj::New([](IO::Ref io, Li::DrawList::Ref l, Container::Ref r = DynObj::New([](IO::Ref io, Li::DrawList::Ref l,
UI7::Container* self) { UI7::Container* self) {
l->pLayer = 0; l->Layer(0);
l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f, l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f,
LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot); LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot);
l->PathFill(io->Theme->Get(UI7Color_Background)); l->PathFill(io->Theme->Get(UI7Color_Background));
@@ -275,11 +275,11 @@ PD_UI7_API void Menu::DrawBaseLayout() {
if (!(Flags & UI7MenuFlags_NoTitlebar)) { if (!(Flags & UI7MenuFlags_NoTitlebar)) {
Container::Ref r = DynObj::New( Container::Ref r = DynObj::New(
[=, this](UI7::IO::Ref io, Li::DrawList::Ref l, UI7::Container* self) { [=, this](UI7::IO::Ref io, Li::DrawList::Ref l, UI7::Container* self) {
l->pLayer = 20; l->Layer(20);
/** Header Bar */ /** Header Bar */
l->DrawRectFilled(self->FinalPos(), self->GetSize(), l->DrawRectFilled(self->FinalPos(), self->GetSize(),
io->Theme->Get(UI7Color_Header)); io->Theme->Get(UI7Color_Header));
l->pLayer = 21; l->Layer(21);
/** Inline if statement to shift the Text if collapse sym is shown */ /** Inline if statement to shift the Text if collapse sym is shown */
/** What the hell is this code btw (didn't found a better way) */ /** What the hell is this code btw (didn't found a better way) */
l->DrawText(self->FinalPos() + fvec2((Flags & UI7MenuFlags_NoCollapse) l->DrawText(self->FinalPos() + fvec2((Flags & UI7MenuFlags_NoCollapse)
@@ -300,7 +300,7 @@ PD_UI7_API void Menu::DrawBaseLayout() {
r = DynObj::New([=, this](UI7::IO::Ref io, Li::DrawList::Ref l, r = DynObj::New([=, this](UI7::IO::Ref io, Li::DrawList::Ref l,
UI7::Container* self) { UI7::Container* self) {
/** This sym actually requires layer 21 (i dont know why) */ /** This sym actually requires layer 21 (i dont know why) */
l->pLayer = 21; l->Layer(21);
/** /**
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;) * Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
*/ */
+10 -14
View File
@@ -51,25 +51,25 @@ PD_UI7_API void Context::UseViewPort(const ID &id) {
pIO->CurrentViewPort = pIO->ViewPorts[id]->GetSize(); pIO->CurrentViewPort = pIO->ViewPorts[id]->GetSize();
} }
PD_UI7_API bool Context::BeginMenu(const ID &id, UI7MenuFlags flags, PD_UI7_API Menu::Ref Context::BeginMenu(const ID &id, UI7MenuFlags flags,
bool *pShow) { bool *pShow) {
if (pCurrent) { if (pCurrent) {
std::cout << "[UI7] Error: You are already in " << pCurrent->pID.GetName() std::cout << "[UI7] Error: You are already in " << pCurrent->pID.GetName()
<< " Menu" << std::endl; << " Menu" << std::endl;
return false; return nullptr;
} }
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), (u32)id) != if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), (u32)id) !=
pCurrentMenus.end()) { pCurrentMenus.end()) {
std::cout << "[UI7] Error: Menu " << id.GetName() << " already exists!" std::cout << "[UI7] Error: Menu " << id.GetName() << " already exists!"
<< std::endl; << std::endl;
return false; return nullptr;
} }
pCurrent = pGetOrCreateMenu(id); pCurrent = pGetOrCreateMenu(id);
this->pCurrent->pIsShown = pShow; this->pCurrent->pIsShown = pShow;
if (pCurrent->pIsShown != nullptr) { if (pCurrent->pIsShown != nullptr) {
if (!*pCurrent->pIsShown) { if (!*pCurrent->pIsShown) {
pCurrent = nullptr; pCurrent = nullptr;
return false; return nullptr;
} }
} }
/** Probably we dont even need Input Handling in this stage */ /** Probably we dont even need Input Handling in this stage */
@@ -79,7 +79,7 @@ PD_UI7_API bool Context::BeginMenu(const ID &id, UI7MenuFlags flags,
if (!pCurrent->pIsOpen) { if (!pCurrent->pIsOpen) {
pCurrent = nullptr; pCurrent = nullptr;
} }
return pCurrent != nullptr; return pCurrent;
} }
PD_UI7_API void Context::EndMenu() { PD_UI7_API void Context::EndMenu() {
@@ -154,8 +154,7 @@ PD_UI7_API void Context::Update() {
} }
PD_UI7_API void Context::AboutMenu(bool *show) { PD_UI7_API void Context::AboutMenu(bool *show) {
if (BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) { if (auto m = BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
auto m = pCurrent;
m->Label("Palladium UI7 " + GetVersion()); m->Label("Palladium UI7 " + GetVersion());
m->Separator(); m->Separator();
m->Label("(c) 2023-2025 René Amthor"); m->Label("(c) 2023-2025 René Amthor");
@@ -177,8 +176,7 @@ PD_UI7_API void Context::AboutMenu(bool *show) {
} }
PD_UI7_API void Context::MetricsMenu(bool *show) { PD_UI7_API void Context::MetricsMenu(bool *show) {
if (BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) { if (auto m = BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
auto m = pCurrent;
m->Label("Palladium - UI7 " + GetVersion()); m->Label("Palladium - UI7 " + GetVersion());
m->Separator(); m->Separator();
m->Label( m->Label(
@@ -209,7 +207,7 @@ PD_UI7_API void Context::MetricsMenu(bool *show) {
} }
m->SeparatorText("Palladium Info"); m->SeparatorText("Palladium Info");
m->Label("Renderer: " + PD::Gfx::pGfx->pName); m->Label("Renderer: " + PD::Gfx::pGfx->pName);
if (m->BeginTreeNode("Input: " + PD::Hid::pHid->pName)) { if (m->BeginTreeNode(std::string("Input: " + PD::Hid::pHid->pName))) {
if (PD::Hid::GetFlags() & PD::HidDriver::Flags_HasKeyboard) { if (PD::Hid::GetFlags() & PD::HidDriver::Flags_HasKeyboard) {
m->Label("- Keyboard Supported"); m->Label("- Keyboard Supported");
} }
@@ -303,9 +301,7 @@ PD_UI7_API void Context::MetricsMenu(bool *show) {
} }
PD_UI7_API void UI7::Context::StyleEditor(bool *show) { PD_UI7_API void UI7::Context::StyleEditor(bool *show) {
if (this->BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) { if (auto m = BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) {
auto m = pCurrent;
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor"); m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
m->Separator(); m->Separator();
m->DragData("MenuPadding", (float *)&pIO->MenuPadding, 2, 0.f, 100.f); m->DragData("MenuPadding", (float *)&pIO->MenuPadding, 2, 0.f, 100.f);
+9 -11
View File
@@ -80,6 +80,7 @@ int main() {
int wx, wy; int wx, wy;
glfwGetWindowSize(win, &wx, &wy); glfwGetWindowSize(win, &wx, &wy);
PD::Gfx::pGfx->ViewPort = PD::ivec2(wx, wy); PD::Gfx::pGfx->ViewPort = PD::ivec2(wx, wy);
ui7->GetIO()->CurrentViewPort = PD::ivec4(0, 0, wx, wy);
glViewport(0, 0, wx, wy); glViewport(0, 0, wx, wy);
glClearColor(0, 0, 0, 0); glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
@@ -102,15 +103,14 @@ int main() {
/** Draw text */ /** Draw text */
List->DrawText( List->DrawText(
20, 20,
"Test String oder So\nPalladium 0.5.0\n" + "Test String oder So\nPalladium 0.6.0\n" +
std::format("{}\nMousePos: {}", std::format("{}\nMousePos: {}",
PD::Strings::FormatNanos( PD::Strings::FormatNanos(
PD::OS::GetTraceRef("REN")->GetLastDiff()), PD::OS::GetTraceRef("REN")->GetLastDiff()),
PD::Hid::MousePos()) + PD::Hid::MousePos()) +
"\nUI7 Version: " + PD::UI7::GetVersion(), "\nUI7 Version: " + PD::UI7::GetVersion(),
0xff000000); 0xff000000);
if (ui7->BeginMenu("Test")) { if (auto menu = ui7->BeginMenu("Test")) {
auto menu = ui7->pCurrent;
menu->Label("Hello"); menu->Label("Hello");
menu->Label("World!"); menu->Label("World!");
menu->Checkbox("About Menu", AboutOderSo); menu->Checkbox("About Menu", AboutOderSo);
@@ -125,17 +125,16 @@ int main() {
menu->Label( menu->Label(
std::format("Left: {}", PD::Hid::IsHeld(PD::Hid::Key::Touch))); std::format("Left: {}", PD::Hid::IsHeld(PD::Hid::Key::Touch)));
menu->DragData("Value", &v, 1); menu->DragData("Value", &v, 1);
menu->Slider("Value 2", &v);
ui7->EndMenu(); ui7->EndMenu();
} }
if (ui7->BeginMenu("Yet another Window")) { if (auto menu = ui7->BeginMenu("Yet another Window")) {
auto menu = ui7->pCurrent;
menu->Label(std::format("this->Pos: {}", menu->pLayout->GetPosition())); menu->Label(std::format("this->Pos: {}", menu->pLayout->GetPosition()));
menu->Label(std::format("Vertices: {}", PD::Gfx::pGfx->VertexCounter)); menu->Label(std::format("Vertices: {}", PD::Gfx::pGfx->VertexCounter));
menu->Label(std::format("Indices: {}", PD::Gfx::pGfx->IndexCounter)); menu->Label(std::format("Indices: {}", PD::Gfx::pGfx->IndexCounter));
ui7->EndMenu(); ui7->EndMenu();
} }
if (ui7->BeginMenu("#Debug (UI7)")) { if (auto menu = ui7->BeginMenu("#Debug (UI7)")) {
auto menu = ui7->pCurrent;
menu->Label(std::format("Framerate: {:.1f} [{:.2f}]", ui7->pIO->Framerate, menu->Label(std::format("Framerate: {:.1f} [{:.2f}]", ui7->pIO->Framerate,
ui7->pIO->Delta)); ui7->pIO->Delta));
menu->SeparatorText("Input"); menu->SeparatorText("Input");
@@ -149,8 +148,7 @@ int main() {
} }
ui7->EndMenu(); ui7->EndMenu();
} }
if (ui7->BeginMenu("NoDebug")) { if (auto m = ui7->BeginMenu("NoDebug")) {
auto m = ui7->pCurrent;
if (m->BeginTreeNode("Test")) { if (m->BeginTreeNode("Test")) {
m->Label("Hello World!"); m->Label("Hello World!");
if (m->BeginTreeNode("AnotherNode")) { if (m->BeginTreeNode("AnotherNode")) {
@@ -176,8 +174,8 @@ int main() {
#endif #endif
PD::TT::Beg("REN"); PD::TT::Beg("REN");
PD::Gfx::NewFrame(); PD::Gfx::NewFrame();
PD::Gfx::RenderDrawData(List->pDrawList); PD::Gfx::RenderDrawData(List->Data());
PD::Gfx::RenderDrawData(ui7->GetDrawData()->pDrawList); PD::Gfx::RenderDrawData(ui7->GetDrawData()->Data());
/** Clear The List */ /** Clear The List */
List->Clear(); List->Clear();
PD::TT::End("REN"); PD::TT::End("REN");