more ui work

This commit is contained in:
Matthew 2025-12-09 07:25:40 +11:00
parent ec19c26071
commit 2703c95673
3 changed files with 132 additions and 174 deletions

View File

@ -141,7 +141,33 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
BeginUI(ctx, inputs);
for(auto p = ctx.base_panel; !Nil(p); p = Recurse(p))
UIPanel* root = ctx.base_panel;
root.size.x = g_ui_ctx.res.x;
root.size.y = g_ui_ctx.res.y;
root.rect.vec0 = 0.0;
root.rect.vec1 = 0.0;
static foreach(axis; A2D.min .. A2D.max)
{
for(UIPanel* p = root; !Nil(p); p = Recurse(p, root, g_UI_NIL_PANEL))
{
f32 pos = p.rect.vec0.v[axis];
for(UIPanel* c = p.first; !Nil(c); c = c.next)
{
c.size.v[axis] = p.axis == axis ? c.pct * p.size.v[axis] : p.size.v[axis];
c.rect.vec0.v[axis] = pos;
c.rect.vec1.v[axis] = pos + c.size.v[axis];
if(axis == p.axis)
{
pos += c.size.v[axis];
}
}
}
}
for(auto p = ctx.base_panel; !Nil(p); p = Recurse(p, ctx.base_panel, g_UI_NIL_PANEL))
{
Panel(p);
}

View File

@ -19,6 +19,14 @@ import core.stdc.math : fabsf;
import std.conv;
import core.stdc.stdio : sprintf;
/****** IMPORTANT NOTES *********
- Display string should be separate from key string
- If key is 0 then its transient and will be discarded next frame
- Events should be created then processed instead of directly from inputs
*********************************/
enum Vec4[4] BG_COL = Vec4(0.13, 0.13, 0.13, 1.0);
enum Vec4[4] BG_HL_COL = Vec4(0.24, 0.45, 0.81, 1.0);
enum Vec4[4] BORDER_COL = Vec4(0.254, 0.254, 0.266, 1.0);
@ -49,6 +57,7 @@ Vec4[4] g_border_col_default = BORDER_COL;
Vec4[4] g_border_hl_col_default = BORDER_HL_COL;
Vec4 g_text_col_default = TEXT_COL;
Vec4 g_text_hl_col_default = TEXT_HL_COL;
UISize[2] g_size_info_default = [UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0)];
const UI_COUNT = 5000;
@ -114,26 +123,22 @@ enum UISignal
alias UIS = UISignal;
enum SizeType
{
Pixels,
Percentage,
FitChild,
}
alias ST = SizeType;
mixin template UICtxParameter(T, string name)
mixin template
UICtxParameter(T, string name)
{
static string
CtxParameterGen(string type, string name)()
CtxParameterGen(T, string name)()
{
return type ~ " " ~ name ~ ";";
import std.traits;
import std.array;
string stack_top = "\tStackTop!("~T.stringof~") "~name~";\n";
string stack = "\tStack!("~T.stringof~")* "~name~"_top;\n";
return stack_top~stack;
}
mixin(CtxParameterGen!((StackTop!(T)).stringof, name)());
mixin(CtxParameterGen!((Stack!(T)*).stringof, name~"_top")());
mixin(CtxParameterGen!(T, name)());
}
template CtxMemberInfo(int i)
@ -173,7 +178,7 @@ struct UICtx
u64 frame;
u64 f_idx;
PlatformWindow* window;
PlatformWindow* window;
Renderer rd;
Descriptor font_atlas;
Descriptor sampler;
@ -194,6 +199,7 @@ struct UICtx
u32 tab_width;
f32 text_size;
UIItem* root;
UIItem* drag_item;
UIPanel* parent_panel;
UIPanel* focused_panel;
@ -208,6 +214,7 @@ struct UICtx
mixin UICtxParameter!(Vec4[4], "border_hl_col");
mixin UICtxParameter!(Vec4, "text_col");
mixin UICtxParameter!(Vec4, "text_hl_col");
mixin UICtxParameter!(UISize[2], "size_info");
debug bool dbg;
}
@ -246,7 +253,6 @@ mixin template UIItemParameters()
}
mixin(UIItemParameterGen());
pragma(msg, UIItemParameterGen());
}
struct UIItem
@ -257,15 +263,26 @@ struct UIItem
UIItem* next, prev, first, last; // parent in mixin
mixin UIItemParameters!();
Rect pref_size;
Rect size;
Vec2 p0, p1;
mixin UIItemParameters!();
}
enum SizeType
{
Pixels,
Percentage,
FitChild,
}
alias ST = SizeType;
struct UISize
{
SizeType type;
f32 value;
f32 strictness = 1.0;
}
struct UIBuffer
@ -492,7 +509,6 @@ InitUICtx(PlatformWindow* window)
void
Set(UIItem* item, UICtx* ctx)
{
enum char[256] buf = 0;
static foreach(i, m; UICtx.tupleof)
{
static foreach(j, m2; UIItem.tupleof)
@ -502,10 +518,7 @@ Set(UIItem* item, UICtx* ctx)
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);
mixin("item."~item_id~" = ctx."~ctx_id~".top.value;\n");
}
}
}
@ -565,7 +578,7 @@ BeginUI(EditorCtx* edctx, Inputs* inputs)
memset(ctx.buffers[ctx.f_idx].idx.ptr, 0, u32.sizeof * ctx.buffers[ctx.f_idx].count);
ctx.buffers[ctx.f_idx].count = 0;
SetPanelSizes(edctx.base_panel);
ctx.root = Root(ctx);
}
void
@ -573,6 +586,17 @@ EndUI()
{
UICtx* ctx = GetCtx();
static foreach(axis; A2D.min .. A2D.max)
{
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, ctx.root, g_UI_NIL))
{
if(item.size_info[axis].type == ST.Pixels)
{
item.size.v[axis] = item.size_info[axis].value;
}
}
}
with(ctx)
{
BindBuffers(&rd, &buffers[f_idx].m_idx, &buffers[f_idx].m_vtx);
@ -585,6 +609,14 @@ EndUI()
ctx.frame += 1;
}
UIItem*
Root(UICtx* ctx)
{
UISize[2] sizes = [UISize(ST.Pixels, ctx.res.x), UISize(ST.Pixels, ctx.res.y)];
Push!("size_info")(ctx, sizes);
return MakeItem("###root");
}
template StackIDs(string stack)
{
import std.string : replace;
@ -709,6 +741,26 @@ ResetStacks(UICtx* ctx)
}
}
T*
Recurse(bool pre = true, T)(T* panel, T* root, T* nil)
{
T* result = nil;
if(!Nil(panel.first))
{
result = pre ? panel.first : panel.last;
}
else for(T* p = panel; !Nil(p) && p != root; p = p.parent)
{
if(!Nil(pre ? p.next : p.prev))
{
result = pre ? p.next : p.prev;
break;
}
}
return result;
}
f32
LineCounterWidth(u32 char_width)
{
@ -721,36 +773,6 @@ InnerSize(UIPanel* panel)
return panel.size - Vec2(g_ui_ctx.border_thickness_top.value*2.0);;
}
void
SetPanelSizes(UIPanel* panel)
{
UICtx* ctx = GetCtx();
panel.size.x = ctx.res.x;
panel.size.y = ctx.res.y;
panel.rect.vec0 = 0.0;
panel.rect.vec1 = 0.0;
static foreach(axis; A2D.min .. A2D.max)
{
for(UIPanel* p = panel; !Nil(p); p = Recurse(p))
{
f32 pos = p.rect.vec0.v[axis];
for(UIPanel* c = p.first; !Nil(c); c = c.next)
{
c.size.v[axis] = p.axis == axis ? c.pct * p.size.v[axis] : p.size.v[axis];
c.rect.vec0.v[axis] = pos;
c.rect.vec1.v[axis] = pos + c.size.v[axis];
if(axis == p.axis)
{
pos += c.size.v[axis];
}
}
}
}
}
pragma(inline) void
DrawChar(u8 ch, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
{
@ -758,27 +780,6 @@ DrawChar(u8 ch, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
DrawGlyph(g, 1.0, x_pos, y, col);
}
bool
PrintInputs()
{
bool result;
UICtx* ctx = GetCtx();
for(auto n = ctx.inputs.list.first; n != null; n = n.next)
{
Logf("key %s %s %s", n.value.key, n.value.x, n.value.y);
result = true;
}
return result;
}
f32
EaseOutQuint(f32 x)
{
return 1.0 - pow(1.0 - x, 5);
}
void
SetScrollOffset(UIPanel* panel)
{
@ -809,7 +810,6 @@ SetScrollOffset(UIPanel* panel)
if(fabsf(panel.scroll_offset-panel.scroll_target) < 0.0009)
{
Logf("end");
panel.scroll_offset = panel.scroll_target;
}
}
@ -875,17 +875,11 @@ MakeKey(T)(T str) if(StringType!T)
key.hash_text = hash_only ? id : [];
key.hash = Hash(id);
}
else if(hash_count == 2)
else if(hash_count == 2 || hash_count == 3)
{
key.text = id[0 .. pos];
key.hash_text = id[pos .. $];
key.hash = Hash(id);
}
else if(hash_count == 3)
{
key.text = id[0 .. pos];
key.hash_text = id[pos .. $];
key.hash = Hash(id[pos+hash_count .. $]);
key.hash = hash_count == 2 ? Hash(id) : Hash(id[pos+hash_count .. $]);
}
return key;
@ -1259,44 +1253,6 @@ Dragged(UIItem* item, Vec2 p0, Vec2 p1)
return result;
}
u8[]
ScratchName(u64 num_len, u8[] base, u64 iteration)
{
import core.stdc.stdio : sprintf;
char[64] ch_buf;
char[] s = ch_buf.sformat("%%0%sllu%%s", num_len);
u8[] id = ScratchAlloc!(u8)(base.length+num_len);
sprintf(cast(char*)id.ptr, s.ptr, iteration, cast(char*)base.ptr);
return id;
}
u8[]
ScratchName(string fmt, u64 len, u64 iteration)
{
u8[] id = ScratchAlloc!(u8)(len);
(cast(char[])id).sformat(fmt, iteration);
return id;
}
u8[]
ScratchName(u8[] base, u8[] append)
{
u8[] id = ScratchAlloc!(u8)(base.length+append.length);
id[0 .. base.length] = base[0 .. $];
id[base.length .. $] = append[0 .. $];
return id;
}
u8[]
ScratchName(u8[] base, string append)
{
u8[] u8_append = CastStr!(u8)(append);
return ScratchName(base, u8_append);
}
unittest
{
{ // UI Key

View File

@ -161,30 +161,6 @@ CommandPalette(CmdPalette* cmd)
}
}
UIPanel*
Recurse(UIPanel* panel)
{
UIPanel* result = g_UI_NIL_PANEL;
if(!Nil(panel.first))
{
result = panel.first;
}
else if(!Nil(panel.next))
{
result = panel.next;
}
else for(UIPanel* p = panel.parent; !Nil(p); p = p.parent)
{
if(!Nil(p.next))
{
result = p.next;
break;
}
}
return result;
}
bool
CheckPanelBounds(f32 pct)
{