more ui work
This commit is contained in:
parent
49501a32aa
commit
0387acfcc7
@ -145,19 +145,39 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
|
||||
|
||||
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] blue = Vec4(0.1, 0.3, 0.9, 1.0);
|
||||
Vec4[4] black = Vec4(0.0, 0.0, 0.0, 1.0);
|
||||
Vec4[4] green = Vec4(0.2, 0.8, 0.1, 1.0);
|
||||
Vec4[4] white = Vec4(1.0);
|
||||
|
||||
Push!("border_thickness", true)(ui_ctx, 10.0f);
|
||||
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|UIF.DrawBorder);
|
||||
|
||||
Push!("layout_axis", true)(ui_ctx, A2D.Y);
|
||||
Push!("parent", true)(ui_ctx, p0);
|
||||
Push!("size_info", true)(ui_ctx, MakeUISize(UISize(ST.ChildrenSum, 1.0), UISize(ST.Percentage, 1.0)));
|
||||
Push!("bg_col", true)(ui_ctx, blue);
|
||||
UIItem* ln = MakeItem("###ln", UIF.DrawBackground);
|
||||
|
||||
Push!("parent")(ui_ctx, ln);
|
||||
Push!("bg_col")(ui_ctx, white);
|
||||
Push!("padding")(ui_ctx, Vec2(4.0, 0.0));
|
||||
Push!("size_info")(ui_ctx, MakeUISize(UISize(ST.TextSize, 1.0), UISize(ST.Pixels, ui_ctx.char_height)));
|
||||
|
||||
foreach(i; 0 .. 99)
|
||||
{
|
||||
MakeItem("%s##ln", i, UIF.DrawText);
|
||||
}
|
||||
|
||||
Pop!("padding", "size_info", "parent", "bg_col")(ui_ctx);
|
||||
|
||||
Push!("size_info", true)(ui_ctx, MakeUISize(UISize(ST.Pixels, 200.0), UISize(ST.Pixels, 80.0)));
|
||||
Push!("parent", true)(ui_ctx, p0);
|
||||
Push!("bg_col", true)(ui_ctx, green);
|
||||
Push!("padding", true)(ui_ctx, Vec2(4.0));
|
||||
UIItem* text = MakeItem("Haha##text", UIF.DrawBackground|UIF.DrawText);
|
||||
UIItem* text = MakeItem("Haha0##text", UIF.DrawBackground|UIF.DrawText|UIF.RightAlignText|UIF.TextWrap);
|
||||
|
||||
Push!("size_info", true)(ui_ctx, MakeUISizeX(ST.Pixels, 2.0));
|
||||
Push!("bg_col", true)(ui_ctx, black);
|
||||
|
||||
266
src/editor/ui.d
266
src/editor/ui.d
@ -95,23 +95,26 @@ alias A2D = Axis2D;
|
||||
|
||||
enum UIFlags
|
||||
{
|
||||
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,
|
||||
CenteredWindow = 1<<12,
|
||||
TextInput = 1<<13,
|
||||
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,
|
||||
CenteredWindow = 1<<12,
|
||||
TextInput = 1<<13,
|
||||
RightAlignText = 1<<14,
|
||||
CenterAlignText = 1<<15,
|
||||
TextWrap = 1<<16,
|
||||
|
||||
Clamp = UIFlags.ClampX | UIFlags.ClampY,
|
||||
Clamp = UIFlags.ClampX | UIFlags.ClampY,
|
||||
}
|
||||
alias UIF = UIFlags;
|
||||
|
||||
@ -128,12 +131,12 @@ alias UIS = UISignal;
|
||||
|
||||
enum UIEvent
|
||||
{
|
||||
None = 0,
|
||||
Click = 1<<0,
|
||||
None = 0,
|
||||
Click = 1<<0,
|
||||
DragRelease = 1<<1,
|
||||
Drag = 1<<2,
|
||||
DragStart = 1<<3,
|
||||
Press = 1<<4,
|
||||
Drag = 1<<2,
|
||||
DragStart = 1<<3,
|
||||
Press = 1<<4,
|
||||
}
|
||||
alias UIE = UIEvent;
|
||||
|
||||
@ -214,6 +217,7 @@ struct UICtx
|
||||
FontFace font;
|
||||
FontAtlasBuf atlas_buf;
|
||||
f32 char_width;
|
||||
f32 char_height;
|
||||
|
||||
UIBuffer[FRAME_OVERLAP] buffers;
|
||||
|
||||
@ -300,7 +304,8 @@ struct UIItem
|
||||
Vec2 size;
|
||||
|
||||
f32 resize_pct;
|
||||
u8[] display_string;
|
||||
string display_string;
|
||||
string[] text_lines;
|
||||
|
||||
mixin UIItemParameters!();
|
||||
}
|
||||
@ -310,6 +315,7 @@ enum SizeType
|
||||
Pixels,
|
||||
Percentage,
|
||||
ChildrenSum,
|
||||
TextSize,
|
||||
}
|
||||
|
||||
alias ST = SizeType;
|
||||
@ -363,8 +369,8 @@ alias UIPair = KVPair!(UIHash, UIItem*);
|
||||
|
||||
struct UIKey
|
||||
{
|
||||
u8[] text, hash_text;
|
||||
u64 hash;
|
||||
string text, hash_text;
|
||||
u64 hash;
|
||||
}
|
||||
|
||||
struct UIPanel
|
||||
@ -441,7 +447,8 @@ InitUICtx(PlatformWindow* window)
|
||||
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);
|
||||
ctx.atlas_buf = CreateAtlas(&arena, ctx.font, 16.0, 256);
|
||||
ctx.char_height = cast(f32)((ctx.font.size.metrics.ascender - ctx.font.size.metrics.descender) >> 6);
|
||||
|
||||
version(ENABLE_RENDERER)
|
||||
{
|
||||
@ -528,6 +535,26 @@ Set(UIItem* item, UICtx* ctx)
|
||||
}
|
||||
}
|
||||
|
||||
UIItem*
|
||||
MakeItem(Args...)(string str, Args args)
|
||||
{
|
||||
UIItem* item = g_UI_NIL;
|
||||
|
||||
static if(Args.length)
|
||||
{
|
||||
enum has_flag = Args[Args.length-1].stringof == UIFlags.stringof;
|
||||
|
||||
UIFlags flags = has_flag ? args[args.length-1] : UIF.None;
|
||||
enum len = has_flag ? Args.length-1 : Args.length;
|
||||
|
||||
char[] key = sformat(ScratchAlloc!(char)(cast(u64)(str.length*1.5)), str, args[0 .. len]);
|
||||
|
||||
item = MakeItem(key, flags);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
UIItem*
|
||||
MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
||||
{
|
||||
@ -560,9 +587,61 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
||||
}
|
||||
}
|
||||
|
||||
item.last_frame = ctx.frame;
|
||||
string str = item.display_string.length ? item.display_string : item.key.text;
|
||||
if(item.flags & UIF.TextWrap)
|
||||
{
|
||||
f32 width = item.size_info[A2D.X].type == ST.TextSize ? item.parent.size.x : item.size.x;
|
||||
f32 text_width = CalcTextWidth(str);
|
||||
|
||||
item.padding += item.border_thickness;
|
||||
if(text_width < width || width == 0.0) goto InitSingleLine;
|
||||
|
||||
u64 lines = cast(u64)(ceil(text_width/width));
|
||||
item.text_lines = ScratchAlloc!(string)(lines);
|
||||
|
||||
f32 w = 0.0;
|
||||
u64 line = 0;
|
||||
u64 ch_start = 0;
|
||||
Glyph[] glyphs = ctx.atlas_buf.atlas.glyphs;
|
||||
|
||||
for(u64 i = 0; i < str.length; i += 1)
|
||||
{
|
||||
Glyph* g = str[i] < glyphs.length ? glyphs.ptr+str[i] : glyphs.ptr+0;
|
||||
|
||||
f32 glyph_w = GlyphWidth(g);
|
||||
if(glyph_w+w > width)
|
||||
{
|
||||
item.text_lines[line++] = str[ch_start .. i];
|
||||
ch_start = i;
|
||||
|
||||
if(line == lines-1)
|
||||
{
|
||||
item.text_lines[line] = str[ch_start .. $];
|
||||
break;
|
||||
}
|
||||
|
||||
w = 0.0;
|
||||
}
|
||||
|
||||
w += glyph_w;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InitSingleLine:
|
||||
item.text_lines = ScratchAlloc!(string)(1);
|
||||
item.text_lines[0] = str;
|
||||
}
|
||||
|
||||
item.last_frame = ctx.frame;
|
||||
item.padding += item.border_thickness;
|
||||
|
||||
if(item.text_lines.length > 1)
|
||||
{
|
||||
foreach(i; 0 .. item.text_lines.length)
|
||||
{
|
||||
Logf("line %s: %s", i, item.text_lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
@ -782,7 +861,18 @@ EndUI()
|
||||
{
|
||||
if(item.size_info[axis].type == ST.Pixels)
|
||||
{
|
||||
item.size.v[axis] = item.size_info[axis].value;
|
||||
item.size.v[axis] = item.padding.v[axis] + item.size_info[axis].value;
|
||||
}
|
||||
else if(item.size_info[axis].type == ST.TextSize)
|
||||
{
|
||||
static if(axis == A2D.X)
|
||||
{
|
||||
item.size.v[axis] = item.padding.x*2.0 + CalcTextWidth(item.display_string.length ? item.display_string : item.key.text);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.size.v[axis] = item.padding.y*2.0 + TEXT_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -812,10 +902,19 @@ EndUI()
|
||||
{
|
||||
if(item.size_info[axis].type == ST.ChildrenSum)
|
||||
{
|
||||
f32 size = 0.0;
|
||||
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||
if(item.layout_axis == axis)
|
||||
{
|
||||
size += c.size.v[axis];
|
||||
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||
{
|
||||
item.size.v[axis] += c.size.v[axis];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||
{
|
||||
item.size.v[axis] = item.size.v[axis] < c.size.v[axis] ? c.size.v[axis] : item.size.v[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -872,10 +971,7 @@ EndUI()
|
||||
{
|
||||
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||
{
|
||||
if(c.size.v[axis] > size)
|
||||
{
|
||||
c.size.v[axis] = size;
|
||||
}
|
||||
c.size.v[axis] = c.size.v[axis] > size ? size : c.size.v[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -885,7 +981,16 @@ EndUI()
|
||||
f32 pos = 0.0;
|
||||
for(UIItem* item = ctx.root; !Nil(item);)
|
||||
{
|
||||
f32 inner_pos = pos + item.parent.padding.v[axis];
|
||||
if(item.parent.layout_axis != axis)
|
||||
{
|
||||
pos = item.parent.rect.p0.v[axis] + item.parent.padding.v[axis];
|
||||
}
|
||||
else if(item == item.parent.first)
|
||||
{
|
||||
pos += item.parent.padding.v[axis];
|
||||
}
|
||||
|
||||
f32 inner_pos = pos;
|
||||
f32 next_pos = 0.0;
|
||||
f32 end_pos = inner_pos + item.size.v[axis];
|
||||
|
||||
@ -925,7 +1030,6 @@ EndUI()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Render Items
|
||||
RenderItems(ctx.root);
|
||||
RenderItems(ctx.window_root);
|
||||
@ -962,8 +1066,8 @@ RenderItems(UIItem* root)
|
||||
{
|
||||
// DrawRect
|
||||
Vertex* v = GetVertex(ctx);
|
||||
v.dst_start = item.rect.p0; // - item.border_thickness;
|
||||
v.dst_end = item.rect.p1; // + item.border_thickness;
|
||||
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;
|
||||
|
||||
@ -983,16 +1087,28 @@ RenderItems(UIItem* root)
|
||||
AddVertexCount(ctx);
|
||||
}
|
||||
|
||||
if(item.flags & UIF.DrawText)
|
||||
if(item.flags & UIF.DrawText || item.display_string)
|
||||
{
|
||||
FontAtlas* atl = &ctx.atlas_buf.atlas;
|
||||
f32 x_pos = item.rect.p0.x + item.border_thickness + item.padding.x;
|
||||
f32 y_pos = item.rect.p0.y + item.border_thickness + item.padding.y;
|
||||
foreach(i; 0 .. item.key.text.length)
|
||||
string str = item.display_string ? item.display_string : item.key.text;
|
||||
|
||||
if(item.flags & UIF.CenterAlignText)
|
||||
{
|
||||
u8 ch = item.key.text[i];
|
||||
Glyph* g = ch < atl.glyphs.length ? atl.glyphs.ptr + ch : null;
|
||||
DrawGlyph(item, g, &x_pos, y_pos);
|
||||
// TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
FontAtlas* atl = &ctx.atlas_buf.atlas;
|
||||
|
||||
f32 x_pos = item.flags & UIF.RightAlignText ? item.rect.p1.x - item.padding.x - CalcTextWidth(str) :
|
||||
item.rect.p0.x + item.padding.x;
|
||||
|
||||
f32 y_pos = item.rect.p0.y + item.padding.y;
|
||||
foreach(i; 0 .. str.length)
|
||||
{
|
||||
u8 ch = str[i];
|
||||
Glyph* g = ch < atl.glyphs.length ? atl.glyphs.ptr + ch : null;
|
||||
DrawGlyph(item, g, &x_pos, y_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1072,6 +1188,15 @@ Pop(string stack_str)(UICtx* ctx)
|
||||
return pop.value;
|
||||
}
|
||||
|
||||
void
|
||||
Pop(stack_strs...)(UICtx* ctx)
|
||||
{
|
||||
static foreach(stack; stack_strs)
|
||||
{
|
||||
Pop!(stack)(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AutoPopStacks(UICtx* ctx)
|
||||
{
|
||||
@ -1225,11 +1350,11 @@ MakeKey(T)(T str) if(StringType!T)
|
||||
{
|
||||
static if(is(T: string))
|
||||
{
|
||||
u8[] id = CastStr!(u8)(str);
|
||||
string id = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8[] id = cast(u8[])str;
|
||||
string id = ConvToStr(str);
|
||||
}
|
||||
|
||||
UIKey key;
|
||||
@ -1264,8 +1389,8 @@ MakeKey(T)(T str) if(StringType!T)
|
||||
|
||||
if(hash_count < 2 || hash_only)
|
||||
{
|
||||
key.text = hash_only ? [] : id;
|
||||
key.hash_text = hash_only ? id : [];
|
||||
key.text = hash_only ? "" : id;
|
||||
key.hash_text = hash_only ? id : "";
|
||||
key.hash = Hash(id);
|
||||
}
|
||||
else if(hash_count == 2 || hash_count == 3)
|
||||
@ -1313,7 +1438,7 @@ Get(T)(T k) if(is(T: UIKey) || StringType!T)
|
||||
}
|
||||
|
||||
f32
|
||||
CalcTextWidth(u8[] str)
|
||||
CalcTextWidth(string str)
|
||||
{
|
||||
u32 tab_width = g_ui_ctx.tab_width;
|
||||
Glyph* space = g_ui_ctx.atlas_buf.atlas.glyphs.ptr + ' ';
|
||||
@ -1363,20 +1488,18 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y)
|
||||
f32 b = glyph.plane_bottom * item.text_scale;
|
||||
|
||||
GlyphBounds gb = {
|
||||
r: r,
|
||||
l: l,
|
||||
t: t,
|
||||
b: b,
|
||||
w: r - l,
|
||||
h: b - t,
|
||||
atlas_r: glyph.atlas_right,
|
||||
atlas_l: glyph.atlas_left,
|
||||
atlas_t: glyph.atlas_top,
|
||||
atlas_b: glyph.atlas_bottom,
|
||||
r: r,
|
||||
l: l,
|
||||
t: t,
|
||||
b: b,
|
||||
w: r - l,
|
||||
h: b - t,
|
||||
atlas_r: glyph.atlas_right,
|
||||
atlas_l: glyph.atlas_left,
|
||||
atlas_t: glyph.atlas_top,
|
||||
atlas_b: glyph.atlas_bottom,
|
||||
};
|
||||
|
||||
f32 y_pos = t;
|
||||
|
||||
v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
||||
|
||||
v.dst_start = Vec2(*x_pos+gb.l, y);
|
||||
@ -1392,15 +1515,22 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y)
|
||||
|
||||
f32 end_x = *x_pos + advance;
|
||||
f32 width = end_x - *x_pos;
|
||||
if(end_x > item.rect.p1.x)
|
||||
f32 bound_x = item.flags & UIF.RightAlignText ? item.rect.p0.x : item.rect.p1.x;
|
||||
if(item.flags & UIF.RightAlignText && bound_x > *x_pos)
|
||||
{
|
||||
f32 cull_pct = (end_x - item.rect.p1.x) / width;
|
||||
f32 cull_pct = (bound_x - *x_pos) / width;
|
||||
v.dst_start.x += (v.dst_end.x - v.dst_start.x) * cull_pct;
|
||||
v.src_start.x += (v.src_end.x - v.src_start.x) * cull_pct;
|
||||
}
|
||||
else if(!(item.flags & UIF.RightAlignText) && end_x > bound_x)
|
||||
{
|
||||
f32 cull_pct = (end_x - bound_x) / width;
|
||||
v.dst_end.x -= (v.dst_end.x - v.dst_start.x) * cull_pct;
|
||||
v.src_end.x -= (v.src_end.x - v.src_start.x) * cull_pct;
|
||||
}
|
||||
|
||||
f32 end_y = y_pos + TEXT_SIZE;
|
||||
f32 height = end_y - y_pos;
|
||||
f32 end_y = y + TEXT_SIZE;
|
||||
f32 height = end_y - y;
|
||||
if(end_y > item.rect.p1.y)
|
||||
{
|
||||
f32 cull_pct = (end_y - item.rect.p1.y) / height;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user