more work on ui
This commit is contained in:
parent
849404f78a
commit
3282b1e90f
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit b4bcfb7929ca87d59a35719c43b34d64ecaec9a0
|
Subproject commit c7f77523c4b7c86b625149ef7fde76257f6fcf51
|
||||||
@ -20,6 +20,7 @@ const u8[] FRAGMENT_BYTES = import("gui.frag.spv");
|
|||||||
|
|
||||||
const UI_COUNT = 5000;
|
const UI_COUNT = 5000;
|
||||||
|
|
||||||
|
f32 g_delta = 0.0;
|
||||||
Editor* g_editor;
|
Editor* g_editor;
|
||||||
|
|
||||||
struct Editor
|
struct Editor
|
||||||
@ -47,6 +48,8 @@ struct Editor
|
|||||||
FontFace font;
|
FontFace font;
|
||||||
FontAtlasBuf atlas_buf;
|
FontAtlasBuf atlas_buf;
|
||||||
|
|
||||||
|
Stack!(UIPanel*) panel_stack;
|
||||||
|
|
||||||
UVec2 res;
|
UVec2 res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +202,7 @@ Cycle(Editor* ed, Inputs* inputs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 prev_box_count = box_count;
|
u32 prev_box_count = box_count;
|
||||||
f32 delta = DeltaTime(&timer);
|
g_delta = DeltaTime(&timer);
|
||||||
for(auto ev = inputs.list.first; ev != null; ev = ev.next)
|
for(auto ev = inputs.list.first; ev != null; ev = ev.next)
|
||||||
{
|
{
|
||||||
count += 1;
|
count += 1;
|
||||||
@ -218,106 +221,28 @@ Cycle(Editor* ed, Inputs* inputs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static UIPanel* panel = null;
|
PanelStart("##Base", Vec3(0.5));
|
||||||
if (panel == null)
|
|
||||||
{
|
|
||||||
panel = Alloc!(UIPanel);
|
|
||||||
|
|
||||||
panel.split_axis = A2D.X;
|
PanelStart("##horizontal1", Vec3(0.2, 0.3, 0.7));
|
||||||
panel.percent = 1.0;
|
|
||||||
panel.first = panel.last = Alloc!(UIPanel);
|
|
||||||
|
|
||||||
panel.first.percent = 1.0;
|
PanelStart("##horizontal2", Vec3(0.2, 0.3, 0.7));
|
||||||
|
|
||||||
UIPanel* child = panel.first;
|
char[128] buf;
|
||||||
foreach(i; 0 .. 8)
|
|
||||||
{
|
|
||||||
UIPanel* p = Alloc!(UIPanel);
|
|
||||||
|
|
||||||
child.next = p;
|
|
||||||
panel.last = p;
|
|
||||||
child = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char[128] buf = 0;
|
|
||||||
f32 x_pct = 1.0/box_count;
|
f32 x_pct = 1.0/box_count;
|
||||||
|
|
||||||
if (box_count > prev_box_count)
|
|
||||||
{
|
|
||||||
u32 added = box_count - prev_box_count;
|
|
||||||
f32 insert_size = 0.0;
|
|
||||||
UIPanel* child = panel.first;
|
|
||||||
foreach(i; 0 .. prev_box_count)
|
|
||||||
{
|
|
||||||
child.anim.start = child.percent;
|
|
||||||
child.anim.end = x_pct;
|
|
||||||
child.anim.time_start = 0.2;
|
|
||||||
child.anim.time_remaining = 0.2;
|
|
||||||
|
|
||||||
child = child.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(i; 0 .. box_count-prev_box_count)
|
|
||||||
{
|
|
||||||
child.anim.start = insert_size;
|
|
||||||
child.anim.end = x_pct;
|
|
||||||
child.anim.time_start = 0.2;
|
|
||||||
child.anim.time_remaining = 0.2;
|
|
||||||
child.percent = insert_size;
|
|
||||||
|
|
||||||
child = child.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (box_count < prev_box_count)
|
|
||||||
{
|
|
||||||
UIPanel* child = panel.first;
|
|
||||||
foreach(i; 0 .. box_count)
|
|
||||||
{
|
|
||||||
child.anim.start = child.percent;
|
|
||||||
child.anim.end = x_pct;
|
|
||||||
child.anim.time_start = 0.2;
|
|
||||||
child.anim.time_remaining = 0.2;
|
|
||||||
|
|
||||||
child = child.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UIPanel* child = panel.first;
|
|
||||||
foreach(i; 0 .. box_count)
|
|
||||||
{
|
|
||||||
if (child.anim.time_remaining == 0.0) break;
|
|
||||||
|
|
||||||
f32 r = child.anim.time_remaining;
|
|
||||||
|
|
||||||
r -= delta;
|
|
||||||
if (r < 0.0)
|
|
||||||
{
|
|
||||||
r = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
f32 t = Remap(r, 0.0, child.anim.time_start, 1.0, 0.0);
|
|
||||||
child.percent = Mix(child.anim.start, child.anim.end, t);
|
|
||||||
|
|
||||||
child.anim.time_remaining = r;
|
|
||||||
if (r == 0.0)
|
|
||||||
{
|
|
||||||
child.anim.start = child.anim.end = child.anim.time_start = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
child = child.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UIPanel* child = panel.first;
|
|
||||||
foreach(i; 0 .. box_count)
|
foreach(i; 0 .. box_count)
|
||||||
{
|
{
|
||||||
buf.sformat("##%s", i);
|
buf.sformat("##%s", i);
|
||||||
DrawPanel(cast(u8[])buf, Vec4(Vec3(x_pct * i), 1.0), child);
|
PanelStart(cast(u8[])buf, Vec3(x_pct * i));
|
||||||
child = child.next;
|
PanelEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PanelEnd();
|
||||||
|
|
||||||
|
PanelStart("##horizontal3", Vec3(0.2, 0.5, 0.9));
|
||||||
|
PanelEnd();
|
||||||
|
|
||||||
|
PanelEnd();
|
||||||
|
|
||||||
BeginFrame(&ed.rd);
|
BeginFrame(&ed.rd);
|
||||||
|
|
||||||
UVec2 ext = UVec2(GetExtent(&ed.rd));
|
UVec2 ext = UVec2(GetExtent(&ed.rd));
|
||||||
|
|||||||
153
src/editor/ui.d
153
src/editor/ui.d
@ -5,6 +5,7 @@ import dlib.alloc;
|
|||||||
import dlib.fonts;
|
import dlib.fonts;
|
||||||
import vulkan;
|
import vulkan;
|
||||||
import widgets;
|
import widgets;
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
import editor;
|
import editor;
|
||||||
|
|
||||||
@ -30,13 +31,9 @@ struct UIContext
|
|||||||
Rect padding;
|
Rect padding;
|
||||||
u32 tab_width;
|
u32 tab_width;
|
||||||
f32 text_scale;
|
f32 text_scale;
|
||||||
Stack!(UIItem) parent_stack;
|
UIItem* parent_stack;
|
||||||
Axis2D layout_axis;
|
Axis2D layout_axis;
|
||||||
}
|
Vec2 position;
|
||||||
|
|
||||||
struct Stack(T)
|
|
||||||
{
|
|
||||||
T* first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIBuffer
|
struct UIBuffer
|
||||||
@ -63,6 +60,7 @@ enum CtxProperty
|
|||||||
TextScale,
|
TextScale,
|
||||||
TabWidth,
|
TabWidth,
|
||||||
LayoutAxis,
|
LayoutAxis,
|
||||||
|
Position,
|
||||||
}
|
}
|
||||||
|
|
||||||
alias CtxP = CtxProperty;
|
alias CtxP = CtxProperty;
|
||||||
@ -154,11 +152,15 @@ struct UIItem
|
|||||||
UIItem* prev;
|
UIItem* prev;
|
||||||
UIItem* parent;
|
UIItem* parent;
|
||||||
|
|
||||||
|
UIItem* list_next;
|
||||||
|
UIItem* list_prev;
|
||||||
|
|
||||||
|
debug { u8[] debug_id; }
|
||||||
|
|
||||||
UISize[A2D.max] size;
|
UISize[A2D.max] size;
|
||||||
Vec4[4] bg_color;
|
Vec4[4] bg_color;
|
||||||
Vec4[4] border_color;
|
Vec4[4] border_color;
|
||||||
Rect padding;
|
Rect padding;
|
||||||
f32[A2D.max] computed_rel_pos;
|
|
||||||
f32[A2D.max] computed_size;
|
f32[A2D.max] computed_size;
|
||||||
f32[A2D.max] fixed_position;
|
f32[A2D.max] fixed_position;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
@ -194,10 +196,9 @@ UIBeginBuild()
|
|||||||
|
|
||||||
ui.buffer.count = 0;
|
ui.buffer.count = 0;
|
||||||
|
|
||||||
ClearStack(&g_ui_ctx.parent_stack, g_UI_NIL);
|
ClearParentStack();
|
||||||
|
|
||||||
ui.root = RootItem();
|
ui.root = RootItem();
|
||||||
PushParent(ui.root);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -223,26 +224,25 @@ UIFinishBuild()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. PercentOfParent (Upward dependant) size (pre-order) (Ignore downward dependant sizes)
|
// 2. PercentOfParent (Upward dependant) size (pre-order) (Ignore downward dependant sizes)
|
||||||
u32 count = 0;
|
foreach(axis; A2D.min .. A2D.max)
|
||||||
|
{
|
||||||
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root).next)
|
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)
|
for(UIItem* child = item.first; !Nil(child); child = child.next)
|
||||||
{
|
{
|
||||||
foreach(i, ref s; child.size)
|
if (child.size[axis].kind == SK.PercentOfParent)
|
||||||
{
|
|
||||||
if (s.kind == SK.PercentOfParent)
|
|
||||||
{
|
{
|
||||||
UIItem* fixed_parent = g_UI_NIL;
|
UIItem* fixed_parent = g_UI_NIL;
|
||||||
for(UIItem* p = child.parent; !Nil(p); p = p.parent)
|
for(UIItem* p = child.parent; !Nil(p); p = p.parent)
|
||||||
{
|
{
|
||||||
if (p.size[i].kind == SK.Pixels || p.size[i].kind == SK.TextContent)
|
if (p.size[axis].kind == SK.Pixels || p.size[axis].kind == SK.TextContent)
|
||||||
{
|
{
|
||||||
fixed_parent = p;
|
fixed_parent = p;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
child.computed_size[i] = fixed_parent.computed_size[i] * s.value;
|
child.computed_size[axis] = fixed_parent.computed_size[axis] * child.size[axis].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,11 +259,33 @@ UIFinishBuild()
|
|||||||
i32 pop_index = 0;
|
i32 pop_index = 0;
|
||||||
for(UIItem* i = item; !Nil(item) && pop_index <= rec.pop_count; i = i.parent, pop_index += 1)
|
for(UIItem* i = item; !Nil(item) && pop_index <= rec.pop_count; i = i.parent, pop_index += 1)
|
||||||
{
|
{
|
||||||
|
if (i.size[axis].kind == SK.ChildrenSum)
|
||||||
|
{
|
||||||
|
f32 sum = 0.0;
|
||||||
|
for(UIItem* child = i.first; !Nil(child); child = child.next)
|
||||||
|
{
|
||||||
|
sum = axis == child.layout_axis ? sum + child.computed_size[axis] : Max(sum, child.computed_size[axis]);
|
||||||
|
}
|
||||||
|
i.computed_size[axis] = sum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 4. Solve violations e.g. extending past boundaries of parent (pre-order)
|
// 4. Solve violations e.g. extending past boundaries of parent (pre-order)
|
||||||
|
foreach(axis; A2D.min .. A2D.max)
|
||||||
|
{
|
||||||
|
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root).next)
|
||||||
|
{
|
||||||
|
if (!Nil(item.parent))
|
||||||
|
{
|
||||||
|
if (item.parent.computed_size[axis] < item.computed_size[axis])
|
||||||
|
{
|
||||||
|
item.computed_size[axis] = item.parent.computed_size[axis];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 5. Compute relative positions of each widgets (pre-order)
|
// 5. Compute relative positions of each widgets (pre-order)
|
||||||
foreach(axis; A2D.min .. A2D.max)
|
foreach(axis; A2D.min .. A2D.max)
|
||||||
@ -271,12 +293,12 @@ UIFinishBuild()
|
|||||||
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root).next)
|
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root).next)
|
||||||
{
|
{
|
||||||
f32 layout_position = 0.0;
|
f32 layout_position = 0.0;
|
||||||
|
|
||||||
for(UIItem* child = item.first; !Nil(child); child = child.next)
|
for(UIItem* child = item.first; !Nil(child); child = child.next)
|
||||||
{
|
{
|
||||||
child.computed_rel_pos[axis] = layout_position;
|
child.fixed_position[axis] = layout_position;
|
||||||
child.rect.vec0.v[axis] = layout_position;
|
|
||||||
child.rect.vec1.v[axis] = layout_position + child.computed_size[axis];
|
child.rect.vec0.v[axis] = item.rect.vec0.v[axis] + child.fixed_position[axis];
|
||||||
|
child.rect.vec1.v[axis] = child.rect.vec0.v[axis] + child.computed_size[axis];
|
||||||
|
|
||||||
if (axis == item.layout_axis)
|
if (axis == item.layout_axis)
|
||||||
{
|
{
|
||||||
@ -286,29 +308,56 @@ UIFinishBuild()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 count = 0;
|
||||||
for(UIItem* item = ui.root; !Nil(item); item = Recurse!(UIR.PreOrder)(item, ui.root).next)
|
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 (item.flags & UIP.DrawBackground)
|
||||||
{
|
{
|
||||||
if (!Nil(child))
|
DrawRect(ui, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WidgetsComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PrintTree(UIItem* item, u32 count = 0, string prefix = "", bool is_left = false)
|
||||||
|
{
|
||||||
|
if (!Nil(item))
|
||||||
{
|
{
|
||||||
if (child.flags & UIP.DrawBackground)
|
writeln(is_left ? "f" : "l", count, prefix, is_left ? "├──" : "└──", item.debug_id);
|
||||||
{
|
|
||||||
DrawRect(ui, child);
|
prefix ~= is_left ? "│ " : " ";
|
||||||
}
|
PrintTree(item.first, count + 1, prefix, true);
|
||||||
}
|
PrintTree(item.next, count + 1, prefix, false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PushParent(UIItem* parent)
|
||||||
|
{
|
||||||
|
auto ctx = GetCtx();
|
||||||
|
parent.list_next = ctx.parent_stack;
|
||||||
|
ctx.parent_stack = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIItem*
|
||||||
|
PopParent()
|
||||||
|
{
|
||||||
|
auto ctx = GetCtx();
|
||||||
|
UIItem* parent = ctx.parent_stack;
|
||||||
|
ctx.parent_stack = parent.list_next;
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItem*
|
||||||
BuildItem(UIKey key, UIProperties flags)
|
BuildItem(UIKey key, UIProperties flags)
|
||||||
{
|
{
|
||||||
UIContext* ui = GetCtx();
|
UIContext* ui = GetCtx();
|
||||||
|
|
||||||
UIItem* item = Get(key);
|
UIItem* item = Get(key);
|
||||||
item.first = item.last = item.next = item.prev = item.parent = g_UI_NIL;
|
item.first = item.last = item.next = item.prev = item.parent = item.list_next = item.list_prev = g_UI_NIL;
|
||||||
item.computed_rel_pos = item.computed_size = 0;
|
item.computed_size = 0;
|
||||||
|
|
||||||
item.flags = flags;
|
item.flags = flags;
|
||||||
item.size = ui.size_axes;
|
item.size = ui.size_axes;
|
||||||
@ -328,31 +377,25 @@ BuildItem(UIKey key, UIProperties flags)
|
|||||||
item.text_scale = ui.text_scale;
|
item.text_scale = ui.text_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.parent = ui.parent_stack.first;
|
item.parent = ui.parent_stack;
|
||||||
if (!Nil(item.parent))
|
if (!Nil(item.parent))
|
||||||
{
|
{
|
||||||
DLLPush(item.parent, item, g_UI_NIL);
|
DLLPush(item.parent, item, g_UI_NIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug
|
||||||
|
{
|
||||||
|
item.debug_id = key.text;
|
||||||
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ClearStack(T)(Stack!(T)* stack, T* nil)
|
ClearParentStack()
|
||||||
{
|
{
|
||||||
while(SPop(stack, nil) != nil) {}
|
auto ctx = GetCtx();
|
||||||
}
|
ctx.parent_stack = g_UI_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
|
void
|
||||||
@ -378,7 +421,8 @@ InitUIContext(Renderer* rd)
|
|||||||
g_ui_ctx.buffer.mapped_idx = idx;
|
g_ui_ctx.buffer.mapped_idx = idx;
|
||||||
g_ui_ctx.buffer.vtx = vtx.data;
|
g_ui_ctx.buffer.vtx = vtx.data;
|
||||||
g_ui_ctx.buffer.idx = idx.data;
|
g_ui_ctx.buffer.idx = idx.data;
|
||||||
g_ui_ctx.parent_stack.first = g_UI_NIL;
|
|
||||||
|
InitWidgetContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
UIKey
|
UIKey
|
||||||
@ -551,17 +595,23 @@ Recurse(alias mode)(UIItem* item, UIItem* root)
|
|||||||
UIItem* sibling, child;
|
UIItem* sibling, child;
|
||||||
UIItemRec result = UIItemRec(next: g_UI_NIL);
|
UIItemRec result = UIItemRec(next: g_UI_NIL);
|
||||||
|
|
||||||
static if (mode == UIR.PostOrder) sibling = item.next; else sibling = item.prev;
|
static if (mode == UIR.PostOrder) child = item.last; else child = item.first;
|
||||||
static if (mode == UIR.PostOrder) child = item.prev; else child = item.last;
|
|
||||||
|
|
||||||
if (!Nil(child))
|
if (!Nil(child))
|
||||||
{
|
{
|
||||||
result.next = child;
|
result.next = child;
|
||||||
result.push_count = 1;
|
result.push_count = 1;
|
||||||
}
|
}
|
||||||
else for(UIItem* i = sibling; !Nil(i) && i != root; i = i.parent)
|
else for(UIItem* i = item; !Nil(i) && i != root; i = i.parent)
|
||||||
{
|
{
|
||||||
static if (mode == UIR.PostOrder) sibling = i.next; else sibling = i.prev;
|
static if (mode == UIR.PostOrder)
|
||||||
|
{
|
||||||
|
sibling = i.prev;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sibling = i.next;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Nil(sibling))
|
if (!Nil(sibling))
|
||||||
{
|
{
|
||||||
@ -584,6 +634,11 @@ SetProp(alias P, T)(T value)
|
|||||||
static if (P == CtxP.LayoutAxis) g_ui_ctx.layout_axis = value;
|
static if (P == CtxP.LayoutAxis) g_ui_ctx.layout_axis = value;
|
||||||
else static assert(false, "Unknown property for type Axis2D");
|
else static assert(false, "Unknown property for type Axis2D");
|
||||||
}
|
}
|
||||||
|
else static if (is(T: Vec2))
|
||||||
|
{
|
||||||
|
static if (P == CtxP.Position) g_ui_ctx.position = value;
|
||||||
|
else static assert(false, "Unknown property for type Vec2");
|
||||||
|
}
|
||||||
else static if (is(T: Vec4))
|
else static if (is(T: Vec4))
|
||||||
{
|
{
|
||||||
static if (P == CtxP.BGColor) g_ui_ctx.bg_cols = [value, value, value, value];
|
static if (P == CtxP.BGColor) g_ui_ctx.bg_cols = [value, value, value, value];
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import dlib;
|
import dlib;
|
||||||
|
|
||||||
|
import editor;
|
||||||
import ui;
|
import ui;
|
||||||
|
|
||||||
struct WidgetAnimation
|
struct WidgetAnimation
|
||||||
@ -10,6 +11,18 @@ struct WidgetAnimation
|
|||||||
f32 time_remaining;
|
f32 time_remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WidgetContext g_widget_ctx;
|
||||||
|
const UIPanel g_ui_panel;
|
||||||
|
UIPanel* g_PANEL_NIL;
|
||||||
|
|
||||||
|
struct WidgetContext
|
||||||
|
{
|
||||||
|
u64 frame;
|
||||||
|
Arena arena;
|
||||||
|
HashTable!(UIHash, UIPanel*) panels;
|
||||||
|
UIPanel* parent_panel;
|
||||||
|
}
|
||||||
|
|
||||||
struct UIPanel
|
struct UIPanel
|
||||||
{
|
{
|
||||||
Axis2D split_axis;
|
Axis2D split_axis;
|
||||||
@ -17,12 +30,41 @@ struct UIPanel
|
|||||||
|
|
||||||
UIPanel* first;
|
UIPanel* first;
|
||||||
UIPanel* last;
|
UIPanel* last;
|
||||||
|
UIPanel* prev;
|
||||||
UIPanel* next;
|
UIPanel* next;
|
||||||
u32 count;
|
UIPanel* parent;
|
||||||
|
|
||||||
|
UIPanel* list_next;
|
||||||
|
|
||||||
|
u64 last_frame;
|
||||||
|
bool new_children;
|
||||||
|
u32 child_count;
|
||||||
|
|
||||||
WidgetAnimation anim;
|
WidgetAnimation anim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InitWidgetContext()
|
||||||
|
{
|
||||||
|
g_PANEL_NIL = cast(UIPanel*)&g_ui_panel;
|
||||||
|
|
||||||
|
g_widget_ctx.arena = CreateArena(MB(1));
|
||||||
|
g_widget_ctx.parent_panel = g_PANEL_NIL;
|
||||||
|
g_widget_ctx.panels = CreateHashTable!(UIHash, UIPanel*)(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WidgetsComplete()
|
||||||
|
{
|
||||||
|
g_widget_ctx.frame += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Nil(UIPanel* panel)
|
||||||
|
{
|
||||||
|
return panel == g_PANEL_NIL || panel == null;
|
||||||
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItem*
|
||||||
RootItem()
|
RootItem()
|
||||||
{
|
{
|
||||||
@ -37,22 +79,141 @@ RootItem()
|
|||||||
|
|
||||||
UIItem* item = BuildItem(key, UIP.DrawBackground);
|
UIItem* item = BuildItem(key, UIP.DrawBackground);
|
||||||
|
|
||||||
|
UIContext* ui = GetCtx();
|
||||||
|
|
||||||
|
PushParent(ui.root);
|
||||||
|
|
||||||
|
assert(g_widget_ctx.parent_panel == g_PANEL_NIL);
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItem*
|
||||||
DrawPanel(u8[] str, Vec4 col, UIPanel* panel)
|
PanelStart(string str, Vec3 col)
|
||||||
|
{
|
||||||
|
u8[] u8_str = (cast(u8*)str.ptr)[0 .. str.length];
|
||||||
|
return PanelStart(u8_str, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
UIPanel*
|
||||||
|
GetPanel(UIKey key)
|
||||||
|
{
|
||||||
|
UIPanel* panel;
|
||||||
|
Result!(UIPanel*) result = g_widget_ctx.panels[key.hash];
|
||||||
|
if (result.ok)
|
||||||
|
{
|
||||||
|
panel = result.value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
panel = Alloc!(UIPanel)(&g_widget_ctx.arena);
|
||||||
|
panel.last_frame = u64.max;
|
||||||
|
g_widget_ctx.panels[key.hash] = panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIItem*
|
||||||
|
PanelStart(u8[] str, Vec3 col)
|
||||||
{
|
{
|
||||||
UIKey key = MakeKey(str);
|
UIKey key = MakeKey(str);
|
||||||
|
UIPanel* panel = GetPanel(key);
|
||||||
|
|
||||||
f32 x_pct = panel.split_axis == A2D.X ? panel.percent : 1.0;
|
panel.first = panel.last = panel.next = panel.list_next = g_PANEL_NIL;
|
||||||
f32 y_pct = panel.split_axis == A2D.Y ? panel.percent : 1.0;
|
panel.child_count = 0;
|
||||||
|
|
||||||
SetProp!(CtxP.AxisX)(UISize(SK.PercentOfParent, x_pct));
|
if (panel.anim.time_remaining > 0.0)
|
||||||
SetProp!(CtxP.AxisY)(UISize(SK.PercentOfParent, y_pct));
|
{
|
||||||
SetProp!(CtxP.BGColor)(col);
|
f32 r = panel.anim.time_remaining;
|
||||||
|
|
||||||
|
r -= g_delta;
|
||||||
|
if (r < 0.0)
|
||||||
|
{
|
||||||
|
r = 0.0;
|
||||||
|
}
|
||||||
|
Logf("%f", r);
|
||||||
|
|
||||||
|
f32 t = Remap(r, 0.0, panel.anim.time_start, 1.0, 0.0);
|
||||||
|
panel.percent = Lerp(panel.anim.start, panel.anim.end, t);
|
||||||
|
|
||||||
|
panel.anim.time_remaining = r;
|
||||||
|
if (r == 0.0)
|
||||||
|
{
|
||||||
|
panel.anim.start = panel.anim.end = panel.anim.time_start = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.parent = g_widget_ctx.parent_panel;
|
||||||
|
panel.list_next = g_widget_ctx.parent_panel;
|
||||||
|
g_widget_ctx.parent_panel = panel;
|
||||||
|
|
||||||
|
f32 x_pct = 1.0, y_pct = 1.0;
|
||||||
|
if (!Nil(panel.parent))
|
||||||
|
{
|
||||||
|
if (panel.parent.split_axis == A2D.X)
|
||||||
|
{
|
||||||
|
x_pct = panel.percent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
y_pct = panel.percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panel.last_frame != g_widget_ctx.frame)
|
||||||
|
{
|
||||||
|
Logf("new");
|
||||||
|
panel.parent.new_children = true;
|
||||||
|
panel.anim.start = panel.anim.end = panel.anim.time_start = panel.anim.time_remaining = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
panel.child_count += 1;
|
||||||
|
DLLPush(panel.parent, panel, g_PANEL_NIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetProp!(CtxP.LayoutAxis)(panel.split_axis);
|
||||||
|
SetProp!(CtxP.AxisX)(UISize(SK.PercentOfParent, x_pct, 1.0));
|
||||||
|
SetProp!(CtxP.AxisY)(UISize(SK.PercentOfParent, y_pct, 1.0));
|
||||||
|
SetProp!(CtxP.BGColor)(Vec4(col, 1.0));
|
||||||
|
|
||||||
UIItem* item = BuildItem(key, UIP.DrawBackground);
|
UIItem* item = BuildItem(key, UIP.DrawBackground);
|
||||||
|
|
||||||
|
PushParent(item);
|
||||||
|
|
||||||
|
panel.last_frame = g_widget_ctx.frame + 1;
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PanelEnd()
|
||||||
|
{
|
||||||
|
UIPanel* parent = g_widget_ctx.parent_panel;
|
||||||
|
if (parent.new_children)
|
||||||
|
{
|
||||||
|
f32 new_percent = 1.0/cast(f32)(parent.child_count);
|
||||||
|
for(UIPanel* child = parent.first; !Nil(child); child = child.next)
|
||||||
|
{
|
||||||
|
f32 percent = child.percent;
|
||||||
|
if (percent > 0.0)
|
||||||
|
{
|
||||||
|
percent -= new_percent/cast(f32)(parent.child_count-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
percent = new_percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
child.anim.start = child.percent;
|
||||||
|
child.anim.end = new_percent;
|
||||||
|
child.anim.time_start = 0.2;
|
||||||
|
child.anim.time_remaining = 0.2;
|
||||||
|
child.percent = percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.new_children = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_widget_ctx.parent_panel = g_widget_ctx.parent_panel.list_next;
|
||||||
|
PopParent();
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user