diff --git a/.gitignore b/.gitignore index 4e7bf47..98060db 100755 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ .cache +.vscode \ No newline at end of file diff --git a/include/pd/core/vec.hpp b/include/pd/core/vec.hpp index 774e61b..1f068bc 100755 --- a/include/pd/core/vec.hpp +++ b/include/pd/core/vec.hpp @@ -39,7 +39,7 @@ template struct std::formatter, CharT> : std::formatter { template auto format(const PD::vec2& v, FormatContext& ctx) const { - return std::format_to(ctx.out(), "({}, {})", v.x, v.y); + return std::format_to(ctx.out(), "{}, {}", v.x, v.y); } }; @@ -47,7 +47,7 @@ template struct std::formatter, CharT> : std::formatter { template auto format(const PD::vec3& v, FormatContext& ctx) const { - return std::format_to(ctx.out(), "({}, {}, {})", v.x, v.y, v.z); + return std::format_to(ctx.out(), "{}, {}, {}", v.x, v.y, v.z); } }; @@ -55,6 +55,6 @@ template struct std::formatter, CharT> : std::formatter { template auto format(const PD::vec4& v, FormatContext& ctx) const { - return std::format_to(ctx.out(), "({}, {}, {}, {})", v.x, v.y, v.z, v.w); + return std::format_to(ctx.out(), "{}, {}, {}, {}", v.x, v.y, v.z, v.w); } }; \ No newline at end of file diff --git a/include/pd/lithium/drawlist.hpp b/include/pd/lithium/drawlist.hpp index d023aee..a523d3c 100755 --- a/include/pd/lithium/drawlist.hpp +++ b/include/pd/lithium/drawlist.hpp @@ -61,6 +61,14 @@ class PD_LITHIUM_API DrawList { PD_SHARED(DrawList); + /** + * Append an input drawlist on top of this one + * This Function will clear the Input list to make sure + * THat the moved memory blocks don't get used + * @param list DrawList to move into current + */ + void Merge(DrawList::Ref list); + Command::Ref PreGenerateCmd(); void AddCommand(Command::Ref v) { pDrawList.push_back(std::move(v)); } void Clear() { pDrawList.clear(); } diff --git a/include/pd/lithium/rect.hpp b/include/pd/lithium/rect.hpp index 88cc3ba..95bf228 100755 --- a/include/pd/lithium/rect.hpp +++ b/include/pd/lithium/rect.hpp @@ -85,7 +85,7 @@ class Rect { * Get the bottom-right corner position. * @return Bottom-right position as vec2. */ - fvec2 BotRight() const { return fvec2(Bot.z, Bot.y); } + fvec2 BotRight() const { return fvec2(Bot.z, Bot.w); } /** * Set the top-left corner position. diff --git a/include/pd/ui7/container/container.hpp b/include/pd/ui7/container/container.hpp index 1ba00a9..b64fae7 100755 --- a/include/pd/ui7/container/container.hpp +++ b/include/pd/ui7/container/container.hpp @@ -63,6 +63,11 @@ class PD_UI7_API Container { // 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 */ @@ -161,6 +166,10 @@ class PD_UI7_API Container { 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/dynobj.hpp b/include/pd/ui7/container/dynobj.hpp index 810765c..dd3747d 100755 --- a/include/pd/ui7/container/dynobj.hpp +++ b/include/pd/ui7/container/dynobj.hpp @@ -52,6 +52,10 @@ class PD_UI7_API DynObj : public Container { PD_SHARED(DynObj); + void AddInputHandler(std::function inp) { + pInp = inp; + } + /** Return true if butten is pressed*/ bool IsPressed() { return pressed; } /** @@ -72,6 +76,7 @@ class PD_UI7_API DynObj : public Container { 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/flags.hpp b/include/pd/ui7/flags.hpp index 9e62402..027639d 100755 --- a/include/pd/ui7/flags.hpp +++ b/include/pd/ui7/flags.hpp @@ -31,8 +31,6 @@ using UI7Align = unsigned int; using UI7IOFlags = unsigned int; /** 32Bit Value for Layout Flags */ using UI7LayoutFlags = unsigned int; -/** 32Bit value for DrawFlags */ -using UI7DrawFlags = unsigned int; /** Menu Flags */ enum UI7MenuFlags_ { @@ -48,6 +46,9 @@ enum UI7MenuFlags_ { 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 // Enable Horizontal and Vertical Scrolling UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling, }; @@ -58,12 +59,6 @@ enum UI7LayoutFlags_ { UI7LayoutFlags_UseClipRect = 1 << 0, ///< Enable ClipRect }; -enum UI7DrawFlags_ { - UI7DrawFlags_None = 0, - UI7DrawFlags_Close = 1 << 0, ///< Close a PolyLine - UI7DrawFlags_AALines = 1 << 1, ///< Anti aliased Lines -}; - /** UI7 Context Flags */ enum UI7IOFlags_ { UI7IOFlags_None = 0, ///< No Additional Config available @@ -91,6 +86,11 @@ enum UI7LytAdd_ { 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, diff --git a/include/pd/ui7/io.hpp b/include/pd/ui7/io.hpp index 1b181b5..931b153 100755 --- a/include/pd/ui7/io.hpp +++ b/include/pd/ui7/io.hpp @@ -40,6 +40,7 @@ class PD_UI7_API IO { Theme = UI7::Theme::New(); Back = Li::DrawList::New(); Front = Li::DrawList::New(); + FDL = Li::DrawList::New(); DeltaStats = TimeStats::New(60); /** Probably not the best solution i guess */ CurrentViewPort.z = PD::Li::Gfx::pGfx->ViewPort.x; @@ -54,6 +55,12 @@ class PD_UI7_API IO { */ void Update(); + /** + * Final Draw List for PD::Li::Gfx::RednerDrawData + * + * Possible thanks to the DrawList::Merge Feature + */ + Li::DrawList::Ref FDL = nullptr; ivec4 CurrentViewPort = ivec4(0, 0, 0, 0); std::unordered_map ViewPorts; float Framerate = 0.f; @@ -94,6 +101,13 @@ class PD_UI7_API IO { ViewPorts[id] = ViewPort::New(id, size); } + ViewPort::Ref GetViewPort(const ID& id) { + if (ViewPorts.count(id)) { + return nullptr; + } + return ViewPorts[id]; + } + UI7::InputHandler::Ref InputHandler; }; } // namespace UI7 diff --git a/include/pd/ui7/layout.hpp b/include/pd/ui7/layout.hpp index 6ccd2a6..1af1d2e 100755 --- a/include/pd/ui7/layout.hpp +++ b/include/pd/ui7/layout.hpp @@ -126,7 +126,8 @@ class PD_UI7_API Layout { fvec2 MaxPosition; fvec4 WorkRect; - // Scrolling + // Scrolling (Only theoretical) + // Rendering must be done by the Objective that uses the Lyt fvec2 ScrollOffset; bool Scrolling[2]; diff --git a/include/pd/ui7/menu.hpp b/include/pd/ui7/menu.hpp index 18e86ae..cf50ff2 100755 --- a/include/pd/ui7/menu.hpp +++ b/include/pd/ui7/menu.hpp @@ -24,16 +24,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "pd/ui7/container/dragdata.hpp" #include #include #include #include +#include "pd/ui7/container/dragdata.hpp" + namespace PD { namespace UI7 { class PD_UI7_API Menu { -public: + public: Menu(const UI7::ID &id, UI7::IO::Ref pIO); ~Menu() {} @@ -87,9 +88,11 @@ public: } pLayout->AddObject(r); } - void Sameline() { pLayout->SameLine(); } + void SameLine() { pLayout->SameLine(); } void Separator(); void SeparatorText(const std::string &label); + bool BeginTreeNode(const ID &id); + void EndTreeNode(); void HandleFocus(); void HandleScrolling(); @@ -106,8 +109,9 @@ public: ID pID; bool *pIsShown = nullptr; bool pIsOpen = true; + std::unordered_map pTreeNodes; float TitleBarHeight = 0.f; }; -} // namespace UI7 -} // namespace PD +} // namespace UI7 +} // namespace PD diff --git a/include/pd/ui7/ui7.hpp b/include/pd/ui7/ui7.hpp index 626bf32..751e1e2 100755 --- a/include/pd/ui7/ui7.hpp +++ b/include/pd/ui7/ui7.hpp @@ -24,12 +24,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "pd/ui7/flags.hpp" #include #include #include #include +#include "pd/ui7/flags.hpp" + /** * Declare UI7 Version * Format: 00 00 00 00 @@ -48,7 +49,7 @@ namespace UI7 { PD_UI7_API std::string GetVersion(bool show_build = false); /** Base Context for UI7 */ class PD_UI7_API Context { -public: + public: Context() { pIO = IO::New(); } ~Context() = default; @@ -57,8 +58,13 @@ public: void AddViewPort(const ID &id, const ivec4 &vp); void UseViewPort(const ID &id); void Update(); - bool BeginMenu(const ID &id, UI7MenuFlags flags, bool *pShow = nullptr); + bool BeginMenu(const ID &id, UI7MenuFlags flags = 0, bool *pShow = nullptr); void EndMenu(); + void AboutMenu(bool *show = nullptr); + void MetricsMenu(bool *show = nullptr); + void StyleEditor(bool *show = nullptr); + + Li::DrawList::Ref GetDrawData() { return pIO->FDL; } Menu::Ref pGetOrCreateMenu(const ID &id) { auto menu = pMenus.find(id); @@ -73,7 +79,8 @@ public: /** Current Menu */ Menu::Ref pCurrent = nullptr; std::vector pCurrentMenus; + std::vector pDFO; /** Debug Final Order */ std::unordered_map pMenus; }; -} // namespace UI7 -} // namespace PD +} // namespace UI7 +} // namespace PD diff --git a/pd/lithium/source/drawlist.cpp b/pd/lithium/source/drawlist.cpp index 3fe0714..acdd8d3 100755 --- a/pd/lithium/source/drawlist.cpp +++ b/pd/lithium/source/drawlist.cpp @@ -33,13 +33,21 @@ namespace PD { namespace Li { PD_LITHIUM_API void DrawList::DrawSolid() { CurrentTex = Gfx::GetSolidTex(); } +PD_LITHIUM_API void DrawList::Merge(DrawList::Ref list) { + for (size_t i = 0; i < list->pDrawList.size(); i++) { + pDrawList.push_back(std::move(list->pDrawList[i])); + } + /** Make sure The list gets cleared */ + list->Clear(); +} + PD_LITHIUM_API Command::Ref DrawList::PreGenerateCmd() { Command::Ref cmd = Command::New(); cmd->Layer = Layer; cmd->Index = pDrawList.size(); cmd->Tex = CurrentTex; pClipCmd(cmd.get()); - return std::move(cmd); + return cmd; } PD_LITHIUM_API void DrawList::pClipCmd(Command *cmd) { @@ -193,7 +201,7 @@ PD_LITHIUM_API void DrawList::DrawCircle(const fvec2 ¢er, float rad, float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments; PathArcToN(center, rad, 0.f, am, num_segments); } - DrawSolid(); // Only Solid Color Supported + DrawSolid(); // Only Solid Color Supported PathStroke(color, thickness, (1 << 0)); } @@ -234,7 +242,7 @@ PD_LITHIUM_API void DrawList::DrawPolyLine(const Vec &points, u32 clr, PD_LITHIUM_API void DrawList::DrawConvexPolyFilled(const Vec &points, u32 clr) { if (points.Size() < 3) { - return; // Need at least three points + return; // Need at least three points } auto cmd = PreGenerateCmd(); Renderer::CmdConvexPolyFilled(cmd.get(), points, clr, CurrentTex); @@ -276,5 +284,5 @@ PD_LITHIUM_API void DrawList::DrawLine(const fvec2 &a, const fvec2 &b, PathAdd(b); PathStroke(color, t); } -} // namespace Li -} // namespace PD +} // namespace Li +} // namespace PD diff --git a/pd/ui7/source/container/dynobj.cpp b/pd/ui7/source/container/dynobj.cpp index 6e7d2ac..f369114 100755 --- a/pd/ui7/source/container/dynobj.cpp +++ b/pd/ui7/source/container/dynobj.cpp @@ -27,7 +27,13 @@ SOFTWARE. namespace PD { namespace UI7 { PD_UI7_API void DynObj::Draw() { pRenFun(io, list, this); } -PD_UI7_API void DynObj::HandleInput() {} + +PD_UI7_API void DynObj::HandleInput() { + if (pInp) { + pInp(io, this); + } +} + PD_UI7_API void DynObj::Update() {} } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/pd/ui7/source/container/label.cpp b/pd/ui7/source/container/label.cpp index 19ddee2..4616f03 100755 --- a/pd/ui7/source/container/label.cpp +++ b/pd/ui7/source/container/label.cpp @@ -28,7 +28,13 @@ namespace UI7 { PD_UI7_API void Label::Draw() { // Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // io->Ren->OnScreen(screen); + if (pCLipRectUsed) { + list->PushClipRect(pClipRect); + } list->DrawText(FinalPos(), label, io->Theme->Get(UI7Color_Text)); + if (pCLipRectUsed) { + list->PopClipRect(); + } } } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/pd/ui7/source/menu.cpp b/pd/ui7/source/menu.cpp index edd9b06..19c0faa 100755 --- a/pd/ui7/source/menu.cpp +++ b/pd/ui7/source/menu.cpp @@ -37,6 +37,7 @@ Menu::Menu(const ID &id, IO::Ref io) : pIO(io), pID(id) { PD_UI7_API void Menu::Label(const std::string &label) { // Layout API auto r = Label::New(label, pIO); + r->SetClipRect(fvec4(pLayout->GetPosition(), pLayout->GetSize())); pLayout->AddObject(r); } @@ -128,7 +129,10 @@ PD_UI7_API void Menu::HandleFocus() { pIO->InputHandler->FocusedMenuRect = newarea; } } + +/** Todo: (func name is self describing) */ PD_UI7_API void Menu::HandleScrolling() {} + PD_UI7_API void Menu::HandleTitlebarActions() { // Collapse if (!(Flags & UI7MenuFlags_NoCollapse)) { @@ -157,6 +161,21 @@ PD_UI7_API void Menu::HandleTitlebarActions() { // 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( @@ -167,13 +186,35 @@ PD_UI7_API void Menu::HandleTitlebarActions() { } pLayout->Pos = pLayout->Pos + (pIO->InputHandler->DragPosition - pIO->InputHandler->DragLastPosition); - // Have no ViewPort Yet :( - // pLayout->Pos = std::clamp(pLayout->Pos, fvec2(10), fvec2(1270, 710)); + // 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.z - 10); + pLayout->Pos.y = + std::clamp(pLayout->Pos.y, 0.f, pIO->CurrentViewPort.w - 10); } } } PD_UI7_API void Menu::DrawBaseLayout() { if (pIsOpen) { + /** Resize Sym (Render on Top of Everything) */ + if (!(Flags & UI7MenuFlags_NoResize)) { + Container::Ref r = DynObj::New( + [](IO::Ref io, Li::DrawList::Ref 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::Ref r = DynObj::New([](IO::Ref io, Li::DrawList::Ref l, UI7::Container *self) { l->Layer = 0; @@ -237,7 +278,7 @@ PD_UI7_API void Menu::DrawBaseLayout() { } /** Close Sym (only shown if pIsShown is not nullptr) */ if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) { - fvec2 size = TitleBarHeight - pIO->FramePadding.y * 2; // Fixed quad size + 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()); @@ -254,6 +295,7 @@ PD_UI7_API void Menu::DrawBaseLayout() { } } } + PD_UI7_API void Menu::Update() { HandleFocus(); if (!(Flags & UI7MenuFlags_NoTitlebar)) { @@ -262,5 +304,62 @@ PD_UI7_API void Menu::Update() { DrawBaseLayout(); pLayout->Update(); } -} // namespace UI7 -} // namespace PD + +PD_UI7_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(), pIO->FontScale); + fvec2 szs = tdim + fvec2(pIO->ItemSpace.x + 10, 0); + + if (n->second) { + pLayout->InitialCursorOffset += 10.f; + } + + // Object + auto r = + DynObj::New([=, this](IO::Ref io, Li::DrawList::Ref 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(), io->Theme->Get(UI7Color_Text)); + }); + /** Yes this new function handler was created for tree nodes */ + r->AddInputHandler([=, this](IO::Ref 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_UI7_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/pd/ui7/source/ui7.cpp b/pd/ui7/source/ui7.cpp index 7417e2a..1f0cff0 100755 --- a/pd/ui7/source/ui7.cpp +++ b/pd/ui7/source/ui7.cpp @@ -21,9 +21,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include + #include "pd/ui7/flags.hpp" #include "pd/ui7/pd_p_api.hpp" -#include + +#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x) +#define UI7DTF(x) PD::Strings::FormatNanos(x) namespace PD { namespace UI7 { @@ -32,8 +36,7 @@ PD_UI7_API std::string GetVersion(bool show_build) { s << ((UI7_VERSION >> 24) & 0xFF) << "."; s << ((UI7_VERSION >> 16) & 0xFF) << "."; s << ((UI7_VERSION >> 8) & 0xFF); - if (show_build) - s << "-" << ((UI7_VERSION) & 0xFF); + if (show_build) s << "-" << ((UI7_VERSION) & 0xFF); return s.str(); } @@ -63,11 +66,271 @@ PD_UI7_API bool Context::BeginMenu(const ID &id, UI7MenuFlags flags, } pCurrent = pGetOrCreateMenu(id); this->pCurrent->pIsShown = pShow; - this->pIO->InputHandler->CurrentMenu = id; - + if (pCurrent->pIsShown != nullptr) { + if (!*pCurrent->pIsShown) { + pCurrent = nullptr; + return false; + } + } + /** 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 != nullptr; } -PD_UI7_API void Context::Update() { pIO->Update(); } -} // namespace UI7 -} // namespace PD +PD_UI7_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_UI7_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(); +} + +PD_UI7_API void Context::AboutMenu(bool *show) { + if (BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) { + auto m = pCurrent; + 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 -> (hidden)"); // + LibInfo::CompiledWith()); + } + EndMenu(); + } +} + +PD_UI7_API void Context::MetricsMenu(bool *show) { + if (BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) { + auto m = pCurrent; + 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(OS::GetTraceMap().size()) + + ")")) { + for (auto &it : OS::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(); + } + /** 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_UI7_API void UI7::Context::StyleEditor(bool *show) { + if (this->BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) { + auto m = pCurrent; + + 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.get()); + } + m->SameLine(); + if (m->Button("Flashbang")) { + UI7::Theme::Flashbang(*pIO->Theme.get()); + } + /// 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); + ts2(UI7Color_Background); + ts2(UI7Color_Border); + ts2(UI7Color_Button); + ts2(UI7Color_ButtonDead); + ts2(UI7Color_ButtonActive); + ts2(UI7Color_ButtonHovered); + ts2(UI7Color_Text); + ts2(UI7Color_TextDead); + ts2(UI7Color_Header); + ts2(UI7Color_HeaderDead); + ts2(UI7Color_Selector); + ts2(UI7Color_Checkmark); + ts2(UI7Color_FrameBackground); + ts2(UI7Color_FrameBackgroundHovered); + ts2(UI7Color_Progressbar); + ts2(UI7Color_ListEven); + ts2(UI7Color_ListOdd); + this->EndMenu(); + } +} +} // namespace UI7 +} // namespace PD diff --git a/test/source/main.cpp b/test/source/main.cpp index 3fcf690..ef3391f 100755 --- a/test/source/main.cpp +++ b/test/source/main.cpp @@ -17,6 +17,8 @@ void RoundedRect(PD::Li::DrawList::Ref l, PD::fvec2 p, PD::fvec2 s, PD::u32 clr, } int v = 20; +int TheScale = 1; +bool AboutOderSo = true; int main() { void *PD_INIT_DATA = nullptr; @@ -63,9 +65,6 @@ int main() { ui7->AddViewPort(VpTop, PD::ivec4(0, 0, 400, 240)); ui7->UseViewPort(VpTop); ui7->pIO->Font = font; - PD::UI7::Menu::Ref menu = PD::UI7::Menu::New("Test", ui7->pIO); - bool open_haxx = true; - menu->pIsShown = &open_haxx; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** MainLoop */ #ifndef __3DS__ @@ -81,6 +80,7 @@ int main() { int wx, wy; glfwGetWindowSize(win, &wx, &wy); PD::Li::Gfx::pGfx->ViewPort = PD::ivec2(wx, wy); + // ui7->pIO->GetViewPort(VpTop)->pSize = PD::ivec4(0, 0, wx, wy); #endif /** Rendering some stuff */ List->DrawSolid(); @@ -90,7 +90,10 @@ int main() { RoundedRect(List, PD::fvec2(200, 50), 100, 0xffffffff, ((1 + std::sin(PD::OS::GetTime() / 1000.f)) * 0.5f) * 100.f); List->DrawText(PD::fvec2(50, 190), "OK", 0xffffffff); - List->DrawLine(PD::fvec2(0), PD::fvec2(1000, 600), 0xffffffff); + // List->DrawLine(PD::fvec2(0), PD::fvec2(1000, 600), 0xffffffff); + List->PathAdd(500); + List->PathAdd(550); + List->PathStroke(0xff00ffff, TheScale); // List->DrawRectFilled(PD::fvec2(10, 10), PD::fvec2(1260, 700), // 0xffffffff); /** Draw text */ @@ -103,10 +106,12 @@ int main() { PD::Hid::MousePos()) + "\nUI7 Version: " + PD::UI7::GetVersion(), 0xff000000); - ui7->pIO->InputHandler->CurrentMenu = menu->pID; - if (menu->pIsOpen) { + if (ui7->BeginMenu("Test")) { + auto menu = ui7->pCurrent; menu->Label("Hello"); menu->Label("World!"); + menu->Checkbox("About Menu", AboutOderSo); + menu->DragData("Line", &TheScale); if (menu->Button("Test")) { break; } @@ -117,9 +122,50 @@ int main() { menu->Label( std::format("Left: {}", PD::Hid::IsHeld(PD::Hid::Key::Touch))); menu->DragData("Value", &v, 1); + ui7->EndMenu(); } - menu->Update(); + if (ui7->BeginMenu("Yet another Window")) { + auto menu = ui7->pCurrent; + menu->Label(std::format("this->Pos: {}", menu->pLayout->GetPosition())); + menu->Label( + std::format("Vertices: {}", PD::Li::Gfx::pGfx->VertexCounter)); + menu->Label(std::format("Indices: {}", PD::Li::Gfx::pGfx->IndexCounter)); + ui7->EndMenu(); + } + if (ui7->BeginMenu("#Debug (UI7)")) { + auto menu = ui7->pCurrent; + menu->Label(std::format("Framerate: {:.1f} [{:.2f}]", ui7->pIO->Framerate, + ui7->pIO->Delta)); + menu->SeparatorText("Input"); + menu->Label(std::format("FocusedMenu: #{:08X}", + ui7->pIO->InputHandler->FocusedMenu)); + menu->Label(std::format("FocusedMenuRect: {}", + ui7->pIO->InputHandler->FocusedMenuRect)); + menu->SeparatorText("Menu Order"); + for (auto &it : ui7->pDFO) { + menu->Label(std::format("{}", ui7->pMenus[it]->pID.GetName())); + } + ui7->EndMenu(); + } + if (ui7->BeginMenu("NoDebug")) { + auto m = ui7->pCurrent; + if (m->BeginTreeNode("Test")) { + m->Label("Hello World!"); + if (m->BeginTreeNode("AnotherNode")) { + m->Label("Another Label!"); + m->EndTreeNode(); + } + m->EndTreeNode(); + } + m->Label("Yes another Label!"); + ui7->EndMenu(); + } + ui7->AboutMenu(&AboutOderSo); + ui7->MetricsMenu(); + ui7->StyleEditor(); + PD::TT::Beg("ui7->Update"); ui7->Update(); + PD::TT::End("ui7->Update"); /** Render DrawData */ #ifdef __3DS__ C3D_FrameBegin(C3D_FRAME_SYNCDRAW); @@ -129,10 +175,9 @@ int main() { PD::TT::Beg("REN"); PD::Li::Gfx::NewFrame(); PD::Li::Gfx::RenderDrawData(List->pDrawList); - PD::Li::Gfx::RenderDrawData(menu->pLayout->GetDrawList()->pDrawList); + PD::Li::Gfx::RenderDrawData(ui7->GetDrawData()->pDrawList); /** Clear The List */ List->Clear(); - menu->pLayout->GetDrawList()->pDrawList.clear(); PD::TT::End("REN"); #ifndef __3DS__ /** Do OS Specifc Stuff (swapp buffers / window buttan events) */ diff --git a/tools/ppam/source/main.cpp b/tools/ppam/source/main.cpp index 6a75ac2..e3ca06b 100755 --- a/tools/ppam/source/main.cpp +++ b/tools/ppam/source/main.cpp @@ -28,7 +28,9 @@ SOFTWARE. #include #include -const char* license_text = R"(/* +constexpr std::string_view ppa_text = R"(#pragma once + +/* MIT License Copyright (c) 2024 - 2025 RenĂ© Amthor (tobid7) @@ -50,35 +52,34 @@ 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. */ -)"; -constexpr std::string_view ppa_text = - "#pragma once\n\n{0}\n" - "/** Generated with ppam */\n\n" - "#ifdef _WIN32 // Windows (MSVC Tested)\n" - "#ifdef {1}_BUILD_SHARED\n" - "#define {1}_API __declspec(dllexport)\n" - "#else\n" - "#define {1}_API __declspec(dllimport)\n" - "#endif\n" - "#elif defined(__APPLE__) // macOS (untested yet)\n" - "#ifdef {1}_BUILD_SHARED\n" - "#define {1}_API __attribute__((visibility(\"default\")))\n" - "#else\n" - "#define {1}_API\n" - "#endif\n" - "#elif defined(__linux__) // Linux (untested yet)\n" - "#ifdef {1}_BUILD_SHARED\n" - "#define {1}_API __attribute__((visibility(\"default\")))\n" - "#else\n" - "#define {1}_API\n" - "#endif\n" - "#elif defined(__3DS__) // 3ds Specific\n" - "// Only Static supported\n" - "#define {1}_API\n" - "#else\n" - "#define {1}_API\n" - "#endif\n"; +/** Generated with ppam */ + +#ifdef _WIN32 // Windows (MSVC Tested) +#ifdef {0}_BUILD_SHARED +#define {0}_API __declspec(dllexport) +#else +#define {0}_API __declspec(dllimport) +#endif +#elif defined(__APPLE__) // macOS (untested yet) +#ifdef {0}_BUILD_SHARED +#define {0}_API __attribute__((visibility("default"))) +#else +#define {0}_API +#endif +#elif defined(__linux__) // Linux (untested yet) +#ifdef {0}_BUILD_SHARED +#define {0}_API __attribute__((visibility("default"))) +#else +#define {0}_API +#endif +#elif defined(__3DS__) // 3ds Specific +// Only Static supported +#define {0}_API +#else +#define {0}_API +#endif +)"; /** * Tool to generate the `pd_p_api.hpp` (Palladium Platform Api) @@ -91,7 +92,7 @@ int main(int argc, char* argv[]) { return 0; } std::fstream off("pd_p_api.hpp", std::ios::out); - off << std::format(ppa_text, license_text, argv[1]); + off << std::format(ppa_text, argv[1]); off.close(); return 0; } \ No newline at end of file