more work on ui layout
This commit is contained in:
parent
e30d8f6689
commit
1bbf142039
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
||||
Subproject commit 263cd8435ddd7a1cf67b39c2933e606a891bfe7b
|
||||
Subproject commit a7d571bd5a1bdbe7aa15e5cacfba8795f2e5979b
|
||||
@ -16,7 +16,9 @@ const u8[] FONT_BYTES = import("pc-9800.ttf");
|
||||
const u8[] VERTEX_BYTES = import("gui.vert.spv");
|
||||
const u8[] FRAGMENT_BYTES = import("gui.frag.spv");
|
||||
|
||||
const UI_COUNT = 50000;
|
||||
const UI_COUNT = 5000;
|
||||
|
||||
Editor* g_editor;
|
||||
|
||||
struct Editor
|
||||
{
|
||||
@ -175,11 +177,15 @@ void
|
||||
Cycle(Editor* ed)
|
||||
{
|
||||
Reset(&ed.temp_arena);
|
||||
UIBeginFrame();
|
||||
Logf("begin");
|
||||
UIBeginBuild();
|
||||
Logf("end");
|
||||
|
||||
/*
|
||||
f32 pos = 0.0;
|
||||
f32 h = ed.atlas_buf.atlas.size;
|
||||
DrawBuffer(ed, 0.0, 0.0, h, ed.active_buffer);
|
||||
*/
|
||||
|
||||
BeginFrame(&ed.rd);
|
||||
|
||||
@ -196,6 +202,10 @@ Cycle(Editor* ed)
|
||||
|
||||
Bind(&ed.rd, ed.pipeline, ed.desc_set);
|
||||
|
||||
UIFinishBuild();
|
||||
|
||||
DrawUI();
|
||||
|
||||
FinishRendering(&ed.rd);
|
||||
|
||||
SubmitAndPresent(&ed.rd);
|
||||
|
||||
195
src/editor/ui.d
195
src/editor/ui.d
@ -4,6 +4,7 @@ import dlib.util;
|
||||
import dlib.alloc;
|
||||
import dlib.fonts;
|
||||
import vulkan;
|
||||
import widgets;
|
||||
|
||||
import editor;
|
||||
|
||||
@ -29,6 +30,12 @@ struct UIContext
|
||||
Rect padding;
|
||||
u32 tab_width;
|
||||
f32 text_scale;
|
||||
Stack!(UIItem) parent_stack;
|
||||
}
|
||||
|
||||
struct Stack(T)
|
||||
{
|
||||
T* first;
|
||||
}
|
||||
|
||||
struct UIBuffer
|
||||
@ -43,7 +50,7 @@ struct UIBuffer
|
||||
enum CtxProperty
|
||||
{
|
||||
None,
|
||||
BackgroundColor,
|
||||
BGColor,
|
||||
BorderColor,
|
||||
SizeKind,
|
||||
SizeValue,
|
||||
@ -129,6 +136,7 @@ struct UISize
|
||||
struct UIItem
|
||||
{
|
||||
UIProperties flags;
|
||||
UIKey key;
|
||||
|
||||
UIItem* first;
|
||||
UIItem* last;
|
||||
@ -137,9 +145,12 @@ struct UIItem
|
||||
UIItem* parent;
|
||||
|
||||
UISize[A2D.max] size;
|
||||
Vec4[4] bg_color;
|
||||
Vec4[4] border_color;
|
||||
Rect padding;
|
||||
f32[A2D.max] computed_rel_pos;
|
||||
f32[A2D.max] computed_size;
|
||||
f32[A2D.max] fixed_position;
|
||||
Rect rect;
|
||||
f32 text_scale;
|
||||
}
|
||||
@ -150,14 +161,130 @@ struct UIKey
|
||||
u64 hash;
|
||||
}
|
||||
|
||||
void
|
||||
UIBeginFrame()
|
||||
UIContext*
|
||||
GetCtx()
|
||||
{
|
||||
g_ui_ctx.buffer.count = 0;
|
||||
return &g_ui_ctx;
|
||||
}
|
||||
|
||||
Vec2
|
||||
RootSize()
|
||||
{
|
||||
Vec2 size = GetExtent(GetCtx().rd);
|
||||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
UIFrameSubmit()
|
||||
UIBeginBuild()
|
||||
{
|
||||
UIContext* ui = GetCtx();
|
||||
|
||||
ui.buffer.count = 0;
|
||||
|
||||
ClearStack(&g_ui_ctx.parent_stack, g_UI_NIL);
|
||||
|
||||
ui.root = RootItem();
|
||||
PushParent(ui.root);
|
||||
}
|
||||
|
||||
void
|
||||
UIFinishBuild()
|
||||
{
|
||||
UIContext* ui = GetCtx();
|
||||
|
||||
|
||||
// 1. Pixel/Text sizes (any order)
|
||||
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root))
|
||||
{
|
||||
foreach(i, ref s; item.size)
|
||||
{
|
||||
if (s.kind == SK.Pixels)
|
||||
{
|
||||
item.computed_size[i] = s.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. PercentOfParent (Upward dependant) size (pre-order) (Ignore downward dependant sizes)
|
||||
// 3. ChildrenSum (Downward dependant) (post-order)
|
||||
// 4. Solve violations e.g. extending past boundaries of parent (pre-order)
|
||||
|
||||
// 5. Compute relative positions of each widgets (pre-order)
|
||||
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root))
|
||||
{
|
||||
if (Nil(item.parent))
|
||||
{
|
||||
item.computed_rel_pos = item.fixed_position;
|
||||
|
||||
item.rect.x0 = item.computed_rel_pos[A2D.X];
|
||||
item.rect.y0 = item.computed_rel_pos[A2D.Y];
|
||||
item.rect.x1 = item.computed_size[A2D.X];
|
||||
item.rect.y1 = item.computed_size[A2D.Y];
|
||||
}
|
||||
}
|
||||
|
||||
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root))
|
||||
{
|
||||
if (!Nil(item))
|
||||
{
|
||||
if (item.flags & UIP.DrawBackground)
|
||||
{
|
||||
DrawRect(ui, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UIItem*
|
||||
BuildItem(UIKey key, UIProperties flags)
|
||||
{
|
||||
UIContext* ui = GetCtx();
|
||||
|
||||
UIItem* item = Get(key);
|
||||
item.first = item.last = item.next = item.prev = item.parent = g_UI_NIL;
|
||||
item.computed_rel_pos = item.computed_size = 0;
|
||||
|
||||
|
||||
item.flags = flags;
|
||||
item.size = ui.size_axes;
|
||||
item.padding = ui.padding;
|
||||
|
||||
if (item.flags & UIP.DrawBackground)
|
||||
{
|
||||
item.bg_color = ui.bg_cols;
|
||||
}
|
||||
if (item.flags & UIP.DrawBorder)
|
||||
{
|
||||
item.border_color = ui.border_cols;
|
||||
}
|
||||
if (item.flags & UIP.DrawText)
|
||||
{
|
||||
item.text_scale = ui.text_scale;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void
|
||||
ClearStack(T)(Stack!(T)* stack, T* nil)
|
||||
{
|
||||
while(SPop(stack, nil) != nil) {}
|
||||
}
|
||||
|
||||
void
|
||||
PushParent(UIItem* parent)
|
||||
{
|
||||
SPush(&g_ui_ctx.parent_stack, parent, g_UI_NIL);
|
||||
}
|
||||
|
||||
UIItem*
|
||||
PopParent()
|
||||
{
|
||||
return SPop(&g_ui_ctx.parent_stack, g_UI_NIL);
|
||||
}
|
||||
|
||||
void
|
||||
DrawUI()
|
||||
{
|
||||
BindBuffers(g_ui_ctx.rd, &g_ui_ctx.buffer.mapped_idx, &g_ui_ctx.buffer.mapped_vtx);
|
||||
DrawIndexed(g_ui_ctx.rd, 6, g_ui_ctx.buffer.count, 0);
|
||||
@ -179,6 +306,14 @@ InitUIContext(Renderer* rd)
|
||||
g_ui_ctx.buffer.mapped_idx = idx;
|
||||
g_ui_ctx.buffer.vtx = vtx.data;
|
||||
g_ui_ctx.buffer.idx = idx.data;
|
||||
g_ui_ctx.parent_stack.first = g_UI_NIL;
|
||||
}
|
||||
|
||||
UIKey
|
||||
MakeKey(string str)
|
||||
{
|
||||
u8[] id = (cast(u8*)str)[0 .. str.length];
|
||||
return MakeKey(id);
|
||||
}
|
||||
|
||||
UIKey
|
||||
@ -231,27 +366,18 @@ MakeKey(u8[] id)
|
||||
}
|
||||
|
||||
UIItem*
|
||||
Find(u8[] id)
|
||||
Get(UIKey key)
|
||||
{
|
||||
u64 hash = Hash(id);
|
||||
Result!(UIItem*) result = g_ui_ctx.items[hash];
|
||||
Result!(UIItem*) result = g_ui_ctx.items[key.hash];
|
||||
if (!result.ok)
|
||||
{
|
||||
result.value = Alloc!(UIItem)(&g_ui_ctx.arena);
|
||||
Push(&g_ui_ctx.items, hash, result.value);
|
||||
Push(&g_ui_ctx.items, key.hash, result.value);
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
|
||||
bool
|
||||
UIWindow(Rect rect, f32 border_px, u8[] text)
|
||||
{
|
||||
UIItem* item = Find(text);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
f32
|
||||
CalcTextWidth(u8[] str)
|
||||
{
|
||||
@ -312,25 +438,21 @@ DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
||||
*x_pos += glyph.advance * scale;
|
||||
}
|
||||
|
||||
/*
|
||||
pragma(inline) void
|
||||
DrawRect(UIContext* ctx, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, f32 border, f32 corner, f32 softness, f32 raised, Vec4[4] cols)
|
||||
DrawRect(UIContext* ctx, UIItem* item)
|
||||
{
|
||||
// Y reversed
|
||||
Vertex* v = g_ui_ctx.buffer.vtx.ptr + g_ui_ctx.buffer.count;
|
||||
v.dst_start.x = p0_x;
|
||||
v.dst_start.y = p0_y;
|
||||
v.dst_end.x = p1_x;
|
||||
v.dst_end.y = p1_y;
|
||||
v.cols = cols;
|
||||
v.border_thickness = border;
|
||||
v.corner_radius = corner;
|
||||
v.edge_softness = softness;
|
||||
v.raised = raised;
|
||||
Vertex* v = ctx.buffer.vtx.ptr + ctx.buffer.count;
|
||||
v.dst_start = item.rect.vec0;
|
||||
v.dst_end = item.rect.vec1;
|
||||
v.cols = item.bg_color;
|
||||
v.border_thickness = 0.0;
|
||||
v.corner_radius = 0.0;
|
||||
v.edge_softness = 0.0;
|
||||
v.raised = 0.0;
|
||||
|
||||
AddUIIndices(ctx);
|
||||
AddUIIndices();
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
AddUIIndices()
|
||||
@ -381,10 +503,17 @@ Recurse(alias mode)(UIItem* item, UIItem* root)
|
||||
pragma(inline) void
|
||||
SetProp(alias P, T)(T value)
|
||||
{
|
||||
static if (is(T: Vec4[4]))
|
||||
static if (is(T: Vec4))
|
||||
{
|
||||
static if (0) {}
|
||||
else static if (P == CtxP.BackgroundColor) { g_ui_ctx.bg_cols = value; }
|
||||
else static if (P == CtxP.BGColor) g_ui_ctx.bg_cols = [value, value, value, value];
|
||||
else static if (P == CtxP.BorderColor) g_ui_ctx.border_cols = [value, value, value, value];
|
||||
else static assert(false, "Unknown Property for type Vec4");
|
||||
}
|
||||
else static if (is(T: Vec4[4]))
|
||||
{
|
||||
static if (0) {}
|
||||
else static if (P == CtxP.BGColor) g_ui_ctx.bg_cols = value;
|
||||
else static if (P == CtxP.BorderColor) g_ui_ctx.border_cols = value;
|
||||
else static assert(false, "Unknown Property for type Vec4[4]");
|
||||
}
|
||||
|
||||
19
src/editor/widgets.d
Normal file
19
src/editor/widgets.d
Normal file
@ -0,0 +1,19 @@
|
||||
import dlib;
|
||||
|
||||
import ui;
|
||||
|
||||
UIItem*
|
||||
RootItem()
|
||||
{
|
||||
Vec2 size = RootSize();
|
||||
|
||||
UIKey key = MakeKey("##root_key");
|
||||
|
||||
SetProp!(CtxP.AxisX)(UISize(SK.Pixels, size.x, 1.0));
|
||||
SetProp!(CtxP.AxisY)(UISize(SK.Pixels, size.y, 1.0));
|
||||
SetProp!(CtxP.BGColor)(Vec4(0.2, 0.5, 0.85, 1.0));
|
||||
|
||||
UIItem* item = BuildItem(key, UIP.DrawBackground);
|
||||
|
||||
return item;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user