diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dcd0ec..3e0ee87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,7 @@ execute_process( ) # Set Project -project(palladium LANGUAGES C CXX VERSION 0.3.0) +project(palladium LANGUAGES C CXX VERSION 0.3.1) option(PD_BUILD_TESTS "Sets if TestApp and TestBench get build" OFF) @@ -131,6 +131,7 @@ source/app/error.cpp) set(UI7_SRC source/ui7/drawlist.cpp source/ui7/io.cpp +source/ui7/layout.cpp source/ui7/menu.cpp source/ui7/theme.cpp source/ui7/ui7.cpp @@ -138,6 +139,7 @@ source/ui7/container/container.cpp source/ui7/container/button.cpp source/ui7/container/checkbox.cpp source/ui7/container/coloredit.cpp +source/ui7/container/dragdata.cpp source/ui7/container/image.cpp source/ui7/container/label.cpp) diff --git a/README.md b/README.md index bdfe27d..8ba03be 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ make install | pd-lithium | 0.2.9 | 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.9 | 3ds | pd-core, pd-image, pd-lib3ds, pd-lithium | +| pd-ui7 | 0.3.1 | 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/container/button.hpp b/include/pd/ui7/container/button.hpp index 31514bd..c41370a 100644 --- a/include/pd/ui7/container/button.hpp +++ b/include/pd/ui7/container/button.hpp @@ -54,9 +54,8 @@ class Button : public Container { /** * Override for the Input Handler * @note This function is usally called by Menu::Update - * @param inp Reference to the Input Handler */ - void HandleInput(Hid::Ref inp) override; + void HandleInput() override; /** * Override for the Rendering Handler * @note This function is usally called by Menu::Update diff --git a/include/pd/ui7/container/checkbox.hpp b/include/pd/ui7/container/checkbox.hpp index 363a2a3..63b2ef5 100644 --- a/include/pd/ui7/container/checkbox.hpp +++ b/include/pd/ui7/container/checkbox.hpp @@ -50,9 +50,8 @@ class Checkbox : public Container { /** * Override for the Input Handler * @note This function is usally called by Menu::Update - * @param inp Reference to the Input Handler */ - void HandleInput(Hid::Ref inp) override; + void HandleInput() override; /** * Override for the Rendering Handler * @note This function is usally called by Menu::Update diff --git a/include/pd/ui7/container/coloredit.hpp b/include/pd/ui7/container/coloredit.hpp index 898a263..257ce73 100644 --- a/include/pd/ui7/container/coloredit.hpp +++ b/include/pd/ui7/container/coloredit.hpp @@ -25,6 +25,7 @@ SOFTWARE. #include #include +#include namespace PD { namespace UI7 { @@ -51,9 +52,8 @@ class ColorEdit : public Container { /** * Override for the Input Handler * @note This function is usally called by Menu::Update - * @param inp Reference to the Input Handler */ - void HandleInput(Hid::Ref inp) override; + void HandleInput() override; /** * Override for the Rendering Handler * @note This function is usally called by Menu::Update @@ -68,6 +68,8 @@ class ColorEdit : public Container { u32* color_ref = nullptr; ///< Color Reference u32 initial_color; ///< Initial Color std::string label; ///< Label of the Button + Layout::Ref layout; ///< Layout to open + bool is_shown = false; ///< AHow Layout Editor }; } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/container/container.hpp b/include/pd/ui7/container/container.hpp index 31cb550..5db20df 100644 --- a/include/pd/ui7/container/container.hpp +++ b/include/pd/ui7/container/container.hpp @@ -103,7 +103,7 @@ class Container : public SmartCtor { */ void HandleScrolling(vec2 scrolling, vec4 viewport); /** Template function for Input Handling */ - virtual void HandleInput(Hid::Ref inp) {} + virtual void HandleInput() {} /** Tamplate function for Object rendering */ virtual void Draw() {} /** Template function to update internal data (if needed) */ diff --git a/include/pd/ui7/container/dragdata.hpp b/include/pd/ui7/container/dragdata.hpp new file mode 100644 index 0000000..f953681 --- /dev/null +++ b/include/pd/ui7/container/dragdata.hpp @@ -0,0 +1,79 @@ +#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 + +namespace PD { +namespace UI7 { +/** + * DragData Object can take a datatype or a list + * and modifys these by moving left or right when dragging + */ +template +class DragData : public Container { + public: + /** + * Constructor + * @param label Label of the Button + * @param pos Base Position + * @param lr Reference to the Renderer + */ + DragData(const std::string& label, T* data, size_t num_elms, UI7::IO::Ref io, + T min = 0, T max = 100) { + PD::Assert(data != nullptr, "Input Data Address is null!"); + this->label = label; + this->data = data; + this->elm_count = num_elms; + this->min = min; + this->max = max; + this->tdim = io->Ren->GetTextDimensions(label); + } + ~DragData() = default; + + /** + * 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: + vec2 tdim; ///< Text size + std::string label; ///< Label of the Button + T* data; + size_t elm_count = 0; + T min; + T max; +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/containers.hpp b/include/pd/ui7/containers.hpp index d09eae2..b62d536 100644 --- a/include/pd/ui7/containers.hpp +++ b/include/pd/ui7/containers.hpp @@ -26,5 +26,6 @@ SOFTWARE. #include #include #include +#include #include -#include +#include \ No newline at end of file diff --git a/include/pd/ui7/flags.hpp b/include/pd/ui7/flags.hpp index 05772d6..2a6d00e 100644 --- a/include/pd/ui7/flags.hpp +++ b/include/pd/ui7/flags.hpp @@ -29,6 +29,8 @@ using UI7MenuFlags = unsigned int; using UI7Align = unsigned int; /** 32Bit Value to store Context (IO) flags */ using UI7IOFlags = unsigned int; +/** 32Bit Value for Layout Flags */ +using UI7LayoutFlags = unsigned int; /** Menu Flags */ enum UI7MenuFlags_ { @@ -48,6 +50,12 @@ enum UI7MenuFlags_ { UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling, }; +/** UI7 Layout Flags */ +enum UI7LayoutFlags_ { + UI7LayoutFlags_None = 0, ///< No Flags used + UI7LayoutFlags_UseClipRect = 1 << 0, ///< Enable ClipRect +}; + /** UI7 Context Flags */ enum UI7IOFlags_ { UI7IOFlags_None = 0, ///< No Additional Config available diff --git a/include/pd/ui7/io.hpp b/include/pd/ui7/io.hpp index 3340841..e7227c9 100644 --- a/include/pd/ui7/io.hpp +++ b/include/pd/ui7/io.hpp @@ -61,6 +61,7 @@ class IO : public SmartCtor { float Framerate = 0.f; float Delta = 0.f; + u64 LastTime = 0; TimeStats::Ref DeltaStats; Timer::Ref Time; Hid::Ref Inp; @@ -69,7 +70,8 @@ class IO : public SmartCtor { vec2 MenuPadding = 5.f; vec2 FramePadding = 5.f; vec2 ItemSpace = vec2(5.f, 2.f); - u64 DoubleClickTime = 500; // Milliseconds + vec2 MinSliderDragSize = 10.f; // Min height (Vt) and Min Width (Hz) + u64 DoubleClickTime = 500; // Milliseconds std::vector> DrawListRegestry; DrawList::Ref Back; DrawList::Ref Front; diff --git a/include/pd/ui7/layout.hpp b/include/pd/ui7/layout.hpp new file mode 100644 index 0000000..ca2c538 --- /dev/null +++ b/include/pd/ui7/layout.hpp @@ -0,0 +1,119 @@ +#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 + +namespace PD { +namespace UI7 { +class Layout : public PD::SmartCtor { + public: + Layout(const ID& id, IO::Ref io) : ID(id) { + this->IO = io; + DrawList = UI7::DrawList::New(io->Ren); + Scrolling[0] = false; + Scrolling[1] = false; + CursorInit(); + Pos = vec2(0, 0); + Size = vec2(320, 240); + WorkRect = vec4(IO->MenuPadding, Size - (vec2(2) * IO->MenuPadding)); + } + ~Layout() = default; + + const std::string& GetName() const { return ID.GetName(); } + const UI7::ID& GetID() const { return this->ID; } + + const vec2& GetPosition() const { return Pos; } + void SetPosition(const vec2& v) { Pos = v; } + const vec2& GetSize() const { return Size; } + void SetSize(const vec2& v) { Size = v; } + + UI7::DrawList::Ref GetDrawList() { return DrawList; } + + void CursorInit(); + void SameLine(); + void CursorMove(const vec2& size); + + bool ObjectWorkPos(vec2& movpos); + + void AddObject(Container::Ref obj); + Container::Ref FindObject(u32 id); + + vec2 AlignPosition(vec2 pos, vec2 size, vec4 area, UI7Align alignment); + + /** Get the Alignment for Current State */ + UI7Align GetAlignment() { + /// if temp alignment is used then return it and + /// reset tmpalign + if (TempAlign) { + auto t = TempAlign; + TempAlign = 0; + return t; + } + return Alignment; + } + + void SetAlign(UI7Align a) { Alignment = a; } + void NextAlign(UI7Align a) { TempAlign = a; } + + void Update(); + + private: + friend class Menu; + friend class Context; + // Base Components + UI7::ID ID; + UI7::IO::Ref IO; + UI7::DrawList::Ref DrawList; + + // Positioning + vec2 Pos; + vec2 Size; + UI7Align Alignment = UI7Align_Default; + UI7Align TempAlign; + + // Cursor + vec2 Cursor; + vec2 InitialCursorOffset; + vec2 BackupCursor; + vec2 SamelineCursor; + vec2 BeforeSameLine; + vec2 LastObjSize; + vec2 MaxPosition; + vec4 WorkRect; + + // Scrolling + vec2 ScrollOffset; + bool Scrolling[2]; + + // Objects + std::vector Objects; + std::vector IDObjects; +}; +} // 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 26a6926..1c0489f 100644 --- a/include/pd/ui7/menu.hpp +++ b/include/pd/ui7/menu.hpp @@ -30,6 +30,7 @@ SOFTWARE. #include #include #include +#include namespace PD { namespace UI7 { @@ -47,12 +48,11 @@ class Menu : public SmartCtor { this->id = id; this->name = id.GetName(); /// Set Default Values here - scrolling[0] = false; - scrolling[1] = false; scrollbar[0] = false; scrollbar[1] = false; scroll_allowed[0] = false; scroll_allowed[1] = false; + Layout = UI7::Layout::New(id, io); } ~Menu() = default; @@ -88,6 +88,19 @@ class Menu : public SmartCtor { * @param color Color reference to edit */ void ColorEdit(const std::string& label, u32* color); + + void DragFloat(const std::string& label, float* data, size_t num_elms); + template + void DragData(const std::string& label, T* data, size_t num_elms = 1, + T min = 0, T max = 100) { + u32 id = Strings::FastHash("dfl" + label + std::to_string(count_btn++)); + Container::Ref r = Layout->FindObject(id); + if (!r) { + r = PD::New>(label, data, num_elms, io, min, max); + r->SetID(id); + } + Layout->AddObject(r); + } // Basic API /** @@ -102,7 +115,7 @@ class Menu : public SmartCtor { void EndTreeNode(); /** Add the Next Objext to the same line */ - void SameLine(); + void SameLine() { Layout->SameLine(); } /** Add a Separator Line */ void Separator(); /** @@ -128,23 +141,14 @@ class Menu : public SmartCtor { * Set a Temp alignment op for the next Object * @param a Alignment Operation */ - void NextAlign(UI7Align a) { tmpalign = a; } + void NextAlign(UI7Align a) { Layout->NextAlign(a); } /** * Align Every Single Object by this operationset * @param a Alignment */ - void PushAlignment(UI7Align a) { alignment = a; } + void PushAlignment(UI7Align a) { Layout->SetAlign(a); } /** Use default alignment */ - void PopAlignment() { alignment = UI7Align_Default; } - /** - * Get a New Position depending on the Alignment - * @param pos Current Position - * @param size Object size - * @param view Viewport [position and size] - * @param a Alignment Operations - * @return new position based on the alignment - */ - static vec2 AlignPos(vec2 pos, vec2 size, vec4 view, UI7Align a); + void PopAlignment() { Layout->Alignment = UI7Align_Default; } /** * Returns a Reference to the theme * @return Reference to the base Theme of the context @@ -166,35 +170,6 @@ class Menu : public SmartCtor { // API for Custom Objects - /** - * Handles the Position of Objects in Scrolling Menu - * @note As Containers have their own FUnc to handle this, this - * function is only useful to Render Live Objects whicch cannot be aligned - * by the internal Alignment Api - * @param pos position reference to write the new position to - * @param size size of the Object - * @return if the object can be skipped in rendering - */ - bool HandleScrolling(vec2& pos, const vec2& size); - /** - * Get the Cursor Position - * @return Cursor Pos - */ - vec2 Cursor() const { return view_area.xy() + cursor; } - /** - * Set the Cursor position - * @note The old Position can be restored with RestoreCursor - * @param v New Position - */ - void Cursor(const vec2& v) { - bcursor = cursor; - cursor = v; - } - /** Restore to the last cursor Position */ - void RestoreCursor() { - cursor = bcursor; - bcursor = vec2(); - } /** Return if a Vertical Scrollbar exists */ bool HasVerticalScrollbar() { return scrollbar[1]; } /** Return if a Horizontal Scrollbar exists */ @@ -206,43 +181,13 @@ class Menu : public SmartCtor { * @note Could destroy some basic functionality */ void TitleBarHeight(float v) { tbh = v; } - /** - * Init the Cursor - * @note Useful when using with a Custom TitlebarHeight - */ - void CursorInit() { Cursor(io->MenuPadding + vec2(0, tbh)); } - /** - * Move the Cursor for new Object - * @param szs Size of the current Object - */ - void CursorMove(const vec2& szs); - /** Get the ViewArea of the Menu */ - vec4 ViewArea() const { return view_area; } - /** - * Get the Main Area of the Menu - * (only relevant for input) - */ - vec4 MainArea() const { return main_area; } - /** - * Set a MainArea for input - * @param v Area where Objects can receive inputs - */ - void MainArea(const vec4& v) { main_area = v; } - /** Get The Scrolling offset */ - vec2 ScrollOffset() const { return scrolling_off; } - /** - * Set a Scrolling offset - * @param v Custom Scrolling offset - */ - void ScrollOffset(const vec2& v) { scrolling_off = v; } - /** Get the Current Scrollmodification value */ - vec2 ScrollMod() const { return scroll_mod; } + /** * Animated Scroll to Position * @param pos Destination Position */ void ScrollTo(vec2 pos) { - scroll_anim.From(scrolling_off) + scroll_anim.From(Layout->ScrollOffset) .To(pos) .In(1.f) .As(scroll_anim.EaseInOutSine); @@ -252,19 +197,6 @@ class Menu : public SmartCtor { // Objects API - /** - * Push an object to the current ListHandler - * @param obj Object reference to use - * @return Reference to the Object (from a time - * where ObjectPush(Container::New()) was used) - */ - Container::Ref ObjectPush(Container::Ref obj); - /** - * Search for an Object by an id - * @param id 32 Bit hash/id - * @return the found Object or nullptr - */ - Container::Ref FindIDObj(u32 id); /** * Create a Parent Container to move and edit all sub * instances at once @@ -276,7 +208,8 @@ class Menu : public SmartCtor { // Draw List /** Get DrawList */ - DrawList::Ref GetDrawList() { return main; } + DrawList::Ref GetDrawList() { return Layout->DrawList; } + UI7::Layout::Ref GetLayout() { return Layout; } // Advanced @@ -305,43 +238,6 @@ class Menu : public SmartCtor { /** Handle things like scrolling */ void PostHandler(); - // Basic Settings - - /** - * Set Backup Cursor - * @param v Position - */ - void BackupCursor(const vec2& v) { bcursor = v; } - /** Get Sameline Cursor */ - vec2 SameLineCursor() const { return slcursor; } - /** - * Set Sameline Cursor - * @param v Position - */ - void SameLineCursor(const vec2& v) { slcursor = v; } - /** - * Set View Area - * @param v vec4 containing pos and size - */ - void ViewArea(const vec4& v) { view_area = v; } - /** - * Set Scroll Modification - * @param v Mod - */ - void ScrollMod(const vec2& v) { scroll_mod = v; } - - /** Get the Alignment for Current State */ - UI7Align GetAlignment() { - /// if temp alignment is used then return it and - /// reset tmpalign - if (tmpalign) { - auto t = tmpalign; - tmpalign = 0; - return t; - } - return alignment; - } - /** Internal Processing */ void Update(float delta); @@ -363,21 +259,9 @@ class Menu : public SmartCtor { // Data - // Default Alignment for all Objects - UI7Align alignment = UI7Align_Default; - UI7Align tmpalign = 0; ///< Temp Alignment [only used once] UI7MenuFlags flags = 0; ///< Menu Flags u32 id; ///< Menu ID std::string name; ///< Menu Name - vec2 cursor; ///< Current Cursor Position - vec2 icursoroff; ///< Initial Cursor Offset (Also in Newline) - vec2 bcursor; ///< Backup Cursor - vec2 slcursor; ///< Sameline Cursor - 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 - vec2 scroll_mod; ///< Scroll Modificator float tbh; ///< Titlebar height bool scrollbar[2]; ///< Is Hz or Vt Scrollbar rendered bool scroll_allowed[2]; ///< Is Hz or Vt Scrolling Alowed @@ -389,20 +273,9 @@ class Menu : public SmartCtor { // Objects API - std::vector objects; ///< Current frame Objects - std::vector idobjs; ///< Objects using an ID - std::vector join; ///< List of Combined Objects - int count_btn = 0; ///< Count for Button ID Prefix - int count_cbx = 0; ///< Cound for Checkbox ID Prefix - - // DrawList - - DrawList::Ref main; ///< Main Drawlist - - vec2 max; ///< Max Position - vec2 mouse; ///< Mouse/Touch Position - vec2 bslpos; ///< Before Sameline Position - vec2 last_size; ///< Last Object Size + std::vector join; ///< List of Combined Objects + int count_btn = 0; ///< Count for Button ID Prefix + int count_cbx = 0; ///< Cound for Checkbox ID Prefix UI7::IO::Ref io; ///< IO Reference @@ -411,6 +284,9 @@ class Menu : public SmartCtor { // Animations System Tween scroll_anim; ///< for Scroll to Animation + + // Layout API + PD::UI7::Layout::Ref Layout; }; } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/ui7.hpp b/include/pd/ui7/ui7.hpp index c1773c1..4d88d87 100644 --- a/include/pd/ui7/ui7.hpp +++ b/include/pd/ui7/ui7.hpp @@ -37,7 +37,7 @@ SOFTWARE. * Major Minor Patch Build * 0x01010000 -> 1.1.0-0 */ -#define UI7_VERSION 0x00030000 +#define UI7_VERSION 0x00030100 namespace PD { namespace UI7 { diff --git a/source/ui7/container/button.cpp b/source/ui7/container/button.cpp index 58f0378..e81d6bd 100644 --- a/source/ui7/container/button.cpp +++ b/source/ui7/container/button.cpp @@ -25,7 +25,7 @@ SOFTWARE. namespace PD { namespace UI7 { -void Button::HandleInput(Hid::Ref inp) { +void Button::HandleInput() { /// Ensure to only check input once if (inp_done) { return; diff --git a/source/ui7/container/checkbox.cpp b/source/ui7/container/checkbox.cpp index 091bb77..a0f95ff 100644 --- a/source/ui7/container/checkbox.cpp +++ b/source/ui7/container/checkbox.cpp @@ -25,7 +25,7 @@ SOFTWARE. namespace PD { namespace UI7 { -void Checkbox::HandleInput(Hid::Ref inp) { +void Checkbox::HandleInput() { /// Ensure to only check input once if (inp_done) { return; diff --git a/source/ui7/container/coloredit.cpp b/source/ui7/container/coloredit.cpp index 776ee1e..c46fa5a 100644 --- a/source/ui7/container/coloredit.cpp +++ b/source/ui7/container/coloredit.cpp @@ -22,10 +22,11 @@ SOFTWARE. */ #include +#include namespace PD { namespace UI7 { -void ColorEdit::HandleInput(Hid::Ref inp) { +void ColorEdit::HandleInput() { /// Ensure to only check input once if (inp_done) { return; @@ -34,6 +35,7 @@ void ColorEdit::HandleInput(Hid::Ref inp) { if (screen->ScreenType() == Screen::Bottom) { if (io->DragObject(this->GetID(), vec4(FinalPos(), size))) { if (io->DragReleased) { + is_shown = !is_shown; } } } @@ -45,6 +47,14 @@ void ColorEdit::Draw() { list->AddRectangle(FinalPos(), vec2(20, 20), *color_ref); list->AddText(FinalPos() + vec2(io->ItemSpace.x() + 20, 0), label, io->Theme->Get(UI7Color_Text)); + if (is_shown) { + if (!layout) { + layout = Layout::New(GetID(), io); + } + layout->AddObject(PD::New