From d55f485b8d55ab47a34b363cac7eaf5da1cf3b6c Mon Sep 17 00:00:00 2001 From: tobid7 Date: Wed, 22 Jan 2025 09:22:03 +0100 Subject: [PATCH] # Rewrite Stage 1.6 - Add static Text (Auto Static Text) - Add a Text Flag that Renders Text if it is Out of Screen - Shorter Keyboard animations and Fix Vertical Movement - Make Keyboard keys transparent - Make | to / in Performance Overlay as the symbol lokks biggy on System Font - Add Ast and Tms to Performance OVL --- CMakeLists.txt | 2 + include/pd/graphics/lithium.hpp | 49 +++++++++++-- include/pd/ui7/theme.hpp | 2 +- source/graphics/lithium.cpp | 60 ++++++++++++++-- source/overlays/keyboard.cpp | 120 ++++++++++++++++++++------------ source/overlays/performance.cpp | 4 +- source/ui7/ui7.cpp | 0 test/main.cpp | 1 + 8 files changed, 184 insertions(+), 54 deletions(-) create mode 100644 source/ui7/ui7.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ba0dffb..175480e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,8 @@ set(SRC_FILES source/tools/gamepad_icons.cpp # UI7 source/ui7/drawlist.cpp + source/ui7/theme.cpp + source/ui7/ui7.cpp # External source/external/stb.cpp ) diff --git a/include/pd/graphics/lithium.hpp b/include/pd/graphics/lithium.hpp index 72f30f2..d3f2a00 100644 --- a/include/pd/graphics/lithium.hpp +++ b/include/pd/graphics/lithium.hpp @@ -37,10 +37,11 @@ enum LITextFlags_ { LITextFlags_None = 0, LITextFlags_AlignRight = 1 << 0, LITextFlags_AlignMid = 1 << 1, - LITextFlags_Shaddow = 1 << 2, // Draws the text twice - LITextFlags_Wrap = 1 << 3, // May be runs better with TMS - LITextFlags_Short = 1 << 4, // May be runs better with TMS - LITextFlags_Scroll = 1 << 5, // Not implemented + LITextFlags_Shaddow = 1 << 2, // Draws the text twice + LITextFlags_Wrap = 1 << 3, // May be runs better with TMS + LITextFlags_Short = 1 << 4, // May be runs better with TMS + LITextFlags_Scroll = 1 << 5, // Not implemented + LITextFlags_RenderOOS = 1 << 6 // Render Out of Screen }; namespace PD { @@ -330,19 +331,53 @@ class StaticObject : public SmartCtor { std::vector cpy; std::vector cmds; }; + using RenderFlags = u32; enum RenderFlags_ { RenderFlags_None = 0, RenderFlags_TMS = 1 << 0, ///< Text Map System RenderFlags_LRS = 1 << 1, ///< Layer Render System RenderFlags_AST = 1 << 2, ///< Auto Static Text - RenderFlags_Default = RenderFlags_TMS, + RenderFlags_Default = RenderFlags_TMS | RenderFlags_LRS | RenderFlags_AST, }; class Renderer : public SmartCtor { public: Renderer(RenderFlags flags = RenderFlags_Default); ~Renderer(); + class StaticText : public SmartCtor { + public: + StaticText() {} + StaticText(Renderer* ren, const vec2& pos, u32 clr, const std::string& text, + LITextFlags flags = 0, const vec2& box = 0) { + Setup(ren, pos, clr, text, flags, box); + } + ~StaticText() {} + + void Setup(Renderer* ren, const vec2& pos, u32 clr, const std::string& text, + LITextFlags flags = 0, const vec2& box = 0); + + vec2 GetDim() const { return tdim; } + vec2 GetPos() const { return pos; } + + void SetColor(u32 col); + void SetPos(const vec2& pos); + + void SetUnused() { used = false; } + bool Used() const { return used; } + + bool IsSetup() { return text != nullptr; } + + void Draw(); + + private: + bool used; + Renderer* ren; + vec2 tdim; + vec2 pos; + StaticObject::Ref text; + }; + void Render(); void OnScreen(Screen::Screen_ screen) { @@ -431,6 +466,8 @@ class Renderer : public SmartCtor { u32 Indices() const { return indices; } u32 Commands() const { return commands; } u32 DrawCalls() const { return drawcalls; } + u32 AstUsage() const { return ast.size(); } + u32 TmsUsage() const { return tms.size(); } /// TOOLS /// static void RotateCorner(vec2& v, float s, float c); @@ -488,6 +525,8 @@ class Renderer : public SmartCtor { RenderMode mode = RenderMode_RGBA; // Text Map System std::map tms; + // (Auto) Static Text + std::unordered_map ast; /// Text Rendering /// const float default_font_h = 24.f; const float default_text_size = 0.7f; diff --git a/include/pd/ui7/theme.hpp b/include/pd/ui7/theme.hpp index 7148599..e1a0d67 100644 --- a/include/pd/ui7/theme.hpp +++ b/include/pd/ui7/theme.hpp @@ -25,7 +25,7 @@ SOFTWARE. #include -using UI7Color = u32; +using UI7Color = PD::u32; enum UI7Color_ { UI7Color_Background, diff --git a/source/graphics/lithium.cpp b/source/graphics/lithium.cpp index 3e03fef..3469d4c 100644 --- a/source/graphics/lithium.cpp +++ b/source/graphics/lithium.cpp @@ -243,6 +243,30 @@ Renderer::~Renderer() { C3D_Fini(); } +void Renderer::StaticText::Setup(Renderer* ren, const vec2& pos, u32 clr, + const std::string& text, LITextFlags flags, + const vec2& box) { + this->tdim = ren->GetTextDimensions(text); + this->pos = pos; + this->ren = ren; + this->text = StaticObject::New(); + ren->TextCommand(this->text->List(), pos, clr, text, flags, box); + OptiCommandList(this->text->List()); +} + +void Renderer::StaticText::Draw() { + used = true; + for (auto& it : text->List()) { + ren->PushCommand(it); + } + text->ReCopy(); +} + +void Renderer::StaticText::SetColor(u32 col) { text->ReColor(col); } +void Renderer::StaticText::SetPos(const vec2& pos) { + text->MoveIt(pos - this->pos); +} + bool Renderer::InBox(const vec2& pos, const vec2& szs, const vec4& rect) { return (pos[0] < rect[2] || pos[1] < rect[3] || pos[0] + szs[0] > rect[0] || pos[1] + szs[1] > rect[1]); @@ -363,7 +387,8 @@ void Renderer::TextCommand(std::vector& cmds, const vec2& pos, if (pos[1] + off[1] + lh < 0) { off[1] += lh; continue; - } else if (pos[1] + off[1] > GetViewport().w()) { + } else if (pos[1] + off[1] > GetViewport().w() && + !(flags & LITextFlags_RenderOOS)) { // Break cause next lines would be out of screen break; } @@ -524,9 +549,9 @@ void Renderer::RenderOn(bool bot) { commands = cmds.size(); size_t index = 0; - // if (flags & RenderFlags_LRS) { - OptiCommandList(cmds); - //} + if (flags & RenderFlags_LRS) { + OptiCommandList(cmds); + } while (index < cmds.size()) { C3D_Tex* tex = cmds[index]->Tex()->GetTex(); @@ -605,6 +630,18 @@ void Renderer::Render() { } for (auto it : rem) tms.erase(it); } + if (flags & RenderFlags_AST) { + std::vector rem; + for (auto it : ast) { + if (!it.second->Used()) { + rem.push_back(it.first); + } + it.second->SetUnused(); + } + for (auto& it : rem) { + ast.erase(it); + } + } } void Renderer::DrawRect(const vec2& pos, const vec2& size, u32 color, @@ -677,6 +714,21 @@ void Renderer::DrawImage(const vec2& pos, Texture::Ref tex, const vec2& scale) { void Renderer::DrawText(const vec2& pos, u32 color, const std::string& text, u32 flags, const vec2& ap) { + if (this->flags & RenderFlags_AST) { + u32 id = Strings::FastHash(text); + auto e = ast.find(id); + if (e == ast.end()) { + ast[id] = StaticText::New(); + e = ast.find(id); + } + if (!e->second->IsSetup()) { + e->second->Setup(this, pos, color, text, flags, ap); + } + e->second->SetPos(pos); + e->second->SetColor(color); + e->second->Draw(); + return; + } TextCommand(draw_list[bottom], pos, color, text, flags, ap); } diff --git a/source/overlays/keyboard.cpp b/source/overlays/keyboard.cpp index d19e71a..3080bfb 100644 --- a/source/overlays/keyboard.cpp +++ b/source/overlays/keyboard.cpp @@ -245,12 +245,12 @@ int Keyboard::too = 0; void Keyboard::MoveSelector() { /// Move from Current position to New Position - selector.From(selector).To(layouts[0][raw_sel].pos).In(0.2f); + selector.From(selector).To(layouts[0][raw_sel].pos).In(0.1f); /// If Button Size Changed, animate to the new size if (cselszs != layouts[0][raw_sel].size) { cselszs = layouts[0][raw_sel].size; sel_szs.Swap(); - sel_szs.To(cselszs).In(0.2); + sel_szs.To(cselszs).In(0.1); } } @@ -290,51 +290,84 @@ void Keyboard::Movement(Hid::Ref inp) { } else { /// Go Up Movement if (inp->IsUp(inp->Up)) { - // beginning pos of the keyboard - vec2 sp = flymgr; - // Keys are offset by 22 - sp.y() += 22; - // temp pos to save selector tween to - vec2 tp = selector; - // set its offset to startpos to - // create a box over all rows - tp.y() = sp.y(); - // Get the selector tween size - vec2 tszs = sel_szs; - // Get the last keys pos and size - // to calculate the size of temp szs - auto const& lok = layouts[0][layouts[0].size() - 1]; - tszs.y() = lok.pos.y() + lok.size.y(); - // Backwards loop - for (int i = raw_sel; i >= 0; i--) { - if (LI::Renderer::InBox( - sp + layouts[0][i].pos - vec2(0, layouts[0][i].size.y()), - layouts[0][i].size, vec4(tp, tszs))) { - raw_sel = i; - break; + vec2 tpos = layouts[0][raw_sel].pos; + vec2 tsize = layouts[0][raw_sel].size; + float tcen = tpos.x() + (tsize.x() * 0.5); + int bidx = -1; + float min_diff = std::numeric_limits::max(); + float try_ = -1; + + int start = raw_sel - 1; + if (tpos.y() == layouts[0][0].pos.y()) { + start = (int)layouts[0].size(); + } + + for (int i = start; i >= 0; i--) { + auto& tk = layouts[0][i]; + + if (tk.pos.y() != tpos.y()) { + if (try_ == -1) { + try_ = tk.pos.y(); + } + if (tk.pos.y() != try_) { + break; + } + + float tcenl = tk.pos.x() + (tk.size.x() * 0.5); + float diff = std::abs(tcen - tcenl); + if (diff < min_diff) { + min_diff = diff; + bidx = i; + } } } + + if (bidx != -1) { + raw_sel = bidx; + } MoveSelector(); } + /// Go Down Movement if (inp->IsUp(inp->Down)) { - vec2 fly = flymgr; - vec2 sel = selector; - vec2 selszs = sel_szs; - vec4 box(fly + sel, selszs); - // clang-format off - int start = layouts[0][raw_sel].pos.y() == - layouts[0][layouts[0].size() - 1].pos.y() - ? 0 : raw_sel + 3; - // clang-format on + vec2 tpos = layouts[0][raw_sel].pos; + vec2 tsize = layouts[0][raw_sel].size; + float tcen = tpos.x() + (tsize.x() * 0.5); + int bidx = -1; + float min_diff = std::numeric_limits::max(); + float try_ = -1; + + int start = raw_sel + 1; + if (tpos.y() == layouts[0][layouts[0].size() - 1].pos.y()) { + start = 0; + } + for (int i = start; i < (int)layouts[0].size(); i++) { - if (LI::Renderer::InBox(fly + layouts[0][i].pos, sel_szs, box)) { - raw_sel = i; - break; + auto& tk = layouts[0][i]; + + if (tk.pos.y() != tpos.y()) { + if (try_ == -1) { + try_ = tk.pos.y(); + } + if (tk.pos.y() != try_) { + break; + } + + float tcenl = tk.pos.x() + (tk.size.x() * 0.5); + float diff = std::abs(tcen - tcenl); + if (diff < min_diff) { + min_diff = diff; + bidx = i; + } } } + + if (bidx != -1) { + raw_sel = bidx; + } MoveSelector(); } + /// Go right movement if (inp->IsUp(inp->Right)) { if ((raw_sel + 1 >= (int)layouts[0].size()) || layouts[0][raw_sel].pos.y() != layouts[0][raw_sel + 1].pos.y()) { @@ -353,6 +386,7 @@ void Keyboard::Movement(Hid::Ref inp) { } MoveSelector(); } + // Go left Movement if (inp->IsUp(inp->Left)) { if (raw_sel - 1 < 0 || layouts[0][raw_sel].pos.y() != layouts[0][raw_sel - 1].pos.y()) { @@ -415,7 +449,7 @@ void Keyboard::RecolorBy(KeyOperation op, u32 color, int cm) { /// Not the fastest but the best for custom layouts for (auto& it : layouts[cm]) { if (it.op == op) { - keys[cm]->ReColorQuad(i, PD::Color(0xff222222)); + keys[cm]->ReColorQuad(i, PD::Color(0xaa222222)); break; } i++; @@ -423,10 +457,10 @@ void Keyboard::RecolorBy(KeyOperation op, u32 color, int cm) { } void Keyboard::InputOpBind(Hid::Key k, KeyOperation op, Hid::Ref inp, int cm) { if (inp->IsUp(k)) { - RecolorBy(op, PD::Color(0xff222222), cm); + RecolorBy(op, PD::Color(0xaa222222), cm); DoOperation(op, ""); } else if (inp->IsHeld(k)) { - RecolorBy(op, PD::Color(0xff333333), cm); + RecolorBy(op, PD::Color(0xaa333333), cm); } } @@ -504,18 +538,18 @@ void Keyboard::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) { keys[cm]->ReCopy(); int ii = 0; for (auto& it : layouts[mode]) { - PD::Color bgc(0xff444444); + PD::Color bgc(0xaa444444); if (((ren->InBox(inp->TouchPosLast(), vec4(start + it.pos, it.size)) && inp->IsHeld(inp->Touch)) || (inp->IsHeld(inp->A) && ii == raw_sel)) && flymgr.IsFinished()) { - bgc = PD::Color(0xff333333); + bgc = PD::Color(0xaa333333); } if (((ren->InBox(inp->TouchPosLast(), vec4(start + it.pos, it.size)) && inp->IsUp(inp->Touch)) || (inp->IsUp(inp->A) && ii == raw_sel)) && flymgr.IsFinished()) { - bgc = PD::Color(0xff222222); + bgc = PD::Color(0xaa222222); DoOperation(it.op, it.k); } /// This is hardcoded shit guessing that the @@ -536,7 +570,7 @@ void Keyboard::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) { if (raw_sel != -1) { ren->Layer(l); ren->DrawRectSolid(start + selector - vec2(1), vec2(sel_szs) + vec2(2), - 0xffffffff); + 0xaaffffff); ren->Layer(l); } keys[cm]->ReLayer(l); diff --git a/source/overlays/performance.cpp b/source/overlays/performance.cpp index 930f0a2..693e217 100644 --- a/source/overlays/performance.cpp +++ b/source/overlays/performance.cpp @@ -12,7 +12,7 @@ void Performance::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) { ren->OnScreen(Screen::Top); ren->TextScale(0.6); vec2 pos; - Line(pos, std::format("FPS {:.1f} FPS | {:.2f}ms", 1000.f / delta, delta), + Line(pos, std::format("FPS {:.1f} FPS / {:.2f}ms", 1000.f / delta, delta), ren); Line(pos, "Ren [AVG]: " + TSA("LI_RenderAll"), ren); Line(pos, "App [AVG]: " + TSA("App_MainLoop"), ren); @@ -25,6 +25,8 @@ void Performance::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) { "DC: [" + std::to_string(ren->DrawCalls()) + ", " + std::to_string(ren->Commands()) + "]", ren); + Line(pos, "AST: " + std::to_string(ren->AstUsage()), ren); + Line(pos, "TMS: " + std::to_string(ren->TmsUsage()), ren); ren->DefaultTextScale(); } diff --git a/source/ui7/ui7.cpp b/source/ui7/ui7.cpp new file mode 100644 index 0000000..e69de29 diff --git a/test/main.cpp b/test/main.cpp index 806c1cd..4305922 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -104,6 +104,7 @@ class Test : public PD::App { PD::Keyboard::State state; PD::UI7::Context::Ref ui7; PD::LI::Font::Ref font; + vec2 text_pos; }; int main() {