From ec19c260714fcd0c0733e39f37053b2006521c29 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sat, 6 Dec 2025 21:22:04 +1100 Subject: [PATCH] template automation for ui parameters --- src/editor/ui.d | 177 ++++++++++++++++++++++++++++-------------------- 1 file changed, 104 insertions(+), 73 deletions(-) diff --git a/src/editor/ui.d b/src/editor/ui.d index b26c774..061dd20 100644 --- a/src/editor/ui.d +++ b/src/editor/ui.d @@ -58,7 +58,7 @@ __gshared UIPanel* g_UI_NIL_PANEL; __gshared const UIItem g_ui_nil_item; __gshared UIItem* g_UI_NIL; -alias g_item_parent_default = g_UI_NIL; +alias g_parent_default = g_UI_NIL; __gshared const Stack!f32 g_nil_f32_stack; __gshared Stack!f32* g_NIL_F32_STACK; @@ -123,6 +123,47 @@ enum SizeType alias ST = SizeType; + +mixin template UICtxParameter(T, string name) +{ + static string + CtxParameterGen(string type, string name)() + { + return type ~ " " ~ name ~ ";"; + } + + mixin(CtxParameterGen!((StackTop!(T)).stringof, name)()); + mixin(CtxParameterGen!((Stack!(T)*).stringof, name~"_top")()); +} + +template CtxMemberInfo(int i) +{ + import std.string : endsWith; + import std.traits : isInstanceOf, isPointer; + + struct MemberInfo + { + string id; + bool is_stack, is_top, is_stack_top; + } + + enum string id = __traits(identifier, UICtx.tupleof[i]); + enum bool is_ptr = isPointer!(typeof(UICtx.tupleof[i])); + enum bool is_top = endsWith(id, "_top"); + enum bool is_stack_top = isInstanceOf!(StackTop, typeof(UICtx.tupleof[i])); + + static if(is_ptr) + { + enum bool is_stack = isInstanceOf!(Stack, typeof(*UICtx.tupleof[i])); + } + else + { + enum bool is_stack = false; + } + + enum MemberInfo CtxMemberInfo = MemberInfo(id: id, is_stack: is_ptr && is_stack, is_top: is_top, is_stack_top: is_stack_top); +} + struct UICtx { HashTable!(UIHash, UIItem*) items; @@ -154,30 +195,19 @@ struct UICtx f32 text_size; UIItem* drag_item; - UIPanel* parent; + UIPanel* parent_panel; UIPanel* focused_panel; - StackTop!(UIItem*) item_parent; - StackTop!(f32) corner_radius; - StackTop!(f32) border_thickness; - StackTop!(f32) edge_softness; - StackTop!(Vec4[4]) bg_col; - StackTop!(Vec4[4]) bg_hl_col; - StackTop!(Vec4[4]) border_col; - StackTop!(Vec4[4]) border_hl_col; - StackTop!(Vec4) text_col; - StackTop!(Vec4) text_hl_col; - - Stack!(UIItem*)* item_parent_top; - Stack!(f32)* corner_radius_top; - Stack!(f32)* border_thickness_top; - Stack!(f32)* edge_softness_top; - Stack!(Vec4[4])* bg_col_top; - Stack!(Vec4[4])* bg_hl_col_top; - Stack!(Vec4[4])* border_col_top; - Stack!(Vec4[4])* border_hl_col_top; - Stack!(Vec4)* text_col_top; - Stack!(Vec4)* text_hl_col_top; + mixin UICtxParameter!(UIItem*, "parent"); + mixin UICtxParameter!(f32, "corner_radius"); + mixin UICtxParameter!(f32, "border_thickness"); + mixin UICtxParameter!(f32, "edge_softness"); + mixin UICtxParameter!(Vec4[4], "bg_col"); + mixin UICtxParameter!(Vec4[4], "bg_hl_col"); + mixin UICtxParameter!(Vec4[4], "border_col"); + mixin UICtxParameter!(Vec4[4], "border_hl_col"); + mixin UICtxParameter!(Vec4, "text_col"); + mixin UICtxParameter!(Vec4, "text_hl_col"); debug bool dbg; } @@ -195,24 +225,39 @@ struct StackTop(T) bool auto_pop; } +mixin template UIItemParameters() +{ + static string + UIItemParameterGen() + { + string fields = ""; + static foreach(i, m; UICtx.tupleof) + { + { + enum info = CtxMemberInfo!(i); + static if(info.is_stack_top) + { + fields ~= typeof(UICtx.tupleof[i].top.value).stringof ~ " " ~ info.id ~ ";\n"; + } + } + } + + return fields; + } + + mixin(UIItemParameterGen()); + pragma(msg, UIItemParameterGen()); +} + struct UIItem { UIKey key; u64 last_frame; Vec2 dragged; - UIItem* next, prev, first, last, parent; + UIItem* next, prev, first, last; // parent in mixin - - Vec4[4] bg_col; - Vec4[4] bg_hl_col; - Vec4[4] border_col; - Vec4[4] border_hl_col; - Vec4 text_col; - Vec4 text_hl_col; - f32 corner_radius; - f32 border_thickness; - f32 edge_softness; + mixin UIItemParameters!(); Vec2 p0, p1; } @@ -356,7 +401,7 @@ InitUICtx(PlatformWindow* window) g_NIL_VEC4_STACK = cast(Stack!Vec4*)&g_nil_vec4_stack; g_NIL_U32_STACK = cast(Stack!u32*)&g_nil_u32_stack; - g_ui_ctx.parent = g_UI_NIL_PANEL; + g_ui_ctx.parent_panel = g_UI_NIL_PANEL; Arena arena = CreateArena(MB(4)); @@ -444,6 +489,29 @@ InitUICtx(PlatformWindow* window) g_ui_ctx = ctx; } +void +Set(UIItem* item, UICtx* ctx) +{ + enum char[256] buf = 0; + static foreach(i, m; UICtx.tupleof) + { + static foreach(j, m2; UIItem.tupleof) + { + { + enum ctx_id = __traits(identifier, UICtx.tupleof[i]); + enum item_id = __traits(identifier, UIItem.tupleof[j]); + static if(ctx_id == item_id) + { + enum line = sformat(buf, "item.%s = ctx.%s.top.value;", item_id, ctx_id); + mixin(line); + pragma(msg, i); + pragma(msg, line); + } + } + } + } +} + UIItem* MakeItem(T)(T k) if(is(T: UIKey) || StringType!T) { @@ -451,16 +519,7 @@ MakeItem(T)(T k) if(is(T: UIKey) || StringType!T) UIItem* item = Get(k); - item.bg_col = ctx.bg_col.top.value; - item.bg_hl_col = ctx.bg_hl_col.top.value; - item.border_col = ctx.border_col.top.value; - item.border_hl_col = ctx.border_hl_col.top.value; - item.text_col = ctx.text_col.top.value; - item.text_hl_col = ctx.text_hl_col.top.value; - item.corner_radius = ctx.corner_radius.top.value; - item.border_thickness = ctx.border_thickness.top.value; - item.edge_softness = ctx.edge_softness.top.value; - item.parent = ctx.top_parent.top.value; + Set(item, ctx); if(!Nil(item.parent)) { @@ -526,34 +585,6 @@ EndUI() ctx.frame += 1; } -template CtxMemberInfo(int i) -{ - import std.string : endsWith; - import std.traits : isInstanceOf, isPointer; - - struct MemberInfo - { - string id; - bool is_stack, is_top, is_stack_top; - } - - enum string id = __traits(identifier, UICtx.tupleof[i]); - enum bool is_ptr = isPointer!(typeof(UICtx.tupleof[i])); - enum bool is_top = endsWith(id, "_top"); - enum bool is_stack_top = isInstanceOf!(StackTop, typeof(UICtx.tupleof[i])); - - static if(is_ptr) - { - enum bool is_stack = isInstanceOf!(Stack, typeof(*UICtx.tupleof[i])); - } - else - { - enum bool is_stack = false; - } - - enum MemberInfo CtxMemberInfo = MemberInfo(id: id, is_stack: is_ptr && is_stack, is_top: is_top, is_stack_top: is_stack_top); -} - template StackIDs(string stack) { import std.string : replace;