From e45598f9f6b98f9d10098208349d29670b20d6d8 Mon Sep 17 00:00:00 2001 From: tobid7 Date: Thu, 6 Mar 2025 18:14:39 +0100 Subject: [PATCH] # Changes 0.2.7 - Add UI7 32Bit Version Num - Fix ClipRect Bug with Separators - Fix Triangle/Rect Render order Bug (UI7 - Bug of Lithium) - Add Position to Menus and Movement by dragging the Title bar - Add Menu Collabse (+ Flag to disable) - Add About and Metrics Menus to Context --- CMakeLists.txt | 2 +- README.md | 6 +- include/pd/ui7/flags.hpp | 2 + include/pd/ui7/menu.hpp | 12 +++- include/pd/ui7/ui7.hpp | 28 +++++++++ source/lithium/renderer.cpp | 1 - source/ui7/menu.cpp | 109 +++++++++++++++++++++++++++++------- source/ui7/ui7.cpp | 55 +++++++++++++++++- 8 files changed, 185 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eb5d2d..f946bb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,7 @@ execute_process( ) # Set Project -project(palladium LANGUAGES C CXX VERSION 0.2.6) +project(palladium LANGUAGES C CXX VERSION 0.2.7) option(PD_BUILD_TESTS "Sets if TestApp and TestBench get build" OFF) diff --git a/README.md b/README.md index 8691003..92c8fc5 100644 --- a/README.md +++ b/README.md @@ -27,16 +27,16 @@ make install | Name | Last Updated | Platform | Depends | |---|---|---|---| -| pd-core | 0.2.4 | multi | none | +| pd-core | 0.2.6 | multi | none | | pd-external | 0.1.0 | multi | none | | pd-image | 0.2.6 | multi | pd-core | | pd-drivers | 0.2.4 | multi | pd-core | | pd-lib3ds | 0.2.4 | 3ds | pd-core, pd-drivers | | pd-net | 0.2.4 | 3ds | pd-core, pd-lib3ds | -| pd-lithium | 0.2.6 | 3ds | pd-core, pd-image pd-lib3ds, citro3d | +| pd-lithium | 0.2.7 | 3ds | pd-core, pd-image pd-lib3ds, citro3d | | pd-sound | 0.2.4 | 3ds | pd-core, mpg123 | | pd-overlays | 0.2.4 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium, pd-ui7 | -| pd-ui7 | 0.2.6 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium | +| pd-ui7 | 0.2.7 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium | | pd-app | 0.2.4 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium | ## Credits diff --git a/include/pd/ui7/flags.hpp b/include/pd/ui7/flags.hpp index 5d2a01c..17779c9 100644 --- a/include/pd/ui7/flags.hpp +++ b/include/pd/ui7/flags.hpp @@ -36,6 +36,8 @@ enum UI7MenuFlags_ { UI7MenuFlags_HzScrolling = 1 << 2, ///< Enable Horizontal Scrolling UI7MenuFlags_VtScrolling = 1 << 3, ///< Enable Vertical Scrolling UI7MenuFlags_NoBackground = 1 << 4, ///< Dont Render Menu Background + UI7MenuFlags_NoClipRect = 1 << 5, ///< Disable clip render area of the Menu + UI7MenuFlags_NoCollapse = 1 << 6, ///< Disable Menu Collapse // Enable Horizontal and Vertical Scrolling UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling, }; diff --git a/include/pd/ui7/menu.hpp b/include/pd/ui7/menu.hpp index a2954ec..48d92a2 100644 --- a/include/pd/ui7/menu.hpp +++ b/include/pd/ui7/menu.hpp @@ -158,7 +158,7 @@ class Menu : public SmartCtor { * Get the Cursor Position * @return Cursor Pos */ - vec2 Cursor() const { return cursor; } + vec2 Cursor() const { return pos + cursor; } /** * Set the Cursor position * @note The old Position can be restored with RestoreCursor @@ -268,8 +268,12 @@ class Menu : public SmartCtor { // Advanced - /** Display Debug Labels of the Menu */ - void DebugLabels(); + /** + * Display Debug Labels of a Menu + * @param m Menu to display Data from + * @param t Target to Write the Labels into + */ + static void DebugLabels(Menu::Ref m, Menu::Ref t = nullptr); // Uneditable Stuff @@ -352,6 +356,7 @@ class Menu : public SmartCtor { bool scrollbar[2]; ///< Is Hz or Vt Scrollbar rendered bool scroll_allowed[2]; ///< Is Hz or Vt Scrolling Alowed bool has_touch; ///< Menu has touch (depends on screen) + bool is_open = true; ///< For Collapse Event Container::Ref tmp_parent; ///< Parent Container (for better alignment etc) @@ -373,6 +378,7 @@ class Menu : public SmartCtor { vec2 mouse; ///< Mouse/Touch Position vec2 bslpos; ///< Before Sameline Position vec2 last_size; ///< Last Object Size + vec2 pos; ///< Menu Position // Theme Theme::Ref theme; diff --git a/include/pd/ui7/ui7.hpp b/include/pd/ui7/ui7.hpp index e793293..7c29ee4 100644 --- a/include/pd/ui7/ui7.hpp +++ b/include/pd/ui7/ui7.hpp @@ -23,15 +23,29 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include #include #include #include #include +/** + * Declare UI7 Version + * Format: 00 00 00 00 + * Major Minor Patch Build + * 0x01010000 -> 1.1.0-0 + */ +#define UI7_VERSION 0x00020700 namespace PD { namespace UI7 { +/** + * Get UI7 Version String + * @param show_build Ahow build num (mostly unused) + * @return Version String (1.0.0-1 for example) + */ +std::string GetVersion(bool show_build = false); /** Base Context for UI7 */ class Context : public SmartCtor { public: @@ -48,6 +62,7 @@ class Context : public SmartCtor { theme = Theme::New(); back = DrawList::New(ren); front = DrawList::New(ren); + s_delta = TimeStats::New(60); } ~Context() = default; @@ -110,6 +125,14 @@ class Context : public SmartCtor { /** Get the Root Layer of the Menu */ int RootLayer() const { return root_layer; } + // Debugging / Demo / About + + /** About Menu */ + void AboutMenu(); + + /** Metrics */ + void MetricsMenu(); + private: // Used in Overlays int root_layer = 0; @@ -139,6 +162,11 @@ class Context : public SmartCtor { DrawList::Ref back; // Active Theme Theme::Ref theme; + + // Metrics + + // Deltatime Average + TimeStats::Ref s_delta; }; } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/source/lithium/renderer.cpp b/source/lithium/renderer.cpp index 757695d..e06be25 100644 --- a/source/lithium/renderer.cpp +++ b/source/lithium/renderer.cpp @@ -152,7 +152,6 @@ void Renderer::QuadCommand(Command::Ref cmd, const Rect& quad, const Rect& uv, void Renderer::TriangleCommand(Command::Ref cmd, const vec2& a, const vec2& b, const vec2& c, u32 col) { - cmd->Index(cmd_idx++).Layer(current_layer).Tex(current_tex); cmd->PushIndex(2).PushIndex(1).PushIndex(0); cmd->PushVertex(Vertex(a, vec2(0.f, 1.f), col)); cmd->PushVertex(Vertex(b, vec2(1.f, 1.f), col)); diff --git a/source/ui7/menu.cpp b/source/ui7/menu.cpp index 3e85f1f..07a4410 100644 --- a/source/ui7/menu.cpp +++ b/source/ui7/menu.cpp @@ -78,28 +78,32 @@ void UI7::Menu::Image(Texture::Ref img, vec2 size) { r->HandleScrolling(scrolling_off, view_area); } -void UI7::Menu::DebugLabels() { +void UI7::Menu::DebugLabels(Menu::Ref m, Menu::Ref t) { + if (t == nullptr) { + t = m; + } std::stringstream s; - s << "Name: " << name << " ["; - s << std::hex << std::setw(8) << std::setfill('0') << id; + s << "Name: " << m->name << " ["; + s << std::hex << std::setw(8) << std::setfill('0') << m->id; s << std::dec << "]"; - this->Label(s.str()); - this->Label( + t->Label(s.str()); + t->Label(std::format("Size: {:.2f}, {:.2f}", m->max.x(), m->max.y())); + t->Label( "Pre: " + Strings::FormatNanos( - Sys::GetTraceRef("MPRE_" + name)->GetProtocol()->GetAverage())); - this->Label( + Sys::GetTraceRef("MPRE_" + m->name)->GetProtocol()->GetAverage())); + t->Label( "Post: " + Strings::FormatNanos( - Sys::GetTraceRef("MPOS_" + name)->GetProtocol()->GetAverage())); - this->Label( + Sys::GetTraceRef("MPOS_" + m->name)->GetProtocol()->GetAverage())); + t->Label( "Update: " + Strings::FormatNanos( - Sys::GetTraceRef("MUPT_" + name)->GetProtocol()->GetAverage())); - this->Label( + Sys::GetTraceRef("MUPT_" + m->name)->GetProtocol()->GetAverage())); + t->Label( "MUser: " + Strings::FormatNanos( - Sys::GetTraceRef("MUSR_" + name)->GetProtocol()->GetAverage())); + Sys::GetTraceRef("MUSR_" + m->name)->GetProtocol()->GetAverage())); } void UI7::Menu::Update(float delta) { @@ -108,7 +112,11 @@ void UI7::Menu::Update(float delta) { if (!scroll_anim.IsFinished()) { scrolling_off = scroll_anim; } - main->PushClipRect(vec4(5, tbh, view_area.z() - 12, view_area.w())); + if (!(flags & UI7MenuFlags_NoClipRect)) { + main->PushClipRect(vec4(pos.x() + 5, pos.y() + tbh, + pos.x() + view_area.z() - 12, + pos.y() + view_area.w())); + } std::vector tbr; for (int i = 0; i < (int)objects.size(); i++) { auto& it = objects[i]; @@ -132,7 +140,9 @@ void UI7::Menu::Update(float delta) { for (auto it : tbr) { idobjs.erase(idobjs.begin() + it); } - main->PopClipRect(); + if (!(flags & UI7MenuFlags_NoClipRect)) { + main->PopClipRect(); + } this->back->Process(); this->main->Process(); this->front->Process(); @@ -163,28 +173,79 @@ void UI7::Menu::PreHandler(UI7MenuFlags flags) { this->scrolling[0] = flags & UI7MenuFlags_HzScrolling; this->scrolling[1] = flags & UI7MenuFlags_VtScrolling; has_touch = main->ren->CurrentScreen()->ScreenType() == Screen::Bottom; - if (!(flags & UI7MenuFlags_NoBackground)) { - back->AddRectangle(0, view_area.zw(), theme->Get(UI7Color_Background)); + if (!(flags & UI7MenuFlags_NoBackground) && is_open) { + back->AddRectangle(pos, view_area.zw(), theme->Get(UI7Color_Background)); } if (!(flags & UI7MenuFlags_NoTitlebar)) { tbh = front->ren->TextScale() * 30.f; - front->AddRectangle(0, vec2(view_area.z(), tbh), + front->AddRectangle(pos, vec2(view_area.z(), tbh), theme->Get(UI7Color_Header)); vec2 tpos(5, tbh * 0.5 - front->ren->GetTextDimensions(name).y() * 0.5); + if (!(flags & UI7MenuFlags_NoCollapse)) { + tpos.x() += 18; + vec2 cpos = pos + 5; + UI7Color clr = UI7Color_FrameBackground; + if (inp->IsUp(inp->Touch) && + LI::Renderer::InBox(inp->TouchPosLast(), vec4(cpos, vec2(18, tbh))) && + has_touch) { + is_open = !is_open; + } + if (inp->IsHeld(inp->Touch) && + LI::Renderer::InBox(inp->TouchPos(), vec4(cpos, vec2(18, tbh))) && + has_touch) { + clr = UI7Color_FrameBackgroundHovered; + } + vec2 positions[2] = { + vec2(12, 6), + vec2(0, 12), + }; + if (is_open) { + float t = positions[0].y(); + positions[0].y() = positions[1].x(); + positions[1].x() = t; + } + this->front->AddTriangle(cpos, cpos + positions[0], cpos + positions[1], + theme->Get(clr)); + } LITextFlags tflags = LITextFlags_None; if (flags & UI7MenuFlags_CenterTitle) { tpos = 0; tflags = LITextFlags_AlignMid; } - front->AddText(tpos, this->name, theme->Get(UI7Color_Text), tflags, + front->Layer(front->Layer() + 1); + front->AddText(pos + tpos, this->name, theme->Get(UI7Color_Text), tflags, vec2(view_area.z(), tbh)); main_area[1] = tbh; CursorInit(); + // Add a clip Rect for Separators + if (!(flags & UI7MenuFlags_NoClipRect)) { + main->PushClipRect(vec4(pos.x() + 5, pos.y() + tbh, + pos.x() + view_area.z() - 12, + pos.y() + view_area.w())); + } } } void UI7::Menu::PostHandler() { TT::Scope st("MPOS_" + name); + if (inp->IsDown(inp->Touch) && + LI::Renderer::InBox(inp->TouchPos(), + vec4(pos + vec2(18, 0), vec2(view_area.z(), tbh))) && + has_touch) { + mouse = inp->TouchPos(); + } else if (inp->IsUp(inp->Touch) && + LI::Renderer::InBox( + inp->TouchPos(), + vec4(pos + vec2(18, 0), vec2(view_area.z(), tbh))) && + has_touch) { + mouse = 0; + } else if (inp->IsHeld(inp->Touch) && + LI::Renderer::InBox( + inp->TouchPosLast(), + vec4(pos + vec2(18, 0), vec2(view_area.z(), tbh))) && + has_touch) { + pos = inp->TouchPos() - mouse; + } if (scrolling[1]) { scroll_allowed[1] = (max[1] > 235); scrollbar[1] = scroll_allowed[1]; @@ -286,15 +347,21 @@ void UI7::Menu::PostHandler() { 0.f, float(szs - vslider_h - 4)); /// Rendering Stage - front->AddRectangle(vec2(screen_w - 12, tsp), vec2(slider_w * 2, szs), + front->AddRectangle(pos + vec2(screen_w - 12, tsp), + vec2(slider_w * 2, szs), theme->Get(UI7Color_FrameBackground)); - front->AddRectangle(vec2(screen_w - 10, tsp + 2), vec2(slider_w, szs - 4), + front->AddRectangle(pos + vec2(screen_w - 10, tsp + 2), + vec2(slider_w, szs - 4), theme->Get(UI7Color_FrameBackgroundHovered)); - front->AddRectangle(vec2(screen_w - 10, srpos + 2), + front->AddRectangle(pos + vec2(screen_w - 10, srpos + 2), vec2(slider_w, vslider_h), theme->Get(UI7Color_Button)); } } + // Remove the Clip Rect + if (!(flags & UI7MenuFlags_NoClipRect)) { + main->PopClipRect(); + } TT::End("MUSR_" + name); } diff --git a/source/ui7/ui7.cpp b/source/ui7/ui7.cpp index 211fcb9..fc0fa6a 100644 --- a/source/ui7/ui7.cpp +++ b/source/ui7/ui7.cpp @@ -25,6 +25,14 @@ SOFTWARE. #include namespace PD { +std::string UI7::GetVersion(bool show_build) { + std::stringstream s; + s << ((UI7_VERSION >> 24) & 0xFF) << "."; + s << ((UI7_VERSION >> 16) & 0xFF) << "."; + s << ((UI7_VERSION >> 8) & 0xFF); + if (show_build) s << "-" << ((UI7_VERSION) & 0xFF); + return s.str(); +} bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags) { Assert(!this->current, "You are already in another Menu!"); Assert(std::find(amenus.begin(), amenus.end(), (u32)id) == amenus.end(), @@ -50,7 +58,10 @@ bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags) { this->current->ViewArea(this->ren->GetViewport()); this->current->PreHandler(flags); amenus.push_back(this->current->GetID()); - return true; + if (!this->current->is_open) { + this->current = nullptr; + } + return this->current->is_open; } UI7::Menu::Ref UI7::Context::GetCurrentMenu() { @@ -74,6 +85,8 @@ void UI7::Context::EndMenu() { void UI7::Context::Update(float delta) { TT::Scope st("UI7_Update"); Assert(current == nullptr, "Still in a Menu!"); + this->delta = delta; + s_delta->Add(delta * 1000); this->back->BaseLayer(root_layer + 10); this->back->Process(); for (auto it : amenus) { @@ -83,4 +96,44 @@ void UI7::Context::Update(float delta) { this->front->Process(); this->amenus.clear(); } + +void UI7::Context::AboutMenu() { + if (this->BeginMenu("About UI7", UI7MenuFlags_Scrolling)) { + auto m = this->GetCurrentMenu(); + + m->Label("Palladium - UI7 " + GetVersion()); + m->Separator(); + m->Label("(c) 2023-2025 René Amthor"); + m->Label("UI7 is licensed under the MIT License."); + m->Label("See LICENSE for more information."); + static bool show_build; + m->Checkbox("Show Build Info", show_build); + if (show_build) { + m->SeparatorText("Build Info"); + m->Label("Full Version -> " + GetVersion(true)); + m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t))); + m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(LI::Vertex))); + m->Label("__cplusplus -> " + std::to_string(__cplusplus)); + m->Label("Compiler -> " + LibInfo::CompiledWith()); + } + this->EndMenu(); + } +} + +void UI7::Context::MetricsMenu() { + if (this->BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling)) { + auto m = this->GetCurrentMenu(); + + m->Label("Palladium - UI7 " + GetVersion()); + m->Separator(); + m->Label(std::format("Average {:.3f} ms/f ({:.1f} FPS)", + ((float)s_delta->GetAverage() / 1000.f), + 1000.f / ((float)s_delta->GetAverage() / 1000.f))); + m->Label(std::format("Vertices: {} Indices: {}", ren->Vertices(), + ren->Indices())); + m->Label("Triangles: " + std::to_string(ren->Indices() / 3)); + m->Label("Menus: " + std::to_string(menus.size())); + this->EndMenu(); + } +} } // namespace PD \ No newline at end of file