delete unneccessary code

This commit is contained in:
Matthew 2025-10-12 18:29:42 +11:00
parent 3ad296ba0f
commit e3ee79c3e8
3 changed files with 429 additions and 2020 deletions

View File

@ -3,9 +3,8 @@ import dlib;
import vulkan;
import std.format : sformat;
import buffer;
import ui : Nil;
import ui;
import widgets : Nil;
import widgets;
import parsing;
import std.format;
@ -148,7 +147,17 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
for(auto p = ctx.base_panel; !Nil(p); p = Recurse(p))
{
Panel2(p);
Panel(p);
}
if(ctx.state == ES.CmdOpen)
{
if(ctx.cmd.commands.length == 0 && ctx.cmd.icount == 0)
{
GetCommands(&ctx.cmd);
}
CommandPalette(&ctx.cmd);
}
EndUI();

File diff suppressed because it is too large Load Diff

View File

@ -1,986 +0,0 @@
import dlib;
import vulkan;
import buffer;
import ui : Nil;
import ui;
import parsing;
import editor;
import std.format : sformat;
import std.math.rounding : ceil, floor;
import std.math.exponential : pow;
import core.stdc.math : fabsf;
import std.conv;
import core.stdc.stdio : sprintf;
const Vec4[4] DEFAULT_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] DEFAULT_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] LC_COLOR = 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] CMD_PALETTE_INPUT_HL = Vec4(0.24, 0.45, 0.81, 1.0);
const Vec4[4] CMD_INPUT_BORDER_COL = Vec4(0.003, 0.48, 0.68, 1.0);
const Vec4[4] CMD_INPUT_BORDER_HL = Vec4(0.05, 0.56, 0.76, 1.0);
const Vec4[4] CMD_PALETTE_INPUT_COL = [
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),
];
// TODO: add setting
const f32 TEXT_SIZE = 16.0;
const UIPanel g_ui_nil_panel;
UIPanel* g_UI_NIL_PANEL;
UIPanel g_root_panel;
WidgetCtx g_widget_ctx;
struct WidgetCtx
{
UIPanel* parent;
UIPanel* focused_panel;
}
struct UIPanel
{
AnimState anim;
u8[] id;
Editor* ed;
UIPanel* parent;
UIPanel* next;
UIPanel* prev;
UIPanel* first;
UIPanel* last;
UIPanel* list_next;
Axis2D axis;
SizeType size_type;
f32 pct;
Vec4 color;
i64 prev_offset;
i64 start_row;
i64 end_row;
Rect rect;
Vec2 size;
}
struct AnimState
{
f32 start_value;
f32 end_value;
f32 start_time;
f32 remaining_time;
}
struct TextPart
{
UIItem* item;
TextPart* next;
u32 count;
}
UIItem*
Root()
{
Vec2 d = RootSize();
Push!("color")(DEFAULT_COL);
Push!("layout_axis")(A2D.Y);
UIItem* root = Get("##root_item");
BuildItem(root, UISize(ST.Pixels, d.x), UISize(ST.Pixels, d.y), UIF.DrawBackground);
g_root_panel.pct = 1.0;
g_root_panel.axis = A2D.Y;
g_root_panel.color = Vec4(Vec3(0.0), 1.0);
g_root_panel.list_next = g_root_panel.parent = g_root_panel.next = g_root_panel.prev = g_root_panel.first = g_root_panel.last = g_UI_NIL_PANEL;
g_widget_ctx.parent = &g_root_panel;
return root;
}
void
BeginUI(EditorCtx* edctx, Inputs* inputs)
{
UICtx* ctx = GetCtx();
Reset(&ctx.temp_arena);
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
ctx.inputs = inputs;
PrepRendering(ctx);
SetPanelSizes(edctx.base_panel);
}
void
EndUI()
{
UICtx* ctx = GetCtx();
with(ctx)
{
BindBuffers(&rd, &buffers[f_idx].m_idx, &buffers[f_idx].m_vtx);
DrawIndexed(&rd, 6, buffers[f_idx].count, 0);
}
CompleteRendering(ctx);
ctx.frame += 1;
}
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(FontAtlas* atlas, u8 ch, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
{
if(ch < atlas.glyphs.length)
{
Glyph* g = atlas.glyphs.ptr + ch;
DrawGlyph(g, 1.0, x_pos, y, col);
}
}
void
Panel2(UIPanel* panel)
{
UICtx* ctx = GetCtx();
UIItem* item = Get(panel.id);
Editor* ed = panel.ed;
bool focused = GetFocusedPanel() == panel;
UIPanel* parent = panel.parent;
UIPanel* prev = panel.prev;
Axis2D pax = parent.axis;
Vec2 adj = Vec2(
parent.axis == A2D.X ? 10 : 0,
parent.axis == A2D.Y ? 10 : 0
);
Vec2 p0 = panel.rect.vec0-adj;
Vec2 p1 = panel.rect.vec1+adj;
if(!Nil(prev)) with(panel)
{
if(Dragged(item, p0, p1) && item.dragged.v[pax] != 0.0)
{
f32 mov_pct = Remap(item.dragged.v[pax], 0.0, size.v[pax], 0.0, 1.0);
if(CheckPanelBounds(pct + mov_pct) && CheckPanelBounds(panel.prev.pct - mov_pct))
{
pct += mov_pct;
panel.prev.pct -= mov_pct;
}
}
}
if(panel.ed != null)
{
if(Clicked(item, p0, p1))
{
SetFocusedPanel(panel);
}
DrawBorderedRect(panel.rect.vec0, panel.size, 2.0, 2.0, 0.1, DEFAULT_COL, focused ? HL_BORDER_COL : DEFAULT_BORDER_COL);
i64 rows = cast(i64)ceil(panel.size.y/TEXT_SIZE);
GetLines(&ed.buf, &ed.linebufs, rows);
char[64] ch_buf = '\0';
char[] fmt = ch_buf.sformat("%%0%ss", u64(ed.linebufs.end.toChars().length));
u8[] end_line_text = ScratchAlloc!(u8)(ed.linebufs.end.toChars().length, '0');
f32 lcw = CalcTextWidth(end_line_text);
f32 padding = 4.0;
DrawRect(panel.rect.vec0, panel.rect.vec1+Vec2(lcw+padding*2, panel.size.y), 0.0, 0.0, focused ? LC_HL_COLOR : LC_COLOR);
f32 x = panel.rect.x0;
f32 y = panel.rect.y0 + TEXT_SIZE;
FontAtlas* atlas = &ctx.atlas_buf.atlas;
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;
DrawLineCount(atlas, fmt, &x_pos, y, ed.linebufs.start+i);
x_pos += padding;
u64 ch_offset;
auto parts = MakeMultiline(buf.text, panel.size.x-lcw, buf.style);
for(auto n = parts; n != null; n = n.next)
{
auto l = &n.value;
if(pos.y == i)
{
DrawCursor(atlas, l.text, pos.x, x+lcw+padding*2.0, y, ch_offset, edit);
}
foreach(j; 0 .. l.text.length)
{
bool hl = pos.y == i && !edit && 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]]);
}
y += TEXT_SIZE;
x_pos = x + lcw + padding*2.0;
ch_offset += l.text.length;
}
}
}
}
pragma(inline) void
DrawCursor(FontAtlas* atlas, u8[] text, u64 ch_x, f32 x, f32 y, u64 offset, bool edit)
{
Glyph* g = GetGlyph(' ');
foreach(j; 0 .. text.length)
{
bool hl = j == ch_x-offset;
if(hl)
{
break;
}
g = j == text.length-1 ? GetGlyph(' ') : GetGlyph(text[j]);
x += GlyphWidth(g);
}
DrawRect(x, y, atlas, cast(u8)g.ch, Vec4(1.0), edit);
}
pragma(inline) void
DrawLineCount(FontAtlas* atlas, char[] fmt, f32* x_pos, f32 y, u64 line)
{
char[32] line_buf = '\0';
char[] line_str = sformat(line_buf, fmt, line);
foreach(j; 0 .. line_str.length)
{
DrawChar(atlas, line_str[j], x_pos, y, Vec4(1.0));
}
}
f32
LineCounter2(UIPanel* panel, i64 start_row, i64 end_row)
{
UICtx* ctx = GetCtx();
f32 lc_width = 0.0;
f32 padding = 4.0;
UIItem* item = Get(ScratchName(panel.id, "linec"));
u8[] max_line_text;
u8[][] line_counts = ScratchAlloc!(u8[])(end_row-start_row);
u64 width = u64(end_row.toChars().length);
char[32] buf = '\0';
char[] fmt = buf.sformat("%%0%sllu", width);
if(line_counts.length > 0)
{
for(u64 i = 0; start_row+i < end_row; i += 1)
{
line_counts[i] = ScratchAlloc!(u8)(width);
sprintf(cast(char*)line_counts[i].ptr, fmt.ptr, start_row+i);
}
max_line_text = ScratchAlloc!(u8)(width, '0');
}
lc_width = CalcTextWidth(max_line_text) + padding*2.0;
f32 x = panel.rect.x0 + padding;
f32 y = panel.rect.y0 + TEXT_SIZE;
foreach(i; 0 .. line_counts.length)
{
f32 x_pos = x;
foreach(j; 0 .. line_counts[i].length)
{
DrawChar(&ctx.atlas_buf.atlas, line_counts[i][j], &x_pos, y);
}
y += TEXT_SIZE;
}
return lc_width;
}
UIItem*
Panel(UIPanel* panel, UIFlags flags = UIF.None)
{
Push!("color")(DEFAULT_COL);
Push!("layout_axis")(panel.axis);
UIItem* item = Get(panel.id);
UIItem* separator = g_UI_NIL;
UIPanel* parent_pn = panel.parent;
UIItem* next = !Nil(panel.next) ? Get(panel.next.id) : g_UI_NIL;
UIItem* prev = !Nil(panel.prev) ? Get(panel.prev.id) : g_UI_NIL;
UIItem* parent = !Nil(parent_pn) ? Get(parent_pn.id) : PeekParent();
f32 x_pct = 1.0, y_pct = 1.0;
if(!Nil(parent_pn))
{
x_pct = parent_pn.axis == A2D.X ? panel.pct : 1.0;
y_pct = parent_pn.axis == A2D.Y ? panel.pct : 1.0;
}
if(item.signal & UIS.Clicked)
{
SetFocusedPanel(panel);
}
f32 adj_x = 0.0, adj_y = 0.0;
if(!Nil(prev) || !Nil(next))
{
A2D p_axis = parent_pn.axis;
UIS prev_signal = p_axis == A2D.X ? UIS.BorderX0 : UIS.BorderY0;
UIS next_signal = p_axis == A2D.X ? UIS.BorderX1 : UIS.BorderY1;
if(p_axis == A2D.X)
{
flags |= !Nil(prev) ? UIF.BorderX0 : UIF.None;
flags |= !Nil(next) ? UIF.BorderX1 : UIF.None;
}
else
{
flags |= !Nil(prev) ? UIF.BorderY0 : UIF.None;
flags |= !Nil(next) ? UIF.BorderY1 : UIF.None;
}
Signal(item);
f32 p_start = parent.rect.vec0.v[p_axis];
f32 p_end = parent.rect.vec1.v[p_axis];
f32 pos = item.dragged.v[p_axis];
if(!Nil(prev) && item.signal & UIS.DraggedBorder && item.signal & prev_signal && pos != 0.0)
{
f32 pct = Remap(pos, 0.0, p_start-p_end, 0.0, 1.0);
if(CheckPanelBounds(panel.pct - pct) && CheckPanelBounds(panel.prev.pct + pct))
{
panel.pct -= pct;
panel.prev.pct += pct;
}
}
else if(!Nil(next) && item.signal & UIS.DraggedBorder && item.signal & next_signal && pos != 0.0)
{
f32 pct = Remap(pos, 0.0, p_start-p_end, 0.0, 1.0);
if(CheckPanelBounds(panel.next.pct - pct) && CheckPanelBounds(panel.pct + pct))
{
panel.next.pct -= pct;
panel.pct += pct;
}
}
}
BuildItem(item, UISize(ST.Percentage, x_pct), UISize(ST.Percentage, y_pct), UIF.DrawBackground|UIF.DragBorder|flags);
PushParent(item);
Pop!("color", "layout_axis");
return item;
}
UIItem*
LineCounter(u8[] parent_id, FlatBuffer* buf, f32 offset, i64 start_row, i64 end_row, bool focused)
{
f32 padding = 4.0;
Push!("padding")(Vec2(padding, 0.0));
Push!("color")(focused ? LC_HL_COLOR : LC_COLOR);
u8[] id = ScratchName(parent_id, "linec");
u8[] max_row_text;
u8[][] line_counts = ScratchAlloc!(u8[])(end_row-start_row);
u64 width = u64(end_row.toChars().length);
if(line_counts.length > 0)
{
for(u64 i = 0; start_row+i < end_row; i += 1)
{
line_counts[i] = ScratchName(width, parent_id, start_row+i);
}
max_row_text = ScratchAlloc!(u8)(width);
max_row_text[] = cast(u8)'0';
}
UISize s_x = UISize(ST.Pixels, CalcTextWidth(max_row_text) + (padding*2.0));
UISize s_y = UISize(ST.Percentage, 1.0);
UIItem* item = Container(ScratchName(parent_id, "linec"), s_x, s_y, A2D.Y, UIF.DrawBackground);
{
UIItem* inner = Container(ScratchName(parent_id, "lcinner"), s_x, s_y, A2D.Y, UIF.None);
{
for(u64 i = 0; i < line_counts.length; i += 1)
{
if(i == 0)
{
Push!("offset")(Vec2(0.0, offset));
UIItem* line = Text(line_counts[i]);
Pop!("offset");
}
else
{
UIItem* line = Text(line_counts[i]);
}
}
}
EndContainer();
}
EndContainer();
Pop!("padding", "color");
return item;
}
UIItem*
Container(u8[] text, UISize size_x, UISize size_y, Axis2D axis, UIF flags = UIF.None)
{
Push!("layout_axis")(axis);
UIItem* item = Get(text);
BuildItem(item, size_x, size_y, flags);
PushParent(item);
Pop!("layout_axis");
return item;
}
void
EndContainer()
{
PopParent();
}
UIItem*
Text(u8[] text)
{
UIItem* item = Get(text);
f32 width = CalcTextWidth(item.key.text);
BuildItem(item, UISize(ST.Pixels, width), UISize(ST.Pixels, 16.0), UIF.DrawText);
return item;
}
void
SetPanelScroll(UIPanel* panel, i64 rows, f32 text_size)
{
i64 low = panel.prev_offset < panel.ed.buf.offset ? panel.prev_offset : panel.ed.buf.offset;
i64 high = panel.prev_offset < panel.ed.buf.offset ? panel.ed.buf.offset + rows : panel.prev_offset + rows;
panel.start_row = low;
panel.end_row = high;
f32 start = panel.anim.start_value;
f32 end = panel.anim.end_value;
f32 offset = (panel.prev_offset-panel.ed.buf.offset) * text_size;
if(offset > 0.0)
{
end = -offset;
}
else
{
start = offset;
}
with(panel.anim)
{
start_value = start;
end_value = end;
start_time = 0.1;
remaining_time = remaining_time > 0.05 ? 0.04 : 0.1;
panel.prev_offset = panel.ed.buf.offset;
}
}
f32
EaseOutExp(f32 v)
{
return fabsf(1.0 - v) <= 0.00009 ? 1.0 : 1.0 - pow(2, -10 * v);
}
void
EditorView(UIPanel* panel)
{
bool focused = panel == GetFocusedPanel();
UICtx* ctx = GetCtx();
Editor* ed = panel.ed;
Push!("border_thickness")(2.0);
Push!("border_color")(focused ? HL_BORDER_COL : DEFAULT_BORDER_COL);
UIItem* item = Panel(panel, UIF.Clickable|UIF.DeferredBorder);
{
Pop!("border_thickness", "border_color");
Container(ScratchName(panel.id, "cntr"), UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0), A2D.X);
{
f32 text_size = 16.0;
f32 height = 0.0;
i64 rows = cast(i64)ceil(item.size.y/text_size);
if(ed.buf.rows != rows)
{
ed.buf.rows = rows;
}
if(panel.prev_offset != ed.buf.offset)
{
SetPanelScroll(panel, rows, text_size);
}
f32 offset = 0.0;
i64 line_offset = ed.buf.offset;
i64 line_rows = rows;
if(panel.anim.remaining_time > 0.0) with(panel.anim)
{
remaining_time -= g_delta;
if(remaining_time < 0.0)
{
remaining_time = 0.0;
}
offset = Remap(remaining_time, 0.0, start_time, 0.0, 1.0);
offset = Remap(EaseOutExp(offset), 0.0, 1.0, start_value, end_value);
line_offset = panel.start_row;
line_rows = panel.end_row-panel.start_row;
GetLines(&ed.buf, &ed.linebufs, panel.start_row, panel.end_row-panel.start_row);
if(remaining_time == 0.0)
{
start_value = end_value = start_time = 0.0;
panel.start_row = panel.end_row = -1;
}
}
else
{
GetLines(&ed.buf, &ed.linebufs, rows);
}
UIItem* lc = LineCounter(panel.id, &panel.ed.buf, offset, line_offset, line_offset+line_rows, focused);
Container(ScratchName(panel.id, "lines"), UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0), A2D.Y);
{
I64Vec2 sel = ed.buf.sel;
if(sel.x > sel.y)
{
i64 t = sel.y;
sel.y = sel.x;
sel.x = t;
}
U64Vec2 pos = VecPos(&ed.buf);
SelectMode sm = ed.buf.sel_mode;
u64 i = 0;
for(LineBuffer* buf = ed.linebufs.first; buf != null; buf = buf.next, i += 1)
{
if(buf == ed.linebufs.first)
{
Push!("offset")(Vec2(0.0, offset));
}
if(buf.text.length > 0)
{
i64 line_no = i+line_offset;
if(sm == SM.Line && line_no >= sel.x && line_no <= sel.y)
{
}
TextPart* tp = WrappedTextLine(buf.text, panel.id, text_size, line_no, buf.style, &pos, focused);
height += (text_size * tp.count);
if(TextClicked(tp))
{
SetFocusedPanel(panel);
}
}
if(buf == ed.linebufs.first)
{
Pop!("offset");
}
}
}
EndContainer();
}
EndContainer();
}
EndPanel();
if(item.signal & UIS.Clicked)
{
SetFocusedPanel(panel);
}
}
bool
TextClicked(TextPart* text_part)
{
bool result = false;
alias result res;
for(TextPart* tp = text_part; !Nil(tp.item); tp = tp.next)
{
if(tp.item.signal & UIS.Clicked)
{
res = true;
break;
}
}
return res;
}
TextPart*
WrappedTextLine(u8[] text, u8[] parent_id, f32 text_size, u64 line_no, TS[] style = [], U64Vec2* hl_pos, bool focused)
{
/*
Push!("color")(Vec4(1.0));
Push!("text_size")(text_size);
UIItem* parent = PeekParent();
TextPart* part = ScratchAlloc!(TextPart)();
part.item = g_UI_NIL;
i64 hl = -1;
if(hl_pos.y == line_no)
{
hl = hl_pos.x;
}
f32 parent_width = parent.size.x - (parent.border_thickness * 2);
Logf("w %f", parent_width);
u64 chars;
TextPart* tp = part;
Node!(TextBuffer)* lines = MakeMultiline(text, parent_width, parent_id, line_no, style);
for(Node!(TextBuffer)* line = lines; line != null; line = line.next, tp = tp.next)
{
part.count += 1;
tp.item = Get(line.value.text);
tp.next = ScratchAlloc!(TextPart)();
tp.next.item = g_UI_NIL;
tp.item.token_styles = line.value.style;
if(focused && hl >= 0)
{
if(hl <= tp.item.key.text.length)
{
Push!("highlighted_char")(hl);
hl = -1;
}
else
{
hl -= tp.item.key.text.length;
}
}
Signal(tp.item);
if(tp.item.signal & UIS.Clicked)
{
ClickedCharIndex(tp.item);
}
BuildItem(tp.item, UISize(ST.Percentage, 1.0), UISize(ST.Pixels, text_size), UIF.DrawText|UIF.Clickable|UIF.Draggable);
Push!("highlighted_char")(-1);
}
Pop!("color");
return part;
*/
return null;
}
UIItem*
TextInput(u8[] text, u8[] hash, f32 x, f32 y, f32 w_pct, f32 h, f32 text_size, Vec4[4] bg_cols, Vec4[4] border_col)
{
UIItem* input = Get(ScratchName(text, hash));
Push!("padding")(Vec2(6.0, (h-(text_size))*0.5)-2.0);
Push!("offset")(Vec2(x, y));
Push!("border_color")(border_col);
Push!("color")(bg_cols);
Container(ScratchName(hash, "_cntr"), UISize(ST.Percentage, w_pct), UISize(ST.Pixels, h), A2D.Y, UIF.DrawBackground|UIF.DrawBorder);
Pop!("color", "offset", "border_color");
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", "padding");
return input;
}
void
CommandPalette(CmdPalette* cmd)
{
u8[] text = cmd.buffer[0 .. cmd.icount];
u8[][] options = cmd.opt_strs;
Vec2 size = RootSize();
f32 x = size.x*0.15;
f32 y = size.y*0.1;
f32 w = size.x*0.7;
f32 h = size.y*0.8;
Push!("color")(CMD_PALETTE_COL);
UIItem* window = Window(CastStr!(u8)("##cmd_palette"), x, y, w, 40.0*(options.length+1));
Push!("corner_radius")(2.0);
Push!("edge_softness")(0.1);
Push!("border_thickness")(2.0);
UIItem* text_box = TextInput(text, CastStr!(u8)("###cmd_palette_input"), 0.0, 0.0, 1.0, 40.0, 16.0, CMD_PALETTE_INPUT_COL, CMD_INPUT_BORDER_COL);
for(u64 i = 0; i < options.length; i += 1)
{
TextInput(
options[i],
ScratchName("###cmd%04s", 10, i),
0.0,
0.0,
1.0,
40.0,
16.0,
i == cmd.selected ? CMD_PALETTE_INPUT_HL : CMD_PALETTE_INPUT_COL,
i == cmd.selected ? CMD_INPUT_BORDER_HL : CMD_INPUT_BORDER_COL
);
}
EndWindow();
Pop!("border_thickness", "corner_radius", "edge_softness", "color");
}
UIItem*
Window(u8[] id, f32 x, f32 y, f32 w, f32 h)
{
UIItem* item = Get(id);
Push!("offset")(Vec2(x, y));
BuildItem(item, UISize(ST.Pixels, w), UISize(ST.Pixels, h), UIF.Window|UIF.DrawBackground|UIF.DrawBorder);
Pop!("offset");
PushParent(item);
return item;
}
void
EndWindow()
{
PopParent();
}
void
EndPanel()
{
PopParent();
}
void
DrawPanels(UIPanel* panel)
{
if(!Nil(panel))
{
debug
{
import core.stdc.math : fabsf;
if(!Nil(panel.first))
{
f32 total = 1.0;
for(UIPanel* child = panel.first; !Nil(child); child = child.next)
{
total -= child.pct;
}
if(total > 0.00009)
{
Logf("%s failed with %f", cast(char[])panel.id, total);
assert(false);
}
}
}
if(panel.ed)
{
EditorView(panel);
}
else
{
Panel(panel);
}
DrawPanels(panel.first);
if(panel.ed == null)
{
EndPanel();
}
DrawPanels(panel.next);
}
}
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)
{
return pct >= 0.0 && pct <= 1.0;
}
void
PushPanel(UIPanel* parent, UIPanel* panel)
{
DLLPush(parent, panel, g_UI_NIL_PANEL);
panel.parent = parent;
}
void
InsertPanel(UIPanel* parent, UIPanel* prev, UIPanel* panel)
{
DLLInsert(parent, panel, prev, g_UI_NIL_PANEL);
panel.parent = prev.parent;
}
void
InitWidgets()
{
g_UI_NIL_PANEL = cast(UIPanel*)&g_ui_nil_panel;
g_widget_ctx.parent = g_UI_NIL_PANEL;
}
void
SetFocusedPanel(UIPanel* panel)
{
if(!CheckNil(g_UI_NIL_PANEL, panel))
{
g_widget_ctx.focused_panel = panel;
SetFocus(Get(panel.id));
}
}
UIPanel*
GetFocusedPanel()
{
return Nil(g_widget_ctx.focused_panel) ? g_UI_NIL_PANEL : g_widget_ctx.focused_panel;
}
bool
Nil(UIPanel* panel)
{
return panel == null || panel == g_UI_NIL_PANEL;
}