code cleanup, fixes and start work on reimplementing scroll animation

This commit is contained in:
Matthew 2025-10-18 20:02:54 +11:00
parent 9b6c56c41a
commit d739893046
3 changed files with 226 additions and 175 deletions

View File

@ -11,6 +11,7 @@ struct FlatBuffer
Tokenizer tk; Tokenizer tk;
Arena arena; Arena arena;
Arena ls_arena; Arena ls_arena;
LineBuffers linebufs;
u8[] file_name; u8[] file_name;
@ -18,16 +19,17 @@ struct FlatBuffer
u8* pbuf; u8* pbuf;
u64 length; u64 length;
LineStart[] lines; Line[] lines;
u64 line_count; u64 line_count;
i64 pos; i64 pos;
i64 line_offset; i64 col_pos;
i64 rows;
I64Vec2 sel; I64Vec2 sel;
SelectMode sel_mode; SelectMode sel_mode;
f32 view_width;
bool dirty; bool dirty;
} }
@ -40,7 +42,7 @@ enum SelectMode
alias SM = SelectMode; alias SM = SelectMode;
struct LineStart struct Line
{ {
u64 pos; u64 pos;
u64 length; u64 length;
@ -107,6 +109,9 @@ const bool[128] SYM_TOKENS = [
';': true, ';': true,
]; ];
const LineBuffer g_nil_line_buf;
LineBuffer* g_NIL_LINE_BUF;
const u64 SPACING = 2; const u64 SPACING = 2;
const u64 BUF_START = 1; const u64 BUF_START = 1;
@ -118,6 +123,8 @@ CreateFlatBuffer(u8[] data, u8[] file_name)
ls_arena: CreateArena(KB(512)), ls_arena: CreateArena(KB(512)),
}; };
g_NIL_LINE_BUF = cast(LineBuffer*)&g_nil_line_buf;
Init(&fb, data, file_name); Init(&fb, data, file_name);
fb.tk = CreateTokenizer(&fb); fb.tk = CreateTokenizer(&fb);
Fix(&fb); Fix(&fb);
@ -137,6 +144,7 @@ Init(FlatBuffer* fb, u8[] data, u8[] file_name)
fb.length = data.length; fb.length = data.length;
fb.sel = -1; fb.sel = -1;
fb.sel_mode = SM.None; fb.sel_mode = SM.None;
fb.linebufs = CreateLineBuffers(MB(1));
SetBuffers(fb, buf); SetBuffers(fb, buf);
@ -154,6 +162,7 @@ void
Change(FlatBuffer* fb, u8[] data, u8[] file_name) Change(FlatBuffer* fb, u8[] data, u8[] file_name)
{ {
Free(fb._buf); Free(fb._buf);
Reset(&fb.linebufs.arena);
Init(fb, data, file_name); Init(fb, data, file_name);
ResetTokenizer(&fb.tk, fb._buf.length); ResetTokenizer(&fb.tk, fb._buf.length);
@ -199,10 +208,10 @@ Fix(FlatBuffer* fb)
{ {
Reset(&ls_arena); Reset(&ls_arena);
lines = Alloc!(LineStart)(&ls_arena, line_count); lines = Alloc!(Line)(&ls_arena, line_count);
lines[0].pos = 0; lines[0].pos = 0;
LineStart* prev = null; Line* prev = null;
u16 ignore, pending_level, level; u16 ignore, pending_level, level;
u64 ls_idx = 1; u64 ls_idx = 1;
for(u64 i = 0; i < length; i += 1) for(u64 i = 0; i < length; i += 1)
@ -347,8 +356,6 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos)
Fix(fb); Fix(fb);
Reset(&fb.arena); Reset(&fb.arena);
UpdateOffset(fb);
} }
void void
@ -448,52 +455,35 @@ LineLength(FlatBuffer* fb, u64 line)
} }
void void
GetLines(FlatBuffer* fb, LineBuffers* linebufs, u64 length) StartLineBuffer(FlatBuffer* fb, f32 view_width)
{ {
fb.rows = length; Reset(&fb.linebufs.arena);
GetLines(fb, linebufs, fb.line_offset, length); fb.view_width = view_width;
} }
pragma(inline) void LineBuffer*
SliceLineBuffer(FlatBuffer* fb, LineBuffers* lbufs, LineStart* ls) GetLine(FlatBuffer* fb, u64 line)
{ {
LineBuffer* lbuf = Alloc!(LineBuffer)(&lbufs.arena); LineBuffer* lbuf = g_NIL_LINE_BUF;
if(line < fb.lines.length)
{
lbuf = SliceLineBuffer(fb, &fb.lines[line]);
}
return lbuf;
}
pragma(inline) LineBuffer*
SliceLineBuffer(FlatBuffer* fb, Line* ls)
{
LineBuffer* lbuf = Alloc!(LineBuffer)(&fb.linebufs.arena);
lbuf.text = fb.pbuf[ls.pos .. ls.pos+ls.length]; lbuf.text = fb.pbuf[ls.pos .. ls.pos+ls.length];
lbuf.style = fb.tk.ptokens[ls.pos .. ls.pos+ls.length]; lbuf.style = fb.tk.ptokens[ls.pos .. ls.pos+ls.length];
lbufs.count += 1; fb.linebufs.count += 1;
SLLPush(lbufs, lbuf, null); return lbuf;
}
void
GetLines(FlatBuffer* fb, LineBuffers* linebufs, u64 start_line, u64 length)
{
assert(linebufs != null, "GetLines failure: linebufs is null");
Reset(&linebufs.arena);
linebufs.first = linebufs.last = null;
linebufs.count = 0;
u64 total_lines = fb.lines.length;
linebufs.start = Min(start_line, total_lines);
linebufs.end = Min(start_line + length, total_lines);
if(fb.length == 0)
{
SliceLineBuffer(fb, linebufs, &fb.lines[0]);
}
else if(linebufs.start == linebufs.end) with(fb)
{
SliceLineBuffer(fb, linebufs, &lines[linebufs.start]);
}
else with(linebufs)
{
for(u64 i = start; i < end; i += 1)
{
SliceLineBuffer(fb, linebufs, &fb.lines[i]);
}
}
} }
void void
@ -542,6 +532,7 @@ MoveUp(FlatBuffer* fb, u64 col)
{ {
u64 end = fb.lines[line].pos-1; u64 end = fb.lines[line].pos-1;
line -= 1; line -= 1;
col = Max(col, fb.col_pos);
fb.pos = Min(fb.lines[line].pos+col, end); fb.pos = Min(fb.lines[line].pos+col, end);
} }
} }
@ -561,6 +552,7 @@ MoveDown(FlatBuffer* fb, u64 col)
line += 1; line += 1;
fb.pos = fb.lines[line].pos; fb.pos = fb.lines[line].pos;
u64 end = fb.lines.length > line+1 ? fb.lines[line+1].pos-1 : fb.length; u64 end = fb.lines.length > line+1 ? fb.lines[line+1].pos-1 : fb.length;
col = Max(col, fb.col_pos);
fb.pos = Min(fb.pos+col, end); fb.pos = Min(fb.pos+col, end);
} }
} }
@ -875,7 +867,11 @@ Move(FlatBuffer* fb, Input key, Modifier md)
} }
} }
UpdateOffset(fb); if(key == Input.Left || key == Input.Right)
{
fb.col_pos = LinePos(fb, fb.pos);
}
UpdateSelection(fb); UpdateSelection(fb);
Logf("selection %s", fb.sel.v); Logf("selection %s", fb.sel.v);
@ -897,30 +893,6 @@ UpdateSelection(FlatBuffer* fb)
} }
} }
void
UpdateOffset(FlatBuffer* fb)
{
if(fb.rows > 0) with(fb)
{
i64 screen_pos = CurrentLine(fb) - line_offset;
i64 start = 0;
i64 end = rows-2;
Logf("p %s start %s end %s", screen_pos, start, end);
if(line_offset > 0 && screen_pos < start)
{
line_offset += screen_pos;
Logf("scroll up %s", line_offset);
}
else if(screen_pos > end)
{
line_offset += screen_pos - end;
Logf("scroll down %s", line_offset);
}
}
assert(fb.line_offset <= fb.line_count);
}
void void
Backspace(FlatBuffer* fb) Backspace(FlatBuffer* fb)
{ {

View File

@ -51,14 +51,12 @@ struct Editor
FlatBuffer buf; FlatBuffer buf;
Tokenizer tk; Tokenizer tk;
LineBuffers linebufs;
Vec2 cursor_pos; Vec2 cursor_pos;
Vec2 select_start; Vec2 select_start;
Vec2 select_end; Vec2 select_end;
f32 text_size; f32 text_size;
u64 line_offset;
} }
struct ChangeStacks struct ChangeStacks
@ -161,24 +159,6 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
} }
EndUI(); EndUI();
/*
if(ctx.state == ES.CmdOpen)
{
if(ctx.cmd.commands.length == 0 && ctx.cmd.icount == 0)
{
GetCommands(&ctx.cmd);
}
CommandPalette(&ctx.cmd);
}
DrawPanels(ctx.base_panel);
*/
//EndBuild();
// UI Functions Before This Point
} }
@ -245,6 +225,10 @@ CreatePanel(EditorCtx* ctx, SizeType size_type = ST.Percentage)
p.axis = A2D.Y; p.axis = A2D.Y;
p.id = Alloc!(u8)(&ctx.arena, 10); p.id = Alloc!(u8)(&ctx.arena, 10);
p.pct = 1.0; p.pct = 1.0;
p.scroll_offset = 0.0;
p.scroll_target = 0.0;
p.scroll_begin = -1.0;
(cast(char[])p.id).sformat("##%08s", ctx.panel_id); (cast(char[])p.id).sformat("##%08s", ctx.panel_id);
p.parent = p.first = p.last = p.next = p.prev = g_UI_NIL_PANEL; p.parent = p.first = p.last = p.next = p.prev = g_UI_NIL_PANEL;
@ -395,7 +379,6 @@ CreateEditor(EditorCtx* ctx)
ed.arena = CreateArena(MB(4)); ed.arena = CreateArena(MB(4));
ed.buf = CreateFlatBuffer([], []); ed.buf = CreateFlatBuffer([], []);
ed.linebufs = CreateLineBuffers(MB(1));
return ed; return ed;
} }

View File

@ -9,31 +9,32 @@ import editor;
import std.stdio; import std.stdio;
import std.math.traits : isNaN; import std.math.traits : isNaN;
import std.math.rounding : ceil; import std.math.rounding : ceil;
import std.math.exponential : pow;
import std.format : sformat; import std.format : sformat;
import core.stdc.string : memset; import core.stdc.string : memset;
import core.stdc.math : fabsf; import core.stdc.math : fabsf;
import std.conv; import std.conv;
import core.stdc.stdio : sprintf; import core.stdc.stdio : sprintf;
const Vec4[4] DEFAULT_COL = Vec4(0.13, 0.13, 0.13, 1.0); const Vec4[4] BG_COL = Vec4(0.13, 0.13, 0.13, 1.0);
const Vec4[4] CMD_PALETTE_COL = Vec4(0.21, 0.21, 0.21, 1.0); const Vec4[4] CMD_PALETTE_COL = Vec4(0.21, 0.21, 0.21, 1.0);
const Vec4[4] DEFAULT_BORDER_COL = Vec4(0.254, 0.254, 0.266, 1.0); const Vec4[4] BORDER_COL = Vec4(0.254, 0.254, 0.266, 1.0);
const Vec4[4] HL_BORDER_COL = Vec4(0.035, 0.549, 0.824, 1.0); const Vec4[4] BORDER_COL_HL = Vec4(0.035, 0.549, 0.824, 1.0);
const Vec4[4] LC_COLOR = Vec4(0.12, 0.12, 0.12, 1.0); const Vec4[4] LINECOUNT_COL = Vec4(0.12, 0.12, 0.12, 1.0);
const Vec4[4] LC_HL_COLOR = Vec4(0.012, 0.176, 0.29, 1.0); const Vec4[4] LINECOUNT_COL_HL = Vec4(0.012, 0.176, 0.29, 1.0);
const Vec4[4] CMD_PALETTE_INPUT_HL = Vec4(0.24, 0.45, 0.81, 1.0); const Vec4[4] CMD_BORDER_COL = Vec4(0.003, 0.48, 0.68, 1.0);
const Vec4[4] CMD_INPUT_BORDER_COL = Vec4(0.003, 0.48, 0.68, 1.0); const Vec4[4] CMD_BORDER_COL_HL = Vec4(0.05, 0.56, 0.76, 1.0);
const Vec4[4] CMD_INPUT_BORDER_HL = Vec4(0.05, 0.56, 0.76, 1.0); const Vec4[4] CMD_COL_HL = Vec4(0.24, 0.45, 0.81, 1.0);
const Vec4[4] CMD_PALETTE_INPUT_COL = [ const Vec4[4] CMD_COL = [
Vec4(0.14, 0.14, 0.14, 1.0), Vec4(0.14, 0.14, 0.14, 1.0),
Vec4(0.14, 0.14, 0.14, 1.0), Vec4(0.14, 0.14, 0.14, 1.0),
Vec4(0.17, 0.17, 0.17, 1.0), Vec4(0.17, 0.17, 0.17, 1.0),
@ -44,6 +45,8 @@ const u64 VERTEX_MAX_COUNT = 10000;
// TODO: add setting // TODO: add setting
const f32 TEXT_SIZE = 16.0; const f32 TEXT_SIZE = 16.0;
const f32 SCROLL_SPEED = 48.0;
const f32 LINE_COUNT_PADDING = 4.0;
const UIPanel g_ui_nil_panel; const UIPanel g_ui_nil_panel;
@ -143,6 +146,7 @@ struct UICtx
u8[] font_data; u8[] font_data;
FontFace font; FontFace font;
FontAtlasBuf atlas_buf; FontAtlasBuf atlas_buf;
f32 char_width;
UIBuffer[FRAME_OVERLAP] buffers; UIBuffer[FRAME_OVERLAP] buffers;
@ -153,6 +157,19 @@ struct UICtx
UIPanel* parent; UIPanel* parent;
UIPanel* focused_panel; UIPanel* focused_panel;
f32 corner_radius;
f32 border_thickness;
f32 edge_softness;
Vec4[4] bg_col;
Vec4[4] border_col;
Vec4[4] border_col_hl;
Vec4[4] line_count_col;
Vec4[4] line_count_col_hl;
Vec4[4] cmd_col;
Vec4[4] cmd_col_hl;
Vec4[4] cmd_border_col;
Vec4[4] cmd_border_col_hl;
debug bool dbg; debug bool dbg;
} }
@ -260,7 +277,6 @@ struct UIKey
struct UIPanel struct UIPanel
{ {
AnimState anim;
u8[] id; u8[] id;
Editor* ed; Editor* ed;
@ -278,14 +294,14 @@ struct UIPanel
Rect rect; Rect rect;
Vec2 size; Vec2 size;
}
struct AnimState i64 start_ln;
{ i64 end_ln;
f32 start_value; i64 vis_lines;
f32 end_value; i64 prev_start_ln;
f32 start_time; f32 scroll_offset;
f32 remaining_time; f32 scroll_begin;
f32 scroll_target;
} }
struct TextPart struct TextPart
@ -304,6 +320,19 @@ BeginUI(EditorCtx* edctx, Inputs* inputs)
ctx.f_idx = ctx.frame%FRAME_OVERLAP; ctx.f_idx = ctx.frame%FRAME_OVERLAP;
ctx.inputs = inputs; ctx.inputs = inputs;
ctx.char_width = GlyphWidth(&ctx.atlas_buf.atlas.glyphs['0']);
ctx.corner_radius = 2.0;
ctx.edge_softness = 0.1;
ctx.border_thickness = 2.0;
ctx.bg_col = BG_COL;
ctx.border_col = BORDER_COL;
ctx.border_col_hl = BORDER_COL_HL;
ctx.line_count_col = LINECOUNT_COL;
ctx.line_count_col_hl = LINECOUNT_COL_HL;
ctx.cmd_col = CMD_COL;
ctx.cmd_col_hl = CMD_COL_HL;
ctx.cmd_border_col = CMD_BORDER_COL;
ctx.cmd_border_col_hl = CMD_BORDER_COL_HL;
PrepRendering(ctx); PrepRendering(ctx);
@ -326,6 +355,18 @@ EndUI()
ctx.frame += 1; ctx.frame += 1;
} }
f32
LineCounterWidth(u32 char_width)
{
return f32(char_width)*GetCtx().char_width + LINE_COUNT_PADDING*2.0;
}
Vec2
InnerSize(UIPanel* panel)
{
return panel.size - Vec2(g_ui_ctx.border_thickness*2.0);
}
void void
SetPanelSizes(UIPanel* panel) SetPanelSizes(UIPanel* panel)
{ {
@ -357,14 +398,11 @@ SetPanelSizes(UIPanel* panel)
} }
pragma(inline) void pragma(inline) void
DrawChar(FontAtlas* atlas, u8 ch, f32* x_pos, f32 y, Vec4 col = Vec4(1.0)) DrawChar(u8 ch, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
{ {
if(ch < atlas.glyphs.length) Glyph* g = GetGlyph(ch);
{
Glyph* g = atlas.glyphs.ptr + ch;
DrawGlyph(g, 1.0, x_pos, y, col); DrawGlyph(g, 1.0, x_pos, y, col);
} }
}
bool bool
PrintInputs() PrintInputs()
@ -381,6 +419,58 @@ PrintInputs()
return result; return result;
} }
f32
EaseOutQuint(f32 x)
{
return 1.0 - pow(1.0 - x, 5);
}
void
SetScrollOffset(UIPanel* panel)
{
U64Vec2 pos = VecPos(&panel.ed.buf);
if(pos.y > 0)
{
Logf("y %s start %s end %s prev %s", pos.y, panel.start_ln, panel.end_ln, panel.prev_start_ln);
}
if((pos.y < panel.start_ln || pos.y > panel.end_ln))
{
f32 off = f32(panel.start_ln - panel.prev_start_ln)*TEXT_SIZE;
panel.scroll_target += off;
panel.prev_start_ln = panel.start_ln;
if(panel.scroll_begin == -1.0)
{
panel.scroll_begin = panel.scroll_offset;
}
}
if(panel.scroll_begin != -1.0)
{
f32 min, max;
if(panel.scroll_offset > panel.scroll_target)
{
min = panel.scroll_target;
max = panel.scroll_offset;
}
else
{
min = panel.scroll_offset;
max = panel.scroll_target;
}
panel.scroll_offset = EaseOutQuint(Remap(panel.scroll_offset, min, max, 0.0, 1.0)) * g_delta;
if(panel.scroll_offset - panel.scroll_target < 0.0009)
{
panel.scroll_offset = panel.scroll_target;
panel.scroll_begin = -1.0;
}
}
}
void void
Panel(UIPanel* panel) Panel(UIPanel* panel)
{ {
@ -428,67 +518,62 @@ Panel(UIPanel* panel)
SetFocusedPanel(panel); SetFocusedPanel(panel);
} }
i64 rows = cast(i64)ceil(panel.size.y/TEXT_SIZE); Vec2 inner = InnerSize(panel);
GetLines(&ed.buf, &ed.linebufs, rows); panel.start_ln = cast(u64)(floor(panel.scroll_offset/TEXT_SIZE));
panel.end_ln = panel.start_ln + cast(u64)(ceil(inner.y/TEXT_SIZE));
panel.vis_lines = panel.end_ln - panel.start_ln;
char[64] ch_buf = '\0'; char[64] ch_buf = '\0';
char[] fmt = ch_buf.sformat("%%0%ss", u64(ed.linebufs.end.toChars().length)); char[] fmt = ch_buf.sformat("%%0%ss", u64(panel.end_ln.toChars().length));
u8[] end_line_text = ScratchAlloc!(u8)(ed.linebufs.end.toChars().length, '0'); f32 lc_w = panel.end_ln.toChars().length*ctx.char_width + LINE_COUNT_PADDING*2.0;
f32 code_view_width = inner.x-lc_w;
f32 lcw = CalcTextWidth(end_line_text); StartLineBuffer(&panel.ed.buf, code_view_width);
f32 padding = 4.0;
f32 border = 2.0, radius = 2.0, softness = 0.1; //SetScrollOffset(panel);
DrawRect(panel.rect.vec0, panel.size, radius, border, DEFAULT_COL); U64Vec2 pos = VecPos(&ed.buf);
DrawRect(panel.rect.vec0, Vec2(lcw+padding*2, panel.size.y), 0.0, 0.0, focused ? LC_HL_COLOR : LC_COLOR);
DrawBorder(panel.rect.vec0, panel.size, border, radius, softness, focused ? HL_BORDER_COL : DEFAULT_BORDER_COL); DrawPanel(panel, lc_w, focused);
f32 x = panel.rect.x0; f32 x = panel.rect.x0;
f32 y = panel.rect.y0 + TEXT_SIZE; f32 y = panel.rect.y0 + TEXT_SIZE - (panel.scroll_offset % TEXT_SIZE);
f32 code_view_width = panel.size.x-lcw-border*2.0-padding*2.0; u64 i = panel.start_ln;
FontAtlas* atlas = &ctx.atlas_buf.atlas; for(auto buf = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, buf) && i < panel.end_ln; i += 1, buf = GetLine(&ed.buf, i))
bool edit = EditModeActive();
U64Vec2 pos = VecPos(&ed.buf);
u64 i;
for(auto buf = ed.linebufs.first; buf != null; buf = buf.next, i += 1)
{ {
f32 x_pos = x + padding; f32 x_pos = x + LINE_COUNT_PADDING;
DrawLineCount(fmt, &x_pos, y, i);
DrawLineCount(atlas, fmt, &x_pos, y, ed.linebufs.start+i);
x_pos += padding;
u64 ch_offset; u64 ch_offset;
auto parts = MakeMultiline(buf.text, code_view_width, buf.style); auto parts = MakeMultiline(buf.text, code_view_width, buf.style);
if(parts == null) if(parts == null)
{ {
if(pos.y == ed.buf.line_offset+i) if(pos.y == i)
{ {
DrawCursor(atlas, [], 0, x+lcw+padding*2.0, y, ch_offset, edit); DrawCursor([], 0, x+lc_w, y, ch_offset);
} }
} }
else for(auto n = parts; n != null; n = n.next) else for(auto n = parts; n != null; n = n.next)
{ {
auto l = &n.value; auto l = &n.value;
if(pos.y == ed.buf.line_offset+i) if(pos.y == i)
{ {
DrawCursor(atlas, l.text, pos.x, x+lcw+padding*2.0, y, ch_offset, edit); DrawCursor(l.text, pos.x, x+lc_w, y, ch_offset);
} }
foreach(j; 0 .. l.text.length) foreach(j; 0 .. l.text.length)
{ {
bool hl = pos.y == i && !edit && j == pos.x-ch_offset; bool hl = pos.y == i && !EditModeActive() && j == pos.x-ch_offset;
DrawChar(atlas, l.text[j], &x_pos, y, hl ? Vec4(Vec3(0.0), 1.0) : SYNTAX_COLORS[l.style[j]]); DrawChar(l.text[j], &x_pos, y, hl ? Vec4(Vec3(0.0), 1.0) : SYNTAX_COLORS[l.style[j]]);
} }
y += TEXT_SIZE; y += TEXT_SIZE;
x_pos = x + lcw + padding*2.0; x_pos = x + lc_w + LINE_COUNT_PADDING*2.0;
ch_offset += l.text.length; ch_offset += l.text.length;
} }
} }
@ -496,7 +581,7 @@ Panel(UIPanel* panel)
} }
pragma(inline) void pragma(inline) void
DrawCursor(FontAtlas* atlas, u8[] text, u64 ch_x, f32 x, f32 y, u64 offset, bool edit) DrawCursor(u8[] text, u64 ch_x, f32 x, f32 y, u64 offset)
{ {
Glyph* g = GetGlyph(' '); Glyph* g = GetGlyph(' ');
foreach(j; 0 .. text.length) foreach(j; 0 .. text.length)
@ -511,19 +596,21 @@ DrawCursor(FontAtlas* atlas, u8[] text, u64 ch_x, f32 x, f32 y, u64 offset, bool
x += GlyphWidth(g); x += GlyphWidth(g);
} }
DrawRect(x, y, atlas, cast(u8)g.ch, Vec4(1.0), edit); DrawRect(x, y, cast(u8)g.ch, Vec4(1.0), EditModeActive());
} }
pragma(inline) void pragma(inline) void
DrawLineCount(FontAtlas* atlas, char[] fmt, f32* x_pos, f32 y, u64 line) DrawLineCount(char[] fmt, f32* x_pos, f32 y, u64 line)
{ {
char[32] line_buf = '\0'; char[32] line_buf = '\0';
char[] line_str = sformat(line_buf, fmt, line+1); char[] line_str = sformat(line_buf, fmt, line+1);
foreach(j; 0 .. line_str.length) foreach(j; 0 .. line_str.length)
{ {
DrawChar(atlas, line_str[j], x_pos, y, Vec4(1.0)); DrawChar(line_str[j], x_pos, y, Vec4(1.0));
} }
*x_pos += LINE_COUNT_PADDING;
} }
void void
@ -541,9 +628,7 @@ CommandPalette(CmdPalette* cmd)
f32 w = size.x*0.7; f32 w = size.x*0.7;
f32 h = 40.0; f32 h = 40.0;
f32 corner_r = 2.0, edge_softness = 0.1, border_thickness = 2.0; DrawCmdRect(Vec2(x, y), Vec2(w, h), false);
DrawBorderedRect(Vec2(x, y), Vec2(w, h), border_thickness, corner_r, edge_softness, CMD_PALETTE_INPUT_COL, CMD_INPUT_BORDER_COL);
f32 y_off = h*0.5 + 6; f32 y_off = h*0.5 + 6;
f32 ch_x = x + 6.0; f32 ch_x = x + 6.0;
@ -551,7 +636,7 @@ CommandPalette(CmdPalette* cmd)
foreach(i; 0 .. text.length) foreach(i; 0 .. text.length)
{ {
DrawChar(&ctx.atlas_buf.atlas, text[i], &ch_x, ch_y, Vec4(1.0)); DrawChar(text[i], &ch_x, ch_y, Vec4(1.0));
} }
for(u64 i = 0; i < options.length; i += 1) for(u64 i = 0; i < options.length; i += 1)
@ -560,19 +645,11 @@ CommandPalette(CmdPalette* cmd)
ch_x = x + 6.0; ch_x = x + 6.0;
ch_y = y + y_off; ch_y = y + y_off;
DrawBorderedRect( DrawCmdRect(Vec2(x, y), Vec2(w, h), cmd.selected == i);
Vec2(x, y),
Vec2(w, h),
border_thickness,
corner_r,
edge_softness,
cmd.selected == i ? CMD_PALETTE_INPUT_HL : CMD_PALETTE_INPUT_COL,
cmd.selected == i ? CMD_INPUT_BORDER_HL : CMD_INPUT_BORDER_COL
);
foreach(j; 0 .. options[i].length) foreach(j; 0 .. options[i].length)
{ {
DrawChar(&ctx.atlas_buf.atlas, options[i][j], &ch_x, ch_y, Vec4(1.0)); DrawChar(options[i][j], &ch_x, ch_y, Vec4(1.0));
} }
if(y+h > size.y+h) break; if(y+h > size.y+h) break;
@ -1136,10 +1213,28 @@ GetVertex(UICtx* ctx)
} }
pragma(inline) void pragma(inline) void
DrawBorderedRect(Vec2 pos, Vec2 size, f32 border, f32 radius, f32 softness, Vec4[4] cols, Vec4[4] border_col) DrawCmdRect(Vec2 pos, Vec2 size, bool edit)
{ {
DrawRect(pos, size, radius, border, cols); UICtx* ctx = GetCtx();
DrawBorder(pos, size, border, radius, softness, border_col);
Vec4[4] bg_col = edit ? ctx.cmd_col_hl : ctx.cmd_col;
Vec4[4] border_col = edit ? ctx.cmd_border_col_hl : ctx.cmd_border_col;
DrawRect(pos, size, ctx.corner_radius, ctx.border_thickness, bg_col);
DrawBorder(pos, size, ctx.border_thickness, ctx.corner_radius, ctx.edge_softness, border_col);
}
pragma(inline) void
DrawPanel(UIPanel* panel, f32 lc_w, bool focus)
{
UICtx* ctx = GetCtx();
Vec2 pos = panel.rect.vec0;
Vec2 size = panel.size;
DrawRect(pos, size, ctx.corner_radius, ctx.border_thickness, ctx.bg_col);
DrawRect(pos, Vec2(lc_w, size.y), 0.0, 0.0, focus ? ctx.line_count_col_hl : ctx.line_count_col);
DrawBorder(pos, size, ctx.border_thickness, ctx.corner_radius, ctx.edge_softness, focus ? ctx.border_col_hl : ctx.border_col);
} }
pragma(inline) Glyph* pragma(inline) Glyph*
@ -1150,7 +1245,7 @@ GetGlyph(u8 ch)
} }
pragma(inline) void pragma(inline) void
DrawRect(f32 x, f32 y, FontAtlas* atlas, u8 ch, Vec4 col, bool edit_mode) DrawRect(f32 x, f32 y, u8 ch, Vec4 col, bool edit_mode)
{ {
Glyph* g = GetGlyph(ch); Glyph* g = GetGlyph(ch);
Vec4[4] cols = col; Vec4[4] cols = col;
@ -1158,9 +1253,10 @@ DrawRect(f32 x, f32 y, FontAtlas* atlas, u8 ch, Vec4 col, bool edit_mode)
} }
pragma(inline) void pragma(inline) void
DrawRect(Vec2 pos, Vec2 size, f32 corner_radius, f32 border, Vec4[4] cols) DrawRect(Vec2 pos, Vec2 size, f32 corner_radius, f32 border_thickness, Vec4[4] cols)
{ {
DrawRect(pos.x, pos.y, size.x, size.y, corner_radius, border, cols); UICtx* ctx = GetCtx();
DrawRect(pos.x, pos.y, size.x, size.y, corner_radius, border_thickness, cols);
} }
void void