more ui work
This commit is contained in:
parent
ec19c26071
commit
2703c95673
@ -21,16 +21,16 @@ debug bool g_frame_continue = false;
|
||||
|
||||
struct EditorCtx
|
||||
{
|
||||
Arena arena;
|
||||
Arena arena;
|
||||
PlatformWindow* window;
|
||||
UIPanel* base_panel;
|
||||
u64 panel_id;
|
||||
EditState state;
|
||||
u8[128] input_buf;
|
||||
u32 icount;
|
||||
Timer timer;
|
||||
CmdPalette cmd;
|
||||
u8[][] file_names;
|
||||
UIPanel* base_panel;
|
||||
u64 panel_id;
|
||||
EditState state;
|
||||
u8[128] input_buf;
|
||||
u32 icount;
|
||||
Timer timer;
|
||||
CmdPalette cmd;
|
||||
u8[][] file_names;
|
||||
}
|
||||
|
||||
struct CmdPalette
|
||||
@ -141,7 +141,33 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
|
||||
|
||||
BeginUI(ctx, inputs);
|
||||
|
||||
for(auto p = ctx.base_panel; !Nil(p); p = Recurse(p))
|
||||
UIPanel* root = ctx.base_panel;
|
||||
|
||||
root.size.x = g_ui_ctx.res.x;
|
||||
root.size.y = g_ui_ctx.res.y;
|
||||
root.rect.vec0 = 0.0;
|
||||
root.rect.vec1 = 0.0;
|
||||
|
||||
static foreach(axis; A2D.min .. A2D.max)
|
||||
{
|
||||
for(UIPanel* p = root; !Nil(p); p = Recurse(p, root, g_UI_NIL_PANEL))
|
||||
{
|
||||
f32 pos = p.rect.vec0.v[axis];
|
||||
for(UIPanel* c = p.first; !Nil(c); c = c.next)
|
||||
{
|
||||
c.size.v[axis] = p.axis == axis ? c.pct * p.size.v[axis] : p.size.v[axis];
|
||||
c.rect.vec0.v[axis] = pos;
|
||||
c.rect.vec1.v[axis] = pos + c.size.v[axis];
|
||||
|
||||
if(axis == p.axis)
|
||||
{
|
||||
pos += c.size.v[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(auto p = ctx.base_panel; !Nil(p); p = Recurse(p, ctx.base_panel, g_UI_NIL_PANEL))
|
||||
{
|
||||
Panel(p);
|
||||
}
|
||||
|
||||
236
src/editor/ui.d
236
src/editor/ui.d
@ -19,6 +19,14 @@ import core.stdc.math : fabsf;
|
||||
import std.conv;
|
||||
import core.stdc.stdio : sprintf;
|
||||
|
||||
/****** IMPORTANT NOTES *********
|
||||
|
||||
- Display string should be separate from key string
|
||||
- If key is 0 then its transient and will be discarded next frame
|
||||
- Events should be created then processed instead of directly from inputs
|
||||
|
||||
*********************************/
|
||||
|
||||
enum Vec4[4] BG_COL = Vec4(0.13, 0.13, 0.13, 1.0);
|
||||
enum Vec4[4] BG_HL_COL = Vec4(0.24, 0.45, 0.81, 1.0);
|
||||
enum Vec4[4] BORDER_COL = Vec4(0.254, 0.254, 0.266, 1.0);
|
||||
@ -48,7 +56,8 @@ Vec4[4] g_bg_hl_col_default = BG_HL_COL;
|
||||
Vec4[4] g_border_col_default = BORDER_COL;
|
||||
Vec4[4] g_border_hl_col_default = BORDER_HL_COL;
|
||||
Vec4 g_text_col_default = TEXT_COL;
|
||||
Vec4 g_text_hl_col_default = TEXT_HL_COL;
|
||||
Vec4 g_text_hl_col_default = TEXT_HL_COL;
|
||||
UISize[2] g_size_info_default = [UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0)];
|
||||
|
||||
const UI_COUNT = 5000;
|
||||
|
||||
@ -114,26 +123,22 @@ enum UISignal
|
||||
|
||||
alias UIS = UISignal;
|
||||
|
||||
enum SizeType
|
||||
{
|
||||
Pixels,
|
||||
Percentage,
|
||||
FitChild,
|
||||
}
|
||||
|
||||
alias ST = SizeType;
|
||||
|
||||
|
||||
mixin template UICtxParameter(T, string name)
|
||||
mixin template
|
||||
UICtxParameter(T, string name)
|
||||
{
|
||||
static string
|
||||
CtxParameterGen(string type, string name)()
|
||||
CtxParameterGen(T, string name)()
|
||||
{
|
||||
return type ~ " " ~ name ~ ";";
|
||||
import std.traits;
|
||||
import std.array;
|
||||
|
||||
string stack_top = "\tStackTop!("~T.stringof~") "~name~";\n";
|
||||
string stack = "\tStack!("~T.stringof~")* "~name~"_top;\n";
|
||||
|
||||
return stack_top~stack;
|
||||
}
|
||||
|
||||
mixin(CtxParameterGen!((StackTop!(T)).stringof, name)());
|
||||
mixin(CtxParameterGen!((Stack!(T)*).stringof, name~"_top")());
|
||||
mixin(CtxParameterGen!(T, name)());
|
||||
}
|
||||
|
||||
template CtxMemberInfo(int i)
|
||||
@ -173,7 +178,7 @@ struct UICtx
|
||||
u64 frame;
|
||||
u64 f_idx;
|
||||
|
||||
PlatformWindow* window;
|
||||
PlatformWindow* window;
|
||||
Renderer rd;
|
||||
Descriptor font_atlas;
|
||||
Descriptor sampler;
|
||||
@ -194,20 +199,22 @@ struct UICtx
|
||||
u32 tab_width;
|
||||
f32 text_size;
|
||||
|
||||
UIItem* root;
|
||||
UIItem* drag_item;
|
||||
UIPanel* parent_panel;
|
||||
UIPanel* focused_panel;
|
||||
|
||||
mixin UICtxParameter!(UIItem*, "parent");
|
||||
mixin UICtxParameter!(f32, "corner_radius");
|
||||
mixin UICtxParameter!(f32, "border_thickness");
|
||||
mixin UICtxParameter!(f32, "edge_softness");
|
||||
mixin UICtxParameter!(Vec4[4], "bg_col");
|
||||
mixin UICtxParameter!(Vec4[4], "bg_hl_col");
|
||||
mixin UICtxParameter!(Vec4[4], "border_col");
|
||||
mixin UICtxParameter!(Vec4[4], "border_hl_col");
|
||||
mixin UICtxParameter!(Vec4, "text_col");
|
||||
mixin UICtxParameter!(Vec4, "text_hl_col");
|
||||
mixin UICtxParameter!(UIItem*, "parent");
|
||||
mixin UICtxParameter!(f32, "corner_radius");
|
||||
mixin UICtxParameter!(f32, "border_thickness");
|
||||
mixin UICtxParameter!(f32, "edge_softness");
|
||||
mixin UICtxParameter!(Vec4[4], "bg_col");
|
||||
mixin UICtxParameter!(Vec4[4], "bg_hl_col");
|
||||
mixin UICtxParameter!(Vec4[4], "border_col");
|
||||
mixin UICtxParameter!(Vec4[4], "border_hl_col");
|
||||
mixin UICtxParameter!(Vec4, "text_col");
|
||||
mixin UICtxParameter!(Vec4, "text_hl_col");
|
||||
mixin UICtxParameter!(UISize[2], "size_info");
|
||||
|
||||
debug bool dbg;
|
||||
}
|
||||
@ -246,7 +253,6 @@ mixin template UIItemParameters()
|
||||
}
|
||||
|
||||
mixin(UIItemParameterGen());
|
||||
pragma(msg, UIItemParameterGen());
|
||||
}
|
||||
|
||||
struct UIItem
|
||||
@ -257,15 +263,26 @@ struct UIItem
|
||||
|
||||
UIItem* next, prev, first, last; // parent in mixin
|
||||
|
||||
mixin UIItemParameters!();
|
||||
Rect pref_size;
|
||||
Rect size;
|
||||
|
||||
Vec2 p0, p1;
|
||||
mixin UIItemParameters!();
|
||||
}
|
||||
|
||||
enum SizeType
|
||||
{
|
||||
Pixels,
|
||||
Percentage,
|
||||
FitChild,
|
||||
}
|
||||
|
||||
alias ST = SizeType;
|
||||
|
||||
struct UISize
|
||||
{
|
||||
SizeType type;
|
||||
f32 value;
|
||||
f32 strictness = 1.0;
|
||||
}
|
||||
|
||||
struct UIBuffer
|
||||
@ -284,12 +301,12 @@ struct PushConst
|
||||
|
||||
struct GlyphBounds
|
||||
{
|
||||
f32 r = 0.0;
|
||||
f32 l = 0.0;
|
||||
f32 t = 0.0;
|
||||
f32 b = 0.0;
|
||||
f32 w = 0.0;
|
||||
f32 h = 0.0;
|
||||
f32 r = 0.0;
|
||||
f32 l = 0.0;
|
||||
f32 t = 0.0;
|
||||
f32 b = 0.0;
|
||||
f32 w = 0.0;
|
||||
f32 h = 0.0;
|
||||
f32 atlas_r = 0.0;
|
||||
f32 atlas_l = 0.0;
|
||||
f32 atlas_t = 0.0;
|
||||
@ -492,7 +509,6 @@ InitUICtx(PlatformWindow* window)
|
||||
void
|
||||
Set(UIItem* item, UICtx* ctx)
|
||||
{
|
||||
enum char[256] buf = 0;
|
||||
static foreach(i, m; UICtx.tupleof)
|
||||
{
|
||||
static foreach(j, m2; UIItem.tupleof)
|
||||
@ -502,10 +518,7 @@ Set(UIItem* item, UICtx* ctx)
|
||||
enum item_id = __traits(identifier, UIItem.tupleof[j]);
|
||||
static if(ctx_id == item_id)
|
||||
{
|
||||
enum line = sformat(buf, "item.%s = ctx.%s.top.value;", item_id, ctx_id);
|
||||
mixin(line);
|
||||
pragma(msg, i);
|
||||
pragma(msg, line);
|
||||
mixin("item."~item_id~" = ctx."~ctx_id~".top.value;\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -565,7 +578,7 @@ BeginUI(EditorCtx* edctx, Inputs* inputs)
|
||||
memset(ctx.buffers[ctx.f_idx].idx.ptr, 0, u32.sizeof * ctx.buffers[ctx.f_idx].count);
|
||||
ctx.buffers[ctx.f_idx].count = 0;
|
||||
|
||||
SetPanelSizes(edctx.base_panel);
|
||||
ctx.root = Root(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
@ -573,6 +586,17 @@ EndUI()
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
|
||||
static foreach(axis; A2D.min .. A2D.max)
|
||||
{
|
||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, ctx.root, g_UI_NIL))
|
||||
{
|
||||
if(item.size_info[axis].type == ST.Pixels)
|
||||
{
|
||||
item.size.v[axis] = item.size_info[axis].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
with(ctx)
|
||||
{
|
||||
BindBuffers(&rd, &buffers[f_idx].m_idx, &buffers[f_idx].m_vtx);
|
||||
@ -585,6 +609,14 @@ EndUI()
|
||||
ctx.frame += 1;
|
||||
}
|
||||
|
||||
UIItem*
|
||||
Root(UICtx* ctx)
|
||||
{
|
||||
UISize[2] sizes = [UISize(ST.Pixels, ctx.res.x), UISize(ST.Pixels, ctx.res.y)];
|
||||
Push!("size_info")(ctx, sizes);
|
||||
return MakeItem("###root");
|
||||
}
|
||||
|
||||
template StackIDs(string stack)
|
||||
{
|
||||
import std.string : replace;
|
||||
@ -709,6 +741,26 @@ ResetStacks(UICtx* ctx)
|
||||
}
|
||||
}
|
||||
|
||||
T*
|
||||
Recurse(bool pre = true, T)(T* panel, T* root, T* nil)
|
||||
{
|
||||
T* result = nil;
|
||||
if(!Nil(panel.first))
|
||||
{
|
||||
result = pre ? panel.first : panel.last;
|
||||
}
|
||||
else for(T* p = panel; !Nil(p) && p != root; p = p.parent)
|
||||
{
|
||||
if(!Nil(pre ? p.next : p.prev))
|
||||
{
|
||||
result = pre ? p.next : p.prev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
f32
|
||||
LineCounterWidth(u32 char_width)
|
||||
{
|
||||
@ -721,36 +773,6 @@ InnerSize(UIPanel* panel)
|
||||
return panel.size - Vec2(g_ui_ctx.border_thickness_top.value*2.0);;
|
||||
}
|
||||
|
||||
void
|
||||
SetPanelSizes(UIPanel* panel)
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
|
||||
panel.size.x = ctx.res.x;
|
||||
panel.size.y = ctx.res.y;
|
||||
panel.rect.vec0 = 0.0;
|
||||
panel.rect.vec1 = 0.0;
|
||||
|
||||
static foreach(axis; A2D.min .. A2D.max)
|
||||
{
|
||||
for(UIPanel* p = panel; !Nil(p); p = Recurse(p))
|
||||
{
|
||||
f32 pos = p.rect.vec0.v[axis];
|
||||
for(UIPanel* c = p.first; !Nil(c); c = c.next)
|
||||
{
|
||||
c.size.v[axis] = p.axis == axis ? c.pct * p.size.v[axis] : p.size.v[axis];
|
||||
c.rect.vec0.v[axis] = pos;
|
||||
c.rect.vec1.v[axis] = pos + c.size.v[axis];
|
||||
|
||||
if(axis == p.axis)
|
||||
{
|
||||
pos += c.size.v[axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pragma(inline) void
|
||||
DrawChar(u8 ch, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
||||
{
|
||||
@ -758,27 +780,6 @@ DrawChar(u8 ch, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
||||
DrawGlyph(g, 1.0, x_pos, y, col);
|
||||
}
|
||||
|
||||
bool
|
||||
PrintInputs()
|
||||
{
|
||||
bool result;
|
||||
UICtx* ctx = GetCtx();
|
||||
|
||||
for(auto n = ctx.inputs.list.first; n != null; n = n.next)
|
||||
{
|
||||
Logf("key %s %s %s", n.value.key, n.value.x, n.value.y);
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
f32
|
||||
EaseOutQuint(f32 x)
|
||||
{
|
||||
return 1.0 - pow(1.0 - x, 5);
|
||||
}
|
||||
|
||||
void
|
||||
SetScrollOffset(UIPanel* panel)
|
||||
{
|
||||
@ -809,7 +810,6 @@ SetScrollOffset(UIPanel* panel)
|
||||
|
||||
if(fabsf(panel.scroll_offset-panel.scroll_target) < 0.0009)
|
||||
{
|
||||
Logf("end");
|
||||
panel.scroll_offset = panel.scroll_target;
|
||||
}
|
||||
}
|
||||
@ -875,17 +875,11 @@ MakeKey(T)(T str) if(StringType!T)
|
||||
key.hash_text = hash_only ? id : [];
|
||||
key.hash = Hash(id);
|
||||
}
|
||||
else if(hash_count == 2)
|
||||
else if(hash_count == 2 || hash_count == 3)
|
||||
{
|
||||
key.text = id[0 .. pos];
|
||||
key.hash_text = id[pos .. $];
|
||||
key.hash = Hash(id);
|
||||
}
|
||||
else if(hash_count == 3)
|
||||
{
|
||||
key.text = id[0 .. pos];
|
||||
key.hash_text = id[pos .. $];
|
||||
key.hash = Hash(id[pos+hash_count .. $]);
|
||||
key.hash = hash_count == 2 ? Hash(id) : Hash(id[pos+hash_count .. $]);
|
||||
}
|
||||
|
||||
return key;
|
||||
@ -1259,44 +1253,6 @@ Dragged(UIItem* item, Vec2 p0, Vec2 p1)
|
||||
return result;
|
||||
}
|
||||
|
||||
u8[]
|
||||
ScratchName(u64 num_len, u8[] base, u64 iteration)
|
||||
{
|
||||
import core.stdc.stdio : sprintf;
|
||||
|
||||
char[64] ch_buf;
|
||||
char[] s = ch_buf.sformat("%%0%sllu%%s", num_len);
|
||||
|
||||
u8[] id = ScratchAlloc!(u8)(base.length+num_len);
|
||||
sprintf(cast(char*)id.ptr, s.ptr, iteration, cast(char*)base.ptr);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
u8[]
|
||||
ScratchName(string fmt, u64 len, u64 iteration)
|
||||
{
|
||||
u8[] id = ScratchAlloc!(u8)(len);
|
||||
(cast(char[])id).sformat(fmt, iteration);
|
||||
return id;
|
||||
}
|
||||
|
||||
u8[]
|
||||
ScratchName(u8[] base, u8[] append)
|
||||
{
|
||||
u8[] id = ScratchAlloc!(u8)(base.length+append.length);
|
||||
id[0 .. base.length] = base[0 .. $];
|
||||
id[base.length .. $] = append[0 .. $];
|
||||
return id;
|
||||
}
|
||||
|
||||
u8[]
|
||||
ScratchName(u8[] base, string append)
|
||||
{
|
||||
u8[] u8_append = CastStr!(u8)(append);
|
||||
return ScratchName(base, u8_append);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
{ // UI Key
|
||||
|
||||
@ -161,30 +161,6 @@ CommandPalette(CmdPalette* cmd)
|
||||
}
|
||||
}
|
||||
|
||||
UIPanel*
|
||||
Recurse(UIPanel* panel)
|
||||
{
|
||||
UIPanel* result = g_UI_NIL_PANEL;
|
||||
if(!Nil(panel.first))
|
||||
{
|
||||
result = panel.first;
|
||||
}
|
||||
else if(!Nil(panel.next))
|
||||
{
|
||||
result = panel.next;
|
||||
}
|
||||
else for(UIPanel* p = panel.parent; !Nil(p); p = p.parent)
|
||||
{
|
||||
if(!Nil(p.next))
|
||||
{
|
||||
result = p.next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
CheckPanelBounds(f32 pct)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user