input handling added, panels now resizeable, panels now have persistent state

This commit is contained in:
Matthew 2025-09-10 06:18:53 +10:00
parent 55247980c1
commit de90479aa7
4 changed files with 257 additions and 54 deletions

@ -1 +1 @@
Subproject commit b2b6fef26c0b0e15575ee431eea60235d4565c34
Subproject commit f30edc3bbe9fdfda5eb429a214fdf050a0012af0

View File

@ -182,40 +182,107 @@ Cycle(Editor* ed, Inputs* inputs)
BeginBuild(inputs);
Panel("##panel_1", 1.0, 0.3, A2D.X, Vec4(0.2, 0.5, 0.8, 1.0));
{
Panel("##sub_panel_1", 0.125, 1.0, A2D.X, Vec4(0.2, 0.4, 0.5, 1.0));
EndPanel();
Panel("##sub_panel_2", 0.675, 1.0, A2D.X, Vec4(0.9, 0.6, 0.5, 1.0));
EndPanel();
Panel("##sub_panel_3", 0.2, 1.0, A2D.X, Vec4(1.0, 0.4, 0.5, 1.0));
EndPanel();
}
EndPanel();
Panel("##panel_2", 1.0, 0.3, A2D.X, Vec4(0.5, 0.2, 0.45, 1.0));
{
}
EndPanel();
Panel("##panel_3", 1.0, 0.4, A2D.X, Vec4(0.3, 0.7, 0.6, 1.0));
{
Panel("##sub_panel_6", 0.25, 1.0, A2D.Y, Vec4(0.33, 0.4, 0.8, 1.0));
static UIPanel[11] panels = [
{
Panel("##sub_sub_panel_1", 1.0, 0.4, A2D.X, Vec4(1.0, 0.0, 0.0, 1.0));
id: CastStr!(u8)("##panel_1"),
pct: 0.3,
axis: A2D.X,
color: Vec4(0.2, 0.5, 0.8, 1.0),
},
{
id: CastStr!(u8)("##sub_panel_1"),
pct: 0.125,
axis: A2D.X,
color: Vec4(0.2, 0.4, 0.5, 1.0),
},
{
id: CastStr!(u8)("##sub_panel_2"),
pct: 0.675,
axis: A2D.X,
color: Vec4(0.9, 0.6, 0.5, 1.0),
},
{
id: CastStr!(u8)("##sub_panel_3"),
pct: 0.2,
axis: A2D.X,
color: Vec4(1.0, 0.4, 0.5, 1.0),
},
{
id: CastStr!(u8)("##panel_2"),
pct: 0.3,
axis: A2D.X,
color: Vec4(0.5, 0.2, 0.45, 1.0),
},
{
id: CastStr!(u8)("##panel_3"),
pct: 0.4,
axis: A2D.X,
color: Vec4(0.3, 0.7, 0.6, 1.0),
},
{
id: CastStr!(u8)("##sub_panel_4"),
pct: 0.25,
axis: A2D.Y,
color: Vec4(0.33, 0.4, 0.8, 1.0),
},
{
id: CastStr!(u8)("##sub_sub_panel_1"),
pct: 0.4,
axis: A2D.X,
color: Vec4(1.0, 0.0, 0.0, 1.0),
},
{
id: CastStr!(u8)("##sub_sub_panel_2"),
pct: 0.6,
axis: A2D.X,
color: Vec4(1.0, 1.0, 0.0, 1.0),
},
{
id: CastStr!(u8)("##sub_panel_5"),
pct: 0.55,
axis: A2D.X,
color: Vec4(0.9, 0.2, 0.3, 1.0),
},
{
id: CastStr!(u8)("##sub_panel_6"),
pct: 0.2,
axis: A2D.X,
color: Vec4(0.2, 0.76, 0.5, 1.0),
},
];
Panel(&panels[0]);
{
Panel(&panels[1]);
EndPanel();
Panel(&panels[2]);
EndPanel();
Panel(&panels[3]);
EndPanel();
}
EndPanel();
Panel(&panels[4]);
EndPanel();
Panel(&panels[5]);
{
Panel(&panels[6]);
{
Panel(&panels[7]);
EndPanel();
Panel("##sub_sub_panel_2", 1.0, 0.6, A2D.X, Vec4(1.0, 1.0, 0.0, 1.0));
Panel(&panels[8]);
EndPanel();
}
EndPanel();
Panel("##sub_panel_7", 0.55, 1.0, A2D.X, Vec4(0.9, 0.2, 0.3, 1.0));
Panel(&panels[9]);
EndPanel();
Panel("##sub_panel_8", 0.2, 1.0, A2D.X, Vec4(0.2, 0.76, 0.5, 1.0));
Panel(&panels[10]);
EndPanel();
}
EndPanel();

View File

@ -10,7 +10,7 @@ import std.stdio;
import editor;
UIContext g_ui_ctx;
UICtx g_ui_ctx;
const UIItem g_ui_nil_item;
UIItem* g_UI_NIL;
@ -54,7 +54,7 @@ enum SizeType
alias ST = SizeType;
struct UIContext
struct UICtx
{
HashTable!(UIHash, UIItem*) items;
Arena arena;
@ -104,6 +104,7 @@ struct UIItem
UIItem* parent;
u32 level;
Vec2 dragged;
// Build Parameters
Axis2D layout_axis;
@ -169,7 +170,7 @@ InitUICtx(Renderer* rd, FontAtlas atlas)
MappedBuffer!(Vertex) m_vtx = CreateMappedBuffer!(Vertex)(rd, BT.Vertex, 5000);
MappedBuffer!(u32) m_idx = CreateMappedBuffer!(u32)(rd, BT.Index, 15000);
UIContext ctx = {
UICtx ctx = {
rd: rd,
items: CreateHashTable!(UIHash, UIItem*)(12),
arena: CreateArena(MB(4)),
@ -187,12 +188,14 @@ InitUICtx(Renderer* rd, FontAtlas atlas)
};
g_ui_ctx = ctx;
InitWidgets();
}
UIItemNode*
PopItemNode()
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
UIItemNode* node;
if (!CheckNil(g_UI_NIL_NODE, ctx.stack_free_list.first))
@ -213,14 +216,14 @@ PopItemNode()
void
PushItemNode(UIItemNode* node)
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
SLLPushFront(&ctx.stack_free_list, node, g_UI_NIL_NODE);
}
void
PushSiblingPanel(UIItem* panel)
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
UIItemNode* node = PopItemNode();
node.item = panel;
@ -231,7 +234,7 @@ PushSiblingPanel(UIItem* panel)
UIItem*
PopSiblingPanel()
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
UIItem* panel = g_UI_NIL;
UIItemNode* node = ctx.prev_sibling;
@ -264,7 +267,7 @@ PeekSiblingPanel()
UIItem*
PrevSiblingPanel(UIItem* panel)
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
UIItem* result = g_UI_NIL;
UIItemNode* prev = ctx.prev_sibling;
for(;;)
@ -305,7 +308,7 @@ PeekParent()
UIItem*
PopParent()
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
UIItemNode* node = ctx.top_parent;
UIItem* item = node.item;
@ -320,7 +323,7 @@ PopParent()
void
PushParent(UIItem* parent)
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
UIItemNode* node = PopItemNode();
node.item = parent;
@ -344,7 +347,7 @@ SetColor(Vec4 col)
void
SetColor(Vec4 col0, Vec4 col1, Vec4 col2, Vec4 col3)
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
ctx.color[0] = col0;
ctx.color[1] = col1;
ctx.color[2] = col2;
@ -354,14 +357,14 @@ SetColor(Vec4 col0, Vec4 col1, Vec4 col2, Vec4 col3)
void
SetLayoutAxis(Axis2D axis)
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
ctx.layout_axis = axis;
}
void
BeginBuild(Inputs* inputs)
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
ctx.inputs = inputs;
ctx.buffer.count = 0;
@ -374,7 +377,7 @@ BeginBuild(Inputs* inputs)
void
EndBuild()
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
PopParent();
PopSiblingPanels();
@ -390,10 +393,29 @@ EndBuild()
}
DrawUI(ctx, ctx.root);
static bool first = false;
if (!first)
{
DrawNodes(ctx.root);
first = true;
}
BindBuffers(g_ui_ctx.rd, &g_ui_ctx.buffer.mapped_idx, &g_ui_ctx.buffer.mapped_vtx);
DrawIndexed(g_ui_ctx.rd, 6, g_ui_ctx.buffer.count, 0);
}
void
DrawNodes(UIItem* item)
{
if (!Nil(item))
{
Logf("x0 %s x1 %s y0 %s y1 %s", item.rect.x0, item.rect.x1, item.rect.y0, item.rect.y1);
DrawNodes(item.first);
DrawNodes(item.next);
}
}
void
CalcFixedSizes(UIItem* item)
{
@ -447,7 +469,7 @@ CalcPositions(alias axis)(UIItem* item, f32 pos = 0.0)
}
void
DrawUI(UIContext* ctx, UIItem* item)
DrawUI(UICtx* ctx, UIItem* item)
{
if (!Nil(item))
{
@ -461,7 +483,7 @@ DrawUI(UIContext* ctx, UIItem* item)
void
BuildItem(UIItem* item, UISize size_x, UISize size_y, UIFlags properties)
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
item.first = item.last = item.next = item.prev = g_UI_NIL;
@ -486,28 +508,53 @@ BuildItem(UIItem* item, UISize size_x, UISize size_y, UIFlags properties)
void
Signal(UIItem* item)
{
UIContext* ctx = GetCtx();
UICtx* ctx = GetCtx();
item.signal = UIS.None;
item.dragged = 0.0;
for(DNode!(InputEvent)* n = ctx.inputs.list.first; !CheckNil(null, n); n = n.next)
{
bool taken = false;
if (item.flags & UIF.Clickable && Clicked(item, n))
{
Logf("Clicked");
DLLRemove(&ctx.inputs.list, n, null);
item.signal |= UIS.Clicked;
taken = true;
}
if (item.flags & UIF.Draggable && Clicked(item, n))
if (item.flags & UIF.Draggable && Clicked(item, n) && Nil(ctx.drag_item))
{
Logf("Dragged");
item.signal |= UIS.Dragged;
ctx.drag_item = item;
taken = true;
}
if (ctx.drag_item == item && n.value.key == Input.LeftClick && !n.value.pressed)
{
Logf("Released");
ctx.drag_item = g_UI_NIL;
taken = true;
}
if (ctx.drag_item == item && n.value.key == Input.MouseMotion)
{
item.signal |= UIS.Dragged;
item.dragged.x += cast(f32)n.value.rel_x;
item.dragged.y += cast(f32)n.value.rel_y;
taken = true;
}
if (taken)
{
DLLRemove(&ctx.inputs.list, n, null);
}
}
}
UIContext*
UICtx*
GetCtx()
{
return &g_ui_ctx;
@ -653,7 +700,7 @@ DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
}
pragma(inline) void
DrawRect(UIContext* ctx, UIItem* item)
DrawRect(UICtx* ctx, UIItem* item)
{
// Y reversed
Vertex* v = ctx.buffer.vtx.ptr + ctx.buffer.count;

View File

@ -3,6 +3,58 @@ import dlib;
import ui;
import std.format : sformat;
const UIPanel g_ui_nil_panel;
UIPanel* g_UI_NIL_PANEL;
UIPanel g_root_panel;
WidgetCtx g_widget_ctx;
struct WidgetCtx
{
UIPanel* parent;
}
struct UIPanel
{
u8[] id;
UIPanel* parent;
UIPanel* next;
UIPanel* prev;
UIPanel* first;
UIPanel* last;
UIPanel* list_next;
Axis2D axis;
f32 pct;
Vec4 color;
}
void
PushPanel(UIPanel* parent)
{
parent.list_next = g_widget_ctx.parent;
g_widget_ctx.parent = parent;
}
UIPanel*
PopPanel()
{
UIPanel* parent = g_widget_ctx.parent;
g_widget_ctx.parent = parent.list_next;
parent.list_next = g_UI_NIL_PANEL;
return parent;
}
void
InitWidgets()
{
g_UI_NIL_PANEL = cast(UIPanel*)&g_ui_nil_panel;
g_widget_ctx.parent = g_UI_NIL_PANEL;
}
UIItem*
Root()
{
@ -11,47 +63,81 @@ Root()
UIItem* root = Get("##root_item");
BuildItem(root, UISize(ST.Pixels, d.x), UISize(ST.Pixels, d.y), UIF.DrawBackground);
g_root_panel.pct = 1.0;
g_root_panel.axis = A2D.Y;
g_root_panel.color = Vec4(Vec3(0.0), 1.0);
g_root_panel.list_next = g_root_panel.parent = g_root_panel.next = g_root_panel.prev = g_root_panel.first = g_root_panel.last = g_UI_NIL_PANEL;
g_widget_ctx.parent = &g_root_panel;
return root;
}
UIItem*
Panel(string id, f32 x_pct, f32 y_pct, Axis2D layout_axis, Vec4 color)
Panel(UIPanel* panel)
{
UIItem* item = Get(id);
UIItem* item = Get(panel.id);
UIItem* separator = g_UI_NIL;
UIItem* prev_panel = PeekSiblingPanel();
UIItem* parent = PeekParent();
UIPanel* parent_pn = g_widget_ctx.parent;
DLLPush(parent_pn, panel, g_UI_NIL_PANEL);
f32 x_pct = 1.0, y_pct = 1.0;
if (parent_pn != g_UI_NIL_PANEL)
{
x_pct = parent_pn.axis == A2D.X ? panel.pct : 1.0;
y_pct = parent_pn.axis == A2D.Y ? panel.pct : 1.0;
}
Signal(item);
f32 adj_x = 0.0, adj_y = 0.0;
if (!Nil(prev_panel) && parent != prev_panel)
{
f32 sep_y = 1.0, sep_x = 1.0;
f32 sep_y = 1.0, sep_x = 1.0, parent_start = 0.0, parent_end = 0.0;
if (parent.layout_axis == A2D.X)
{
sep_x = 5.0;
adj_x = -5.0;
parent_start = parent.rect.vec0.x;
parent_end = parent.rect.vec1.x;
}
else
{
sep_y = 5.0;
adj_y = -5.0;
parent_start = parent.rect.vec0.y;
parent_end = parent.rect.vec1.y;
}
u8[128] buf = 0;
(cast(char[])buf).sformat("sep_%s", id);
(cast(char[])buf).sformat("sep_%s", cast(char[])panel.id);
separator = Get(buf);
Separator(separator, sep_x, sep_y, parent.layout_axis);
Signal(separator);
f32 pos = separator.dragged.v[parent.layout_axis];
if (separator.signal & UIS.Dragged && pos != 0.0)
{
f32 pct = Remap(pos, 0.0, parent_start-parent_end, 0.0, 1.0);
panel.pct -= pct;
panel.prev.pct += pct;
Logf("%f", pct);
Logf("%s %f %s %f", cast(char[])panel.id, panel.pct, cast(char[])panel.prev.id, panel.prev.pct);
}
}
SetColor(color);
SetLayoutAxis(layout_axis);
SetColor(panel.color);
SetLayoutAxis(panel.axis);
BuildItem(item, UISize(ST.Percentage, x_pct), UISize(ST.Percentage, y_pct), UIF.DrawBackground);
@ -60,6 +146,8 @@ Panel(string id, f32 x_pct, f32 y_pct, Axis2D layout_axis, Vec4 color)
PushSiblingPanel(item);
PushParent(item);
PushPanel(panel);
return item;
}
@ -78,4 +166,5 @@ void
EndPanel()
{
PopParent();
PopPanel();
}