diff --git a/include/pd/ui7/container/slider.hpp b/include/pd/ui7/container/slider.hpp new file mode 100644 index 0000000..6f6d090 --- /dev/null +++ b/include/pd/ui7/container/slider.hpp @@ -0,0 +1,91 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2025 René Amthor (tobid7) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include +#include + +namespace PD { +namespace UI7 { +/** + * Slider Object can take a datatype or a list + * and modifys these by moving left or right when dragging + */ +template +class PD_UI7_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::Ref 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.z * 0.3f; + this->tdim = io->Font->GetTextBounds(label, io->FontScale); + } + ~Slider() = default; + + /** Als ob das funktioniert... */ + PD_SHARED(Slider); + /** + * 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 index 3f7f8dd..59911d1 100755 --- a/include/pd/ui7/containers.hpp +++ b/include/pd/ui7/containers.hpp @@ -30,3 +30,4 @@ SOFTWARE. #include #include #include +#include diff --git a/include/pd/ui7/menu.hpp b/include/pd/ui7/menu.hpp index 6bd37a2..3a593b5 100755 --- a/include/pd/ui7/menu.hpp +++ b/include/pd/ui7/menu.hpp @@ -25,6 +25,7 @@ SOFTWARE. */ #include +#include #include #include #include @@ -92,6 +93,18 @@ class PD_UI7_API Menu { } 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::Ref r = pLayout->FindObject(id); + if (!r) { + r = UI7::Slider::New(label, data, pIO, min, max, precision); + r->SetID(id); + } + pLayout->AddObject(r); + } void SameLine() { pLayout->SameLine(); } void Separator(); void SeparatorText(const std::string &label); diff --git a/pd/ui7/CMakeLists.txt b/pd/ui7/CMakeLists.txt index c8a6cd3..01ab2f6 100755 --- a/pd/ui7/CMakeLists.txt +++ b/pd/ui7/CMakeLists.txt @@ -17,6 +17,7 @@ set(SRC source/container/dynobj.cpp source/container/image.cpp source/container/label.cpp + source/container/slider.cpp ) if(PD_BUILD_SHARED) @@ -25,4 +26,4 @@ else() pd_add_lib(pd-ui7 SRC_FILES ${SRC}) endif() -target_link_libraries(pd-ui7 PUBLIC pd-lithium pd-core) \ No newline at end of file +target_link_libraries(pd-ui7 PUBLIC pd-lithium pd-core) diff --git a/pd/ui7/source/container/slider.cpp b/pd/ui7/source/container/slider.cpp new file mode 100644 index 0000000..c00244c --- /dev/null +++ b/pd/ui7/source/container/slider.cpp @@ -0,0 +1,107 @@ +/* +MIT License +Copyright (c) 2024 - 2025 René Amthor (tobid7) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include +#include +#include + +namespace PD { +namespace UI7 { +// Setup Supported Datatypes (Probably making this Object +// header only to not care about datatype support) +template class PD_UI7_API Slider; +template class PD_UI7_API Slider; +template class PD_UI7_API Slider; +template class PD_UI7_API Slider; +template class PD_UI7_API Slider; +template class PD_UI7_API Slider; +template class PD_UI7_API Slider; +template +PD_UI7_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_UI7_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, 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, 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, io->Theme->Get(UI7Color_Text)); +} + +template +PD_UI7_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, 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/test/source/main.cpp b/test/source/main.cpp index 25486f1..925c8c0 100755 --- a/test/source/main.cpp +++ b/test/source/main.cpp @@ -80,6 +80,7 @@ int main() { int wx, wy; glfwGetWindowSize(win, &wx, &wy); PD::Gfx::pGfx->ViewPort = PD::ivec2(wx, wy); + ui7->GetIO()->CurrentViewPort = PD::ivec4(0, 0, wx, wy); glViewport(0, 0, wx, wy); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); @@ -102,15 +103,14 @@ int main() { /** Draw text */ List->DrawText( 20, - "Test String oder So\nPalladium 0.5.0\n" + + "Test String oder So\nPalladium 0.6.0\n" + std::format("{}\nMousePos: {}", PD::Strings::FormatNanos( PD::OS::GetTraceRef("REN")->GetLastDiff()), PD::Hid::MousePos()) + "\nUI7 Version: " + PD::UI7::GetVersion(), 0xff000000); - if (ui7->BeginMenu("Test")) { - auto menu = ui7->pCurrent; + if (auto menu = ui7->BeginMenu("Test")) { menu->Label("Hello"); menu->Label("World!"); menu->Checkbox("About Menu", AboutOderSo); @@ -125,17 +125,16 @@ int main() { menu->Label( std::format("Left: {}", PD::Hid::IsHeld(PD::Hid::Key::Touch))); menu->DragData("Value", &v, 1); + menu->Slider("Value 2", &v); ui7->EndMenu(); } - if (ui7->BeginMenu("Yet another Window")) { - auto menu = ui7->pCurrent; + if (auto menu = ui7->BeginMenu("Yet another Window")) { menu->Label(std::format("this->Pos: {}", menu->pLayout->GetPosition())); menu->Label(std::format("Vertices: {}", PD::Gfx::pGfx->VertexCounter)); menu->Label(std::format("Indices: {}", PD::Gfx::pGfx->IndexCounter)); ui7->EndMenu(); } - if (ui7->BeginMenu("#Debug (UI7)")) { - auto menu = ui7->pCurrent; + if (auto menu = ui7->BeginMenu("#Debug (UI7)")) { menu->Label(std::format("Framerate: {:.1f} [{:.2f}]", ui7->pIO->Framerate, ui7->pIO->Delta)); menu->SeparatorText("Input"); @@ -149,8 +148,7 @@ int main() { } ui7->EndMenu(); } - if (ui7->BeginMenu("NoDebug")) { - auto m = ui7->pCurrent; + if (auto m = ui7->BeginMenu("NoDebug")) { if (m->BeginTreeNode("Test")) { m->Label("Hello World!"); if (m->BeginTreeNode("AnotherNode")) { @@ -176,8 +174,8 @@ int main() { #endif PD::TT::Beg("REN"); PD::Gfx::NewFrame(); - PD::Gfx::RenderDrawData(List->pDrawList); - PD::Gfx::RenderDrawData(ui7->GetDrawData()->pDrawList); + PD::Gfx::RenderDrawData(List->Data()); + PD::Gfx::RenderDrawData(ui7->GetDrawData()->Data()); /** Clear The List */ List->Clear(); PD::TT::End("REN");