template automation for ui parameters

This commit is contained in:
Matthew 2025-12-06 21:22:04 +11:00
parent 2a3be6ad58
commit ec19c26071

View File

@ -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;