more work
This commit is contained in:
parent
80b454914a
commit
f4f311a49c
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit 1160d747ccb550b72a60cd68aa22a14f6dcb1ab1
|
Subproject commit 10c7fdcaedfdd98af47c640e00f1fad8705f476d
|
||||||
439
src/editor/ui.d
439
src/editor/ui.d
@ -16,7 +16,7 @@ import std.math.remainder : fmod;
|
|||||||
import std.algorithm.comparison : clamp;
|
import std.algorithm.comparison : clamp;
|
||||||
import std.format : sformat;
|
import std.format : sformat;
|
||||||
import core.stdc.string : memset;
|
import core.stdc.string : memset;
|
||||||
import core.stdc.math : fabsf;
|
import core.stdc.math : fabsf, cbrtf;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import core.stdc.stdio : sprintf;
|
import core.stdc.stdio : sprintf;
|
||||||
|
|
||||||
@ -29,12 +29,12 @@ import core.stdc.stdio : sprintf;
|
|||||||
|
|
||||||
*********************************/
|
*********************************/
|
||||||
|
|
||||||
enum Vec4 BG_COL = Vec4(0.13, 0.13, 0.13, 1.0);
|
enum Vec4 BG_COL = SRGBVec4(0.13, 0.13, 0.13, 1.0);
|
||||||
enum Vec4 BG_HL_COL = Vec4(0.24, 0.45, 0.81, 1.0);
|
enum Vec4 BG_HL_COL = SRGBVec4(0.24, 0.45, 0.81, 1.0);
|
||||||
enum Vec4 BORDER_COL = Vec4(0.254, 0.254, 0.266, 1.0);
|
enum Vec4 BORDER_COL = SRGBVec4(0.254, 0.254, 0.266, 1.0);
|
||||||
enum Vec4 BORDER_HL_COL = Vec4(0.035, 0.549, 0.824, 1.0);
|
enum Vec4 BORDER_HL_COL = SRGBVec4(0.035, 0.549, 0.824, 1.0);
|
||||||
enum Vec4 TEXT_COL = Vec4(1.0);
|
enum Vec4 TEXT_COL = SRGBVec4(1.0);
|
||||||
enum Vec4 TEXT_HL_COL = Vec4(0.0, 0.0, 0.0, 1.0);
|
enum Vec4 TEXT_HL_COL = SRGBVec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
const u64 VERTEX_MAX_COUNT = 10000;
|
const u64 VERTEX_MAX_COUNT = 10000;
|
||||||
const Vec2 CLICK_BUFFER = Vec2(3.0, 3.0);
|
const Vec2 CLICK_BUFFER = Vec2(3.0, 3.0);
|
||||||
@ -100,7 +100,7 @@ enum Axis2D
|
|||||||
|
|
||||||
alias A2D = Axis2D;
|
alias A2D = Axis2D;
|
||||||
|
|
||||||
enum UIFlags
|
enum UIFlags : u64
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
DrawBackground = 1<<0,
|
DrawBackground = 1<<0,
|
||||||
@ -128,6 +128,11 @@ enum UIFlags
|
|||||||
OverflowY = 1<<22,
|
OverflowY = 1<<22,
|
||||||
Gradient = 1<<23,
|
Gradient = 1<<23,
|
||||||
VerticalAlignText = 1<<24,
|
VerticalAlignText = 1<<24,
|
||||||
|
SetHot = 1<<25,
|
||||||
|
SetReady = 1<<26,
|
||||||
|
AnimateReady = 1<<27, // Fade in/out
|
||||||
|
AnimateHot = 1<<28, // Hover highlight
|
||||||
|
AnimateActive = 1<<29, // Animate selected (probably do later)
|
||||||
|
|
||||||
Clamp = UIFlags.ClampX | UIFlags.ClampY,
|
Clamp = UIFlags.ClampX | UIFlags.ClampY,
|
||||||
PortalView = UIFlags.PortalViewX | UIFlags.PortalViewY,
|
PortalView = UIFlags.PortalViewX | UIFlags.PortalViewY,
|
||||||
@ -236,7 +241,6 @@ struct UICtx
|
|||||||
|
|
||||||
LinkedList!(UIInput) events;
|
LinkedList!(UIInput) events;
|
||||||
IVec2 mouse_pos;
|
IVec2 mouse_pos;
|
||||||
IVec2 drag_start;
|
|
||||||
|
|
||||||
PlatformWindow* window;
|
PlatformWindow* window;
|
||||||
Renderer rd;
|
Renderer rd;
|
||||||
@ -259,9 +263,14 @@ struct UICtx
|
|||||||
u32 tab_width;
|
u32 tab_width;
|
||||||
Vec4[TS.max][UISH.max] syntax_colors;
|
Vec4[TS.max][UISH.max] syntax_colors;
|
||||||
|
|
||||||
UIItem* root;
|
UIItem* root_first;
|
||||||
UIItem* drag_item;
|
UIItem* root_last;
|
||||||
UIItem* focus_item;
|
UIKey drag_key;
|
||||||
|
UIKey hover_key;
|
||||||
|
u64 last_hover_frame;
|
||||||
|
|
||||||
|
f32 scroll_rate;
|
||||||
|
f32 animation_rate;
|
||||||
|
|
||||||
mixin UICtxParameter!(Vec4, "bg_col");
|
mixin UICtxParameter!(Vec4, "bg_col");
|
||||||
mixin UICtxParameter!(Vec4, "bg_col_end");
|
mixin UICtxParameter!(Vec4, "bg_col_end");
|
||||||
@ -363,6 +372,10 @@ struct UIItem
|
|||||||
f32 resize_pct;
|
f32 resize_pct;
|
||||||
bool rendered;
|
bool rendered;
|
||||||
|
|
||||||
|
f32 ready_t; // Item visible
|
||||||
|
f32 hot_t; // Item to be interacted with (e.g. hover)
|
||||||
|
f32 active_t; // Item active (retained focus)
|
||||||
|
|
||||||
mixin UIItemParameters!();
|
mixin UIItemParameters!();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +516,6 @@ InitUICtx(PlatformWindow* window)
|
|||||||
ctx.free_items = Alloc!(UIItem)(&arena);
|
ctx.free_items = Alloc!(UIItem)(&arena);
|
||||||
ctx.arena = arena;
|
ctx.arena = arena;
|
||||||
ctx.temp_arena = CreateArena(MB(1));
|
ctx.temp_arena = CreateArena(MB(1));
|
||||||
ctx.drag_item = g_UI_NIL;
|
|
||||||
ctx.transient_items = g_UI_NIL;
|
ctx.transient_items = g_UI_NIL;
|
||||||
ctx.font = OpenFont(cast(u8[])FONT_BYTES);
|
ctx.font = OpenFont(cast(u8[])FONT_BYTES);
|
||||||
ctx.tab_width = 2;
|
ctx.tab_width = 2;
|
||||||
@ -662,20 +674,23 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
{
|
{
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
UIItem* item = Get(k);
|
UIItem* item = Get(k);
|
||||||
|
|
||||||
item.flags = flags;
|
item.flags = flags;
|
||||||
|
item.signal = UIS.None;
|
||||||
|
|
||||||
Set(item, ctx);
|
Set(item, ctx);
|
||||||
if(item.flags & (UIF.Window | UIF.FloatingWindow))
|
if(Nil(ctx.root_first))
|
||||||
|
{
|
||||||
|
ctx.root_first = ctx.root_last = item;
|
||||||
|
Push!("parent")(item);
|
||||||
|
}
|
||||||
|
if(item.flags & (UIF.Window | UIF.FloatingWindow) || Nil(ctx.root_first))
|
||||||
{
|
{
|
||||||
item.parent = g_UI_NIL;
|
item.parent = g_UI_NIL;
|
||||||
UIItem* next = ctx.root;
|
|
||||||
while(!Nil(next.next))
|
|
||||||
{
|
|
||||||
next = next.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
next.next = item;
|
ctx.root_last.next = item;
|
||||||
item.prev = next;
|
item.prev = ctx.root_last;
|
||||||
|
ctx.root_last = item;
|
||||||
}
|
}
|
||||||
else if(!Nil(item.parent))
|
else if(!Nil(item.parent))
|
||||||
{
|
{
|
||||||
@ -702,12 +717,11 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
string str = item.display_string.length ? item.display_string : item.key.text;
|
string str = item.display_string.length ? item.display_string : item.key.text;
|
||||||
if(item.flags & UIF.TextWrap)
|
if(item.flags & UIF.TextWrap)
|
||||||
{
|
{
|
||||||
|
|
||||||
f32 width = item.size_info[A2D.X].type == ST.TextSize ? item.parent.size.x : item.size.x;
|
f32 width = item.size_info[A2D.X].type == ST.TextSize ? item.parent.size.x : item.size.x;
|
||||||
u32 ch_per_line = cast(u32)floor(width/abuf.atlas.max_advance);
|
u32 ch_per_line = cast(u32)floor(width/abuf.atlas.max_advance);
|
||||||
u64 lines = (str.length/ch_per_line) + (str.length%ch_per_line ? 1 : 0);
|
u64 lines = (str.length/ch_per_line) + (str.length%ch_per_line ? 1 : 0);
|
||||||
|
|
||||||
item.text_lines = ScratchAlloc!(string)(lines);
|
item.text_lines = ScratchAlloc!(string)(lines);
|
||||||
|
|
||||||
u64 start;
|
u64 start;
|
||||||
for(u64 i = 0; i < lines; i += 1)
|
for(u64 i = 0; i < lines; i += 1)
|
||||||
@ -744,14 +758,13 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 scroll_speed = 1 - pow(2, (-60.0f * g_delta));
|
|
||||||
static foreach(axis; A2D.min .. A2D.max)
|
static foreach(axis; A2D.min .. A2D.max)
|
||||||
{
|
{
|
||||||
if(item.flags & (UIF.ScrollX << axis))
|
if(item.flags & (UIF.ScrollX << axis))
|
||||||
{
|
{
|
||||||
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) > 0.0009)
|
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) > 0.0009)
|
||||||
{
|
{
|
||||||
f32 v = scroll_speed * (item.scroll_target.v[axis] - item.scroll_offset.v[axis]);
|
f32 v = ctx.scroll_rate * (item.scroll_target.v[axis] - item.scroll_offset.v[axis]);
|
||||||
item.scroll_offset.v[axis] += v;
|
item.scroll_offset.v[axis] += v;
|
||||||
|
|
||||||
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) < 2.0)
|
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) < 2.0)
|
||||||
@ -767,65 +780,113 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(item.flags & UIF.AnimateHot)
|
||||||
|
{
|
||||||
|
bool is_hot = cast(bool)(item.flags & UIF.SetHot) || Hovered!(true)(item);
|
||||||
|
item.hot_t += ctx.animation_rate * (cast(f32)(is_hot) - item.hot_t);
|
||||||
|
item.bg_col = Mix(item.bg_col, BG_HL_COL, item.hot_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(item.flags & UIF.AnimateReady)
|
||||||
|
{
|
||||||
|
item.ready_t += ctx.animation_rate * (1.0 - item.ready_t);
|
||||||
|
item.bg_col.a *= item.ready_t;
|
||||||
|
item.bg_col_end.a *= item.ready_t;
|
||||||
|
item.text_col.a *= item.ready_t;
|
||||||
|
item.border_col.a *= item.ready_t;
|
||||||
|
}
|
||||||
|
|
||||||
if(item.flags & UIF.DrawBorder && item.border_thickness < 0.0009)
|
if(item.flags & UIF.DrawBorder && item.border_thickness < 0.0009)
|
||||||
{
|
{
|
||||||
item.border_thickness = 1.0;
|
item.border_thickness = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.last_frame = ctx.frame;
|
item.last_frame = ctx.frame;
|
||||||
item.rendered = false;
|
item.rendered = false;
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Hovered(bool current_frame, T)(T param)
|
||||||
|
{
|
||||||
|
UICtx* ctx = GetCtx();
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
static if(is(T == UIKey))
|
||||||
|
{
|
||||||
|
UIKey key = param;
|
||||||
|
}
|
||||||
|
else static if(is(T == UIItem*))
|
||||||
|
{
|
||||||
|
UIKey key = param.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ZeroKey(ctx.hover_key))
|
||||||
|
{
|
||||||
|
static if(current_frame)
|
||||||
|
{
|
||||||
|
result = key.hash == ctx.hover_key.hash && ctx.last_hover_frame == ctx.frame;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = key.hash == ctx.hover_key_hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Signal(UIItem* item)
|
Signal(UIItem* item)
|
||||||
{
|
{
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
|
|
||||||
item.signal = UIS.None;
|
if(item.signal != UIS.None)
|
||||||
bool mouse_over = InBounds(ctx.mouse_pos, &item.rect);
|
|
||||||
|
|
||||||
if(mouse_over)
|
|
||||||
{
|
{
|
||||||
item.signal |= UIS.Hovered;
|
bool mouse_over = InBounds(ctx.mouse_pos, &item.rect);
|
||||||
}
|
|
||||||
|
|
||||||
item.dragged = 0;
|
if(mouse_over)
|
||||||
|
|
||||||
for(UIInput* i = ctx.events.first; !CheckNil(g_UI_NIL_INPUT, i); i = i.next)
|
|
||||||
{
|
|
||||||
bool taken;
|
|
||||||
|
|
||||||
if(item.flags & UIF.Clickable && i.type == UIE.Click && InBounds(ctx.mouse_pos, &item.rect))
|
|
||||||
{
|
{
|
||||||
item.signal |= UIS.Clicked;
|
item.signal |= UIS.Hovered;
|
||||||
taken = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Nil(ctx.drag_item) && item.flags & UIF.Draggable && i.type == UIE.DragStart && InBounds(i.pos, &item.rect))
|
|
||||||
{
|
|
||||||
item.signal |= UIS.Dragged;
|
|
||||||
ctx.drag_item = item;
|
|
||||||
taken = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ctx.drag_item == item && i.type == UIE.Drag)
|
item.dragged = 0;
|
||||||
{
|
|
||||||
item.signal |= UIS.Dragged;
|
|
||||||
item.dragged += i.rel;
|
|
||||||
taken = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ctx.drag_item == item && i.type == UIE.DragRelease)
|
for(UIInput* i = ctx.events.first; !CheckNil(g_UI_NIL_INPUT, i); i = i.next)
|
||||||
{
|
{
|
||||||
ctx.drag_item = g_UI_NIL;
|
bool taken;
|
||||||
taken = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(taken)
|
if(item.flags & UIF.Clickable && i.type == UIE.Click && InBounds(ctx.mouse_pos, &item.rect))
|
||||||
{
|
{
|
||||||
DLLRemove(&ctx.events, i, g_UI_NIL_INPUT);
|
item.signal |= UIS.Clicked;
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ZeroKey(ctx.drag_key) && item.flags & UIF.Draggable && i.type == UIE.DragStart && InBounds(i.pos, &item.rect))
|
||||||
|
{
|
||||||
|
item.signal |= UIS.Dragged;
|
||||||
|
ctx.drag_key = item.key;
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(KeyEq(ctx.drag_key, item.key) && i.type == UIE.Drag)
|
||||||
|
{
|
||||||
|
item.signal |= UIS.Dragged;
|
||||||
|
item.dragged += i.rel;
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(KeyEq(ctx.drag_key, item.key) && i.type == UIE.DragRelease)
|
||||||
|
{
|
||||||
|
ctx.drag_key = ZeroKey();
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(taken)
|
||||||
|
{
|
||||||
|
DLLRemove(&ctx.events, i, g_UI_NIL_INPUT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -868,8 +929,9 @@ BeginUI(Inputs* inputs)
|
|||||||
// Convert Inputs
|
// Convert Inputs
|
||||||
ctx.events.first = ctx.events.last = null;
|
ctx.events.first = ctx.events.last = null;
|
||||||
|
|
||||||
static bool dragging;
|
bool mouse_moved;
|
||||||
static bool mouse_down;
|
static bool dragging;
|
||||||
|
static bool mouse_down;
|
||||||
for(InputEvent* i = inputs.first; i; i = i.next)
|
for(InputEvent* i = inputs.first; i; i = i.next)
|
||||||
{
|
{
|
||||||
switch(i.key)
|
switch(i.key)
|
||||||
@ -889,6 +951,7 @@ BeginUI(Inputs* inputs)
|
|||||||
} break;
|
} break;
|
||||||
case Input.MouseMotion:
|
case Input.MouseMotion:
|
||||||
{
|
{
|
||||||
|
mouse_moved = true;
|
||||||
ctx.mouse_pos = IVec2(i.x, i.y);
|
ctx.mouse_pos = IVec2(i.x, i.y);
|
||||||
|
|
||||||
if(!dragging && mouse_down)
|
if(!dragging && mouse_down)
|
||||||
@ -920,6 +983,41 @@ BeginUI(Inputs* inputs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 next_frame = ctx.frame+1;
|
||||||
|
|
||||||
|
// Check current mouse target
|
||||||
|
if(mouse_moved && !Nil(ctx.root_last))
|
||||||
|
{
|
||||||
|
UIItem* last = ctx.root_last;
|
||||||
|
while(!Nil(last.last))
|
||||||
|
{
|
||||||
|
last = last.last;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIKey hovered = ZeroKey();
|
||||||
|
for(UIItem* item = last; !Nil(item); item = Recurse!(false)(item, g_UI_NIL))
|
||||||
|
{
|
||||||
|
Logf("key %s pos %s rect %s %s", item.key.hash_text, ctx.mouse_pos.v, item.rect.p0.v, item.rect.p1.v);
|
||||||
|
if(InBounds(ctx.mouse_pos, &item.rect) && !ZeroKey(item.key))
|
||||||
|
{
|
||||||
|
hovered = item.key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ZeroKey(hovered))
|
||||||
|
{
|
||||||
|
ctx.last_hover_frame = next_frame;
|
||||||
|
ctx.hover_key = hovered;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx.hover_key = ZeroKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.root_first = ctx.root_last = g_UI_NIL;
|
||||||
|
|
||||||
// Clean up items
|
// Clean up items
|
||||||
KVPair!(UIHash, UIItem*)*[] items = GetAllNodes(&ctx.temp_arena, &ctx.items);
|
KVPair!(UIHash, UIItem*)*[] items = GetAllNodes(&ctx.temp_arena, &ctx.items);
|
||||||
foreach(i; 0 .. items.length)
|
foreach(i; 0 .. items.length)
|
||||||
@ -944,10 +1042,12 @@ BeginUI(Inputs* inputs)
|
|||||||
|
|
||||||
// Ctx state
|
// Ctx state
|
||||||
ctx.transient_items = g_UI_NIL;
|
ctx.transient_items = g_UI_NIL;
|
||||||
ctx.frame += 1;
|
ctx.frame = next_frame;
|
||||||
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
|
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
|
||||||
ctx.inputs = inputs;
|
ctx.inputs = inputs;
|
||||||
|
|
||||||
|
assert(!mouse_moved || ZeroKey(ctx.hover_key) || (ctx.frame == ctx.last_hover_frame));
|
||||||
|
|
||||||
ResetStacks(ctx);
|
ResetStacks(ctx);
|
||||||
|
|
||||||
version(ENABLE_RENDERER)
|
version(ENABLE_RENDERER)
|
||||||
@ -973,14 +1073,12 @@ BeginUI(Inputs* inputs)
|
|||||||
ctx.buffers[ctx.f_idx].count = 0;
|
ctx.buffers[ctx.f_idx].count = 0;
|
||||||
ctx.buffers[ctx.f_idx].vtx_offset = 0;
|
ctx.buffers[ctx.f_idx].vtx_offset = 0;
|
||||||
|
|
||||||
// Root Item
|
ctx.animation_rate = 1.0 - pow(2.0, (-30.0f * g_delta));
|
||||||
UISize[2] sizes = [UISize(ST.Pixels, ctx.res.x), UISize(ST.Pixels, ctx.res.y)];
|
ctx.scroll_rate = 1.0 - pow(2.0, (-60.0f * g_delta));
|
||||||
Push!("size_info")(sizes);
|
|
||||||
|
|
||||||
ctx.root = MakeItem("###root");
|
|
||||||
|
|
||||||
Pop!("size_info");
|
// Root Item
|
||||||
Push!("parent")(ctx.root);
|
Push!("size_info")(UIS2(ST.Pixels, ST.Pixels, ctx.res.x, ctx.res.y), true);
|
||||||
|
MakeItem("###root");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -989,7 +1087,7 @@ EndUI()
|
|||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
|
|
||||||
// Automatic signals
|
// Automatic signals
|
||||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(false)(item, g_UI_NIL))
|
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(false)(item, g_UI_NIL))
|
||||||
{
|
{
|
||||||
if(item.flags & AUTO_FLAGS)
|
if(item.flags & AUTO_FLAGS)
|
||||||
{
|
{
|
||||||
@ -1026,7 +1124,7 @@ EndUI()
|
|||||||
static foreach(axis; A2D.min .. A2D.max)
|
static foreach(axis; A2D.min .. A2D.max)
|
||||||
{
|
{
|
||||||
// Pixel sizes
|
// Pixel sizes
|
||||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||||
{
|
{
|
||||||
if(item.size_info[axis].type == ST.Pixels)
|
if(item.size_info[axis].type == ST.Pixels)
|
||||||
{
|
{
|
||||||
@ -1040,7 +1138,7 @@ EndUI()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Percentage sizes
|
// Percentage sizes
|
||||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||||
{
|
{
|
||||||
if(item.size_info[axis].type == ST.Percentage)
|
if(item.size_info[axis].type == ST.Percentage)
|
||||||
{
|
{
|
||||||
@ -1061,7 +1159,7 @@ EndUI()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sum of children sizes
|
// Sum of children sizes
|
||||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(false)(item, g_UI_NIL))
|
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(false)(item, g_UI_NIL))
|
||||||
{
|
{
|
||||||
if(item.size_info[axis].type == ST.ChildrenSum)
|
if(item.size_info[axis].type == ST.ChildrenSum)
|
||||||
{
|
{
|
||||||
@ -1083,7 +1181,7 @@ EndUI()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Violations
|
// Violations
|
||||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||||
{
|
{
|
||||||
f32 size = InnerSize!(axis)(item);
|
f32 size = InnerSize!(axis)(item);
|
||||||
|
|
||||||
@ -1155,7 +1253,7 @@ EndUI()
|
|||||||
// Calculate final sizes
|
// Calculate final sizes
|
||||||
{
|
{
|
||||||
f32 pos = 0.0;
|
f32 pos = 0.0;
|
||||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||||
{
|
{
|
||||||
item.last_relative_item = g_UI_NIL;
|
item.last_relative_item = g_UI_NIL;
|
||||||
|
|
||||||
@ -1196,7 +1294,10 @@ EndUI()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Render Items
|
// Render Items
|
||||||
RenderItems(ctx.root);
|
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||||
|
{
|
||||||
|
RenderItem(ctx, item);
|
||||||
|
}
|
||||||
|
|
||||||
version(ENABLE_RENDERER)
|
version(ENABLE_RENDERER)
|
||||||
{
|
{
|
||||||
@ -1206,13 +1307,13 @@ EndUI()
|
|||||||
SubmitAndPresent(&ctx.rd);
|
SubmitAndPresent(&ctx.rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Nil(ctx.drag_item))
|
if(!ZeroKey(ctx.drag_key))
|
||||||
{
|
{
|
||||||
for(UIInput* i = ctx.events.first; !CheckNil(g_UI_NIL_INPUT, i); i = i.next)
|
for(UIInput* i = ctx.events.first; !CheckNil(g_UI_NIL_INPUT, i); i = i.next)
|
||||||
{
|
{
|
||||||
if(i.type == UIE.DragRelease)
|
if(i.type == UIE.DragRelease)
|
||||||
{
|
{
|
||||||
ctx.drag_item = g_UI_NIL;
|
ctx.drag_key = ZeroKey();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1377,16 +1478,6 @@ RenderItem(UICtx* ctx, UIItem* item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
RenderItems(UIItem* root)
|
|
||||||
{
|
|
||||||
UICtx* ctx = GetCtx();
|
|
||||||
for(UIItem* item = root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
|
||||||
{
|
|
||||||
RenderItem(ctx, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32[2]
|
u32[2]
|
||||||
GetExtent()
|
GetExtent()
|
||||||
{
|
{
|
||||||
@ -1405,104 +1496,6 @@ StackIDs(string stack, string ctx = "ctx")
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PushSizeInfo(SizeType type0, f32 value0, f32 strictness0, SizeType type1, f32 value1, f32 strictness1, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
UISize[2] size_info = [
|
|
||||||
UISize(type0, value0, strictness0),
|
|
||||||
UISize(type1, value1, strictness1),
|
|
||||||
];
|
|
||||||
|
|
||||||
Push!("size_info")(size_info, auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushSizeInfoVec(int i)(SizeType type, f32 value, f32 strictness = 1.0, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
UISize[2] size_info = g_size_info_default;
|
|
||||||
|
|
||||||
size_info[i].type = type;
|
|
||||||
size_info[i].value = value;
|
|
||||||
size_info[i].strictness = strictness;
|
|
||||||
|
|
||||||
Push!("size_info")(size_info, auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushSizeInfoX(SizeType type, f32 value, f32 strictness = 1.0, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushSizeInfoVec!(0)(type, value, strictness, auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushSizeInfoY(SizeType type, f32 value, f32 strictness = 1.0, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushSizeInfoVec!(1)(type, value, strictness, auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushCornerRadius(f32 v, bool auto_pop)
|
|
||||||
{
|
|
||||||
Vec4 value = v;
|
|
||||||
Push!("corner_radius")(value, auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushScrollClampVec(int i)(Vec2 clamp, bool auto_pop)
|
|
||||||
{
|
|
||||||
Vec2[2] scroll_clamp = g_scroll_clamp_default;
|
|
||||||
scroll_clamp[i] = clamp;
|
|
||||||
Push!("scroll_clamp")(scroll_clamp, auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushScrollClampX(f32 start, f32 end, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushScrollClampVec!(0)(Vec2(start, end), auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushScrollClampY(f32 start, f32 end, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushScrollClampVec!(1)(Vec2(start, end), auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushPaddingX(f32 padding, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushPadding(Vec2(padding, 0.0), auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushPaddingY(f32 padding, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushPadding(Vec2(0.0, padding), auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushViewOffsetX(f32 offset, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushViewOffset(Vec2(offset, 0.0), auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushViewOffsetY(f32 offset, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushViewOffset(Vec2(0.0, offset), auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushScrollTargetX(f32 target, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushScrollTarget(Vec2(target, 0.0), auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushScrollTargetY(f32 target, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
PushScrollTarget(Vec2(0.0, target), auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
static string
|
static string
|
||||||
PushScope(string stack, string value)()
|
PushScope(string stack, string value)()
|
||||||
{
|
{
|
||||||
@ -1824,6 +1817,12 @@ HexCol(u64 col)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
KeyEq(UIKey k0, UIKey k1)
|
||||||
|
{
|
||||||
|
return k0.hash == k1.hash;
|
||||||
|
}
|
||||||
|
|
||||||
static UIKey
|
static UIKey
|
||||||
ZeroKey()
|
ZeroKey()
|
||||||
{
|
{
|
||||||
@ -2088,6 +2087,68 @@ Vec2A2(f32 x0, f32 y0, f32 x1, f32 y1)
|
|||||||
return [Vec2(x0, y0), Vec2(x1, y1)];
|
return [Vec2(x0, y0), Vec2(x1, y1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static f32
|
||||||
|
SRGB(f32 v)
|
||||||
|
{
|
||||||
|
return v < 0.0031308 ? v * 12.92 : pow(v, 0.41666) * 1.055 - 0.055;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vec4
|
||||||
|
LinearToSRGB(Vec4 v)
|
||||||
|
{
|
||||||
|
return Vec4(SRGB(v.v[0]), SRGB(v.v[1]), SRGB(v.v[2]), v.v[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vec4
|
||||||
|
SRGBVec4(f32 v)
|
||||||
|
{
|
||||||
|
return LinearToSRGB(Vec4(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vec4
|
||||||
|
SRGBVec4(f32 r, f32 g, f32 b, f32 a)
|
||||||
|
{
|
||||||
|
return LinearToSRGB(Vec4(r, g, b, a));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vec4
|
||||||
|
SRGBToOklab(Vec4 v)
|
||||||
|
{
|
||||||
|
f32 l = 0.4122214708f * v.r + 0.5363325363f * v.g + 0.0514459929f * v.b;
|
||||||
|
f32 m = 0.2119034982f * v.r + 0.6806995451f * v.g + 0.1073969566f * v.b;
|
||||||
|
f32 s = 0.0883024619f * v.r + 0.2817188376f * v.g + 0.6299787005f * v.b;
|
||||||
|
|
||||||
|
f32 l_ = cbrtf(l);
|
||||||
|
f32 m_ = cbrtf(m);
|
||||||
|
f32 s_ = cbrtf(s);
|
||||||
|
|
||||||
|
return Vec4(
|
||||||
|
0.2104542553f*l_ + 0.7936177850f*m_ - 0.0040720468f*s_,
|
||||||
|
1.9779984951f*l_ - 2.4285922050f*m_ + 0.4505937099f*s_,
|
||||||
|
0.0259040371f*l_ + 0.7827717662f*m_ - 0.8086757660f*s_,
|
||||||
|
v.a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vec4
|
||||||
|
OklabToSRGB(Vec4 v)
|
||||||
|
{
|
||||||
|
f32 l_ = v.r + 0.3963377774f * v.g + 0.2158037573f * v.b;
|
||||||
|
f32 m_ = v.r - 0.1055613458f * v.g - 0.0638541728f * v.b;
|
||||||
|
f32 s_ = v.r - 0.0894841775f * v.g - 1.2914855480f * v.b;
|
||||||
|
|
||||||
|
float l = l_*l_*l_;
|
||||||
|
float m = m_*m_*m_;
|
||||||
|
float s = s_*s_*s_;
|
||||||
|
|
||||||
|
return Vec4(
|
||||||
|
+4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s,
|
||||||
|
-1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s,
|
||||||
|
-0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s,
|
||||||
|
v.a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
{ // UI Key
|
{ // UI Key
|
||||||
|
|||||||
@ -259,7 +259,7 @@ CommandPalette(CmdPalette* cmd)
|
|||||||
];
|
];
|
||||||
|
|
||||||
mixin(PushOnce!(cmd_params));
|
mixin(PushOnce!(cmd_params));
|
||||||
UIItem* cmd_item = MakeItem("###cmd_palette", UIF.Window|UIF.FixedPosition|UIF.DrawBackground|UIF.DrawBorder);
|
UIItem* cmd_item = MakeItem("###cmd_palette", UIF.Window|UIF.FixedPosition|UIF.DrawBackground|UIF.DrawBorder|UIF.AnimateReady);
|
||||||
|
|
||||||
f32 padding_y = 4.0;
|
f32 padding_y = 4.0;
|
||||||
|
|
||||||
@ -296,11 +296,20 @@ CommandPalette(CmdPalette* cmd)
|
|||||||
Vec4(0.35, 0.35, 0.35, 1.0),
|
Vec4(0.35, 0.35, 0.35, 1.0),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Active should be highlights around the item like File Pilot
|
||||||
|
|
||||||
for(u64 i = 0; i < cmd.opt_strs.length && i < max_opts; i += 1)
|
for(u64 i = 0; i < cmd.opt_strs.length && i < max_opts; i += 1)
|
||||||
{
|
{
|
||||||
PushDisplayString(Str(cmd.opt_strs[i]), true);
|
PushDisplayString(Str(cmd.opt_strs[i]), true);
|
||||||
PushBgCol(cmd.selected == i ? HL_BG_COL : opt_cols[i%2], true);
|
PushBgCol(opt_cols[i%2], true);
|
||||||
MakeItem(zero, UIF.DrawBackground|UIF.DrawText);
|
|
||||||
|
UIKey k = MakeKey("###copt_%s", i);
|
||||||
|
if(Hovered!(true)(k))
|
||||||
|
{
|
||||||
|
cmd.selected = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
MakeItem(k, UIF.DrawBackground|UIF.DrawText|UIF.AnimateHot|(cmd.selected == i ? UIF.SetHot : UIF.None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user