diff --git a/src/editor/editor.d b/src/editor/editor.d index 8145742..8c914c6 100644 --- a/src/editor/editor.d +++ b/src/editor/editor.d @@ -21,16 +21,16 @@ debug bool g_frame_continue = false; struct EditorCtx { - Arena arena; + Arena arena; PlatformWindow* window; - UIPanel* base_panel; - u64 panel_id; - EditState state; - u8[128] input_buf; - u32 icount; - Timer timer; - CmdPalette cmd; - u8[][] file_names; + UIPanel* base_panel; + u64 panel_id; + EditState state; + u8[128] input_buf; + u32 icount; + Timer timer; + CmdPalette cmd; + u8[][] file_names; } struct CmdPalette @@ -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); } diff --git a/src/editor/ui.d b/src/editor/ui.d index 061dd20..e1f0926 100644 --- a/src/editor/ui.d +++ b/src/editor/ui.d @@ -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); @@ -48,7 +56,8 @@ Vec4[4] g_bg_hl_col_default = BG_HL_COL; 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; +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,20 +199,22 @@ struct UICtx u32 tab_width; f32 text_size; + UIItem* root; UIItem* drag_item; UIPanel* parent_panel; UIPanel* focused_panel; - 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"); + 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"); + 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 @@ -284,12 +301,12 @@ struct PushConst struct GlyphBounds { - f32 r = 0.0; - f32 l = 0.0; - f32 t = 0.0; - f32 b = 0.0; - f32 w = 0.0; - f32 h = 0.0; + f32 r = 0.0; + f32 l = 0.0; + f32 t = 0.0; + f32 b = 0.0; + f32 w = 0.0; + f32 h = 0.0; f32 atlas_r = 0.0; f32 atlas_l = 0.0; f32 atlas_t = 0.0; @@ -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 diff --git a/src/editor/views.d b/src/editor/views.d index 4fe71bc..4db7f1d 100644 --- a/src/editor/views.d +++ b/src/editor/views.d @@ -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) {