begin work on UI
This commit is contained in:
parent
5eca5811fb
commit
ef5ea1d90a
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit 69f5cd1a76ce0ee4f61201a5cae460664a5d8ca9
|
Subproject commit 6a757dd36b29f553c290d7188e8e02400cd25ba9
|
||||||
@ -6,6 +6,7 @@ import vulkan;
|
|||||||
import dlib.math;
|
import dlib.math;
|
||||||
import dlib.alloc;
|
import dlib.alloc;
|
||||||
import buffer;
|
import buffer;
|
||||||
|
import ui;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.exception;
|
import std.exception;
|
||||||
@ -23,6 +24,8 @@ 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;
|
||||||
@ -32,9 +35,6 @@ struct Editor
|
|||||||
PushConst pc;
|
PushConst pc;
|
||||||
MappedBuffer!(Vertex) m_vertex_buf;
|
MappedBuffer!(Vertex) m_vertex_buf;
|
||||||
MappedBuffer!(u32) m_index_buf;
|
MappedBuffer!(u32) m_index_buf;
|
||||||
Vertex[] vertices;
|
|
||||||
u32[] indices;
|
|
||||||
u32 ui_count;
|
|
||||||
|
|
||||||
FlatBuffer[] buffers;
|
FlatBuffer[] buffers;
|
||||||
Tokenizer[] tokenizers;
|
Tokenizer[] tokenizers;
|
||||||
@ -50,6 +50,13 @@ struct Editor
|
|||||||
UVec2 res;
|
UVec2 res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct UIBuffer
|
||||||
|
{
|
||||||
|
Vertex[] vtx;
|
||||||
|
u32[] idx;
|
||||||
|
u32 count;
|
||||||
|
}
|
||||||
|
|
||||||
struct PushConst
|
struct PushConst
|
||||||
{
|
{
|
||||||
Mat4 projection;
|
Mat4 projection;
|
||||||
@ -72,19 +79,17 @@ struct Vertex
|
|||||||
void
|
void
|
||||||
Cycle(Editor* ed)
|
Cycle(Editor* ed)
|
||||||
{
|
{
|
||||||
ed.ui_count = 0;
|
|
||||||
|
|
||||||
Reset(&ed.temp_arena);
|
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, 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));
|
||||||
//DrawRect(ed, 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 col = Vec4(0.2, 0.5, 0.9, 1.0);
|
||||||
Vec4 col2 = Vec4(0.2, 0.4, 0.7, 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 col3 = Vec4(0.2, 0.3, 0.65, 1.0);
|
||||||
Vec4 black = Vec4(0.0, 0.0, 0.0, 1.0);
|
Vec4 black = Vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
DrawRect(ed, -1000.0, -1000.0, 3000.0, 3000.0, 0.0, 0.0, 0.0, 0.0, [black, black, black, black]);
|
DrawRect(&ed.ctx, -1000.0, -1000.0, 3000.0, 3000.0, 0.0, 0.0, 0.0, 0.0, col);
|
||||||
//DrawRect(ed, 450.0, 450.0, 550.0, 550.0, 2.0, 5.0, 0.2, 20.0, [black, black, black, black]);
|
//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 pos = 0.0;
|
||||||
f32 h = ed.atlas_buf.atlas.size;
|
f32 h = ed.atlas_buf.atlas.size;
|
||||||
@ -107,7 +112,7 @@ Cycle(Editor* ed)
|
|||||||
|
|
||||||
BindBuffers(&ed.rd, &ed.m_index_buf, &ed.m_vertex_buf);
|
BindBuffers(&ed.rd, &ed.m_index_buf, &ed.m_vertex_buf);
|
||||||
|
|
||||||
DrawIndexed(&ed.rd, 6, ed.ui_count, 0);
|
DrawIndexed(&ed.rd, 6, ed.ctx.buffer.count, 0);
|
||||||
|
|
||||||
FinishRendering(&ed.rd);
|
FinishRendering(&ed.rd);
|
||||||
|
|
||||||
@ -228,8 +233,8 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name)
|
|||||||
|
|
||||||
editor.m_vertex_buf = CreateMappedBuffer!(Vertex)(&editor.rd, BT.Vertex, Vertex.sizeof * UI_COUNT);
|
editor.m_vertex_buf = CreateMappedBuffer!(Vertex)(&editor.rd, BT.Vertex, Vertex.sizeof * UI_COUNT);
|
||||||
editor.m_index_buf = CreateMappedBuffer!(u32)(&editor.rd, BT.Index, u32.sizeof * UI_COUNT);
|
editor.m_index_buf = CreateMappedBuffer!(u32)(&editor.rd, BT.Index, u32.sizeof * UI_COUNT);
|
||||||
editor.vertices = editor.m_vertex_buf.data;
|
|
||||||
editor.indices = editor.m_index_buf.data;
|
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);
|
||||||
|
|
||||||
@ -249,6 +254,44 @@ DrawText(Editor* ed, f32 x, f32 y, f32 px, string str)
|
|||||||
DrawText(ed, x, y, px, str_buf);
|
DrawText(ed, x, y, px, str_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DrawText(Editor* ed, f32 x, f32 y, f32 px, u8[] str)
|
||||||
|
{
|
||||||
|
u32 tab_count = 2;
|
||||||
|
f32 x_pos = x;
|
||||||
|
f32 scale = px / ed.atlas_buf.atlas.size;
|
||||||
|
foreach(ch; str)
|
||||||
|
{
|
||||||
|
foreach(glyph; ed.atlas_buf.atlas.glyphs)
|
||||||
|
{
|
||||||
|
if (ch == glyph.ch)
|
||||||
|
{
|
||||||
|
if (ch == '\t')
|
||||||
|
{
|
||||||
|
Glyph g = glyph;
|
||||||
|
g.atlas_left = g.atlas_right = 0.0;
|
||||||
|
foreach(i; 0 .. tab_count)
|
||||||
|
{
|
||||||
|
DrawGlyph(&ed.ctx, &g, scale, &x_pos, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ch == '\n')
|
||||||
|
{
|
||||||
|
Glyph g = glyph;
|
||||||
|
g.atlas_left = g.atlas_right = 0.0;
|
||||||
|
DrawGlyph(&ed.ctx, &g, scale, &x_pos, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawGlyph(&ed.ctx, &glyph, scale, &x_pos, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawBuffer(Editor* ed, f32 x, f32 y, f32 px, FlatBuffer* fb)
|
DrawBuffer(Editor* ed, f32 x, f32 y, f32 px, FlatBuffer* fb)
|
||||||
{
|
{
|
||||||
@ -288,126 +331,21 @@ 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, g, scale, &x_pos, y_pos);
|
DrawGlyph(&ed.ctx, 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, g, scale, &x_pos, y_pos);
|
DrawGlyph(&ed.ctx, g, scale, &x_pos, y_pos);
|
||||||
y_pos += px;
|
y_pos += px;
|
||||||
x_pos = 0.0;
|
x_pos = 0.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DrawGlyph(ed, g, scale, &x_pos, y_pos, cols[fb.tk.buffer[i]]);
|
DrawGlyph(&ed.ctx, g, scale, &x_pos, y_pos, cols[fb.tk.buffer[i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
DrawText(Editor* ed, f32 x, f32 y, f32 px, u8[] str)
|
|
||||||
{
|
|
||||||
u32 tab_count = 2;
|
|
||||||
f32 x_pos = x;
|
|
||||||
f32 scale = px / ed.atlas_buf.atlas.size;
|
|
||||||
foreach(ch; str)
|
|
||||||
{
|
|
||||||
foreach(glyph; ed.atlas_buf.atlas.glyphs)
|
|
||||||
{
|
|
||||||
if (ch == glyph.ch)
|
|
||||||
{
|
|
||||||
if (ch == '\t')
|
|
||||||
{
|
|
||||||
Glyph g = glyph;
|
|
||||||
g.atlas_left = g.atlas_right = 0.0;
|
|
||||||
foreach(i; 0 .. tab_count)
|
|
||||||
{
|
|
||||||
DrawGlyph(ed, &g, scale, &x_pos, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ch == '\n')
|
|
||||||
{
|
|
||||||
Glyph g = glyph;
|
|
||||||
g.atlas_left = g.atlas_right = 0.0;
|
|
||||||
DrawGlyph(ed, &g, scale, &x_pos, y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DrawGlyph(ed, &glyph, scale, &x_pos, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline): void
|
|
||||||
DrawGlyph(Editor* ed, Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
|
||||||
{
|
|
||||||
if (glyph.atlas_left != glyph.atlas_right)
|
|
||||||
{
|
|
||||||
Vertex* v = ed.vertices.ptr + ed.ui_count;
|
|
||||||
|
|
||||||
f32 r = glyph.plane_right * scale;
|
|
||||||
f32 l = glyph.plane_left * scale;
|
|
||||||
f32 w = r - l;
|
|
||||||
f32 h = (glyph.plane_bottom - glyph.plane_top) * scale;
|
|
||||||
f32 y_pos = glyph.plane_top * scale;
|
|
||||||
|
|
||||||
v.dst_start.x = *x_pos + l;
|
|
||||||
v.dst_start.y = y - y_pos;
|
|
||||||
v.dst_end.x = *x_pos + w + l;
|
|
||||||
v.dst_end.y = y + h - y_pos;
|
|
||||||
|
|
||||||
v.src_start.x = glyph.atlas_left;
|
|
||||||
v.src_start.y = glyph.atlas_top;
|
|
||||||
v.src_end.x = glyph.atlas_right;
|
|
||||||
v.src_end.y = glyph.atlas_bottom;
|
|
||||||
|
|
||||||
v.cols[0] = col;
|
|
||||||
v.cols[1] = col;
|
|
||||||
v.cols[2] = col;
|
|
||||||
v.cols[3] = col;
|
|
||||||
|
|
||||||
v.texture = 1;
|
|
||||||
|
|
||||||
AddUIIndices(ed);
|
|
||||||
}
|
|
||||||
|
|
||||||
*x_pos += glyph.advance * scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline) void
|
|
||||||
DrawRect(Editor* ed, 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
|
|
||||||
Vertex* v = ed.vertices.ptr + ed.ui_count;
|
|
||||||
v.dst_start.x = p0_x;
|
|
||||||
v.dst_start.y = p0_y;
|
|
||||||
v.dst_end.x = p1_x;
|
|
||||||
v.dst_end.y = p1_y;
|
|
||||||
v.cols = cols;
|
|
||||||
v.border_thickness = border;
|
|
||||||
v.corner_radius = corner;
|
|
||||||
v.edge_softness = softness;
|
|
||||||
v.raised = raised;
|
|
||||||
|
|
||||||
AddUIIndices(ed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
AddUIIndices(Editor* ed)
|
|
||||||
{
|
|
||||||
ed.indices[0] = 0;
|
|
||||||
ed.indices[1] = 1;
|
|
||||||
ed.indices[2] = 2;
|
|
||||||
ed.indices[3] = 2;
|
|
||||||
ed.indices[4] = 1;
|
|
||||||
ed.indices[5] = 3;
|
|
||||||
|
|
||||||
ed.ui_count += 1;
|
|
||||||
}
|
|
||||||
|
|||||||
184
src/editor/ui.d
Normal file
184
src/editor/ui.d
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import dlib.aliases;
|
||||||
|
import dlib.math;
|
||||||
|
import dlib.util;
|
||||||
|
import dlib.alloc;
|
||||||
|
import dlib.fonts;
|
||||||
|
import vulkan;
|
||||||
|
|
||||||
|
import editor;
|
||||||
|
|
||||||
|
enum BaseFlags : u32
|
||||||
|
{
|
||||||
|
Clickable = (1<<0),
|
||||||
|
ViewScroll = (1<<1),
|
||||||
|
DrawText = (1<<2),
|
||||||
|
DrawBackground = (1<<3),
|
||||||
|
DrawBorder = (1<<4),
|
||||||
|
Resizeable = (1<<5),
|
||||||
|
Draggable = (1<<6),
|
||||||
|
}
|
||||||
|
|
||||||
|
union Rect
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Vec2 vec0;
|
||||||
|
Vec2 vec1;
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
f32 x0;
|
||||||
|
f32 y0;
|
||||||
|
f32 x1;
|
||||||
|
f32 y1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
alias UIHash = u64;
|
||||||
|
|
||||||
|
alias UIPair = KVPair!(UIHash, UIItem*);
|
||||||
|
|
||||||
|
struct UIItem
|
||||||
|
{
|
||||||
|
BaseFlags flags;
|
||||||
|
Rect rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UIContext
|
||||||
|
{
|
||||||
|
HashTable!(UIHash, UIItem*) items;
|
||||||
|
Arena arena;
|
||||||
|
|
||||||
|
UIBuffer buffer;
|
||||||
|
|
||||||
|
Vec4[4] bg_cols;
|
||||||
|
Vec4[4] border_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Reset(UIContext* ctx)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
SetBgCols(UIContext* ctx, Vec4[4] cols)
|
||||||
|
{
|
||||||
|
ctx.bg_cols = cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetBorderCols(UIContext* ctx, Vec4[4] cols)
|
||||||
|
{
|
||||||
|
ctx.border_color = cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIItem*
|
||||||
|
Find(UIContext* ctx, u8[] id)
|
||||||
|
{
|
||||||
|
u64 hash = Hash(id);
|
||||||
|
Result!(UIItem*) result = ctx.items[hash];
|
||||||
|
if (!result.ok)
|
||||||
|
{
|
||||||
|
result.value = Alloc!(UIItem)(&ctx.arena);
|
||||||
|
Push(&ctx.items, hash, result.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
UIWindow(UIContext* ctx, Rect rect, f32 border_px, u8[] text)
|
||||||
|
{
|
||||||
|
UIItem* item = Find(ctx, text);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
DrawGlyph(UIContext* ctx, Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
||||||
|
{
|
||||||
|
if (glyph.atlas_left != glyph.atlas_right)
|
||||||
|
{
|
||||||
|
Vertex* v = ctx.buffer.vtx.ptr + ctx.buffer.count;
|
||||||
|
|
||||||
|
f32 r = glyph.plane_right * scale;
|
||||||
|
f32 l = glyph.plane_left * scale;
|
||||||
|
f32 w = r - l;
|
||||||
|
f32 h = (glyph.plane_bottom - glyph.plane_top) * scale;
|
||||||
|
f32 y_pos = glyph.plane_top * scale;
|
||||||
|
|
||||||
|
v.dst_start.x = *x_pos + l;
|
||||||
|
v.dst_start.y = y - y_pos;
|
||||||
|
v.dst_end.x = *x_pos + w + l;
|
||||||
|
v.dst_end.y = y + h - y_pos;
|
||||||
|
|
||||||
|
v.src_start.x = glyph.atlas_left;
|
||||||
|
v.src_start.y = glyph.atlas_top;
|
||||||
|
v.src_end.x = glyph.atlas_right;
|
||||||
|
v.src_end.y = glyph.atlas_bottom;
|
||||||
|
|
||||||
|
v.cols[0] = col;
|
||||||
|
v.cols[1] = col;
|
||||||
|
v.cols[2] = col;
|
||||||
|
v.cols[3] = col;
|
||||||
|
|
||||||
|
v.texture = 1;
|
||||||
|
|
||||||
|
AddUIIndices(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
*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
|
||||||
|
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
|
||||||
|
Vertex* v = ctx.buffer.vtx.ptr + ctx.buffer.count;
|
||||||
|
v.dst_start.x = p0_x;
|
||||||
|
v.dst_start.y = p0_y;
|
||||||
|
v.dst_end.x = p1_x;
|
||||||
|
v.dst_end.y = p1_y;
|
||||||
|
v.cols = cols;
|
||||||
|
v.border_thickness = border;
|
||||||
|
v.corner_radius = corner;
|
||||||
|
v.edge_softness = softness;
|
||||||
|
v.raised = raised;
|
||||||
|
|
||||||
|
AddUIIndices(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AddUIIndices(UIContext* ctx)
|
||||||
|
{
|
||||||
|
ctx.buffer.idx[0] = 0;
|
||||||
|
ctx.buffer.idx[1] = 1;
|
||||||
|
ctx.buffer.idx[2] = 2;
|
||||||
|
ctx.buffer.idx[3] = 2;
|
||||||
|
ctx.buffer.idx[4] = 1;
|
||||||
|
ctx.buffer.idx[5] = 3;
|
||||||
|
|
||||||
|
ctx.buffer.count += 1;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user