diff --git a/src/dlib b/src/dlib index 27d62be..cadb2b5 160000 --- a/src/dlib +++ b/src/dlib @@ -1 +1 @@ -Subproject commit 27d62beb4195c08bd25bffaa0d9c72b523d971f4 +Subproject commit cadb2b5f853a22aa870dc1d986e73330c9136bb5 diff --git a/src/editor/editor.d b/src/editor/editor.d index 827286c..7c51c8c 100644 --- a/src/editor/editor.d +++ b/src/editor/editor.d @@ -14,8 +14,11 @@ import widgets; import std.format; import std.stdio; import std.exception; +import std.file; f32 g_delta = 0.0; +debug bool g_frame_step = false; +debug bool g_frame_continue = false; struct EditorCtx { @@ -25,6 +28,8 @@ struct EditorCtx EditState state; u8[128] input_buf; u32 icount; + u8[] cmd_buffer; + u32 cmd_count; Timer timer; } @@ -64,23 +69,32 @@ Cycle(EditorCtx* ctx, Inputs* inputs) g_delta = DeltaTime(&ctx.timer); + debug if(g_frame_step) + { + g_delta = 0.01; + } + assert(Nil(ctx.base_panel.next)); HandleInputs(ctx, inputs); + debug if(g_frame_step && !g_frame_continue) return; + debug g_frame_continue = false; + g_input_mode = ctx.state == ES.InputMode; - + // UI Functions After This Point BeginBuild(inputs); if(ctx.state == ES.CmdOpen) { - CommandPalette(); + CommandPalette(ctx.cmd_buffer[0 .. ctx.cmd_count]); } DrawPanels(ctx.base_panel); EndBuild(); + // UI Functions Before This Point } EditorCtx @@ -97,6 +111,7 @@ InitEditorCtx(PlatformWindow* window) ctx.base_panel = CreatePanel(&ctx); ctx.base_panel.ed = CreateEditor(&ctx); ctx.timer = CreateTimer(); + ctx.cmd_buffer = MAllocArray!(u8)(1024); SetFocusedPanel(ctx.base_panel); return ctx; @@ -123,6 +138,12 @@ EditModeActive() return g_input_mode; } +void +ScanFiles(EditorCtx* ctx) +{ + +} + // Load all files then move things into editor after being created when selected Editor* @@ -251,6 +272,10 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs) { taken = HandleInputMode(ctx, node.value); } + else if(ctx.state == ES.CmdOpen) + { + taken = HandleCmdMode(ctx, node.value); + } else { switch(key) with(Input) @@ -276,11 +301,25 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs) } break; case c: { - //AddEditor(ctx, GetFocusedPanel(), A2D.Y); - //taken = true; + AddEditor(ctx, GetFocusedPanel(), A2D.Y); + taken = true; } break; case d: { + static bool dbg = false; + dbg = !dbg; + SetDebug(dbg); + } break; + case g: + { + debug + { + g_frame_step = !g_frame_step; + } + } break; + debug case s: + { + g_frame_continue = true; } break; case Up: case Down: @@ -367,6 +406,64 @@ HandleInputMode(EditorCtx* ctx, InputEvent ev) return taken; } +static string +TextLineCharCases() +{ + import std.traits; + + string result = ""; + foreach(input; EnumMembers!Input) + { + u8 ch = InputToChar(input); + if(ch > 0 && ch != '\n') + { + if(ch == '\'' || ch == '\\') + { + result ~= format("case %s: result = '\\%s'; taken = true; break;\n", input, cast(char)ch); + } + else + { + result ~= format("case %s: result = '%s'; taken = true; break;\n", input, cast(char)ch); + } + } + } + + return result; +} + +bool +HandleCmdMode(EditorCtx* ctx, InputEvent ev) +{ + + u8 result = 0; + bool taken = false; + switch(ev.key) with(Input) + { + mixin(TextLineCharCases()); + case Backspace: + { + if(ctx.cmd_count > 0) + { + ctx.cmd_count -= 1; + } + } break; + case Escape: + { + ctx.cmd_count = 0; + ctx.state = ES.NormalMode; + } break; + default: break; + } + + if(result != 0) + { + Logf("test"); + ctx.cmd_buffer[ctx.cmd_count++] = result; + } + + return taken; +} + /* void DrawBuffer(Editor* ed, f32 x, f32 y, f32 px, FlatBuffer* fb) diff --git a/src/editor/ui.d b/src/editor/ui.d index 51e02f2..af87a79 100644 --- a/src/editor/ui.d +++ b/src/editor/ui.d @@ -195,6 +195,20 @@ struct PushConst Mat4 projection; } +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 atlas_r = 0.0; + f32 atlas_l = 0.0; + f32 atlas_t = 0.0; + f32 atlas_b = 0.0; +} + struct Vertex { Vec4[4] cols; @@ -234,6 +248,7 @@ alias UIPair = KVPair!(UIHash, UIItem*); struct UIKey { u8[] text; + u8[] hash_text; u64 hash; } @@ -655,7 +670,7 @@ EndBuild() DrawUI(ctx, ctx.root); - if(ctx.dbg) + debug if(ctx.dbg) { DrawDebugUI(ctx, ctx.root); } @@ -674,7 +689,8 @@ EndBuild() static u32 prev_count = 0; if(prev_count != ctx.item_count) { - PrintNodes(ctx.root); + //Logf("New node count, printing node debug info: "); + //PrintNodes(ctx.root); prev_count = ctx.item_count; } } @@ -715,12 +731,8 @@ PrintNodes(UIItem* item) { if(!Nil(item)) { - if(item.culling.vec0 != Vec2(0.0) || item.culling.vec1 != Vec2(0.0)) - { - Logf("%s:", cast(char[])item.key.text); - Logf("x0 %s x1 %s y0 %s y1 %s", item.rect.x0, item.rect.x1, item.rect.y0, item.rect.y1); - Logf("cull x0 %s x1 %s y0 %s y1 %s\n", item.culling.x0, item.culling.x1, item.culling.y0, item.culling.y1); - } + Logf("%s:", cast(char[])item.key.text); + Logf("x0 %s x1 %s y0 %s y1 %s", item.rect.x0, item.rect.x1, item.rect.y0, item.rect.y1); PrintNodes(item.first); PrintNodes(item.next); @@ -791,15 +803,24 @@ CalcPositions(alias axis)(UIItem* item) f32 end_pos = 0.0, next_pos = 0.0; if(i.flags & UIF.Window) { - end_pos = i.size.v[axis] + i.offset.v[axis]; + end_pos = i.offset.v[axis] + i.size.v[axis]; i.rect.vec0.v[axis] = i.offset.v[axis]; i.rect.vec1.v[axis] = end_pos; + + pos = i.rect.vec0.v[axis]; } else { + pos += i.offset.v[axis]; end_pos = pos + i.size.v[axis]; - i.rect.vec0.v[axis] = pos + i.offset.v[axis]; - i.rect.vec1.v[axis] = end_pos + i.offset.v[axis]; + i.rect.vec0.v[axis] = pos; + i.rect.vec1.v[axis] = end_pos; + + + if(item.parent.key.text == r"###cmd_palette_input_cntr") + { + Logf("pos %s end_pos %s", pos, end_pos); + } assert(!isNaN(i.rect.vec0.v[axis])); assert(!isNaN(i.rect.vec1.v[axis])); @@ -1032,18 +1053,6 @@ RootSize() return size; } - -UIKey -MakeKey(u8[] text, u8[] hash) -{ - UIKey key; - - key.text = text; - key.hash = Hash(text, hash); - - return key; -} - UIKey MakeKey(u8[] id) { @@ -1079,18 +1088,21 @@ MakeKey(u8[] id) if(hash_count < 2 || hash_only) { - key.text = id; - key.hash = Hash(id); + key.text = hash_only ? [] : id; + key.hash_text = hash_only ? id : []; + key.hash = Hash(id); } else if(hash_count == 2) { - key.text = id.ptr[0 .. pos]; - key.hash = Hash(id); + key.text = id[0 .. pos]; + key.hash_text = id[pos .. $]; + key.hash = Hash(id); } else if(hash_count == 3) { - key.text = id.ptr[0 .. pos]; - key.hash = Hash(id[pos+hash_count .. $]); + key.text = id[0 .. pos]; + key.hash_text = id[pos .. $]; + key.hash = Hash(id[pos+hash_count .. $]); } return key; @@ -1306,6 +1318,58 @@ DrawLine(UIItem* item) } } +pragma(inline) bool +CullText(UIItem* item, GlyphBounds* gb) +{ + bool skip = false; + + if(item.culling.x0 != 0.0 || item.culling.x1 != 0.0) + { + if(gb.w <= item.culling.x0+item.culling.x1) + { + skip = true; + } + else + { + f32 start_pct = 1.0-((gb.w-item.culling.x0)/gb.w); + f32 end_pct = 1.0-((gb.w-item.culling.x1)/gb.w); + + f32 atlas_len = gb.atlas_r - gb.atlas_l; + gb.atlas_l += atlas_len * start_pct; + gb.atlas_r -= atlas_len * end_pct; + + gb.l += item.culling.x0; + gb.r -= item.culling.x1; + + gb.w = gb.r-gb.l; + } + } + + if(!skip && (item.culling.y0 != 0.0 || item.culling.y1 != 0.0)) + { + if(gb.h <= item.culling.y0+item.culling.y1) + { + skip = true; + } + else + { + f32 start_pct = 1.0-((gb.h-item.culling.y0)/gb.h); + f32 end_pct = 1.0-((gb.h-item.culling.y1)/gb.h); + + f32 atlas_len = gb.atlas_b-gb.atlas_t; + gb.atlas_t += atlas_len * start_pct; + gb.atlas_b -= atlas_len * end_pct; + + gb.t += item.culling.y0; + gb.b -= item.culling.y1; + + gb.h = gb.b-gb.t; + } + } + + return skip; +} + pragma(inline) void DrawGlyph(UIItem* item, Glyph* glyph, f32 scale, f32* x_pos, f32 y, bool highlight = false, Vec4 col = Vec4(1.0)) { @@ -1316,63 +1380,27 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32 scale, f32* x_pos, f32 y, bool highlig { *x_pos += glyph.advance * (GetCtx().tab_width - 1); } - + f32 r = glyph.plane_right * scale; f32 l = glyph.plane_left * scale; f32 t = glyph.plane_top * scale; f32 b = glyph.plane_bottom * scale; - f32 w = r - l; - f32 h = b - t; - f32 atlas_r = glyph.atlas_right; - f32 atlas_l = glyph.atlas_left; - f32 atlas_t = glyph.atlas_top; - f32 atlas_b = glyph.atlas_bottom; + GlyphBounds gb = { + r: r, + l: l, + t: t, + b: b, + w: r - l, + h: b - t, + atlas_r: glyph.atlas_right, + atlas_l: glyph.atlas_left, + atlas_t: glyph.atlas_top, + atlas_b: glyph.atlas_bottom, + }; - bool skip = false; - if(item.culling.x0 != 0.0 || item.culling.x1 != 0.0) - { - if(w <= item.culling.x0+item.culling.x1) - { - skip = true; - } - else - { - f32 start_pct = 1.0-((w-item.culling.x0)/w); - f32 end_pct = 1.0-((w-item.culling.x1)/w); - - f32 atlas_len = atlas_r - atlas_l; - atlas_l += atlas_len * start_pct; - atlas_r -= atlas_len * end_pct; - - l += item.culling.x0; - r -= item.culling.x1; - - w = r-l; - } - } - - if(!skip && (item.culling.y0 != 0.0 || item.culling.y1 != 0.0)) - { - if(h <= item.culling.y0+item.culling.y1) - { - skip = true; - } - else - { - f32 start_pct = 1.0-((h-item.culling.y0)/h); - f32 end_pct = 1.0-((h-item.culling.y1)/h); - - f32 atlas_len = atlas_b-atlas_t; - atlas_t += atlas_len * start_pct; - atlas_b -= atlas_len * end_pct; - - t += item.culling.y0; - b -= item.culling.y1; - - h = b-t; - } - } + //bool skip = false; + bool skip = CullText(item, &gb); if(!skip) { @@ -1380,17 +1408,17 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32 scale, f32* x_pos, f32 y, bool highlig v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count; - v.dst_start.x = *x_pos + l; + v.dst_start.x = *x_pos + gb.l; v.dst_start.y = y - y_pos; - v.dst_end.x = *x_pos + w + l; - v.dst_end.y = y + h - y_pos; + v.dst_end.x = *x_pos + gb.w + gb.l; + v.dst_end.y = y + gb.h - y_pos; if(glyph.ch != '\t' && glyph.ch != '\n') { - v.src_start.x = glyph.atlas_left; - v.src_start.y = glyph.atlas_top; - v.src_end.x = glyph.atlas_right; - v.src_end.y = glyph.atlas_bottom; + v.src_start.x = gb.atlas_l; + v.src_start.y = gb.atlas_t; + v.src_end.x = gb.atlas_r; + v.src_end.y = gb.atlas_b; } if(highlight) @@ -1417,7 +1445,7 @@ DrawRect(UICtx* ctx, UIItem* item) v.dst_end = item.rect.vec1; v.cols = item.color; v.border_thickness = 0.0; - v.corner_radius = 0.0; + v.corner_radius = item.corner_radius; v.edge_softness = 0.0; v.raised = 0.0; @@ -1501,16 +1529,20 @@ Clicked(UIItem* item, DNode!(InputEvent)* n) return result; } +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); - - u8[] id = ScratchAlloc!(u8)(base.length+append.length); - id[0 .. base.length] = base[0 .. $]; - id[base.length .. $] = u8_append[0 .. $]; - - return id; + return ScratchName(base, u8_append); } void diff --git a/src/editor/widgets.d b/src/editor/widgets.d index 0df7137..19e6108 100644 --- a/src/editor/widgets.d +++ b/src/editor/widgets.d @@ -13,9 +13,9 @@ import core.stdc.stdio : sprintf; const Vec4[4] DEFAULT_COL = [ Vec4(0.3, 0.65, 0.86, 1.0), - Vec4(0.25, 0.60, 0.81, 1.0), - Vec4(0.25, 0.60, 0.81, 1.0), - Vec4(0.3, 0.65, 0.86, 1.0), + Vec4(0.28, 0.63, 0.83, 1.0), + Vec4(0.26, 0.62, 0.82, 1.0), + Vec4(0.25, 0.61, 0.80, 1.0), ]; const UIPanel g_ui_nil_panel; @@ -137,7 +137,6 @@ UIItem* LineCounter(u8[] parent_id, FlatBuffer* buf, f32 offset, i64 start_row, i64 end_row) { Push!("padding")(Vec2(4.0, 0.0)); - Push!("offset")(Vec2(0.0, offset)); Push!("color")(Vec4(0.2, 0.5, 0.65, 1.0)); u8[] id = ScratchName(parent_id, "linec"); @@ -169,17 +168,18 @@ LineCounter(u8[] parent_id, FlatBuffer* buf, f32 offset, i64 start_row, i64 end_ { UIItem* inner = Container(ScratchName(parent_id, "lcinner"), s_x, s_y, A2D.Y, UIF.None); { + Push!("offset")(Vec2(0.0, offset)); for(u64 i = 0; i < line_counts.length; i += 1) { UIItem* line = Text(line_counts[i]); } + Pop!("offset")(); } EndContainer(); } EndContainer(); Pop!("padding")(); - Pop!("offset")(); Pop!("color")(); return item; @@ -364,11 +364,9 @@ EditorView(UIPanel* panel) LineCounter(panel.id, &panel.ed.buf, offset, line_offset, line_offset+line_rows); - Push!("offset")(Vec2(0.0, offset)); - scope(exit) Pop!("offset")(); - Container(ScratchName(panel.id, "lines"), UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0), A2D.Y); { + Push!("offset")(Vec2(0.0, offset)); U64Vec2 pos = VecPos(&ed.buf); u64 i = 0; for(LineBuffer* buf = ed.linebufs.first; buf != null; buf = buf.next, i += 1) @@ -404,6 +402,8 @@ EditorView(UIPanel* panel) { SetFocusedPanel(panel); } + + Pop!("offset"); } bool @@ -455,27 +455,67 @@ WrappedTextLine(u8[] text, u8[] parent_id, f32 text_size, u64 line_no) BuildItem(tp.item, UISize(ST.Percentage, 1.0), UISize(ST.Pixels, text_size), UIF.DrawText|UIF.Clickable|UIF.Draggable); } - Pop!("color")(); + Pop!("color"); return part; } UIItem* -CommandPalette() +TextInput(u8[] text, u8[] hash, f32 x, f32 y, f32 w_pct, f32 text_size, Vec4 bg_col) +{ + UIItem* input = Get(ScratchName(text, hash)); + + //Logf("%s %s %s", input.rect.vec0.v, input.rect.vec1.v, cast(char[])input.key.text); + + Push!("offset")(Vec2(x, y)); + Push!("padding")(Vec2(2.0)); + Push!("color")(bg_col); + + Container(ScratchName(hash, "_cntr"), UISize(ST.Percentage, w_pct), UISize(ST.Pixels, text_size), A2D.Y, UIF.DrawBackground); + + Pop!("color"); + Pop!("offset"); + + Push!("color")(Vec4(1.0)); + Push!("text_size")(text_size); + + BuildItem(input, UISize(ST.Percentage, 1.0), UISize(ST.Pixels, text_size), UIF.DrawText); + + EndContainer(); + + Pop!("color"); + Pop!("padding"); + + return input; +} + +void +CommandPalette(u8[] text) { Vec2 size = RootSize(); - f32 x = size.x*0.3; f32 y = size.y*0.2; f32 w = size.x*0.4; f32 h = size.y*0.3; - Logf("%s %s %s %s %s", size.v, x, y, w, h); + Push!("border_thickness")(2.0); + Push!("color")(Vec4(0.2, 0.5, 0.65, 1.0)); + Push!("border_color")(Vec4(0.08, 0.3, 0.40, 1.0)); + Push!("corner_radius")(4.0); + Push!("edge_softness")(0.08); UIItem* window = Window(CastStr!(u8)("##cmd_palette"), x, y, w, h); - return window; + UIItem* text_box = TextInput(text, CastStr!(u8)("###cmd_palette_input"), w*0.1, y*0.2, 0.8, 16.0, Vec4(Vec3(0.0), 1.0)); + + EndWindow(); + + Pop!("border_thickness"); + Pop!("border_color"); + Pop!("corner_radius"); + Pop!("edge_softness"); + Pop!("color"); } UIItem* @@ -487,11 +527,19 @@ Window(u8[] id, f32 x, f32 y, f32 w, f32 h) BuildItem(item, UISize(ST.Pixels, x), UISize(ST.Pixels, y), UIF.Window|UIF.DrawBackground|UIF.DrawBorder); - Pop!("offset")(); + Pop!("offset"); + + PushParent(item); return item; } +void +EndWindow() +{ + PopParent(); +} + void EndPanel() { diff --git a/src/shaders/gui.frag.glsl b/src/shaders/gui.frag.glsl index 665ae18..03adc64 100644 --- a/src/shaders/gui.frag.glsl +++ b/src/shaders/gui.frag.glsl @@ -75,7 +75,6 @@ void main() if(in_has_texture != 0) { tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FD.uv); - //tex_color = pow(tex_color, gamma); } vec4 color = ToLinear(FD.color);