From 669c1a55e20d62ea4a1f36b9b3ed4b018f265a39 Mon Sep 17 00:00:00 2001 From: Matthew Date: Mon, 8 Sep 2025 06:49:21 +1000 Subject: [PATCH] begin work on panel separators --- src/dlib | 2 +- src/editor/editor.d | 2 +- src/editor/ui.d | 163 ++++++++++++++++++++++++++++++++++++++++--- src/editor/widgets.d | 5 ++ 4 files changed, 160 insertions(+), 12 deletions(-) diff --git a/src/dlib b/src/dlib index 421f903..b2b6fef 160000 --- a/src/dlib +++ b/src/dlib @@ -1 +1 @@ -Subproject commit 421f903cffaa22c7d7f9115ae49daa45576adfa8 +Subproject commit b2b6fef26c0b0e15575ee431eea60235d4565c34 diff --git a/src/editor/editor.d b/src/editor/editor.d index 5aa8cd6..a352c34 100644 --- a/src/editor/editor.d +++ b/src/editor/editor.d @@ -180,7 +180,7 @@ Cycle(Editor* ed, Inputs* inputs) { Reset(&ed.temp_arena); - BeginBuild(); + BeginBuild(inputs); Panel("##panel_1", 1.0, 0.3, A2D.X, Vec4(0.2, 0.5, 0.8, 1.0)); { diff --git a/src/editor/ui.d b/src/editor/ui.d index 5ea5c67..f7896c3 100644 --- a/src/editor/ui.d +++ b/src/editor/ui.d @@ -1,4 +1,5 @@ import dlib.aliases; +import dlib.platform; import dlib.math; import dlib.util; import dlib.alloc; @@ -14,6 +15,9 @@ UIContext g_ui_ctx; const UIItem g_ui_nil_item; UIItem* g_UI_NIL; +const UIItemNode g_ui_nil_item_node; +UIItemNode* g_UI_NIL_NODE; + enum Axis2D { X, @@ -51,7 +55,11 @@ struct UIContext UIBuffer buffer; UIItem* root; - UIItem* top_parent; + UIItemNode* top_parent; + UIItemNode* prev_sibling; + u32 panel_level; + + UIItemStackList stack_free_list; FontAtlas atlas; Vec4[4] color; @@ -60,6 +68,18 @@ struct UIContext Axis2D layout_axis; } +struct UIItemStackList +{ + UIItemNode* first; + UIItemNode* last; +} + +struct UIItemNode +{ + UIItem* item; + UIItemNode* next; +} + struct UIItem { UIFlags flags; @@ -71,7 +91,7 @@ struct UIItem UIItem* last; // last child UIItem* parent; - UIItem* stack_next; + u32 level; // Build Parameters Axis2D layout_axis; @@ -129,6 +149,7 @@ void InitUICtx(Renderer* rd, FontAtlas atlas) { g_UI_NIL = cast(UIItem*)&g_ui_nil_item; + g_UI_NIL_NODE = cast(UIItemNode*)&g_ui_nil_item_node; Arena arena = CreateArena(MB(4)); @@ -141,7 +162,8 @@ InitUICtx(Renderer* rd, FontAtlas atlas) arena: CreateArena(MB(4)), atlas: atlas, root: g_UI_NIL, - top_parent: g_UI_NIL, + top_parent: g_UI_NIL_NODE, + prev_sibling: g_UI_NIL_NODE, buffer: { mapped_vtx: m_vtx, mapped_idx: m_idx, @@ -153,21 +175,138 @@ InitUICtx(Renderer* rd, FontAtlas atlas) g_ui_ctx = ctx; } +UIItemNode* +PopItemNode() +{ + UIContext* ctx = GetCtx(); + + UIItemNode* node; + if (!CheckNil(g_UI_NIL_NODE, ctx.stack_free_list.first)) + { + node = SLLPop(&ctx.stack_free_list, g_UI_NIL_NODE); + } + else + { + node = Alloc!(UIItemNode)(&ctx.arena); + } + + node.item = g_UI_NIL; + node.next = g_UI_NIL_NODE; + + return node; +} + +void +PushItemNode(UIItemNode* node) +{ + UIContext* ctx = GetCtx(); + SLLPushFront(&ctx.stack_free_list, node, g_UI_NIL_NODE); +} + +void +PushSiblingPanel(UIItem* panel) +{ + UIContext* ctx = GetCtx(); + UIItemNode* node = PopItemNode(); + + node.item = panel; + node.next = ctx.prev_sibling; + ctx.prev_sibling = node; +} + +UIItem* +PopSiblingPanel() +{ + UIContext* ctx = GetCtx(); + UIItem* panel = g_UI_NIL; + UIItemNode* node = ctx.prev_sibling; + + if (node != g_UI_NIL_NODE) + { + panel = node.item; + ctx.prev_sibling = node.next; + PushItemNode(node); + } + + return panel; +} + +void +PopSiblingPanels() +{ + UIItem* sibling = PeekSiblingPanel(); + while(!Nil(sibling)) + { + sibling = PopSiblingPanel(); + } +} + +UIItem* +PeekSiblingPanel() +{ + return g_ui_ctx.prev_sibling == g_UI_NIL_NODE ? g_UI_NIL : g_ui_ctx.prev_sibling.item; +} + +UIItem* +PrevSiblingPanel(UIItem* panel) +{ + UIContext* ctx = GetCtx(); + UIItem* result = g_UI_NIL; + UIItemNode* prev = ctx.prev_sibling; + for(;;) + { + if (panel == prev.item) + { + prev = prev.next; + } + + if (prev == g_UI_NIL_NODE) + { + break; + } + + if (prev.item.level < panel.level) + { + break; + } + + if (prev.item.level == panel.level) + { + result = prev.item; + break; + } + + prev = prev.next; + } + + return result; +} + UIItem* PopParent() { UIContext* ctx = GetCtx(); - UIItem* parent = ctx.top_parent; - ctx.top_parent = ctx.top_parent.stack_next; - return parent; + UIItemNode* node = ctx.top_parent; + UIItem* item = node.item; + + assert(!Nil(item)); + ctx.top_parent = node.next; + PushItemNode(node); + ctx.panel_level -= 1; + + return item; } void PushParent(UIItem* parent) { UIContext* ctx = GetCtx(); - parent.stack_next = ctx.top_parent; - ctx.top_parent = parent; + UIItemNode* node = PopItemNode(); + + node.item = parent; + node.next = ctx.top_parent; + ctx.top_parent = node; + ctx.panel_level += 1; } void @@ -200,6 +339,7 @@ BeginBuild(Inputs* inputs) ctx.inputs = inputs; ctx.buffer.count = 0; + ctx.panel_level = 0; ctx.root = Root(); PushParent(ctx.root); @@ -211,8 +351,10 @@ EndBuild() UIContext* ctx = GetCtx(); PopParent(); + PopSiblingPanels(); - assert(Nil(ctx.top_parent)); + assert(ctx.prev_sibling == g_UI_NIL_NODE); + assert(ctx.top_parent == g_UI_NIL_NODE); CalcFixedSizes(ctx.root); CalcPercentageSizes(ctx.root); @@ -312,8 +454,9 @@ BuildItem(u8[] id, UISize size_x, UISize size_y, UIFlags properties) item.size_info[A2D.Y] = size_y; item.color = ctx.color; item.layout_axis = ctx.layout_axis; + item.level = ctx.panel_level; - item.parent = ctx.top_parent; + item.parent = ctx.top_parent == g_UI_NIL_NODE ? g_UI_NIL : ctx.top_parent.item; if (!Nil(item.parent)) { DLLPush(item.parent, item, g_UI_NIL); diff --git a/src/editor/widgets.d b/src/editor/widgets.d index 79bc4b7..33e75bb 100644 --- a/src/editor/widgets.d +++ b/src/editor/widgets.d @@ -19,6 +19,11 @@ Panel(string id, f32 x_pct, f32 y_pct, Axis2D layout_axis, Vec4 color) SetLayoutAxis(layout_axis); UIItem* item = BuildItem(id, UISize(ST.Percentage, x_pct), UISize(ST.Percentage, y_pct), UIF.DrawBackground); + UIItem* prev_panel = PrevSiblingPanel(item); + + Logf("%s %s", id, !Nil(prev_panel)); + + PushSiblingPanel(item); PushParent(item); return item;