more work on UI, starting to replace existing UI code
This commit is contained in:
parent
ad3ababe97
commit
8acbeee072
10
dub.json
10
dub.json
@ -16,8 +16,9 @@
|
||||
"versions": ["VULKAN_DEBUG", "ENABLE_RENDERER"],
|
||||
"preGenerateCommands-linux": ["./build.sh"],
|
||||
"preGenerateCommands-windows": [],
|
||||
"dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2", "-Jbuild", "-Jassets", "-link-debuglib"],
|
||||
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"]
|
||||
"dflags": ["-P-I/usr/include/freetype2", "-Jbuild", "-Jassets"],
|
||||
"dflags-ldc2": ["-link-debuglib"],
|
||||
"dflags-dmd": []
|
||||
},
|
||||
{
|
||||
"name": "editor-test",
|
||||
@ -33,8 +34,9 @@
|
||||
"versions": ["VULKAN_DEBUG"],
|
||||
"preGenerateCommands-linux": ["./build.sh"],
|
||||
"preGenerateCommands-windows": [],
|
||||
"dflags": ["-Xcc=-mno-sse", "-P-I/usr/include/freetype2", "-Jbuild", "-Jassets", "-link-debuglib", "-unittest"],
|
||||
"dflags-dmd": ["-P=-DSTBI_NO_SIMD"]
|
||||
"dflags": ["-P-I/usr/include/freetype2", "-Jbuild", "-Jassets", "-unittest"],
|
||||
"dflags-ldc2": ["-link-debuglib"],
|
||||
"dflags-dmd": []
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
||||
Subproject commit e5f91cae6d90c40e458e1208c2ab8f8eb917c99a
|
||||
Subproject commit 617e03f917911f6f9898086720a6539756f79758
|
||||
@ -141,6 +141,29 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
|
||||
|
||||
BeginUI(inputs);
|
||||
|
||||
UICtx* ui_ctx = GetCtx();
|
||||
|
||||
Vec4[4] col0 = Vec4(0.2, 0.4, 0.8, 1.0);
|
||||
Vec4[4] col1 = Vec4(0.8, 0.4, 0.2, 1.0);
|
||||
Vec4[4] col_sep = Vec4(0.2, 0.8, 0.1, 1.0);
|
||||
|
||||
Push!("size_info")(ui_ctx, MakeUISizeX(ST.Percentage, 0.5));
|
||||
|
||||
Push!("bg_col", true)(ui_ctx, col0);
|
||||
UIItem* p0 = MakeItem("###p0", UIF.DrawBackground|UIF.Resizeable);
|
||||
|
||||
Logf("%s", *ui_ctx.size_info.top);
|
||||
Push!("size_info", true)(ui_ctx, MakeUISizeX(ST.Pixels, 2.0));
|
||||
Logf("%s", *ui_ctx.size_info.top);
|
||||
Push!("bg_col", true)(ui_ctx, col_sep);
|
||||
UIItem* sep = MakeItem("###sep", UIF.Draggable|UIF.DrawBackground|UIF.ResizeAdjacent);
|
||||
Logf("%s", *ui_ctx.size_info.top);
|
||||
|
||||
|
||||
Push!("bg_col", true)(ui_ctx, col1);
|
||||
UIItem* p1 = MakeItem("###p1", UIF.DrawBackground|UIF.Resizeable);
|
||||
|
||||
/*
|
||||
UIPanel* root = ctx.base_panel;
|
||||
|
||||
root.size.x = g_ui_ctx.res.x;
|
||||
@ -150,7 +173,7 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
|
||||
|
||||
static foreach(axis; A2D.min .. A2D.max)
|
||||
{
|
||||
for(UIPanel* p = root; !Nil(p); p = Recurse(p, root, g_UI_NIL_PANEL))
|
||||
for(UIPanel* p = root; !Nil(p); p = Recurse(p, g_UI_NIL_PANEL))
|
||||
{
|
||||
f32 pos = p.rect.p0.v[axis];
|
||||
for(UIPanel* c = p.first; !Nil(c); c = c.next)
|
||||
@ -167,7 +190,7 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
|
||||
}
|
||||
}
|
||||
|
||||
for(auto p = ctx.base_panel; !Nil(p); p = Recurse(p, ctx.base_panel, g_UI_NIL_PANEL))
|
||||
for(auto p = ctx.base_panel; !Nil(p); p = Recurse(p, g_UI_NIL_PANEL))
|
||||
{
|
||||
Panel(p);
|
||||
}
|
||||
@ -181,6 +204,7 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
|
||||
|
||||
CommandPalette(&ctx.cmd);
|
||||
}
|
||||
*/
|
||||
|
||||
EndUI();
|
||||
}
|
||||
|
||||
300
src/editor/ui.d
300
src/editor/ui.d
@ -14,6 +14,7 @@ import std.math.traits : isNaN;
|
||||
import std.math.rounding : ceil, floor;
|
||||
import std.math.exponential : pow;
|
||||
import std.math.remainder : fmod;
|
||||
import std.algorithm.comparison : clamp;
|
||||
import std.format : sformat;
|
||||
import core.stdc.string : memset;
|
||||
import core.stdc.math : fabsf;
|
||||
@ -102,12 +103,17 @@ enum UIFlags
|
||||
ScrollY = 1<<6,
|
||||
ClampX = 1<<7,
|
||||
ClampY = 1<<8,
|
||||
|
||||
Resizeable = 1<<9,
|
||||
ResizeAdjacent = 1<<10,
|
||||
FloatingWindow = 1<<11,
|
||||
CenteredWindow = 1<<12,
|
||||
TextInput = 1<<13,
|
||||
|
||||
Clamp = UIFlags.ClampX | UIFlags.ClampY,
|
||||
}
|
||||
alias UIF = UIFlags;
|
||||
|
||||
const UIFlags AUTO_FLAGS = UIF.ResizeAdjacent;
|
||||
|
||||
enum UISignal
|
||||
{
|
||||
@ -159,35 +165,27 @@ UICtxParameter(T, string name)
|
||||
|
||||
template CtxMemberInfo(int i)
|
||||
{
|
||||
import std.string : endsWith;
|
||||
import std.string : endsWith, startsWith;
|
||||
import std.traits : isInstanceOf, isPointer;
|
||||
|
||||
struct MemberInfo
|
||||
{
|
||||
string id;
|
||||
bool is_stack, is_top, is_stack_top;
|
||||
bool is_stack, is_top;
|
||||
}
|
||||
|
||||
enum string id = __traits(identifier, UICtx.tupleof[i]);
|
||||
enum bool is_ptr = isPointer!(typeof(UICtx.tupleof[i]));
|
||||
enum bool is_top = endsWith(id, "_top");
|
||||
enum bool is_stack_top = isInstanceOf!(StackTop, typeof(UICtx.tupleof[i]));
|
||||
enum bool is_stack = startsWith(typeof(UICtx.tupleof[i]).stringof, "StackTop!");
|
||||
|
||||
static if(is_ptr)
|
||||
{
|
||||
enum bool is_stack = isInstanceOf!(Stack, typeof(*UICtx.tupleof[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
enum bool is_stack = false;
|
||||
}
|
||||
|
||||
enum MemberInfo CtxMemberInfo = MemberInfo(id: id, is_stack: is_ptr && is_stack, is_top: is_top, is_stack_top: is_stack_top);
|
||||
enum MemberInfo CtxMemberInfo = MemberInfo(id: id, is_stack: is_stack, is_top: is_top);
|
||||
}
|
||||
|
||||
struct UICtx
|
||||
{
|
||||
HashTable!(UIHash, UIItem*) items;
|
||||
UIItem* free_items;
|
||||
|
||||
Arena arena;
|
||||
Arena temp_arena;
|
||||
Inputs* inputs;
|
||||
@ -219,6 +217,7 @@ struct UICtx
|
||||
u32 tab_width;
|
||||
f32 text_size;
|
||||
|
||||
UIItem* window_root;
|
||||
UIItem* root;
|
||||
UIItem* drag_item;
|
||||
UIPanel* parent_panel;
|
||||
@ -245,13 +244,13 @@ struct Stack(T)
|
||||
{
|
||||
Stack!(T)* next;
|
||||
T value;
|
||||
bool auto_pop;
|
||||
}
|
||||
|
||||
struct StackTop(T)
|
||||
{
|
||||
Stack!(T)* top;
|
||||
Stack!(T)* free;
|
||||
bool auto_pop;
|
||||
}
|
||||
|
||||
mixin template UIItemParameters()
|
||||
@ -264,7 +263,7 @@ mixin template UIItemParameters()
|
||||
{
|
||||
{
|
||||
enum info = CtxMemberInfo!(i);
|
||||
static if(info.is_stack_top)
|
||||
static if(info.is_stack)
|
||||
{
|
||||
fields ~= typeof(UICtx.tupleof[i].top.value).stringof ~ " " ~ info.id ~ ";\n";
|
||||
}
|
||||
@ -279,17 +278,20 @@ mixin template UIItemParameters()
|
||||
|
||||
struct UIItem
|
||||
{
|
||||
UIKey key;
|
||||
UIFlags flags;
|
||||
u64 last_frame;
|
||||
IVec2 dragged;
|
||||
IVec2 dragged;
|
||||
UIKey key;
|
||||
|
||||
UIItem* next, prev, first, last; // parent in mixin
|
||||
u64 last_frame;
|
||||
UISignal signal;
|
||||
UIFlags flags;
|
||||
|
||||
Rect rect;
|
||||
Vec2 size;
|
||||
UIItem* next, prev, first, last; // parent in mixin
|
||||
|
||||
u8[] display_string;
|
||||
Rect rect;
|
||||
Vec2 size;
|
||||
|
||||
f32 resize_pct;
|
||||
u8[] display_string;
|
||||
|
||||
mixin UIItemParameters!();
|
||||
}
|
||||
@ -417,6 +419,7 @@ InitUICtx(PlatformWindow* window)
|
||||
|
||||
UICtx ctx = {
|
||||
items: CreateHashTable!(UIHash, UIItem*)(12),
|
||||
free_items: Alloc!(UIItem)(&arena),
|
||||
arena: arena,
|
||||
temp_arena: CreateArena(MB(1)),
|
||||
drag_item: g_UI_NIL,
|
||||
@ -426,6 +429,9 @@ InitUICtx(PlatformWindow* window)
|
||||
tab_width: 2,
|
||||
};
|
||||
|
||||
UIItem* fi = ctx.free_items;
|
||||
fi.first = fi.last = fi.next = fi.prev = fi.parent = g_UI_NIL;
|
||||
|
||||
ctx.atlas_buf = CreateAtlas(&arena, ctx.font, 16.0, 256);
|
||||
|
||||
version(ENABLE_RENDERER)
|
||||
@ -435,9 +441,10 @@ InitUICtx(PlatformWindow* window)
|
||||
for(u64 i = 0; i < FRAME_OVERLAP; i += 1)
|
||||
{
|
||||
ctx.buffers[i].m_vtx = CreateMappedBuffer!(Vertex)(&ctx.rd, BT.Vertex, VERTEX_MAX_COUNT);
|
||||
ctx.buffers[i].m_idx = CreateMappedBuffer!(u32)(&ctx.rd, BT.Index, cast(u64)(ceil(VERTEX_MAX_COUNT*1.5)));
|
||||
ctx.buffers[i].m_idx = CreateMappedBuffer!(u32)(&ctx.rd, BT.Index, 6);
|
||||
ctx.buffers[i].vtx = ctx.buffers[i].m_vtx.data;
|
||||
ctx.buffers[i].idx = ctx.buffers[i].m_idx.data;
|
||||
ctx.buffers[i].idx[0 .. $] = [0, 1, 2, 2, 1, 3];
|
||||
}
|
||||
|
||||
DescLayoutBinding[2] layout_bindings = [
|
||||
@ -513,33 +520,54 @@ Set(UIItem* item, UICtx* ctx)
|
||||
}
|
||||
|
||||
UIItem*
|
||||
MakeItem(T)(T k) if(is(T: UIKey) || StringType!T)
|
||||
MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
UICtx* ctx = GetCtx();
|
||||
UIItem* item = Get(k);
|
||||
item.flags = flags;
|
||||
|
||||
Set(item, ctx);
|
||||
if(!Nil(item.parent))
|
||||
if(item.flags & (UIF.CenteredWindow | UIF.FloatingWindow))
|
||||
{
|
||||
item.parent = ctx.window_root;
|
||||
DLLPush(item.parent, item, g_UI_NIL);
|
||||
}
|
||||
else if(!Nil(item.parent))
|
||||
{
|
||||
DLLPush(item.parent, item, g_UI_NIL);
|
||||
}
|
||||
AutoPopStacks(ctx);
|
||||
|
||||
if(item.last_frame != ctx.frame-1 && item.flags & UIF.Resizeable)
|
||||
{
|
||||
if(item.size_info[item.parent.layout_axis].type != ST.Percentage)
|
||||
{
|
||||
Logf("Warning: Resizing not percentage SizeType item, disabling flag");
|
||||
item.flags &= ~UIF.Resizeable;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.resize_pct = item.size_info[item.layout_axis].value;
|
||||
}
|
||||
}
|
||||
|
||||
item.last_frame = ctx.frame;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
UISignal
|
||||
void
|
||||
Signal(UIItem* item)
|
||||
{
|
||||
UISignal signal;
|
||||
UICtx* ctx = GetCtx();
|
||||
UICtx* ctx = GetCtx();
|
||||
i32 x = ctx.mouse_pos.x;
|
||||
i32 y = ctx.mouse_pos.y;
|
||||
|
||||
i32 x = ctx.mouse_pos.x;
|
||||
i32 y = ctx.mouse_pos.y;
|
||||
item.signal = UIS.None;
|
||||
|
||||
if(x >= item.rect.p0.x && x <= item.rect.p1.x && y >= item.rect.p0.y && y <= item.rect.p1.y)
|
||||
{
|
||||
signal |= UIS.Hovered;
|
||||
item.signal |= UIS.Hovered;
|
||||
}
|
||||
|
||||
item.dragged = 0;
|
||||
@ -548,21 +576,27 @@ Signal(UIItem* item)
|
||||
{
|
||||
bool taken;
|
||||
|
||||
Logf("%s", i.type);
|
||||
|
||||
if(item.flags & UIF.Clickable && i.type == UIE.Click && InBounds(ctx.mouse_pos, &item.rect))
|
||||
{
|
||||
signal |= UIS.Clicked;
|
||||
taken = true;
|
||||
Logf("clicked");
|
||||
item.signal |= UIS.Clicked;
|
||||
taken = true;
|
||||
}
|
||||
|
||||
if(Nil(ctx.drag_item) && item.flags & UIF.Draggable && i.type == UIE.DragStart && InBounds(i.pos, &item.rect))
|
||||
{
|
||||
signal |= UIS.Dragged;
|
||||
Logf("dragged");
|
||||
item.signal |= UIS.Dragged;
|
||||
ctx.drag_item = item;
|
||||
taken = true;
|
||||
}
|
||||
|
||||
if(ctx.drag_item == item && i.type == UIE.Drag)
|
||||
{
|
||||
Logf("dragged");
|
||||
item.signal |= UIS.Dragged;
|
||||
item.dragged += i.rel;
|
||||
taken = true;
|
||||
}
|
||||
@ -572,8 +606,6 @@ Signal(UIItem* item)
|
||||
DLLRemove(&ctx.events, i, g_UI_NIL_INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
void
|
||||
@ -593,8 +625,8 @@ BeginUI(Inputs* inputs)
|
||||
|
||||
Reset(a);
|
||||
|
||||
// Convert Inputs
|
||||
ctx.events.first = ctx.events.last = null;
|
||||
|
||||
static bool dragging;
|
||||
static bool mouse_down;
|
||||
for(auto i = inputs.first; i; i = i.next)
|
||||
@ -633,6 +665,21 @@ BeginUI(Inputs* inputs)
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up items
|
||||
KVPair!(UIHash, UIItem*)*[] items = GetAllNodes(&ctx.temp_arena, &ctx.items);
|
||||
foreach(i; 0 .. items.length)
|
||||
{
|
||||
UIItem* item = items[i].value;
|
||||
if(item.last_frame != ctx.frame)
|
||||
{
|
||||
Logf("discarding %s", cast(char[])item.key.hash_text);
|
||||
item.first = item.last = item.parent = item.prev = item.next = g_UI_NIL;
|
||||
DLLPush(ctx.free_items, item, g_UI_NIL);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.frame += 1;
|
||||
|
||||
// Ctx state
|
||||
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
|
||||
ctx.inputs = inputs;
|
||||
@ -660,13 +707,16 @@ BeginUI(Inputs* inputs)
|
||||
}
|
||||
|
||||
memset(ctx.buffers[ctx.f_idx].vtx.ptr, 0, Vertex.sizeof * ctx.buffers[ctx.f_idx].count);
|
||||
memset(ctx.buffers[ctx.f_idx].idx.ptr, 0, u32.sizeof * ctx.buffers[ctx.f_idx].count);
|
||||
ctx.buffers[ctx.f_idx].count = 0;
|
||||
|
||||
// Root Item
|
||||
UISize[2] sizes = [UISize(ST.Pixels, ctx.res.x), UISize(ST.Pixels, ctx.res.y)];
|
||||
Push!("size_info", true)(ctx, sizes);
|
||||
ctx.root = MakeItem("###root");
|
||||
Push!("size_info")(ctx, sizes);
|
||||
|
||||
ctx.root = MakeItem("###root");
|
||||
ctx.window_root = MakeItem("###window_root");
|
||||
|
||||
Pop!("size_info")(ctx);
|
||||
Push!("parent")(ctx, ctx.root);
|
||||
}
|
||||
|
||||
@ -675,9 +725,45 @@ EndUI()
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
|
||||
// Automatic signals
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||
{
|
||||
if(item.flags & AUTO_FLAGS)
|
||||
{
|
||||
Signal(item);
|
||||
|
||||
if(item.signal & UIS.Dragged)
|
||||
{
|
||||
Logf("1");
|
||||
}
|
||||
|
||||
if(item.flags & UIF.ResizeAdjacent && item.dragged != IVec2(0))
|
||||
{
|
||||
UIItem* prev = !Nil(item.prev) ? item.prev : g_UI_NIL;
|
||||
UIItem* next = !Nil(item.next) ? item.next : g_UI_NIL;
|
||||
|
||||
if(prev.flags & UIF.Resizeable && next.flags & UIF.Resizeable)
|
||||
{
|
||||
Axis2D axis = item.parent.layout_axis;
|
||||
f32 mov_pct = Remap(item.dragged.v[axis], 0.0, item.parent.size.v[axis], 0.0, 1.0);
|
||||
if(prev.resize_pct > 0.0 && prev.resize_pct < 1.0 && next.resize_pct > 0.0 && next.resize_pct < 1.0)
|
||||
{
|
||||
prev.resize_pct -= mov_pct;
|
||||
next.resize_pct += mov_pct;
|
||||
|
||||
prev.resize_pct = clamp(prev.resize_pct, 0.0, 1.0);
|
||||
next.resize_pct = clamp(next.resize_pct, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate item properties
|
||||
static foreach(axis; A2D.min .. A2D.max)
|
||||
{
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, ctx.root, g_UI_NIL))
|
||||
// Pixel sizes
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||
{
|
||||
if(item.size_info[axis].type == ST.Pixels)
|
||||
{
|
||||
@ -685,10 +771,16 @@ EndUI()
|
||||
}
|
||||
}
|
||||
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, ctx.root, g_UI_NIL))
|
||||
// Percentage sizes
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||
{
|
||||
if(item.size_info[axis].type == ST.Percentage)
|
||||
{
|
||||
if(item.layout_axis == axis && item.flags & UIF.Resizeable)
|
||||
{
|
||||
item.size_info[axis].value = item.resize_pct;
|
||||
}
|
||||
|
||||
for(UIItem* p = item.parent; !Nil(p); p = p.parent)
|
||||
{
|
||||
if(p.size_info[axis].type == ST.Pixels)
|
||||
@ -700,7 +792,8 @@ EndUI()
|
||||
}
|
||||
}
|
||||
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(false)(item, ctx.root, g_UI_NIL))
|
||||
// Sum of children sizes
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(false)(item, g_UI_NIL))
|
||||
{
|
||||
if(item.size_info[axis].type == ST.ChildrenSum)
|
||||
{
|
||||
@ -712,7 +805,8 @@ EndUI()
|
||||
}
|
||||
}
|
||||
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, ctx.root, g_UI_NIL))
|
||||
// Violations
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||
{
|
||||
if(axis == item.layout_axis)
|
||||
{
|
||||
@ -724,7 +818,6 @@ EndUI()
|
||||
|
||||
if(children_size > item.size[axis])
|
||||
{
|
||||
Logf("%s %s %s %s", axis, cast(char[])item.key.hash_text, children_size, item.size[axis]);
|
||||
u64 child_count;
|
||||
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||
{
|
||||
@ -766,6 +859,7 @@ EndUI()
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate final sizes
|
||||
{
|
||||
f32 pos = 0.0;
|
||||
for(UIItem* item = ctx.root; !Nil(item);)
|
||||
@ -809,6 +903,11 @@ EndUI()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Render Items
|
||||
RenderItems(ctx.root);
|
||||
RenderItems(ctx.window_root);
|
||||
|
||||
version(ENABLE_RENDERER) with(ctx)
|
||||
{
|
||||
BindBuffers(&rd, &buffers[f_idx].m_idx, &buffers[f_idx].m_vtx);
|
||||
@ -817,8 +916,39 @@ EndUI()
|
||||
FinishRendering(&rd);
|
||||
SubmitAndPresent(&rd);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.frame += 1;
|
||||
void
|
||||
RenderItems(UIItem* root)
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||
{
|
||||
if(item.flags & UIF.DrawBackground)
|
||||
{
|
||||
// DrawRect
|
||||
Vertex* v = GetVertex(ctx);
|
||||
v.dst_start = item.rect.p0 + item.border_thickness;
|
||||
v.dst_end = item.rect.p1 - item.border_thickness;
|
||||
v.cols = item.bg_col;
|
||||
v.corner_radius = item.corner_radius;
|
||||
|
||||
AddVertexCount(ctx);
|
||||
}
|
||||
|
||||
if(item.flags & UIF.DrawBorder)
|
||||
{
|
||||
Vertex* v = GetVertex(ctx);
|
||||
v.dst_start = item.rect.p0;
|
||||
v.dst_end = item.rect.p1;
|
||||
v.cols = item.border_col;
|
||||
v.corner_radius = item.corner_radius;
|
||||
v.border_thickness = item.border_thickness;
|
||||
v.edge_softness = item.edge_softness;
|
||||
|
||||
AddVertexCount(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32[2]
|
||||
@ -862,11 +992,11 @@ Push(string stack_str, bool auto_pop = false, T)(UICtx* ctx, T value)
|
||||
node = Alloc!(Stack!(T))(&ctx.temp_arena);
|
||||
}
|
||||
|
||||
node.next = stack.top;
|
||||
node.value = value;
|
||||
node.next = stack.top;
|
||||
node.value = value;
|
||||
node.auto_pop = auto_pop;
|
||||
|
||||
stack.top = node;
|
||||
stack.auto_pop = auto_pop;
|
||||
}
|
||||
|
||||
auto
|
||||
@ -902,12 +1032,12 @@ AutoPopStacks(UICtx* ctx)
|
||||
{
|
||||
{
|
||||
enum member_info = CtxMemberInfo!(i);
|
||||
static if(member_info.is_stack && !member_info.is_top)
|
||||
static if(member_info.is_stack)
|
||||
{
|
||||
if(ctx.tupleof[i].auto_pop)
|
||||
if(ctx.tupleof[i].top.auto_pop)
|
||||
{
|
||||
ctx.tupleof[i].top.auto_pop = false;
|
||||
Pop!(member_info.id)(ctx);
|
||||
ctx.tupleof[i].auto_pop = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -924,7 +1054,7 @@ InitStacks(UICtx* ctx)
|
||||
{
|
||||
{
|
||||
enum member_info = CtxMemberInfo!(i);
|
||||
static if(member_info.is_stack && member_info.is_top)
|
||||
static if(member_info.is_top)
|
||||
{
|
||||
enum global_default = replace("g_@_default", "@", chomp(member_info.id, "_top"));
|
||||
|
||||
@ -946,11 +1076,10 @@ ResetStacks(UICtx* ctx)
|
||||
{
|
||||
{
|
||||
enum member_info = CtxMemberInfo!(i);
|
||||
static if(member_info.is_stack_top)
|
||||
static if(member_info.is_stack)
|
||||
{
|
||||
enum top = replace("ctx.@_top", "@", member_info.id);
|
||||
ctx.tupleof[i].top = mixin(top);
|
||||
ctx.tupleof[i].auto_pop = false;
|
||||
ctx.tupleof[i].free = null;
|
||||
|
||||
assert(ctx.tupleof[i].top.next == null, "Top stack node next isn't null");
|
||||
@ -960,18 +1089,21 @@ ResetStacks(UICtx* ctx)
|
||||
}
|
||||
|
||||
T*
|
||||
Recurse(bool pre = true, T)(T* panel, T* root, T* nil)
|
||||
Recurse(bool pre = true, T)(T* node, T* nil)
|
||||
{
|
||||
T* child = pre ? node.first : node.last;
|
||||
T* sibling = pre ? node.next : node.prev;
|
||||
|
||||
T* result = nil;
|
||||
if(!Nil(panel.first))
|
||||
if(!Nil(child))
|
||||
{
|
||||
result = pre ? panel.first : panel.last;
|
||||
result = child;
|
||||
}
|
||||
else for(T* p = panel; !Nil(p) && p != root; p = p.parent)
|
||||
else for(T* p = node; !Nil(p); p = p.parent)
|
||||
{
|
||||
if(!Nil(pre ? p.next : p.prev))
|
||||
if(!Nil(sibling))
|
||||
{
|
||||
result = pre ? p.next : p.prev;
|
||||
result = sibling;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1115,16 +1247,26 @@ Get(T)(T k) if(is(T: UIKey) || StringType!T)
|
||||
UIKey key = MakeKey(k);
|
||||
}
|
||||
|
||||
Result!(UIItem*) result = g_ui_ctx.items[key.hash];
|
||||
if(!result.ok)
|
||||
Result!(UIItem*) res = g_ui_ctx.items[key.hash];
|
||||
if(!res.ok)
|
||||
{
|
||||
result.value = Alloc!(UIItem)(&g_ui_ctx.arena);
|
||||
HTPush(&g_ui_ctx.items, key.hash, result.value);
|
||||
if(!Nil(g_ui_ctx.free_items.first))
|
||||
{
|
||||
res.value = DLLPop(g_ui_ctx.free_items, g_UI_NIL);
|
||||
}
|
||||
else
|
||||
{
|
||||
res.value = Alloc!(UIItem)(&g_ui_ctx.arena);
|
||||
HTPush(&g_ui_ctx.items, key.hash, res.value);
|
||||
}
|
||||
|
||||
res.value.last_frame = g_ui_ctx.frame-2;
|
||||
}
|
||||
|
||||
result.value.key = key;
|
||||
res.value.key = key;
|
||||
res.value.next = res.value.prev = res.value.first = res.value.last = res.value.parent = g_UI_NIL;
|
||||
|
||||
return result.value;
|
||||
return res.value;
|
||||
}
|
||||
|
||||
f32
|
||||
@ -1283,7 +1425,7 @@ DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y)
|
||||
v.src_end.y = gb.atlas_b;
|
||||
}
|
||||
|
||||
AddUIIndices(ctx);
|
||||
AddVertexCount(ctx);
|
||||
|
||||
*x_pos += glyph.advance * scale;
|
||||
|
||||
@ -1382,7 +1524,7 @@ DrawRect(f32 x, f32 y, f32 w, f32 h, f32 corner_radius, f32 border, Vec4[4] cols
|
||||
v.dst_end -= border;
|
||||
}
|
||||
|
||||
AddUIIndices(ctx);
|
||||
AddVertexCount(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1399,21 +1541,13 @@ DrawBorder(Vec2 pos, Vec2 size, f32 border, f32 radius, f32 softness, Vec4[4] co
|
||||
v.edge_softness = softness;
|
||||
v.raised = 0.0;
|
||||
|
||||
AddUIIndices(ctx);
|
||||
AddVertexCount(ctx);
|
||||
}
|
||||
|
||||
pragma(inline) void
|
||||
AddUIIndices(UICtx* ctx)
|
||||
AddVertexCount(UICtx* ctx)
|
||||
{
|
||||
ctx.buffers[ctx.f_idx].idx[0] = 0;
|
||||
ctx.buffers[ctx.f_idx].idx[1] = 1;
|
||||
ctx.buffers[ctx.f_idx].idx[2] = 2;
|
||||
ctx.buffers[ctx.f_idx].idx[3] = 2;
|
||||
ctx.buffers[ctx.f_idx].idx[4] = 1;
|
||||
ctx.buffers[ctx.f_idx].idx[5] = 3;
|
||||
|
||||
ctx.buffers[ctx.f_idx].count += 1;
|
||||
|
||||
assert(ctx.buffers[ctx.f_idx].count < VERTEX_MAX_COUNT);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user