Add Input functionality to Ultra

- Add point InSpace check to PD::Li::Math
- Add Universal AlignmentCenter flag for Horizontal and and Vertical Alignment
-  Add Fallbackfont to Layout (if you dont want to set font per object)
- Add Button Object WIP
- Rename OnHover to OnFocus and add OnUnfocus
- Move font and FontScale to ElementBase (for fallback logic etc)
- Add UpdateInput func to ElementBase
- Corectly Set fontScale in Text Rendering
- Update ecample
This commit is contained in:
2026-04-03 15:17:43 +02:00
parent af7fc026df
commit 679de3ae94
12 changed files with 195 additions and 19 deletions
+1
View File
@@ -10,6 +10,7 @@ PD_API bool InBounds(const fvec2& pos, const fvec2& size, const fvec4& rect);
PD_API bool InBounds(const fvec2& pos, const fvec4& rect);
PD_API bool InBounds(const fvec2& a, const fvec2& b, const fvec2& c,
const fvec4& rect);
PD_API bool InSpace(const PD::fvec2& pos, const Rect& rect);
PD_API void RotateCorner(fvec2& pos, float sinus, float cosinus);
PD_API Rect PrimRect(const fvec2& pos, const fvec2& size, float angle = 0.f);
PD_API Rect PrimLine(const fvec2& a, const fvec2& b, int t = 1);
+56
View File
@@ -0,0 +1,56 @@
#pragma once
#include <pd/core/core.hpp>
#include <pd/ultra/elems/element.hpp>
namespace PD {
namespace Ultra {
class PD_API Button : public ElementBase {
public:
Button() {}
Button(const PD::fvec2& pos, const PD::fvec2& size, const PD::Color& color,
float rounding = 0.f, UltraAlignment align = 0)
: pColor(color), pRounding(rounding) {
this->pAlignment = align;
this->pPos = pos;
this->pSize = size;
}
Button(float x, float y, float w, float h, const PD::Color& color,
float rounding = 0.f, UltraAlignment align = 0)
: pColor(color), pRounding(rounding) {
this->pAlignment = align;
this->pPos = PD::fvec2(x, y);
this->pSize = PD::fvec2(w, h);
}
~Button() {}
void Draw(PD::Li::Drawlist& l) override;
void Update() override;
void SetColor(const PD::Color& color) { pColor = color; }
void SetFocusedColor(const PD::Color& color) { pHovered = color; }
void SetTextColor(const PD::Color& color) { pTextColor = color; }
void SetRounding(float r) { pRounding = r; }
void SetLined(bool v) { pLined = v; }
void SetThickness(int v) { pThickness = v; }
void SetText(const std::string& text) { pText = text; }
void SetAutoSizePadding(const PD::fvec2& size) { pAsp = size; }
// Discard these funcs
void OnFocus(EventFunc func) override {}
void OnUnFocus(EventFunc func) override {}
private:
std::string pText;
PD::Color pRenderColor;
PD::Color pColor;
PD::Color pHovered;
PD::Color pTextColor;
float pRounding = 0.f;
bool pLined = false;
int pThickness = 1.f;
// Auto-Size-Padding
PD::fvec2 pAsp = PD::fvec2(30, 10);
};
} // namespace Ultra
} // namespace PD
+23 -2
View File
@@ -27,16 +27,32 @@ class PD_API ElementBase {
void SetSize(const PD::fvec2& size) { pSize = size; }
void SetSize(float w, float h) { pSize = PD::fvec2(w, h); }
/**
* Executed every frame
* Executed on Hovering
* Elemnents can override / discard this func
*/
virtual void OnHover(EventFunc func) { pHover = func; }
virtual void OnFocus(EventFunc func) { pHover = func; }
/**
* Executed on Mocing out of the space
* Elemnents can override / discard this func
*/
virtual void OnUnFocus(EventFunc func) { pUnHover = func; }
/**
* Executrd on KeyUp event
* Elemnents can override / discard this func
*/
virtual void OnPress(EventFunc func) { pPress = func; }
void SetFontScale(float s = 1.f) { pFontScale = 1.f; }
float GetFontScale() const { return pFontScale; }
void SetFont(PD::Li::Font& font) { pFont = &font; }
void SetFontIfNull(PD::Li::Font& font) {
if (!pFont) pFont = &font;
}
virtual void UpdateInput();
protected:
friend class Container;
void SetParent(Container* c) { pParent = c; }
@@ -48,7 +64,12 @@ class PD_API ElementBase {
PD::fvec2 pSize;
PD::Li::Rect pRenderspace;
EventFunc pHover = nullptr;
EventFunc pUnHover = nullptr;
EventFunc pPress = nullptr;
bool pFocued = false;
// Not used by every object btw
PD::Li::Font* pFont = nullptr;
float pFontScale = 1.f;
};
} // namespace Ultra
} // namespace PD
-4
View File
@@ -15,14 +15,10 @@ class PD_API Text : public ElementBase {
void SetColor(const PD::Color& color) { pColor = color; }
void SetText(const std::string& text) { pText = text; }
void SetFont(PD::Li::Font& font) { pFont = &font; }
void SetScale(float scale) { pScale = scale; }
private:
PD::Color pColor;
float pScale = 1.f;
std::string pText;
PD::Li::Font* pFont = nullptr;
};
} // namespace Ultra
+2
View File
@@ -15,4 +15,6 @@ enum UltraAlignment_ {
UltraAlignment_TopRight = UltraAlignment_Top | UltraAlignment_Right,
UltraAlignment_BotLeft = UltraAlignment_Bot | UltraAlignment_Left,
UltraAlignment_BotRight = UltraAlignment_Bot | UltraAlignment_Right,
UltraAlignment_Center =
UltraAlignment_CenterVertical | UltraAlignment_CenterHorizontal,
};
+8
View File
@@ -11,7 +11,15 @@ class PD_API Layout : public Container {
Layout() {}
~Layout() {}
/**
* Set a fallback font if you dont want to explicitly set a font for every
* objectt individually
*/
void SetFont(PD::Li::Font& font) { pFont = &font; }
void Render(PD::Li::Drawlist& list);
private:
PD::Li::Font* pFont = nullptr;
};
} // namespace Ultra
} // namespace PD
+5
View File
@@ -20,6 +20,11 @@ PD_API bool InBounds(const fvec2& a, const fvec2& b, const fvec2& c,
(a.x > 0 && b.x > 0 && c.x > 0) || (a.y > 0 && b.y > 0 && c.y > 0));
}
PD_API bool InSpace(const PD::fvec2& pos, const Rect& rect) {
return (pos.x > rect.Top.x && pos.x < rect.Top.z && pos.y > rect.Top.y &&
pos.y < rect.Bot.y);
}
PD_API void RotateCorner(fvec2& pos, float sinus, float cosinus) {
float x = pos.x * cosinus - pos.y * sinus;
float y = pos.y * cosinus - pos.x * sinus;
+46
View File
@@ -0,0 +1,46 @@
#include <pd/drivers/drivers.hpp>
#include <pd/ultra/container.hpp>
#include <pd/ultra/elems/button.hpp>
namespace PD {
namespace Ultra {
PD_API void Button::Draw(PD::Li::Drawlist& l) {
float r = pRounding;
if (pParent) r = pParent->GetCanvas().VTranslateSize(r).x;
l.PathRect(pRenderspace.TopLeft(), pRenderspace.BotRight(), r);
if (pLined) {
l.PathStroke(pRenderColor, pThickness, LiDrawFlags_Close);
} else {
l.PathFill(pRenderColor);
}
if (!pFont) return; // discard here if we dont have a font
PD::fvec2 off = 0.f;
if (pParent) off = pParent->GetCanvas().VTranslateSize(pAsp) * 0.5;
l.SetFont(pFont);
l.SetFontscale(pParent->GetCanvas().VTranslateFontscale(pFontScale));
l.DrawText(pRenderspace.TopLeft() + off, pText.c_str(), pTextColor);
}
PD_API void Button::Update() {
pRenderColor = pColor;
if (!pParent || !pFont) ElementBase::Update();
PD::fvec2 size = pSize;
if (size == PD::fvec2(0)) {
size = pFont->GetTextBounds(
pText.c_str(),
pParent->GetCanvas().VTranslateFontscale(pFontScale)) +
pParent->GetCanvas().VTranslateSize(pAsp);
} else {
size = pParent->GetCanvas().VTranslateSize(size);
}
pRenderspace = pParent->GetCanvas().VTranslateObject(
pParent->GetTopLeft() + pPos, size, pAlignment, true);
if (PD::Li::Math::InSpace(PD::Hid::MousePos(), pRenderspace)) {
pRenderColor = pHovered;
} else {
pRenderColor = pColor;
}
UpdateInput();
}
} // namespace Ultra
} // namespace PD
+28 -3
View File
@@ -1,3 +1,4 @@
#include <pd/drivers/drivers.hpp>
#include <pd/ultra/container.hpp>
#include <pd/ultra/elems/element.hpp>
@@ -12,11 +13,35 @@ PD_API bool ElementBase::RevisionUpdate(PD::u32 req) {
}
}
PD_API void ElementBase::Update() {
if (!pParent) pRenderspace = PD::fvec4(pPos, pPos + pSize);
pRenderspace = pParent->GetCanvas().VTranslateObject(
pParent->GetTopLeft() + pPos, pSize, pAlignment);
if (!pParent)
pRenderspace = PD::fvec4(pPos, pPos + pSize);
else
pRenderspace = pParent->GetCanvas().VTranslateObject(
pParent->GetTopLeft() + pPos, pSize, pAlignment);
UpdateInput();
/*pRenderspace = PD::fvec4(pParent->GetTopLeft() + pPos,
pParent->GetTopLeft() + pPos + pSize);*/
}
PD_API void ElementBase::UpdateInput() {
if (PD::Li::Math::InSpace(
PD::Hid::MousePos(),
PD::fvec4(pRenderspace.TopLeft(), pRenderspace.BotRight()))) {
if (pHover && !pFocued) {
pHover();
pFocued = true;
}
if (PD::Hid::IsEvent(PD::Hid::Event::Up, PD::Hid::Gamepad::Touch)) {
if (pPress) {
pPress();
}
}
} else {
if (pUnHover && pFocued) {
pUnHover();
pFocued = false;
}
}
}
} // namespace Ultra
} // namespace PD
+3 -2
View File
@@ -6,6 +6,7 @@ namespace Ultra {
PD_API void Text::Draw(PD::Li::Drawlist& l) {
if (!pFont) return;
l.SetFont(pFont);
l.SetFontscale(pParent->GetCanvas().VTranslateFontscale(pFontScale));
l.DrawText(pRenderspace.TopLeft(), pText.c_str(), pColor);
}
@@ -14,8 +15,8 @@ PD_API void Text::Update() {
if (!pParent) ElementBase::Update();
pRenderspace = pParent->GetCanvas().VTranslateObject(
pParent->GetTopLeft() + pPos,
pFont->GetTextBounds(pText.c_str(),
pParent->GetCanvas().VTranslateFontscale(pScale)),
pFont->GetTextBounds(
pText.c_str(), pParent->GetCanvas().VTranslateFontscale(pFontScale)),
pAlignment, true);
}
} // namespace Ultra
+1
View File
@@ -7,6 +7,7 @@ PD_API void Layout::Render(PD::Li::Drawlist& list) {
float fc = list.GetFontScale();
list.SetFontscale(GetCanvas().VTranslateFontscale(fc));
for (auto& it : GetElements()) {
it->SetFontIfNull(*pFont);
it->Update();
it->Draw(list);
}
+22 -8
View File
@@ -4,10 +4,13 @@
#include <palladium>
////
#include <pd/ultra/elems/button.hpp>
#include <pd/ultra/elems/element.hpp>
#include <pd/ultra/elems/image.hpp>
#include <pd/ultra/elems/rect.hpp>
#include <pd/ultra/elems/text.hpp>
#include <pd/ultra/layout.hpp>
////
PD::OsCtx* pOs = nullptr;
@@ -25,24 +28,36 @@ const char* ResourcePath(const char* in) {
class MainMenu : public PD::Ultra::Layout {
public:
MainMenu(PD::Li::Font& font) {
SetFont(font);
SetBaseViewport(PD::ivec2(1280, 720));
pBackground.SetSize(800, 450);
pBackground.SetColor(PD::Color("#ffffffff"));
pBackground.SetColor("#ffffffff");
pBackground.SetAlignment(UltraAlignment_CenterHorizontal |
UltraAlignment_CenterVertical);
Push(pBackground);
pText.SetColor(PD::Color("#000000"));
pText.SetText("Hello World");
pText.SetAlignment(UltraAlignment_CenterHorizontal |
UltraAlignment_CenterVertical);
pText.SetFont(font);
pText.SetColor("#ffffff");
pText.SetText("MousePos: ");
pText.SetAlignment(UltraAlignment_TopLeft);
Push(pText);
pBtn.SetText("Test");
pBtn.SetAlignment(UltraAlignment_Center);
pBtn.SetColor("#1273fb");
pBtn.SetFocusedColor("#0011ff");
pBtn.SetTextColor("#ffffff");
pBtn.SetRounding(10);
pBtn.OnPress([]() { PD::Log("Btn Pressed..."); });
Push(pBtn);
}
~MainMenu() {}
void Update() {
pText.SetText(std::format("MousePos: {}", PD::Hid::MousePos()));
}
private:
PD::Ultra::Rect pBackground;
PD::Ultra::Text pText;
PD::Ultra::Button pBtn;
};
class App {
@@ -51,6 +66,7 @@ class App {
~App() {}
void Update(PD::ivec2 vp, PD::Li::Drawlist& list) {
main.Update();
main.SetViewport(vp);
main.Render(list);
}
@@ -92,8 +108,6 @@ int main(int argc, char** argv) {
pOs->ClearViewPort();
PD::Li::ResetPools(); // Move to other place (or refactor this)
app.Update(pOs->GetViewport(), pList);
pList.DrawText(5, std::format("Mouse: {}", PD::Hid::MousePos()).c_str(),
PD::Color("#ffffffff"));
PD::Gfx::Reset();
PD::Gfx::Draw(pList);
pList.Clear();