diff --git a/CMakeLists.txt b/CMakeLists.txt index 1554c42..88976d2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,22 @@ set(PD_SOURCES source/lithium/font.cpp source/lithium/math.cpp + # UI7 + source/ui7/io.cpp + source/ui7/layout.cpp + source/ui7/menu.cpp + source/ui7/theme.cpp + source/ui7/ui7.cpp + source/ui7/container/button.cpp + source/ui7/container/checkbox.cpp + source/ui7/container/coloredit.cpp + source/ui7/container/container.cpp + source/ui7/container/dragdata.cpp + source/ui7/container/dynobj.cpp + source/ui7/container/image.cpp + source/ui7/container/label.cpp + source/ui7/container/slider.cpp + # Ultra source/ultra/canvas.cpp source/ultra/layout.cpp diff --git a/include/palladium b/include/palladium index 32392d7..94afbe3 100755 --- a/include/palladium +++ b/include/palladium @@ -26,4 +26,5 @@ SOFTWARE. #include #include #include -#include \ No newline at end of file +#include +#include \ No newline at end of file diff --git a/include/pd/ui7/container/button.hpp b/include/pd/ui7/container/button.hpp new file mode 100755 index 0000000..b25c439 --- /dev/null +++ b/include/pd/ui7/container/button.hpp @@ -0,0 +1,75 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 { +/** + * Button Object + * @note Button Press is delayed by 1 frame + * (but the visual reaction is done in the same frame) + * This only means that InPressed is responding the info in + * the next frame + */ +class PD_API Button : public Container { + public: + /** + * Button Object constructor + * @param label Label of the Button + * @param pos Base Position + * @param lr Reference to the Renderer + */ + Button(const std::string& label, UI7::IO& io) { + this->label = label; + this->tdim = io.Font->GetTextBounds(label.c_str(), io.FontScale); + } + ~Button() = default; + + /** Return true if butten is pressed*/ + bool IsPressed() { return pressed; } + /** + * 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: + fvec2 tdim; ///< Text size + UI7Color color = UI7Color_Button; ///< current button color + std::string label; ///< Label of the Button + bool pressed = false; ///< ispressed value +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/container/checkbox.hpp b/include/pd/ui7/container/checkbox.hpp new file mode 100755 index 0000000..69efb63 --- /dev/null +++ b/include/pd/ui7/container/checkbox.hpp @@ -0,0 +1,72 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +/** + * Checkbox Object + * @note The Updated input is available after + * Context::Update while the visual update is done + * during the Update + */ +class PD_API Checkbox : public Container { + public: + /** + * Constructor for Checkbox Object + * @param label Label of the Checkbox + * @param usr_ref Reference to the bool value to update + * @param io IO Reference + */ + Checkbox(const std::string& label, bool& usr_ref, UI7::IO& io) + : usr_ref(usr_ref) { + this->label = label; + this->tdim = io.Font->GetTextBounds(label.c_str(), io.FontScale); + } + ~Checkbox() = 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; + + /** Update Size if framepadding changed */ + void Update() override; + + private: + fvec2 tdim; ///< Text Size + fvec2 cbs = fvec2(18); ///< Checkbox size + UI7Color color = UI7Color_FrameBackground; ///< Checkbox background Color + std::string label; ///< Checkbox Label + bool& usr_ref; ///< User bool reference +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/container/coloredit.hpp b/include/pd/ui7/container/coloredit.hpp new file mode 100755 index 0000000..5985a84 --- /dev/null +++ b/include/pd/ui7/container/coloredit.hpp @@ -0,0 +1,75 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +/** + * Color Editor (Creating a PopUP when clicking) + */ +class PD_API ColorEdit : public Container { + public: + /** + * Constructor + * @param label Label of the Button + * @param pos Base Position + * @param lr Reference to the Renderer + */ + ColorEdit(const std::string& label, u32* color, UI7::IO& io) { + // PD::Assert(color != nullptr, "Input Color Address is null!"); + this->label = label; + this->color_ref = color; + this->initial_color = *color; + this->tdim = io.Font->GetTextBounds(label.c_str(), io.FontScale); + } + ~ColorEdit() = 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: + fvec2 tdim; ///< Text size + u32* color_ref = nullptr; ///< Color Reference + u32 initial_color; ///< Initial Color + std::string label; ///< Label of the Button + Layout* 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 new file mode 100644 index 0000000..44a9e9d --- /dev/null +++ b/include/pd/ui7/container/container.hpp @@ -0,0 +1,179 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +/** + * Container base class all Objects are based on + * @note this class can be used to create custom Objects as well + */ +class PD_API Container { + public: + Container() = default; + /** + * Constructor with pos and Size + * @param pos Container Position + * @param size Container Size + */ + Container(const fvec2& pos, const fvec2& size) : pos(pos), size(size) {} + /** + * Constructor by a vec4 box + * @param box Box containing top left and bottom right coords + */ + Container(const fvec4& box) + : pos(fvec2(box.x, box.y)), size(fvec2(box.z - box.x, box.w - box.y)) {} + ~Container() = default; + + /** + * Init Function Required by every Object that uses + * Render or Input functions + * @param io IO Reference + * @param l Drawlist Reference + */ + void Init(UI7::IO* io, Li::Drawlist* l) { + list = l; + this->io = io; + // this->screen = io->Ren->CurrentScreen(); + } + + void SetClipRect(fvec4 clip) { + pClipRect = clip; + pCLipRectUsed = true; + } + + /** Setter for Position */ + void SetPos(const fvec2& pos) { this->pos = pos; } + /** Setter for Size */ + void SetSize(const fvec2& size) { this->size = size; } + /** Getter for Position */ + fvec2 GetPos() { return pos; } + /** Getter for Size */ + fvec2 GetSize() { return size; } + /** + * Get the Containers Final Position + * for Rendering and Input (if it has a parent Object) + */ + fvec2 FinalPos() { + vec2 res = pos; + if (parent) { + /// Probably should use parant->FinalPos here + res += parent->GetPos(); + } + return res; + } + + /** Setter for Parent Container */ + void SetParent(Container* v) { parent = v; } + /** Getter for Parent Container */ + Container* GetParent() { return parent; } + + /** Check if Rendering can be skipped */ + bool Skippable() const { return skippable; } + /** Check if the Object got a timeout (ID OBJ Relevant) */ + bool Removable() const { return rem; } + + /** + * Handles Scrolling by scrolling pos as well as + * Time for Remove for ID Objects + * @param scrolling Scrolling Position + * @param viewport Viewport to check if the Object is skippable + */ + void HandleScrolling(fvec2 scrolling, fvec4 viewport); + /** Template function for Input Handling */ + virtual void HandleInput() {} + /** Tamplate function for Object rendering */ + virtual void Draw() {} + /** Template function to update internal data (if needed) */ + virtual void Update() {} + + /** Internal function */ + void PreDraw(); + /** Internal function */ + void PostDraw(); + + /** Internal Input Handler */ + void HandleInternalInput(); + + /** + * Function to unlock Input after Rendering is done in + * Menu::Update + * @note This is used if the Object got Input Handled directly after creation + * to not check for Inputs twice + */ + void UnlockInput() { inp_done = false; } + + /** Get the Objects ID (if it is an ID object)*/ + u32 GetID() const { return id; } + /** + * Set ID for ID Objects + * @param id Object ID (hashed prefix+objname+prefixed_counter) + */ + void SetID(u32 id) { this->id = id; } + + /** Get a reference to IO */ + UI7::IO* GetIO() { return io; } + + protected: + /** used to skip Input/Render preocessing ot not*/ + bool skippable = false; + /** value to check if an ID Object goes out of lifetime*/ + bool rem = false; + /** Time of the last use (set by HandleScrolling)*/ + u64 last_use = 0; + /** Input done or not for current frame*/ + bool inp_done = false; + /** Reference to the Screen to draw the Object on*/ + // Screen::Ref screen; + /** Container Position*/ + fvec2 pos; + /** Container Size*/ + fvec2 size; + /** Reference to the Drawlist to Draw to*/ + Li::Drawlist* list; + /** IO Reference for Renderer and Theme */ + UI7::IO* io; + /** Reference to the parent container*/ + Container* parent; + /** Object ID (0 if unused)*/ + u32 id = 0; + /** Internal Flags */ + u32 pFlags = 0; + /** Is Selected? */ + bool pSelected = false; + /** Was Pressed */ + bool pPressed = false; + /** Was Pressed Twice */ + bool pPressedTwice = false; + /** ClipRect */ + fvec4 pClipRect; + /** Clip Rect used */ + bool pCLipRectUsed = false; +}; +} // namespace UI7 +} // namespace PD diff --git a/include/pd/ui7/container/dragdata.hpp b/include/pd/ui7/container/dragdata.hpp new file mode 100755 index 0000000..685e85e --- /dev/null +++ b/include/pd/ui7/container/dragdata.hpp @@ -0,0 +1,90 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 PD_API DragData : public Container { + public: + /** + * Constructor + * @param label Label of the Button + * @param data Data reference (Supported types can be seen in dragdata.cpp) + * @param num_elms Number of Array elements (for exaple with use ofvec4) + * @param io IO Reference + * @param min minimum number using Minimum limit + * @param max Maximum number set by max limit by default + * @param step To set the modifier for drag movement + * @param precision for float and double to set precision + */ + DragData(const std::string& label, T* data, size_t num_elms, UI7::IO& io, + T min = std::numeric_limits::min(), + T max = std::numeric_limits::max(), T step = 1, + int precision = 1) { + // 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->step = step; + this->precision = precision; + this->tdim = io.Font->GetTextBounds(label.c_str(), io.FontScale); + } + ~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: + fvec2 tdim; ///< Text size + std::string label; ///< Label of the Button + T* data; + size_t elm_count = 0; + T min; + T max; + T step; + int precision = 1; +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/container/dynobj.hpp b/include/pd/ui7/container/dynobj.hpp new file mode 100755 index 0000000..b43ef62 --- /dev/null +++ b/include/pd/ui7/container/dynobj.hpp @@ -0,0 +1,79 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +/** + * Button Object + * @note Button Press is delayed by 1 frame + * (but the visual reaction is done in the same frame) + * This only means that InPressed is responding the info in + * the next frame + */ +class PD_API DynObj : public Container { + public: + /** + * Button Object constructor + * @param label Label of the Button + * @param pos Base Position + * @param lr Reference to the Renderer + */ + DynObj(std::function RenderFunc) { + pRenFun = RenderFunc; + } + ~DynObj() = default; + + void AddInputHandler(std::function inp) { + pInp = inp; + } + + /** Return true if butten is pressed*/ + bool IsPressed() { return pressed; } + /** + * 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: + UI7Color color = UI7Color_Button; ///< current button color + bool pressed = false; ///< ispressed value + std::function pRenFun; + std::function pInp; +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/container/image.hpp b/include/pd/ui7/container/image.hpp new file mode 100755 index 0000000..d58cb32 --- /dev/null +++ b/include/pd/ui7/container/image.hpp @@ -0,0 +1,66 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +/** + * Image Object + */ +class PD_API Image : public Container { + public: + /** + * Constructor for the Image Object + * @param img Image Texture Reference + * @param size Custom Size of the Image + */ + Image(Li::Texture img, fvec2 size = 0.f, Li::Rect uv = fvec4(0.f)) { + this->img = img; + if (size == fvec2(0.f)) { + size = img.GetSize(); + } + if (uv == Li::Rect(fvec4(0.f))) { + uv = img.GetUV(); + } + this->cuv = uv; + this->newsize = size; + SetSize(size); + } + ~Image() = default; + + /** + * Override for the Rendering Handler + * @note This function is usally called by Menu::Update + * */ + void Draw() override; + + private: + Li::Texture img; ///< Texture + fvec2 newsize = 0.f; ///< New Size + Li::Rect cuv; ///< Custom UV +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/container/label.hpp b/include/pd/ui7/container/label.hpp new file mode 100755 index 0000000..b0ce750 --- /dev/null +++ b/include/pd/ui7/container/label.hpp @@ -0,0 +1,63 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +/** + * Label [Text] Object + */ +class PD_API Label : public Container { + public: + /** + * Constructor for Label Object + * @param label Label [Text] to Draw + * @param lr Renderer Reference + */ + Label(const std::string& label, IO& io) { + this->label = label; + this->tdim = io.Font->GetTextBounds(label.c_str(), io.FontScale); + this->SetSize(tdim); + } + ~Label() = default; + + /** + * Override for the Rendering Handler + * @note This function is usally called by Menu::Update + * */ + void Draw() override; + /** + * Override Update func to support Text modifications + */ + void Update() override; + + private: + fvec2 tdim; ///< Text Size + UI7Color color = UI7Color_Text; ///< Color + std::string label; ///< Text to Render +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/container/slider.hpp b/include/pd/ui7/container/slider.hpp new file mode 100644 index 0000000..d6d719f --- /dev/null +++ b/include/pd/ui7/container/slider.hpp @@ -0,0 +1,89 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 { +/** + * Slider Object can take a datatype or a list + * and modifys these by moving left or right when dragging + */ +template +class PD_API Slider : public Container { + public: + /** + * Constructor + * @param label Label of the Button + * @param data Data reference (Supported types can be seen in Slider.cpp) + * @param num_elms Number of Array elements (for exaple with use ofvec4) + * @param io IO Reference + * @param min minimum number using Minimum limit + * @param max Maximum number set by max limit by default + * @param step To set the modifier for drag movement + * @param precision for float and double to set precision + */ + Slider(const std::string& label, T* data, UI7::IO& io, + T min = std::numeric_limits::min(), + T max = std::numeric_limits::max(), int precision = 1) { + // PD::Assert(data != nullptr, "Input Data Address is null!"); + this->label = label; + this->data = data; + this->min = min; + this->max = max; + this->precision = precision; + this->width = io.CurrentViewPort.pSize.z * 0.3f; + this->tdim = io.Font->GetTextBounds(label.c_str(), io.FontScale); + } + ~Slider() = 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: + fvec2 tdim; ///< Text size + float width; ///< Size + std::string label; ///< Label of the Button + T* data; + T min; + T max; + int precision = 1; + float slw = 0.f; // silider drag width (calculated in update) + float slp = 0.f; // silider drag pos (calculated in update) +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/containers.hpp b/include/pd/ui7/containers.hpp new file mode 100755 index 0000000..026b9a4 --- /dev/null +++ b/include/pd/ui7/containers.hpp @@ -0,0 +1,33 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 +#include +#include diff --git a/include/pd/ui7/flags.hpp b/include/pd/ui7/flags.hpp new file mode 100644 index 0000000..960d95e --- /dev/null +++ b/include/pd/ui7/flags.hpp @@ -0,0 +1,100 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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. + */ + +/** 32Bit Value to Stpre Menu Flags */ +using UI7MenuFlags = unsigned int; +/** 32Bit Value to store Alignment Flags */ +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_ { + UI7MenuFlags_None = 0, ///< No Flags (Default) + UI7MenuFlags_NoTitlebar = 1 << 0, ///< Dont Show Titlebar + UI7MenuFlags_CenterTitle = 1 << 1, ///< Center the Menu Title in Titlebar + 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 + UI7MenuFlags_NoMove = 1 << 7, ///< Disable Menu Movement + UI7MenuFlags_NoResize = 1 << 8, ///< Disable Menu Resize + UI7MenuFlags_NoClose = 1 << 9, ///< Disable Close Button + UI7MenuFlags_NoScrollbar = 1 << 10, ///< Hide the Scrollbar + // POC + UI7MenuFlags_Maximize = 1 << 11, ///< Add a Maximize Button + UI7MenuFlags_Minimize = 1 << 12, ///< Add a Minimize Button + UI7MenuFlags_AlwaysAutoSize = 1 << 13, ///< Always Auto Resize Menu + // Enable Horizontal and Vertical Scrolling + 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 + UI7IOFlags_HasTouch = 1 << 0, ///< Enable touch support [future] + UI7IOFlags_HasMouseCursor = 1 << 1, ///< Enable Mouse support [future] +}; + +/** Probably need to update this */ +enum UI7Align_ { + UI7Align_Left = 1 << 0, ///< [Hz Op] Align Left (Default) + UI7Align_Center = 1 << 1, ///< [Hz Op] Align Center + UI7Align_Right = 1 << 2, ///< [Hz Op] Align Right + UI7Align_Top = 1 << 3, ///< [Vt Op] Align Top (Default) + UI7Align_Mid = 1 << 4, ///< [Vt Op] Align Mid + UI7Align_Bottom = 1 << 5, ///< [Vt Op] Align Bottom + // Default Horizontal and Vertical Alignment + UI7Align_Default = UI7Align_Left | UI7Align_Top, +}; + +/** Special flags for Layout::AddObjectEx */ +enum UI7LytAdd_ { + UI7LytAdd_None = 0, ///< Also known as default or ->AddObject + UI7LytAdd_NoCursorUpdate = 1 << 0, ///< Add without cursor alignment + UI7LytAdd_NoScrollHandle = 1 << 1, ///< Skip HandleScrolling + UI7LytAdd_Front = 1 << 2, ///< Add in front of the list +}; + +/** + * Todo: Look at this + * Maybe proof of concept ??? + * Didnt remember that this exists + */ +enum UI7ContainerFlags_ { + UI7ContainerFlags_None = 0, + UI7ContainerFlags_EnableInternalInput = 1 << 0, + UI7ContainerFlags_Selectable = 1 << 1, + UI7ContainerFlags_OutlineSelected = 1 << 2, +}; \ No newline at end of file diff --git a/include/pd/ui7/id.hpp b/include/pd/ui7/id.hpp new file mode 100644 index 0000000..d050028 --- /dev/null +++ b/include/pd/ui7/id.hpp @@ -0,0 +1,74 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +/** + * ID Class (Generating an ID by String) + */ +class ID { + public: + /** + * Constructor to Generate ID by input string + * @param text Input String + */ + ID(const std::string& text) { + pID = PD::Strings::FastHash(text); + // pStrName = text; + pName = text; + } + /** + * Constructor used for const char* which is automatically + * used when directly placing a string istead of using ID("") + * @param text Input String + */ + constexpr ID(const char* text) { + pID = PD::FNV1A32(text); + pName = text; + } + /** + * Use an ID as Input + */ + ID(u32 id) { pID = id; } + ~ID() = default; + + /** Get The ID Initial Name */ + // constexpr const std::string_view& GetNameView() const { return pName; } + const std::string GetName() const { return std::string(pName); } + + /** Getter for the raw 32bit int id */ + constexpr const u32& RawID() const { return pID; } + + /** Return the ID when casting to u32 */ + constexpr operator u32() const { return pID; } + + u32 pID; ///< Hash of the name + std::string pName; ///< Name + // std::string pStrName; ///< Keep this stringview alive +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/input_api.hpp b/include/pd/ui7/input_api.hpp new file mode 100644 index 0000000..fa69f06 --- /dev/null +++ b/include/pd/ui7/input_api.hpp @@ -0,0 +1,138 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 InputHandler { + public: + InputHandler() {} + ~InputHandler() = default; + + /** + * Function to Check if current Object is dragged + * or set it dragged + * @param id ID to identify this specific Object + * @param area Area where to start dragging + * @return if inputs to this objects are alowed or not + */ + bool DragObject(const UI7::ID& id, fvec4 area) { + if (CurrentMenu != FocusedMenu) { + return false; + } + if (IsObjectDragged()) { + // Only block if the Dragged Object has a difrent id + if (DraggedObject != id) { + return false; + } + } + // Get a Short define for touch pos + fvec2 p = PD::Hid::MousePos(); + // Check if Drag starts in the area position + if ((PD::Hid::IsEvent(PD::Hid::Event::Down, PD::Hid::Gamepad::Touch) || + PD::Hid::IsEvent(PD::Hid::Event::Down, + PD::Hid::Keyboard::MouseLeft)) && + Li::Math::InBounds(p, area)) { + // Set ID and iniatial Positions + DraggedObject = id; + DragSourcePos = p; + DragPosition = p; + DragLastPosition = p; + DragDestination = area; + // Reset and Start DragTimer + DragTime.Reset(); + DragTime.Rseume(); + return false; // To make sure the Object is "Dragged" + } else if ((PD::Hid::IsEvent(PD::Hid::Event::Held, + PD::Hid::Gamepad::Touch) || + PD::Hid::IsEvent(PD::Hid::Event::Held, + PD::Hid::Keyboard::MouseLeft)) && + IsObjectDragged()) { + // Update DragLast and DragPoisition + DragLastPosition = DragPosition; + DragPosition = p; + } else if ((PD::Hid::IsEvent(PD::Hid::Event::Up, PD::Hid::Gamepad::Touch) || + PD::Hid::IsEvent(PD::Hid::Event::Up, + PD::Hid::Keyboard::MouseLeft)) && + IsObjectDragged()) { + // Released... Everything gets reset + DraggedObject = 0; + DragPosition = 0; + DragSourcePos = 0; + DragLastPosition = 0; + DragDestination = fvec4(0); + // Set Drag released to true (only one frame) + // and Only if still in Box + DragReleased = Li::Math::InBounds(PD::Hid::MousePosLast(), area); + DragReleasedAW = true; // Advanced + u64 d_rel = PD::Os::GetTime(); + if (d_rel - DragLastReleased < DoubleClickTime) { + DragDoubleRelease = true; + DragLastReleased = 0; // Set 0 to prevent double exec + } else { + DragLastReleased = d_rel; + } + // Ensure timer is paused + DragTime.Pause(); + DragTime.Reset(); + // Still return The Object is Dragged to ensure + // the DragReleased var can be used + return true; + } + return IsObjectDragged(); + } + + void Update() { + DragTime.Update(); + DragReleased = false; + DragReleasedAW = false; + DragDoubleRelease = false; + } + + u64 DoubleClickTime = 500; // Milliseconds + u32 FocusedMenu = 0; + fvec4 FocusedMenuRect; + u32 CurrentMenu = 0; + u32 DraggedObject = 0; + fvec2 DragSourcePos = 0; + fvec2 DragPosition = 0; + fvec2 DragLastPosition = 0; + /** Fvec4 has an constructor problem currently */ + fvec4 DragDestination = fvec4(0); + Timer DragTime; + u64 DragLastReleased = 0; + bool DragReleased = false; ///< Drag Releaded in Box + bool DragReleasedAW = false; ///< Drag Released Anywhere + bool DragDoubleRelease = false; ///< Double Click + /** Check if an object is Dragged already */ + bool IsObjectDragged() const { return DraggedObject != 0; } +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/io.hpp b/include/pd/ui7/io.hpp new file mode 100644 index 0000000..2191cf1 --- /dev/null +++ b/include/pd/ui7/io.hpp @@ -0,0 +1,110 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 { +class Context; +namespace UI7 { +class PD_API IO { + public: + IO() : DeltaStats(60), CurrentViewPort("", 0) { + /** Probably not the best solution i guess */ + // CurrentViewPort = + // ViewPort::New("Default", ivec4(ivec2(0, 0), pCtx.Gfx()->ViewPort)); + } + ~IO() {} + + /** + * IO Update Internal Variables + */ + void Update(); + + /** + * Final Draw List for PD::Li::Gfx::RednerDrawData + * + * Possible thanks to the Drawlist::Merge Feature + */ + Li::Drawlist FDL; + ViewPort CurrentViewPort; + // ivec4 CurrentViewPort = ivec4(0, 0, 0, 0); + std::unordered_map ViewPorts; + float Framerate = 0.f; + float Delta = 0.f; + u64 LastTime = 0; + TimeStats DeltaStats; + Timer Time; + Li::Font* Font = nullptr; + float FontScale = 0.7f; + UI7::Theme Theme; + fvec2 MenuPadding = 5.f; + fvec2 FramePadding = 5.f; + float ItemRowHeight = 0.f; + float FrameRounding = 0.f; + fvec2 ItemSpace = fvec2(5.f, 2.f); + fvec2 MinSliderDragSize = 10.f; // Min height (Vt) and Min Width (Hz) + bool ShowMenuBorder = true; + bool ShowFrameBorder = false; // not implemented yet + bool WrapLabels = false; // Beta state + float OverScrollMod = 0.15f; + u64 DoubleClickTime = 500; // Milliseconds + std::list> DrawlistRegestry; + // Short define for DrawKLstRegestryLast + std::list> pDLRL; + Li::Drawlist Back; + Li::Drawlist Front; + u32 NumVertices = 0; ///< Debug Vertices Num + u32 NumIndices = 0; ///< Debug Indices Num + std::vector MenuOrder; + + // DrawlistApi + void RegisterDrawlist(const UI7::ID& id, Li::Drawlist* v) { + DrawlistRegestry.push_back(std::make_pair(id, v)); + } + + void AddViewPort(const ID& id, const ivec4& size) { + if (ViewPorts.count(id.RawID())) { + return; + } + ViewPorts[id.RawID()] = ViewPort(id, size); + } + + ViewPort& GetViewPort(const ID& id) { + if (!ViewPorts.count(id.RawID())) { + static ViewPort err; + return err; + } + return ViewPorts[id.RawID()]; + } + + UI7::InputHandler InputHandler; +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/layout.hpp b/include/pd/ui7/layout.hpp new file mode 100644 index 0000000..04adfec --- /dev/null +++ b/include/pd/ui7/layout.hpp @@ -0,0 +1,207 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 +#include +#include + +namespace PD { +namespace UI7 { +class Context; +class PD_API Layout { + public: + Layout(const ID& id, IO& io) : ID(id), IO(io) { + DrawList.SetFont(IO.Font); + DrawList.SetFontscale(io.FontScale); + Scrolling[0] = false; + Scrolling[1] = false; + CursorInit(); + Pos = fvec2(io.CurrentViewPort.pSize.x, io.CurrentViewPort.pSize.y); + Size = 0; + WorkRect = fvec4(IO.MenuPadding, Size - (fvec2(2) * IO.MenuPadding)); + } + ~Layout() = default; + + /** SECTION CONTAINERS */ + /** + * Render a Simple Label + * @param label The text to draw + */ + void Label(const std::string& label); + template + void Label(std::format_string s, Args&&... args) { + Label(std::format(s, std::forward(args)...)); + } + /** + * Render a Button + * @param label The buttons text + * @return if the button was pressed + */ + bool Button(const std::string& label); + /** + * Render a Checkbox + * @param label Label of the Checkbox + * @param v A value to update + */ + void Checkbox(const std::string& label, bool& v); + /** + * Render an Image + * @param img Texture reference of the image + * @param size a Custom Size if needed + */ + void Image(Li::Texture img, fvec2 size = 0.f, Li::Rect uv = fvec4(0)); + /** + * Render a Drag Object witth any supported type: + * [`int`, `float`, `double`, `u8`, `u16`, `u32`] + * @param label Name of the Drag + * @param data Reference to Data Object (can be multiple as well) + * @param num_elements Defien the number of Elements in the Data addr + * @param precission Difine the Format string len for float/double + */ + template + void DragData(const std::string& label, T* data, size_t num_elms = 1, + T min = std::numeric_limits::min(), + T max = std::numeric_limits::max(), T step = 1, + int precision = 1) { + u32 id = Strings::FastHash("drd" + label + std::to_string((uintptr_t)data)); + Container* r = FindObject(id); + if (!r) { + r = new UI7::DragData(label, data, num_elms, this->IO, min, max, step, + precision); + r->SetID(id); + } + AddObject(r); + } + template + void Slider(const std::string& label, T* data, + T min = std::numeric_limits::min(), + T max = std::numeric_limits::max(), int precision = 1) { + u32 id = Strings::FastHash("drd" + label + std::to_string((uintptr_t)data)); + Container* r = FindObject(id); + if (!r) { + r = new UI7::Slider(label, data, this->IO, min, max, precision); + r->SetID(id); + } + AddObject(r); + } + + /** SECTION OTHERSTUFF */ + + const std::string GetName() const { return ID.GetName(); } + const UI7::ID& GetID() const { return this->ID; } + + const fvec2& GetPosition() const { return Pos; } + void SetPosition(const fvec2& v) { Pos = v; } + const fvec2& GetSize() const { return Size; } + void SetSize(const fvec2& v) { Size = v; } + + Li::Drawlist& GetDrawList() { return DrawList; } + + void CursorInit(); + void SameLine(); + void CursorMove(const fvec2& size); + + bool ObjectWorkPos(fvec2& movpos); + + /** + * Extended Object Add Func to Add Object in Front or disable + * Position by cursor as well as cursor update... + * Should only be used in special cases as the + * AddObject function is faster + * Using Flags for its features cause dont want to have too much args + */ + void AddObjectEx(Container* obj, u32 Flags); + /** + * Fast Function to Add Object in Layout SPace like + * button Label images etc + */ + void AddObject(Container* obj); + Container* FindObject(u32 id); + void ClearIDObjects() { IDObjects.clear(); } + + fvec2 AlignPosition(fvec2 pos, fvec2 size, fvec4 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(); + + fvec2 DbgScrollOffset() { return ScrollOffset; } + + private: + friend class Menu; + friend class PD::UI7::Context; + friend class ReMenu; + // Base Components + UI7::ID ID; + UI7::IO& IO; + Li::Drawlist DrawList; + UI7LayoutFlags Flags; + + // Positioning + fvec2 Pos; + fvec2 Size; + UI7Align Alignment = UI7Align_Default; + UI7Align TempAlign; + + // Cursor + fvec2 Cursor; + fvec2 InitialCursorOffset; + fvec2 BackupCursor; + fvec2 SamelineCursor; + fvec2 BeforeSameLine; + fvec2 LastObjSize; + fvec2 MaxPosition; + fvec4 WorkRect; + + // Scrolling (Only theoretical) + // Rendering must be done by the Objective that uses the Lyt + fvec2 ScrollOffset; + fvec2 ScrollStart; + bool Scrolling[2]; + + // Objects + std::list 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 new file mode 100644 index 0000000..59f19a6 --- /dev/null +++ b/include/pd/ui7/menu.hpp @@ -0,0 +1,144 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 "pd/ui7/container/dragdata.hpp" + +namespace PD { +namespace UI7 { +class PD_API Menu { + public: + Menu(const UI7::ID& id, UI7::IO& pIO); + ~Menu() {} + + /** + * Render a Simple Label + * @param label The text to draw + */ + void Label(const std::string& label); + template + void Label(std::format_string s, Args&&... args) { + Label(std::format(s, std::forward(args)...)); + } + /** + * Render a Button + * @param label The buttons text + * @return if the button was pressed + */ + bool Button(const std::string& label); + /** + * Render a Checkbox + * @param label Label of the Checkbox + * @param v A value to update + */ + void Checkbox(const std::string& label, bool& v); + /** + * Render an Image + * @param img Texture reference of the image + * @param size a Custom Size if needed + */ + void Image(Li::Texture img, fvec2 size = 0.f, Li::Rect uv = fvec4(0)); + /** + * Render a Drag Object witth any supported type: + * [`int`, `float`, `double`, `u8`, `u16`, `u32`] + * @param label Name of the Drag + * @param data Reference to Data Object (can be multiple as well) + * @param num_elements Defien the number of Elements in the Data addr + * @param precission Difine the Format string len for float/double + */ + template + void DragData(const std::string& label, T* data, size_t num_elms = 1, + T min = std::numeric_limits::min(), + T max = std::numeric_limits::max(), T step = 1, + int precision = 1) { + u32 id = Strings::FastHash("drd" + label + std::to_string((uintptr_t)data)); + Container* r = pLayout.FindObject(id); + if (!r) { + r = new UI7::DragData(label, data, num_elms, pIO, min, max, step, + precision); + // Isnt This exactly the same line??? + // r = UI7::DragData::New(label, data, num_elms, pIO, min, max, step, + // precision); + r->SetID(id); + } + pLayout.AddObject(r); + } + template + void Slider(const std::string& label, T* data, + T min = std::numeric_limits::min(), + T max = std::numeric_limits::max(), int precision = 1) { + u32 id = Strings::FastHash("drd" + label + std::to_string((uintptr_t)data)); + Container* r = pLayout.FindObject(id); + if (!r) { + r = new UI7::Slider(label, data, pIO, min, max, precision); + r->SetID(id); + } + pLayout.AddObject(r); + } + void ColorEdit(const std::string& label, u32& clr); + void SameLine() { pLayout.SameLine(); } + void Separator(); + void SeparatorText(const std::string& label); + bool BeginTreeNode(const ID& id); + void EndTreeNode(); + + void HandleFocus(); + void HandleScrolling(); + void HandleTitlebarActions(); + void DrawBaseLayout(); + + void AddObject(PD::UI7::Container* obj) { pLayout.AddObject(obj); } + void AddObjectEx(PD::UI7::Container* obj, PD::u32 flags) { + pLayout.AddObjectEx(obj, flags); + } + Container* FindObject(u32 id) { return pLayout.FindObject(id); } + + void Update(); + + void SetSize(PD::fvec2 size) { pLayout.SetSize(size); } + void SetPosition(PD::fvec2 pos) { pLayout.SetPosition(pos); } + const PD::fvec2& GetSize() const { return pLayout.GetSize(); } + const PD::fvec2& GetPosition() const { return pLayout.GetPosition(); } + + /** Data Section */ + + UI7MenuFlags Flags = 0; + Layout pLayout; + IO& pIO; + ID pID; + bool* pIsShown = nullptr; + bool pIsOpen = true; + std::unordered_map pTreeNodes; + fvec2 TempScrollXY; + + float TitleBarHeight = 0.f; +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/theme.hpp b/include/pd/ui7/theme.hpp new file mode 100755 index 0000000..d1a5e7f --- /dev/null +++ b/include/pd/ui7/theme.hpp @@ -0,0 +1,159 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 + +/** + * Using this to support 32bit color values as well as + * values from UI7Color_ + */ +using UI7Color = PD::u32; + +/** Theme Color */ +enum UI7Color_ { + UI7Color_Background, ///< UI7 Menu Background + UI7Color_Border, ///< Menu/Frame Border Color + UI7Color_Button, ///< UI7 Button Idle Color + UI7Color_ButtonDead, ///< UI7 Disabled Button Color + UI7Color_ButtonActive, ///< UI7 Pressed Button Color + UI7Color_ButtonHovered, ///< UI7 Hovered Button Color + UI7Color_Text, ///< UI7 Text Color + UI7Color_TextDead, ///< UI7 Dead Text Color + UI7Color_Header, ///< UI7 Menu Header Color + UI7Color_HeaderDead, ///< Inactive Header + UI7Color_Selector, ///< UI7 Selector Color + UI7Color_Checkmark, ///< UI7 Checkmark Color + UI7Color_FrameBackground, ///< UI7 Frame Background + UI7Color_FrameBackgroundHovered, ///< UI7 Hovered Frame Background + UI7Color_Progressbar, ///< UI7 Progressbar Background + UI7Color_ListEven, ///< UI7 List (Even Entry) Background Color + UI7Color_ListOdd, ///< UI7 List (Odd Entry) Background Color +}; + +namespace PD { +namespace UI7 { +class PD_API Theme { + public: + /** + * Default Constructor Setting up the Default theme + * @note if using Shared Reference you probably need to do + * Theme::Default(*theme.get()); + */ + Theme() { Default(*this); } + ~Theme() {} + + /** + * Simple static Loader for the Default Theme + * @param theme Theme Reference + */ + static void Default(Theme& theme); + /** + * White Mode Theme + * @param Theme theme reference + */ + static void Flashbang(Theme& theme); + + /** Revert the last Color Change */ + Theme& Pop() { + pTheme[pChanges[pChanges.size() - 1].first] = + pChanges[pChanges.size() - 1].second; + pChanges.pop_back(); + return *this; + } + + /** + * Revert the last color Change done for a specific color + * @param c Color to revert change from + */ + Theme& Pop(UI7Color c) { + for (size_t i = pChanges.size() - 1; i > 0; i--) { + if (pChanges[i].first == c) { + pTheme[c] = pChanges[i].second; + pChanges.erase(pChanges.begin() + i); + break; + } + } + return *this; + } + + /** + * Change a Color + * @param tc Color Identifier + * @param color Color to change to + */ + Theme& Change(UI7Color tc, u32 color) { + if (pTheme.find(tc) == pTheme.end()) { + return *this; + } + pChanges.push_back(std::make_pair(tc, pTheme[tc])); + pTheme[tc] = color; + return *this; + } + + /** + * Get the Color of a Color ReferenceID + * @param c ReferenceID + */ + u32 Get(UI7Color c) const { + auto e = pTheme.find(c); + if (e == pTheme.end()) { + return 0x00000000; + } + return e->second; + } + + /** + * [UNSAFE] to use + * Get the Color Ref of a Color ReferenceID + * @param c ReferenceID + */ + u32& GetRef(UI7Color c) { + auto e = pTheme.find(c); + if (e == pTheme.end()) { + static u32 noclr = 0x00000000; + return noclr; + } + return e->second; + } + + /** + * Operator wrapper for get + * @param c Color ReferenceID + */ + u32 operator[](UI7Color c) const { return Get(c); } + + /** + * Change but just sets [can implement completly new ids] + * @param tc Color ID (Can be self creeated ones as well) + * @param clr Color it should be set to + */ + void Set(UI7Color tc, u32 clr) { pTheme[tc] = clr; } + + std::unordered_map pTheme; ///< Theme Data + std::vector> pChanges; ///< List of Changes +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/ui7.hpp b/include/pd/ui7/ui7.hpp new file mode 100644 index 0000000..72ca8e1 --- /dev/null +++ b/include/pd/ui7/ui7.hpp @@ -0,0 +1,86 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 "pd/ui7/flags.hpp" + +/** + * Declare UI7 Version + * Format: 00 00 00 00 + * Major Minor Patch Build + * 0x01010000 -> 1.1.0-0 + */ +#define UI7_VERSION 0x00070000 + +namespace PD { +namespace UI7 { +/** + * Get UI7 Version String + * @param show_build Show build num (mostly unused) + * @return Version String (1.0.0-1 for example) + */ +PD_API std::string GetVersion(bool show_build = false); +/** Base Context for UI7 */ +class PD_API Context { + public: + Context() {} + ~Context() = default; + + IO& GetIO() { return pIO; } + void AddViewPort(const ID& id, const ivec4& vp); + void UseViewPort(const ID& id); + void Update(); + Menu* BeginMenu(const ID& id, UI7MenuFlags flags = 0, + bool* pShow = nullptr); + Menu* CurrentMenu() { return pCurrent; } + void EndMenu(); + void AboutMenu(bool* show = nullptr); + void MetricsMenu(bool* show = nullptr); + void StyleEditor(bool* show = nullptr); + + Li::Drawlist& GetDrawData() { return pIO.FDL; } + + Menu* pGetOrCreateMenu(const ID& id) { + auto menu = pMenus.find(id); + if (menu == pMenus.end()) { + pMenus[id] = new Menu(id, pIO); + menu = pMenus.find(id); + } + return menu->second; + } + + IO pIO; + /** Current Menu */ + Menu* pCurrent = nullptr; + std::vector pCurrentMenus; + std::vector pDFO; /** Debug Final Order */ + std::unordered_map pMenus; +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/viewport.hpp b/include/pd/ui7/viewport.hpp new file mode 100644 index 0000000..1c73d4c --- /dev/null +++ b/include/pd/ui7/viewport.hpp @@ -0,0 +1,44 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2026 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 { +class ViewPort { + public: + ViewPort() : pID(""), pSize(0) {} + ViewPort(const ID& id, const ivec4& size) : pID(id), pSize(size) {} + ~ViewPort() {} + + ID GetID() const { return pID; } + ivec4& GetSize() { return pSize; } + + ID pID; + ivec4 pSize; +}; +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/container/button.cpp b/source/ui7/container/button.cpp new file mode 100755 index 0000000..e4c67d9 --- /dev/null +++ b/source/ui7/container/button.cpp @@ -0,0 +1,65 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +PD_API void Button::HandleInput() { + /// Ensure to only check input once + if (inp_done) { + return; + } + /// Ensure it gets sed to false and stays if not pressed + pressed = false; + color = UI7Color_Button; + // Assert(screen.get(), "Screen is not set up!"); + // if (screen->ScreenType() == Screen::Bottom) { + if (io->InputHandler.DragObject(this->GetID(), fvec4(FinalPos(), size))) { + if (io->InputHandler.DragReleased) { + color = UI7Color_ButtonActive; + pressed = true; + } else { + color = UI7Color_ButtonHovered; + } + } + //} + inp_done = true; +} +PD_API void Button::Draw() { + // Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); + // io->Ren->OnScreen(screen); + list->PathRect(FinalPos(), FinalPos() + size, io->FrameRounding); + list->PathFill(io->Theme.Get(color)); + // list->LayerUp(); + list->DrawText(FinalPos() + size * 0.5 - tdim * 0.5, label.c_str(), + io->Theme.Get(UI7Color_Text)); + // list->LayerDown(); +} + +PD_API void Button::Update() { + // Assert(io.get(), "Did you run Container::Init correctly?"); + this->SetSize(tdim + io->FramePadding); +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/container/checkbox.cpp b/source/ui7/container/checkbox.cpp new file mode 100755 index 0000000..49e1fb5 --- /dev/null +++ b/source/ui7/container/checkbox.cpp @@ -0,0 +1,68 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +PD_API void Checkbox::HandleInput() { + /// Ensure to only check input once + if (inp_done) { + return; + } + color = UI7Color_FrameBackground; + /// Ensure it gets sed to false and stays if not pressed + // Assert(screen.get(), "Screen is not set up!"); + // if (screen->ScreenType() == Screen::Bottom) { + if (io->InputHandler.DragObject(this->GetID(), fvec4(FinalPos(), size))) { + if (io->InputHandler.DragReleased) { + color = UI7Color_FrameBackgroundHovered; + usr_ref = !usr_ref; + } else { + color = UI7Color_FrameBackgroundHovered; + } + } + //} + inp_done = true; +} +PD_API void Checkbox::Draw() { + // Assert(list.get() && io.get(), "Did you run Container::Init correctly?"); + // io->Ren->OnScreen(screen); + list->PathRect(FinalPos(), FinalPos() + cbs, io->FrameRounding); + list->PathFill(io->Theme.Get(color)); + if (usr_ref) { + list->PathRect(FinalPos() + 2, FinalPos() + cbs - 2, io->FrameRounding); + list->PathFill(io->Theme.Get(UI7Color_Checkmark)); + } + list->DrawText( + FinalPos() + fvec2(cbs.x + io->ItemSpace.x, cbs.y * 0.5 - tdim.y * 0.5), + label.c_str(), io->Theme.Get(UI7Color_Text)); +} + +PD_API void Checkbox::Update() { + // Assert(io.get(), "Did you run Container::Init correctly?"); + cbs = io->ItemRowHeight; + this->SetSize(cbs + fvec2(tdim.x + io->ItemSpace.x, 0)); +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/container/coloredit.cpp b/source/ui7/container/coloredit.cpp new file mode 100755 index 0000000..f810107 --- /dev/null +++ b/source/ui7/container/coloredit.cpp @@ -0,0 +1,99 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 { +PD_API void ColorEdit::HandleInput() { + /// Ensure to only check input once + if (inp_done) { + return; + } + // Assert(screen.get(), "Screen is not set up!"); + // if (screen->ScreenType() == Screen::Bottom) { + if (io->InputHandler.DragObject(this->GetID() + 2, + fvec4(FinalPos(), size))) { + if (io->InputHandler.DragReleasedAW) { + is_shown = !is_shown; + } + } + //} + inp_done = true; +} +PD_API void ColorEdit::Draw() { + // Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); + // io->Ren->OnScreen(screen); + list->PathRect(FinalPos(), FinalPos() + io->ItemRowHeight, io->FrameRounding); + list->PathFill(*color_ref); + list->DrawText(FinalPos() + fvec2(io->ItemSpace.x + io->ItemRowHeight, 0), + label.c_str(), io->Theme.Get(UI7Color_Text)); + if (is_shown) { + if (!layout) { + layout = new UI7::Layout(GetID(), *io); + } + layout->SetPosition(FinalPos()); + layout->AddObjectEx( + new DynObj( + [=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) { + thiz->SetSize(layout->GetSize()); + // l->Layer(30); + l->PathRect(thiz->GetPos(), thiz->GetPos() + thiz->GetSize(), + io->FrameRounding); + l->PathFill(io->Theme.Get(UI7Color_FrameBackground)); + }), + UI7LytAdd_Front | UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); + auto obj = new DynObj( + [=, this](UI7::IO* io, Li::Drawlist* l, Container* thiz) { + l->PathRect(thiz->FinalPos(), thiz->FinalPos() + io->ItemRowHeight, + io->FrameRounding); + l->PathFill(*color_ref); + l->DrawText( + thiz->FinalPos() + fvec2(io->ItemSpace.x + io->ItemRowHeight, 0), + label.c_str(), io->Theme.Get(UI7Color_Text)); + }); + obj->SetSize(PD::fvec2(200, io->ItemRowHeight)); + layout->AddObject(obj); + layout->Label("RGBA: ({}, {}, {}, {})", *((u8*)color_ref), + *(((u8*)color_ref) + 1), *(((u8*)color_ref) + 2), + *(((u8*)color_ref) + 3)); + layout->Label("Hex: {}", PD::Color(*color_ref).Hex(true)); + + layout->Slider("R", ((u8*)color_ref)); + layout->Slider("G", ((u8*)color_ref) + 1); + layout->Slider("B", ((u8*)color_ref) + 2); + layout->Slider("A", ((u8*)color_ref) + 3); + layout->Update(); + list->Merge(layout->GetDrawList()); + // io->RegisterDrawList(GetID(), layout->GetDrawList()); + } +} + +PD_API void ColorEdit::Update() { + // Assert(io.get(), "Did you run Container::Init correctly?"); + this->SetSize( + fvec2(tdim.x + io->ItemSpace.x + io->ItemRowHeight, io->ItemRowHeight)); +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/container/container.cpp b/source/ui7/container/container.cpp new file mode 100755 index 0000000..f0e9c81 --- /dev/null +++ b/source/ui7/container/container.cpp @@ -0,0 +1,57 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +PD_API void Container::HandleScrolling(fvec2 scrolling, fvec4 viewport) { + if (last_use != 0 && PD::Os::GetTime() - last_use > 5000) { + rem = true; + } + last_use = PD::Os::GetTime(); + pos -= fvec2(0, scrolling.y); + skippable = !Li::Math::InBounds( + pos, size, + fvec4(viewport.x, viewport.y, viewport.x + viewport.z, + viewport.y + viewport.w)); +} + +PD_API void Container::HandleInternalInput() { + /** Requires Handle Scrolling First */ +} + +/** Internal function */ +PD_API void Container::PreDraw() { + if (pCLipRectUsed) { + // list->PushClipRect(pClipRect); + } +} +/** Internal function */ +PD_API void Container::PostDraw() { + if (pCLipRectUsed) { + // list->PopClipRect(); + } +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/container/dragdata.cpp b/source/ui7/container/dragdata.cpp new file mode 100755 index 0000000..06cde42 --- /dev/null +++ b/source/ui7/container/dragdata.cpp @@ -0,0 +1,117 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +// Setup Supported Datatypes (Probably making this Object +// header only to not care about datatype support) +template class PD_API DragData; +template class PD_API DragData; +template class PD_API DragData; +template class PD_API DragData; +template class PD_API DragData; +template class PD_API DragData; +template class PD_API DragData; +template +PD_API void DragData::HandleInput() { + /// Ensure to only check input once + if (inp_done) { + return; + } + // Assert(screen.get(), "Screen is not set up!"); + // if (screen->ScreenType() == Screen::Bottom) { + float off_x = 0; + for (size_t i = 0; i < elm_count; i++) { + std::string p; + if constexpr (std::is_floating_point_v) { + p = std::format("{:.{}f}", data[i], precision); + } else { + p = std::format("{}", data[i]); + } + vec2 tdim = io->Font->GetTextBounds(p.c_str(), io->FontScale); + // Unsafe but is the fastest solution + if (io->InputHandler.DragObject( + this->GetID() + i + 1, + fvec4(FinalPos() + fvec2(off_x, 0), tdim + io->FramePadding))) { + data[i] = std::clamp( + T(data[i] + (step * (io->InputHandler.DragPosition.x - + io->InputHandler.DragLastPosition.x))), + this->min, this->max); + } + off_x += tdim.x + io->ItemSpace.x + io->FramePadding.x; + } + //} + inp_done = true; +} + +template +PD_API void DragData::Draw() { + // Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); + // io->Ren->OnScreen(screen); + float off_x = 0.f; + for (size_t i = 0; i < elm_count; i++) { + std::string p; + if constexpr (std::is_floating_point_v) { + p = std::format("{:.{}f}", data[i], precision); + } else { + p = std::format("{}", data[i]); + } + vec2 td = io->Font->GetTextBounds(p.c_str(), io->FontScale); + list->PathRect(FinalPos() + fvec2(off_x, 0), + FinalPos() + fvec2(off_x, 0) + td + io->FramePadding, + io->FrameRounding); + list->PathFill(io->Theme.Get(UI7Color_Button)); + // list->LayerUp(); + list->DrawTextEx(FinalPos() + fvec2(off_x, 0), p.c_str(), + io->Theme.Get(UI7Color_Text), LiTextFlags_AlignMid, + td + io->FramePadding); + // list->LayerDown(); + off_x += td.x + io->ItemSpace.x + io->FramePadding.x; + } + list->DrawText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5), label.c_str(), + io->Theme.Get(UI7Color_Text)); +} + +template +PD_API void DragData::Update() { + // Assert(io.get(), "Did you run Container::Init correctly?"); + // Probably need to find a faster solution (caching sizes calculated here) + float off_x = 0; + for (size_t i = 0; i < elm_count; i++) { + std::string p; + if constexpr (std::is_floating_point_v) { + p = std::format("{:.{}f}", data[i], precision); + } else { + p = std::format("{}", data[i]); + } + vec2 tdim = io->Font->GetTextBounds(p.c_str(), io->FontScale); + off_x += tdim.x + io->ItemSpace.x + io->FramePadding.x; + } + this->SetSize(vec2(tdim.x + off_x, tdim.y + io->FramePadding.y)); +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/container/dynobj.cpp b/source/ui7/container/dynobj.cpp new file mode 100755 index 0000000..96863e0 --- /dev/null +++ b/source/ui7/container/dynobj.cpp @@ -0,0 +1,38 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +PD_API void DynObj::Draw() { pRenFun(io, list, this); } + +PD_API void DynObj::HandleInput() { + if (pInp) { + pInp(io, this); + } +} + +PD_API void DynObj::Update() {} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/container/image.cpp b/source/ui7/container/image.cpp new file mode 100755 index 0000000..3d074c4 --- /dev/null +++ b/source/ui7/container/image.cpp @@ -0,0 +1,39 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +PD_API void Image::Draw() { + // Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); + // Assert(img.get(), "Image is nullptr!"); + // io->Ren->OnScreen(screen); + // list->LayerUp(); + list->BindTexture(img); + list->DrawRectFilled(FinalPos(), newsize, 0xffffffff); + list->UnbindTexture(); + //list->LayerDown(); +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/container/label.cpp b/source/ui7/container/label.cpp new file mode 100755 index 0000000..bb845ef --- /dev/null +++ b/source/ui7/container/label.cpp @@ -0,0 +1,52 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +PD_API void Label::Draw() { + // Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); + // io->Ren->OnScreen(screen); + list->DrawTextEx(FinalPos(), label.c_str(), io->Theme.Get(UI7Color_Text), + LiTextFlags_NoOOS, + PD::fvec2(0, io->CurrentViewPort.pSize.w)); +} + +PD_API void Label::Update() { + /** + * Todo: This is a hacky workaround + * Needs proper optimisation + * Needs a max size (to support sligning dynaically by the window size) + */ + if (io->WrapLabels) { + this->label = io->Font->pWrapText( + this->label, io->FontScale, + PD::fvec2(io->CurrentViewPort.pSize.z - FinalPos().x * 4, + io->CurrentViewPort.pSize.w), + this->tdim); + SetSize(tdim); + } +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/container/slider.cpp b/source/ui7/container/slider.cpp new file mode 100644 index 0000000..7f82e6b --- /dev/null +++ b/source/ui7/container/slider.cpp @@ -0,0 +1,107 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +// Setup Supported Datatypes (Probably making this Object +// header only to not care about datatype support) +template class PD_API Slider; +template class PD_API Slider; +template class PD_API Slider; +template class PD_API Slider; +template class PD_API Slider; +template class PD_API Slider; +template class PD_API Slider; +template +PD_API void Slider::HandleInput() { + /// Ensure to only check input once + if (inp_done) { + return; + } + // Assert(screen.get(), "Screen is not set up!"); + std::string p; + if constexpr (std::is_floating_point_v) { + p = std::format("{:.{}f}", *data, precision); + } else { + p = std::format("{}", *data); + } + // Unsafe but is the fastest solution + float xps = FinalPos().x; + if (io->InputHandler.DragObject( + this->GetID(), + fvec4(FinalPos() + fvec2(2, 0), fvec2(width, GetSize().y)))) { + if (!io->InputHandler.DragReleasedAW) { + *data = std::clamp( + T(max * (std::clamp(io->InputHandler.DragLastPosition.x - xps, 0.f, + width) / + width)), + this->min, this->max); + } + } + inp_done = true; +} + +template +PD_API void Slider::Draw() { + // Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); + // io->Ren->OnScreen(screen); + std::string p; + if constexpr (std::is_floating_point_v) { + p = std::format("{:.{}f}", *data, precision); + } else { + p = std::format("{}", *data); + } + fvec2 td = io->Font->GetTextBounds(p.c_str(), io->FontScale); + list->PathRect(FinalPos(), FinalPos() + fvec2(width, td.y) + io->FramePadding, + io->FrameRounding); + list->PathFill(io->Theme.Get(UI7Color_Button)); + list->PathRect(FinalPos() + 2 + PD::fvec2(slp, 0), + FinalPos() + fvec2(slp + slw - 2, td.y - 2) + io->FramePadding, + io->FrameRounding); + list->PathFill(io->Theme.Get(UI7Color_ButtonActive)); + // list->LayerUp(); + list->DrawTextEx(FinalPos(), p.c_str(), io->Theme.Get(UI7Color_Text), + LiTextFlags_AlignMid, fvec2(width, td.y) + io->FramePadding); + // list->LayerDown(); + list->DrawText(FinalPos() + fvec2(width + io->FramePadding.x * 2.f, + io->FramePadding.y * 0.5), + label.c_str(), io->Theme.Get(UI7Color_Text)); +} + +template +PD_API void Slider::Update() { + // Assert(io.get(), "Did you run Container::Init correctly?"); + // Probably need to find a faster solution (caching sizes calculated here) + slw = std::clamp(static_cast(width / max), 3.f, width); + slp = static_cast((float)*data / (float)max) * (width - slw); + fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale); + + this->SetSize( + fvec2(width + tdim.x + io->ItemSpace.x * 2, tdim.y + io->FramePadding.y)); +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/io.cpp b/source/ui7/io.cpp new file mode 100644 index 0000000..c70bae5 --- /dev/null +++ b/source/ui7/io.cpp @@ -0,0 +1,45 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +PD_API void UI7::IO::Update() { + /** Todo: find out if we even still use the Drawlist regestry */ + u64 current = PD::Os::GetTimeNano(); + Delta = static_cast(current - LastTime) / 1000000.f; + LastTime = current; + DeltaStats.Add(Delta * 1000); + Time.Update(); + InputHandler.Update(); + Framerate = 1000.f / Delta; + DrawlistRegestry.clear(); + DrawlistRegestry.push_front(std::make_pair("CtxBackList", &Back)); + if (Font) ItemRowHeight = FontScale * Font->PixelHeight; + // RegisterDrawList("CtxBackList", Back); + NumIndices = 0;//FDL.pNumIndices; + NumVertices = 0;//FDL.pNumVertices; +} +} // namespace PD \ No newline at end of file diff --git a/source/ui7/layout.cpp b/source/ui7/layout.cpp new file mode 100644 index 0000000..6e27a98 --- /dev/null +++ b/source/ui7/layout.cpp @@ -0,0 +1,190 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 { +PD_API void Layout::CursorInit() { Cursor = fvec2(WorkRect.x, WorkRect.y); } + +PD_API void Layout::SameLine() { + BackupCursor = LastObjSize; + Cursor = SamelineCursor; +} + +PD_API void Layout::CursorMove(const fvec2& size) { + LastObjSize = size; + SamelineCursor = Cursor + fvec2(size.x + IO.ItemSpace.x, 0); + if (BeforeSameLine.y) { + Cursor = + fvec2(IO.MenuPadding.x, Cursor.y + BeforeSameLine.y + IO.ItemSpace.y); + BeforeSameLine = 0.f; + } else { + Cursor = fvec2(IO.MenuPadding.x + InitialCursorOffset.x, + Cursor.y + size.y + IO.ItemSpace.y); + } + // Logical Issue here as x should use a max check + MaxPosition = fvec2(std::max(MaxPosition.x, SamelineCursor.x), Cursor.y); +} + +PD_API bool Layout::ObjectWorkPos(fvec2& movpos) { + if (Scrolling[1]) { + movpos.y -= ScrollOffset.y; + if (!Li::Math::InBounds( + movpos, LastObjSize, + fvec4(WorkRect.x, WorkRect.y, WorkRect.x + WorkRect.z, + WorkRect.y + WorkRect.w))) { + return true; + } + } + return false; +} + +PD_API void Layout::AddObject(Container* obj) { + obj->Init(&IO, &DrawList); + obj->SetPos(AlignPosition(Cursor, obj->GetSize(), WorkRect, GetAlignment())); + obj->Update(); + CursorMove(obj->GetSize()); + obj->HandleScrolling(ScrollOffset, WorkRect); + Objects.push_back(obj); +} + +PD_API void Layout::AddObjectEx(Container* obj, u32 flags) { + obj->Init(&IO, &DrawList); + if (!(flags & UI7LytAdd_NoCursorUpdate)) { + obj->SetPos( + AlignPosition(Cursor, obj->GetSize(), WorkRect, GetAlignment())); + } + obj->Update(); + if (!(flags & UI7LytAdd_NoCursorUpdate)) { + CursorMove(obj->GetSize()); + } + if (!(flags & UI7LytAdd_NoScrollHandle)) { + obj->HandleScrolling(ScrollOffset, WorkRect); + } + if (flags & UI7LytAdd_Front) { + Objects.push_front(obj); + } else { + Objects.push_back(obj); + } +} + +PD_API Container* Layout::FindObject(u32 id) { + for (auto& it : IDObjects) { + if (it->GetID() == id) { + return it; + } + } + return nullptr; +} + +PD_API fvec2 Layout::AlignPosition(fvec2 pos, fvec2 size, fvec4 area, + UI7Align alignment) { + vec2 p = pos; + if (alignment & UI7Align_Center) { + p.x = (area.x + area.z) * 0.5 - (pos.x - area.x + size.x * 0.5); + } else if (alignment & UI7Align_Right) { + } + if (alignment & UI7Align_Mid) { + p.y = (area.y + area.w) * 0.5 - (pos.y - area.y + size.y * 0.5); + } else if (alignment & UI7Align_Bottom) { + } + return p; +} + +PD_API void Layout::Update() { + if (Size == fvec2(0.f)) { + Size = fvec2(MaxPosition) + IO.MenuPadding * 2; + } + for (auto& it : Objects) { + if (it->GetID() != 0 && !FindObject(it->GetID())) { + IDObjects.push_back(it); + } + if (!it->Skippable()) { + it->SetPos(it->GetPos() + Pos); + it->HandleInput(); + it->UnlockInput(); + if (Flags & UI7LayoutFlags_UseClipRect) { + it->SetClipRect(fvec4(Pos, Size)); + } + it->PreDraw(); + it->Draw(); + it->PostDraw(); + } + } + + for (auto it = IDObjects.begin(); it != IDObjects.end();) { + if ((*it)->Removable()) { + it = IDObjects.erase(it); + } else { + it++; + } + } + + Objects.clear(); + WorkRect = fvec4(fvec2(WorkRect.x, WorkRect.y), Size - IO.MenuPadding); + CursorInit(); +} + +/** SECTION CONTAINERS (STOLEN FROM FORMER MENU) */ + +PD_API void Layout::Label(const std::string& label) { + // Layout API + auto r = new UI7::Label(label, IO); + r->SetClipRect(fvec4(GetPosition(), GetPosition() + GetSize())); + AddObject(r); +} + +PD_API bool Layout::Button(const std::string& label) { + bool ret = false; + u32 id = Strings::FastHash("btn" + label + std::to_string(Objects.size())); + Container* r = FindObject(id); + if (!r) { + r = new UI7::Button(label, IO); + r->SetID(id); + } + AddObject(r); + if (!r->Skippable()) { + ret = reinterpret_cast(r)->IsPressed(); + } + return ret; +} + +PD_API void Layout::Checkbox(const std::string& label, bool& v) { + u32 id = Strings::FastHash("cbx" + label + std::to_string(Objects.size())); + Container* r = FindObject(id); + if (!r) { + r = new UI7::Checkbox(label, v, IO); + r->SetID(id); + } + AddObject(r); +} + +PD_API void Layout::Image(Li::Texture img, fvec2 size, Li::Rect uv) { + Container* r = new UI7::Image(img, size, uv); + AddObject(r); +} + +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/menu.cpp b/source/ui7/menu.cpp new file mode 100644 index 0000000..17ae294 --- /dev/null +++ b/source/ui7/menu.cpp @@ -0,0 +1,425 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 { +Menu::Menu(const ID& id, IO& io) : pIO(io), pID(id), pLayout(id, io) { + TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y; + pLayout.WorkRect.y += TitleBarHeight; + pLayout.Flags |= UI7LayoutFlags_UseClipRect; + pLayout.CursorInit(); +} + +PD_API void Menu::Label(const std::string& label) { + // Layout API + auto r = new UI7::Label(label, pIO); + pLayout.AddObject(r); +} + +PD_API bool Menu::Button(const std::string& label) { + bool ret = false; + u32 id = + Strings::FastHash("btn" + label + std::to_string(pLayout.Objects.size())); + Container* r = pLayout.FindObject(id); + if (!r) { + r = new UI7::Button(label, pIO); + r->SetID(id); + } + pLayout.AddObject(r); + if (!r->Skippable()) { + ret = reinterpret_cast(r)->IsPressed(); + } + return ret; +} + +PD_API void Menu::Checkbox(const std::string& label, bool& v) { + u32 id = + Strings::FastHash("cbx" + label + std::to_string(pLayout.Objects.size())); + Container* r = pLayout.FindObject(id); + if (!r) { + r = new UI7::Checkbox(label, v, pIO); + r->SetID(id); + } + pLayout.AddObject(r); +} + +PD_API void Menu::Image(Li::Texture img, fvec2 size, Li::Rect uv) { + Container* r = new UI7::Image(img, size, uv); + pLayout.AddObject(r); +} + +PD_API void Menu::ColorEdit(const std::string& label, u32& clr) { + u32 id = Strings::FastHash("drd" + label); + Container* r = pLayout.FindObject(id); + if (!r) { + r = new UI7::ColorEdit(label, &clr, pIO); + r->SetID(id); + } + pLayout.AddObject(r); +} + +PD_API void Menu::Separator() { + // Dynamic Objects are very simple... + Container* r = new DynObj( + [=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) { + l->DrawRectFilled(self->FinalPos(), self->GetSize(), + pIO.Theme.Get(UI7Color_TextDead)); + }); + // Set size before pushing (cause Cursor Move will require it) + r->SetSize(fvec2( + pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x, + 1)); + pLayout.AddObject(r); +} + +PD_API void Menu::SeparatorText(const std::string& label) { + // Also note to use [=] instead of [&] to not undefined access label + Container* r = new DynObj([=, this](UI7::IO* io, Li::Drawlist* l, + UI7::Container* self) { + fvec2 size = self->GetSize(); + fvec2 tdim = io->Font->GetTextBounds(label.c_str(), io->FontScale); + fvec2 pos = self->FinalPos(); + auto align = pLayout.GetAlignment(); + vec2 rpos = pLayout.AlignPosition(pos, tdim, + fvec4(pLayout.Pos, pLayout.Size), align); + if (!(align & UI7Align_Left)) { + l->DrawRectFilled(fvec2(rpos.x + io->FramePadding.x, tdim.y * 0.5), + fvec2(pos.x - rpos.x - io->MenuPadding.x, 1), + io->Theme.Get(UI7Color_TextDead)); + } + if (!(align & UI7Align_Right)) { + l->DrawRectFilled(pos + fvec2(tdim.x + io->FramePadding.x, tdim.y * 0.5), + fvec2(size.x - tdim.x - io->MenuPadding.x, 1), + io->Theme.Get(UI7Color_TextDead)); + } + l->DrawTextEx(rpos, label.c_str(), io->Theme.Get(UI7Color_Text), 0, + fvec2(pLayout.Size.x, self->GetSize().y)); + }); + // Set size before pushing (cause Cursor Move will require it) + r->SetSize(fvec2( + pLayout.Size.x - pIO.MenuPadding.x * 2 - pLayout.InitialCursorOffset.x, + pIO.Font->PixelHeight * pIO.FontScale)); + pLayout.AddObject(r); +} +PD_API void Menu::HandleFocus() { + // Check if menu can be focused for Selective Menu Input API + vec4 newarea = fvec4(pLayout.Pos, pLayout.Size); + if (!pIsOpen) { + newarea = fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)); + } + if ((PD::Hid::IsEvent(Hid::Event::Down, Hid::Gamepad::Touch) || + PD::Hid::IsEvent(Hid::Event::Down, Hid::Keyboard::MouseLeft)) && + Li::Math::InBounds(PD::Hid::MousePos(), newarea) && + !Li::Math::InBounds(PD::Hid::MousePos(), + pIO.InputHandler.FocusedMenuRect)) { + pIO.InputHandler.FocusedMenu = pID; + } + if (pIO.InputHandler.FocusedMenu == pID) { + pIO.InputHandler.FocusedMenuRect = newarea; + } +} + +/** Todo: (func name is self describing) */ +PD_API void Menu::HandleScrolling() { + if (Flags & UI7MenuFlags_VtScrolling) { + bool allowed = + pLayout.MaxPosition.y > (pLayout.WorkRect.w - pLayout.WorkRect.y); + if (allowed) { + if (PD::Hid::IsEvent(Hid::Event::Down, PD::Hid::Gamepad::Touch)) { + pLayout.ScrollStart = pLayout.ScrollOffset; + } + if (pIO.InputHandler.DragObject( + "sbg" + pID.GetName(), + fvec4(pLayout.Pos, fvec2(0.f)) + pLayout.WorkRect)) { + if (pIO.InputHandler.DragReleasedAW) { + } else { + pLayout.ScrollOffset.y = std::clamp( + pLayout.ScrollStart.y + pIO.InputHandler.DragSourcePos.y - + pIO.InputHandler.DragPosition.y, + -20.f, pLayout.MaxPosition.y - 220); + } + } + } else { + pLayout.ScrollOffset.y = 0.f; + } + + if (pLayout.ScrollOffset.y > pLayout.MaxPosition.y - 240) { + pLayout.ScrollOffset.y -= 1.5; + if (pLayout.ScrollOffset.y < pLayout.MaxPosition.y - 240) { + pLayout.ScrollOffset.y = pLayout.MaxPosition.y - 240; + } + } + if (pLayout.ScrollOffset.y < 0) { + pLayout.ScrollOffset.y += 1.5; + if (pLayout.ScrollOffset.y > 0) { + pLayout.ScrollOffset.y = 0; + } + } + } +} + +PD_API void Menu::HandleTitlebarActions() { + // Collapse + if (!(Flags & UI7MenuFlags_NoCollapse)) { + vec2 cpos = pLayout.Pos + pIO.FramePadding; + // clr_collapse_tri = UI7Color_FrameBackground; + if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clbse"), + fvec4(cpos, fvec2(18, TitleBarHeight)))) { + if (pIO.InputHandler.DragReleased) { + pIsOpen = !pIsOpen; + } + // clr_collapse_tri = UI7Color_FrameBackgroundHovered; + } + } + // Close Logic + if (!(Flags & UI7MenuFlags_NoClose) && pIsShown != nullptr) { + fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; + fvec2 cpos = + fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x, + pLayout.Pos.y + pIO.FramePadding.y); + + // clr_close_btn = UI7Color_FrameBackground; + if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "clse"), + fvec4(cpos, size))) { + if (pIO.InputHandler.DragReleased) { + *pIsShown = !(*pIsShown); + } + // clr_close_btn = UI7Color_FrameBackgroundHovered; + } + } + // Resize logic + if (!(Flags & UI7MenuFlags_NoResize)) { + vec2 cpos = pLayout.Pos + pLayout.Size - fvec2(20); + + // clr_close_btn = UI7Color_FrameBackground; + if (pIO.InputHandler.DragObject(UI7::ID(pID.GetName() + "rszs"), + fvec4(cpos, fvec2(20)))) { + fvec2 szs = pLayout.Size + (pIO.InputHandler.DragPosition - + pIO.InputHandler.DragLastPosition); + if (szs.x < 30) szs.x = 30; + if (szs.y < 30) szs.y = 30; + pLayout.Size = szs; + // clr_close_btn = UI7Color_FrameBackgroundHovered; + } + } + // Menu Movement + if (!(Flags & UI7MenuFlags_NoMove)) { + if (pIO.InputHandler.DragObject( + pID.GetName() + "tmv", + fvec4(pLayout.Pos, fvec2(pLayout.Size.x, TitleBarHeight)))) { + if (pIO.InputHandler.DragDoubleRelease) { + pIsOpen = !pIsOpen; + } + pLayout.Pos = pLayout.Pos + (pIO.InputHandler.DragPosition - + pIO.InputHandler.DragLastPosition); + // Keep Window In Viewport + // Maybe i need to add some operators to vec + pLayout.Pos.x = std::clamp(pLayout.Pos.x, -pLayout.Size.x + 10, + pIO.CurrentViewPort.pSize.z - 10); + pLayout.Pos.y = + std::clamp(pLayout.Pos.y, pIO.CurrentViewPort.pSize.y, + pIO.CurrentViewPort.pSize.w - 10); + } + } +} + +PD_API void Menu::DrawBaseLayout() { + if (pIsOpen) { + /** Resize Sym (Render on Top of Everything) */ + if (!(Flags & UI7MenuFlags_NoResize)) { + Container* r = + new DynObj([](IO* io, Li::Drawlist* l, UI7::Container* self) { + // //l->Layer(1); + l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20)); + l->PathAdd(self->FinalPos() + self->GetSize()); + l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0)); + l->PathFill(io->Theme.Get(UI7Color_Button)); + }); + r->SetSize( + fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight)); + r->SetPos(fvec2(0, TitleBarHeight)); + pLayout.AddObjectEx(r, + UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); + } + + /** Background */ + Container* r = new DynObj([](IO* io, Li::Drawlist* l, + UI7::Container* self) { + //l->Layer(0); + l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f, + LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot); + l->PathFill(io->Theme.Get(UI7Color_Background)); + /*l->DrawRectFilled(self->FinalPos(), self->GetSize(), + io->Theme.Get(UI7Color_Background));*/ + }); + // Set size before pushing (cause Cursor Move will require it) + r->SetSize( + fvec2(pLayout.GetSize().x, pLayout.GetSize().y - TitleBarHeight)); + r->SetPos(fvec2(0, TitleBarHeight)); + pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle | + UI7LytAdd_Front); + } + if (!(Flags & UI7MenuFlags_NoTitlebar)) { + Container* r = new DynObj( + [=, this](UI7::IO* io, Li::Drawlist* l, UI7::Container* self) { + //l->Layer(20); + /** Header Bar */ + l->DrawRectFilled(self->FinalPos(), self->GetSize(), + io->Theme.Get(UI7Color_Header)); + //l->Layer(21); + /** Inline if statement to shift the Text if collapse sym is shown */ + /** What the hell is this code btw (didn't found a better way) */ + l->DrawText(self->FinalPos() + + fvec2((Flags & UI7MenuFlags_NoCollapse) + ? pIO.FramePadding.x + : (TitleBarHeight - pIO.FramePadding.y * 2 + + (io->FramePadding.x * 2)), + 2), + pID.GetName().c_str(), io->Theme.Get(UI7Color_Text)); + }); + r->SetSize(fvec2(pLayout.GetSize().x, TitleBarHeight)); + r->SetPos(0); + pLayout.AddObjectEx(r, UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); + + /** Collapse Sym */ + if (!(Flags & UI7MenuFlags_NoCollapse)) { + r = new DynObj([=, this](UI7::IO* io, Li::Drawlist* l, + UI7::Container* self) { + /** This sym actually requires layer 21 (i dont know why) */ + //l->Layer(21); + /** + * Symbol (Position Swapping set by pIsOpen ? openpos : closepos;) + */ + l->DrawTriangleFilled( + self->FinalPos(), + self->FinalPos() + + fvec2(self->GetSize().x, pIsOpen ? 0 : self->GetSize().y * 0.5), + self->FinalPos() + + fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y), + io->Theme.Get(UI7Color_FrameBackground)); + }); + r->SetSize(TitleBarHeight - pIO.FramePadding.y * 2); + r->SetPos(pIO.FramePadding); + pLayout.AddObjectEx(r, + UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle); + } + /** Close Sym (only shown if pIsShown is not nullptr) */ + if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) { + fvec2 size = TitleBarHeight - pIO.FramePadding.y * 2; // Fixed quad size + // Need to clamp this way as the math lib lacks a less and greater + // operator in vec2 (don't checked if it would make sense yet) + size.x = std::clamp(size.x, 5.f, std::numeric_limits::max()); + size.y = std::clamp(size.y, 5.f, std::numeric_limits::max()); + // Probably should fix the minsize to be locked on y + fvec2 cpos = + fvec2(pLayout.Pos.x + pLayout.Size.x - size.x - pIO.FramePadding.x, + pLayout.Pos.y + pIO.FramePadding.y); + pLayout.DrawList.DrawLine(cpos, cpos + size, + pIO.Theme.Get(UI7Color_FrameBackground), 2); + pLayout.DrawList.DrawLine(cpos + fvec2(0, size.y), + cpos + fvec2(size.x, 0), + pIO.Theme.Get(UI7Color_FrameBackground), 2); + } + } +} + +PD_API void Menu::Update() { + HandleFocus(); + if (pLayout.Size == fvec2(0.f) || Flags & UI7MenuFlags_AlwaysAutoSize) { + pLayout.Size = fvec2(pLayout.MaxPosition) + pIO.MenuPadding * 2; + } + if (!(Flags & UI7MenuFlags_NoTitlebar)) { + TitleBarHeight = pIO.FontScale * pIO.Font->PixelHeight + pIO.MenuPadding.y; + pLayout.WorkRect.y = 5.f + TitleBarHeight; + HandleTitlebarActions(); + } else { + TitleBarHeight = 0.f; + pLayout.WorkRect.y = 5.f; + } + DrawBaseLayout(); + pLayout.Update(); + if (Flags & UI7MenuFlags_VtScrolling || Flags & UI7MenuFlags_HzScrolling) { + HandleScrolling(); + } +} + +PD_API bool Menu::BeginTreeNode(const ID& id) { + // As of some notes this should work: + auto n = pTreeNodes.find(id); + if (n == pTreeNodes.end()) { + pTreeNodes[id] = false; + n = pTreeNodes.find(id); + } + fvec2 pos = pLayout.Cursor; + fvec2 tdim = pIO.Font->GetTextBounds(id.GetName().c_str(), pIO.FontScale); + fvec2 szs = tdim + fvec2(pIO.ItemSpace.x + 10, 0); + + if (n->second) { + pLayout.InitialCursorOffset += 10.f; + } + + // Object + auto r = new DynObj([=, this](IO* io, Li::Drawlist* l, Container* self) { + fvec2 ts = self->FinalPos() + fvec2(0, 7); + fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)}; + if (n->second) { + float t = pl[0].y; + pl[0].y = pl[1].x; + pl[1].x = t; + } + l->DrawTriangleFilled(ts, ts + pl[0], ts + pl[1], + io->Theme.Get(UI7Color_FrameBackground)); + + l->DrawText(self->FinalPos() + fvec2(10 + io->ItemSpace.x, 0), id.GetName().c_str(), + io->Theme.Get(UI7Color_Text)); + }); + /** Yes this new function handler was created for tree nodes */ + r->AddInputHandler([=, this](IO* io, Container* self) { + if (io->InputHandler.DragObject( + ID(pID.GetName() + id.GetName()), + fvec4(self->FinalPos(), self->GetSize()))) { + if (io->InputHandler.DragReleased) { + n->second = !n->second; + } + } + }); + r->SetPos(pos); + r->SetSize(szs); + /** Use Add Object as it is faster */ + pLayout.AddObject(r); + + return n->second; +} + +PD_API void UI7::Menu::EndTreeNode() { + pLayout.InitialCursorOffset.x -= 10.f; + pLayout.Cursor.x -= 10.f; + if (pLayout.InitialCursorOffset.x < 0.f) { + pLayout.InitialCursorOffset.x = 0.f; + } +} +} // namespace UI7 +} // namespace PD diff --git a/source/ui7/theme.cpp b/source/ui7/theme.cpp new file mode 100644 index 0000000..ee20651 --- /dev/null +++ b/source/ui7/theme.cpp @@ -0,0 +1,68 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 + +namespace PD { +namespace UI7 { +PD_API void Theme::Default(Theme& theme) { + theme.Set(UI7Color_Text, Color("#FFFFFFFF")); + theme.Set(UI7Color_TextDead, Color("#AAAAAAFF")); + theme.Set(UI7Color_Background, Color("#222222aa")); + theme.Set(UI7Color_Border, Color("#999999ff")); + theme.Set(UI7Color_Button, Color("#111111FF")); + theme.Set(UI7Color_ButtonDead, Color("#080808FF")); + theme.Set(UI7Color_ButtonActive, Color("#2A2A2AFF")); + theme.Set(UI7Color_ButtonHovered, Color("#222222FF")); + theme.Set(UI7Color_Header, Color("#111111cc")); + theme.Set(UI7Color_HeaderDead, Color("#080808FF")); + theme.Set(UI7Color_Selector, Color("#222222FF")); + theme.Set(UI7Color_Checkmark, Color("#2A2A2AFF")); + theme.Set(UI7Color_FrameBackground, Color("#555555FF")); + theme.Set(UI7Color_FrameBackgroundHovered, Color("#777777FF")); + theme.Set(UI7Color_Progressbar, Color("#00FF00FF")); + theme.Set(UI7Color_ListEven, Color("#CCCCCCFF")); + theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF")); +} + +PD_API void Theme::Flashbang(Theme& theme) { + theme.Set(UI7Color_Text, Color("#000000FF")); + theme.Set(UI7Color_TextDead, Color("#333333FF")); + theme.Set(UI7Color_Background, Color("#eeeeeeFF")); + theme.Set(UI7Color_Border, Color("#777777ff")); + theme.Set(UI7Color_Button, Color("#ccccccFF")); + theme.Set(UI7Color_ButtonDead, Color("#bbbbbbFF")); + theme.Set(UI7Color_ButtonActive, Color("#ccccccFF")); + theme.Set(UI7Color_ButtonHovered, Color("#acacacFF")); + theme.Set(UI7Color_Header, Color("#ddddddFF")); + theme.Set(UI7Color_HeaderDead, Color("#cdcdcdFF")); + theme.Set(UI7Color_Selector, Color("#222222FF")); + theme.Set(UI7Color_Checkmark, Color("#ccccccFF")); + theme.Set(UI7Color_FrameBackground, Color("#aaaaaaFF")); + theme.Set(UI7Color_FrameBackgroundHovered, Color("#909090FF")); + theme.Set(UI7Color_Progressbar, Color("#00FF00FF")); + theme.Set(UI7Color_ListEven, Color("#CCCCCCFF")); + theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF")); +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ui7/ui7.cpp b/source/ui7/ui7.cpp new file mode 100644 index 0000000..e5fa8c1 --- /dev/null +++ b/source/ui7/ui7.cpp @@ -0,0 +1,348 @@ +/* +MIT License +Copyright (c) 2024 - 2026 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 "pd/pd_p_api.hpp" +#include "pd/ui7/flags.hpp" + +#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x) +#define UI7DTF(x) PD::Strings::FormatNanos(x) + +namespace PD { +namespace UI7 { +PD_API std::string 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(); +} + +PD_API void Context::AddViewPort(const ID& id, const ivec4& vp) { + pIO.AddViewPort(id, vp); +} + +PD_API void Context::UseViewPort(const ID& id) { + if (!pIO.ViewPorts.count(id)) { + return; + } + pIO.CurrentViewPort = pIO.ViewPorts[id.RawID()]; +} + +PD_API Menu* Context::BeginMenu(const ID& id, UI7MenuFlags flags, + bool* pShow) { + if (pCurrent) { + PDERR("UI7: You are already in {} Menu!", pCurrent->pID.GetName()); + return nullptr; + } + if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), (u32)id) != + pCurrentMenus.end()) { + PDERR("UI7: Menu {} already exists!", id.GetName()); + return nullptr; + } + pCurrent = pGetOrCreateMenu(id); + this->pCurrent->pIsShown = pShow; + if (pCurrent->pIsShown != nullptr) { + if (!*pCurrent->pIsShown) { + pCurrent = nullptr; + return nullptr; + } + } + /** Probably we dont even need Input Handling in this stage */ + // this->pIO.InputHandler.CurrentMenu = id; + pCurrentMenus.push_back(id); + pCurrent->Flags = flags; + if (!pCurrent->pIsOpen) { + pCurrent = nullptr; + } + return pCurrent; +} + +PD_API void Context::EndMenu() { + /** + * Currently it would be a better wy to handle menus as follows + * + * The folowing context will generate a new menu as normally but instead + * of true or false we have m is false (nullptr) or true (some ptr returned) + * and after that it should simply out of scope + * (This would probably require some wrapper class to find out if m goes + * out of scope) + * ```cpp + * if(auto m = ui7->BeginMenu("Test")) { + * m->Label("Show some Text"); + * } + * ``` + */ + if (!pCurrent) { + return; + } + pCurrent = nullptr; + // pIO.InputHandler.CurrentMenu = 0; +} + +PD_API void Context::Update() { + /** + * Cause Commenting each line looks carbage... + * This function simply clears the FinalDrawList, Searches for Menu ID's in + * The sorted menu List from last frame to insert them as same order into + * the final list. After that it adds new menus to the begin to 'add' new + * menus on top. As final step the focused menu gets add to begin + * Then the menus update their Input and DraeList Generation in List Order + * and the DrawLists get Merged into the FDL in reverse Order. At end the List + * gets cleanup and io gets updated + * + * Very simple ... + */ + pIO.FDL.Clear(); + if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), + pIO.InputHandler.FocusedMenu) == pCurrentMenus.end()) { + pIO.InputHandler.FocusedMenu = 0; + pIO.InputHandler.FocusedMenuRect = fvec4(0); + } + std::vector FinalList; + for (auto it : pDFO) { + if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), it) != + pCurrentMenus.end() && + it != pIO.InputHandler.FocusedMenu) { + FinalList.push_back(it); + } + } + for (auto it : pCurrentMenus) { + if (std::find(FinalList.begin(), FinalList.end(), it) == FinalList.end() && + it != pIO.InputHandler.FocusedMenu) { + FinalList.push_back(it); + } + } + if (pMenus.count(pIO.InputHandler.FocusedMenu)) { + FinalList.insert(FinalList.begin(), pIO.InputHandler.FocusedMenu); + } + pDFO = FinalList; + for (auto& it : FinalList) { + this->pIO.InputHandler.CurrentMenu = it; + pMenus[it]->Update(); /** Render */ + this->pIO.InputHandler.CurrentMenu = 0; + } + for (int i = (int)FinalList.size() - 1; i >= 0; i--) { + pIO.FDL.Merge(pMenus[FinalList[i]]->pLayout.GetDrawList()); + } + pCurrentMenus.clear(); + pIO.Update(); + pIO.FDL.Optimize(); +} + +PD_API void Context::AboutMenu(bool* show) { + if (auto m = BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) { + 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 -> {}", + Strings::GetCompilerVersion()); // + LibInfo::CompiledWith()); + } + EndMenu(); + } +} + +PD_API void Context::MetricsMenu(bool* show) { + if (auto m = BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) { + m->Label("Palladium - UI7 " + GetVersion()); + m->Separator(); + m->Label( + std::format("Average {:.3f} ms/f ({:.1f} FPS)", + ((float)pIO.DeltaStats.GetAverage() / 1000.f), + 1000.f / ((float)pIO.DeltaStats.GetAverage() / 1000.f))); + m->Label(std::format("NumVertices: {}", pIO.NumVertices)); + m->Label(std::format("NumIndices: {} -> {} Tris", pIO.NumIndices, + pIO.NumIndices / 3)); + m->Label("Menus: " + std::to_string(pMenus.size())); + /** Section TimeTrace */ + m->SeparatorText("TimeTrace"); + if (m->BeginTreeNode("Traces (" + + std::to_string(PD::TT::GetTraceMap().size()) + ")")) { + for (auto& it : PD::TT::GetTraceMap()) { + if (m->BeginTreeNode(it.second.GetID())) { + m->Label("Diff: " + UI7DTF(it.second.GetLastDiff())); + m->Label("Protocol Len: " + + std::to_string(it.second.GetProtocol().GetLen())); + m->Label("Average: " + UI7DTF(it.second.GetProtocol().GetAverage())); + m->Label("Min: " + UI7DTF(it.second.GetProtocol().GetMin())); + m->Label("Max: " + UI7DTF(it.second.GetProtocol().GetMax())); + m->EndTreeNode(); + } + } + m->EndTreeNode(); + } + m->SeparatorText("Palladium Info"); + m->Label("Os Driver: {}", PD::Os::GetDriverName()); + m->Label("Renderer: {}", PD::Gfx::GetDriverName()); + if (m->BeginTreeNode( + std::string(std::string("Input: ") + PD::Hid::GetDriverName()))) { + /* if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasKeyboard) { + m->Label("- Keyboard Supported"); + } + if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasMouse) { + m->Label("- Mouse Supported"); + } + if (pIO.pCtx.Hid()->Flags & PD::HidDriver::Flags_HasTouch) { + m->Label("- Touch Supported"); + } + if (pIO.pCtx.Hid()->Flags & PD::HidDriver::FLags_HasGamepad) { + m->Label("- Gamepad Supported"); + }*/ + m->EndTreeNode(); + } + /** Section IO */ + m->SeparatorText("IO"); + if (m->BeginTreeNode("Menus (" + std::to_string(pMenus.size()) + ")")) { + for (auto& it : pMenus) { + if (m->BeginTreeNode(it.second->pID.GetName())) { + m->Label("Name: " + it.second->pID.GetName()); + m->Label(std::format("Pos: {}", it.second->pLayout.GetPosition())); + m->Label(std::format("Size: {}", it.second->pLayout.GetSize())); + m->Label(std::format("WorkRect: {}", it.second->pLayout.WorkRect)); + m->Label(std::format("Cursor: {}", it.second->pLayout.Cursor)); + if (m->BeginTreeNode( + "ID Objects (" + + std::to_string(it.second->pLayout.IDObjects.size()) + ")")) { + for (auto& jt : it.second->pLayout.IDObjects) { + m->Label(std::format("{:08X}", jt->GetID())); + } + m->EndTreeNode(); + } + m->EndTreeNode(); + } + } + m->EndTreeNode(); + } + if (m->BeginTreeNode("Active Menus (" + + std::to_string(pCurrentMenus.size()) + ")")) { + for (auto& it : pCurrentMenus) { + if (m->BeginTreeNode(pMenus[it]->pID.GetName())) { + m->Label("Name: " + pMenus[it]->pID.GetName()); + m->Label(std::format("Pos: {}", pMenus[it]->pLayout.GetPosition())); + m->Label(std::format("Size: {}", pMenus[it]->pLayout.GetSize())); + m->Label(std::format("WorkRect: {}", pMenus[it]->pLayout.WorkRect)); + m->Label(std::format("Cursor: {}", pMenus[it]->pLayout.Cursor)); + if (m->BeginTreeNode( + "ID Objects (" + + std::to_string(pMenus[it]->pLayout.IDObjects.size()) + + ")")) { + for (auto& jt : pMenus[it]->pLayout.IDObjects) { + m->Label(std::format("{:08X}", jt->GetID())); + } + m->EndTreeNode(); + } + m->EndTreeNode(); + } + } + m->EndTreeNode(); + } + // Well this are Li Drawlists now and they do not count their stats (yet) + /*if (m->BeginTreeNode("DrawLists (" + + std::to_string(pIO.DrawListRegestry.size()) + ")")) { + for (auto &it : pIO.DrawListRegestry) { + if (m->BeginTreeNode(it.First.GetName())) { + m->Label("Vertices: " + std::to_string(it.Second->NumVertices)); + m->Label("Indices: " + std::to_string(it.Second->NumIndices)); + m->Label("Base Layer: " + std::to_string(it.Second->Base)); + m->EndTreeNode(); + } + } + m->EndTreeNode(); + }*/ + m->Label("io->Time: " + Strings::FormatMillis(pIO.Time.Get())); + m->Label(std::format("Delta: {:.3f}", pIO.Delta)); + m->Label(std::format("Framerate: {:.2f}", pIO.Framerate)); + m->Label(std::format("Focused Menu: {:08X}", pIO.InputHandler.FocusedMenu)); + m->Label( + std::format("Dragged Object: {:08X}", pIO.InputHandler.DraggedObject)); + m->Label(std::format("DragTime: {:.2f}s", + pIO.InputHandler.DragTime.GetSeconds())); + m->Label( + std::format("DragDestination: [{}]", pIO.InputHandler.DragDestination)); + m->Label(std::format("DragSource: [{}]", pIO.InputHandler.DragSourcePos)); + m->Label(std::format("DragPos: [{}]", pIO.InputHandler.DragPosition)); + m->Label( + std::format("DragLastPos: [{}]", pIO.InputHandler.DragLastPosition)); + EndMenu(); + } +} + +PD_API void UI7::Context::StyleEditor(bool* show) { + if (auto m = BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) { + m->Label("Palladium - UI7 " + GetVersion() + " Style Editor"); + m->Separator(); + m->DragData("MenuPadding", (float*)&pIO.MenuPadding, 2, 0.f, 100.f); + m->DragData("FramePadding", (float*)&pIO.FramePadding, 2, 0.f, 100.f); + m->DragData("ItemSpace", (float*)&pIO.ItemSpace, 2, 0.f, 100.f); + m->DragData("MinSliderSize", (float*)&pIO.MinSliderDragSize, 2, 1.f, 100.f); + m->DragData("OverScroll Modifier", &pIO.OverScrollMod, 1, 0.01f, + std::numeric_limits::max(), 0.01f, 2); + m->Checkbox("Menu Border", pIO.ShowMenuBorder); + m->Checkbox("Frame Border", pIO.ShowFrameBorder); + m->SeparatorText("Theme"); + if (m->Button("Dark")) { + UI7::Theme::Default(pIO.Theme); + } + m->SameLine(); + if (m->Button("Flashbang")) { + UI7::Theme::Flashbang(pIO.Theme); + } + /// Small trick to print without prefix +#define ts(x) m->ColorEdit(std::string(#x).substr(9), pIO.Theme.GetRef(x)); +#define ts2(x) \ + m->DragData(std::string(#x).substr(9), (u8*)&pIO.Theme.GetRef(x), 4, (u8)0, \ + (u8)255); + ts(UI7Color_Background); + ts(UI7Color_Border); + ts(UI7Color_Button); + ts(UI7Color_ButtonDead); + ts(UI7Color_ButtonActive); + ts(UI7Color_ButtonHovered); + ts(UI7Color_Text); + ts(UI7Color_TextDead); + ts(UI7Color_Header); + ts(UI7Color_HeaderDead); + ts(UI7Color_Selector); + ts(UI7Color_Checkmark); + ts(UI7Color_FrameBackground); + ts(UI7Color_FrameBackgroundHovered); + ts(UI7Color_Progressbar); + ts(UI7Color_ListEven); + ts(UI7Color_ListOdd); + this->EndMenu(); + } +} +} // namespace UI7 +} // namespace PD \ No newline at end of file diff --git a/source/ultra/canvas.cpp b/source/ultra/canvas.cpp index 83ccb54..8de0363 100644 --- a/source/ultra/canvas.cpp +++ b/source/ultra/canvas.cpp @@ -111,4 +111,4 @@ PD_API PD::fvec2 Canvas::VTranslateAlignPos(const PD::fvec2& pos, PD_API const PD::u32& Canvas::GetRevision() const { return pRev; } } // namespace Ultra -} // namespace PD \ No newline at end of file +} // namespace PD diff --git a/tests/assets/JetBrainsMono-Medium.ttf b/tests/assets/JetBrainsMono-Medium.ttf new file mode 100644 index 0000000..9767115 Binary files /dev/null and b/tests/assets/JetBrainsMono-Medium.ttf differ diff --git a/tests/assets/OFL.txt b/tests/assets/OFL.txt new file mode 100644 index 0000000..8bee414 --- /dev/null +++ b/tests/assets/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/tests/gfx/source/main.cpp b/tests/gfx/source/main.cpp index fc94ef0..6db5c80 100644 --- a/tests/gfx/source/main.cpp +++ b/tests/gfx/source/main.cpp @@ -1,9 +1,9 @@ +#include #include #include #include #include #include -#include //// #include @@ -169,8 +169,12 @@ struct Cursor { }; int main(int argc, char** argv) { - // PD::LogFilter(PD::LogLevel::Warning); +// PD::LogFilter(PD::LogLevel::Warning); +#ifdef __APPLE__ + Driver drv = Driver::OpenGL2; // default gl2 +#else Driver drv = Driver::OpenGL3; +#endif if (argc == 2) { if (std::string(argv[1]) == "gl2") { drv = Driver::OpenGL2; @@ -193,22 +197,30 @@ int main(int argc, char** argv) { PD::Image img(ResourcePath("icon.png")); auto pTex = PD::Gfx::LoadTexture(img, img.Width(), img.Height()); PD::Li::Font font; - std::future __f = std::async(std::launch::async, [&]() { - font.LoadTTF(ResourcePath("default.ttf"), 32, - LiFontFlags_SDF | LiFontFlags_Monospace); - }); + PD::Li::Font debug_font; + font.LoadTTF(ResourcePath("default.ttf"), 32, LiFontFlags_SDF); + debug_font.LoadTTF(ResourcePath("JetBrainsMono-Medium.ttf"), 32, + LiFontFlags_SDF | LiFontFlags_Monospace); pList.SetFont(&font); App app(font); Cursor LeftStick; Cursor RightStick; RightStick.pColor = "#00ffff"; + PD::UI7::Context ui7; + ui7.GetIO().Font = &font; + ui7.AddViewPort("Default", PD::ivec4(0, 0, 1280, 720)); + ui7.UseViewPort("Default"); while (pOs->Mainloop()) { PD::TT::Scope __st("MainLoop"); PD::Hid::Update(); PD::Gfx::NewFrame(); pOs->ClearViewPort(); - app.Update(pOs->GetViewport(), pList); + // app.Update(pOs->GetViewport(), pList); pList.SetFontscale(0.7); + if (auto m = ui7.BeginMenu("Test")) { + m->Label("Hello World!"); + ui7.EndMenu(); + } if (PD::Hid::IsEvent(PD::Hid::Event::Down, PD::Hid::Gamepad::CPLeft | PD::Hid::Gamepad::CPRight)) { LeftStick.pPos.x += PD::Hid::GetLeftStick().x * 15; @@ -274,8 +286,9 @@ int main(int argc, char** argv) { #ifdef __3DS__ pList.SetFontscale(0.4); #else - pList.SetFontscale(); + pList.SetFontscale(0.6f); #endif + pList.SetFont(&debug_font); int __i = 0; for (auto& it : PD::TT::GetTraceMap()) { pList.DrawText( @@ -285,9 +298,15 @@ int main(int argc, char** argv) { .c_str(), "#ff00ff"); } + pList.SetFont(&font); + ui7.MetricsMenu(); + PD::TT::Beg("UI7::Context::Update"); + ui7.Update(); + PD::TT::End("UI7::Context::Update"); PD::Gfx::Reset(); PD::TT::Beg("PD::Gfx::Draw"); PD::Gfx::Draw(pList); + PD::Gfx::Draw(ui7.GetDrawData()); PD::TT::End("PD::Gfx::Draw"); pList.Clear(); pOs->SwapBuffers();