diff --git a/include/pd/ui7/flags.hpp b/include/pd/ui7/flags.hpp index e420ab8..fd869cd 100644 --- a/include/pd/ui7/flags.hpp +++ b/include/pd/ui7/flags.hpp @@ -38,7 +38,8 @@ enum UI7MenuFlags_ { 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 - UI7MenuFlags_NoMove = 1 << 7, ///< Disable Window Movement + UI7MenuFlags_NoMove = 1 << 7, ///< Disable Menu Movement + UI7MenuFlags_NoResize = 1 << 8, ///< Disable Menu Resize // Enable Horizontal and Vertical Scrolling UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling, }; diff --git a/include/pd/ui7/io.hpp b/include/pd/ui7/io.hpp new file mode 100644 index 0000000..ba5559f --- /dev/null +++ b/include/pd/ui7/io.hpp @@ -0,0 +1,60 @@ +#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 +#include +#include +#include +#include +#include + +namespace PD { +namespace UI7 { +/** + * Shared Configuration and Runtime Data for a UI7 Context + */ +class IO : public SmartCtor { + public: + /** + * IO Constructor setting UP References + */ + IO(Hid::Ref input_driver) { + Time = Timer::New(); + Theme = UI7::Theme::New(); + Inp = input_driver; + }; + ~IO() = default; + + float Framerate = 0.f; + float Delta = 0.f; + Timer::Ref Time; + Hid::Ref Inp; + UI7::Theme::Ref Theme; + float MenuPadding = 5.f; + DrawList::Ref Back; + DrawList::Ref Front; +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/menu.hpp b/include/pd/ui7/menu.hpp index 48d92a2..842498b 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 pos + cursor; } + vec2 Cursor() const { return view_area.xy() + cursor; } /** * Set the Cursor position * @note The old Position can be restored with RestoreCursor @@ -347,7 +347,7 @@ class Menu : public SmartCtor { vec2 cursor; ///< Current Cursor Position vec2 bcursor; ///< Backup Cursor vec2 slcursor; ///< Sameline Cursor - vec4 view_area; ///< view Area + vec4 view_area; ///< view Area (Position and Size) vec4 main_area; ///< Main Area [Input related] vec2 scrolling_off; ///< Scrolling Position bool scrolling[2]; ///< Is Hz or Vt Scrolling Enabled @@ -356,7 +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 + bool is_open = true; ///< For Collapse Event Container::Ref tmp_parent; ///< Parent Container (for better alignment etc) @@ -378,7 +378,6 @@ 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 bfe64be..4855d6c 100644 --- a/include/pd/ui7/ui7.hpp +++ b/include/pd/ui7/ui7.hpp @@ -28,6 +28,7 @@ SOFTWARE. #include #include #include +#include #include #include /** @@ -36,7 +37,7 @@ SOFTWARE. * Major Minor Patch Build * 0x01010000 -> 1.1.0-0 */ -#define UI7_VERSION 0x00020701 +#define UI7_VERSION 0x00020702 namespace PD { namespace UI7 { @@ -58,6 +59,7 @@ class Context : public SmartCtor { /// Set the Internal References this->ren = ren; this->inp = hid; + io = IO::New(hid); /// Init Theme and Front / Back Drawlists theme = Theme::New(); back = DrawList::New(ren); @@ -125,6 +127,9 @@ class Context : public SmartCtor { /** Get the Root Layer of the Menu */ int RootLayer() const { return root_layer; } + /** Get IO Reference */ + IO::Ref GetIO() { return io; } + // Debugging / Demo / About /** About Menu */ @@ -167,6 +172,9 @@ class Context : public SmartCtor { // Deltatime Average TimeStats::Ref s_delta; + + // IO + IO::Ref io; }; } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/source/ui7/menu.cpp b/source/ui7/menu.cpp index ff8aeb3..0d479a7 100644 --- a/source/ui7/menu.cpp +++ b/source/ui7/menu.cpp @@ -79,6 +79,9 @@ void UI7::Menu::Image(Texture::Ref img, vec2 size) { } void UI7::Menu::DebugLabels(Menu::Ref m, Menu::Ref t) { + if (!m) { + return; + } if (t == nullptr) { t = m; } @@ -87,7 +90,11 @@ void UI7::Menu::DebugLabels(Menu::Ref m, Menu::Ref t) { s << std::hex << std::setw(8) << std::setfill('0') << m->id; s << std::dec << "]"; t->Label(s.str()); - t->Label(std::format("Size: {:.2f}, {:.2f}", m->max.x(), m->max.y())); + t->Label(std::format("Max Size: {:.2f}, {:.2f}", m->max.x(), m->max.y())); + t->Label(std::format("Pos: {:.2f}, {:.2f} Size: {:.2f}, {:.2f}", + m->view_area.x(), m->view_area.y(), m->view_area.z(), + m->view_area.w())); + t->Label(std::format("Flags: {:#08x}", m->flags)); t->Label( "Pre: " + Strings::FormatNanos( @@ -113,9 +120,9 @@ void UI7::Menu::Update(float delta) { scrolling_off = scroll_anim; } if (!(flags & UI7MenuFlags_NoClipRect)) { - main->PushClipRect(vec4(pos.x() + 5, pos.y() + tbh, - pos.x() + view_area.z() - 12, - pos.y() + view_area.w())); + main->PushClipRect(vec4(view_area.x() + 5, view_area.y() + tbh, + view_area.x() + view_area.z() - 12, + view_area.y() + view_area.w())); } std::vector tbr; for (int i = 0; i < (int)objects.size(); i++) { @@ -174,16 +181,19 @@ void UI7::Menu::PreHandler(UI7MenuFlags flags) { this->scrolling[1] = flags & UI7MenuFlags_VtScrolling; has_touch = main->ren->CurrentScreen()->ScreenType() == Screen::Bottom; if (!(flags & UI7MenuFlags_NoBackground) && is_open) { - back->AddRectangle(pos, view_area.zw(), theme->Get(UI7Color_Background)); + back->AddRectangle(view_area.xy() + vec2(0, tbh), + view_area.zw() - vec2(0, tbh), + theme->Get(UI7Color_Background)); } if (!(flags & UI7MenuFlags_NoTitlebar)) { + // Title bar setup and Rendering tbh = front->ren->TextScale() * 30.f; - front->AddRectangle(pos, vec2(view_area.z(), tbh), + front->AddRectangle(view_area.xy(), 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; + vec2 cpos = view_area.xy() + 5; UI7Color clr = UI7Color_FrameBackground; if (inp->IsUp(inp->Touch) && LI::Renderer::InBox(inp->TouchPosLast(), vec4(cpos, vec2(18, tbh))) && @@ -213,43 +223,69 @@ void UI7::Menu::PreHandler(UI7MenuFlags flags) { tflags = LITextFlags_AlignMid; } front->Layer(front->Layer() + 1); - front->AddText(pos + tpos, this->name, theme->Get(UI7Color_Text), tflags, - vec2(view_area.z(), tbh)); + front->AddText(view_area.xy() + 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())); + // Menu Movement + if (!(flags & UI7MenuFlags_NoMove)) { + if (inp->IsDown(inp->Touch) && + LI::Renderer::InBox( + inp->TouchPos(), + vec4(view_area.xy() + 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(view_area.xy() + vec2(18, 0), + vec2(view_area.z(), tbh))) && + has_touch) { + mouse = 0; + } else if (inp->IsHeld(inp->Touch) && + LI::Renderer::InBox(inp->TouchPos(), + vec4(view_area.xy() + vec2(18, 0), + vec2(view_area.z(), tbh))) && + has_touch) { + view_area = + vec4(view_area.xy() + (inp->TouchPos() - mouse), view_area.zw()); + mouse = inp->TouchPos(); + } } } + // Add a clip Rect for Separators + if (!(flags & UI7MenuFlags_NoClipRect)) { + main->PushClipRect(vec4(view_area.x() + 5, view_area.y() + tbh, + view_area.x() + view_area.z() - 12, + view_area.y() + view_area.w())); + } } void UI7::Menu::PostHandler() { TT::Scope st("MPOS_" + name); - if (!(flags & UI7MenuFlags_NoMove)) { + if (!(flags & UI7MenuFlags_NoResize)) { + front->AddRectangle(view_area.xy() + view_area.zw() - 20, 20, 0xffffffff); if (inp->IsDown(inp->Touch) && - LI::Renderer::InBox(inp->TouchPos(), vec4(pos + vec2(18, 0), - vec2(view_area.z(), tbh))) && + LI::Renderer::InBox(inp->TouchPos(), + vec4(view_area.xy() + view_area.zw() - 20, 20)) && 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 (inp->IsHeld(inp->Touch) && + LI::Renderer::InBox(inp->TouchPos(), + vec4(view_area.xy() + view_area.zw() - 20, 20)) && + has_touch) { + view_area = + vec4(view_area.xy(), view_area.zw() + (inp->TouchPos() - mouse)); + mouse = inp->TouchPos(); + } + // Not vidible dor some reason + // front->AddTriangle(10, vec2(10, 0), vec2(10, 0), 0xffffffff); } if (scrolling[1]) { - scroll_allowed[1] = (max[1] > 235); + scroll_allowed[1] = (max[1] > view_area.w() - 5); + if (max[1] < view_area.w() - 5) { + scrolling_off[1] = 0.f; + } scrollbar[1] = scroll_allowed[1]; if (scrollbar[1]) { @@ -298,7 +334,8 @@ void UI7::Menu::PostHandler() { mouse = vec2(); } if (inp->IsHeld(inp->Touch)) { - if (front->ren->InBox(tpos, main_area)) { + if (front->ren->InBox(tpos, vec4(view_area.xy() + main_area.xy(), + main_area.zw()))) { if (scrolling_off[1] < max[1] - view_area[3] + 40 && scrolling_off[1] > -40) { /// Cursor Mod @@ -333,7 +370,8 @@ void UI7::Menu::PostHandler() { /// Probably need a new API for this auto tp = inp->TouchPos(); if (inp->IsHeld(inp->Touch) && - LI::Renderer::InBox(tp, vec4(screen_w - 12, tsp, 8, szs))) { + LI::Renderer::InBox(tp, vec4(view_area.x() + screen_w - 12, + view_area.y() + tsp, 8, szs))) { float drag_center = vslider_h / 2.0f; float drag_pos = std::clamp(static_cast((tp[1] - tsp - drag_center) / @@ -349,13 +387,13 @@ void UI7::Menu::PostHandler() { 0.f, float(szs - vslider_h - 4)); /// Rendering Stage - front->AddRectangle(pos + vec2(screen_w - 12, tsp), + front->AddRectangle(view_area.xy() + vec2(screen_w - 12, tsp), vec2(slider_w * 2, szs), theme->Get(UI7Color_FrameBackground)); - front->AddRectangle(pos + vec2(screen_w - 10, tsp + 2), + front->AddRectangle(view_area.xy() + vec2(screen_w - 10, tsp + 2), vec2(slider_w, szs - 4), theme->Get(UI7Color_FrameBackgroundHovered)); - front->AddRectangle(pos + vec2(screen_w - 10, srpos + 2), + front->AddRectangle(view_area.xy() + vec2(screen_w - 10, srpos + 2), vec2(slider_w, vslider_h), theme->Get(UI7Color_Button)); } @@ -405,12 +443,12 @@ void UI7::Menu::SeparatorText(const std::string& label) { } } if (!(alignment & UI7Align_Left)) { - main->AddRectangle(pos + vec2(0, tdim.y() * 0.5), - vec2(lpos.x() - pos.x() - 5, size.y()), + main->AddRectangle(rpos + vec2(0, tdim.y() * 0.5), + vec2(lpos.x() - rpos.x() - 5, size.y()), theme->Get(UI7Color_TextDead)); } if (!(alignment & UI7Align_Right)) { - main->AddRectangle(pos + vec2(lpos.x() + tdim.x(), tdim.y() * 0.5), + main->AddRectangle(rpos + vec2(lpos.x() + tdim.x(), tdim.y() * 0.5), vec2(size.x() - (lpos.x() + tdim.x()), size.y()), theme->Get(UI7Color_TextDead)); } diff --git a/source/ui7/ui7.cpp b/source/ui7/ui7.cpp index 90614bd..b15fb0e 100644 --- a/source/ui7/ui7.cpp +++ b/source/ui7/ui7.cpp @@ -40,6 +40,7 @@ bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags) { auto menu = this->menus.find(id); if (menu == this->menus.end()) { this->menus[id] = Menu::New(id, theme, inp); + this->menus[id]->ViewArea(this->ren->GetViewport()); menu = this->menus.find(id); } this->current = menu->second; @@ -55,7 +56,6 @@ bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags) { this->current->FrontList(DrawList::New(ren)); this->current->FrontList()->BaseLayer(root_layer + 50); } - this->current->ViewArea(this->ren->GetViewport()); this->current->PreHandler(flags); amenus.push_back(this->current->GetID()); if (!this->current->is_open) { @@ -129,10 +129,11 @@ void UI7::Context::MetricsMenu() { 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("Menus: " + std::to_string(menus.size())); + m->SeparatorText("Lithium"); 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(); } }