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
{
None,
DrawBackground,
DragX,
DragY,
None = 0x00,
DrawBackground = 0x01,
Clickable = 0x02,
Draggable = 0x04,
}
alias UIF = UIFlags;
enum UISignal
{
None = 0x00,
Clicked = 0x01,
Dragged = 0x02,
}
alias UIS = UISignal;
enum SizeType
{
Pixels,
@ -58,6 +67,7 @@ struct UIContext
UIItemNode* top_parent;
UIItemNode* prev_sibling;
u32 panel_level;
UIItem* drag_item;
UIItemStackList stack_free_list;
@ -66,6 +76,7 @@ struct UIContext
Vec4[4] border_color;
Vec4 text_color;
Axis2D layout_axis;
Vec2 adjustment;
}
struct UIItemStackList
@ -84,6 +95,7 @@ struct UIItem
{
UIFlags flags;
UIKey key;
UISignal signal;
UIItem* next;
UIItem* prev;
@ -96,6 +108,7 @@ struct UIItem
// Build Parameters
Axis2D layout_axis;
UISize[2] size_info;
Vec2 adjustment;
// Calculated Parameters
Vec2 size;
@ -113,9 +126,9 @@ struct UIBuffer
{
MappedBuffer!(Vertex) mapped_vtx;
MappedBuffer!(u32) mapped_idx;
Vertex[] vtx;
u32[] idx;
u32 count;
Vertex[] vtx;
u32[] idx;
u32 count;
}
union Rect
@ -164,6 +177,7 @@ InitUICtx(Renderer* rd, FontAtlas atlas)
root: g_UI_NIL,
top_parent: g_UI_NIL_NODE,
prev_sibling: g_UI_NIL_NODE,
drag_item: g_UI_NIL,
buffer: {
mapped_vtx: m_vtx,
mapped_idx: m_idx,
@ -315,6 +329,12 @@ PushParent(UIItem* parent)
ctx.panel_level += 1;
}
void
SetAdjustment(Vec2 adj)
{
g_ui_ctx.adjustment = adj;
}
void
SetColor(Vec4 col)
{
@ -383,7 +403,7 @@ CalcFixedSizes(UIItem* item)
{
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)
{
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*
BuildItem(string id, 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)
void
BuildItem(UIItem* item, UISize size_x, UISize size_y, UIFlags properties)
{
UIContext* ctx = GetCtx();
UIKey key = MakeKey(id);
UIItem* item = Get(key);
item.first = item.last = item.next = item.prev = g_UI_NIL;
item.key = key;
item.flags = properties;
item.size_info[A2D.X] = size_x;
item.size_info[A2D.Y] = size_y;
item.color = ctx.color;
item.layout_axis = ctx.layout_axis;
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;
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);
}
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*
@ -534,13 +570,23 @@ MakeKey(u8[] id)
}
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];
if (!result.ok)
{
result.value = Alloc!(UIItem)(&g_ui_ctx.arena);
Push(&g_ui_ctx.items, key.hash, result.value);
result.value.key = key;
}
return result.value;
@ -641,66 +687,27 @@ Nil(UIItem* item)
return item == null || item == g_UI_NIL;
}
/*
// Setter function in case I need to change to using a mutex
pragma(inline) void
SetProp(alias P, T)(T value)
bool
Clicked(UIItem* item, DNode!(InputEvent)* n)
{
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;
else static assert(false, "Unknown property for type Axis2D");
result = true;
}
else static if (is(T: Vec2))
{
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");
return result;
}
*/
unittest
{

View File

@ -8,7 +8,8 @@ Root()
{
Vec2 d = RootSize();
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;
}
@ -16,32 +17,43 @@ Root()
UIItem*
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* parent = PeekParent();
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;
if (parent.layout_axis == A2D.X)
{
sep_x = 0.005;
//x_pct -= 0.005;
sep_x = 5.0;
adj_x = -5.0;
}
else
{
sep_y = 0.005;
//y_pct -= 0.005;
sep_y = 5.0;
adj_y = -5.0;
}
u8[128] buf;
u8[128] buf = 0;
(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);
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);
@ -51,14 +63,15 @@ Panel(string id, f32 x_pct, f32 y_pct, Axis2D layout_axis, Vec4 color)
return item;
}
UIItem*
Separator(u8[] id, f32 x_pct, f32 y_pct)
void
Separator(UIItem* item, f32 x_size, f32 y_size, Axis2D axis)
{
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