basic layout system functional
This commit is contained in:
parent
1bbf142039
commit
34b7501007
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit a7d571bd5a1bdbe7aa15e5cacfba8795f2e5979b
|
Subproject commit ad1b167e2b527a2386f7a42e6f908a0f667b5089
|
||||||
@ -4,9 +4,11 @@ import dlib.platform;
|
|||||||
import dlib.fonts;
|
import dlib.fonts;
|
||||||
import vulkan;
|
import vulkan;
|
||||||
import dlib.math;
|
import dlib.math;
|
||||||
|
import std.format : sformat;
|
||||||
import dlib.alloc;
|
import dlib.alloc;
|
||||||
import buffer;
|
import buffer;
|
||||||
import ui;
|
import ui;
|
||||||
|
import widgets;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.exception;
|
import std.exception;
|
||||||
@ -174,12 +176,10 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Cycle(Editor* ed)
|
Cycle(Editor* ed, Inputs* inputs)
|
||||||
{
|
{
|
||||||
Reset(&ed.temp_arena);
|
Reset(&ed.temp_arena);
|
||||||
Logf("begin");
|
|
||||||
UIBeginBuild();
|
UIBeginBuild();
|
||||||
Logf("end");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
f32 pos = 0.0;
|
f32 pos = 0.0;
|
||||||
@ -187,6 +187,36 @@ Cycle(Editor* ed)
|
|||||||
DrawBuffer(ed, 0.0, 0.0, h, ed.active_buffer);
|
DrawBuffer(ed, 0.0, 0.0, h, ed.active_buffer);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
u32 count = 0;
|
||||||
|
static u32 box_count = 1;
|
||||||
|
for(auto ev = inputs.list.first; ev != null; ev = ev.next)
|
||||||
|
{
|
||||||
|
count += 1;
|
||||||
|
Logf("%s", ev.value.key);
|
||||||
|
switch(ev.value.key)
|
||||||
|
{
|
||||||
|
case KBI.One: box_count = 1; break;
|
||||||
|
case KBI.Two: box_count = 2; break;
|
||||||
|
case KBI.Three: box_count = 3; break;
|
||||||
|
case KBI.Four: box_count = 4; break;
|
||||||
|
case KBI.Five: box_count = 5; break;
|
||||||
|
case KBI.Six: box_count = 6; break;
|
||||||
|
case KBI.Seven: box_count = 7; break;
|
||||||
|
case KBI.Eight: box_count = 8; break;
|
||||||
|
case KBI.Nine: box_count = 9; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char[128] buf = 0;
|
||||||
|
f32 x_pct = 1.0/box_count;
|
||||||
|
foreach(i; 0 .. box_count)
|
||||||
|
{
|
||||||
|
buf.sformat("##%s", i);
|
||||||
|
Logf("%r %s %s %f", buf, i, box_count, x_pct);
|
||||||
|
WindowItem(cast(u8[])buf, x_pct, 1.0, Vec4(Vec3(x_pct * i), 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
BeginFrame(&ed.rd);
|
BeginFrame(&ed.rd);
|
||||||
|
|
||||||
UVec2 ext = UVec2(GetExtent(&ed.rd));
|
UVec2 ext = UVec2(GetExtent(&ed.rd));
|
||||||
|
|||||||
@ -30,6 +30,6 @@ void main(string[] argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cycle(&editor);
|
Cycle(&editor, &window.inputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
145
src/editor/ui.d
145
src/editor/ui.d
@ -31,6 +31,7 @@ struct UIContext
|
|||||||
u32 tab_width;
|
u32 tab_width;
|
||||||
f32 text_scale;
|
f32 text_scale;
|
||||||
Stack!(UIItem) parent_stack;
|
Stack!(UIItem) parent_stack;
|
||||||
|
Axis2D layout_axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Stack(T)
|
struct Stack(T)
|
||||||
@ -61,6 +62,7 @@ enum CtxProperty
|
|||||||
Padding,
|
Padding,
|
||||||
TextScale,
|
TextScale,
|
||||||
TabWidth,
|
TabWidth,
|
||||||
|
LayoutAxis,
|
||||||
}
|
}
|
||||||
|
|
||||||
alias CtxP = CtxProperty;
|
alias CtxP = CtxProperty;
|
||||||
@ -108,6 +110,7 @@ alias SK = SizeKind;
|
|||||||
|
|
||||||
union Rect
|
union Rect
|
||||||
{
|
{
|
||||||
|
Vec2[2] v;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
Vec2 vec0;
|
Vec2 vec0;
|
||||||
@ -133,6 +136,13 @@ struct UISize
|
|||||||
f32 strictness;
|
f32 strictness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct UIItemRec
|
||||||
|
{
|
||||||
|
UIItem* next;
|
||||||
|
i32 push_count;
|
||||||
|
i32 pop_count;
|
||||||
|
}
|
||||||
|
|
||||||
struct UIItem
|
struct UIItem
|
||||||
{
|
{
|
||||||
UIProperties flags;
|
UIProperties flags;
|
||||||
@ -153,6 +163,7 @@ struct UIItem
|
|||||||
f32[A2D.max] fixed_position;
|
f32[A2D.max] fixed_position;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
f32 text_scale;
|
f32 text_scale;
|
||||||
|
Axis2D layout_axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIKey
|
struct UIKey
|
||||||
@ -194,7 +205,7 @@ UIFinishBuild()
|
|||||||
|
|
||||||
|
|
||||||
// 1. Pixel/Text sizes (any order)
|
// 1. Pixel/Text sizes (any order)
|
||||||
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root))
|
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root).next)
|
||||||
{
|
{
|
||||||
foreach(i, ref s; item.size)
|
foreach(i, ref s; item.size)
|
||||||
{
|
{
|
||||||
@ -202,34 +213,87 @@ UIFinishBuild()
|
|||||||
{
|
{
|
||||||
item.computed_size[i] = s.value;
|
item.computed_size[i] = s.value;
|
||||||
}
|
}
|
||||||
|
else if (s.kind == SK.TextContent)
|
||||||
|
{
|
||||||
|
// Text size + padding
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. PercentOfParent (Upward dependant) size (pre-order) (Ignore downward dependant sizes)
|
// 2. PercentOfParent (Upward dependant) size (pre-order) (Ignore downward dependant sizes)
|
||||||
// 3. ChildrenSum (Downward dependant) (post-order)
|
u32 count = 0;
|
||||||
// 4. Solve violations e.g. extending past boundaries of parent (pre-order)
|
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root).next)
|
||||||
|
|
||||||
// 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))
|
for(UIItem* child = item.first; !Nil(child); child = child.next)
|
||||||
{
|
{
|
||||||
item.computed_rel_pos = item.fixed_position;
|
foreach(i, ref s; child.size)
|
||||||
|
{
|
||||||
|
if (s.kind == SK.PercentOfParent)
|
||||||
|
{
|
||||||
|
UIItem* fixed_parent = g_UI_NIL;
|
||||||
|
for(UIItem* p = child.parent; !Nil(p); p = p.parent)
|
||||||
|
{
|
||||||
|
if (p.size[i].kind == SK.Pixels || p.size[i].kind == SK.TextContent)
|
||||||
|
{
|
||||||
|
fixed_parent = p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
item.rect.x0 = item.computed_rel_pos[A2D.X];
|
child.computed_size[i] = fixed_parent.computed_size[i] * s.value;
|
||||||
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))
|
// 3. ChildrenSum (Downward dependant) (post-order)
|
||||||
{
|
{
|
||||||
if (!Nil(item))
|
UIItemRec rec;
|
||||||
|
foreach(axis; A2D.min .. A2D.max)
|
||||||
{
|
{
|
||||||
if (item.flags & UIP.DrawBackground)
|
for(UIItem* item = ui.root; !Nil(item); item = rec.next)
|
||||||
{
|
{
|
||||||
DrawRect(ui, item);
|
rec = Recurse!(UIR.PreOrder)(item, ui.root);
|
||||||
|
i32 pop_index = 0;
|
||||||
|
for(UIItem* i = item; !Nil(item) && pop_index <= rec.pop_count; i = i.parent, pop_index += 1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 4. Solve violations e.g. extending past boundaries of parent (pre-order)
|
||||||
|
|
||||||
|
// 5. Compute relative positions of each widgets (pre-order)
|
||||||
|
foreach(axis; A2D.min .. A2D.max)
|
||||||
|
{
|
||||||
|
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root).next)
|
||||||
|
{
|
||||||
|
f32 layout_position = 0.0;
|
||||||
|
|
||||||
|
for(UIItem* child = item.first; !Nil(child); child = child.next)
|
||||||
|
{
|
||||||
|
child.computed_rel_pos[axis] = layout_position;
|
||||||
|
child.rect.vec0.v[axis] = layout_position;
|
||||||
|
child.rect.vec1.v[axis] = layout_position + child.computed_size[axis];
|
||||||
|
|
||||||
|
if (axis == item.layout_axis)
|
||||||
|
{
|
||||||
|
layout_position += child.computed_size[axis];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root).next)
|
||||||
|
{
|
||||||
|
for(UIItem* child = item.first; !Nil(child); child = child.next)
|
||||||
|
{
|
||||||
|
if (!Nil(child))
|
||||||
|
{
|
||||||
|
if (child.flags & UIP.DrawBackground)
|
||||||
|
{
|
||||||
|
DrawRect(ui, child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,10 +308,10 @@ BuildItem(UIKey key, UIProperties flags)
|
|||||||
item.first = item.last = item.next = item.prev = item.parent = g_UI_NIL;
|
item.first = item.last = item.next = item.prev = item.parent = g_UI_NIL;
|
||||||
item.computed_rel_pos = item.computed_size = 0;
|
item.computed_rel_pos = item.computed_size = 0;
|
||||||
|
|
||||||
|
|
||||||
item.flags = flags;
|
item.flags = flags;
|
||||||
item.size = ui.size_axes;
|
item.size = ui.size_axes;
|
||||||
item.padding = ui.padding;
|
item.padding = ui.padding;
|
||||||
|
item.layout_axis = ui.layout_axis;
|
||||||
|
|
||||||
if (item.flags & UIP.DrawBackground)
|
if (item.flags & UIP.DrawBackground)
|
||||||
{
|
{
|
||||||
@ -262,6 +326,12 @@ BuildItem(UIKey key, UIProperties flags)
|
|||||||
item.text_scale = ui.text_scale;
|
item.text_scale = ui.text_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item.parent = ui.parent_stack.first;
|
||||||
|
if (!Nil(item.parent))
|
||||||
|
{
|
||||||
|
DLLPush(item.parent, item, g_UI_NIL);
|
||||||
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,17 +543,19 @@ Nil(UIItem* item)
|
|||||||
return item == null || item == g_UI_NIL;
|
return item == null || item == g_UI_NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItemRec
|
||||||
Recurse(alias mode)(UIItem* item, UIItem* root)
|
Recurse(alias mode)(UIItem* item, UIItem* root)
|
||||||
{
|
{
|
||||||
UIItem* sibling, child, result = g_UI_NIL;
|
UIItem* sibling, child;
|
||||||
|
UIItemRec result = UIItemRec(next: g_UI_NIL);
|
||||||
|
|
||||||
static if (mode == UIR.PostOrder) sibling = item.next; else sibling = item.prev;
|
static if (mode == UIR.PostOrder) sibling = item.next; else sibling = item.prev;
|
||||||
static if (mode == UIR.PostOrder) child = item.prev; else child = item.last;
|
static if (mode == UIR.PostOrder) child = item.prev; else child = item.last;
|
||||||
|
|
||||||
if (!Nil(child))
|
if (!Nil(child))
|
||||||
{
|
{
|
||||||
result = sibling;
|
result.next = child;
|
||||||
|
result.push_count = 1;
|
||||||
}
|
}
|
||||||
else for(UIItem* i = sibling; !Nil(i) && i != root; i = i.parent)
|
else for(UIItem* i = sibling; !Nil(i) && i != root; i = i.parent)
|
||||||
{
|
{
|
||||||
@ -491,9 +563,11 @@ Recurse(alias mode)(UIItem* item, UIItem* root)
|
|||||||
|
|
||||||
if (!Nil(sibling))
|
if (!Nil(sibling))
|
||||||
{
|
{
|
||||||
result = sibling;
|
result.next = sibling;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.pop_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -503,17 +577,20 @@ Recurse(alias mode)(UIItem* item, UIItem* root)
|
|||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
SetProp(alias P, T)(T value)
|
SetProp(alias P, T)(T value)
|
||||||
{
|
{
|
||||||
static if (is(T: Vec4))
|
static if (is(T: Axis2D))
|
||||||
{
|
{
|
||||||
static if (0) {}
|
static if (P == CtxP.LayoutAxis) g_ui_ctx.layout_axis = value;
|
||||||
else static if (P == CtxP.BGColor) g_ui_ctx.bg_cols = [value, value, value, value];
|
else static assert(false, "Unknown property for type Axis2D");
|
||||||
|
}
|
||||||
|
else static if (is(T: Vec4))
|
||||||
|
{
|
||||||
|
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 if (P == CtxP.BorderColor) g_ui_ctx.border_cols = [value, value, value, value];
|
||||||
else static assert(false, "Unknown Property for type Vec4");
|
else static assert(false, "Unknown Property for type Vec4");
|
||||||
}
|
}
|
||||||
else static if (is(T: Vec4[4]))
|
else static if (is(T: Vec4[4]))
|
||||||
{
|
{
|
||||||
static if (0) {}
|
static if (P == CtxP.BGColor) g_ui_ctx.bg_cols = value;
|
||||||
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 if (P == CtxP.BorderColor) g_ui_ctx.border_cols = value;
|
||||||
else static assert(false, "Unknown Property for type Vec4[4]");
|
else static assert(false, "Unknown Property for type Vec4[4]");
|
||||||
}
|
}
|
||||||
@ -523,32 +600,28 @@ SetProp(alias P, T)(T value)
|
|||||||
}
|
}
|
||||||
else static if (is(T: UISize))
|
else static if (is(T: UISize))
|
||||||
{
|
{
|
||||||
static if (0) {}
|
static if (P == CtxP.AxisX) g_ui_ctx.size_axes[A2D.X] = value;
|
||||||
else static if (P == CtxP.AxisX) g_ui_ctx.size_axes[A2D.X] = value;
|
|
||||||
else static if (P == CtxP.AxisY) g_ui_ctx.size_axes[A2D.Y] = value;
|
else static if (P == CtxP.AxisY) g_ui_ctx.size_axes[A2D.Y] = value;
|
||||||
else static assert(false, "Unknown Property for type UISize");
|
else static assert(false, "Unknown Property for type UISize");
|
||||||
}
|
}
|
||||||
else static if (is(T: FontAtlas))
|
else static if (is(T: FontAtlas))
|
||||||
{
|
{
|
||||||
static if (0) {}
|
static if (P == CtxP.FontAtlas) g_ui_ctx.atlas = value;
|
||||||
else static if (P == CtxP.FontAtlas) g_ui_ctx.atlas = value;
|
|
||||||
else static assert(false, "Unknown Property for type FontAtlas");
|
else static assert(false, "Unknown Property for type FontAtlas");
|
||||||
}
|
}
|
||||||
else static if (is(T: Rect))
|
else static if (is(T: Rect))
|
||||||
{
|
{
|
||||||
static if (0) {}
|
static if (P == CtxP.Padding) g_ui_ctx.padding = value;
|
||||||
else static if (P == CtxP.Padding) g_ui_ctx.padding = value;
|
else static assert(false, "Unknown property for type Rect");
|
||||||
}
|
}
|
||||||
else static if (is(T: f32))
|
else static if (is(T: f32))
|
||||||
{
|
{
|
||||||
static if (0) {}
|
static if (P == CtxP.TextScale) g_ui_ctx.text_scale = value;
|
||||||
else static if (P == CtxP.TextScale) g_ui_ctx.text_scale = value;
|
|
||||||
else static assert(false, "Unknown property for type f32");
|
else static assert(false, "Unknown property for type f32");
|
||||||
}
|
}
|
||||||
else static if (is(T: u32))
|
else static if (is(T: u32))
|
||||||
{
|
{
|
||||||
static if (0) {}
|
static if (P == CtxP.TabWidth) g_ui_ctx.tab_width = value;
|
||||||
else static if (P == CtxP.TabWidth) g_ui_ctx.tab_width = value;
|
|
||||||
else static assert(false, "Unknown property for type u32");
|
else static assert(false, "Unknown property for type u32");
|
||||||
}
|
}
|
||||||
else static assert(false, "Unknown Type");
|
else static assert(false, "Unknown Type");
|
||||||
|
|||||||
@ -2,6 +2,11 @@ import dlib;
|
|||||||
|
|
||||||
import ui;
|
import ui;
|
||||||
|
|
||||||
|
struct Window
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItem*
|
||||||
RootItem()
|
RootItem()
|
||||||
{
|
{
|
||||||
@ -12,8 +17,23 @@ RootItem()
|
|||||||
SetProp!(CtxP.AxisX)(UISize(SK.Pixels, size.x, 1.0));
|
SetProp!(CtxP.AxisX)(UISize(SK.Pixels, size.x, 1.0));
|
||||||
SetProp!(CtxP.AxisY)(UISize(SK.Pixels, size.y, 1.0));
|
SetProp!(CtxP.AxisY)(UISize(SK.Pixels, size.y, 1.0));
|
||||||
SetProp!(CtxP.BGColor)(Vec4(0.2, 0.5, 0.85, 1.0));
|
SetProp!(CtxP.BGColor)(Vec4(0.2, 0.5, 0.85, 1.0));
|
||||||
|
SetProp!(CtxP.LayoutAxis)(A2D.X);
|
||||||
|
|
||||||
UIItem* item = BuildItem(key, UIP.DrawBackground);
|
UIItem* item = BuildItem(key, UIP.DrawBackground);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIItem*
|
||||||
|
WindowItem(u8[] str, f32 x_pct, f32 y_pct, Vec4 col)
|
||||||
|
{
|
||||||
|
UIKey key = MakeKey(str);
|
||||||
|
|
||||||
|
SetProp!(CtxP.AxisX)(UISize(SK.PercentOfParent, x_pct));
|
||||||
|
SetProp!(CtxP.AxisY)(UISize(SK.PercentOfParent, y_pct));
|
||||||
|
SetProp!(CtxP.BGColor)(col);
|
||||||
|
|
||||||
|
UIItem* item = BuildItem(key, UIP.DrawBackground);
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user