many fices
This commit is contained in:
parent
94e64fef9e
commit
2edc6777f9
Binary file not shown.
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-Bold.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-Bold.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-BoldItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-ExtraBold.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-ExtraBold.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-ExtraBoldItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-ExtraBoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-ExtraLight.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-ExtraLight.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-ExtraLightItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-ExtraLightItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-Italic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-Italic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-Light.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-Light.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-LightItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-LightItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-Medium.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-Medium.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-MediumItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-MediumItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-Regular.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-Regular.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-SemiBold.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-SemiBold.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-SemiBoldItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-SemiBoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-Thin.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-Thin.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMono-ThinItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMono-ThinItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Bold.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Bold.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-BoldItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ExtraBold.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ExtraBold.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ExtraBoldItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ExtraBoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ExtraLight.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ExtraLight.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ExtraLightItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ExtraLightItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Italic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Italic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Light.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Light.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-LightItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-LightItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Medium.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Medium.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-MediumItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-MediumItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Regular.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Regular.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-SemiBold.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-SemiBold.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-SemiBoldItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-SemiBoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Thin.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-Thin.ttf
Normal file
Binary file not shown.
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ThinItalic.ttf
Normal file
BIN
assets/jetbrains-mono/JetBrainsMonoNL-ThinItalic.ttf
Normal file
Binary file not shown.
@ -1 +1 @@
|
|||||||
Subproject commit 11cf96b799c6ccee3c4f569e89c263d11c4d5ff8
|
Subproject commit c2b7544979b16e1f27f419475b866a2903bd9c0a
|
||||||
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit bda9abf8b9c74844cb30edb32e81543cbd5ae89d
|
Subproject commit c637de10ffd949a07e51d6a792a6c4f49ac33ac5
|
||||||
@ -1,4 +1,5 @@
|
|||||||
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;
|
||||||
@ -476,6 +477,12 @@ 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,10 +61,7 @@ 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
|
||||||
@ -155,48 +152,6 @@ 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();
|
||||||
}
|
}
|
||||||
@ -266,6 +221,7 @@ 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,18 +37,20 @@ 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");
|
||||||
const u8[] VERTEX_BYTES = import("gui.vert.spv");
|
u8[] FONT_BYTES = cast(u8[])import("jetbrains-mono/JetBrainsMono-Regular.ttf");
|
||||||
const u8[] FRAGMENT_BYTES = import("gui.frag.spv");
|
u8[] VERTEX_BYTES = cast(u8[])import("gui.vert.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;
|
||||||
@ -62,7 +64,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);
|
||||||
f32 g_text_scale_default = 1.0;
|
u32 g_text_size_default = 18;
|
||||||
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);
|
||||||
@ -131,6 +133,7 @@ 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
|
||||||
{
|
{
|
||||||
@ -233,7 +236,8 @@ struct UICtx
|
|||||||
|
|
||||||
PlatformWindow* window;
|
PlatformWindow* window;
|
||||||
Renderer rd;
|
Renderer rd;
|
||||||
Descriptor font_atlas;
|
Descriptor[FONT_SIZES] font_descs;
|
||||||
|
Descriptor default_tex;
|
||||||
Descriptor sampler;
|
Descriptor sampler;
|
||||||
Pipeline pipeline;
|
Pipeline pipeline;
|
||||||
DescSetLayout desc_set_layout;
|
DescSetLayout desc_set_layout;
|
||||||
@ -242,16 +246,13 @@ struct UICtx
|
|||||||
Mat4 projection;
|
Mat4 projection;
|
||||||
Vec2 res;
|
Vec2 res;
|
||||||
|
|
||||||
u8[] font_data;
|
|
||||||
FontFace font;
|
FontFace font;
|
||||||
FontAtlasBuf atlas_buf;
|
FontGlyphs[FONT_SIZES] glyph_sets;
|
||||||
f32 char_width;
|
u32 glyph_sets_used;
|
||||||
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;
|
||||||
@ -278,10 +279,18 @@ 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!(f32, "text_scale");
|
mixin UICtxParameter!(u32, "text_size");
|
||||||
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)
|
||||||
@ -337,6 +346,7 @@ 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;
|
||||||
@ -412,6 +422,7 @@ struct Vertex
|
|||||||
f32 edge_softness;
|
f32 edge_softness;
|
||||||
f32 raised;
|
f32 raised;
|
||||||
u32 texture;
|
u32 texture;
|
||||||
|
u32 atlas_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
union Rect
|
union Rect
|
||||||
@ -462,26 +473,23 @@ InitUICtx(PlatformWindow* window)
|
|||||||
|
|
||||||
UIBuffer[FRAME_OVERLAP] buffers;
|
UIBuffer[FRAME_OVERLAP] buffers;
|
||||||
|
|
||||||
UICtx ctx = {
|
UICtx* ctx = &g_ui_ctx;
|
||||||
items: CreateHashTable!(UIHash, UIItem*)(12),
|
|
||||||
free_items: Alloc!(UIItem)(&arena),
|
ctx.items = CreateHashTable!(UIHash, UIItem*)(12);
|
||||||
arena: arena,
|
ctx.free_items = Alloc!(UIItem)(&arena);
|
||||||
temp_arena: CreateArena(MB(1)),
|
ctx.arena = arena;
|
||||||
drag_item: g_UI_NIL,
|
ctx.temp_arena = CreateArena(MB(1));
|
||||||
transient_items: g_UI_NIL,
|
ctx.drag_item = g_UI_NIL;
|
||||||
font: OpenFont(cast(u8[])FONT_BYTES),
|
ctx.transient_items = g_UI_NIL;
|
||||||
font_data: cast(u8[])FONT_BYTES,
|
ctx.font = OpenFont(cast(u8[])FONT_BYTES);
|
||||||
text_size: 16.0,
|
ctx.tab_width = 2;
|
||||||
tab_width: 2,
|
ctx.syntax_colors = [DEFAULT_COLORS, SYNTAX_COLORS];
|
||||||
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));
|
||||||
@ -496,7 +504,7 @@ InitUICtx(PlatformWindow* window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DescLayoutBinding[2] layout_bindings = [
|
DescLayoutBinding[2] layout_bindings = [
|
||||||
{ binding: 0, descriptorType: DT.Image, descriptorCount: 1, stageFlags: SS.All },
|
{ binding: 0, descriptorType: DT.Image, descriptorCount: FONT_SIZES, stageFlags: SS.All },
|
||||||
{ binding: 1, descriptorType: DT.Sampler, descriptorCount: 1, stageFlags: SS.All },
|
{ binding: 1, descriptorType: DT.Sampler, descriptorCount: 1, stageFlags: SS.All },
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -504,7 +512,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[13] attributes = [
|
Attribute[] 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 },
|
||||||
@ -518,6 +526,7 @@ 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 = {
|
||||||
@ -535,16 +544,69 @@ 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);
|
||||||
|
}
|
||||||
|
|
||||||
g_ui_ctx = ctx;
|
FontAtlasBuf*
|
||||||
|
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
|
||||||
@ -626,75 +688,41 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
item.max_text_width = 0.0;
|
FontAtlasBuf* abuf = GetFontAtlas(item.text_size);
|
||||||
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;
|
||||||
f32 text_width = CalcTextWidth(str);
|
u32 ch_per_line = cast(u32)floor(width/abuf.atlas.max_advance);
|
||||||
|
u64 lines = (str.length/ch_per_line) + (str.length%ch_per_line ? 1 : 0);
|
||||||
|
|
||||||
if(text_width < width || width == 0.0) goto InitSingleLine;
|
u32 max_chars = str.length > ch_per_line ? ch_per_line : cast(u32)str.length;
|
||||||
|
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);
|
||||||
|
|
||||||
assert(!item.syntax_tokens.length || item.syntax_tokens.length == str.length);
|
u64 start;
|
||||||
|
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)
|
||||||
|
|
||||||
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;
|
u64 end = str.length-start <= ch_per_line ? str.length : start+ch_per_line;
|
||||||
|
item.token_lines[i] = item.syntax_tokens[start .. end];
|
||||||
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)
|
||||||
{
|
{
|
||||||
@ -816,6 +844,8 @@ 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
|
||||||
@ -885,19 +915,20 @@ BeginUI(Inputs* inputs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(UIItem* item = ctx.transient_items; !Nil(item); item = item.transient_next)
|
for(UIItem* item = ctx.transient_items; !Nil(item);)
|
||||||
{
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
@ -992,7 +1023,7 @@ EndUI()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
item.size.v[axis] = item.padding.y*2.0 + TEXT_SIZE*item.text_lines.length;
|
item.size.v[axis] = item.padding.y*2.0 + GetFontAtlas(item.text_size).atlas.line_height*item.text_lines.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1074,10 +1105,7 @@ EndUI()
|
|||||||
excess -= reduced;
|
excess -= reduced;
|
||||||
c.size.v[axis] -= reduced;
|
c.size.v[axis] -= reduced;
|
||||||
|
|
||||||
if(excess <= 0.0009)
|
if(excess <= 0.0009) break;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(excess > 0.0009)
|
if(excess > 0.0009)
|
||||||
@ -1093,10 +1121,7 @@ EndUI()
|
|||||||
excess -= reduced;
|
excess -= reduced;
|
||||||
c.size.v[axis] -= reduced;
|
c.size.v[axis] -= reduced;
|
||||||
|
|
||||||
if(excess < 0.0009)
|
if(excess < 0.0009) break;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1118,72 +1143,42 @@ EndUI()
|
|||||||
// Calculate final sizes
|
// Calculate final sizes
|
||||||
{
|
{
|
||||||
f32 pos = 0.0;
|
f32 pos = 0.0;
|
||||||
for(UIItem* item = ctx.root; !Nil(item);)
|
for(UIItem* item = ctx.root; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||||
{
|
{
|
||||||
|
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] = item.fixed_pos.v[axis] + item.parent.rect.p0.v[axis];
|
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.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis];
|
item.rect.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis] - item.padding.v[axis];
|
||||||
|
}
|
||||||
next_pos = pos;
|
else if(Nil(item.parent.last_relative_item))
|
||||||
|
{
|
||||||
|
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
|
||||||
{
|
{
|
||||||
item.rect.p0.v[axis] = pos + item.pos_offset.v[axis];
|
UIItem* prev = parent.last_relative_item;
|
||||||
item.rect.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis];
|
|
||||||
|
|
||||||
next_pos = item.parent.layout_axis == axis ? item.rect.p1.v[axis] : item.rect.p0.v[axis];
|
item.rect.p0.v[axis] = prev.rect.p1.v[axis] + prev.padding.v[axis] + item.padding.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1237,6 +1232,10 @@ 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);
|
||||||
@ -1245,18 +1244,18 @@ RenderItem(UICtx* ctx, UIItem* item)
|
|||||||
{
|
{
|
||||||
DrawUI(ctx);
|
DrawUI(ctx);
|
||||||
|
|
||||||
u32 x = cast(u32)(scissor_x ? floor(item.rect.p0.x) : 0);
|
u32 x = cast(u32)(scissor_x ? floor(p0.x) : 0);
|
||||||
u32 y = cast(u32)(scissor_y ? floor(item.rect.p0.y) : 0);
|
u32 y = cast(u32)(scissor_y ? floor(p0.y) : 0);
|
||||||
u32 w = cast(u32)(scissor_x ? floor(item.rect.p1.x) - x : ctx.res.x);
|
u32 w = cast(u32)(scissor_x ? floor(p1.x) - x : ctx.res.x);
|
||||||
u32 h = cast(u32)(scissor_y ? floor(item.rect.p1.y) - y : ctx.res.y);
|
u32 h = cast(u32)(scissor_y ? floor(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 = item.rect.p0 + item.border_thickness;
|
v.dst_start = p0 + item.border_thickness;
|
||||||
v.dst_end = item.rect.p1 - item.border_thickness;
|
v.dst_end = 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);
|
||||||
@ -1267,8 +1266,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 = item.rect.p0;
|
v.dst_start = p0;
|
||||||
v.dst_end = item.rect.p1;
|
v.dst_end = 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);
|
||||||
@ -1286,27 +1285,25 @@ RenderItem(UICtx* ctx, UIItem* item)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The math around all this is fucked
|
FontGlyphs* fg = GetFontGlyphs(item.text_size);
|
||||||
FontAtlas* atl = &ctx.atlas_buf.atlas;
|
f32 y_pos = p0.y + fg.abuf.atlas.line_height;
|
||||||
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 ? item.rect.p1.x - item.padding.x - CalcTextWidth(str) :
|
f32 x_pos = item.flags & UIF.RightAlignText ? p1.x - item.padding.x - CalcTextWidth(str, &fg.abuf) : p0.x + item.padding.x;
|
||||||
item.rect.p0.x + item.padding.x;
|
|
||||||
|
|
||||||
x_pos = clamp(x_pos, item.rect.p0.x, item.rect.p1.x);
|
x_pos = clamp(x_pos, p0.x, 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 < atl.glyphs.length ? atl.glyphs.ptr + ch : null;
|
Glyph* g = ch < fg.abuf.atlas.glyphs.length ? fg.abuf.atlas.glyphs.ptr + ch : null;
|
||||||
DrawGlyph(item, g, &x_pos, y_pos, syntax_cols[tks[j]]);
|
DrawGlyph(item, g, fg.index, &x_pos, y_pos, syntax_cols[tks[j]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1314,12 +1311,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 < atl.glyphs.length ? atl.glyphs.ptr + ch : null;
|
Glyph* g = ch < fg.abuf.atlas.glyphs.length ? fg.abuf.atlas.glyphs.ptr + ch : null;
|
||||||
DrawGlyph(item, g, &x_pos, y_pos, item.text_col);
|
DrawGlyph(item, g, fg.index, &x_pos, y_pos, item.text_col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y_pos += TEXT_SIZE;
|
y_pos += fg.abuf.atlas.line_height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1376,6 +1373,17 @@ 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)
|
||||||
{
|
{
|
||||||
@ -1463,24 +1471,52 @@ 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!(T)* node = stack.free;
|
Stack!(ST)* node = stack.free;
|
||||||
if(node)
|
if(node)
|
||||||
{
|
{
|
||||||
stack.free = node.next;
|
stack.free = node.next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node = Alloc!(Stack!(T))(&g_ui_ctx.temp_arena);
|
node = Alloc!(Stack!(ST))(&g_ui_ctx.temp_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.next = stack.top;
|
node.next = stack.top;
|
||||||
@ -1762,11 +1798,10 @@ NewItem(UICtx* ctx)
|
|||||||
{
|
{
|
||||||
UIItem* item = g_UI_NIL;
|
UIItem* item = g_UI_NIL;
|
||||||
|
|
||||||
if(!Nil(ctx.free_items.first))
|
debug ctx.item_count += 1;
|
||||||
{
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -1807,6 +1842,7 @@ 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
|
||||||
@ -1823,7 +1859,7 @@ Get(T)(T k) if(is(T: UIKey) || StringType!T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
f32
|
f32
|
||||||
CalcTextWidth(T)(T text) if(is(T == string) || StringType!T)
|
CalcTextWidth(bool fast = true, T, U)(T text, U param) if((is(T == string) || StringType!T) && (is(U: u32) || is(U == FontAtlasBuf*) ))
|
||||||
{
|
{
|
||||||
static if(is(T == string))
|
static if(is(T == string))
|
||||||
{
|
{
|
||||||
@ -1834,42 +1870,63 @@ CalcTextWidth(T)(T text) if(is(T == string) || StringType!T)
|
|||||||
string str = ConvToStr(text);
|
string str = ConvToStr(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 tab_width = g_ui_ctx.tab_width;
|
static if(is(U: u32))
|
||||||
Glyph* space = g_ui_ctx.atlas_buf.atlas.glyphs.ptr + ' ';
|
{
|
||||||
|
FontAtlasBuf* abuf = GetFontAtlas(param);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FontAtlasBuf* abuf = param;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 tab_width = g_ui_ctx.tab_width;
|
||||||
|
|
||||||
|
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(g_ui_ctx.atlas_buf.atlas.glyphs.ptr + str.ptr[i]);
|
width += GlyphWidth(abuf.atlas.glyphs.ptr + str.ptr[i], abuf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) f32
|
pragma(inline) f32
|
||||||
GlyphWidth(Glyph* g)
|
GlyphWidth(Glyph* g, FontAtlasBuf* abuf)
|
||||||
{
|
{
|
||||||
return g.ch == '\t' ? (g_ui_ctx.atlas_buf.atlas.glyphs[' '].advance*cast(f32)(g_ui_ctx.tab_width)) : g.advance;
|
return g.ch == '\t' ? (abuf.atlas.glyphs[' '].advance*cast(f32)(g_ui_ctx.tab_width)) : g.advance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
DrawGlyph(UIItem* item, Glyph* glyph, u32 atlas_index, 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 * item.text_scale;
|
f32 advance = glyph.advance;
|
||||||
|
|
||||||
if(glyph.ch == '\t')
|
if(glyph.ch == ' ' || glyph.ch == '\n')
|
||||||
|
{
|
||||||
|
*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 l = glyph.plane_left * item.text_scale;
|
f32 r = glyph.plane_right;
|
||||||
f32 t = glyph.plane_top * item.text_scale;
|
f32 l = glyph.plane_left;
|
||||||
f32 b = glyph.plane_bottom * item.text_scale;
|
f32 t = glyph.plane_top;
|
||||||
|
f32 b = glyph.plane_bottom;
|
||||||
|
|
||||||
GlyphBounds gb = {
|
GlyphBounds gb = {
|
||||||
r: r,
|
r: r,
|
||||||
@ -1886,13 +1943,14 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
|||||||
|
|
||||||
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) + TEXT_SIZE;
|
f32 y_pos = y + gb.t;
|
||||||
|
|
||||||
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')
|
||||||
{
|
{
|
||||||
@ -1910,7 +1968,8 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
|||||||
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)
|
||||||
{
|
{
|
||||||
@ -1918,6 +1977,7 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
|||||||
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)
|
||||||
{
|
{
|
||||||
@ -1931,6 +1991,7 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
|||||||
|
|
||||||
*x_pos += advance;
|
*x_pos += advance;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) Vec2[2]
|
pragma(inline) Vec2[2]
|
||||||
@ -1952,30 +2013,23 @@ GetVertex(UICtx* ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static UISize[2]
|
static UISize[2]
|
||||||
MakeUISize(UISize x, UISize y)
|
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)
|
||||||
{
|
{
|
||||||
return [x, y];
|
return [UISize(t0, v0, s0), UISize(t1, v1, s1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static UISize[2]
|
static UISize[2]
|
||||||
MakeUISizeX(SizeType type, f32 value, f32 strictness = 1.0)
|
UISX(SizeType type, f32 value = 1.0, 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]
|
||||||
MakeUISizeY(SizeType type, f32 value, f32 strictness = 1.0)
|
UISY(SizeType type, f32 value = 1.0, 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,84 +31,105 @@ struct Panel
|
|||||||
Axis2D layout_axis;
|
Axis2D layout_axis;
|
||||||
Editor* ed;
|
Editor* ed;
|
||||||
u64 id;
|
u64 id;
|
||||||
|
u32 text_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LineCounterView(u64 max_line, u64 lines, i64 line_offset, f32 view_offset)
|
LineCounterView(FontAtlasBuf* abuf, 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)*ctx.char_width; // Should figure out how to accurately measure text width
|
f32 lc_width = cast(f32)(ch_width+1)*abuf.atlas.max_advance;
|
||||||
|
|
||||||
PushLayoutAxis(A2D.Y, true);
|
enum UIPushInfo[] lc_params = [
|
||||||
PushViewOffsetY(view_offset, true);
|
{ "layout_axis", q{ A2D.Y } },
|
||||||
PushPaddingX(4.0, true);
|
{ "view_offset", q{ Vec2(0.0, view_offset) } },
|
||||||
PushSizeInfoX(ST.Pixels, lc_width, 1.0, true);
|
{ "padding", q{ Vec2(8.0) } },
|
||||||
|
{ "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);
|
||||||
|
|
||||||
PushTextCol(Vec4(1.0));
|
mixin(PushScope!("text_col", q{ Vec4(1.0) } ));
|
||||||
PushSizeInfoY(ST.Pixels, TEXT_SIZE);
|
mixin(PushScope!("size_info", q{ UISY(ST.Pixels, abuf.atlas.line_height) } ));
|
||||||
PushParent(line_count);
|
mixin(PushScope!("parent", q{ 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(buf, "%s", i)), true);
|
Push!("display_string")(ConvToStr(sformat(ScratchAlloc!(char)(ch_width), "%s", i)), true);
|
||||||
MakeItem(zero, UIF.DrawText);
|
MakeItem(zero, UIF.DrawText);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pop!("text_col", "size_info", "parent");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EditorTextView(UIItem* editor, Panel* p, u64 lines, i64 line_offset, f32 view_offset)
|
EditorTextView(UIItem* editor, Panel* p, FontAtlasBuf* abuf, 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 clamp_y = cast(f32)(ed.buf.line_count-lines)*TEXT_SIZE;
|
f32 text_size = cast(f32)p.text_size;
|
||||||
f32 scroll_pos = cast(f32)(ed.line_offset)*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 padding = 8.0;
|
||||||
|
|
||||||
PushLayoutAxis(A2D.Y, true);
|
enum UIPushInfo[] text_view_params = [
|
||||||
PushScrollClampY(0.0, clamp_y, true);
|
{ "layout_axis", q{ A2D.Y } },
|
||||||
PushSizeInfo(g_size_info_default, true);
|
{ "border_col", q{ Vec4(1.0) } },
|
||||||
PushBorderCol(Vec4(1.0), true);
|
{ "size_info", q{ UIS2() } },
|
||||||
PushScrollTargetY(scroll_pos, true);
|
{ "scroll_target", q{ Vec2(0.0, scroll_pos) } },
|
||||||
PushViewOffsetY(view_offset, true);
|
{ "scroll_clamp", q{ Vec2(0.0, clamp_y) } },
|
||||||
|
{ "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);
|
||||||
|
|
||||||
PushParent(editor);
|
mixin(PushScope!("parent", q{ 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);
|
||||||
|
|
||||||
f32 cursor_x = CalcTextWidth(lb.text[0 .. ed.cursor_pos.x]);
|
u8 ch = lb.text.length > ed.cursor_pos.y ? lb.text[ed.cursor_pos.y] : 0;
|
||||||
f32 cursor_y = cast(f32)(ed.cursor_pos.y - line_offset)*TEXT_SIZE + view_offset;
|
f32 line_h = abuf.atlas.line_height;
|
||||||
PushSizeInfo(MakeUISize(UISize(ST.Pixels, GetCtx().char_width), UISize(ST.Pixels, TEXT_SIZE)), true);
|
f32 cursor_x = CalcTextWidth!(false)(lb.text[0 .. ed.cursor_pos.x], abuf);
|
||||||
PushFixedPos(Vec2(cursor_x, cursor_y), true);
|
f32 cursor_y = cast(f32)(ed.cursor_pos.y - line_offset)*line_h;
|
||||||
PushBgCol(Vec4(1.0), true);
|
Glyph* g = abuf.atlas.glyphs.length > ch ? abuf.atlas.glyphs.ptr + ch : abuf.atlas.glyphs.ptr + ' ';
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 end_line = line_offset+lines;
|
mixin(PushScope!("size_info", q{ UISY(ST.TextSize) } ));
|
||||||
PushSizeInfoY(ST.TextSize, 1.0);
|
mixin(PushScope!("syntax_highlight", q{ UISH.D } ));
|
||||||
PushSyntaxHighlight(UISH.D);
|
|
||||||
|
|
||||||
scope(exit) Pop!("size_info", "parent", "syntax_highlight");
|
// NEED TO FIX LINES BEING OFFSET FOR WHATEVER REASON
|
||||||
|
|
||||||
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))
|
||||||
{
|
{
|
||||||
PushDisplayString(ConvToStr(lb.text), true);
|
enum UIPushInfo[] lc_info = [
|
||||||
PushSyntaxTokens(cast(u8[])lb.style, true);
|
{ "display_string", q{ ConvToStr(lb.text) } },
|
||||||
|
{ "syntax_tokens", q{ cast(u8[])(lb.style) } },
|
||||||
|
];
|
||||||
|
mixin(PushOnce!(lc_info));
|
||||||
|
|
||||||
UIItem* line = MakeItem(zero, UIF.DrawText);
|
UIItem* line = MakeItem(zero, UIF.DrawText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,6 +140,7 @@ 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))
|
||||||
{
|
{
|
||||||
@ -132,24 +154,26 @@ 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);
|
||||||
|
|
||||||
u64 frame_line_offset = ed.line_offset;
|
f32 text_size = abuf.atlas.line_height;
|
||||||
f32 frame_view_offset = -(editor.scroll_offset.y%TEXT_SIZE);
|
|
||||||
|
|
||||||
PushBgCol(BG_COL, true);
|
u64 frame_line_offset = ed.line_offset;
|
||||||
PushSizeInfoX(ST.Percentage, 1.0, 1.0, true);
|
f32 frame_view_offset = -(editor.scroll_offset.y%text_size);
|
||||||
|
|
||||||
|
enum UIPushInfo[] c_info = [
|
||||||
|
{ "bg_col", q{ BG_COL } },
|
||||||
|
{ "size_info", q{ UIS2() } },
|
||||||
|
];
|
||||||
|
mixin(PushOnce!(c_info));
|
||||||
|
|
||||||
UIItem* container = MakeItem(zero, UIF.DrawBackground);
|
UIItem* container = MakeItem(zero, UIF.DrawBackground);
|
||||||
|
|
||||||
PushParent(container);
|
mixin(PushScope!("parent", q{ container } ));
|
||||||
PushBorderCol(Vec4(1.0));
|
mixin(PushScope!("border_col", q{ 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)ceil(editor.size.y/TEXT_SIZE)+1;
|
view_lines = cast(u64)floor(editor.size.y/text_size);
|
||||||
|
|
||||||
const u64 SCROLL_BUFFER = 4;
|
const u64 SCROLL_BUFFER = 4;
|
||||||
|
|
||||||
u64 start = ed.line_offset;
|
u64 start = ed.line_offset;
|
||||||
@ -166,9 +190,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(ed.buf.line_count, view_lines, start, frame_view_offset);
|
LineCounterView(abuf, ed.buf.line_count, view_lines, start, frame_view_offset);
|
||||||
EditorTextView(editor, p, view_lines, start, frame_view_offset);
|
EditorTextView(editor, p, abuf, 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)
|
||||||
{
|
{
|
||||||
@ -201,6 +225,8 @@ EditorView(Panel* p)
|
|||||||
|
|
||||||
ed.cursor_pos = VecPos(&ed.buf);
|
ed.cursor_pos = VecPos(&ed.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResetBuffer(&ed.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -208,348 +234,64 @@ 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;
|
||||||
|
|
||||||
PushFixedPos(Vec2(ext.x*0.3, ext.y*0.1), true);
|
enum UIPushInfo[] cmd_params = [
|
||||||
PushBgCol(BG_COL, true);
|
{ "layout_axis", q{ A2D.Y } },
|
||||||
PushBorderCol(HL_BORDER_COL, true);
|
{ "fixed_pos", q{ Vec2(ext.x*0.3, ext.y*0.1) } },
|
||||||
PushBorderThickness(2.0f, true);
|
{ "bg_col", q{ BG_COL } },
|
||||||
PushCornerRadius(8.0f, true);
|
{ "border_col", q{ HL_BORDER_COL } },
|
||||||
PushViewOffset(Vec2(-2.0f), true);
|
{ "border_thickness", q{ 4.0 } },
|
||||||
PushLayoutAxis(A2D.Y, true);
|
{ "corner_radius", q{ Vec4(8.0) } },
|
||||||
PushSizeInfo(MakeUISize(UISize(ST.Pixels, w), UISize(ST.Pixels, h)));
|
{ "size_info", q{ UIS2(ST.Pixels, ST.Pixels, w, 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 = 8.0;
|
f32 padding_y = 4.0;
|
||||||
PushParent(cmd_item);
|
|
||||||
PushPadding(Vec2(4.0, padding_y), true);
|
|
||||||
scope(exit) Pop!("parent", "padding")();
|
|
||||||
|
|
||||||
PushBgCol(HL_BG_COL, true);
|
mixin(PushScope!("parent", q{ cmd_item } ));
|
||||||
PushBorderCol(HL_BORDER_COL);
|
mixin(PushScope!("padding", q{ Vec2(4.0, padding_y) }));
|
||||||
PushBorderThickness(2.0f, true);
|
|
||||||
PushCornerRadius(Vec4(8.0, 8.0, 0.0, 0.0), true);
|
enum UIPushInfo[] cmd_input_params = [
|
||||||
PushSizeInfo(MakeUISize(UISize(ST.Pixels, w-padding_y), UISize(ST.TextSize, 1.0)), true);
|
{ "bg_col", q{ HL_BG_COL } },
|
||||||
PushDisplayString(ConvToStr(cmd.buffer[0 .. cmd.icount]), true);
|
{ "size_info", q{ UISY(ST.TextSize) } },
|
||||||
|
{ "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);
|
||||||
|
|
||||||
PushPadding(Vec2(4.0));
|
enum UIPushInfo[] sep_params = [
|
||||||
PushSizeInfoY(ST.TextSize, 1.0);
|
{ "padding", q{ Vec2(0.0) } },
|
||||||
scope(exit) Pop!("size_info", "padding")();
|
{ "size_info", q{ UISY(ST.Pixels, 4.0) } },
|
||||||
|
{ "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),
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach(i; 0 .. cmd.opt_strs.length)
|
for(u64 i = 0; i < cmd.opt_strs.length && i < max_opts; i += 1)
|
||||||
{
|
{
|
||||||
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,9 +5,14 @@
|
|||||||
|
|
||||||
#include "gui.layout"
|
#include "gui.layout"
|
||||||
|
|
||||||
layout (location = 0) flat in uint in_has_texture;
|
layout (location = 0) flat in struct FragDataFlatIn
|
||||||
|
{
|
||||||
|
uint texture;
|
||||||
|
uint atlas_index;
|
||||||
|
} FDF;
|
||||||
|
|
||||||
layout (location = 1) in struct FragDataIn {
|
layout (location = 2) in struct FragDataIn
|
||||||
|
{
|
||||||
vec4 color;
|
vec4 color;
|
||||||
vec2 uv;
|
vec2 uv;
|
||||||
vec2 dst_pos;
|
vec2 dst_pos;
|
||||||
@ -20,7 +25,6 @@ layout (location = 1) 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)
|
||||||
@ -75,7 +79,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(in_has_texture != 0)
|
if(FDF.texture != 0)
|
||||||
{
|
{
|
||||||
tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FD.uv);
|
tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FD.uv);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
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 SpriteAtlas;
|
layout (set = 1, binding = 0) uniform texture2D SpriteAtlasArray[24];
|
||||||
|
|
||||||
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,10 +17,16 @@ 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 uint out_has_texture;
|
layout (location = 0) flat out struct FragDataFlatOut
|
||||||
|
{
|
||||||
|
uint texture;
|
||||||
|
uint atlas_index;
|
||||||
|
} FDF;
|
||||||
|
|
||||||
layout (location = 1) out struct FragDataOut {
|
layout (location = 2) out struct FragDataOut
|
||||||
|
{
|
||||||
vec4 color;
|
vec4 color;
|
||||||
vec2 uv;
|
vec2 uv;
|
||||||
vec2 dst_pos;
|
vec2 dst_pos;
|
||||||
@ -31,7 +37,7 @@ layout (location = 1) out struct FragDataOut {
|
|||||||
float softness;
|
float softness;
|
||||||
float raised;
|
float raised;
|
||||||
float border_thickness;
|
float border_thickness;
|
||||||
} FragData;
|
} FD;
|
||||||
|
|
||||||
vec2 Vertices[4] = vec2[4](
|
vec2 Vertices[4] = vec2[4](
|
||||||
vec2(-1.0, -1.0),
|
vec2(-1.0, -1.0),
|
||||||
@ -77,17 +83,18 @@ 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);
|
||||||
|
|
||||||
FragData.color = in_col;
|
FD.color = in_col;
|
||||||
FragData.uv = uvs[gl_VertexIndex] / tex_size;
|
FD.uv = uvs[gl_VertexIndex] / tex_size;
|
||||||
FragData.dst_pos = pos;
|
FD.dst_pos = pos;
|
||||||
FragData.dst_center = center;
|
FD.dst_center = center;
|
||||||
FragData.dst_half_size = half_size;
|
FD.dst_half_size = half_size;
|
||||||
FragData.corner_radius = corner_radius[gl_VertexIndex];
|
FD.corner_radius = corner_radius[gl_VertexIndex];
|
||||||
FragData.softness = edge_softness;
|
FD.softness = edge_softness;
|
||||||
FragData.raised = raised;
|
FD.raised = raised;
|
||||||
FragData.border_thickness = border_thickness;
|
FD.border_thickness = border_thickness;
|
||||||
FragData.sdf_sample_pos = (2.0f * dst_verts_pct - 1.0f) * half_size;
|
FD.sdf_sample_pos = (2.0f * dst_verts_pct - 1.0f) * half_size;
|
||||||
out_has_texture = in_has_texture;
|
FDF.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