diff --git a/src/editor/editor.d b/src/editor/editor.d index 83f561c..2cd5a2b 100644 --- a/src/editor/editor.d +++ b/src/editor/editor.d @@ -147,91 +147,15 @@ Cycle(EditorCtx* ctx, Inputs* inputs) UICtx* ui_ctx = GetCtx(); - Vec4[4] col0 = Vec4(0.2, 0.4, 0.8, 1.0); - Vec4[4] col1 = Vec4(0.8, 0.4, 0.2, 1.0); - Vec4[4] blue = Vec4(0.1, 0.3, 0.9, 1.0); - Vec4[4] black = Vec4(0.0, 0.0, 0.0, 1.0); - Vec4[4] green = Vec4(0.2, 0.8, 0.1, 1.0); - Vec4[4] white = Vec4(1.0); + static Editor* ed; - Push!("border_thickness", true)(ui_ctx, 10.0f); - Push!("size_info")(ui_ctx, MakeUISizeX(ST.Percentage, 0.5)); - Push!("bg_col", true)(ui_ctx, col0); - UIItem* p0 = MakeItem("###p0", UIF.DrawBackground|UIF.Resizeable|UIF.DrawBorder); - - Push!("layout_axis", true)(ui_ctx, A2D.Y); - Push!("parent")(ui_ctx, p0); - Push!("size_info", true)(ui_ctx, MakeUISize(UISize(ST.ChildrenSum, 1.0), UISize(ST.Percentage, 1.0))); - Push!("bg_col", true)(ui_ctx, blue); - UIItem* ln = MakeItem("###ln", UIF.DrawBackground); - - Push!("parent")(ui_ctx, ln); - Push!("bg_col")(ui_ctx, white); - Push!("padding")(ui_ctx, Vec2(4.0, 0.0)); - Push!("size_info")(ui_ctx, MakeUISize(UISize(ST.TextSize, 1.0), UISize(ST.Pixels, ui_ctx.char_height))); - - foreach(i; 0 .. 99) + if(!ed) { - MakeItem("%s##ln", i, UIF.DrawText); + ed = CreateEditor(ctx); + OpenFile(ed, CastStr!(u8)("src/editor/ui.d")); } - Pop!("padding", "size_info", "parent", "bg_col")(ui_ctx); - - Push!("size_info", true)(ui_ctx, MakeUISizeX(ST.Percentage, 1.0)); - Push!("layout_axis", true)(ui_ctx, A2D.Y); - UIItem* t_box = MakeItem("###t_box"); - - Push!("parent")(ui_ctx, t_box); - - Push!("size_info", true)(ui_ctx, MakeUISize(UISize(ST.Pixels, 350.0, 1.0), UISize(ST.TextSize, 1.0, 1.0))); - Push!("bg_col", true)(ui_ctx, green); - Push!("padding", true)(ui_ctx, Vec2(4.0)); - UIItem* text = MakeItem("Test line of text##text", UIF.DrawBackground|UIF.DrawText|UIF.RightAlignText|UIF.TextWrap); - - Push!("size_info", true)(ui_ctx, MakeUISize(UISize(ST.Percentage, 1.0, 1.0), UISize(ST.TextSize, 1.0, 1.0))); - Push!("bg_col", true)(ui_ctx, white); - Push!("text_col", true)(ui_ctx, black[0]); - Push!("padding", true)(ui_ctx, Vec2(8.0)); - UIItem* text2 = MakeItem("A different line of text for testing purposes##text2", UIF.DrawBackground|UIF.DrawText|UIF.TextWrap); - - Pop!("parent")(ui_ctx); - Pop!("parent")(ui_ctx); - - Push!("size_info", true)(ui_ctx, MakeUISizeX(ST.Pixels, 100.0)); - Push!("bg_col", true)(ui_ctx, black); - UIItem* sep = MakeItem("###sep", UIF.Draggable|UIF.DrawBackground|UIF.ResizeAdjacent); - - Push!("layout_axis", true)(ui_ctx, A2D.Y); - Push!("bg_col", true)(ui_ctx, col1); - UIItem* p1 = MakeItem("###p1", UIF.DrawBackground|UIF.Resizeable); - - Push!("parent")(ui_ctx, p1); - - Vec4[4] c0 = Vec4(Vec3(0.2), 1.0); - Vec4[4] c1 = Vec4(Vec3(0.4), 1.0); - Vec4[4] c2 = Vec4(Vec3(0.6), 1.0); - Vec4[4] c3 = Vec4(Vec3(0.8), 1.0); - Vec4[4] c4 = Vec4(1.0); - - Push!("bg_col", true)(ui_ctx, c0); - Push!("size_info", true)(ui_ctx, MakeUISizeY(ST.Percentage, 0.1)); - MakeItem("###c0", UIF.DrawBackground); - - Push!("bg_col", true)(ui_ctx, c1); - Push!("size_info", true)(ui_ctx, MakeUISizeY(ST.Percentage, 0.13)); - MakeItem("###c1", UIF.DrawBackground); - - Push!("bg_col", true)(ui_ctx, c2); - Push!("size_info", true)(ui_ctx, MakeUISizeY(ST.Percentage, 0.17)); - MakeItem("###c2", UIF.DrawBackground); - - Push!("bg_col", true)(ui_ctx, c3); - Push!("size_info", true)(ui_ctx, MakeUISizeY(ST.Percentage, 0.25)); - MakeItem("###c3", UIF.DrawBackground); - - Push!("bg_col", true)(ui_ctx, c4); - Push!("size_info", true)(ui_ctx, MakeUISizeY(ST.Percentage, 0.35)); - MakeItem("###c4", UIF.DrawBackground); + EditorView(ed); /* UIPanel* root = ctx.base_panel; diff --git a/src/editor/ui.d b/src/editor/ui.d index 8bc7cd9..cce574f 100644 --- a/src/editor/ui.d +++ b/src/editor/ui.d @@ -67,6 +67,7 @@ f32 g_text_scale_default = 1.0; Vec2 g_scroll_target_default = Vec2(0.0); Vec2 g_scroll_clamp_default = Vec2(0.0); Vec2 g_view_offset_default = Vec2(0.0); +string g_display_string_default = null; alias g_parent_default = g_UI_NIL; const UI_COUNT = 5000; @@ -198,6 +199,7 @@ struct UICtx { HashTable!(UIHash, UIItem*) items; UIItem* free_items; + UIItem* transient_items; Arena arena; Arena temp_arena; @@ -249,6 +251,7 @@ struct UICtx mixin UICtxParameter!(Vec2, "padding"); mixin UICtxParameter!(Vec2, "view_offset"); mixin UICtxParameter!(UIItem*, "parent"); + mixin UICtxParameter!(string, "display_string"); mixin UICtxParameter!(Axis2D, "layout_axis"); mixin UICtxParameter!(f32, "corner_radius"); mixin UICtxParameter!(f32, "border_thickness"); @@ -309,11 +312,11 @@ struct UIItem UIFlags flags; UIItem* next, prev, first, last; // parent in mixin + UIItem* transient_next; Rect rect; Vec2 size; - string display_string; string[] text_lines; f32 max_text_width; f32 resize_pct; @@ -461,19 +464,20 @@ InitUICtx(PlatformWindow* window) UIBuffer[FRAME_OVERLAP] buffers; UICtx ctx = { - items: CreateHashTable!(UIHash, UIItem*)(12), - free_items: Alloc!(UIItem)(&arena), - arena: arena, - temp_arena: CreateArena(MB(1)), - drag_item: g_UI_NIL, - font: OpenFont(cast(u8[])FONT_BYTES), - font_data: cast(u8[])FONT_BYTES, - text_size: 16.0, - tab_width: 2, + items: CreateHashTable!(UIHash, UIItem*)(12), + free_items: Alloc!(UIItem)(&arena), + arena: arena, + temp_arena: CreateArena(MB(1)), + drag_item: g_UI_NIL, + transient_items: g_UI_NIL, + font: OpenFont(cast(u8[])FONT_BYTES), + font_data: cast(u8[])FONT_BYTES, + text_size: 16.0, + tab_width: 2, }; UIItem* fi = ctx.free_items; - fi.first = fi.last = fi.next = fi.prev = fi.parent = g_UI_NIL; + fi.transient_next = fi.first = fi.last = fi.next = fi.prev = fi.parent = g_UI_NIL; ctx.atlas_buf = CreateAtlas(&arena, ctx.font, 16.0, 256); ctx.char_height = cast(f32)((ctx.font.size.metrics.ascender - ctx.font.size.metrics.descender) >> 6); @@ -828,15 +832,21 @@ BeginUI(Inputs* inputs) foreach(i; 0 .. items.length) { UIItem* item = items[i].value; - if(item.last_frame != ctx.frame || ZeroKey(item.key)) + if(item.last_frame != ctx.frame) { - Logf("discarding %s", cast(char[])item.key.hash_text); - item.first = item.last = item.parent = item.prev = item.next = g_UI_NIL; + memset(item, 0, UIItem.sizeof); DLLPush(ctx.free_items, item, g_UI_NIL); } } - ctx.frame += 1; + for(UIItem* item = ctx.transient_items; !Nil(item); item = item.transient_next) + { + memset(item, 0, UIItem.sizeof); + DLLPush(ctx.free_items, item, g_UI_NIL); + } + + ctx.frame += 1; + ctx.transient_items = g_UI_NIL; // Ctx state ctx.f_idx = ctx.frame%FRAME_OVERLAP; @@ -989,6 +999,11 @@ EndUI() { f32 size = InnerSize!(axis)(item); + if(item.flags & (UIF.PortalX << axis)) + { + continue; + } + if(axis == item.layout_axis) { f32 children_size = 0.0; @@ -1062,6 +1077,8 @@ EndUI() item.rect.p0.v[axis] = inner_pos; item.rect.p1.v[axis] = end_pos; + next_pos = item.parent.layout_axis == axis ? end_pos : pos; + assert(!isNaN(item.rect.p0.v[axis])); assert(!isNaN(item.rect.p1.v[axis])); @@ -1087,8 +1104,6 @@ EndUI() } } - next_pos = item.parent.layout_axis == axis ? end_pos : pos; - if(!Nil(item.first)) { item = item.first; @@ -1181,7 +1196,7 @@ RenderItem(UICtx* ctx, UIItem* item) v.dst_end = item.rect.p1; v.cols = item.border_col; v.corner_radius = item.corner_radius; - v.border_thickness = item.border_thickness; + v.border_thickness = clamp(item.border_thickness, 1.0, f32.max); v.edge_softness = item.edge_softness; v.bounds = ItemBounds(item.parent); @@ -1566,6 +1581,25 @@ ZeroKey(UIKey key) return key.hash == 0 && key.hash_text.length == 0; } +UIItem* +NewItem(UICtx* ctx) +{ + UIItem* item = g_UI_NIL; + + if(!Nil(ctx.free_items.first)) + { + item = DLLPop(ctx.free_items, g_UI_NIL); + } + else + { + item = Alloc!(UIItem)(&ctx.arena); + } + + item.last_frame = ctx.frame-2; + + return item; +} + UIItem* Get(Args...)(string str, Args args) { @@ -1585,26 +1619,33 @@ Get(T)(T k) if(is(T: UIKey) || StringType!T) UIKey key = MakeKey(k); } - Result!(UIItem*) res = g_ui_ctx.items[key.hash]; - if(!res.ok) + UIItem* item; + UICtx* ctx = GetCtx(); + + if(ZeroKey(key)) { - if(!Nil(g_ui_ctx.free_items.first)) + item = NewItem(ctx); + item.transient_next = ctx.transient_items; + ctx.transient_items = item; + } + else + { + Result!(UIItem*) res = ctx.items[key.hash]; + if(res.ok) { - res.value = DLLPop(g_ui_ctx.free_items, g_UI_NIL); + item = res.value; } else { - res.value = Alloc!(UIItem)(&g_ui_ctx.arena); - HTPush(&g_ui_ctx.items, key.hash, res.value); + item = NewItem(ctx); + HTPush(&ctx.items, key.hash, item); } - - res.value.last_frame = g_ui_ctx.frame-2; } - res.value.key = key; - res.value.next = res.value.prev = res.value.first = res.value.last = res.value.parent = g_UI_NIL; + item.key = key; + item.next = item.prev = item.first = item.last = item.parent = g_UI_NIL; - return res.value; + return item; } f32 diff --git a/src/editor/views.d b/src/editor/views.d index 40a2961..4d8661a 100644 --- a/src/editor/views.d +++ b/src/editor/views.d @@ -25,11 +25,18 @@ EditorView(Editor* ed) u64 frame_line_offset = ed.line_offset; f32 frame_view_offset = editor.scroll_offset.y%TEXT_SIZE; - Push!("border_col" )(ctx, Vec4Arr(Vec4(1.0))); + Push!("bg_col", true)(ctx, Vec4Arr(Vec4(0.2, 0.3, 0.8, 1.0))); + Push!("size_info", true)(ctx, MakeUISizeX(ST.Percentage, 1.0)); + UIItem* container = MakeItem(zero, UIF.DrawBackground); + + Push!("parent")(ctx, container); + + Push!("border_col")(ctx, Vec4Arr(Vec4(1.0))); // Line Counter f32 lc_width = ed.buf.line_count.toChars().length*ctx.char_width; + Push!("layout_axis", true)(ctx, A2D.Y); Push!("view_offset" )(ctx, Vec2(0.0, frame_view_offset)); Push!("padding", true)(ctx, Vec2(4.0, 0.0)); Push!("size_info", true)(ctx, MakeUISizeX(ST.Pixels, lc_width)); @@ -39,6 +46,7 @@ EditorView(Editor* ed) // Editor f32 scroll_pos = cast(f32)(ed.line_offset)*TEXT_SIZE; + Push!("layout_axis", true)(ctx, A2D.Y); Push!("scroll_clamp", true)(ctx, cast(Vec2[2])[Vec2(0.0), Vec2(0.0, cast(f32)(ed.buf.line_count)*TEXT_SIZE)]); Push!("size_info", true)(ctx, MakeUISize(UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0))); Push!("border_col", true)(ctx, Vec4Arr(Vec4(1.0))); @@ -72,14 +80,26 @@ EditorView(Editor* ed) Push!("parent" )(ctx, line_count); Push!("text_col" )(ctx, Vec4(1.0)); - u64 i = frame_line_offset; - for(LineBuffer* lb = GetLine(&ed.buf, i); i < frame_line_offset+view_lines; i += 1) - { + u64 end_line = frame_line_offset+view_lines; + for(u64 i = frame_line_offset; i < end_line; i += 1) + { + MakeItem("%s##ed_%s", i, ed.editor_id, UIF.DrawText); } - Pop!("parent")(ctx); - + Pop!("parent", "size_info")(ctx); + + Push!("size_info")(ctx, MakeUISizeY(ST.TextSize, 1.0)); + Push!("parent")(ctx, editor); + + u64 i = frame_line_offset; + for(LineBuffer* lb = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, lb) && i < end_line; i += 1, lb = GetLine(&ed.buf, i)) + { + Push!("display_string", true)(ctx, ConvToStr(lb.text)); + UIItem* line = MakeItem(zero, UIF.DrawText); + } + + Pop!("parent", "parent", "text_col")(ctx); } /*