diff --git a/CMakeLists.txt b/CMakeLists.txt index b06026f..768d50a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC_FILES source/maths/color.cpp source/maths/bit_util.cpp source/maths/img_convert.cpp + source/maths/img_blur.cpp # Graphics source/graphics/texture.cpp source/graphics/spritesheet.cpp diff --git a/include/pd.hpp b/include/pd.hpp index ceef6f8..5a6c70a 100644 --- a/include/pd.hpp +++ b/include/pd.hpp @@ -37,6 +37,7 @@ SOFTWARE. // Maths #include #include +#include #include #include // Overlays diff --git a/include/pd/graphics/lithium.hpp b/include/pd/graphics/lithium.hpp index 0220f99..eb5a7e1 100644 --- a/include/pd/graphics/lithium.hpp +++ b/include/pd/graphics/lithium.hpp @@ -481,6 +481,8 @@ class Renderer : public SmartCtor { void TextCommand(std::vector& cmds, const vec2& pos, u32 color, const std::string& text, LITextFlags flags, const vec2& box); vec2 GetTextDimensions(const std::string& text); + std::string ShortText(const std::string& text, int maxlen, vec2& newsize); + std::string WrapText(const std::string& text, int maxlen, vec2& newsize); private: /// Helper Funcitons /// diff --git a/include/pd/graphics/spritesheet.hpp b/include/pd/graphics/spritesheet.hpp index 1673479..80e7362 100644 --- a/include/pd/graphics/spritesheet.hpp +++ b/include/pd/graphics/spritesheet.hpp @@ -31,7 +31,7 @@ SOFTWARE. #include namespace PD { -class SpriteSheet { +class SpriteSheet : public SmartCtor { public: SpriteSheet() {} SpriteSheet(const std::string& path) { this->LoadFile(path); } diff --git a/include/pd/maths/img.hpp b/include/pd/maths/img.hpp new file mode 100644 index 0000000..88e4d1c --- /dev/null +++ b/include/pd/maths/img.hpp @@ -0,0 +1,39 @@ +#pragma once + +/* +MIT License + +Copyright (c) 2024 - 2025 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 Img { +inline int Index3dsTex(int x, int y, int width) { + return ((((y >> 3) * (width >> 3) + (x >> 3)) << 6) + + ((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) | ((y & 2) << 2) | + ((x & 4) << 2) | ((y & 4) << 3))); +} +inline int IndexDefault(int x, int y, int width) { return y * width + x; } +} // namespace Img +} // namespace PD \ No newline at end of file diff --git a/include/pd/maths/img_blur.hpp b/include/pd/maths/img_blur.hpp new file mode 100644 index 0000000..bbaf46d --- /dev/null +++ b/include/pd/maths/img_blur.hpp @@ -0,0 +1,54 @@ +#pragma once + +/* +MIT License + +Copyright (c) 2024 - 2025 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 ImgBlur { +std::vector GaussianKernel(int radius, float si); +/// @brief Gaussian Blur for basic Image Buffer +/// @param buf Image Buffer (unsigned char) +/// @param w // width of the image +/// @param h // width of the image +/// @param radius // Blur radius +/// @param si // Blur sigma +/// @param idxfn // Indexing function (if buffer is 3ds tiled) +void GaussianBlur(std::vector &buf, int w, int h, float radius, float si, + std::function idxfn = Img::IndexDefault); +/// @brief Advanced func to access memory directly +/// @param buf Referenvce to the buffer +/// @param w // width of the image +/// @param h // width of the image +/// @param bpp Bytes per Pixels (RGB[A], RGB565, etc) +/// @param radius // Blur radius +/// @param si // Blur sigma +/// @param idxfn // Indexing function (if buffer is 3ds tiled) +void GaussianBlur(void *buf, int w, int h, int bpp, float radius, float si, + std::function idxfn = Img::IndexDefault); +} // namespace ImgBlur +} // namespace PD \ No newline at end of file diff --git a/include/pd/maths/img_convert.hpp b/include/pd/maths/img_convert.hpp index 058750f..cc7a3c4 100644 --- a/include/pd/maths/img_convert.hpp +++ b/include/pd/maths/img_convert.hpp @@ -30,5 +30,10 @@ namespace PD { namespace ImgConvert { void RGB24toRGBA32(std::vector &out, const std::vector &in, const int &w, const int &h); +/// @brief Reverse 32 (RGBA -> ABGR || ABGR -> RGBA) +/// @param buf Buffer to convert +/// @param w width +/// @param h height +void Reverse32(std::vector &buf, const int &w, const int &h); } // namespace ImgConvert } // namespace PD \ No newline at end of file diff --git a/include/pd/overlays/keyboard.hpp b/include/pd/overlays/keyboard.hpp index 51f8830..7b73847 100644 --- a/include/pd/overlays/keyboard.hpp +++ b/include/pd/overlays/keyboard.hpp @@ -64,6 +64,7 @@ class Keyboard : public Overlay { Flags_BlendTop = 1 << 0, Flags_BlendBottom = 1 << 1, Flags_LockControls = 1 << 2, + Flags_Transparency = 1 << 3, Flags_Default = Flags_BlendBottom | Flags_BlendTop | Flags_LockControls, }; Keyboard(std::string& text, State& state, const std::string& hint = "", diff --git a/include/pd/ui7/flags.hpp b/include/pd/ui7/flags.hpp index 90b28f4..8d26183 100644 --- a/include/pd/ui7/flags.hpp +++ b/include/pd/ui7/flags.hpp @@ -24,6 +24,7 @@ SOFTWARE. */ using UI7MenuFlags = unsigned int; +using UI7Align = unsigned int; enum UI7MenuFlags_ { UI7MenuFlags_None = 0, @@ -33,4 +34,15 @@ enum UI7MenuFlags_ { UI7MenuFlags_VtScrolling = 1 << 3, UI7MenuFlags_NoBackground = 1 << 4, UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling, +}; + +/// @brief Probably need to update this +enum UI7Align_ { + UI7Align_Left = 1 << 0, + UI7Align_Center = 1 << 1, + UI7Align_Right = 1 << 2, + UI7Align_Top = 1 << 3, + UI7Align_Mid = 1 << 4, + UI7Align_Bottom = 1 << 5, + UI7Align_Default = UI7Align_Left | UI7Align_Top, }; \ No newline at end of file diff --git a/include/pd/ui7/menu.hpp b/include/pd/ui7/menu.hpp index 0d5cd10..809f67c 100644 --- a/include/pd/ui7/menu.hpp +++ b/include/pd/ui7/menu.hpp @@ -59,9 +59,12 @@ class Menu : public SmartCtor { void Separator(); void SeparatorText(const std::string& label); void Join(); - /// @brief Horizontal Center Joined objects - void JoinOpHzCenter(); - void AfterAlignCenter(); + void JoinAlign(UI7Align a); + void AfterAlign(UI7Align a); + void NextAlign(UI7Align a) { tmpalign = a; } + void PushAlignment(UI7Align a) { alignment = a; } + void PopAlignment() { alignment = UI7Align_Default; } + static vec2 AlignPos(vec2 pos, vec2 size, vec4 view, UI7Align a); /// API for Custom Objects bool HandleScrolling(vec2& pos, const vec2& size); @@ -89,12 +92,15 @@ class Menu : public SmartCtor { vec4 MainArea() const { return main_area; } void MainArea(const vec4& v) { main_area = v; } vec2 ScrollOffset() const { return scrolling_off; } + void ScrollOffset(const vec2& v) { scrolling_off = v; } + vec2 ScrollMod() const { return scroll_mod; } void ScrollTo(vec2 pos) { scroll_anim.From(scrolling_off) .To(pos) .In(1.f) .As(scroll_anim.EaseInOutSine); } + bool IsAnimatedScroll() { return !scroll_anim.IsFinished(); } /// Objects API Container::Ref ObjectPush(Container::Ref obj); @@ -124,10 +130,17 @@ class Menu : public SmartCtor { vec2 SameLineCursor() const { return slcursor; } void SameLineCursor(const vec2& v) { slcursor = v; } void ViewArea(const vec4& v) { view_area = v; } - void ScrollOffset(const vec2& v) { scrolling_off = v; } - vec2 ScrollMod() const { return scroll_mod; } void ScrollMod(const vec2& v) { scroll_mod = v; } + UI7Align GetAlignment() { + if (tmpalign) { + auto t = tmpalign; + tmpalign = 0; + return t; + } + return alignment; + } + /// Internal Processing void Update(float delta); @@ -135,6 +148,8 @@ class Menu : public SmartCtor { friend class Context; /// Data + UI7Align alignment = UI7Align_Default; + UI7Align tmpalign = 0; UI7MenuFlags flags = 0; u32 id; std::string name; diff --git a/include/pd/ui7/ui7.hpp b/include/pd/ui7/ui7.hpp index 049c68a..f747283 100644 --- a/include/pd/ui7/ui7.hpp +++ b/include/pd/ui7/ui7.hpp @@ -45,6 +45,7 @@ class Context : public SmartCtor { bool BeginMenu(const ID& id, UI7MenuFlags flags = 0); Menu::Ref GetCurrentMenu(); + Menu::Ref FindMenu(const ID& id); void EndMenu(); /// Theme Management diff --git a/source/graphics/lithium.cpp b/source/graphics/lithium.cpp index 6f2a202..e61d59e 100644 --- a/source/graphics/lithium.cpp +++ b/source/graphics/lithium.cpp @@ -281,8 +281,8 @@ void Renderer::StaticText::SetPos(const vec2& pos) { void Renderer::StaticText::SetLayer(int layer) { text->ReLayer(layer); } bool Renderer::InBox(const vec2& pos, const vec2& szs, const vec4& rect) { - return (pos[0] < rect[2] || pos[1] < rect[3] || pos[0] + szs[0] > rect[0] || - pos[1] + szs[1] > rect[1]); + return (pos[0] + szs[0] >= rect[0] && pos[1] + szs[1] >= rect[1] && + pos[0] <= rect[2] && pos[1] <= rect[3]); } bool Renderer::InBox(const vec2& pos, const vec4& rect) { @@ -398,7 +398,7 @@ void Renderer::TextCommand(std::vector& cmds, const vec2& pos, rpos = rbox * 0.5 - td * 0.5 + pos; } if (flags & LITextFlags_AlignRight) { - rpos[0] = rbox[0] - td[0]; + rpos[0] = rpos[0] - td[0]; } std::vector lines; @@ -409,7 +409,13 @@ void Renderer::TextCommand(std::vector& cmds, const vec2& pos, } for (auto& it : lines) { - if (rpos[1] + off[1] + lh < 0) { + if (flags & LITextFlags_Short) { + vec2 tmp_dim; + it = ShortText(it, box.x() - pos.x(), tmp_dim); + } + /// Well support OOS Rendering here as well + /// Fixes UI7 Scroll back up bug + if (rpos[1] + off[1] + lh < 0 && !(flags & LITextFlags_RenderOOS)) { off[1] += lh; continue; } else if (rpos[1] + off[1] > GetViewport().w() && @@ -468,6 +474,58 @@ void Renderer::TextCommand(std::vector& cmds, const vec2& pos, vec4 Renderer::GetViewport() { return vec4(vec2(), screen->GetSize()); } +std::string Renderer::ShortText(const std::string& text, int maxlen, + vec2& newsize) { + vec2 cdim; + if (flags & RenderFlags_TMS) { + auto e = tms.find(text); + if (e != tms.end()) { + e->second.TimeCreated(Sys::GetTime()); + if (e->second.Optional()) { + return e->second.Text(); + } + cdim = e->second.Size(); + } + } + cdim = this->GetTextDimensions(text); + if (cdim[0] < (float)maxlen) { + return text; + } + std::string ext; + /// Forgot why i called this var ending cause + /// Its more a placeholder for removed content + std::string ending = "..."; + std::string cpy = text; + std::string res; + size_t extension = text.find_last_of('.'); + if (extension != text.npos) { + ext = text.substr(extension); + cpy = text.substr(0, extension); + maxlen -= GetTextDimensions(ext).x(); + } + maxlen -= GetTextDimensions(ending).x(); + for (auto& it : cpy) { + if (GetTextDimensions(res).x() > (float)maxlen) { + res += ending; + res += ext; + newsize = GetTextDimensions(res); + if (flags & RenderFlags_TMS) { + auto& tmp = tms[text]; + tmp.Text(res); + tmp.Size(newsize); + tmp.TimeCreated(Sys::GetTime()); + tmp.Optional(true); + } + break; + } + res += it; + } + return res; +} + +std::string Renderer::WrapText(const std::string& text, int maxlen, + vec2& newsize) {} + vec2 Renderer::GetTextDimensions(const std::string& text) { if (!font) { // No font no size (oder so) diff --git a/source/maths/img_blur.cpp b/source/maths/img_blur.cpp new file mode 100644 index 0000000..33cf2da --- /dev/null +++ b/source/maths/img_blur.cpp @@ -0,0 +1,88 @@ +/* +MIT License + +Copyright (c) 2024 - 2025 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 + +namespace PD { +namespace ImgBlur { +std::vector GaussianKernel(int r, float si) { + /// Define radius as r to be shorter + int size = 2 * r + 1; + std::vector kernel(size); + float sum = 0.0f; + + for (int i = -r; i <= r; i++) { + kernel[i + r] = exp(-0.5f * (i * i) / (si * si)); + sum += kernel[i + r]; + } + + for (int i = 0; i < size; i++) { + kernel[i] /= sum; + } + return kernel; +} +void GaussianBlur(std::vector &buf, int w, int h, float radius, float si, + std::function idxfn) { + GaussianBlur(buf.data(), w, h, 4, radius, si, idxfn); +} + +void GaussianBlur(void *buf, int w, int h, int bpp, float radius, float si, + std::function idxfn) { + if (bpp != 4 && bpp != 3) { + return; + } + std::vector kernel = GaussianKernel(radius, si); + int hks = kernel.size() / 2; + int end = w * h * bpp; + std::vector res((u8 *)buf, ((u8 *)buf) + end); + ImgConvert::Reverse32(res, w, h); + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + float r = 0.0f, g = 0.0f, b = 0.0f; + for (int ky = -hks; ky <= hks; ky++) { + for (int kx = -hks; kx <= hks; kx++) { + int xoff = std::min(std::max(x + kx, 0), w - 1); + int yoff = std::min(std::max(y + ky, 0), h - 1); + int idx = idxfn(xoff, yoff, w) * 4; + + float weight = kernel[ky + hks] * kernel[kx + hks]; + r += ((u8 *)buf)[idx] * weight; + g += ((u8 *)buf)[idx + 1] * weight; + b += ((u8 *)buf)[idx + 2] * weight; + } + } + int idx = idxfn(x, y, w) * bpp; + res[idx] = std::min(std::max(int(r), 0), 255); + res[idx + 1] = std::min(std::max(int(g), 0), 255); + res[idx + 2] = std::min(std::max(int(b), 0), 255); + } + } + ImgConvert::Reverse32(res, w, h); + std::memcpy(buf, res.data(), res.size()); +} +} // namespace ImgBlur +} // namespace PD \ No newline at end of file diff --git a/source/maths/img_convert.cpp b/source/maths/img_convert.cpp index 216ff3c..5357d59 100644 --- a/source/maths/img_convert.cpp +++ b/source/maths/img_convert.cpp @@ -21,6 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include namespace PD::ImgConvert { @@ -38,4 +39,17 @@ void RGB24toRGBA32(std::vector &out, const std::vector &in, } } } +void Reverse32(std::vector &buf, const int &w, const int &h) { + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int i = Img::IndexDefault(x, y, w); + u8 t0 = buf[i + 0]; + u8 t1 = buf[i + 1]; + buf[i + 0] = buf[i + 3]; + buf[i + 1] = buf[i + 2]; + buf[i + 3] = t0; + buf[i + 2] = t1; + } + } +} } // namespace PD::ImgConvert \ No newline at end of file diff --git a/source/overlays/keyboard.cpp b/source/overlays/keyboard.cpp index 16143ad..6453d42 100644 --- a/source/overlays/keyboard.cpp +++ b/source/overlays/keyboard.cpp @@ -531,8 +531,10 @@ void Keyboard::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) { /// Get the current start possition vec2 start = flymgr; // Draw head and Keyboard background + ren->DrawRectSolid( + vec2(0, start.y()), vec2(320, 125), + PD::Color("#222222ff").a((flags & Flags_Transparency) ? 0xaa : 0xff)); ren->DrawRectSolid(vec2(0, start.y()), vec2(320, 17), 0xaa000000); - ren->DrawRectSolid(vec2(0, start.y()), vec2(320, 125), 0xaa222222); /// Grab the base layer and go one up for texts int l = ren->Layer(); ren->Layer(l + 2); diff --git a/source/overlays/performance.cpp b/source/overlays/performance.cpp index d87b338..c5c404f 100644 --- a/source/overlays/performance.cpp +++ b/source/overlays/performance.cpp @@ -32,7 +32,7 @@ void Performance::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) { if (*skill) { Kill(); } - ren->OnScreen(ren->GetScreen(false)); + ren->OnScreen(ren->GetScreen(*screen)); ren->TextScale(0.6); vec2 pos; Line(pos, std::format("{:.1f} FPS / {:.2f}ms", 1000.f / delta, delta), ren); diff --git a/source/overlays/settings.cpp b/source/overlays/settings.cpp index 541af9c..37bc743 100644 --- a/source/overlays/settings.cpp +++ b/source/overlays/settings.cpp @@ -16,13 +16,13 @@ void SettingsMenu::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) { auto m = ctx->GetCurrentMenu(); m->SeparatorText("Library Info"); m->Label(LibInfo::CompiledWith()); - m->AfterAlignCenter(); + m->AfterAlign(UI7Align_Center); m->Label(LibInfo::CxxVersion()); - m->AfterAlignCenter(); + m->AfterAlign(UI7Align_Center); m->Label("Version: " + LibInfo::Version() + "[" + LibInfo::Commit() + "]"); - m->AfterAlignCenter(); + m->AfterAlign(UI7Align_Center); m->Label("Build Time: " + LibInfo::BuildTime()); - m->AfterAlignCenter(); + m->AfterAlign(UI7Align_Center); ctx->EndMenu(); } ren->OnScreen(ren->GetScreen(true)); diff --git a/source/ui7/container/container.cpp b/source/ui7/container/container.cpp index 0db0652..930f4c3 100644 --- a/source/ui7/container/container.cpp +++ b/source/ui7/container/container.cpp @@ -32,9 +32,7 @@ void Container::HandleScrolling(vec2 scrolling, vec4 viewport) { } last_use = Sys::GetTime(); pos -= vec2(0, scrolling.y()); - if (!LI::Renderer::InBox(pos, size, viewport)) { - skippable = true; - } + skippable = !LI::Renderer::InBox(pos, size, viewport); } } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/source/ui7/drawlist.cpp b/source/ui7/drawlist.cpp index 7a1f314..5f9599d 100644 --- a/source/ui7/drawlist.cpp +++ b/source/ui7/drawlist.cpp @@ -68,6 +68,7 @@ void DrawList::AddText(vec2 pos, const std::string& text, const UI7Color& clr, if (!e->second->IsSetup() || e->second->Font() != ren->Font()) { int l = ren->Layer(); ren->Layer(base); + /// Probably a simple ren.get() would handle the job too e->second->Setup(&(*ren), pos, clr, text, flags, box); e->second->Font(ren->Font()); ren->Layer(l); diff --git a/source/ui7/menu.cpp b/source/ui7/menu.cpp index aaabab7..86d755f 100644 --- a/source/ui7/menu.cpp +++ b/source/ui7/menu.cpp @@ -30,6 +30,7 @@ namespace UI7 { void UI7::Menu::Label(const std::string& label) { Container::Ref r = ObjectPush(PD::New(label, Cursor(), this->back->ren)); + r->SetPos(AlignPos(r->GetPos(), r->GetSize(), view_area, GetAlignment())); CursorMove(r->GetSize()); r->Init(main->ren, main, linked_theme); r->HandleScrolling(scrolling_off, view_area); @@ -45,7 +46,7 @@ bool UI7::Menu::Button(const std::string& label) { r->Init(main->ren, main, linked_theme); } ObjectPush(r); - r->SetPos(Cursor()); + r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment())); CursorMove(r->GetSize()); r->HandleScrolling(scrolling_off, view_area); if (!r->Skippable()) { @@ -63,7 +64,7 @@ void UI7::Menu::Checkbox(const std::string& label, bool& v) { r->Init(main->ren, main, linked_theme); } ObjectPush(r); - r->SetPos(Cursor()); + r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment())); CursorMove(r->GetSize()); r->HandleScrolling(scrolling_off, view_area); } @@ -71,6 +72,7 @@ void UI7::Menu::Checkbox(const std::string& label, bool& v) { void UI7::Menu::Image(Texture::Ref img, vec2 size) { Container::Ref r = ObjectPush(PD::New(img, Cursor(), this->back->ren, size)); + r->SetPos(AlignPos(r->GetPos(), r->GetSize(), view_area, GetAlignment())); CursorMove(r->GetSize()); r->Init(main->ren, main, linked_theme); r->HandleScrolling(scrolling_off, view_area); @@ -113,7 +115,9 @@ void UI7::Menu::Update(float delta) { idobjs.push_back(it); } if (!it->Skippable()) { - it->HandleInput(inp); + if (scroll_mod[1] == 0.f) { + it->HandleInput(inp); + } /// Unlock Input after to ensure nothing is checked twice it->UnlockInput(); it->Draw(); @@ -262,6 +266,20 @@ void UI7::Menu::PostHandler() { } } + /// Slider Dragging???? + /// Probably need a new API for this + auto tp = inp->TouchPos(); + if (inp->IsHeld(inp->Touch) && + LI::Renderer::InBox(tp, vec4(screen_w - 12, tsp, 8, szs))) { + float drag_center = vslider_h / 2.0f; + float drag_pos = + std::clamp(static_cast((tp[1] - tsp - drag_center) / + (szs - vslider_h - 4)), + 0.0f, 1.0f); + + scrolling_off[1] = drag_pos * (max[1] - 240.f); + } + int srpos = tsp + std::clamp(float(szs - vslider_h - 4) * (scrolling_off[1] / (max[1] - view_area[3])), @@ -318,10 +336,8 @@ void UI7::Menu::SeparatorText(const std::string& label) { bool UI7::Menu::HandleScrolling(vec2& pos, const vec2& size) { if (scrolling[1]) { - vec2 p = pos; pos -= vec2(0, scrolling_off.y()); - if (pos.y() > view_area.w() || - (pos.y() + size.y() < tbh - 5 && p.y() > tbh)) { + if (pos.y() > view_area.w() || (pos.y() + size.y() < view_area.y())) { return true; } } @@ -347,22 +363,50 @@ void UI7::Menu::Join() { join.push_back(objects.back().get()); } -void UI7::Menu::JoinOpHzCenter() { +void UI7::Menu::JoinAlign(UI7Align a) { + if (a == 0) { + a = UI7Align_Default; + } this->Join(); - float spos = join.front()->GetPos().x(); - float szs = join.back()->GetPos().x() + join.back()->GetSize().x() - spos; - float off = (view_area.x() + view_area.z() * 0.5) - (spos + szs * 0.5); + + vec2 spos = join.front()->GetPos(); + vec2 szs = join.back()->GetPos() + join.back()->GetSize() - spos; + vec2 off; + if (a & UI7Align_Center) { + off[0] = (view_area[0] + view_area[2] * 0.5) - (spos[0] + szs[0] * 0.5); + } + if (a & UI7Align_Mid) { + off[1] = (view_area[1] + view_area[3] * 0.5) - (spos[1] + szs[1] * 0.5); + } for (auto it : join) { - it->SetPos(it->GetPos() + vec2(off, 0.f)); + it->SetPos(it->GetPos() + off); } join.clear(); } -void UI7::Menu::AfterAlignCenter() { + +vec2 UI7::Menu::AlignPos(vec2 pos, vec2 size, vec4 view, UI7Align a) { + vec2 np = pos; + if (a & UI7Align_Center) { + np[0] = (view[0] + view[2] * 0.5) - (pos[0] + size[0] * 0.5); + } + if (a & UI7Align_Mid) { + np[1] = (view[1] + view[3] * 0.5) - (pos[1] + size[1] * 0.5); + } + return np; +} + +void UI7::Menu::AfterAlign(UI7Align a) { Container* ref = objects.back().get(); vec2 p = ref->GetPos(); vec2 s = ref->GetSize(); - float newx = (view_area.x() + view_area.z() * 0.5) - (p.x() + s.x() * 0.5); - ref->SetPos(vec2(newx, p.y())); + vec2 np = p; + if (a & UI7Align_Center) { + np[0] = (view_area[0] + view_area[2] * 0.5) - (p[0] + s[0] * 0.5); + } + if (a & UI7Align_Mid) { + np[1] = (view_area[1] + view_area[3] * 0.5) - (p[1] + s[1] * 0.5); + } + ref->SetPos(np); } } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/source/ui7/ui7.cpp b/source/ui7/ui7.cpp index 324224c..e23d1bd 100644 --- a/source/ui7/ui7.cpp +++ b/source/ui7/ui7.cpp @@ -58,6 +58,14 @@ UI7::Menu::Ref UI7::Context::GetCurrentMenu() { return current; } +UI7::Menu::Ref UI7::Context::FindMenu(const ID& id) { + auto e = this->menus.find(id); + if (e != this->menus.end()) { + return e->second; + } + return nullptr; +} + void UI7::Context::EndMenu() { this->current->PostHandler(); this->current = nullptr; diff --git a/test/app/main.cpp b/test/app/main.cpp index 3c96783..21a54ab 100644 --- a/test/app/main.cpp +++ b/test/app/main.cpp @@ -60,26 +60,20 @@ class Test : public PD::App { m->SeparatorText("Menu Timings"); m->DebugLabels(); m->SeparatorText("Palladium Info"); + m->PushAlignment(UI7Align_Center); m->Label("Version: " + PD::LibInfo::Version() + " [" + PD::LibInfo::Commit() + "]"); - m->AfterAlignCenter(); m->Label("CompileInfo: " + PD::LibInfo::CompiledWith() + " - " + PD::LibInfo::CxxVersion()); - m->AfterAlignCenter(); m->Label("Build at " + PD::LibInfo::BuildTime()); - m->AfterAlignCenter(); m->SeparatorText("Basic Info"); m->Label("sizeof(size_t): " + std::to_string(sizeof(size_t)) + " -> " + std::to_string(sizeof(size_t) * 8) + "Bit"); - m->AfterAlignCenter(); m->Label("__cplusplus=" + std::to_string(__cplusplus)); - m->AfterAlignCenter(); m->Label(PD::Strings::GetCompilerVersion()); - m->AfterAlignCenter(); m->Label("sizeof(LI::Vertex): " + std::to_string(sizeof(PD::LI::Vertex))); - m->AfterAlignCenter(); m->Label("sizeof(PD::u16): " + std::to_string(sizeof(PD::u16))); - m->AfterAlignCenter(); + m->PopAlignment(); m->SeparatorText("UI7 Tests"); m->Label("This seems to be a label"); m->Image(test);