add text line widget, add text wrapping
This commit is contained in:
parent
de90479aa7
commit
9f8e4aff59
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit f30edc3bbe9fdfda5eb429a214fdf050a0012af0
|
Subproject commit 29a98de0e05cb04001b42a55b1ae094ab42f2ab1
|
||||||
@ -4,6 +4,7 @@ import dlib.alloc;
|
|||||||
import dlib.util;
|
import dlib.util;
|
||||||
import core.stdc.stdio : EOF;
|
import core.stdc.stdio : EOF;
|
||||||
import parsing;
|
import parsing;
|
||||||
|
import std.format : sformat;
|
||||||
|
|
||||||
struct FlatBuffer
|
struct FlatBuffer
|
||||||
{
|
{
|
||||||
@ -25,7 +26,6 @@ struct LineBuffers
|
|||||||
{
|
{
|
||||||
Arena arena;
|
Arena arena;
|
||||||
u8[][] lines;
|
u8[][] lines;
|
||||||
u32[] lengths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FlatBuffer
|
FlatBuffer
|
||||||
@ -108,15 +108,15 @@ Insert(FlatBuffer* buffer, u8[] insert, u64 length, Range pos)
|
|||||||
|
|
||||||
// TODO: handle case for when lines are longer than line buffer
|
// TODO: handle case for when lines are longer than line buffer
|
||||||
void
|
void
|
||||||
GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length, bool add_hash = false)
|
||||||
{
|
{
|
||||||
assert(start_line < buffer.line_count, "GetLines failure: start is not less than line_count");
|
|
||||||
assert(linebufs != null, "GetLines failure: linebufs is null");
|
assert(linebufs != null, "GetLines failure: linebufs is null");
|
||||||
|
length = length > buffer.line_count ? buffer.line_count : length;
|
||||||
|
|
||||||
Reset(&linebufs.arena);
|
Reset(&linebufs.arena);
|
||||||
linebufs.lines = AllocArray!(u8[])(&linebufs.arena, length);
|
linebufs.lines = AllocArray!(u8[])(&linebufs.arena, length);
|
||||||
linebufs.lengths = AllocArray!(u32)(&linebufs.arena, length);
|
|
||||||
|
|
||||||
|
u64 extra_buffer = add_hash ? 10 : 0;
|
||||||
i64 start = -1;
|
i64 start = -1;
|
||||||
u64 line = 0;
|
u64 line = 0;
|
||||||
u64 current_line = 0;
|
u64 current_line = 0;
|
||||||
@ -136,9 +136,8 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
|||||||
|
|
||||||
if (start < 0 && new_line)
|
if (start < 0 && new_line)
|
||||||
{
|
{
|
||||||
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, 1);
|
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, 1 + extra_buffer);
|
||||||
linebufs.lines[current_line][0] = '\n';
|
linebufs.lines[current_line][0] = '\n';
|
||||||
linebufs.lengths[current_line] = 1;
|
|
||||||
current_line += 1;
|
current_line += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -151,9 +150,8 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
|||||||
|
|
||||||
if (new_line)
|
if (new_line)
|
||||||
{
|
{
|
||||||
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, i-start);
|
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, (i-start) + extra_buffer);
|
||||||
linebufs.lines[current_line][0 .. $] = buffer.data[start .. i];
|
linebufs.lines[current_line][0 .. i-start] = buffer.data[start .. i];
|
||||||
linebufs.lengths[current_line] = cast(u32)(i-start);
|
|
||||||
current_line += 1;
|
current_line += 1;
|
||||||
start = -1;
|
start = -1;
|
||||||
continue;
|
continue;
|
||||||
@ -161,9 +159,21 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
|||||||
|
|
||||||
if (i == buffer.length-1)
|
if (i == buffer.length-1)
|
||||||
{
|
{
|
||||||
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, buffer.length-start);
|
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, (buffer.length-start) + extra_buffer);
|
||||||
linebufs.lines[current_line][0 .. $] = buffer.data[start .. buffer.length];
|
linebufs.lines[current_line][0 .. buffer.length-start] = buffer.data[start .. buffer.length];
|
||||||
linebufs.lengths[current_line] = cast(u32)(buffer.length-start);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_hash)
|
||||||
|
{
|
||||||
|
for (u64 i = 0; i < linebufs.lines.length; i += 1)
|
||||||
|
{
|
||||||
|
if (linebufs.lines[i].length > 0)
|
||||||
|
{
|
||||||
|
u8[10] buf = 0;
|
||||||
|
(cast(char[])buf).sformat("##%08s", i);
|
||||||
|
linebufs.lines[i][linebufs.lines[i].length - extra_buffer .. $] = buf[0 .. $];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ struct Editor
|
|||||||
FontFace font;
|
FontFace font;
|
||||||
FontAtlasBuf atlas_buf;
|
FontAtlasBuf atlas_buf;
|
||||||
|
|
||||||
UVec2 res;
|
Vec2 res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PushConst
|
struct PushConst
|
||||||
@ -70,6 +70,82 @@ struct Vertex
|
|||||||
u32 texture;
|
u32 texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cycle(Editor* ed, Inputs* inputs)
|
||||||
|
{
|
||||||
|
Reset(&ed.temp_arena);
|
||||||
|
ResetScratch(MB(4));
|
||||||
|
|
||||||
|
BeginBuild(inputs);
|
||||||
|
|
||||||
|
static UIPanel panel = {
|
||||||
|
id: CastStr!(u8)("##main_panel"),
|
||||||
|
pct: 1.0,
|
||||||
|
axis: A2D.X,
|
||||||
|
color: Vec4(0.2, 0.4, 0.8, 1.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
static UIPanel panel_l = {
|
||||||
|
id: CastStr!(u8)("##panel_l"),
|
||||||
|
pct: 0.5,
|
||||||
|
axis: A2D.Y,
|
||||||
|
color: Vec4(0.2, 0.4, 0.8, 1.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
static UIPanel panel_r = {
|
||||||
|
id: CastStr!(u8)("##panel_r"),
|
||||||
|
pct: 0.5,
|
||||||
|
axis: A2D.Y,
|
||||||
|
color: Vec4(0.4, 0.3, 0.7, 1.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
BeginFrame(&ed.rd);
|
||||||
|
|
||||||
|
Vec2 ext = GetExtent(&ed.rd);
|
||||||
|
if (ext != ed.res)
|
||||||
|
{
|
||||||
|
ed.res = ext;
|
||||||
|
Ortho(&ed.pc.projection, 0.0, 0.0, ext.x, ext.y, 1000.0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 rows = cast(u32)(ext.y / ed.atlas_buf.atlas.size) + 5;
|
||||||
|
Panel(&panel);
|
||||||
|
{
|
||||||
|
Panel(&panel_l);
|
||||||
|
{
|
||||||
|
if (ed.active_buffer != null)
|
||||||
|
{
|
||||||
|
GetLines(&ed.buffers[0], &ed.linebufs, 0, rows);
|
||||||
|
|
||||||
|
for(u64 i = 0; i < ed.linebufs.lines.length; i += 1)
|
||||||
|
{
|
||||||
|
TextLine(ed.linebufs.lines[i], ed.atlas_buf.atlas.size, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EndPanel();
|
||||||
|
|
||||||
|
Panel(&panel_r);
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
EndPanel();
|
||||||
|
}
|
||||||
|
EndPanel();
|
||||||
|
|
||||||
|
BeginRendering(&ed.rd);
|
||||||
|
|
||||||
|
PushConstants(&ed.rd, ed.pipeline, &ed.pc);
|
||||||
|
|
||||||
|
Bind(&ed.rd, ed.pipeline, ed.desc_set);
|
||||||
|
|
||||||
|
EndBuild();
|
||||||
|
|
||||||
|
FinishRendering(&ed.rd);
|
||||||
|
|
||||||
|
SubmitAndPresent(&ed.rd);
|
||||||
|
}
|
||||||
|
|
||||||
Editor
|
Editor
|
||||||
CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name)
|
CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name)
|
||||||
{
|
{
|
||||||
@ -175,140 +251,6 @@ CreateEditor(PlatformWindow* window, u8[] buffer_data, u8[] buffer_name)
|
|||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Cycle(Editor* ed, Inputs* inputs)
|
|
||||||
{
|
|
||||||
Reset(&ed.temp_arena);
|
|
||||||
|
|
||||||
BeginBuild(inputs);
|
|
||||||
|
|
||||||
static UIPanel[11] panels = [
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##panel_1"),
|
|
||||||
pct: 0.3,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(0.2, 0.5, 0.8, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##sub_panel_1"),
|
|
||||||
pct: 0.125,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(0.2, 0.4, 0.5, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##sub_panel_2"),
|
|
||||||
pct: 0.675,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(0.9, 0.6, 0.5, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##sub_panel_3"),
|
|
||||||
pct: 0.2,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(1.0, 0.4, 0.5, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##panel_2"),
|
|
||||||
pct: 0.3,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(0.5, 0.2, 0.45, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##panel_3"),
|
|
||||||
pct: 0.4,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(0.3, 0.7, 0.6, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##sub_panel_4"),
|
|
||||||
pct: 0.25,
|
|
||||||
axis: A2D.Y,
|
|
||||||
color: Vec4(0.33, 0.4, 0.8, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##sub_sub_panel_1"),
|
|
||||||
pct: 0.4,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(1.0, 0.0, 0.0, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##sub_sub_panel_2"),
|
|
||||||
pct: 0.6,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(1.0, 1.0, 0.0, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##sub_panel_5"),
|
|
||||||
pct: 0.55,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(0.9, 0.2, 0.3, 1.0),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: CastStr!(u8)("##sub_panel_6"),
|
|
||||||
pct: 0.2,
|
|
||||||
axis: A2D.X,
|
|
||||||
color: Vec4(0.2, 0.76, 0.5, 1.0),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
Panel(&panels[0]);
|
|
||||||
{
|
|
||||||
Panel(&panels[1]);
|
|
||||||
EndPanel();
|
|
||||||
|
|
||||||
Panel(&panels[2]);
|
|
||||||
EndPanel();
|
|
||||||
|
|
||||||
Panel(&panels[3]);
|
|
||||||
EndPanel();
|
|
||||||
}
|
|
||||||
EndPanel();
|
|
||||||
|
|
||||||
Panel(&panels[4]);
|
|
||||||
EndPanel();
|
|
||||||
|
|
||||||
Panel(&panels[5]);
|
|
||||||
{
|
|
||||||
Panel(&panels[6]);
|
|
||||||
{
|
|
||||||
Panel(&panels[7]);
|
|
||||||
EndPanel();
|
|
||||||
|
|
||||||
Panel(&panels[8]);
|
|
||||||
EndPanel();
|
|
||||||
}
|
|
||||||
EndPanel();
|
|
||||||
|
|
||||||
Panel(&panels[9]);
|
|
||||||
EndPanel();
|
|
||||||
|
|
||||||
Panel(&panels[10]);
|
|
||||||
EndPanel();
|
|
||||||
}
|
|
||||||
EndPanel();
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
EndBuild();
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|||||||
245
src/editor/ui.d
245
src/editor/ui.d
@ -7,6 +7,9 @@ import dlib.fonts;
|
|||||||
import vulkan;
|
import vulkan;
|
||||||
import widgets;
|
import widgets;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
import std.math.rounding : ceil;
|
||||||
|
import std.format : sformat;
|
||||||
|
import core.stdc.string : memset;
|
||||||
|
|
||||||
import editor;
|
import editor;
|
||||||
|
|
||||||
@ -31,8 +34,9 @@ enum UIFlags
|
|||||||
{
|
{
|
||||||
None = 0x00,
|
None = 0x00,
|
||||||
DrawBackground = 0x01,
|
DrawBackground = 0x01,
|
||||||
Clickable = 0x02,
|
DrawText = 0x02,
|
||||||
Draggable = 0x04,
|
Clickable = 0x04,
|
||||||
|
Draggable = 0x08,
|
||||||
}
|
}
|
||||||
|
|
||||||
alias UIF = UIFlags;
|
alias UIF = UIFlags;
|
||||||
@ -60,8 +64,10 @@ struct UICtx
|
|||||||
Arena arena;
|
Arena arena;
|
||||||
Renderer* rd;
|
Renderer* rd;
|
||||||
Inputs* inputs;
|
Inputs* inputs;
|
||||||
|
u64 frame;
|
||||||
|
u64 f_idx;
|
||||||
|
|
||||||
UIBuffer buffer;
|
UIBuffer[FRAME_OVERLAP] buffers;
|
||||||
|
|
||||||
UIItem* root;
|
UIItem* root;
|
||||||
UIItemNode* top_parent;
|
UIItemNode* top_parent;
|
||||||
@ -77,6 +83,8 @@ struct UICtx
|
|||||||
Vec4 text_color;
|
Vec4 text_color;
|
||||||
Axis2D layout_axis;
|
Axis2D layout_axis;
|
||||||
Vec2 adjustment;
|
Vec2 adjustment;
|
||||||
|
u32 tab_width;
|
||||||
|
f32 text_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIItemStackList
|
struct UIItemStackList
|
||||||
@ -125,8 +133,8 @@ struct UISize
|
|||||||
|
|
||||||
struct UIBuffer
|
struct UIBuffer
|
||||||
{
|
{
|
||||||
MappedBuffer!(Vertex) mapped_vtx;
|
MappedBuffer!(Vertex) m_vtx;
|
||||||
MappedBuffer!(u32) mapped_idx;
|
MappedBuffer!(u32) m_idx;
|
||||||
Vertex[] vtx;
|
Vertex[] vtx;
|
||||||
u32[] idx;
|
u32[] idx;
|
||||||
u32 count;
|
u32 count;
|
||||||
@ -167,8 +175,16 @@ InitUICtx(Renderer* rd, FontAtlas atlas)
|
|||||||
|
|
||||||
Arena arena = CreateArena(MB(4));
|
Arena arena = CreateArena(MB(4));
|
||||||
|
|
||||||
MappedBuffer!(Vertex) m_vtx = CreateMappedBuffer!(Vertex)(rd, BT.Vertex, 5000);
|
UIBuffer[FRAME_OVERLAP] buffers;
|
||||||
MappedBuffer!(u32) m_idx = CreateMappedBuffer!(u32)(rd, BT.Index, 15000);
|
|
||||||
|
u64 vertex_size = 10000;
|
||||||
|
for(u64 i = 0; i < FRAME_OVERLAP; i += 1)
|
||||||
|
{
|
||||||
|
buffers[i].m_vtx = CreateMappedBuffer!(Vertex)(rd, BT.Vertex, vertex_size);
|
||||||
|
buffers[i].m_idx = CreateMappedBuffer!(u32)(rd, BT.Index, cast(u64)(ceil(vertex_size * 1.5)));
|
||||||
|
buffers[i].vtx = buffers[i].m_vtx.data;
|
||||||
|
buffers[i].idx = buffers[i].m_idx.data;
|
||||||
|
}
|
||||||
|
|
||||||
UICtx ctx = {
|
UICtx ctx = {
|
||||||
rd: rd,
|
rd: rd,
|
||||||
@ -179,12 +195,9 @@ InitUICtx(Renderer* rd, FontAtlas atlas)
|
|||||||
top_parent: g_UI_NIL_NODE,
|
top_parent: g_UI_NIL_NODE,
|
||||||
prev_sibling: g_UI_NIL_NODE,
|
prev_sibling: g_UI_NIL_NODE,
|
||||||
drag_item: g_UI_NIL,
|
drag_item: g_UI_NIL,
|
||||||
buffer: {
|
text_size: 14.0,
|
||||||
mapped_vtx: m_vtx,
|
tab_width: 2,
|
||||||
mapped_idx: m_idx,
|
buffers: buffers,
|
||||||
vtx: m_vtx.data,
|
|
||||||
idx: m_idx.data,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
g_ui_ctx = ctx;
|
g_ui_ctx = ctx;
|
||||||
@ -361,13 +374,25 @@ SetLayoutAxis(Axis2D axis)
|
|||||||
ctx.layout_axis = axis;
|
ctx.layout_axis = axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetTextSize(f32 size)
|
||||||
|
{
|
||||||
|
g_ui_ctx.text_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BeginBuild(Inputs* inputs)
|
BeginBuild(Inputs* inputs)
|
||||||
{
|
{
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
|
|
||||||
|
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
|
||||||
|
|
||||||
ctx.inputs = inputs;
|
ctx.inputs = inputs;
|
||||||
ctx.buffer.count = 0;
|
|
||||||
|
memset(ctx.buffers[ctx.f_idx].vtx.ptr, 0, Vertex.sizeof * ctx.buffers[ctx.f_idx].count);
|
||||||
|
memset(ctx.buffers[ctx.f_idx].idx.ptr, 0, u32.sizeof * ctx.buffers[ctx.f_idx].count);
|
||||||
|
ctx.buffers[ctx.f_idx].count = 0;
|
||||||
|
|
||||||
ctx.panel_level = 0;
|
ctx.panel_level = 0;
|
||||||
|
|
||||||
ctx.root = Root();
|
ctx.root = Root();
|
||||||
@ -400,8 +425,10 @@ EndBuild()
|
|||||||
first = true;
|
first = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BindBuffers(g_ui_ctx.rd, &g_ui_ctx.buffer.mapped_idx, &g_ui_ctx.buffer.mapped_vtx);
|
BindBuffers(ctx.rd, &ctx.buffers[ctx.f_idx].m_idx, &ctx.buffers[ctx.f_idx].m_vtx);
|
||||||
DrawIndexed(g_ui_ctx.rd, 6, g_ui_ctx.buffer.count, 0);
|
DrawIndexed(ctx.rd, 6, ctx.buffers[ctx.f_idx].count, 0);
|
||||||
|
|
||||||
|
ctx.frame += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -472,8 +499,16 @@ void
|
|||||||
DrawUI(UICtx* ctx, UIItem* item)
|
DrawUI(UICtx* ctx, UIItem* item)
|
||||||
{
|
{
|
||||||
if (!Nil(item))
|
if (!Nil(item))
|
||||||
|
{
|
||||||
|
if (item.flags & UIF.DrawBackground)
|
||||||
{
|
{
|
||||||
DrawRect(ctx, item);
|
DrawRect(ctx, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.flags & UIF.DrawText)
|
||||||
|
{
|
||||||
|
DrawLine(item);
|
||||||
|
}
|
||||||
|
|
||||||
DrawUI(ctx, item.first);
|
DrawUI(ctx, item.first);
|
||||||
DrawUI(ctx, item.next);
|
DrawUI(ctx, item.next);
|
||||||
@ -567,32 +602,41 @@ RootSize()
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UIKey
|
||||||
|
MakeKey(u8[] text, u8[] hash)
|
||||||
|
{
|
||||||
|
UIKey key;
|
||||||
|
|
||||||
|
key.text = text;
|
||||||
|
key.hash = Hash(text, hash);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
UIKey
|
UIKey
|
||||||
MakeKey(u8[] id)
|
MakeKey(u8[] id)
|
||||||
{
|
{
|
||||||
UIKey key;
|
UIKey key;
|
||||||
|
|
||||||
u32 pos = 0;
|
i64 pos = 0;
|
||||||
u32 hash_count = 0;
|
u32 hash_count = 0;
|
||||||
for(u32 i = 0; i < id.length; i += 1)
|
for(i64 i = id.length-1; i >= 0; i -= 1)
|
||||||
{
|
{
|
||||||
if (hash_count == 2)
|
if (hash_count == 2)
|
||||||
{
|
{
|
||||||
if (id[i] == '#')
|
if (id[i] == '#')
|
||||||
{
|
{
|
||||||
hash_count += 1;
|
hash_count += 1;
|
||||||
|
pos = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id[i] == '#')
|
if (id[i] == '#')
|
||||||
{
|
|
||||||
if (hash_count == 0)
|
|
||||||
{
|
{
|
||||||
pos = i;
|
pos = i;
|
||||||
}
|
|
||||||
|
|
||||||
hash_count += 1;
|
hash_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -616,6 +660,21 @@ MakeKey(u8[] id)
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pragma(inline) UIItem*
|
||||||
|
Get(UIKey key)
|
||||||
|
{
|
||||||
|
Result!(UIItem*) result = g_ui_ctx.items[key.hash];
|
||||||
|
if (!result.ok)
|
||||||
|
{
|
||||||
|
result.value = Alloc!(UIItem)(&g_ui_ctx.arena);
|
||||||
|
Push(&g_ui_ctx.items, key.hash, result.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.value.key = key;
|
||||||
|
|
||||||
|
return result.value;
|
||||||
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItem*
|
||||||
Get(string id)
|
Get(string id)
|
||||||
{
|
{
|
||||||
@ -627,48 +686,132 @@ UIItem*
|
|||||||
Get(u8[] id)
|
Get(u8[] id)
|
||||||
{
|
{
|
||||||
UIKey key = MakeKey(id);
|
UIKey key = MakeKey(id);
|
||||||
|
return Get(key);
|
||||||
Result!(UIItem*) result = g_ui_ctx.items[key.hash];
|
|
||||||
if (!result.ok)
|
|
||||||
{
|
|
||||||
result.value = Alloc!(UIItem)(&g_ui_ctx.arena);
|
|
||||||
Push(&g_ui_ctx.items, key.hash, result.value);
|
|
||||||
result.value.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
f32
|
f32
|
||||||
CalcTextWidth(u8[] str)
|
CalcTextWidth(u8[] str)
|
||||||
{
|
{
|
||||||
u32 tab_width = 2; //g_ui_ctx.tab_width;
|
u32 tab_width = g_ui_ctx.tab_width;
|
||||||
Glyph* space = g_ui_ctx.atlas.glyphs.ptr + ' ';
|
Glyph* space = g_ui_ctx.atlas.glyphs.ptr + ' ';
|
||||||
|
|
||||||
f32 width;
|
f32 width = 0.0;
|
||||||
for(u64 i = 0; i < str.length; i += 1)
|
for(u64 i = 0; i < str.length; i += 1)
|
||||||
{
|
{
|
||||||
Glyph* g = g_ui_ctx.atlas.glyphs.ptr + str.ptr[i];
|
width += GlyphWidth(g_ui_ctx.atlas.glyphs.ptr + str.ptr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline) f32
|
||||||
|
GlyphWidth(Glyph* g)
|
||||||
|
{
|
||||||
|
f32 width = 0.0;
|
||||||
if (g.ch == '\t')
|
if (g.ch == '\t')
|
||||||
{
|
{
|
||||||
width += space.advance * cast(f32)(tab_width);
|
width += g_ui_ctx.atlas.glyphs[' '].advance * cast(f32)(g_ui_ctx.tab_width);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
width += g.advance;
|
width += g.advance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
return width; // * g_ui_ctx.text_scale;
|
Node!(u8[])*
|
||||||
|
MakeMultiline(u8[] text, f32 width, u64 line_no)
|
||||||
|
{
|
||||||
|
f32 scaled_width = width * (g_ui_ctx.atlas.size/g_ui_ctx.text_size);
|
||||||
|
f32 text_width = CalcTextWidth(text);
|
||||||
|
|
||||||
|
u64 line_count = cast(u64)(ceil(text_width/scaled_width));
|
||||||
|
Node!(u8[])* node = null;
|
||||||
|
if (line_count > 0)
|
||||||
|
{
|
||||||
|
f32 w = 0.0;
|
||||||
|
u64 line = 0;
|
||||||
|
u64 start = 0;
|
||||||
|
const u64 extra_buf = 10;
|
||||||
|
for(u64 i = 0; i < text.length; i += 1)
|
||||||
|
{
|
||||||
|
f32 ch_w = GlyphWidth(g_ui_ctx.atlas.glyphs.ptr + text[i]);
|
||||||
|
|
||||||
|
if (ch_w + w > scaled_width || i == text.length-1)
|
||||||
|
{
|
||||||
|
u64 len = i-start+1;
|
||||||
|
u8[10] buf = 0;
|
||||||
|
(cast(char[])buf).sformat("##%04s%04s", line_no, line);
|
||||||
|
|
||||||
|
u8[] str = ScratchAlloc!(u8)(len+extra_buf);
|
||||||
|
str[0 .. len] = text[start .. start+len];
|
||||||
|
str[len .. len+extra_buf] = buf[0 .. $];
|
||||||
|
|
||||||
|
Node!(u8[])* n = node;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
node = ScratchAlloc!(Node!(u8[]))();
|
||||||
|
node.value = str;
|
||||||
|
node.next = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n.next == null)
|
||||||
|
{
|
||||||
|
n.next = ScratchAlloc!(Node!(u8[]))();
|
||||||
|
n.next.value = str;
|
||||||
|
n.next.next = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = n.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
line += 1;
|
||||||
|
start = i;
|
||||||
|
w = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
w += ch_w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DrawLine(UIItem* item)
|
||||||
|
{
|
||||||
|
UICtx* ctx = GetCtx();
|
||||||
|
f32 y = item.rect.y0 + ctx.text_size;
|
||||||
|
f32 x = item.rect.x0;
|
||||||
|
FontAtlas* atlas = &ctx.atlas;
|
||||||
|
|
||||||
|
for(u64 i = 0; i < item.key.text.length && item.key.text[i] != '\0'; i += 1)
|
||||||
|
{
|
||||||
|
u8 ch = item.key.text.ptr[i];
|
||||||
|
if (ch < 128)
|
||||||
|
{
|
||||||
|
DrawGlyph(&atlas.glyphs[ch], atlas.size/ctx.text_size, &x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
||||||
{
|
{
|
||||||
if (glyph.atlas_left != glyph.atlas_right)
|
if (glyph.ch == '\t')
|
||||||
{
|
{
|
||||||
Vertex* v = g_ui_ctx.buffer.vtx.ptr + g_ui_ctx.buffer.count;
|
*x_pos += glyph.advance * (GetCtx().tab_width - 1);
|
||||||
|
}
|
||||||
|
else if (glyph.atlas_left != glyph.atlas_right && glyph.ch != '\n')
|
||||||
|
{
|
||||||
|
UICtx* ctx = GetCtx();
|
||||||
|
Vertex* v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].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;
|
||||||
@ -693,7 +836,7 @@ DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
|||||||
|
|
||||||
v.texture = 1;
|
v.texture = 1;
|
||||||
|
|
||||||
AddUIIndices();
|
AddUIIndices(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
*x_pos += glyph.advance * scale;
|
*x_pos += glyph.advance * scale;
|
||||||
@ -703,7 +846,7 @@ pragma(inline) void
|
|||||||
DrawRect(UICtx* ctx, UIItem* item)
|
DrawRect(UICtx* ctx, UIItem* item)
|
||||||
{
|
{
|
||||||
// Y reversed
|
// Y reversed
|
||||||
Vertex* v = ctx.buffer.vtx.ptr + ctx.buffer.count;
|
Vertex* v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
||||||
v.dst_start = item.rect.vec0;
|
v.dst_start = item.rect.vec0;
|
||||||
v.dst_end = item.rect.vec1;
|
v.dst_end = item.rect.vec1;
|
||||||
v.cols = item.color;
|
v.cols = item.color;
|
||||||
@ -712,20 +855,20 @@ DrawRect(UICtx* ctx, UIItem* item)
|
|||||||
v.edge_softness = 0.0;
|
v.edge_softness = 0.0;
|
||||||
v.raised = 0.0;
|
v.raised = 0.0;
|
||||||
|
|
||||||
AddUIIndices();
|
AddUIIndices(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
pragma(inline) void
|
||||||
AddUIIndices()
|
AddUIIndices(UICtx* ctx)
|
||||||
{
|
{
|
||||||
g_ui_ctx.buffer.idx[0] = 0;
|
ctx.buffers[ctx.f_idx].idx[0] = 0;
|
||||||
g_ui_ctx.buffer.idx[1] = 1;
|
ctx.buffers[ctx.f_idx].idx[1] = 1;
|
||||||
g_ui_ctx.buffer.idx[2] = 2;
|
ctx.buffers[ctx.f_idx].idx[2] = 2;
|
||||||
g_ui_ctx.buffer.idx[3] = 2;
|
ctx.buffers[ctx.f_idx].idx[3] = 2;
|
||||||
g_ui_ctx.buffer.idx[4] = 1;
|
ctx.buffers[ctx.f_idx].idx[4] = 1;
|
||||||
g_ui_ctx.buffer.idx[5] = 3;
|
ctx.buffers[ctx.f_idx].idx[5] = 3;
|
||||||
|
|
||||||
g_ui_ctx.buffer.count += 1;
|
ctx.buffers[ctx.f_idx].count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@ -114,8 +114,8 @@ Panel(UIPanel* panel)
|
|||||||
parent_end = parent.rect.vec1.y;
|
parent_end = parent.rect.vec1.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8[128] buf = 0;
|
u8[] buf = ScratchAlloc!(u8)(panel.id.length + 5);
|
||||||
(cast(char[])buf).sformat("sep_%s", cast(char[])panel.id);
|
(cast(char[])buf).sformat("%s_sep", cast(char[])panel.id);
|
||||||
|
|
||||||
separator = Get(buf);
|
separator = Get(buf);
|
||||||
|
|
||||||
@ -127,12 +127,11 @@ Panel(UIPanel* panel)
|
|||||||
if (separator.signal & UIS.Dragged && pos != 0.0)
|
if (separator.signal & UIS.Dragged && pos != 0.0)
|
||||||
{
|
{
|
||||||
f32 pct = Remap(pos, 0.0, parent_start-parent_end, 0.0, 1.0);
|
f32 pct = Remap(pos, 0.0, parent_start-parent_end, 0.0, 1.0);
|
||||||
|
if (CheckPanelBounds(panel.pct - pct) && CheckPanelBounds(panel.prev.pct + pct))
|
||||||
|
{
|
||||||
panel.pct -= pct;
|
panel.pct -= pct;
|
||||||
panel.prev.pct += pct;
|
panel.prev.pct += pct;
|
||||||
|
}
|
||||||
Logf("%f", pct);
|
|
||||||
|
|
||||||
Logf("%s %f %s %f", cast(char[])panel.id, panel.pct, cast(char[])panel.prev.id, panel.prev.pct);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +150,12 @@ Panel(UIPanel* panel)
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CheckPanelBounds(f32 pct)
|
||||||
|
{
|
||||||
|
return pct >= 0.0 && pct <= 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Separator(UIItem* item, f32 x_size, f32 y_size, Axis2D axis)
|
Separator(UIItem* item, f32 x_size, f32 y_size, Axis2D axis)
|
||||||
{
|
{
|
||||||
@ -162,6 +167,25 @@ Separator(UIItem* item, f32 x_size, f32 y_size, Axis2D axis)
|
|||||||
BuildItem(item, UISize(x_t, x_size), UISize(y_t, y_size), UIF.DrawBackground|UIF.Draggable);
|
BuildItem(item, UISize(x_t, x_size), UISize(y_t, y_size), UIF.DrawBackground|UIF.Draggable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextLine(u8[] text, f32 text_size, u64 line_no)
|
||||||
|
{
|
||||||
|
UIItem* parent = PeekParent();
|
||||||
|
|
||||||
|
if (!Nil(parent) && parent.size.x > 0.0)
|
||||||
|
{
|
||||||
|
SetColor(Vec4(1.0));
|
||||||
|
SetTextSize(text_size);
|
||||||
|
|
||||||
|
Node!(u8[])* lines = MakeMultiline(text, parent.size.x, line_no);
|
||||||
|
for(Node!(u8[])* line = lines; line != null; line = line.next)
|
||||||
|
{
|
||||||
|
UIItem* item = Get(line.value);
|
||||||
|
BuildItem(item, UISize(ST.Percentage, 1.0), UISize(ST.Pixels, text_size), UIF.DrawText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EndPanel()
|
EndPanel()
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user