start work on input handling

This commit is contained in:
Matthew 2025-09-09 08:02:41 +10:00
parent 5ee1ae6d17
commit 55247980c1
2 changed files with 111 additions and 91 deletions

View File

@ -29,14 +29,23 @@ alias A2D = Axis2D;
enum UIFlags enum UIFlags
{ {
None, None = 0x00,
DrawBackground, DrawBackground = 0x01,
DragX, Clickable = 0x02,
DragY, Draggable = 0x04,
} }
alias UIF = UIFlags; alias UIF = UIFlags;
enum UISignal
{
None = 0x00,
Clicked = 0x01,
Dragged = 0x02,
}
alias UIS = UISignal;
enum SizeType enum SizeType
{ {
Pixels, Pixels,
@ -58,6 +67,7 @@ struct UIContext
UIItemNode* top_parent; UIItemNode* top_parent;
UIItemNode* prev_sibling; UIItemNode* prev_sibling;
u32 panel_level; u32 panel_level;
UIItem* drag_item;
UIItemStackList stack_free_list; UIItemStackList stack_free_list;
@ -66,6 +76,7 @@ struct UIContext
Vec4[4] border_color; Vec4[4] border_color;
Vec4 text_color; Vec4 text_color;
Axis2D layout_axis; Axis2D layout_axis;
Vec2 adjustment;
} }
struct UIItemStackList struct UIItemStackList
@ -84,6 +95,7 @@ struct UIItem
{ {
UIFlags flags; UIFlags flags;
UIKey key; UIKey key;
UISignal signal;
UIItem* next; UIItem* next;
UIItem* prev; UIItem* prev;
@ -96,6 +108,7 @@ struct UIItem
// Build Parameters // Build Parameters
Axis2D layout_axis; Axis2D layout_axis;
UISize[2] size_info; UISize[2] size_info;
Vec2 adjustment;
// Calculated Parameters // Calculated Parameters
Vec2 size; Vec2 size;
@ -164,6 +177,7 @@ InitUICtx(Renderer* rd, FontAtlas atlas)
root: g_UI_NIL, root: g_UI_NIL,
top_parent: g_UI_NIL_NODE, top_parent: g_UI_NIL_NODE,
prev_sibling: g_UI_NIL_NODE, prev_sibling: g_UI_NIL_NODE,
drag_item: g_UI_NIL,
buffer: { buffer: {
mapped_vtx: m_vtx, mapped_vtx: m_vtx,
mapped_idx: m_idx, mapped_idx: m_idx,
@ -315,6 +329,12 @@ PushParent(UIItem* parent)
ctx.panel_level += 1; ctx.panel_level += 1;
} }
void
SetAdjustment(Vec2 adj)
{
g_ui_ctx.adjustment = adj;
}
void void
SetColor(Vec4 col) SetColor(Vec4 col)
{ {
@ -383,7 +403,7 @@ CalcFixedSizes(UIItem* item)
{ {
if (item.size_info[axis].type == ST.Pixels) if (item.size_info[axis].type == ST.Pixels)
{ {
item.size.v[axis] = item.size_info[axis].value; item.size.v[axis] = item.size_info[axis].value + item.adjustment.v[axis];
} }
} }
@ -401,7 +421,7 @@ CalcPercentageSizes(UIItem* item)
{ {
if (item.size_info[axis].type == ST.Percentage) if (item.size_info[axis].type == ST.Percentage)
{ {
item.size.v[axis] = item.parent.size.v[axis] * item.size_info[axis].value; item.size.v[axis] = (item.parent.size.v[axis]*item.size_info[axis].value) + item.adjustment.v[axis];
} }
} }
@ -438,29 +458,20 @@ DrawUI(UIContext* ctx, UIItem* item)
} }
} }
UIItem* void
BuildItem(string id, UISize size_x, UISize size_y, UIFlags properties) BuildItem(UIItem* item, UISize size_x, UISize size_y, UIFlags properties)
{
u8[] u8_id = CastStr!(u8)(id);
return BuildItem(u8_id, size_x, size_y, properties);
}
UIItem*
BuildItem(u8[] id, UISize size_x, UISize size_y, UIFlags properties)
{ {
UIContext* ctx = GetCtx(); UIContext* ctx = GetCtx();
UIKey key = MakeKey(id);
UIItem* item = Get(key);
item.first = item.last = item.next = item.prev = g_UI_NIL; item.first = item.last = item.next = item.prev = g_UI_NIL;
item.key = key;
item.flags = properties; item.flags = properties;
item.size_info[A2D.X] = size_x; item.size_info[A2D.X] = size_x;
item.size_info[A2D.Y] = size_y; item.size_info[A2D.Y] = size_y;
item.color = ctx.color; item.color = ctx.color;
item.layout_axis = ctx.layout_axis; item.layout_axis = ctx.layout_axis;
item.level = ctx.panel_level; item.level = ctx.panel_level;
item.adjustment = ctx.adjustment;
item.parent = ctx.top_parent == g_UI_NIL_NODE ? g_UI_NIL : ctx.top_parent.item; item.parent = ctx.top_parent == g_UI_NIL_NODE ? g_UI_NIL : ctx.top_parent.item;
if (!Nil(item.parent)) if (!Nil(item.parent))
@ -468,7 +479,32 @@ BuildItem(u8[] id, UISize size_x, UISize size_y, UIFlags properties)
DLLPush(item.parent, item, g_UI_NIL); DLLPush(item.parent, item, g_UI_NIL);
} }
return item; // Reset any once off values here
ctx.adjustment = Vec2(0.0);
}
void
Signal(UIItem* item)
{
UIContext* ctx = GetCtx();
item.signal = UIS.None;
for(DNode!(InputEvent)* n = ctx.inputs.list.first; !CheckNil(null, n); n = n.next)
{
if (item.flags & UIF.Clickable && Clicked(item, n))
{
Logf("Clicked");
DLLRemove(&ctx.inputs.list, n, null);
}
if (item.flags & UIF.Draggable && Clicked(item, n))
{
Logf("Dragged");
DLLRemove(&ctx.inputs.list, n, null);
}
}
} }
UIContext* UIContext*
@ -534,13 +570,23 @@ MakeKey(u8[] id)
} }
UIItem* UIItem*
Get(UIKey key) Get(string id)
{ {
u8[] u8_id = CastStr!(u8)(id);
return Get(u8_id);
}
UIItem*
Get(u8[] id)
{
UIKey key = MakeKey(id);
Result!(UIItem*) result = g_ui_ctx.items[key.hash]; Result!(UIItem*) result = g_ui_ctx.items[key.hash];
if (!result.ok) if (!result.ok)
{ {
result.value = Alloc!(UIItem)(&g_ui_ctx.arena); result.value = Alloc!(UIItem)(&g_ui_ctx.arena);
Push(&g_ui_ctx.items, key.hash, result.value); Push(&g_ui_ctx.items, key.hash, result.value);
result.value.key = key;
} }
return result.value; return result.value;
@ -641,66 +687,27 @@ Nil(UIItem* item)
return item == null || item == g_UI_NIL; return item == null || item == g_UI_NIL;
} }
/* bool
// Setter function in case I need to change to using a mutex Clicked(UIItem* item, DNode!(InputEvent)* n)
pragma(inline) void
SetProp(alias P, T)(T value)
{ {
static if (is(T: Axis2D)) bool result = false;
InputEvent* ev = &n.value;
if (
ev.key == Input.LeftClick &&
ev.x >= item.rect.x0 &&
ev.x <= item.rect.x1 &&
ev.y >= item.rect.y0 &&
ev.y <= item.rect.y1 &&
ev.pressed
)
{ {
static if (P == CtxP.LayoutAxis) g_ui_ctx.layout_axis = value; result = true;
else static assert(false, "Unknown property for type Axis2D");
} }
else static if (is(T: Vec2))
{ return result;
static if (P == CtxP.Position) g_ui_ctx.position = value;
else static assert(false, "Unknown property for type Vec2");
} }
else static if (is(T: Vec4))
{
static if (P == CtxP.BGColor) g_ui_ctx.bg_cols = [value, value, value, value];
else static if (P == CtxP.BorderColor) g_ui_ctx.border_cols = [value, value, value, value];
else static assert(false, "Unknown Property for type Vec4");
}
else static if (is(T: Vec4[4]))
{
static if (P == CtxP.BGColor) g_ui_ctx.bg_cols = value;
else static if (P == CtxP.BorderColor) g_ui_ctx.border_cols = value;
else static assert(false, "Unknown Property for type Vec4[4]");
}
else static if (is(T: SizeKind) && P == CtxP.SizeKind)
{
g_ui_ctx.size_kind = value;
}
else static if (is(T: UISize))
{
static if (P == CtxP.AxisX) g_ui_ctx.size_axes[A2D.X] = value;
else static if (P == CtxP.AxisY) g_ui_ctx.size_axes[A2D.Y] = value;
else static assert(false, "Unknown Property for type UISize");
}
else static if (is(T: FontAtlas))
{
static if (P == CtxP.FontAtlas) g_ui_ctx.atlas = value;
else static assert(false, "Unknown Property for type FontAtlas");
}
else static if (is(T: Rect))
{
static if (P == CtxP.Padding) g_ui_ctx.padding = value;
else static assert(false, "Unknown property for type Rect");
}
else static if (is(T: f32))
{
static if (P == CtxP.TextScale) g_ui_ctx.text_scale = value;
else static assert(false, "Unknown property for type f32");
}
else static if (is(T: u32))
{
static if (P == CtxP.TabWidth) g_ui_ctx.tab_width = value;
else static assert(false, "Unknown property for type u32");
}
else static assert(false, "Unknown Type");
}
*/
unittest unittest
{ {

View File

@ -8,7 +8,8 @@ Root()
{ {
Vec2 d = RootSize(); Vec2 d = RootSize();
SetLayoutAxis(A2D.Y); SetLayoutAxis(A2D.Y);
UIItem* root = BuildItem("##root_item", UISize(ST.Pixels, d.x), UISize(ST.Pixels, d.y), UIF.DrawBackground); UIItem* root = Get("##root_item");
BuildItem(root, UISize(ST.Pixels, d.x), UISize(ST.Pixels, d.y), UIF.DrawBackground);
return root; return root;
} }
@ -16,32 +17,43 @@ Root()
UIItem* UIItem*
Panel(string id, f32 x_pct, f32 y_pct, Axis2D layout_axis, Vec4 color) Panel(string id, f32 x_pct, f32 y_pct, Axis2D layout_axis, Vec4 color)
{ {
UIItem* item = Get(id);
UIItem* separator = g_UI_NIL;
UIItem* prev_panel = PeekSiblingPanel(); UIItem* prev_panel = PeekSiblingPanel();
UIItem* parent = PeekParent(); UIItem* parent = PeekParent();
Signal(item);
f32 adj_x = 0.0, adj_y = 0.0;
if (!Nil(prev_panel) && parent != prev_panel) 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;
if (parent.layout_axis == A2D.X) if (parent.layout_axis == A2D.X)
{ {
sep_x = 0.005; sep_x = 5.0;
//x_pct -= 0.005; adj_x = -5.0;
} }
else else
{ {
sep_y = 0.005; sep_y = 5.0;
//y_pct -= 0.005; adj_y = -5.0;
} }
u8[128] buf; u8[128] buf = 0;
(cast(char[])buf).sformat("sep_%s", id); (cast(char[])buf).sformat("sep_%s", id);
Separator(buf, sep_x, sep_y); separator = Get(buf);
Separator(separator, sep_x, sep_y, parent.layout_axis);
Signal(separator);
} }
SetColor(color); SetColor(color);
SetLayoutAxis(layout_axis); SetLayoutAxis(layout_axis);
UIItem* item = BuildItem(id, UISize(ST.Percentage, x_pct), UISize(ST.Percentage, y_pct), UIF.DrawBackground);
BuildItem(item, UISize(ST.Percentage, x_pct), UISize(ST.Percentage, y_pct), UIF.DrawBackground);
UIItem* sibling = PrevSiblingPanel(item); UIItem* sibling = PrevSiblingPanel(item);
@ -51,14 +63,15 @@ Panel(string id, f32 x_pct, f32 y_pct, Axis2D layout_axis, Vec4 color)
return item; return item;
} }
UIItem* void
Separator(u8[] id, f32 x_pct, f32 y_pct) Separator(UIItem* item, f32 x_size, f32 y_size, Axis2D axis)
{ {
SetColor(Vec4(0.0, 0.0, 0.0, 1.0)); SetColor(Vec4(0.0, 0.0, 0.0, 1.0));
UIItem* item = BuildItem(id, UISize(ST.Percentage, x_pct), UISize(ST.Percentage, y_pct), UIF.DrawBackground); SizeType x_t = axis == A2D.X ? ST.Pixels : ST.Percentage;
SizeType y_t = axis == A2D.Y ? ST.Pixels : ST.Percentage;
return item; BuildItem(item, UISize(x_t, x_size), UISize(y_t, y_size), UIF.DrawBackground|UIF.Draggable);
} }
void void