Compare commits
No commits in common. "e6024b0ff42df9adbe323f2a7dec121aec7cee40" and "94e64fef9ea8b0c69ffede81682209e7ab3bf9ed" have entirely different histories.
e6024b0ff4
...
94e64fef9e
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +1 @@
|
|||||||
Subproject commit c2b7544979b16e1f27f419475b866a2903bd9c0a
|
Subproject commit 11cf96b799c6ccee3c4f569e89c263d11c4d5ff8
|
||||||
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit c00c404006147838fb8af3259cf214396da31c99
|
Subproject commit bda9abf8b9c74844cb30edb32e81543cbd5ae89d
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import dlib;
|
import dlib;
|
||||||
import dlib.alloc : Reset;
|
|
||||||
import core.stdc.stdio : EOF;
|
import core.stdc.stdio : EOF;
|
||||||
import parsing;
|
import parsing;
|
||||||
import parsing : SetBuffers;
|
import parsing : SetBuffers;
|
||||||
@ -477,12 +476,6 @@ SliceLineBuffer(FlatBuffer* fb, Line* ls)
|
|||||||
return lbuf;
|
return lbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
|
||||||
ResetBuffer(FlatBuffer* fb)
|
|
||||||
{
|
|
||||||
Reset(&fb.linebufs.arena);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MoveToEOL(FlatBuffer* fb)
|
MoveToEOL(FlatBuffer* fb)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -61,7 +61,10 @@ struct Editor
|
|||||||
I64Vec2 cursor_pos;
|
I64Vec2 cursor_pos;
|
||||||
Vec2 select_start;
|
Vec2 select_start;
|
||||||
Vec2 select_end;
|
Vec2 select_end;
|
||||||
|
|
||||||
i64 line_offset;
|
i64 line_offset;
|
||||||
|
|
||||||
|
f32 text_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChangeStacks
|
struct ChangeStacks
|
||||||
@ -152,6 +155,48 @@ Cycle(Inputs* inputs)
|
|||||||
{
|
{
|
||||||
CommandPalette(&g_ed_ctx.cmd);
|
CommandPalette(&g_ed_ctx.cmd);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
UIPanel* root = ctx.base_panel;
|
||||||
|
|
||||||
|
root.size.x = g_ui_ctx.res.x;
|
||||||
|
root.size.y = g_ui_ctx.res.y;
|
||||||
|
root.rect.p0 = 0.0;
|
||||||
|
root.rect.p1 = 0.0;
|
||||||
|
|
||||||
|
static foreach(axis; A2D.min .. A2D.max)
|
||||||
|
{
|
||||||
|
for(UIPanel* p = root; !Nil(p); p = Recurse(p, g_UI_NIL_PANEL))
|
||||||
|
{
|
||||||
|
f32 pos = p.rect.p0.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.p0.v[axis] = pos;
|
||||||
|
c.rect.p1.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, g_UI_NIL_PANEL))
|
||||||
|
{
|
||||||
|
Panel(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ctx.state == ES.CmdOpen)
|
||||||
|
{
|
||||||
|
if(ctx.cmd.commands.length == 0 && ctx.cmd.icount == 0)
|
||||||
|
{
|
||||||
|
GetCommands(&ctx.cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandPalette(&ctx.cmd);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
EndUI();
|
EndUI();
|
||||||
}
|
}
|
||||||
@ -221,7 +266,6 @@ CreatePanel(EditorCtx* ctx, Editor* ed = null)
|
|||||||
p.layout_axis = A2D.Y;
|
p.layout_axis = A2D.Y;
|
||||||
p.ed = ed;
|
p.ed = ed;
|
||||||
p.id = ctx.panel_id++;
|
p.id = ctx.panel_id++;
|
||||||
p.text_size = 18;
|
|
||||||
p.parent = p.first = p.last = p.next = p.prev = g_NIL_PANEL;
|
p.parent = p.first = p.last = p.next = p.prev = g_NIL_PANEL;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
|||||||
460
src/editor/ui.d
460
src/editor/ui.d
@ -37,20 +37,18 @@ enum Vec4 TEXT_HL_COL = Vec4(0.0, 0.0, 0.0, 1.0);
|
|||||||
|
|
||||||
const u64 VERTEX_MAX_COUNT = 10000;
|
const u64 VERTEX_MAX_COUNT = 10000;
|
||||||
const Vec2 CLICK_BUFFER = Vec2(3.0, 3.0);
|
const Vec2 CLICK_BUFFER = Vec2(3.0, 3.0);
|
||||||
const u32 FONT_SIZES = 24;
|
|
||||||
const u32 ATLAS_DIMENSION = 512;
|
|
||||||
|
|
||||||
// TODO: add setting
|
// TODO: add setting
|
||||||
|
const f32 TEXT_SIZE = 16.0;
|
||||||
const f32 SCROLL_SPEED = 48.0;
|
const f32 SCROLL_SPEED = 48.0;
|
||||||
const f32 LINE_COUNT_PADDING = 4.0;
|
const f32 LINE_COUNT_PADDING = 4.0;
|
||||||
|
|
||||||
__gshared UICtx g_ui_ctx;
|
__gshared UICtx g_ui_ctx;
|
||||||
|
|
||||||
//const u8[] FONT_BYTES = import("pc-9800.ttf");
|
//const u8[] FONT_BYTES = import("pc-9800.ttf");
|
||||||
//const u8[] FONT_BYTES = import("NuberNextCondensed-DemiBold.otf");
|
const u8[] FONT_BYTES = import("NuberNextCondensed-DemiBold.otf");
|
||||||
u8[] FONT_BYTES = cast(u8[])import("jetbrains-mono/JetBrainsMono-Regular.ttf");
|
const u8[] VERTEX_BYTES = import("gui.vert.spv");
|
||||||
u8[] VERTEX_BYTES = cast(u8[])import("gui.vert.spv");
|
const u8[] FRAGMENT_BYTES = import("gui.frag.spv");
|
||||||
u8[] FRAGMENT_BYTES = cast(u8[])import("gui.frag.spv");
|
|
||||||
|
|
||||||
Vec4 g_corner_radius_default = 0.0;
|
Vec4 g_corner_radius_default = 0.0;
|
||||||
f32 g_edge_softness_default = 0.8;
|
f32 g_edge_softness_default = 0.8;
|
||||||
@ -64,7 +62,7 @@ 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)];
|
UISize[2] g_size_info_default = [UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0)];
|
||||||
Axis2D g_layout_axis_default = A2D.X;
|
Axis2D g_layout_axis_default = A2D.X;
|
||||||
Vec2 g_padding_default = Vec2(0.0);
|
Vec2 g_padding_default = Vec2(0.0);
|
||||||
u32 g_text_size_default = 18;
|
f32 g_text_scale_default = 1.0;
|
||||||
Vec2 g_scroll_target_default = Vec2(0.0);
|
Vec2 g_scroll_target_default = Vec2(0.0);
|
||||||
Vec2 g_scroll_clamp_default = Vec2(0.0);
|
Vec2 g_scroll_clamp_default = Vec2(0.0);
|
||||||
Vec2 g_view_offset_default = Vec2(0.0);
|
Vec2 g_view_offset_default = Vec2(0.0);
|
||||||
@ -133,7 +131,6 @@ enum UIFlags
|
|||||||
alias UIF = UIFlags;
|
alias UIF = UIFlags;
|
||||||
|
|
||||||
const UIFlags AUTO_FLAGS = UIF.ResizeAdjacent;
|
const UIFlags AUTO_FLAGS = UIF.ResizeAdjacent;
|
||||||
const UIFlags DRAW_FLAGS = UIF.DrawBackground|UIF.DrawBorder|UIF.DrawText|UIF.PortalView;
|
|
||||||
|
|
||||||
enum UISignal
|
enum UISignal
|
||||||
{
|
{
|
||||||
@ -236,8 +233,7 @@ struct UICtx
|
|||||||
|
|
||||||
PlatformWindow* window;
|
PlatformWindow* window;
|
||||||
Renderer rd;
|
Renderer rd;
|
||||||
Descriptor[FONT_SIZES] font_descs;
|
Descriptor font_atlas;
|
||||||
Descriptor default_tex;
|
|
||||||
Descriptor sampler;
|
Descriptor sampler;
|
||||||
Pipeline pipeline;
|
Pipeline pipeline;
|
||||||
DescSetLayout desc_set_layout;
|
DescSetLayout desc_set_layout;
|
||||||
@ -246,13 +242,16 @@ struct UICtx
|
|||||||
Mat4 projection;
|
Mat4 projection;
|
||||||
Vec2 res;
|
Vec2 res;
|
||||||
|
|
||||||
|
u8[] font_data;
|
||||||
FontFace font;
|
FontFace font;
|
||||||
FontGlyphs[FONT_SIZES] glyph_sets;
|
FontAtlasBuf atlas_buf;
|
||||||
u32 glyph_sets_used;
|
f32 char_width;
|
||||||
|
f32 char_height;
|
||||||
|
|
||||||
UIBuffer[FRAME_OVERLAP] buffers;
|
UIBuffer[FRAME_OVERLAP] buffers;
|
||||||
|
|
||||||
u32 tab_width;
|
u32 tab_width;
|
||||||
|
f32 text_size;
|
||||||
Vec4[TS.max][UISH.max] syntax_colors;
|
Vec4[TS.max][UISH.max] syntax_colors;
|
||||||
|
|
||||||
UIItem* window_root;
|
UIItem* window_root;
|
||||||
@ -279,18 +278,10 @@ struct UICtx
|
|||||||
mixin UICtxParameter!(Vec4, "corner_radius");
|
mixin UICtxParameter!(Vec4, "corner_radius");
|
||||||
mixin UICtxParameter!(f32, "border_thickness");
|
mixin UICtxParameter!(f32, "border_thickness");
|
||||||
mixin UICtxParameter!(f32, "edge_softness");
|
mixin UICtxParameter!(f32, "edge_softness");
|
||||||
mixin UICtxParameter!(u32, "text_size");
|
mixin UICtxParameter!(f32, "text_scale");
|
||||||
mixin UICtxParameter!(UISyntaxHighlight, "syntax_highlight");
|
mixin UICtxParameter!(UISyntaxHighlight, "syntax_highlight");
|
||||||
|
|
||||||
debug bool dbg;
|
debug bool dbg;
|
||||||
debug u64 item_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FontGlyphs
|
|
||||||
{
|
|
||||||
u32 size;
|
|
||||||
u32 index;
|
|
||||||
FontAtlasBuf abuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Stack(T)
|
struct Stack(T)
|
||||||
@ -346,7 +337,6 @@ struct UIItem
|
|||||||
|
|
||||||
UIItem* next, prev, first, last; // parent in mixin
|
UIItem* next, prev, first, last; // parent in mixin
|
||||||
UIItem* transient_next;
|
UIItem* transient_next;
|
||||||
UIItem* last_relative_item;
|
|
||||||
|
|
||||||
Rect rect;
|
Rect rect;
|
||||||
Vec2 size;
|
Vec2 size;
|
||||||
@ -422,7 +412,6 @@ struct Vertex
|
|||||||
f32 edge_softness;
|
f32 edge_softness;
|
||||||
f32 raised;
|
f32 raised;
|
||||||
u32 texture;
|
u32 texture;
|
||||||
u32 atlas_index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
union Rect
|
union Rect
|
||||||
@ -473,23 +462,26 @@ InitUICtx(PlatformWindow* window)
|
|||||||
|
|
||||||
UIBuffer[FRAME_OVERLAP] buffers;
|
UIBuffer[FRAME_OVERLAP] buffers;
|
||||||
|
|
||||||
UICtx* ctx = &g_ui_ctx;
|
UICtx ctx = {
|
||||||
|
items: CreateHashTable!(UIHash, UIItem*)(12),
|
||||||
ctx.items = CreateHashTable!(UIHash, UIItem*)(12);
|
free_items: Alloc!(UIItem)(&arena),
|
||||||
ctx.free_items = Alloc!(UIItem)(&arena);
|
arena: arena,
|
||||||
ctx.arena = arena;
|
temp_arena: CreateArena(MB(1)),
|
||||||
ctx.temp_arena = CreateArena(MB(1));
|
drag_item: g_UI_NIL,
|
||||||
ctx.drag_item = g_UI_NIL;
|
transient_items: g_UI_NIL,
|
||||||
ctx.transient_items = g_UI_NIL;
|
font: OpenFont(cast(u8[])FONT_BYTES),
|
||||||
ctx.font = OpenFont(cast(u8[])FONT_BYTES);
|
font_data: cast(u8[])FONT_BYTES,
|
||||||
ctx.tab_width = 2;
|
text_size: 16.0,
|
||||||
ctx.syntax_colors = [DEFAULT_COLORS, SYNTAX_COLORS];
|
tab_width: 2,
|
||||||
|
syntax_colors: [DEFAULT_COLORS, SYNTAX_COLORS],
|
||||||
assert(ctx.font);
|
};
|
||||||
|
|
||||||
UIItem* fi = ctx.free_items;
|
UIItem* fi = ctx.free_items;
|
||||||
fi.transient_next = fi.first = fi.last = fi.next = fi.prev = fi.parent = g_UI_NIL;
|
fi.transient_next = fi.first = fi.last = fi.next = fi.prev = fi.parent = g_UI_NIL;
|
||||||
|
|
||||||
|
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)
|
version(ENABLE_RENDERER)
|
||||||
{
|
{
|
||||||
ctx.rd = InitRenderer(handles, MB(16), MB(8));
|
ctx.rd = InitRenderer(handles, MB(16), MB(8));
|
||||||
@ -504,7 +496,7 @@ InitUICtx(PlatformWindow* window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DescLayoutBinding[2] layout_bindings = [
|
DescLayoutBinding[2] layout_bindings = [
|
||||||
{ binding: 0, descriptorType: DT.Image, descriptorCount: FONT_SIZES, stageFlags: SS.All },
|
{ binding: 0, descriptorType: DT.Image, descriptorCount: 1, stageFlags: SS.All },
|
||||||
{ binding: 1, descriptorType: DT.Sampler, descriptorCount: 1, stageFlags: SS.All },
|
{ binding: 1, descriptorType: DT.Sampler, descriptorCount: 1, stageFlags: SS.All },
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -512,7 +504,7 @@ InitUICtx(PlatformWindow* window)
|
|||||||
ctx.desc_set = AllocDescSet(&ctx.rd, ctx.desc_set_layout);
|
ctx.desc_set = AllocDescSet(&ctx.rd, ctx.desc_set_layout);
|
||||||
ctx.pipeline_layout = CreatePipelineLayout(&ctx.rd, ctx.desc_set_layout, Mat4.sizeof);
|
ctx.pipeline_layout = CreatePipelineLayout(&ctx.rd, ctx.desc_set_layout, Mat4.sizeof);
|
||||||
|
|
||||||
Attribute[] attributes = [
|
Attribute[13] attributes = [
|
||||||
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof },
|
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof },
|
||||||
{ binding: 0, location: 1, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof + f32.sizeof*0 },
|
{ binding: 0, location: 1, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof + f32.sizeof*0 },
|
||||||
{ binding: 0, location: 2, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof + f32.sizeof*1 },
|
{ binding: 0, location: 2, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof + f32.sizeof*1 },
|
||||||
@ -526,7 +518,6 @@ InitUICtx(PlatformWindow* window)
|
|||||||
{ binding: 0, location: 10, format: FMT.R_F32, offset: Vertex.edge_softness.offsetof },
|
{ binding: 0, location: 10, format: FMT.R_F32, offset: Vertex.edge_softness.offsetof },
|
||||||
{ binding: 0, location: 11, format: FMT.R_F32, offset: Vertex.raised.offsetof },
|
{ binding: 0, location: 11, format: FMT.R_F32, offset: Vertex.raised.offsetof },
|
||||||
{ binding: 0, location: 12, format: FMT.R_U32, offset: Vertex.texture.offsetof },
|
{ binding: 0, location: 12, format: FMT.R_U32, offset: Vertex.texture.offsetof },
|
||||||
{ binding: 0, location: 13, format: FMT.R_U32, offset: Vertex.atlas_index.offsetof },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
GfxPipelineInfo ui_info = {
|
GfxPipelineInfo ui_info = {
|
||||||
@ -544,69 +535,16 @@ InitUICtx(PlatformWindow* window)
|
|||||||
alpha_op: BO.Add,
|
alpha_op: BO.Add,
|
||||||
};
|
};
|
||||||
|
|
||||||
for(u32 i = 0; i < ctx.font_descs.length; i += 1)
|
|
||||||
{
|
|
||||||
CreateImageViewTex(&ctx.rd, &ctx.font_descs[i], ATLAS_DIMENSION, ATLAS_DIMENSION, DT.Image, 0, i);
|
|
||||||
ctx.glyph_sets[i].index = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
FontAtlasBuf* abuf = GetFontAtlas(g_text_size_default);
|
|
||||||
|
|
||||||
CreateGraphicsPipeline(&ctx.rd, &ctx.pipeline, &ui_info);
|
CreateGraphicsPipeline(&ctx.rd, &ctx.pipeline, &ui_info);
|
||||||
|
CreateImageView(&ctx.rd, &ctx.font_atlas, ctx.atlas_buf.atlas.width, ctx.atlas_buf.atlas.height, 4, ctx.atlas_buf.data, DT.Image, 0);
|
||||||
ctx.sampler = CreateSampler(&ctx.rd, MipmapMode.Nearest, 1);
|
ctx.sampler = CreateSampler(&ctx.rd, MipmapMode.Nearest, 1);
|
||||||
|
Write(&ctx.rd, ctx.desc_set, [ctx.font_atlas, ctx.sampler]);
|
||||||
u8[512*512*4] white_tex = 255;
|
|
||||||
for(u32 i = 1; i < ctx.font_descs.length; i += 1)
|
|
||||||
{
|
|
||||||
Transfer(&ctx.rd, &ctx.font_descs[i].view, white_tex, ATLAS_DIMENSION, ATLAS_DIMENSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
Write(&ctx.rd, ctx.desc_set, ctx.font_descs);
|
|
||||||
Write(&ctx.rd, ctx.desc_set, &ctx.sampler);
|
|
||||||
SetClearColors(&ctx.rd, [0.0, 0.0, 0.0, 1.0], [0.0, 0.0, 0.0, 0.0]);
|
SetClearColors(&ctx.rd, [0.0, 0.0, 0.0, 1.0], [0.0, 0.0, 0.0, 0.0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
InitStacks(ctx);
|
InitStacks(&ctx);
|
||||||
}
|
|
||||||
|
|
||||||
FontAtlasBuf*
|
g_ui_ctx = ctx;
|
||||||
GetFontAtlas(u32 size)
|
|
||||||
{
|
|
||||||
return &GetFontGlyphs(size).abuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
FontGlyphs*
|
|
||||||
GetFontGlyphs(u32 size)
|
|
||||||
{
|
|
||||||
UICtx* ctx = GetCtx();
|
|
||||||
|
|
||||||
FontGlyphs* fg = null;
|
|
||||||
for(u64 i = 0; i < ctx.glyph_sets_used; i += 1)
|
|
||||||
{
|
|
||||||
if(size == ctx.glyph_sets[i].size)
|
|
||||||
{
|
|
||||||
fg = &ctx.glyph_sets[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!fg)
|
|
||||||
{
|
|
||||||
u32 i = ctx.glyph_sets_used;
|
|
||||||
fg = &ctx.glyph_sets[i];
|
|
||||||
|
|
||||||
assert(ctx.font);
|
|
||||||
|
|
||||||
fg.abuf = CreateAtlas(&ctx.arena, ctx.font, cast(f32)size, ATLAS_DIMENSION);
|
|
||||||
fg.size = size;
|
|
||||||
|
|
||||||
Transfer(&ctx.rd, &ctx.font_descs[i].view, fg.abuf.data, ATLAS_DIMENSION, ATLAS_DIMENSION);
|
|
||||||
Write(&ctx.rd, ctx.desc_set, &ctx.font_descs[i]);
|
|
||||||
|
|
||||||
ctx.glyph_sets_used += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -688,41 +626,75 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FontAtlasBuf* abuf = GetFontAtlas(item.text_size);
|
item.max_text_width = 0.0;
|
||||||
string str = item.display_string.length ? item.display_string : item.key.text;
|
string str = item.display_string.length ? item.display_string : item.key.text;
|
||||||
item.max_text_width = cast(f32)(str.length)*abuf.atlas.max_advance;
|
|
||||||
if(item.flags & UIF.TextWrap)
|
if(item.flags & UIF.TextWrap)
|
||||||
{
|
{
|
||||||
|
|
||||||
f32 width = item.size_info[A2D.X].type == ST.TextSize ? item.parent.size.x : item.size.x;
|
f32 width = item.size_info[A2D.X].type == ST.TextSize ? item.parent.size.x : item.size.x;
|
||||||
u32 ch_per_line = cast(u32)floor(width/abuf.atlas.max_advance);
|
f32 text_width = CalcTextWidth(str);
|
||||||
u64 lines = (str.length/ch_per_line) + (str.length%ch_per_line ? 1 : 0);
|
|
||||||
|
|
||||||
u32 max_chars = str.length > ch_per_line ? ch_per_line : cast(u32)str.length;
|
if(text_width < width || width == 0.0) goto InitSingleLine;
|
||||||
item.max_text_width = cast(f32)(max_chars)*abuf.atlas.max_advance;
|
|
||||||
|
u64 lines = cast(u64)(ceil(text_width/width));
|
||||||
item.text_lines = ScratchAlloc!(string)(lines);
|
item.text_lines = ScratchAlloc!(string)(lines);
|
||||||
|
|
||||||
u64 start;
|
assert(!item.syntax_tokens.length || item.syntax_tokens.length == str.length);
|
||||||
for(u64 i = 0; i < lines; i += 1)
|
|
||||||
{
|
|
||||||
u64 end = str.length-start <= ch_per_line ? str.length : start+ch_per_line;
|
|
||||||
item.text_lines[i] = str[start .. end];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(item.syntax_tokens.length)
|
if(item.syntax_tokens.length)
|
||||||
{
|
{
|
||||||
item.token_lines = ScratchAlloc!(u8[])(lines);
|
item.token_lines = ScratchAlloc!(u8[])(lines);
|
||||||
for(u64 i = 0; i < lines; i += 1)
|
|
||||||
{
|
|
||||||
u64 end = str.length-start <= ch_per_line ? str.length : start+ch_per_line;
|
|
||||||
item.token_lines[i] = item.syntax_tokens[start .. end];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
if(item.syntax_tokens.length)
|
||||||
|
{
|
||||||
|
item.token_lines[line] = item.syntax_tokens[ch_start .. i];
|
||||||
|
}
|
||||||
|
|
||||||
|
line += 1;
|
||||||
|
ch_start = i;
|
||||||
|
|
||||||
|
item.max_text_width = item.max_text_width < w ? w : item.max_text_width;
|
||||||
|
|
||||||
|
if(line == lines-1)
|
||||||
|
{
|
||||||
|
item.text_lines[line] = str[ch_start .. $];
|
||||||
|
if(item.syntax_tokens.length)
|
||||||
|
{
|
||||||
|
item.token_lines[line] = item.syntax_tokens[ch_start .. $];
|
||||||
|
}
|
||||||
|
|
||||||
|
w = CalcTextWidth(item.text_lines[line]);
|
||||||
|
item.max_text_width = item.max_text_width < w ? w : item.max_text_width;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
w = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
w += glyph_w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
InitSingleLine:
|
||||||
item.text_lines = ScratchAlloc!(string)(1);
|
item.text_lines = ScratchAlloc!(string)(1);
|
||||||
item.text_lines[0] = str;
|
item.text_lines[0] = str;
|
||||||
|
item.max_text_width = CalcTextWidth(item.text_lines[0]);
|
||||||
|
|
||||||
if(item.syntax_tokens.length)
|
if(item.syntax_tokens.length)
|
||||||
{
|
{
|
||||||
@ -844,8 +816,6 @@ BeginUI(Inputs* inputs)
|
|||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
Arena* a = &ctx.temp_arena;
|
Arena* a = &ctx.temp_arena;
|
||||||
|
|
||||||
debug ctx.item_count = 0;
|
|
||||||
|
|
||||||
Reset(a);
|
Reset(a);
|
||||||
|
|
||||||
// Convert Inputs
|
// Convert Inputs
|
||||||
@ -915,20 +885,19 @@ BeginUI(Inputs* inputs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(UIItem* item = ctx.transient_items; !Nil(item);)
|
for(UIItem* item = ctx.transient_items; !Nil(item); item = item.transient_next)
|
||||||
{
|
{
|
||||||
UIItem* next = item.transient_next;
|
|
||||||
memset(item, 0, UIItem.sizeof);
|
memset(item, 0, UIItem.sizeof);
|
||||||
DLLPush(ctx.free_items, item, g_UI_NIL);
|
DLLPush(ctx.free_items, item, g_UI_NIL);
|
||||||
item = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.frame += 1;
|
||||||
|
ctx.transient_items = g_UI_NIL;
|
||||||
|
|
||||||
// Ctx state
|
// Ctx state
|
||||||
ctx.transient_items = g_UI_NIL;
|
|
||||||
ctx.frame += 1;
|
|
||||||
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
|
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
|
||||||
ctx.inputs = inputs;
|
ctx.inputs = inputs;
|
||||||
|
ctx.char_width = GlyphWidth(&ctx.atlas_buf.atlas.glyphs[' ']);
|
||||||
|
|
||||||
ResetStacks(ctx);
|
ResetStacks(ctx);
|
||||||
|
|
||||||
@ -1023,7 +992,7 @@ EndUI()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
item.size.v[axis] = item.padding.y*2.0 + GetFontAtlas(item.text_size).atlas.line_height*item.text_lines.length;
|
item.size.v[axis] = item.padding.y*2.0 + TEXT_SIZE*item.text_lines.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1105,7 +1074,10 @@ EndUI()
|
|||||||
excess -= reduced;
|
excess -= reduced;
|
||||||
c.size.v[axis] -= reduced;
|
c.size.v[axis] -= reduced;
|
||||||
|
|
||||||
if(excess <= 0.0009) break;
|
if(excess <= 0.0009)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(excess > 0.0009)
|
if(excess > 0.0009)
|
||||||
@ -1121,7 +1093,10 @@ EndUI()
|
|||||||
excess -= reduced;
|
excess -= reduced;
|
||||||
c.size.v[axis] -= reduced;
|
c.size.v[axis] -= reduced;
|
||||||
|
|
||||||
if(excess < 0.0009) break;
|
if(excess < 0.0009)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1143,42 +1118,72 @@ EndUI()
|
|||||||
// Calculate final sizes
|
// Calculate final sizes
|
||||||
{
|
{
|
||||||
f32 pos = 0.0;
|
f32 pos = 0.0;
|
||||||
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
for(UIItem* item = ctx.root; !Nil(item);)
|
||||||
{
|
{
|
||||||
item.last_relative_item = g_UI_NIL;
|
|
||||||
|
|
||||||
bool fixed = cast(bool)(item.flags & UIF.FixedPosition);
|
bool fixed = cast(bool)(item.flags & UIF.FixedPosition);
|
||||||
UIItem* parent = item.parent;
|
|
||||||
|
bool first_child_fixed = item.parent.flags & UIF.FixedPosition && item == item.parent.first;
|
||||||
|
bool on_layout_axis = item.parent.layout_axis == axis;
|
||||||
|
if(!on_layout_axis || first_child_fixed)
|
||||||
|
{
|
||||||
|
pos = item.parent.rect.p0.v[axis] + item.parent.padding.v[axis];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(item.view_offset.x != 0.0 || item.view_offset.y != 0.0)
|
||||||
|
{
|
||||||
|
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||||
|
{
|
||||||
|
if(!(c.flags & UIF.FixedPosition))
|
||||||
|
{
|
||||||
|
c.pos_offset = item.view_offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f32 next_pos = 0.0;
|
||||||
if(fixed)
|
if(fixed)
|
||||||
{
|
{
|
||||||
item.rect.p0.v[axis] = parent.rect.p0.v[axis] + item.fixed_pos.v[axis] + item.padding.v[axis] + parent.view_offset.v[axis];
|
item.rect.p0.v[axis] = item.fixed_pos.v[axis] + item.parent.rect.p0.v[axis];
|
||||||
item.rect.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis] - item.padding.v[axis];
|
item.rect.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis];
|
||||||
}
|
|
||||||
else if(Nil(item.parent.last_relative_item))
|
next_pos = pos;
|
||||||
{
|
|
||||||
item.rect.p0.v[axis] = parent.rect.p0.v[axis] + item.padding.v[axis] + parent.view_offset.v[axis];
|
|
||||||
item.rect.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis] - item.padding.v[axis];
|
|
||||||
}
|
|
||||||
else if(axis != item.parent.layout_axis)
|
|
||||||
{
|
|
||||||
item.rect.p0.v[axis] = parent.rect.p0.v[axis] + parent.view_offset.v[axis] + item.padding.v[axis];
|
|
||||||
item.rect.p1.v[axis] = parent.rect.p0.v[axis] + item.size.v[axis] - item.padding.v[axis];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UIItem* prev = parent.last_relative_item;
|
item.rect.p0.v[axis] = pos + item.pos_offset.v[axis];
|
||||||
|
item.rect.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis];
|
||||||
|
|
||||||
item.rect.p0.v[axis] = prev.rect.p1.v[axis] + prev.padding.v[axis] + item.padding.v[axis];
|
next_pos = item.parent.layout_axis == axis ? item.rect.p1.v[axis] : item.rect.p0.v[axis];
|
||||||
item.rect.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis] - item.padding.v[axis];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!fixed && !Nil(parent))
|
|
||||||
{
|
|
||||||
parent.last_relative_item = item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!isNaN(item.rect.p0.v[axis]));
|
assert(!isNaN(item.rect.p0.v[axis]));
|
||||||
assert(!isNaN(item.rect.p1.v[axis]));
|
assert(!isNaN(item.rect.p1.v[axis]));
|
||||||
|
|
||||||
|
if(!Nil(item.first))
|
||||||
|
{
|
||||||
|
item = item.first;
|
||||||
|
}
|
||||||
|
else if(!Nil(item.next))
|
||||||
|
{
|
||||||
|
item = item.next;
|
||||||
|
pos = next_pos;
|
||||||
|
}
|
||||||
|
else for(UIItem* p = item.parent;; p = p.parent)
|
||||||
|
{
|
||||||
|
if(!Nil(p.next))
|
||||||
|
{
|
||||||
|
item = p.next;
|
||||||
|
pos = item.parent.layout_axis == axis ? item.prev.rect.p1.v[axis] : item.parent.rect.p0.v[axis];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Nil(p))
|
||||||
|
{
|
||||||
|
item = g_UI_NIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1232,10 +1237,6 @@ void
|
|||||||
RenderItem(UICtx* ctx, UIItem* item)
|
RenderItem(UICtx* ctx, UIItem* item)
|
||||||
{
|
{
|
||||||
if(item.rendered) return;
|
if(item.rendered) return;
|
||||||
if(!(item.flags & DRAW_FLAGS)) return;
|
|
||||||
|
|
||||||
Vec2 p0 = item.rect.p0 - item.padding;
|
|
||||||
Vec2 p1 = item.rect.p1 + item.padding;
|
|
||||||
|
|
||||||
// Doesn't really support nesting scissors, will maybe change this later.
|
// Doesn't really support nesting scissors, will maybe change this later.
|
||||||
bool scissor_x = cast(bool)(item.flags & UIF.PortalViewX);
|
bool scissor_x = cast(bool)(item.flags & UIF.PortalViewX);
|
||||||
@ -1244,18 +1245,18 @@ RenderItem(UICtx* ctx, UIItem* item)
|
|||||||
{
|
{
|
||||||
DrawUI(ctx);
|
DrawUI(ctx);
|
||||||
|
|
||||||
u32 x = cast(u32)(scissor_x ? floor(p0.x) : 0);
|
u32 x = cast(u32)(scissor_x ? floor(item.rect.p0.x) : 0);
|
||||||
u32 y = cast(u32)(scissor_y ? floor(p0.y) : 0);
|
u32 y = cast(u32)(scissor_y ? floor(item.rect.p0.y) : 0);
|
||||||
u32 w = cast(u32)(scissor_x ? floor(p1.x) - x : ctx.res.x);
|
u32 w = cast(u32)(scissor_x ? floor(item.rect.p1.x) - x : ctx.res.x);
|
||||||
u32 h = cast(u32)(scissor_y ? floor(p1.y) - y : ctx.res.y);
|
u32 h = cast(u32)(scissor_y ? floor(item.rect.p1.y) - y : ctx.res.y);
|
||||||
SetScissor(&ctx.rd, x, y, w, h);
|
SetScissor(&ctx.rd, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(item.flags & UIF.DrawBackground)
|
if(item.flags & UIF.DrawBackground)
|
||||||
{
|
{
|
||||||
Vertex* v = GetVertex(ctx);
|
Vertex* v = GetVertex(ctx);
|
||||||
v.dst_start = p0 + item.border_thickness;
|
v.dst_start = item.rect.p0 + item.border_thickness;
|
||||||
v.dst_end = p1 - item.border_thickness;
|
v.dst_end = item.rect.p1 - item.border_thickness;
|
||||||
v.cols = item.bg_col;
|
v.cols = item.bg_col;
|
||||||
v.corner_radius = item.flags & UIF.DrawBorder ? item.corner_radius*0.5 : item.corner_radius;
|
v.corner_radius = item.flags & UIF.DrawBorder ? item.corner_radius*0.5 : item.corner_radius;
|
||||||
v.bounds = ItemBounds(item.parent);
|
v.bounds = ItemBounds(item.parent);
|
||||||
@ -1266,8 +1267,8 @@ RenderItem(UICtx* ctx, UIItem* item)
|
|||||||
if(item.flags & UIF.DrawBorder)
|
if(item.flags & UIF.DrawBorder)
|
||||||
{
|
{
|
||||||
Vertex* v = GetVertex(ctx);
|
Vertex* v = GetVertex(ctx);
|
||||||
v.dst_start = p0;
|
v.dst_start = item.rect.p0;
|
||||||
v.dst_end = p1;
|
v.dst_end = item.rect.p1;
|
||||||
v.cols = item.border_col;
|
v.cols = item.border_col;
|
||||||
v.corner_radius = item.corner_radius;
|
v.corner_radius = item.corner_radius;
|
||||||
v.border_thickness = clamp(item.border_thickness, 1.0, f32.max);
|
v.border_thickness = clamp(item.border_thickness, 1.0, f32.max);
|
||||||
@ -1285,25 +1286,27 @@ RenderItem(UICtx* ctx, UIItem* item)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FontGlyphs* fg = GetFontGlyphs(item.text_size);
|
// The math around all this is fucked
|
||||||
f32 y_pos = p0.y + fg.abuf.atlas.line_height;
|
FontAtlas* atl = &ctx.atlas_buf.atlas;
|
||||||
|
f32 y_pos = item.rect.p0.y + item.padding.y;
|
||||||
Vec4[] syntax_cols = ctx.syntax_colors[item.syntax_highlight];
|
Vec4[] syntax_cols = ctx.syntax_colors[item.syntax_highlight];
|
||||||
|
|
||||||
foreach(i; 0 .. item.text_lines.length)
|
foreach(i; 0 .. item.text_lines.length)
|
||||||
{
|
{
|
||||||
string str = item.text_lines[i];
|
string str = item.text_lines[i];
|
||||||
u8[] tks = item.token_lines.length ? item.token_lines[i] : [];
|
u8[] tks = item.token_lines.length ? item.token_lines[i] : [];
|
||||||
f32 x_pos = item.flags & UIF.RightAlignText ? p1.x - item.padding.x - CalcTextWidth(str, &fg.abuf) : p0.x + item.padding.x;
|
f32 x_pos = item.flags & UIF.RightAlignText ? item.rect.p1.x - item.padding.x - CalcTextWidth(str) :
|
||||||
|
item.rect.p0.x + item.padding.x;
|
||||||
|
|
||||||
x_pos = clamp(x_pos, p0.x, p1.x);
|
x_pos = clamp(x_pos, item.rect.p0.x, item.rect.p1.x);
|
||||||
|
|
||||||
if(tks.length)
|
if(tks.length)
|
||||||
{
|
{
|
||||||
foreach(j; 0 .. str.length)
|
foreach(j; 0 .. str.length)
|
||||||
{
|
{
|
||||||
u8 ch = str[j];
|
u8 ch = str[j];
|
||||||
Glyph* g = ch < fg.abuf.atlas.glyphs.length ? fg.abuf.atlas.glyphs.ptr + ch : null;
|
Glyph* g = ch < atl.glyphs.length ? atl.glyphs.ptr + ch : null;
|
||||||
DrawGlyph(item, g, fg.index, &x_pos, y_pos, syntax_cols[tks[j]]);
|
DrawGlyph(item, g, &x_pos, y_pos, syntax_cols[tks[j]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1311,12 +1314,12 @@ RenderItem(UICtx* ctx, UIItem* item)
|
|||||||
foreach(j; 0 .. str.length)
|
foreach(j; 0 .. str.length)
|
||||||
{
|
{
|
||||||
u8 ch = str[j];
|
u8 ch = str[j];
|
||||||
Glyph* g = ch < fg.abuf.atlas.glyphs.length ? fg.abuf.atlas.glyphs.ptr + ch : null;
|
Glyph* g = ch < atl.glyphs.length ? atl.glyphs.ptr + ch : null;
|
||||||
DrawGlyph(item, g, fg.index, &x_pos, y_pos, item.text_col);
|
DrawGlyph(item, g, &x_pos, y_pos, item.text_col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y_pos += fg.abuf.atlas.line_height;
|
y_pos += TEXT_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1373,17 +1376,6 @@ StackIDs(string stack, string ctx = "ctx")
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PushSizeInfo(SizeType type0, f32 value0, f32 strictness0, SizeType type1, f32 value1, f32 strictness1, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
UISize[2] size_info = [
|
|
||||||
UISize(type0, value0, strictness0),
|
|
||||||
UISize(type1, value1, strictness1),
|
|
||||||
];
|
|
||||||
|
|
||||||
Push!("size_info")(size_info, auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PushSizeInfoVec(int i)(SizeType type, f32 value, f32 strictness = 1.0, bool auto_pop = false)
|
PushSizeInfoVec(int i)(SizeType type, f32 value, f32 strictness = 1.0, bool auto_pop = false)
|
||||||
{
|
{
|
||||||
@ -1471,52 +1463,24 @@ PushScrollTargetY(f32 target, bool auto_pop = false)
|
|||||||
PushScrollTarget(Vec2(0.0, target), auto_pop);
|
PushScrollTarget(Vec2(0.0, target), auto_pop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static string
|
|
||||||
PushScope(string stack, string value)()
|
|
||||||
{
|
|
||||||
import std.conv;
|
|
||||||
return i"Push!(\"$(stack)\")($(value)); scope(exit) Pop!(\"$(stack)\")();".text;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string
|
|
||||||
PushOnce(UIPushInfo[] info)()
|
|
||||||
{
|
|
||||||
import std.conv;
|
|
||||||
|
|
||||||
string result = "";
|
|
||||||
static foreach(i; info)
|
|
||||||
{
|
|
||||||
result ~= i"Push!(\"$(i.s)\")($(i.v), true); scope(exit) Pop!(\"$(i.s)\")();".text;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UIPushInfo
|
|
||||||
{
|
|
||||||
string s; // stack
|
|
||||||
string v; // value
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Push(string stack_str, T)(T value, bool auto_pop = false)
|
Push(string stack_str, T)(T value, bool auto_pop = false)
|
||||||
{
|
{
|
||||||
import std.string : replace;
|
import std.string : replace;
|
||||||
|
|
||||||
enum ids = StackIDs!(stack_str, "g_ui_ctx");
|
enum ids = StackIDs!(stack_str, "g_ui_ctx");
|
||||||
alias ST = typeof(mixin(ids.stack ~ ".top.value"));
|
|
||||||
|
|
||||||
auto stack = &mixin(ids.stack);
|
auto stack = &mixin(ids.stack);
|
||||||
auto top = mixin(ids.stack_top_node);
|
auto top = mixin(ids.stack_top_node);
|
||||||
|
|
||||||
Stack!(ST)* node = stack.free;
|
Stack!(T)* node = stack.free;
|
||||||
if(node)
|
if(node)
|
||||||
{
|
{
|
||||||
stack.free = node.next;
|
stack.free = node.next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node = Alloc!(Stack!(ST))(&g_ui_ctx.temp_arena);
|
node = Alloc!(Stack!(T))(&g_ui_ctx.temp_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.next = stack.top;
|
node.next = stack.top;
|
||||||
@ -1798,10 +1762,11 @@ NewItem(UICtx* ctx)
|
|||||||
{
|
{
|
||||||
UIItem* item = g_UI_NIL;
|
UIItem* item = g_UI_NIL;
|
||||||
|
|
||||||
debug ctx.item_count += 1;
|
if(!Nil(ctx.free_items.first))
|
||||||
|
{
|
||||||
item = DLLPop(ctx.free_items, g_UI_NIL);
|
item = DLLPop(ctx.free_items, g_UI_NIL);
|
||||||
if(Nil(item))
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
item = Alloc!(UIItem)(&ctx.arena);
|
item = Alloc!(UIItem)(&ctx.arena);
|
||||||
}
|
}
|
||||||
@ -1842,7 +1807,6 @@ Get(T)(T k) if(is(T: UIKey) || StringType!T)
|
|||||||
Result!(UIItem*) res = ctx.items[key.hash];
|
Result!(UIItem*) res = ctx.items[key.hash];
|
||||||
if(res.ok)
|
if(res.ok)
|
||||||
{
|
{
|
||||||
debug ctx.item_count += 1;
|
|
||||||
item = res.value;
|
item = res.value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1859,7 +1823,7 @@ Get(T)(T k) if(is(T: UIKey) || StringType!T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
f32
|
f32
|
||||||
CalcTextWidth(bool fast = true, T, U)(T text, U param) if((is(T == string) || StringType!T) && (is(U: u32) || is(U == FontAtlasBuf*) ))
|
CalcTextWidth(T)(T text) if(is(T == string) || StringType!T)
|
||||||
{
|
{
|
||||||
static if(is(T == string))
|
static if(is(T == string))
|
||||||
{
|
{
|
||||||
@ -1870,63 +1834,42 @@ CalcTextWidth(bool fast = true, T, U)(T text, U param) if((is(T == string) || St
|
|||||||
string str = ConvToStr(text);
|
string str = ConvToStr(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
static if(is(U: u32))
|
|
||||||
{
|
|
||||||
FontAtlasBuf* abuf = GetFontAtlas(param);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FontAtlasBuf* abuf = param;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 tab_width = g_ui_ctx.tab_width;
|
u32 tab_width = g_ui_ctx.tab_width;
|
||||||
|
Glyph* space = g_ui_ctx.atlas_buf.atlas.glyphs.ptr + ' ';
|
||||||
|
|
||||||
static if(fast)
|
|
||||||
{
|
|
||||||
f32 width = str.length * abuf.atlas.max_advance;
|
|
||||||
assert(abuf.atlas.max_advance > 0.0009);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
f32 width = 0.0;
|
f32 width = 0.0;
|
||||||
for(u64 i = 0; i < str.length; i += 1)
|
for(u64 i = 0; i < str.length; i += 1)
|
||||||
{
|
{
|
||||||
width += GlyphWidth(abuf.atlas.glyphs.ptr + str.ptr[i], abuf);
|
width += GlyphWidth(g_ui_ctx.atlas_buf.atlas.glyphs.ptr + str.ptr[i]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) f32
|
pragma(inline) f32
|
||||||
GlyphWidth(Glyph* g, FontAtlasBuf* abuf)
|
GlyphWidth(Glyph* g)
|
||||||
{
|
{
|
||||||
return g.ch == '\t' ? (abuf.atlas.glyphs[' '].advance*cast(f32)(g_ui_ctx.tab_width)) : g.advance;
|
return g.ch == '\t' ? (g_ui_ctx.atlas_buf.atlas.glyphs[' '].advance*cast(f32)(g_ui_ctx.tab_width)) : g.advance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawGlyph(UIItem* item, Glyph* glyph, u32 atlas_index, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
||||||
{
|
{
|
||||||
if(glyph)
|
if(glyph)
|
||||||
{
|
{
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
Vertex* v = null;
|
Vertex* v = null;
|
||||||
f32 advance = glyph.advance;
|
f32 advance = glyph.advance * item.text_scale;
|
||||||
|
|
||||||
if(glyph.ch == ' ' || glyph.ch == '\n')
|
if(glyph.ch == '\t')
|
||||||
{
|
|
||||||
*x_pos += advance;
|
|
||||||
}
|
|
||||||
else if(glyph.ch == '\t')
|
|
||||||
{
|
{
|
||||||
*x_pos += advance * (GetCtx().tab_width - 1);
|
*x_pos += advance * (GetCtx().tab_width - 1);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
f32 r = glyph.plane_right * item.text_scale;
|
||||||
f32 r = glyph.plane_right;
|
f32 l = glyph.plane_left * item.text_scale;
|
||||||
f32 l = glyph.plane_left;
|
f32 t = glyph.plane_top * item.text_scale;
|
||||||
f32 t = glyph.plane_top;
|
f32 b = glyph.plane_bottom * item.text_scale;
|
||||||
f32 b = glyph.plane_bottom;
|
|
||||||
|
|
||||||
GlyphBounds gb = {
|
GlyphBounds gb = {
|
||||||
r: r,
|
r: r,
|
||||||
@ -1943,14 +1886,13 @@ DrawGlyph(UIItem* item, Glyph* glyph, u32 atlas_index, f32* x_pos, f32 y, Vec4 c
|
|||||||
|
|
||||||
v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
||||||
|
|
||||||
f32 y_pos = y + gb.t;
|
f32 y_pos = (y - gb.t) + TEXT_SIZE;
|
||||||
|
|
||||||
v.dst_start = Vec2(*x_pos+gb.l, y_pos);
|
v.dst_start = Vec2(*x_pos+gb.l, y_pos);
|
||||||
v.dst_end = Vec2(*x_pos+gb.w+gb.l, y_pos+gb.h);
|
v.dst_end = Vec2(*x_pos+gb.w+gb.l, y_pos+gb.h);
|
||||||
v.cols = col;
|
v.cols = col;
|
||||||
v.texture = true;
|
v.texture = true;
|
||||||
v.bounds = ItemBounds(item);
|
v.bounds = ItemBounds(item);
|
||||||
v.atlas_index = atlas_index;
|
|
||||||
|
|
||||||
if(glyph.ch != '\t' && glyph.ch != '\n')
|
if(glyph.ch != '\t' && glyph.ch != '\n')
|
||||||
{
|
{
|
||||||
@ -1968,8 +1910,7 @@ DrawGlyph(UIItem* item, Glyph* glyph, u32 atlas_index, f32* x_pos, f32 y, Vec4 c
|
|||||||
v.src_end.x -= (v.src_end.x - v.src_start.x) * cull_pct;
|
v.src_end.x -= (v.src_end.x - v.src_start.x) * cull_pct;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
f32 end_y = y + TEXT_SIZE;
|
||||||
f32 end_y = y;
|
|
||||||
f32 height = end_y - y;
|
f32 height = end_y - y;
|
||||||
if(end_y > item.rect.p1.y)
|
if(end_y > item.rect.p1.y)
|
||||||
{
|
{
|
||||||
@ -1977,7 +1918,6 @@ DrawGlyph(UIItem* item, Glyph* glyph, u32 atlas_index, f32* x_pos, f32 y, Vec4 c
|
|||||||
v.dst_end.y -= (v.dst_end.y - v.dst_start.y) * cull_pct;
|
v.dst_end.y -= (v.dst_end.y - v.dst_start.y) * cull_pct;
|
||||||
v.src_end.y -= (v.src_end.y - v.src_start.y) * cull_pct;
|
v.src_end.y -= (v.src_end.y - v.src_start.y) * cull_pct;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
static foreach(axis; A2D.min .. A2D.max)
|
static foreach(axis; A2D.min .. A2D.max)
|
||||||
{
|
{
|
||||||
@ -1992,7 +1932,6 @@ DrawGlyph(UIItem* item, Glyph* glyph, u32 atlas_index, f32* x_pos, f32 y, Vec4 c
|
|||||||
*x_pos += advance;
|
*x_pos += advance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline) Vec2[2]
|
pragma(inline) Vec2[2]
|
||||||
ItemBounds(UIItem* item)
|
ItemBounds(UIItem* item)
|
||||||
@ -2013,23 +1952,30 @@ GetVertex(UICtx* ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static UISize[2]
|
static UISize[2]
|
||||||
UIS2(SizeType t0 = ST.Percentage, SizeType t1 = ST.Percentage, f32 v0 = 1.0, f32 v1 = 1.0, f32 s0 = 1.0, f32 s1 = 1.0)
|
MakeUISize(UISize x, UISize y)
|
||||||
{
|
{
|
||||||
return [UISize(t0, v0, s0), UISize(t1, v1, s1)];
|
return [x, y];
|
||||||
}
|
}
|
||||||
|
|
||||||
static UISize[2]
|
static UISize[2]
|
||||||
UISX(SizeType type, f32 value = 1.0, f32 strictness = 1.0)
|
MakeUISizeX(SizeType type, f32 value, f32 strictness = 1.0)
|
||||||
{
|
{
|
||||||
return [UISize(type, value, strictness), UISize(ST.Percentage, 1.0)];
|
return [UISize(type, value, strictness), UISize(ST.Percentage, 1.0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static UISize[2]
|
static UISize[2]
|
||||||
UISY(SizeType type, f32 value = 1.0, f32 strictness = 1.0)
|
MakeUISizeY(SizeType type, f32 value, f32 strictness = 1.0)
|
||||||
{
|
{
|
||||||
return [UISize(ST.Percentage, 1.0), UISize(type, value, strictness)];
|
return [UISize(ST.Percentage, 1.0), UISize(type, value, strictness)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pragma(inline) Glyph*
|
||||||
|
GetGlyph(u8 ch)
|
||||||
|
{
|
||||||
|
FontAtlas* a = &g_ui_ctx.atlas_buf.atlas;
|
||||||
|
return ch < a.glyphs.length ? a.glyphs.ptr + ch : a.glyphs.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
AddVertexCount(UICtx* ctx)
|
AddVertexCount(UICtx* ctx)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -31,105 +31,84 @@ struct Panel
|
|||||||
Axis2D layout_axis;
|
Axis2D layout_axis;
|
||||||
Editor* ed;
|
Editor* ed;
|
||||||
u64 id;
|
u64 id;
|
||||||
u32 text_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LineCounterView(FontAtlasBuf* abuf, u64 max_line, u64 lines, i64 line_offset, f32 view_offset)
|
LineCounterView(u64 max_line, u64 lines, i64 line_offset, f32 view_offset)
|
||||||
{
|
{
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
UIKey zero = ZeroKey();
|
UIKey zero = ZeroKey();
|
||||||
|
|
||||||
u64 ch_width = max_line.toChars().length;
|
u64 ch_width = max_line.toChars().length;
|
||||||
f32 lc_width = cast(f32)(ch_width+1)*abuf.atlas.max_advance;
|
f32 lc_width = cast(f32)(ch_width+1)*ctx.char_width; // Should figure out how to accurately measure text width
|
||||||
|
|
||||||
enum UIPushInfo[] lc_params = [
|
PushLayoutAxis(A2D.Y, true);
|
||||||
{ "layout_axis", q{ A2D.Y } },
|
PushViewOffsetY(view_offset, true);
|
||||||
{ "view_offset", q{ Vec2(0.0, view_offset) } },
|
PushPaddingX(4.0, true);
|
||||||
{ "padding", q{ Vec2(8.0) } },
|
PushSizeInfoX(ST.Pixels, lc_width, 1.0, true);
|
||||||
{ "size_info", q{ UISX(ST.Pixels, lc_width) }},
|
|
||||||
];
|
|
||||||
|
|
||||||
mixin(PushOnce!(lc_params));
|
|
||||||
|
|
||||||
UIItem* line_count = MakeItem(zero, UIF.DrawBorder|UIF.PortalViewY);
|
UIItem* line_count = MakeItem(zero, UIF.DrawBorder|UIF.PortalViewY);
|
||||||
|
|
||||||
mixin(PushScope!("text_col", q{ Vec4(1.0) } ));
|
PushTextCol(Vec4(1.0));
|
||||||
mixin(PushScope!("size_info", q{ UISY(ST.Pixels, abuf.atlas.line_height) } ));
|
PushSizeInfoY(ST.Pixels, TEXT_SIZE);
|
||||||
mixin(PushScope!("parent", q{ line_count } ));
|
PushParent(line_count);
|
||||||
|
|
||||||
u64 end_line = lines+line_offset;
|
u64 end_line = lines+line_offset;
|
||||||
for(u64 i = line_offset; i < end_line && i < max_line; i += 1)
|
for(u64 i = line_offset; i < end_line && i < max_line; i += 1)
|
||||||
{
|
{
|
||||||
char[] buf = ScratchAlloc!(char)(ch_width);
|
char[] buf = ScratchAlloc!(char)(ch_width);
|
||||||
Push!("display_string")(ConvToStr(sformat(ScratchAlloc!(char)(ch_width), "%s", i)), true);
|
Push!("display_string")(ConvToStr(sformat(buf, "%s", i)), true);
|
||||||
MakeItem(zero, UIF.DrawText);
|
MakeItem(zero, UIF.DrawText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pop!("text_col", "size_info", "parent");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EditorTextView(UIItem* editor, Panel* p, FontAtlasBuf* abuf, u64 lines, i64 line_offset, f32 view_offset)
|
EditorTextView(UIItem* editor, Panel* p, u64 lines, i64 line_offset, f32 view_offset)
|
||||||
{
|
{
|
||||||
Editor* ed = p.ed;
|
Editor* ed = p.ed;
|
||||||
|
|
||||||
PushLayoutAxis(A2D.Y, true);
|
PushLayoutAxis(A2D.Y, true);
|
||||||
|
|
||||||
f32 text_size = cast(f32)p.text_size;
|
f32 clamp_y = cast(f32)(ed.buf.line_count-lines)*TEXT_SIZE;
|
||||||
f32 clamp_y = cast(f32)(ed.buf.line_count-lines)*text_size;
|
f32 scroll_pos = cast(f32)(ed.line_offset)*TEXT_SIZE;
|
||||||
f32 scroll_pos = cast(f32)(ed.line_offset)*text_size;
|
|
||||||
f32 padding = 8.0;
|
|
||||||
|
|
||||||
enum UIPushInfo[] text_view_params = [
|
PushLayoutAxis(A2D.Y, true);
|
||||||
{ "layout_axis", q{ A2D.Y } },
|
PushScrollClampY(0.0, clamp_y, true);
|
||||||
{ "border_col", q{ Vec4(1.0) } },
|
PushSizeInfo(g_size_info_default, true);
|
||||||
{ "size_info", q{ UIS2() } },
|
PushBorderCol(Vec4(1.0), true);
|
||||||
{ "scroll_target", q{ Vec2(0.0, scroll_pos) } },
|
PushScrollTargetY(scroll_pos, true);
|
||||||
{ "scroll_clamp", q{ Vec2(0.0, clamp_y) } },
|
PushViewOffsetY(view_offset, true);
|
||||||
{ "view_offset", q{ Vec2(0.0, view_offset) } },
|
|
||||||
{ "padding", q{ Vec2(padding) } },
|
|
||||||
];
|
|
||||||
mixin(PushOnce!(text_view_params));
|
|
||||||
|
|
||||||
editor = MakeItem(editor.key, UIF.DrawBorder|UIF.ScrollY|UIF.ClampY);
|
editor = MakeItem(editor.key, UIF.DrawBorder|UIF.ScrollY|UIF.ClampY);
|
||||||
|
|
||||||
mixin(PushScope!("parent", q{ editor }));
|
PushParent(editor);
|
||||||
|
|
||||||
UIKey zero = ZeroKey();
|
UIKey zero = ZeroKey();
|
||||||
|
|
||||||
// Cursor
|
// Cursor
|
||||||
{
|
{
|
||||||
LineBuffer* lb = GetLine(&ed.buf, ed.cursor_pos.y);
|
LineBuffer* lb = GetLine(&ed.buf, ed.cursor_pos.y);
|
||||||
|
|
||||||
u8 ch = lb.text.length > ed.cursor_pos.y ? lb.text[ed.cursor_pos.y] : 0;
|
f32 cursor_x = CalcTextWidth(lb.text[0 .. ed.cursor_pos.x]);
|
||||||
f32 line_h = abuf.atlas.line_height;
|
f32 cursor_y = cast(f32)(ed.cursor_pos.y - line_offset)*TEXT_SIZE + view_offset;
|
||||||
f32 cursor_x = CalcTextWidth!(false)(lb.text[0 .. ed.cursor_pos.x], abuf);
|
PushSizeInfo(MakeUISize(UISize(ST.Pixels, GetCtx().char_width), UISize(ST.Pixels, TEXT_SIZE)), true);
|
||||||
f32 cursor_y = cast(f32)(ed.cursor_pos.y - line_offset)*line_h;
|
PushFixedPos(Vec2(cursor_x, cursor_y), true);
|
||||||
Glyph* g = abuf.atlas.glyphs.length > ch ? abuf.atlas.glyphs.ptr + ch : abuf.atlas.glyphs.ptr + ' ';
|
PushBgCol(Vec4(1.0), true);
|
||||||
|
|
||||||
enum UIPushInfo[] cursor_info = [
|
|
||||||
{ "size_info", q{ UIS2(ST.Pixels, ST.Pixels, g.advance, line_h) } },
|
|
||||||
{ "fixed_pos", q{ Vec2(cursor_x, cursor_y) } },
|
|
||||||
{ "bg_col", q{ Vec4(1.0) } },
|
|
||||||
];
|
|
||||||
mixin(PushOnce!(cursor_info));
|
|
||||||
|
|
||||||
MakeItem(zero, UIF.DrawBackground|UIF.FixedPosition);
|
MakeItem(zero, UIF.DrawBackground|UIF.FixedPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin(PushScope!("size_info", q{ UISY(ST.TextSize) } ));
|
u64 end_line = line_offset+lines;
|
||||||
mixin(PushScope!("syntax_highlight", q{ UISH.D } ));
|
PushSizeInfoY(ST.TextSize, 1.0);
|
||||||
|
PushSyntaxHighlight(UISH.D);
|
||||||
|
|
||||||
// NEED TO FIX LINES BEING OFFSET FOR WHATEVER REASON
|
scope(exit) Pop!("size_info", "parent", "syntax_highlight");
|
||||||
|
|
||||||
u64 i = line_offset;
|
u64 i = line_offset;
|
||||||
for(LineBuffer* lb = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, lb) && i < line_offset+lines; i += 1, lb = GetLine(&ed.buf, i))
|
for(LineBuffer* lb = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, lb) && i < line_offset+lines; i += 1, lb = GetLine(&ed.buf, i))
|
||||||
{
|
{
|
||||||
enum UIPushInfo[] lc_info = [
|
PushDisplayString(ConvToStr(lb.text), true);
|
||||||
{ "display_string", q{ ConvToStr(lb.text) } },
|
PushSyntaxTokens(cast(u8[])lb.style, true);
|
||||||
{ "syntax_tokens", q{ cast(u8[])(lb.style) } },
|
|
||||||
];
|
|
||||||
mixin(PushOnce!(lc_info));
|
|
||||||
|
|
||||||
UIItem* line = MakeItem(zero, UIF.DrawText);
|
UIItem* line = MakeItem(zero, UIF.DrawText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +119,6 @@ EditorView(Panel* p)
|
|||||||
Editor* ed = p.ed;
|
Editor* ed = p.ed;
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
UIKey zero = ZeroKey();
|
UIKey zero = ZeroKey();
|
||||||
FontAtlasBuf* abuf = GetFontAtlas(p.text_size);
|
|
||||||
|
|
||||||
if(CheckNil(g_NIL_ED, ed))
|
if(CheckNil(g_NIL_ED, ed))
|
||||||
{
|
{
|
||||||
@ -154,26 +132,24 @@ EditorView(Panel* p)
|
|||||||
UIKey ed_key = MakeKey("###ed_%s", ed.editor_id);
|
UIKey ed_key = MakeKey("###ed_%s", ed.editor_id);
|
||||||
UIItem* editor = Get(ed_key);
|
UIItem* editor = Get(ed_key);
|
||||||
|
|
||||||
f32 text_size = abuf.atlas.line_height;
|
|
||||||
|
|
||||||
u64 frame_line_offset = ed.line_offset;
|
u64 frame_line_offset = ed.line_offset;
|
||||||
f32 frame_view_offset = -(editor.scroll_offset.y%text_size);
|
f32 frame_view_offset = -(editor.scroll_offset.y%TEXT_SIZE);
|
||||||
|
|
||||||
enum UIPushInfo[] c_info = [
|
PushBgCol(BG_COL, true);
|
||||||
{ "bg_col", q{ BG_COL } },
|
PushSizeInfoX(ST.Percentage, 1.0, 1.0, true);
|
||||||
{ "size_info", q{ UIS2() } },
|
|
||||||
];
|
|
||||||
mixin(PushOnce!(c_info));
|
|
||||||
|
|
||||||
UIItem* container = MakeItem(zero, UIF.DrawBackground);
|
UIItem* container = MakeItem(zero, UIF.DrawBackground);
|
||||||
|
|
||||||
mixin(PushScope!("parent", q{ container } ));
|
PushParent(container);
|
||||||
mixin(PushScope!("border_col", q{ Vec4(1.0) } ));
|
PushBorderCol(Vec4(1.0));
|
||||||
|
|
||||||
|
scope(exit) Pop!("parent", "border_col");
|
||||||
|
|
||||||
u64 view_lines;
|
u64 view_lines;
|
||||||
if(editor.size.y > 0.0)
|
if(editor.size.y > 0.0)
|
||||||
{
|
{
|
||||||
view_lines = cast(u64)floor(editor.size.y/text_size);
|
view_lines = cast(u64)ceil(editor.size.y/TEXT_SIZE)+1;
|
||||||
|
|
||||||
const u64 SCROLL_BUFFER = 4;
|
const u64 SCROLL_BUFFER = 4;
|
||||||
|
|
||||||
u64 start = ed.line_offset;
|
u64 start = ed.line_offset;
|
||||||
@ -190,9 +166,9 @@ EditorView(Panel* p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 start = cast(u64)floor(editor.scroll_offset.y/text_size);
|
u64 start = cast(u64)floor(editor.scroll_offset.y/TEXT_SIZE);
|
||||||
LineCounterView(abuf, ed.buf.line_count, view_lines, start, frame_view_offset);
|
LineCounterView(ed.buf.line_count, view_lines, start, frame_view_offset);
|
||||||
EditorTextView(editor, p, abuf, view_lines, start, frame_view_offset);
|
EditorTextView(editor, p, view_lines, start, frame_view_offset);
|
||||||
|
|
||||||
for(UIInput* i = ctx.events.first; !CheckNil(g_UI_NIL_INPUT, i) && g_ed_ctx.focused_editor == p.ed; i = i.next)
|
for(UIInput* i = ctx.events.first; !CheckNil(g_UI_NIL_INPUT, i) && g_ed_ctx.focused_editor == p.ed; i = i.next)
|
||||||
{
|
{
|
||||||
@ -225,8 +201,6 @@ EditorView(Panel* p)
|
|||||||
|
|
||||||
ed.cursor_pos = VecPos(&ed.buf);
|
ed.cursor_pos = VecPos(&ed.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetBuffer(&ed.buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -234,64 +208,348 @@ CommandPalette(CmdPalette* cmd)
|
|||||||
{
|
{
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
Vec2 ext = GetExtent();
|
Vec2 ext = GetExtent();
|
||||||
FontAtlasBuf* abuf = &g_ui_ctx.glyph_sets[0].abuf;
|
|
||||||
|
|
||||||
f32 w = ext.x*0.4;
|
f32 w = ext.x*0.4;
|
||||||
f32 h = ext.y*0.7;
|
f32 h = ext.y*0.7;
|
||||||
|
|
||||||
enum UIPushInfo[] cmd_params = [
|
PushFixedPos(Vec2(ext.x*0.3, ext.y*0.1), true);
|
||||||
{ "layout_axis", q{ A2D.Y } },
|
PushBgCol(BG_COL, true);
|
||||||
{ "fixed_pos", q{ Vec2(ext.x*0.3, ext.y*0.1) } },
|
PushBorderCol(HL_BORDER_COL, true);
|
||||||
{ "bg_col", q{ BG_COL } },
|
PushBorderThickness(2.0f, true);
|
||||||
{ "border_col", q{ HL_BORDER_COL } },
|
PushCornerRadius(8.0f, true);
|
||||||
{ "border_thickness", q{ 4.0 } },
|
PushViewOffset(Vec2(-2.0f), true);
|
||||||
{ "corner_radius", q{ Vec4(8.0) } },
|
PushLayoutAxis(A2D.Y, true);
|
||||||
{ "size_info", q{ UIS2(ST.Pixels, ST.Pixels, w, h) } },
|
PushSizeInfo(MakeUISize(UISize(ST.Pixels, w), UISize(ST.Pixels, h)));
|
||||||
];
|
|
||||||
|
|
||||||
mixin(PushOnce!(cmd_params));
|
|
||||||
UIItem* cmd_item = MakeItem("###cmd_palette", UIF.Window|UIF.FixedPosition|UIF.DrawBackground|UIF.DrawBorder);
|
UIItem* cmd_item = MakeItem("###cmd_palette", UIF.Window|UIF.FixedPosition|UIF.DrawBackground|UIF.DrawBorder);
|
||||||
|
|
||||||
f32 padding_y = 4.0;
|
f32 padding_y = 8.0;
|
||||||
|
PushParent(cmd_item);
|
||||||
|
PushPadding(Vec2(4.0, padding_y), true);
|
||||||
|
scope(exit) Pop!("parent", "padding")();
|
||||||
|
|
||||||
mixin(PushScope!("parent", q{ cmd_item } ));
|
PushBgCol(HL_BG_COL, true);
|
||||||
mixin(PushScope!("padding", q{ Vec2(4.0, padding_y) }));
|
PushBorderCol(HL_BORDER_COL);
|
||||||
|
PushBorderThickness(2.0f, true);
|
||||||
enum UIPushInfo[] cmd_input_params = [
|
PushCornerRadius(Vec4(8.0, 8.0, 0.0, 0.0), true);
|
||||||
{ "bg_col", q{ HL_BG_COL } },
|
PushSizeInfo(MakeUISize(UISize(ST.Pixels, w-padding_y), UISize(ST.TextSize, 1.0)), true);
|
||||||
{ "size_info", q{ UISY(ST.TextSize) } },
|
PushDisplayString(ConvToStr(cmd.buffer[0 .. cmd.icount]), true);
|
||||||
{ "display_string", q{ ConvToStr(cmd.buffer[0 .. cmd.icount]) } },
|
|
||||||
];
|
|
||||||
|
|
||||||
mixin(PushOnce!(cmd_input_params));
|
|
||||||
|
|
||||||
UIKey zero = ZeroKey();
|
UIKey zero = ZeroKey();
|
||||||
|
|
||||||
MakeItem(zero, UIF.DrawBorder|UIF.DrawBackground|UIF.DrawText|UIF.Overflow);
|
MakeItem(zero, UIF.DrawBorder|UIF.DrawBackground|UIF.DrawText|UIF.Overflow);
|
||||||
|
|
||||||
enum UIPushInfo[] sep_params = [
|
PushPadding(Vec2(4.0));
|
||||||
{ "padding", q{ Vec2(0.0) } },
|
PushSizeInfoY(ST.TextSize, 1.0);
|
||||||
{ "size_info", q{ UISY(ST.Pixels, 4.0) } },
|
scope(exit) Pop!("size_info", "padding")();
|
||||||
{ "bg_col", q{ HL_BORDER_COL } },
|
|
||||||
];
|
|
||||||
|
|
||||||
mixin(PushOnce!(sep_params));
|
|
||||||
MakeItem(zero, UIF.DrawBackground);
|
|
||||||
|
|
||||||
mixin(PushScope!("padding", q{ Vec2(4.0) } ));
|
|
||||||
mixin(PushScope!("size_info", q{ UISY(ST.TextSize) } ));
|
|
||||||
|
|
||||||
u64 max_opts = cast(u64)ceil(h/abuf.atlas.line_height);
|
|
||||||
|
|
||||||
Vec4[2] opt_cols = [
|
Vec4[2] opt_cols = [
|
||||||
Vec4(0.22, 0.22, 0.22, 1.0),
|
Vec4(0.22, 0.22, 0.22, 1.0),
|
||||||
Vec4(0.35, 0.35, 0.35, 1.0),
|
Vec4(0.35, 0.35, 0.35, 1.0),
|
||||||
];
|
];
|
||||||
|
|
||||||
for(u64 i = 0; i < cmd.opt_strs.length && i < max_opts; i += 1)
|
foreach(i; 0 .. cmd.opt_strs.length)
|
||||||
{
|
{
|
||||||
PushDisplayString(ConvToStr(cmd.opt_strs[i]), true);
|
PushDisplayString(ConvToStr(cmd.opt_strs[i]), true);
|
||||||
PushBgCol(cmd.selected == i ? HL_BG_COL : opt_cols[i%2], true);
|
PushBgCol(cmd.selected == i ? HL_BG_COL : opt_cols[i%2], true);
|
||||||
MakeItem(zero, UIF.DrawBackground|UIF.DrawText);
|
MakeItem(zero, UIF.DrawBackground|UIF.DrawText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//PushDisplayString(ConvToStr(cmd.buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void
|
||||||
|
Panel(UIPanel* panel)
|
||||||
|
{
|
||||||
|
UICtx* ctx = GetCtx();
|
||||||
|
UIItem* item = Get(panel.id);
|
||||||
|
Editor* ed = panel.ed;
|
||||||
|
bool focused = GetFocusedPanel() == panel;
|
||||||
|
|
||||||
|
UIPanel* parent = panel.parent;
|
||||||
|
UIPanel* prev = panel.prev;
|
||||||
|
|
||||||
|
Axis2D pax = parent.axis;
|
||||||
|
|
||||||
|
Vec2 adj = Vec2(
|
||||||
|
parent.axis == A2D.X ? 10 : 0,
|
||||||
|
parent.axis == A2D.Y ? 10 : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
Vec2 p0 = panel.rect.p0+adj;
|
||||||
|
Vec2 p1 = panel.rect.p1-adj;
|
||||||
|
Rect r = Rect(p0: p0, p1: p1);
|
||||||
|
|
||||||
|
if(!Nil(prev)) with(panel)
|
||||||
|
{
|
||||||
|
Vec2 d0 = rect.p0-adj;
|
||||||
|
Vec2 d1 = Vec2(
|
||||||
|
pax == A2D.X ? rect.p0.x+adj.x : rect.p1.x,
|
||||||
|
pax == A2D.Y ? rect.p0.y+adj.y : rect.p1.y
|
||||||
|
);
|
||||||
|
|
||||||
|
Rect dr = Rect(p0: d0, p1: d1);
|
||||||
|
if(Dragged(item, &dr) && item.dragged.v[pax] != 0.0)
|
||||||
|
{
|
||||||
|
f32 mov_pct = Remap(item.dragged.v[pax], 0.0, panel.parent.size.v[pax], 0.0, 1.0);
|
||||||
|
if(CheckPanelBounds(pct + mov_pct) && CheckPanelBounds(panel.prev.pct - mov_pct))
|
||||||
|
{
|
||||||
|
pct += mov_pct;
|
||||||
|
panel.prev.pct -= mov_pct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(panel.ed != null)
|
||||||
|
{
|
||||||
|
if(Clicked(item, &r))
|
||||||
|
{
|
||||||
|
SetFocusedPanel(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 inner = InnerSize(panel);
|
||||||
|
|
||||||
|
SetScrollOffset(panel);
|
||||||
|
|
||||||
|
panel.start_ln = cast(u64)(floor(panel.scroll_offset/TEXT_SIZE));
|
||||||
|
panel.end_ln = panel.start_ln + cast(u64)(ceil(inner.y/TEXT_SIZE));
|
||||||
|
panel.vis_lines = panel.end_ln - panel.start_ln;
|
||||||
|
|
||||||
|
char[64] ch_buf = '\0';
|
||||||
|
char[] fmt = ch_buf.sformat("%%0%ss", u64(panel.end_ln.toChars().length));
|
||||||
|
|
||||||
|
f32 lc_w = panel.end_ln.toChars().length*ctx.char_width + LINE_COUNT_PADDING*2.0;
|
||||||
|
f32 code_view_width = inner.x-lc_w;
|
||||||
|
|
||||||
|
StartLineBuffer(&panel.ed.buf, code_view_width);
|
||||||
|
|
||||||
|
U64Vec2 pos = VecPos(&ed.buf);
|
||||||
|
|
||||||
|
DrawPanel(panel, lc_w, focused);
|
||||||
|
|
||||||
|
f32 y_rem = fmod(panel.scroll_offset, TEXT_SIZE);
|
||||||
|
|
||||||
|
f32 x = panel.rect.p0.x;
|
||||||
|
f32 y = panel.rect.p1.y + TEXT_SIZE - fmod(panel.scroll_offset, TEXT_SIZE);
|
||||||
|
|
||||||
|
u64 i = panel.start_ln;
|
||||||
|
for(auto buf = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, buf) && i < panel.end_ln; i += 1, buf = GetLine(&ed.buf, i))
|
||||||
|
{
|
||||||
|
f32 x_pos = x + LINE_COUNT_PADDING;
|
||||||
|
DrawLineCount(fmt, &x_pos, y, i);
|
||||||
|
|
||||||
|
u64 ch_offset;
|
||||||
|
|
||||||
|
auto parts = MakeMultiline(buf.text, code_view_width, buf.style);
|
||||||
|
if(parts == null)
|
||||||
|
{
|
||||||
|
if(pos.y == i)
|
||||||
|
{
|
||||||
|
DrawCursor([], 0, x+lc_w, y, ch_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else for(auto n = parts; n != null; n = n.next)
|
||||||
|
{
|
||||||
|
auto l = n;
|
||||||
|
|
||||||
|
if(pos.y == i)
|
||||||
|
{
|
||||||
|
DrawCursor(l.text, pos.x, x+lc_w, y, ch_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(j; 0 .. l.text.length)
|
||||||
|
{
|
||||||
|
bool hl = pos.y == i && !EditModeActive() && j == pos.x-ch_offset;
|
||||||
|
DrawChar(l.text[j], &x_pos, y, hl ? Vec4(Vec3(0.0), 1.0) : SYNTAX_COLORS[l.style[j]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
y += TEXT_SIZE;
|
||||||
|
x_pos = x + lc_w + LINE_COUNT_PADDING*2.0;
|
||||||
|
ch_offset += l.text.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CommandPalette(CmdPalette* cmd)
|
||||||
|
{
|
||||||
|
UICtx* ctx = GetCtx();
|
||||||
|
|
||||||
|
u8[] text = cmd.buffer[0 .. cmd.icount];
|
||||||
|
u8[][] options = cmd.opt_strs;
|
||||||
|
|
||||||
|
Vec2 size = RootSize();
|
||||||
|
|
||||||
|
f32 x = size.x*0.15;
|
||||||
|
f32 y = size.y*0.1;
|
||||||
|
f32 w = size.x*0.7;
|
||||||
|
f32 h = 40.0;
|
||||||
|
|
||||||
|
DrawCmdRect(Vec2(x, y), Vec2(w, h), false);
|
||||||
|
|
||||||
|
f32 y_off = h*0.5 + 6;
|
||||||
|
f32 ch_x = x + 6.0;
|
||||||
|
f32 ch_y = y + y_off;
|
||||||
|
|
||||||
|
foreach(i; 0 .. text.length)
|
||||||
|
{
|
||||||
|
DrawChar(text[i], &ch_x, ch_y, Vec4(1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(u64 i = 0; i < options.length; i += 1)
|
||||||
|
{
|
||||||
|
y += h;
|
||||||
|
ch_x = x + 6.0;
|
||||||
|
ch_y = y + y_off;
|
||||||
|
|
||||||
|
DrawCmdRect(Vec2(x, y), Vec2(w, h), cmd.selected == i);
|
||||||
|
|
||||||
|
foreach(j; 0 .. options[i].length)
|
||||||
|
{
|
||||||
|
DrawChar(options[i][j], &ch_x, ch_y, Vec4(1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(y+h > size.y+h) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CheckPanelBounds(f32 pct)
|
||||||
|
{
|
||||||
|
return pct >= 0.0 && pct <= 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PushPanel(UIPanel* parent, UIPanel* panel)
|
||||||
|
{
|
||||||
|
DLLPush(parent, panel, g_UI_NIL_PANEL);
|
||||||
|
panel.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InsertPanel(UIPanel* parent, UIPanel* prev, UIPanel* panel)
|
||||||
|
{
|
||||||
|
DLLInsert(parent, panel, prev, g_UI_NIL_PANEL);
|
||||||
|
panel.parent = prev.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetFocusedPanel(UIPanel* panel)
|
||||||
|
{
|
||||||
|
if(!CheckNil(g_UI_NIL_PANEL, panel))
|
||||||
|
{
|
||||||
|
g_ui_ctx.focused_panel = panel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UIPanel*
|
||||||
|
GetFocusedPanel()
|
||||||
|
{
|
||||||
|
return Nil(g_ui_ctx.focused_panel) ? g_UI_NIL_PANEL : g_ui_ctx.focused_panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBuffer*
|
||||||
|
MakeMultiline(u8[] text, f32 width, TS[] style = [])
|
||||||
|
{
|
||||||
|
f32 scaled_width = width * (g_ui_ctx.atlas_buf.atlas.size/g_ui_ctx.text_size);
|
||||||
|
f32 text_width = CalcTextWidth(text);
|
||||||
|
|
||||||
|
u64 line_count = cast(u64)(ceil(text_width/scaled_width));
|
||||||
|
TextBuffer* node = null;
|
||||||
|
if(line_count > 0)
|
||||||
|
{
|
||||||
|
f32 w = 0.0;
|
||||||
|
u64 line = 0;
|
||||||
|
u64 start = 0;
|
||||||
|
const u64 extra_buf = 20;
|
||||||
|
for(u64 i = 0; i < text.length; i += 1)
|
||||||
|
{
|
||||||
|
f32 ch_w = GlyphWidth(g_ui_ctx.atlas_buf.atlas.glyphs.ptr + text[i]);
|
||||||
|
|
||||||
|
if(ch_w + w > scaled_width || i == text.length-1)
|
||||||
|
{
|
||||||
|
u64 len = i-start+1;
|
||||||
|
|
||||||
|
u8[] str = ScratchAlloc!(u8)(text, start, len);
|
||||||
|
|
||||||
|
TS[] stl = [];
|
||||||
|
if(style.length > 0)
|
||||||
|
{
|
||||||
|
stl = ScratchAlloc!(TS)(style, start, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBuffer* n = node;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(node == null)
|
||||||
|
{
|
||||||
|
node = ScratchAlloc!(TextBuffer)();
|
||||||
|
|
||||||
|
node.text = str;
|
||||||
|
node.style = stl;
|
||||||
|
node.next = null;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(n.next == null)
|
||||||
|
{
|
||||||
|
n.next = ScratchAlloc!(TextBuffer)();
|
||||||
|
|
||||||
|
n.next.text = str;
|
||||||
|
n.next.style = stl;
|
||||||
|
n.next.next = null;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = n.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
line += 1;
|
||||||
|
start = i;
|
||||||
|
w = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
w += ch_w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline) void
|
||||||
|
DrawCursor(u8[] text, u64 ch_x, f32 x, f32 y, u64 offset)
|
||||||
|
{
|
||||||
|
Glyph* g = GetGlyph(' ');
|
||||||
|
foreach(j; 0 .. text.length)
|
||||||
|
{
|
||||||
|
bool hl = j == ch_x-offset;
|
||||||
|
if(hl)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g = j == text.length-1 ? GetGlyph(' ') : GetGlyph(text[j]);
|
||||||
|
x += GlyphWidth(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawRect(x, y, cast(u8)g.ch, Vec4(1.0), EditModeActive());
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline) void
|
||||||
|
DrawLineCount(char[] fmt, f32* x_pos, f32 y, u64 line)
|
||||||
|
{
|
||||||
|
char[32] line_buf = '\0';
|
||||||
|
char[] line_str = sformat(line_buf, fmt, line+1);
|
||||||
|
|
||||||
|
foreach(j; 0 .. line_str.length)
|
||||||
|
{
|
||||||
|
DrawChar(line_str[j], x_pos, y, Vec4(1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
*x_pos += LINE_COUNT_PADDING;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@ -5,14 +5,9 @@
|
|||||||
|
|
||||||
#include "gui.layout"
|
#include "gui.layout"
|
||||||
|
|
||||||
layout (location = 0) flat in struct FragDataFlatIn
|
layout (location = 0) flat in uint in_has_texture;
|
||||||
{
|
|
||||||
uint texture;
|
|
||||||
uint atlas_index;
|
|
||||||
} FDF;
|
|
||||||
|
|
||||||
layout (location = 2) in struct FragDataIn
|
layout (location = 1) in struct FragDataIn {
|
||||||
{
|
|
||||||
vec4 color;
|
vec4 color;
|
||||||
vec2 uv;
|
vec2 uv;
|
||||||
vec2 dst_pos;
|
vec2 dst_pos;
|
||||||
@ -25,6 +20,7 @@ layout (location = 2) in struct FragDataIn
|
|||||||
float border_thickness;
|
float border_thickness;
|
||||||
} FD;
|
} FD;
|
||||||
|
|
||||||
|
|
||||||
layout (location = 0) out vec4 FragColor;
|
layout (location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
float RectSDF(vec2 pos, vec2 half_size, float radius)
|
float RectSDF(vec2 pos, vec2 half_size, float radius)
|
||||||
@ -79,7 +75,7 @@ void main()
|
|||||||
vec4 gamma = vec4(1.0/1.4);
|
vec4 gamma = vec4(1.0/1.4);
|
||||||
|
|
||||||
vec4 tex_color = vec4(1.0);
|
vec4 tex_color = vec4(1.0);
|
||||||
if(FDF.texture != 0)
|
if(in_has_texture != 0)
|
||||||
{
|
{
|
||||||
tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FD.uv);
|
tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FD.uv);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
layout (rgba16f, set = 0, binding = 0) uniform image2D DrawImage;
|
layout (rgba16f, set = 0, binding = 0) uniform image2D DrawImage;
|
||||||
|
|
||||||
layout (set = 1, binding = 0) uniform texture2D SpriteAtlasArray[24];
|
layout (set = 1, binding = 0) uniform texture2D SpriteAtlas;
|
||||||
|
|
||||||
layout (set = 1, binding = 1) uniform sampler SamplerNearest;
|
layout (set = 1, binding = 1) uniform sampler SamplerNearest;
|
||||||
|
|
||||||
layout (push_constant) uniform Constants {
|
layout (push_constant) uniform Constants {
|
||||||
mat4 projection;
|
mat4 projection;
|
||||||
} PC;
|
} PC;
|
||||||
|
|
||||||
#define SpriteAtlas SpriteAtlasArray[FDF.atlas_index]
|
|
||||||
|
|||||||
@ -17,16 +17,10 @@ layout (location = 9) in float border_thickness;
|
|||||||
layout (location = 10) in float edge_softness;
|
layout (location = 10) in float edge_softness;
|
||||||
layout (location = 11) in float raised;
|
layout (location = 11) in float raised;
|
||||||
layout (location = 12) in uint in_has_texture;
|
layout (location = 12) in uint in_has_texture;
|
||||||
layout (location = 13) in uint in_atlas_index;
|
|
||||||
|
|
||||||
layout (location = 0) flat out struct FragDataFlatOut
|
layout (location = 0) flat out uint out_has_texture;
|
||||||
{
|
|
||||||
uint texture;
|
|
||||||
uint atlas_index;
|
|
||||||
} FDF;
|
|
||||||
|
|
||||||
layout (location = 2) out struct FragDataOut
|
layout (location = 1) out struct FragDataOut {
|
||||||
{
|
|
||||||
vec4 color;
|
vec4 color;
|
||||||
vec2 uv;
|
vec2 uv;
|
||||||
vec2 dst_pos;
|
vec2 dst_pos;
|
||||||
@ -37,7 +31,7 @@ layout (location = 2) out struct FragDataOut
|
|||||||
float softness;
|
float softness;
|
||||||
float raised;
|
float raised;
|
||||||
float border_thickness;
|
float border_thickness;
|
||||||
} FD;
|
} FragData;
|
||||||
|
|
||||||
vec2 Vertices[4] = vec2[4](
|
vec2 Vertices[4] = vec2[4](
|
||||||
vec2(-1.0, -1.0),
|
vec2(-1.0, -1.0),
|
||||||
@ -83,18 +77,17 @@ void main()
|
|||||||
vec2 dst_verts_pct = vec2(bool(gl_VertexIndex >> 1) ? 1.0f : 0.0f,
|
vec2 dst_verts_pct = vec2(bool(gl_VertexIndex >> 1) ? 1.0f : 0.0f,
|
||||||
bool(gl_VertexIndex & 1) ? 0.0f : 1.0f);
|
bool(gl_VertexIndex & 1) ? 0.0f : 1.0f);
|
||||||
|
|
||||||
FD.color = in_col;
|
FragData.color = in_col;
|
||||||
FD.uv = uvs[gl_VertexIndex] / tex_size;
|
FragData.uv = uvs[gl_VertexIndex] / tex_size;
|
||||||
FD.dst_pos = pos;
|
FragData.dst_pos = pos;
|
||||||
FD.dst_center = center;
|
FragData.dst_center = center;
|
||||||
FD.dst_half_size = half_size;
|
FragData.dst_half_size = half_size;
|
||||||
FD.corner_radius = corner_radius[gl_VertexIndex];
|
FragData.corner_radius = corner_radius[gl_VertexIndex];
|
||||||
FD.softness = edge_softness;
|
FragData.softness = edge_softness;
|
||||||
FD.raised = raised;
|
FragData.raised = raised;
|
||||||
FD.border_thickness = border_thickness;
|
FragData.border_thickness = border_thickness;
|
||||||
FD.sdf_sample_pos = (2.0f * dst_verts_pct - 1.0f) * half_size;
|
FragData.sdf_sample_pos = (2.0f * dst_verts_pct - 1.0f) * half_size;
|
||||||
FDF.texture = in_has_texture;
|
out_has_texture = in_has_texture;
|
||||||
FDF.atlas_index = in_atlas_index;
|
|
||||||
|
|
||||||
vec4 v_pos = PC.projection * vec4(pos.x, pos.y, 0, 1);
|
vec4 v_pos = PC.projection * vec4(pos.x, pos.y, 0, 1);
|
||||||
gl_Position = vec4(v_pos.x, v_pos.y, v_pos.z, 1);
|
gl_Position = vec4(v_pos.x, v_pos.y, v_pos.z, 1);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user