start work on ui layout frameowkr
This commit is contained in:
parent
91f2914c46
commit
e30d8f6689
@ -679,6 +679,7 @@ unittest
|
|||||||
|
|
||||||
// FlatBuffer lines
|
// FlatBuffer lines
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
u8[] data = StringToU8("This is a line.\nThis is a second line,\nalong with a third line.");
|
u8[] data = StringToU8("This is a line.\nThis is a second line,\nalong with a third line.");
|
||||||
FlatBuffer buf = CreateFlatBuffer(data);
|
FlatBuffer buf = CreateFlatBuffer(data);
|
||||||
|
|
||||||
@ -727,5 +728,6 @@ unittest
|
|||||||
assert(lines[i][j] == ch, "FlatBuffer GetLines 2 failure: result strings do not match");
|
assert(lines[i][j] == ch, "FlatBuffer GetLines 2 failure: result strings do not match");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,8 +24,6 @@ struct Editor
|
|||||||
Arena temp_arena;
|
Arena temp_arena;
|
||||||
PlatformWindow* window;
|
PlatformWindow* window;
|
||||||
|
|
||||||
UIContext ctx;
|
|
||||||
|
|
||||||
Renderer rd;
|
Renderer rd;
|
||||||
ImageView font_atlas;
|
ImageView font_atlas;
|
||||||
Pipeline pipeline;
|
Pipeline pipeline;
|
||||||
@ -33,8 +31,6 @@ struct Editor
|
|||||||
DescSet desc_set;
|
DescSet desc_set;
|
||||||
PipelineLayout pipeline_layout;
|
PipelineLayout pipeline_layout;
|
||||||
PushConst pc;
|
PushConst pc;
|
||||||
MappedBuffer!(Vertex) m_vertex_buf;
|
|
||||||
MappedBuffer!(u32) m_index_buf;
|
|
||||||
|
|
||||||
FlatBuffer[] buffers;
|
FlatBuffer[] buffers;
|
||||||
Tokenizer[] tokenizers;
|
Tokenizer[] tokenizers;
|
||||||
@ -50,13 +46,6 @@ struct Editor
|
|||||||
UVec2 res;
|
UVec2 res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIBuffer
|
|
||||||
{
|
|
||||||
Vertex[] vtx;
|
|
||||||
u32[] idx;
|
|
||||||
u32 count;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PushConst
|
struct PushConst
|
||||||
{
|
{
|
||||||
Mat4 projection;
|
Mat4 projection;
|
||||||
@ -76,69 +65,6 @@ struct Vertex
|
|||||||
u32 texture;
|
u32 texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Cycle(Editor* ed)
|
|
||||||
{
|
|
||||||
Reset(&ed.temp_arena);
|
|
||||||
Reset(&ed.ctx);
|
|
||||||
|
|
||||||
//DrawRect(&ed.ctx, 200.0, 200.0, 300.0, 300.0, 0.0, 0.0, 0.0, Vec4(0.2, 0.4, 0.8, 1.0));
|
|
||||||
//DrawRect(&ed.ctx, 330.0, 330.0, 430.0, 430.0, 0.0, 0.0, 0.0, Vec4(0.2, 0.4, 0.8, 1.0));
|
|
||||||
Vec4 col = Vec4(0.2, 0.5, 0.9, 1.0);
|
|
||||||
Vec4 col2 = Vec4(0.2, 0.4, 0.7, 1.0);
|
|
||||||
Vec4 col3 = Vec4(0.2, 0.3, 0.65, 1.0);
|
|
||||||
Vec4 black = Vec4(0.0, 0.0, 0.0, 1.0);
|
|
||||||
DrawRect(&ed.ctx, -1000.0, -1000.0, 3000.0, 3000.0, 0.0, 0.0, 0.0, 0.0, col);
|
|
||||||
//DrawRect(&ed.ctx, 450.0, 450.0, 550.0, 550.0, 2.0, 5.0, 0.2, 20.0, [black, black, black, black]);
|
|
||||||
|
|
||||||
f32 pos = 0.0;
|
|
||||||
f32 h = ed.atlas_buf.atlas.size;
|
|
||||||
DrawBuffer(ed, 0.0, 0.0, h, ed.active_buffer);
|
|
||||||
|
|
||||||
BeginFrame(&ed.rd);
|
|
||||||
|
|
||||||
UVec2 ext = UVec2(GetExtent(&ed.rd));
|
|
||||||
if (ext != ed.res)
|
|
||||||
{
|
|
||||||
ed.res = ext;
|
|
||||||
Ortho(&ed.pc.projection, 0.0, 0.0, cast(f32)(ext.x), cast(f32)(ext.y), 1000.0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
BeginRendering(&ed.rd);
|
|
||||||
|
|
||||||
PushConstants(&ed.rd, ed.pipeline, &ed.pc);
|
|
||||||
|
|
||||||
Bind(&ed.rd, ed.pipeline, ed.desc_set);
|
|
||||||
|
|
||||||
BindBuffers(&ed.rd, &ed.m_index_buf, &ed.m_vertex_buf);
|
|
||||||
|
|
||||||
DrawIndexed(&ed.rd, 6, ed.ctx.buffer.count, 0);
|
|
||||||
|
|
||||||
FinishRendering(&ed.rd);
|
|
||||||
|
|
||||||
SubmitAndPresent(&ed.rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8[]
|
|
||||||
LoadFile(Arena* arena, string name)
|
|
||||||
{
|
|
||||||
File f;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
f = File(name, "rb");
|
|
||||||
}
|
|
||||||
catch (ErrnoException e)
|
|
||||||
{
|
|
||||||
assert(false, "Unable to open file");
|
|
||||||
}
|
|
||||||
|
|
||||||
u8[] data = AllocArray!(u8)(arena, f.size());
|
|
||||||
f.rawRead(data);
|
|
||||||
f.close();
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
Editor
|
Editor
|
||||||
CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name)
|
CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name)
|
||||||
{
|
{
|
||||||
@ -231,10 +157,8 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name)
|
|||||||
|
|
||||||
assert(CreateGraphicsPipeline(&editor.rd, &editor.pipeline, &ui_info), "Unable to build UI pipeline");
|
assert(CreateGraphicsPipeline(&editor.rd, &editor.pipeline, &ui_info), "Unable to build UI pipeline");
|
||||||
|
|
||||||
editor.m_vertex_buf = CreateMappedBuffer!(Vertex)(&editor.rd, BT.Vertex, Vertex.sizeof * UI_COUNT);
|
InitUIContext(&editor.rd);
|
||||||
editor.m_index_buf = CreateMappedBuffer!(u32)(&editor.rd, BT.Index, u32.sizeof * UI_COUNT);
|
SetProp!(CtxP.FontAtlas)(editor.atlas_buf.atlas);
|
||||||
|
|
||||||
editor.ctx = CreateUIContext(editor.m_vertex_buf.data, editor.m_index_buf.data);
|
|
||||||
|
|
||||||
CreateImageView(&editor.rd, &editor.font_atlas, editor.atlas_buf.atlas.width, editor.atlas_buf.atlas.height, 4, editor.atlas_buf.data);
|
CreateImageView(&editor.rd, &editor.font_atlas, editor.atlas_buf.atlas.width, editor.atlas_buf.atlas.height, 4, editor.atlas_buf.data);
|
||||||
|
|
||||||
@ -247,6 +171,36 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name)
|
|||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cycle(Editor* ed)
|
||||||
|
{
|
||||||
|
Reset(&ed.temp_arena);
|
||||||
|
UIBeginFrame();
|
||||||
|
|
||||||
|
f32 pos = 0.0;
|
||||||
|
f32 h = ed.atlas_buf.atlas.size;
|
||||||
|
DrawBuffer(ed, 0.0, 0.0, h, ed.active_buffer);
|
||||||
|
|
||||||
|
BeginFrame(&ed.rd);
|
||||||
|
|
||||||
|
UVec2 ext = UVec2(GetExtent(&ed.rd));
|
||||||
|
if (ext != ed.res)
|
||||||
|
{
|
||||||
|
ed.res = ext;
|
||||||
|
Ortho(&ed.pc.projection, 0.0, 0.0, cast(f32)(ext.x), cast(f32)(ext.y), 1000.0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
BeginRendering(&ed.rd);
|
||||||
|
|
||||||
|
PushConstants(&ed.rd, ed.pipeline, &ed.pc);
|
||||||
|
|
||||||
|
Bind(&ed.rd, ed.pipeline, ed.desc_set);
|
||||||
|
|
||||||
|
FinishRendering(&ed.rd);
|
||||||
|
|
||||||
|
SubmitAndPresent(&ed.rd);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawText(Editor* ed, f32 x, f32 y, f32 px, string str)
|
DrawText(Editor* ed, f32 x, f32 y, f32 px, string str)
|
||||||
{
|
{
|
||||||
@ -272,18 +226,18 @@ DrawText(Editor* ed, f32 x, f32 y, f32 px, u8[] str)
|
|||||||
g.atlas_left = g.atlas_right = 0.0;
|
g.atlas_left = g.atlas_right = 0.0;
|
||||||
foreach(i; 0 .. tab_count)
|
foreach(i; 0 .. tab_count)
|
||||||
{
|
{
|
||||||
DrawGlyph(&ed.ctx, &g, scale, &x_pos, y);
|
DrawGlyph(&g, scale, &x_pos, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ch == '\n')
|
else if (ch == '\n')
|
||||||
{
|
{
|
||||||
Glyph g = glyph;
|
Glyph g = glyph;
|
||||||
g.atlas_left = g.atlas_right = 0.0;
|
g.atlas_left = g.atlas_right = 0.0;
|
||||||
DrawGlyph(&ed.ctx, &g, scale, &x_pos, y);
|
DrawGlyph(&g, scale, &x_pos, y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DrawGlyph(&ed.ctx, &glyph, scale, &x_pos, y);
|
DrawGlyph(&glyph, scale, &x_pos, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -331,19 +285,19 @@ DrawBuffer(Editor* ed, f32 x, f32 y, f32 px, FlatBuffer* fb)
|
|||||||
g.atlas_left = g.atlas_right = 0.0;
|
g.atlas_left = g.atlas_right = 0.0;
|
||||||
foreach(j; 0 .. tab_count)
|
foreach(j; 0 .. tab_count)
|
||||||
{
|
{
|
||||||
DrawGlyph(&ed.ctx, g, scale, &x_pos, y_pos);
|
DrawGlyph(g, scale, &x_pos, y_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ch == '\n')
|
else if (ch == '\n')
|
||||||
{
|
{
|
||||||
g.atlas_left = g.atlas_right = 0.0;
|
g.atlas_left = g.atlas_right = 0.0;
|
||||||
DrawGlyph(&ed.ctx, g, scale, &x_pos, y_pos);
|
DrawGlyph(g, scale, &x_pos, y_pos);
|
||||||
y_pos += px;
|
y_pos += px;
|
||||||
x_pos = 0.0;
|
x_pos = 0.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DrawGlyph(&ed.ctx, g, scale, &x_pos, y_pos, cols[fb.tk.buffer[i]]);
|
DrawGlyph(g, scale, &x_pos, y_pos, cols[fb.tk.buffer[i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -618,7 +618,7 @@ ParseId(FlatBuffer* fb)
|
|||||||
assert(t.start < t.end, "ParseId failure: start is lower or equal to end");
|
assert(t.start < t.end, "ParseId failure: start is lower or equal to end");
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): bool
|
pragma(inline) bool
|
||||||
CheckEOL(u8 ch)
|
CheckEOL(u8 ch)
|
||||||
{
|
{
|
||||||
return ch == 0x0D||
|
return ch == 0x0D||
|
||||||
@ -627,7 +627,7 @@ CheckEOL(u8 ch)
|
|||||||
ch == 0x0C;
|
ch == 0x0C;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): bool
|
pragma(inline) bool
|
||||||
CheckWhiteSpace(u8 ch)
|
CheckWhiteSpace(u8 ch)
|
||||||
{
|
{
|
||||||
return ch == ' ' ||
|
return ch == ' ' ||
|
||||||
|
|||||||
375
src/editor/ui.d
375
src/editor/ui.d
@ -7,7 +7,75 @@ import vulkan;
|
|||||||
|
|
||||||
import editor;
|
import editor;
|
||||||
|
|
||||||
enum BaseFlags : u32
|
UIContext g_ui_ctx;
|
||||||
|
const UIItem g_ui_nil_item;
|
||||||
|
UIItem* g_UI_NIL;
|
||||||
|
|
||||||
|
struct UIContext
|
||||||
|
{
|
||||||
|
HashTable!(UIHash, UIItem*) items;
|
||||||
|
Arena arena;
|
||||||
|
Renderer* rd;
|
||||||
|
|
||||||
|
UIBuffer buffer;
|
||||||
|
|
||||||
|
UIItem* root;
|
||||||
|
|
||||||
|
// UI builder state
|
||||||
|
FontAtlas atlas;
|
||||||
|
Vec4[4] bg_cols;
|
||||||
|
Vec4[4] border_cols;
|
||||||
|
UISize[A2D.max] size_axes;
|
||||||
|
Rect padding;
|
||||||
|
u32 tab_width;
|
||||||
|
f32 text_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UIBuffer
|
||||||
|
{
|
||||||
|
MappedBuffer!(Vertex) mapped_vtx;
|
||||||
|
MappedBuffer!(u32) mapped_idx;
|
||||||
|
Vertex[] vtx;
|
||||||
|
u32[] idx;
|
||||||
|
u32 count;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CtxProperty
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
BackgroundColor,
|
||||||
|
BorderColor,
|
||||||
|
SizeKind,
|
||||||
|
SizeValue,
|
||||||
|
SizeStrictness,
|
||||||
|
FontAtlas,
|
||||||
|
AxisX,
|
||||||
|
AxisY,
|
||||||
|
Padding,
|
||||||
|
TextScale,
|
||||||
|
TabWidth,
|
||||||
|
}
|
||||||
|
|
||||||
|
alias CtxP = CtxProperty;
|
||||||
|
|
||||||
|
enum Axis2D
|
||||||
|
{
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Max,
|
||||||
|
}
|
||||||
|
|
||||||
|
alias A2D = Axis2D;
|
||||||
|
|
||||||
|
enum UIRecurse
|
||||||
|
{
|
||||||
|
PostOrder,
|
||||||
|
PreOrder,
|
||||||
|
}
|
||||||
|
|
||||||
|
alias UIR = UIRecurse;
|
||||||
|
|
||||||
|
enum UIProperties : u64
|
||||||
{
|
{
|
||||||
Clickable = (1<<0),
|
Clickable = (1<<0),
|
||||||
ViewScroll = (1<<1),
|
ViewScroll = (1<<1),
|
||||||
@ -18,6 +86,19 @@ enum BaseFlags : u32
|
|||||||
Draggable = (1<<6),
|
Draggable = (1<<6),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alias UIP = UIProperties;
|
||||||
|
|
||||||
|
enum SizeKind : u64
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Pixels,
|
||||||
|
TextContent,
|
||||||
|
PercentOfParent,
|
||||||
|
ChildrenSum,
|
||||||
|
}
|
||||||
|
|
||||||
|
alias SK = SizeKind;
|
||||||
|
|
||||||
union Rect
|
union Rect
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
@ -38,87 +119,169 @@ alias UIHash = u64;
|
|||||||
|
|
||||||
alias UIPair = KVPair!(UIHash, UIItem*);
|
alias UIPair = KVPair!(UIHash, UIItem*);
|
||||||
|
|
||||||
|
struct UISize
|
||||||
|
{
|
||||||
|
SizeKind kind;
|
||||||
|
f32 value;
|
||||||
|
f32 strictness;
|
||||||
|
}
|
||||||
|
|
||||||
struct UIItem
|
struct UIItem
|
||||||
{
|
{
|
||||||
BaseFlags flags;
|
UIProperties flags;
|
||||||
|
|
||||||
|
UIItem* first;
|
||||||
|
UIItem* last;
|
||||||
|
UIItem* next;
|
||||||
|
UIItem* prev;
|
||||||
|
UIItem* parent;
|
||||||
|
|
||||||
|
UISize[A2D.max] size;
|
||||||
|
Rect padding;
|
||||||
|
f32[A2D.max] computed_rel_pos;
|
||||||
|
f32[A2D.max] computed_size;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
f32 text_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIContext
|
struct UIKey
|
||||||
{
|
{
|
||||||
HashTable!(UIHash, UIItem*) items;
|
u8[] text;
|
||||||
Arena arena;
|
u64 hash;
|
||||||
|
|
||||||
UIBuffer buffer;
|
|
||||||
|
|
||||||
Vec4[4] bg_cols;
|
|
||||||
Vec4[4] border_cols;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Reset(UIContext* ctx)
|
UIBeginFrame()
|
||||||
{
|
{
|
||||||
ctx.buffer.count = 0;
|
g_ui_ctx.buffer.count = 0;
|
||||||
}
|
|
||||||
|
|
||||||
UIContext
|
|
||||||
CreateUIContext(Vertex[] vtx, u32[] idx)
|
|
||||||
{
|
|
||||||
UIContext ctx = {
|
|
||||||
items: CreateHashTable!(UIHash, UIItem*)(16),
|
|
||||||
arena: CreateArena(MB(8)),
|
|
||||||
buffer: {
|
|
||||||
vtx: vtx,
|
|
||||||
idx: idx,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetBgCols(UIContext* ctx, Vec4[4] cols)
|
UIFrameSubmit()
|
||||||
{
|
{
|
||||||
ctx.bg_cols = cols;
|
BindBuffers(g_ui_ctx.rd, &g_ui_ctx.buffer.mapped_idx, &g_ui_ctx.buffer.mapped_vtx);
|
||||||
|
DrawIndexed(g_ui_ctx.rd, 6, g_ui_ctx.buffer.count, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetBorderCols(UIContext* ctx, Vec4[4] cols)
|
InitUIContext(Renderer* rd)
|
||||||
{
|
{
|
||||||
ctx.border_cols = cols;
|
g_UI_NIL = cast(UIItem*)&g_ui_nil_item;
|
||||||
|
|
||||||
|
auto vtx = CreateMappedBuffer!(Vertex)(rd, BT.Vertex, Vertex.sizeof * UI_COUNT);
|
||||||
|
auto idx = CreateMappedBuffer!(u32)(rd, BT.Index, u32.sizeof * UI_COUNT);
|
||||||
|
|
||||||
|
g_ui_ctx.root = g_UI_NIL;
|
||||||
|
g_ui_ctx.items = CreateHashTable!(UIHash, UIItem*)(16);
|
||||||
|
g_ui_ctx.arena = CreateArena(MB(8));
|
||||||
|
g_ui_ctx.rd = rd;
|
||||||
|
g_ui_ctx.buffer.mapped_vtx = vtx;
|
||||||
|
g_ui_ctx.buffer.mapped_idx = idx;
|
||||||
|
g_ui_ctx.buffer.vtx = vtx.data;
|
||||||
|
g_ui_ctx.buffer.idx = idx.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIKey
|
||||||
|
MakeKey(u8[] id)
|
||||||
|
{
|
||||||
|
UIKey key;
|
||||||
|
|
||||||
|
u32 pos = 0;
|
||||||
|
u32 hash_count = 0;
|
||||||
|
for(u32 i = 0; i < id.length; i += 1)
|
||||||
|
{
|
||||||
|
if (hash_count == 2)
|
||||||
|
{
|
||||||
|
if (id[i] == '#')
|
||||||
|
{
|
||||||
|
hash_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id[i] == '#')
|
||||||
|
{
|
||||||
|
if (hash_count == 0)
|
||||||
|
{
|
||||||
|
pos = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash_count == 2)
|
||||||
|
{
|
||||||
|
key.text = id[0 .. pos];
|
||||||
|
key.hash = Hash(id);
|
||||||
|
}
|
||||||
|
else if (hash_count == 3)
|
||||||
|
{
|
||||||
|
key.text = id[0 .. pos];
|
||||||
|
key.hash = Hash(id[pos+hash_count .. $]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key.text = id;
|
||||||
|
key.hash = Hash(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItem*
|
||||||
Find(UIContext* ctx, u8[] id)
|
Find(u8[] id)
|
||||||
{
|
{
|
||||||
u64 hash = Hash(id);
|
u64 hash = Hash(id);
|
||||||
Result!(UIItem*) result = ctx.items[hash];
|
Result!(UIItem*) result = g_ui_ctx.items[hash];
|
||||||
if (!result.ok)
|
if (!result.ok)
|
||||||
{
|
{
|
||||||
result.value = Alloc!(UIItem)(&ctx.arena);
|
result.value = Alloc!(UIItem)(&g_ui_ctx.arena);
|
||||||
Push(&ctx.items, hash, result.value);
|
Push(&g_ui_ctx.items, hash, result.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.value;
|
return result.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
UIWindow(UIContext* ctx, Rect rect, f32 border_px, u8[] text)
|
UIWindow(Rect rect, f32 border_px, u8[] text)
|
||||||
{
|
{
|
||||||
UIItem* item = Find(ctx, text);
|
UIItem* item = Find(text);
|
||||||
|
|
||||||
DrawRect(ctx, rect.x0, rect.y0, rect.x1, rect.y1, 0.0, 0.0, 0.0, 0.0, ctx.bg_cols);
|
|
||||||
DrawRect(ctx, rect.x0, rect.y0, rect.x1, rect.y1, border_px, 0.0, 0.0, 0.0, ctx.border_cols);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
f32
|
||||||
DrawGlyph(UIContext* ctx, Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
CalcTextWidth(u8[] str)
|
||||||
|
{
|
||||||
|
u32 tab_width = g_ui_ctx.tab_width;
|
||||||
|
Glyph* space = g_ui_ctx.atlas.glyphs.ptr + ' ';
|
||||||
|
|
||||||
|
f32 width;
|
||||||
|
for(u64 i = 0; i < str.length; i += 1)
|
||||||
|
{
|
||||||
|
Glyph* g = g_ui_ctx.atlas.glyphs.ptr + str.ptr[i];
|
||||||
|
|
||||||
|
if (g.ch == '\t')
|
||||||
|
{
|
||||||
|
width += space.advance * cast(f32)(tab_width);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width += g.advance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return width * g_ui_ctx.text_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline) void
|
||||||
|
DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
||||||
{
|
{
|
||||||
if (glyph.atlas_left != glyph.atlas_right)
|
if (glyph.atlas_left != glyph.atlas_right)
|
||||||
{
|
{
|
||||||
Vertex* v = ctx.buffer.vtx.ptr + ctx.buffer.count;
|
Vertex* v = g_ui_ctx.buffer.vtx.ptr + g_ui_ctx.buffer.count;
|
||||||
|
|
||||||
f32 r = glyph.plane_right * scale;
|
f32 r = glyph.plane_right * scale;
|
||||||
f32 l = glyph.plane_left * scale;
|
f32 l = glyph.plane_left * scale;
|
||||||
@ -143,23 +306,18 @@ DrawGlyph(UIContext* ctx, Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col =
|
|||||||
|
|
||||||
v.texture = 1;
|
v.texture = 1;
|
||||||
|
|
||||||
AddUIIndices(ctx);
|
AddUIIndices();
|
||||||
}
|
}
|
||||||
|
|
||||||
*x_pos += glyph.advance * scale;
|
*x_pos += glyph.advance * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
/*
|
||||||
DrawRect(UIContext* ctx, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, f32 border, f32 corner, f32 softness, f32 raised, Vec4 col)
|
|
||||||
{
|
|
||||||
DrawRect(ctx, p0_x, p0_y, p1_x, p1_y, border, corner, softness, raised, [col, col, col, col]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
DrawRect(UIContext* ctx, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, f32 border, f32 corner, f32 softness, f32 raised, Vec4[4] cols)
|
DrawRect(UIContext* ctx, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, f32 border, f32 corner, f32 softness, f32 raised, Vec4[4] cols)
|
||||||
{
|
{
|
||||||
// Y reversed
|
// Y reversed
|
||||||
Vertex* v = ctx.buffer.vtx.ptr + ctx.buffer.count;
|
Vertex* v = g_ui_ctx.buffer.vtx.ptr + g_ui_ctx.buffer.count;
|
||||||
v.dst_start.x = p0_x;
|
v.dst_start.x = p0_x;
|
||||||
v.dst_start.y = p0_y;
|
v.dst_start.y = p0_y;
|
||||||
v.dst_end.x = p1_x;
|
v.dst_end.x = p1_x;
|
||||||
@ -172,16 +330,115 @@ DrawRect(UIContext* ctx, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, f32 border, f32
|
|||||||
|
|
||||||
AddUIIndices(ctx);
|
AddUIIndices(ctx);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
AddUIIndices(UIContext* ctx)
|
AddUIIndices()
|
||||||
{
|
{
|
||||||
ctx.buffer.idx[0] = 0;
|
g_ui_ctx.buffer.idx[0] = 0;
|
||||||
ctx.buffer.idx[1] = 1;
|
g_ui_ctx.buffer.idx[1] = 1;
|
||||||
ctx.buffer.idx[2] = 2;
|
g_ui_ctx.buffer.idx[2] = 2;
|
||||||
ctx.buffer.idx[3] = 2;
|
g_ui_ctx.buffer.idx[3] = 2;
|
||||||
ctx.buffer.idx[4] = 1;
|
g_ui_ctx.buffer.idx[4] = 1;
|
||||||
ctx.buffer.idx[5] = 3;
|
g_ui_ctx.buffer.idx[5] = 3;
|
||||||
|
|
||||||
ctx.buffer.count += 1;
|
g_ui_ctx.buffer.count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Nil(UIItem* item)
|
||||||
|
{
|
||||||
|
return item == null || item == g_UI_NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIItem*
|
||||||
|
Recurse(alias mode)(UIItem* item, UIItem* root)
|
||||||
|
{
|
||||||
|
UIItem* sibling, child, result = g_UI_NIL;
|
||||||
|
|
||||||
|
static if (mode == UIR.PostOrder) sibling = item.next; else sibling = item.prev;
|
||||||
|
static if (mode == UIR.PostOrder) child = item.prev; else child = item.last;
|
||||||
|
|
||||||
|
if (!Nil(child))
|
||||||
|
{
|
||||||
|
result = sibling;
|
||||||
|
}
|
||||||
|
else for(UIItem* i = sibling; !Nil(i) && i != root; i = i.parent)
|
||||||
|
{
|
||||||
|
static if (mode == UIR.PostOrder) sibling = i.next; else sibling = i.prev;
|
||||||
|
|
||||||
|
if (!Nil(sibling))
|
||||||
|
{
|
||||||
|
result = sibling;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setter function in case I need to change to using a mutex
|
||||||
|
pragma(inline) void
|
||||||
|
SetProp(alias P, T)(T value)
|
||||||
|
{
|
||||||
|
static if (is(T: Vec4[4]))
|
||||||
|
{
|
||||||
|
static if (0) {}
|
||||||
|
else static if (P == CtxP.BackgroundColor) { g_ui_ctx.bg_cols = value; }
|
||||||
|
else static if (P == CtxP.BorderColor) g_ui_ctx.border_cols = value;
|
||||||
|
else static assert(false, "Unknown Property for type Vec4[4]");
|
||||||
|
}
|
||||||
|
else static if (is(T: SizeKind) && P == CtxP.SizeKind)
|
||||||
|
{
|
||||||
|
g_ui_ctx.size_kind = value;
|
||||||
|
}
|
||||||
|
else static if (is(T: UISize))
|
||||||
|
{
|
||||||
|
static if (0) {}
|
||||||
|
else static if (P == CtxP.AxisX) g_ui_ctx.size_axes[A2D.X] = value;
|
||||||
|
else static if (P == CtxP.AxisY) g_ui_ctx.size_axes[A2D.Y] = value;
|
||||||
|
else static assert(false, "Unknown Property for type UISize");
|
||||||
|
}
|
||||||
|
else static if (is(T: FontAtlas))
|
||||||
|
{
|
||||||
|
static if (0) {}
|
||||||
|
else static if (P == CtxP.FontAtlas) g_ui_ctx.atlas = value;
|
||||||
|
else static assert(false, "Unknown Property for type FontAtlas");
|
||||||
|
}
|
||||||
|
else static if (is(T: Rect))
|
||||||
|
{
|
||||||
|
static if (0) {}
|
||||||
|
else static if (P == CtxP.Padding) g_ui_ctx.padding = value;
|
||||||
|
}
|
||||||
|
else static if (is(T: f32))
|
||||||
|
{
|
||||||
|
static if (0) {}
|
||||||
|
else static if (P == CtxP.TextScale) g_ui_ctx.text_scale = value;
|
||||||
|
else static assert(false, "Unknown property for type f32");
|
||||||
|
}
|
||||||
|
else static if (is(T: u32))
|
||||||
|
{
|
||||||
|
static if (0) {}
|
||||||
|
else static if (P == CtxP.TabWidth) g_ui_ctx.tab_width = value;
|
||||||
|
else static assert(false, "Unknown property for type u32");
|
||||||
|
}
|
||||||
|
else static assert(false, "Unknown Type");
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
{ // UI Key
|
||||||
|
u8[] str = cast(u8[])r"Test String##123";
|
||||||
|
UIKey key = MakeKey(str);
|
||||||
|
|
||||||
|
assert(key.text == cast(u8[])r"Test String");
|
||||||
|
assert(key.hash == Hash(str));
|
||||||
|
|
||||||
|
u8[] str1 = cast(u8[])r"Test String###123123";
|
||||||
|
key = MakeKey(str1);
|
||||||
|
|
||||||
|
assert(key.text == cast(u8[])r"Test String");
|
||||||
|
assert(key.hash == Hash(r"123123"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user