start work on some ui changes
This commit is contained in:
parent
dcb0d620c7
commit
57c56ce650
221
src/editor/ui.d
221
src/editor/ui.d
@ -104,48 +104,49 @@ alias A2D = Axis2D;
|
||||
enum UIFlags : u64
|
||||
{
|
||||
None = 0,
|
||||
DrawBackground = 1<<0,
|
||||
DrawText = 1<<1,
|
||||
DrawBorder = 1<<2,
|
||||
Clickable = 1<<3,
|
||||
Draggable = 1<<4,
|
||||
ScrollX = 1<<5,
|
||||
ScrollY = 1<<6,
|
||||
ClampX = 1<<7,
|
||||
ClampY = 1<<8,
|
||||
Resizeable = 1<<9,
|
||||
ResizeAdjacent = 1<<10,
|
||||
FloatingWindow = 1<<11, // todo
|
||||
Window = 1<<12,
|
||||
TextInput = 1<<13, // todo
|
||||
RightAlignText = 1<<14,
|
||||
CenterAlignText = 1<<15, // todo
|
||||
TextWrap = 1<<16,
|
||||
PortalViewX = 1<<17,
|
||||
PortalViewY = 1<<18,
|
||||
FixedPosition = 1<<19,
|
||||
FixedPosAnimated = 1<<20, // todo: add fixed_pos_target then interpolate position every frame
|
||||
OverflowX = 1<<21,
|
||||
OverflowY = 1<<22,
|
||||
Gradient = 1<<23,
|
||||
VerticalAlignText = 1<<24,
|
||||
SetHot = 1<<25,
|
||||
SetReady = 1<<26,
|
||||
SetActive = 1<<27,
|
||||
AnimateReady = 1<<28, // Fade in/out
|
||||
AnimateHot = 1<<29, // Hover highlight
|
||||
AnimateActive = 1<<30, // Animate selected (probably do later)
|
||||
DrawDropShadow = 1<<31,
|
||||
DrawBackground = 1LU<<0,
|
||||
DrawText = 1LU<<1,
|
||||
DrawBorder = 1LU<<2,
|
||||
Clickable = 1LU<<3,
|
||||
Draggable = 1LU<<4,
|
||||
ScrollX = 1LU<<5,
|
||||
ScrollY = 1LU<<6,
|
||||
ClampX = 1LU<<7,
|
||||
ClampY = 1LU<<8,
|
||||
Resizeable = 1LU<<9,
|
||||
ResizeAdjacent = 1LU<<10,
|
||||
FloatingWindow = 1LU<<11, // todo
|
||||
Window = 1LU<<12,
|
||||
TextInput = 1LU<<13, // todo
|
||||
RightAlignText = 1LU<<14,
|
||||
CenterAlignText = 1LU<<15, // todo
|
||||
TextWrap = 1LU<<16,
|
||||
ScissorX = 1LU<<17,
|
||||
ScissorY = 1LU<<18,
|
||||
FixedPosition = 1LU<<19,
|
||||
FixedPosAnimated = 1LU<<20, // todo: add fixed_pos_target then interpolate position every frame
|
||||
OverflowX = 1LU<<21,
|
||||
OverflowY = 1LU<<22,
|
||||
Gradient = 1LU<<23,
|
||||
VerticalAlignText = 1LU<<24,
|
||||
SetHot = 1LU<<25,
|
||||
SetReady = 1LU<<26,
|
||||
SetActive = 1LU<<27,
|
||||
AnimateReady = 1LU<<28, // Fade in/out
|
||||
AnimateHot = 1LU<<29, // Hover highlight
|
||||
AnimateActive = 1LU<<30, // Animate selected (probably do later)
|
||||
DrawDropShadow = 1LU<<31,
|
||||
ScrollFitChildren = 1LU<<32,
|
||||
|
||||
Clamp = UIFlags.ClampX | UIFlags.ClampY,
|
||||
PortalView = UIFlags.PortalViewX | UIFlags.PortalViewY,
|
||||
Scissor = UIFlags.ScissorX | UIFlags.ScissorY,
|
||||
Scroll = UIFlags.ScrollX | UIFlags.ScrollY,
|
||||
Overflow = UIFlags.OverflowX | UIFlags.OverflowY,
|
||||
}
|
||||
alias UIF = UIFlags;
|
||||
|
||||
const UIFlags AUTO_FLAGS = UIF.ResizeAdjacent;
|
||||
const UIFlags DRAW_FLAGS = UIF.DrawBackground|UIF.DrawBorder|UIF.DrawText|UIF.PortalView|UIF.DrawDropShadow;
|
||||
const UIFlags DRAW_FLAGS = UIF.DrawBackground|UIF.DrawBorder|UIF.DrawText|UIF.Scissor|UIF.DrawDropShadow;
|
||||
|
||||
enum UISignal
|
||||
{
|
||||
@ -388,10 +389,11 @@ struct UIItem
|
||||
string[] text_lines;
|
||||
u8[][] token_lines;
|
||||
Vec2 scroll_offset;
|
||||
Vec2 scroll_size;
|
||||
u8[] text_buffer;
|
||||
f32 max_text_width;
|
||||
f32 resize_pct;
|
||||
bool rendered;
|
||||
bool processed;
|
||||
|
||||
f32 ready_t; // Item visible
|
||||
f32 hot_t; // Item to be interacted with (e.g. hover)
|
||||
@ -814,24 +816,6 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(KeyType!(T))
|
||||
|
||||
static foreach(axis; A2D.min .. A2D.max)
|
||||
{
|
||||
if(item.flags & (UIF.ScrollX << axis))
|
||||
{
|
||||
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) > 0.0009)
|
||||
{
|
||||
f32 v = ctx.scroll_rate * (item.scroll_target.v[axis] - item.scroll_offset.v[axis]);
|
||||
item.scroll_offset.v[axis] += v;
|
||||
|
||||
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) < 2.0)
|
||||
{
|
||||
item.scroll_offset.v[axis] = item.scroll_target.v[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(item.flags & (UIF.ClampX << axis))
|
||||
{
|
||||
item.scroll_offset.v[axis] = clamp(item.scroll_offset.v[axis], item.scroll_clamp[axis].x, item.scroll_clamp[axis].y);
|
||||
}
|
||||
}
|
||||
|
||||
if(item.flags & UIF.AnimateHot)
|
||||
@ -854,7 +838,7 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(KeyType!(T))
|
||||
}
|
||||
|
||||
item.last_frame = ctx.frame;
|
||||
item.rendered = false;
|
||||
item.processed = false;
|
||||
|
||||
return item;
|
||||
}
|
||||
@ -961,10 +945,9 @@ Signal(UIItem* item)
|
||||
|
||||
assert(!ZeroKey(item.key), "Zero key passed to Signal");
|
||||
|
||||
bool mouse_over = KeyEq(ctx.hover_key, item.key);
|
||||
if(item.signal == UIS.None && !ZeroKey(item.key))
|
||||
{
|
||||
bool mouse_over = KeyEq(ctx.hover_key, item.key);
|
||||
|
||||
if(mouse_over)
|
||||
{
|
||||
item.signal |= UIS.Hovered;
|
||||
@ -1008,6 +991,21 @@ Signal(UIItem* item)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(item.flags & UIF.ResizeAdjacent && ZeroKey(ctx.drag_key))
|
||||
{
|
||||
for(UIInput* i = ctx.events.first; !CheckNil(g_UI_NIL_INPUT, i); i = i.next)
|
||||
{
|
||||
if(mouse_over && i.type == UIE.DragStart)
|
||||
{
|
||||
item.signal |= UIS.Dragged;
|
||||
}
|
||||
|
||||
if(item.signal & UIS.Dragged)
|
||||
{
|
||||
item.dragged += i.rel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1268,11 +1266,6 @@ EndUI()
|
||||
else if(item.size_info[axis].type == ST.TextSize)
|
||||
{
|
||||
f32 size = axis == A2D.X ? item.max_text_width : GetFontAtlas(item.text_size).atlas.line_height * item.text_lines.length;
|
||||
if(axis == A2D.Y)
|
||||
{
|
||||
// Logf("line height %f %f %f", size, floor(size), AxisPadding!(axis)(item));
|
||||
|
||||
}
|
||||
item.size.v[axis] = floor(size) + AxisPadding!(axis)(item);
|
||||
}
|
||||
}
|
||||
@ -1325,7 +1318,7 @@ EndUI()
|
||||
{
|
||||
f32 size = InnerSize!(axis)(item);
|
||||
|
||||
if(item.flags & (UIF.PortalViewX << axis))
|
||||
if(item.flags & ((UIF.ScissorX << axis) | (UIF.ScrollX << axis)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1390,6 +1383,45 @@ EndUI()
|
||||
}
|
||||
}
|
||||
|
||||
// Scrollable Size Calculation & Offsets
|
||||
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||
{
|
||||
if(item.flags & UIF.ScrollFitChildren)
|
||||
{
|
||||
f32 scroll_size = 0.0;
|
||||
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||
{
|
||||
scroll_size += c.size.v[axis];
|
||||
}
|
||||
|
||||
item.scroll_size.v[axis] = scroll_size;
|
||||
}
|
||||
|
||||
if(item.flags & (UIF.ScrollX << axis))
|
||||
{
|
||||
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) > 0.0009)
|
||||
{
|
||||
f32 v = ctx.scroll_rate * (item.scroll_target.v[axis] - item.scroll_offset.v[axis]);
|
||||
item.scroll_offset.v[axis] += v;
|
||||
|
||||
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) < 2.0)
|
||||
{
|
||||
item.scroll_offset.v[axis] = item.scroll_target.v[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(item.flags & ((UIF.ClampX << axis) | UIF.ScrollFitChildren))
|
||||
{
|
||||
f32 upper = item.scroll_size.v[axis] >= item.size.v[axis] ? item.scroll_size.v[axis]-item.size.v[axis] : 0.0;
|
||||
item.scroll_offset.v[axis] = clamp(item.scroll_offset.v[axis], 0.0, upper);
|
||||
}
|
||||
else if(item.flags & (UIF.ClampX << axis))
|
||||
{
|
||||
item.scroll_offset.v[axis] = clamp(item.scroll_offset.v[axis], item.scroll_clamp[axis].x, item.scroll_clamp[axis].y);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate final sizes
|
||||
{
|
||||
f32 pos = 0.0;
|
||||
@ -1431,7 +1463,23 @@ EndUI()
|
||||
assert(!isNaN(item.rect.p1.v[axis]));
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate offsets for scrollable windows
|
||||
{
|
||||
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||
{
|
||||
if(item.flags & (UIF.ScrollX << axis))
|
||||
{
|
||||
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||
{
|
||||
c.rect.p0.v[axis] -= item.scroll_offset.v[axis];
|
||||
c.rect.p1.v[axis] -= item.scroll_offset.v[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Render Items
|
||||
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||
@ -1487,6 +1535,22 @@ EndUI()
|
||||
}
|
||||
}
|
||||
|
||||
UIItem*
|
||||
NextNonChild(UIItem* item)
|
||||
{
|
||||
UIItem* first = item.first;
|
||||
UIItem* last = item.last;
|
||||
|
||||
item.first = item.last = g_UI_NIL;
|
||||
|
||||
UIItem* next = Recurse!(true)(item, g_UI_NIL);
|
||||
|
||||
item.first = first;
|
||||
item.last = last;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
void
|
||||
FocusItem(Args...)(string str, Args args)
|
||||
{
|
||||
@ -1509,7 +1573,7 @@ FocusItem(T)(T focus) if(ItemAndKeyType!(T))
|
||||
pragma(inline) void
|
||||
RenderItem(UICtx* ctx, UIItem* item)
|
||||
{
|
||||
if(item.rendered) return;
|
||||
if(item.processed) return;
|
||||
if(!(item.flags & DRAW_FLAGS)) return;
|
||||
|
||||
Vec2 border_p0 = item.rect.p0 - Vec2(InnerOffset!(A2D.X, true )(item), InnerOffset!(A2D.Y, true )(item));
|
||||
@ -1628,8 +1692,10 @@ RenderItem(UICtx* ctx, UIItem* item)
|
||||
}
|
||||
|
||||
// Doesn't really support nesting scissors, will maybe change this later.
|
||||
bool scissor_x = cast(bool)(item.flags & UIF.PortalViewX);
|
||||
bool scissor_y = cast(bool)(item.flags & UIF.PortalViewY);
|
||||
bool scissor_x = cast(bool)(item.flags & UIF.ScissorX);
|
||||
bool scissor_y = cast(bool)(item.flags & UIF.ScissorY);
|
||||
scissor_x |= cast(bool)(item.flags & UIF.ScrollX);
|
||||
scissor_y |= cast(bool)(item.flags & UIF.ScrollY);
|
||||
if(scissor_x || scissor_y )
|
||||
{
|
||||
DrawUI(ctx);
|
||||
@ -1641,20 +1707,25 @@ RenderItem(UICtx* ctx, UIItem* item)
|
||||
|
||||
SetScissor(&ctx.rd, x, y, w, h);
|
||||
|
||||
UIItem* first = item.first;
|
||||
UIItem* last = item.last;
|
||||
|
||||
item.first = item.last = g_UI_NIL;
|
||||
|
||||
UIItem* next = Recurse!(true)(item, g_UI_NIL);
|
||||
|
||||
item.first = first;
|
||||
item.last = last;
|
||||
UIItem* next = NextNonChild(item);
|
||||
|
||||
bool scroll_x = cast(bool)(item.flags & UIF.ScrollX);
|
||||
bool scroll_y = cast(bool)(item.flags & UIF.ScrollY);
|
||||
if(scroll_x || scroll_y)
|
||||
{
|
||||
for(UIItem* d = item.first; !Nil(d) && d != next; d = Recurse!(true)(d, g_UI_NIL))
|
||||
{
|
||||
if(scroll_x && (d.rect.p1.x < item.rect.p0.x || d.rect.p0.x > item.rect.p1.x)) { d.processed = true; continue; }
|
||||
if(scroll_y && (d.rect.p1.y < item.rect.p0.y || d.rect.p0.y > item.rect.p1.y)) { d.processed = true; continue; }
|
||||
|
||||
RenderItem(ctx, d);
|
||||
d.rendered = true;
|
||||
d.processed = true;
|
||||
}
|
||||
}
|
||||
else for(UIItem* d = item.first; !Nil(d) && d != next; d = Recurse!(true)(d, g_UI_NIL))
|
||||
{
|
||||
RenderItem(ctx, d);
|
||||
d.processed = true;
|
||||
}
|
||||
|
||||
DrawUI(ctx);
|
||||
|
||||
@ -70,7 +70,7 @@ LineCounterView(FontAtlasBuf* abuf, u64 max_line, u64 lines, i64 line_offset, f3
|
||||
|
||||
mixin(PushOnce!(lc_params));
|
||||
|
||||
UIItem* line_count = MakeItem(ZERO, UIF.DrawBorder|UIF.PortalViewY);
|
||||
UIItem* line_count = MakeItem(ZERO, UIF.DrawBorder|UIF.ScissorY);
|
||||
|
||||
mixin(PushScope!("text_col", q{ Vec4(1.0) } ));
|
||||
mixin(PushScope!("size_info", q{ UISY(ST.Pixels, abuf.atlas.line_height) } ));
|
||||
@ -97,20 +97,42 @@ EditorTextView(UIItem* editor, Panel* p, FontAtlasBuf* abuf, u64 lines, i64 line
|
||||
f32 scroll_pos = cast(f32)(ed.line_offset)*text_size;
|
||||
f32 padding = 8.0;
|
||||
|
||||
f32 scroll_target = 0.0;
|
||||
static bool toggled = true;
|
||||
static f32 t = 0.0;
|
||||
if(toggled)
|
||||
{
|
||||
scroll_target = 0.0;
|
||||
t += g_delta;
|
||||
if(t > 0.5)
|
||||
{
|
||||
toggled = !toggled;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scroll_target = 1000.0;
|
||||
t -= g_delta;
|
||||
if(t < 0.0)
|
||||
{
|
||||
toggled = !toggled;
|
||||
}
|
||||
}
|
||||
|
||||
enum UIPushInfo[] text_view_params = [
|
||||
{ "layout_axis", q{ A2D.Y } },
|
||||
{ "border_col", q{ Vec4(1.0) } },
|
||||
{ "size_info", q{ UIS2() } },
|
||||
{ "scroll_target", q{ Vec2(0.0, scroll_pos) } },
|
||||
{ "scroll_clamp", q{ Vec2(0.0, clamp_y) } },
|
||||
{ "view_offset", q{ Vec2(0.0, view_offset) } },
|
||||
{ "scroll_target", q{ Vec2(0.0, scroll_target) } },
|
||||
//{ "scroll_clamp", q{ Vec2(0.0, clamp_y) } },
|
||||
//{ "view_offset", q{ Vec2(0.0, view_offset) } },
|
||||
{ "padding", q{ Vec2(4.0) } },
|
||||
{ "edge_softness", q{ 0.0 } },
|
||||
{ "border_thickness", q{ 1.0 } },
|
||||
];
|
||||
mixin(PushOnce!(text_view_params));
|
||||
|
||||
editor = MakeItem(editor.key, UIF.DrawBorder|UIF.ScrollY|UIF.ClampY|UIF.PortalViewY);
|
||||
editor = MakeItem(editor.key, UIF.DrawBorder|UIF.ScrollY|UIF.ClampY|UIF.ScissorY|UIF.ScrollFitChildren);
|
||||
|
||||
mixin(PushScope!("parent", q{ editor }));
|
||||
|
||||
@ -139,6 +161,12 @@ EditorTextView(UIItem* editor, Panel* p, FontAtlasBuf* abuf, u64 lines, i64 line
|
||||
mixin(PushScope!("size_info", q{ UISY(ST.TextSize) } ));
|
||||
mixin(PushScope!("syntax_highlight", q{ UISH.D } ));
|
||||
|
||||
for(u64 i = 0; i < 200; i += 1)
|
||||
{
|
||||
MakeItem("%s", i, UIF.DrawText);
|
||||
}
|
||||
|
||||
/*
|
||||
u64 i = line_offset;
|
||||
for(LineBuffer* lb = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, lb) && i < line_offset+lines; i += 1, lb = GetLine(&ed.buf, i))
|
||||
{
|
||||
@ -148,6 +176,7 @@ EditorTextView(UIItem* editor, Panel* p, FontAtlasBuf* abuf, u64 lines, i64 line
|
||||
|
||||
UIItem* line = MakeItem(zero, UIF.DrawText);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user