clean up, editor position/offset/etc within a buffer now tracked per editor per buffer
This commit is contained in:
parent
117b5eb51e
commit
5261118dd0
2
dub.json
2
dub.json
@ -16,7 +16,7 @@
|
|||||||
"versions": ["VULKAN_DEBUG", "ENABLE_RENDERER", "DLIB"],
|
"versions": ["VULKAN_DEBUG", "ENABLE_RENDERER", "DLIB"],
|
||||||
"preGenerateCommands-linux": ["./build.sh"],
|
"preGenerateCommands-linux": ["./build.sh"],
|
||||||
"preGenerateCommands-windows": [],
|
"preGenerateCommands-windows": [],
|
||||||
"dflags": ["-P-I/usr/include/freetype2", "-Jbuild", "-Jassets", "-P-DBUILD_VULKAN"],
|
"dflags": ["-P-I/usr/include/freetype2", "-Jbuild", "-Jassets", "-P-DBUILD_VULKAN", "-verrors=100"],
|
||||||
"dflags-ldc2": ["-link-debuglib", "--Xcc=-DBUILD_VULKAN"],
|
"dflags-ldc2": ["-link-debuglib", "--Xcc=-DBUILD_VULKAN"],
|
||||||
"dflags-dmd": ["-Xcc=-DBUILD_VULKAN"]
|
"dflags-dmd": ["-Xcc=-DBUILD_VULKAN"]
|
||||||
},
|
},
|
||||||
|
|||||||
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit 53eb211a1e227d1cf3d8036a0e8ecfb79f514eed
|
Subproject commit f3d1f551ccfa37de73d626479252bada0fc17cb2
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
|||||||
import dlib;
|
import dlib;
|
||||||
import dlib.util : Str;
|
import dlib.util : Str;
|
||||||
|
import dlib.alloc : Reset;
|
||||||
|
|
||||||
import vulkan;
|
import vulkan;
|
||||||
import std.format : sformat;
|
import std.format : sformat;
|
||||||
@ -16,8 +17,12 @@ import std.file;
|
|||||||
import std.string;
|
import std.string;
|
||||||
import core.stdc.stdio;
|
import core.stdc.stdio;
|
||||||
|
|
||||||
|
const u64 ARRAY_COUNT_INCREMENT = 32;
|
||||||
|
|
||||||
f32 g_delta = 0.0;
|
f32 g_delta = 0.0;
|
||||||
|
|
||||||
|
alias UIHashTable = HashTable!(UIHash, UIItem*);
|
||||||
|
|
||||||
struct RenderCtx
|
struct RenderCtx
|
||||||
{
|
{
|
||||||
PlatformWindow* window;
|
PlatformWindow* window;
|
||||||
@ -25,7 +30,6 @@ struct RenderCtx
|
|||||||
Descriptor default_tex;
|
Descriptor default_tex;
|
||||||
Descriptor sampler;
|
Descriptor sampler;
|
||||||
Pipeline pipeline;
|
Pipeline pipeline;
|
||||||
Pipeline slug_pipeline;
|
|
||||||
DescSetLayout desc_set_layout;
|
DescSetLayout desc_set_layout;
|
||||||
DescSet[FO] desc_sets;
|
DescSet[FO] desc_sets;
|
||||||
PipelineLayout pipeline_layout;
|
PipelineLayout pipeline_layout;
|
||||||
@ -36,7 +40,7 @@ struct Ctx
|
|||||||
{
|
{
|
||||||
RenderCtx rd_ctx;
|
RenderCtx rd_ctx;
|
||||||
|
|
||||||
HashTable!(UIHash, UIItem*) items;
|
UIHashTable items;
|
||||||
UIItem* free_items;
|
UIItem* free_items;
|
||||||
UIItem* last_item;
|
UIItem* last_item;
|
||||||
|
|
||||||
@ -46,7 +50,7 @@ struct Ctx
|
|||||||
|
|
||||||
Inputs* inputs;
|
Inputs* inputs;
|
||||||
u64 frame;
|
u64 frame;
|
||||||
u64 f_idx;
|
u64 frame_index;
|
||||||
|
|
||||||
Notification* active_notifications;
|
Notification* active_notifications;
|
||||||
Notification* free_notifications;
|
Notification* free_notifications;
|
||||||
@ -54,7 +58,6 @@ struct Ctx
|
|||||||
LinkedList!(UIInput) events;
|
LinkedList!(UIInput) events;
|
||||||
IVec2 mouse_pos;
|
IVec2 mouse_pos;
|
||||||
|
|
||||||
SlugFont slug_font;
|
|
||||||
FontFace font;
|
FontFace font;
|
||||||
FontSet[FS] font_sets;
|
FontSet[FS] font_sets;
|
||||||
u32 font_sets_used;
|
u32 font_sets_used;
|
||||||
@ -64,10 +67,6 @@ struct Ctx
|
|||||||
|
|
||||||
UIBuffer[FO] buffers;
|
UIBuffer[FO] buffers;
|
||||||
|
|
||||||
SlugBuffer[FO] slug_buffers;
|
|
||||||
MappedBuffer!(SlugVertex)[FO] slug_vertex_buffers;
|
|
||||||
MappedBuffer!(u32)[FO] slug_index_buffers;
|
|
||||||
|
|
||||||
u32 tab_width;
|
u32 tab_width;
|
||||||
Vec4[TS.max][UISH.max] syntax_colors;
|
Vec4[TS.max][UISH.max] syntax_colors;
|
||||||
|
|
||||||
@ -96,6 +95,14 @@ struct Ctx
|
|||||||
CmdPalette cmd;
|
CmdPalette cmd;
|
||||||
string[] file_names;
|
string[] file_names;
|
||||||
u64 panel_id;
|
u64 panel_id;
|
||||||
|
Editor[] editors;
|
||||||
|
u64 editor_count;
|
||||||
|
Editor* free_editors;
|
||||||
|
FlatBuffer[] text_buffers;
|
||||||
|
u64 text_buffer_count;
|
||||||
|
FlatBuffer* free_text_buffers;
|
||||||
|
|
||||||
|
@property ref DescSet desc_set() => this.rd_ctx.desc_sets[this.frame_index];
|
||||||
|
|
||||||
debug bool dbg;
|
debug bool dbg;
|
||||||
|
|
||||||
@ -131,21 +138,17 @@ struct CmdPalette
|
|||||||
|
|
||||||
struct Editor
|
struct Editor
|
||||||
{
|
{
|
||||||
Arena arena;
|
alias BufferViewTable = HashTable!(string, BufferViewInfo);
|
||||||
|
|
||||||
|
BufferViewInfo view_info_default;
|
||||||
|
FlatBuffer* buffer;
|
||||||
|
Editor* list_next;
|
||||||
|
BufferViewInfo* view_info;
|
||||||
u64 editor_id;
|
u64 editor_id;
|
||||||
|
|
||||||
FlatBuffer buf;
|
|
||||||
Tokenizer tk;
|
|
||||||
|
|
||||||
I64Vec2 cursor_pos;
|
|
||||||
Vec2 select_start;
|
|
||||||
Vec2 select_end;
|
|
||||||
i64 line_offset;
|
|
||||||
i64 line_height;
|
i64 line_height;
|
||||||
|
BufferViewTable view_info_table;
|
||||||
|
|
||||||
Editor* free_next;
|
alias buffer this;
|
||||||
|
|
||||||
alias buf this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChangeStacks
|
struct ChangeStacks
|
||||||
@ -165,7 +168,7 @@ struct EditorChange
|
|||||||
EditorChange* next;
|
EditorChange* next;
|
||||||
}
|
}
|
||||||
|
|
||||||
alias CmdFn = bool function(Ctx* ctx); // return true when completed
|
alias CmdFn = bool function(ref Ctx ctx); // return true when completed
|
||||||
|
|
||||||
struct Command
|
struct Command
|
||||||
{
|
{
|
||||||
@ -236,16 +239,18 @@ enum EditState
|
|||||||
} alias ES = EditState;
|
} alias ES = EditState;
|
||||||
|
|
||||||
__gshared Ctx g_ctx;
|
__gshared Ctx g_ctx;
|
||||||
__gshared const Editor g_nil_ed;
|
|
||||||
__gshared Editor* g_NIL_ED;
|
__gshared Editor g_nil_ed;
|
||||||
__gshared const UIItem g_ui_nil_item;
|
__gshared UIItem g_ui_nil_item;
|
||||||
__gshared UIItem* g_UI_NIL;
|
__gshared UIInput g_ui_nil_input;
|
||||||
__gshared const UIInput g_ui_nil_input;
|
__gshared UIPanel g_nil_panel;
|
||||||
__gshared UIInput* g_UI_NIL_INPUT;
|
__gshared Notification g_nil_notif;
|
||||||
__gshared const UIPanel g_nil_panel;
|
|
||||||
__gshared UIPanel* g_NIL_PANEL;
|
__gshared Editor* g_NIL_ED = &g_nil_ed;
|
||||||
__gshared const Notification g_nil_notif;
|
__gshared UIItem* g_UI_NIL_ITEM = &g_ui_nil_item;
|
||||||
__gshared Notification* g_NIL_NOTIF;
|
__gshared UIInput* g_UI_NIL_INPUT = &g_ui_nil_input;
|
||||||
|
__gshared UIPanel* g_NIL_PANEL = &g_nil_panel;
|
||||||
|
__gshared Notification* g_NIL_NOTIF = &g_nil_notif;
|
||||||
|
|
||||||
const Command NO_CMD = {
|
const Command NO_CMD = {
|
||||||
name: [],
|
name: [],
|
||||||
@ -402,10 +407,24 @@ Command[21] CMD_LIST = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
ref Ctx GetCtx() => g_ctx;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ClosePanelCmd(Ctx* ctx)
|
ClosePanelCmd(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
Clear(ctx.focused_panel.ed);
|
Editor* editor = ctx.focused_panel.ed;
|
||||||
|
ctx.focused_panel.ed = null;
|
||||||
|
if(editor.file_name.length == 0 && editor.length == 0)
|
||||||
|
{
|
||||||
|
editor.buffer.list_next = ctx.free_text_buffers;
|
||||||
|
ctx.free_text_buffers = editor.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeHashTable(editor.view_info_table);
|
||||||
|
memset(editor, 0, Editor.sizeof);
|
||||||
|
editor.list_next = ctx.free_editors;
|
||||||
|
ctx.free_editors = editor;
|
||||||
|
|
||||||
if(ctx.focused_panel != ctx.base_panel)
|
if(ctx.focused_panel != ctx.base_panel)
|
||||||
{
|
{
|
||||||
DLLRemove(ctx.focused_panel.parent, ctx.focused_panel, g_NIL_PANEL);
|
DLLRemove(ctx.focused_panel.parent, ctx.focused_panel, g_NIL_PANEL);
|
||||||
@ -456,38 +475,27 @@ ClosePanelCmd(Ctx* ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SplitVertically(Ctx* ctx)
|
SplitVertically(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
AddPanel(ctx.focused_panel, A2D.X);
|
AddPanel(ctx.focused_panel, A2D.X);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SplitHorizontally(Ctx* ctx)
|
SplitHorizontally(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
AddPanel(ctx.focused_panel, A2D.Y);
|
AddPanel(ctx.focused_panel, A2D.Y);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
NotImplementedCallback(Ctx* ctx)
|
NotImplementedCallback(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
Logf("Not yet implemented!");
|
Logf("Not yet implemented!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool Active(EditState state) => g_ctx.state == state;
|
||||||
CmdModeActive()
|
|
||||||
{
|
|
||||||
return g_ctx.state == ES.CmdPalette;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Active(EditState state)
|
|
||||||
{
|
|
||||||
return g_ctx.state == state;
|
|
||||||
}
|
|
||||||
|
|
||||||
UIPanel*
|
UIPanel*
|
||||||
MakePanel(UIPanel* parent = g_NIL_PANEL)
|
MakePanel(UIPanel* parent = g_NIL_PANEL)
|
||||||
@ -511,7 +519,7 @@ Cycle(Inputs* inputs)
|
|||||||
|
|
||||||
BeginUI(inputs);
|
BeginUI(inputs);
|
||||||
|
|
||||||
Ctx* ctx = GetCtx();
|
ref Ctx ctx = GetCtx();
|
||||||
|
|
||||||
Panel(ctx, ctx.base_panel);
|
Panel(ctx, ctx.base_panel);
|
||||||
|
|
||||||
@ -538,12 +546,7 @@ Focus(UIPanel* panel)
|
|||||||
void
|
void
|
||||||
InitCtx(PlatformWindow* window)
|
InitCtx(PlatformWindow* window)
|
||||||
{
|
{
|
||||||
Ctx* ctx = &g_ctx;
|
ref Ctx ctx = GetCtx();
|
||||||
|
|
||||||
g_NIL_ED = cast(Editor*)&g_nil_ed;
|
|
||||||
g_UI_NIL = cast(UIItem*)&g_ui_nil_item;
|
|
||||||
g_UI_NIL_INPUT = cast(UIInput*)&g_ui_nil_input;
|
|
||||||
g_NIL_PANEL = cast(UIPanel*)&g_nil_panel;
|
|
||||||
|
|
||||||
ctx.window = window;
|
ctx.window = window;
|
||||||
ctx.arena = CreateArena(MB(2));
|
ctx.arena = CreateArena(MB(2));
|
||||||
@ -552,6 +555,8 @@ InitCtx(PlatformWindow* window)
|
|||||||
ctx.cmd.exec_cmd_arena = CreateArena(MB(1));
|
ctx.cmd.exec_cmd_arena = CreateArena(MB(1));
|
||||||
ctx.timer = CreateTimer();
|
ctx.timer = CreateTimer();
|
||||||
ctx.free_panels = g_NIL_PANEL;
|
ctx.free_panels = g_NIL_PANEL;
|
||||||
|
ctx.text_buffers = Alloc!(FlatBuffer)(ARRAY_COUNT_INCREMENT);
|
||||||
|
ctx.editors = Alloc!(Editor)(ARRAY_COUNT_INCREMENT);
|
||||||
|
|
||||||
InitUI(ctx);
|
InitUI(ctx);
|
||||||
|
|
||||||
@ -590,86 +595,36 @@ InitCtx(PlatformWindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ctx*
|
|
||||||
GetCtx()
|
|
||||||
{
|
|
||||||
return &g_ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
char[]
|
|
||||||
ToAbsolutePath(string file_name)
|
|
||||||
{
|
|
||||||
import core.stdc.string : strlen;
|
|
||||||
|
|
||||||
char[1024] name_buf = '\0';
|
|
||||||
char[1024] wd_buf = '\0';
|
|
||||||
version(linux)
|
|
||||||
{
|
|
||||||
import core.sys.posix.unistd;
|
|
||||||
getcwd(wd_buf.ptr, wd_buf.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
version(Windows)
|
|
||||||
{
|
|
||||||
import core.sys.windows.direct;
|
|
||||||
_getcwd(wd_buf.ptr, wd_buf.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
char[] wd = wd_buf[0 .. strlen(wd_buf.ptr)];
|
|
||||||
|
|
||||||
version(linux)
|
|
||||||
{
|
|
||||||
if(file_name[0] != '/')
|
|
||||||
{
|
|
||||||
name_buf.sformat("%s/%s", wd, cast(char[])file_name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
name_buf.sformat("%s", cast(char[])file_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
version(Windows)
|
|
||||||
{
|
|
||||||
name_buf.sformat("%s/%s", wd, cast(char[])file_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
char[] path_buf = ScratchAlloc!(char)(strlen(name_buf.ptr)+1);
|
|
||||||
path_buf[0 .. $] = name_buf[0 .. path_buf.length];
|
|
||||||
|
|
||||||
return path_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SaveFile(Editor* ed, string file_name)
|
SaveFile(Editor* ed, string file_name)
|
||||||
{
|
{
|
||||||
import core.stdc.stdio;
|
import core.stdc.stdio;
|
||||||
|
|
||||||
file_name = file_name.length == 0 ? Str(ed.buf.file_name) : file_name;
|
file_name = file_name.length == 0 ? Str(ed.file_name) : file_name;
|
||||||
|
|
||||||
if(file_name.length > 0)
|
if(file_name.length > 0)
|
||||||
{
|
{
|
||||||
char[] file_path = ToAbsolutePath(file_name);
|
string file_path = AbsolutePath(file_name);
|
||||||
auto f = fopen(cast(char*)file_path.ptr, "wb");
|
auto f = fopen(cast(char*)file_path.ptr, "wb");
|
||||||
if(f != null)
|
if(f != null)
|
||||||
{
|
{
|
||||||
u64 tab_count;
|
u64 tab_count;
|
||||||
for(u64 i = 0; i < ed.buf.length; i += 1)
|
for(u64 i = 0; i < ed.length; i += 1)
|
||||||
{
|
{
|
||||||
if(ed.buf.data[i] == '\t')
|
if(ed.data[i] == '\t')
|
||||||
{
|
{
|
||||||
tab_count += 1;
|
tab_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 tab_width = GetCtx().tab_width;
|
u64 tab_width = GetCtx().tab_width;
|
||||||
u64 buf_size = ed.buf.length + ((tab_width-1) * tab_count);
|
u64 buf_size = ed.length + ((tab_width-1) * tab_count);
|
||||||
u8[] temp_buf = ScratchAlloc!(u8)(buf_size);
|
u8[] temp_buf = ScratchAlloc!(u8)(buf_size);
|
||||||
|
|
||||||
u64 buf_pos;
|
u64 buf_pos;
|
||||||
for(u64 i = 0; i < ed.buf.length; i += 1)
|
for(u64 i = 0; i < ed.length; i += 1)
|
||||||
{
|
{
|
||||||
if(ed.buf.data[i] == '\t')
|
if(ed.data[i] == '\t')
|
||||||
{
|
{
|
||||||
for(u64 j = 0; j < tab_width; j += 1)
|
for(u64 j = 0; j < tab_width; j += 1)
|
||||||
{
|
{
|
||||||
@ -678,7 +633,7 @@ SaveFile(Editor* ed, string file_name)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
temp_buf[buf_pos++] = ed.buf.data[i];
|
temp_buf[buf_pos++] = ed.data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,40 +644,6 @@ SaveFile(Editor* ed, string file_name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
OpenFile(Editor* ed, string file_name)
|
|
||||||
{
|
|
||||||
import core.stdc.stdio;
|
|
||||||
import std.file;
|
|
||||||
import std.conv;
|
|
||||||
|
|
||||||
if(file_name.length > 0)
|
|
||||||
{
|
|
||||||
char[] file_path = ToAbsolutePath(file_name);
|
|
||||||
auto f = fopen(file_path.ptr, "rb");
|
|
||||||
if(f != null)
|
|
||||||
{
|
|
||||||
fseek(f, 0, SEEK_END);
|
|
||||||
i64 len = ftell(f);
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
|
|
||||||
if(len > 0)
|
|
||||||
{
|
|
||||||
u8[] buf = ScratchAlloc!(u8)(len);
|
|
||||||
fread(buf.ptr, u8.sizeof, len, f);
|
|
||||||
Change(&ed.buf, buf, file_name);
|
|
||||||
ed.buf.file_name = file_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
perror("[Error] Unable to open file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string
|
string
|
||||||
Str(TextInputBuffer text_buffer)
|
Str(TextInputBuffer text_buffer)
|
||||||
{
|
{
|
||||||
@ -732,20 +653,48 @@ Str(TextInputBuffer text_buffer)
|
|||||||
Editor*
|
Editor*
|
||||||
CreateEditor()
|
CreateEditor()
|
||||||
{
|
{
|
||||||
Editor* ed = Alloc!(Editor)(&g_ctx.arena);
|
ref Ctx ctx = GetCtx();
|
||||||
ed.arena = CreateArena(MB(4));
|
|
||||||
ed.buf = CreateFlatBuffer([], []);
|
|
||||||
ed.editor_id = g_ctx.editor_id_incr++;
|
|
||||||
|
|
||||||
return ed;
|
if(ctx.editor_count == ctx.editors.length)
|
||||||
|
{
|
||||||
|
ctx.editors = Realloc(ctx.editors, ctx.editors.length+ARRAY_COUNT_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor* editor = ctx.free_editors;
|
||||||
|
if(editor)
|
||||||
|
{
|
||||||
|
ctx.free_editors = editor.list_next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
editor = &ctx.editors[ctx.editor_count++];
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.view_info_table = CreateHashTable!(string, BufferViewInfo)(4);
|
||||||
|
ResetViewInfo(&editor.view_info_default);
|
||||||
|
editor.view_info = &editor.view_info_default;
|
||||||
|
|
||||||
|
editor.buffer = ctx.free_text_buffers;
|
||||||
|
if(editor.buffer)
|
||||||
|
{
|
||||||
|
ctx.free_text_buffers = editor.buffer.list_next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
editor.buffer = CreateFlatBuffer(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.editor_id = g_ctx.editor_id_incr++;
|
||||||
|
|
||||||
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
InsertInputToBuf(Ctx* ctx, Editor* ed)
|
InsertInputToBuf(ref Ctx ctx, Editor* ed)
|
||||||
{
|
{
|
||||||
if(ctx.icount > 0)
|
if(ctx.icount > 0)
|
||||||
{
|
{
|
||||||
Insert(&ed.buf, ctx.input_buf, ctx.icount);
|
Insert(ed, ctx.input_buf, ctx.icount);
|
||||||
ctx.icount = 0;
|
ctx.icount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -753,12 +702,12 @@ InsertInputToBuf(Ctx* ctx, Editor* ed)
|
|||||||
void
|
void
|
||||||
ResetCtx(Editor* ed)
|
ResetCtx(Editor* ed)
|
||||||
{
|
{
|
||||||
InsertInputToBuf(&g_ctx, ed);
|
InsertInputToBuf(GetCtx(), ed);
|
||||||
ResetCtx();
|
ResetCtx();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ResetCmd(Ctx* ctx)
|
ResetCmd(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
ctx.cmd.text_input.length = 0;
|
ctx.cmd.text_input.length = 0;
|
||||||
ctx.cmd.selected = 0;
|
ctx.cmd.selected = 0;
|
||||||
@ -836,9 +785,8 @@ bool
|
|||||||
HandleInputs(UIPanel* p, LinkedList!(UIInput)* inputs, bool hovered, bool focused)
|
HandleInputs(UIPanel* p, LinkedList!(UIInput)* inputs, bool hovered, bool focused)
|
||||||
{
|
{
|
||||||
Editor* ed = p.ed;
|
Editor* ed = p.ed;
|
||||||
Ctx* ctx = &g_ctx;
|
ref Ctx ctx = GetCtx();
|
||||||
FlatBuffer* fb = &ed.buf;
|
u64 initial_len = p.ed.length;
|
||||||
u64 initial_len = p.ed.buf.length;
|
|
||||||
u8[] cb_text;
|
u8[] cb_text;
|
||||||
|
|
||||||
for(auto node = inputs.first; node != null; node = node.next)
|
for(auto node = inputs.first; node != null; node = node.next)
|
||||||
@ -896,17 +844,17 @@ HandleInputs(UIPanel* p, LinkedList!(UIInput)* inputs, bool hovered, bool focuse
|
|||||||
{
|
{
|
||||||
case a, i:
|
case a, i:
|
||||||
{
|
{
|
||||||
if(key == a && Shift(md) && fb)
|
if(key == a && Shift(md))
|
||||||
{
|
{
|
||||||
MoveToEOL(fb);
|
MoveToEOL(ed);
|
||||||
}
|
}
|
||||||
else if(key == a)
|
else if(key == a)
|
||||||
{
|
{
|
||||||
Move(fb, Right, MD.None);
|
Move(ed, Right, MD.None);
|
||||||
}
|
}
|
||||||
else if(key == i && Shift(md))
|
else if(key == i && Shift(md))
|
||||||
{
|
{
|
||||||
MoveToSOL(fb);
|
MoveToSOL(ed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.state = ES.InputMode;
|
ctx.state = ES.InputMode;
|
||||||
@ -930,11 +878,11 @@ HandleInputs(UIPanel* p, LinkedList!(UIInput)* inputs, bool hovered, bool focuse
|
|||||||
}
|
}
|
||||||
if(Shift(md))
|
if(Shift(md))
|
||||||
{
|
{
|
||||||
ToggleSelection(fb, SM.Line);
|
ToggleSelection(ed, SM.Line);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ToggleSelection(fb, SM.Normal);
|
ToggleSelection(ed, SM.Normal);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case c:
|
case c:
|
||||||
@ -984,22 +932,22 @@ HandleInputs(UIPanel* p, LinkedList!(UIInput)* inputs, bool hovered, bool focuse
|
|||||||
|
|
||||||
if(cb_text.length > 0)
|
if(cb_text.length > 0)
|
||||||
{
|
{
|
||||||
Insert(fb, cb_text, cb_text.length);
|
Insert(ed, cb_text, cb_text.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return initial_len != p.ed.buf.length;
|
return initial_len != p.ed.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SetOffset(Editor* ed, i64 adjust)
|
SetOffset(Editor* ed, i64 adjust)
|
||||||
{
|
{
|
||||||
i64 max_offset = ed.buf.line_count-ed.line_height;
|
i64 max_offset = ed.line_count-ed.line_height;
|
||||||
if(max_offset < 0)
|
if(max_offset < 0)
|
||||||
{
|
{
|
||||||
max_offset = 0;
|
max_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ed.line_offset = clamp(ed.line_offset+adjust, 0, max_offset);
|
ed.view_info.line_offset = clamp(ed.view_info.line_offset+adjust, 0, max_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1009,15 +957,15 @@ MoveCursor(Editor* ed, UIInput* ev)
|
|||||||
|
|
||||||
switch(ev.key) with(Input)
|
switch(ev.key) with(Input)
|
||||||
{
|
{
|
||||||
case Up, Down, Left, Right: taken = Move(&ed.buf, ev.key, ev.md); break;
|
case Up, Down, Left, Right: taken = Move(ed, ev.key, ev.md); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(taken)
|
if(taken)
|
||||||
{
|
{
|
||||||
I64Vec2 pos = VecPos(&ed.buf);
|
I64Vec2 pos = VecPos(ed);
|
||||||
i64 min = ed.line_offset+2;
|
i64 min = ed.view_info.line_offset+2;
|
||||||
i64 max = clamp(ed.line_offset+ed.line_height-3, 0, ed.buf.line_count);
|
i64 max = clamp(ed.view_info.line_offset+ed.line_height-3, 0, ed.line_count);
|
||||||
if(pos.y > max)
|
if(pos.y > max)
|
||||||
{
|
{
|
||||||
SetOffset(ed, pos.y-max);
|
SetOffset(ed, pos.y-max);
|
||||||
@ -1032,7 +980,7 @@ MoveCursor(Editor* ed, UIInput* ev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
InsertChar(Ctx* ctx, Input input, bool modified)
|
InsertChar(ref Ctx ctx, Input input, bool modified)
|
||||||
{
|
{
|
||||||
ctx.input_buf[ctx.icount++] = InputToChar(input, modified);
|
ctx.input_buf[ctx.icount++] = InputToChar(input, modified);
|
||||||
}
|
}
|
||||||
@ -1055,7 +1003,7 @@ CharCases()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
HandleInputMode(Ctx* ctx, UIPanel* p, UIInput* ev)
|
HandleInputMode(ref Ctx ctx, UIPanel* p, UIInput* ev)
|
||||||
{
|
{
|
||||||
bool taken;
|
bool taken;
|
||||||
|
|
||||||
@ -1064,7 +1012,7 @@ HandleInputMode(Ctx* ctx, UIPanel* p, UIInput* ev)
|
|||||||
mixin(CharCases());
|
mixin(CharCases());
|
||||||
case Input.Backspace:
|
case Input.Backspace:
|
||||||
{
|
{
|
||||||
Backspace(&p.ed.buf);
|
Backspace(p.ed);
|
||||||
taken = true;
|
taken = true;
|
||||||
} break;
|
} break;
|
||||||
case Input.Escape:
|
case Input.Escape:
|
||||||
@ -1168,7 +1116,7 @@ StrContains(bool begins_with)(string str, string match)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HandleCmdMode(Ctx* ctx, bool* enter_hit, bool* buffer_changed, bool* selection_changed)
|
HandleCmdMode(ref Ctx ctx, bool* enter_hit, bool* buffer_changed, bool* selection_changed)
|
||||||
{
|
{
|
||||||
UIPanel* panel = ctx.focused_panel;
|
UIPanel* panel = ctx.focused_panel;
|
||||||
Editor* ed = panel.ed;
|
Editor* ed = panel.ed;
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import dlib;
|
import dlib;
|
||||||
|
|
||||||
|
import dlib.alloc : Reset;
|
||||||
|
|
||||||
|
import editor;
|
||||||
import buffer;
|
import buffer;
|
||||||
|
|
||||||
enum TokenStyle : u8
|
enum TokenStyle : u8
|
||||||
@ -399,28 +402,22 @@ struct Tokenizer
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Nil(Token* tk)
|
Nil(Token* token)
|
||||||
{
|
{
|
||||||
return tk == g_NIL_TOKEN || tk == null;
|
return token == g_NIL_TOKEN || token == null;
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SetBuffers(Tokenizer* tk, TokenStyle[] tokens)
|
|
||||||
{
|
|
||||||
tk.tokens = tokens;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokenizer
|
Tokenizer
|
||||||
CreateTokenizer(FlatBuffer* fb)
|
CreateTokenizer(FlatBuffer* buffer)
|
||||||
{
|
{
|
||||||
Tokenizer tk = {
|
Tokenizer tokenizer = {
|
||||||
arena: CreateArena(MB(4)),
|
arena: CreateArena(MB(4)),
|
||||||
};
|
};
|
||||||
|
|
||||||
SetBuffers(&tk, Alloc!(TS)(fb.data.length));
|
tokenizer.tokens = Alloc!(TS)(buffer.data.length);
|
||||||
|
|
||||||
g_NIL_TOKEN = cast(Token*)&g_nil_tk;
|
g_NIL_TOKEN = cast(Token*)&g_nil_tk;
|
||||||
tk.first = tk.last = g_NIL_TOKEN;
|
tokenizer.first = tokenizer.last = g_NIL_TOKEN;
|
||||||
|
|
||||||
for(u64 i = 0; i < D_KEYWORDS.length; i += 1)
|
for(u64 i = 0; i < D_KEYWORDS.length; i += 1)
|
||||||
{
|
{
|
||||||
@ -438,132 +435,133 @@ CreateTokenizer(FlatBuffer* fb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tk;
|
return tokenizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ResetTokenizer(Tokenizer* tk, u64 len)
|
ResetTokenizer(Tokenizer* tokenizer, u64 length)
|
||||||
{
|
{
|
||||||
Reset(&tk.arena);
|
Reset(&tokenizer.arena);
|
||||||
Free(tk.tokens);
|
Free(tokenizer.tokens);
|
||||||
|
|
||||||
SetBuffers(tk, Alloc!(TS)(len));
|
tokenizer.tokens = Alloc!(TS)(length);
|
||||||
tk.pos = 0;
|
tokenizer.pos = 0;
|
||||||
tk.first = tk.last = g_NIL_TOKEN;
|
tokenizer.first = tokenizer.last = g_NIL_TOKEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token*
|
Token*
|
||||||
MakeToken(Tokenizer* tk, TokenType type, u64 start, u64 end)
|
MakeToken(Tokenizer* tokenizer, TokenType type, u64 length)
|
||||||
{
|
{
|
||||||
Token* t = Alloc!(Token)(&tk.arena);
|
Token* token = Alloc!(Token)(&tokenizer.arena);
|
||||||
|
|
||||||
t.type = type;
|
token.type = type;
|
||||||
t.start = start;
|
token.start = tokenizer.pos;
|
||||||
t.end = end;
|
token.end = tokenizer.pos+length;
|
||||||
|
|
||||||
DLLPush(tk, t, g_NIL_TOKEN);
|
DLLPush(tokenizer, token, g_NIL_TOKEN);
|
||||||
|
|
||||||
return t;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8
|
u8
|
||||||
Peek(FlatBuffer* fb)
|
Peek(T)(T* buffer) if(is(T == Editor) || is(T == FlatBuffer))
|
||||||
{
|
{
|
||||||
return fb.tk.pos+1 < fb.length ? fb.data[fb.tk.pos+1] : 0;
|
return buffer.tokenizer.pos+1 < buffer.length ? buffer.data[buffer.tokenizer.pos+1] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TokenizeD(FlatBuffer* fb)
|
TokenizeD(T)(T* buffer)
|
||||||
|
if(is(T == Editor) || is(T == FlatBuffer))
|
||||||
{
|
{
|
||||||
Tokenizer* tk = &fb.tk;
|
Tokenizer* tokenizer = &buffer.tokenizer;
|
||||||
|
|
||||||
Reset(&tk.arena);
|
Reset(&tokenizer.arena);
|
||||||
tk.pos = 0;
|
tokenizer.pos = 0;
|
||||||
tk.first = tk.last = g_NIL_TOKEN;
|
tokenizer.first = tokenizer.last = g_NIL_TOKEN;
|
||||||
|
|
||||||
for(; tk.pos < fb.length;)
|
for(; tokenizer.pos < buffer.length;)
|
||||||
{
|
{
|
||||||
u8 ch = fb.data[tk.pos];
|
u8 ch = buffer.data[tokenizer.pos];
|
||||||
bool alpha = (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
|
bool alpha = (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
|
||||||
|
|
||||||
if(ch == ' ' || ch == '\t')
|
if(ch == ' ' || ch == '\t')
|
||||||
{
|
{
|
||||||
Token* t = MakeToken(tk, TT.Whitespace, tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, TT.Whitespace, 1);
|
||||||
|
|
||||||
for(tk.pos += 1; tk.pos < fb.length; tk.pos += 1)
|
for(tokenizer.pos += 1; tokenizer.pos < buffer.length; tokenizer.pos += 1)
|
||||||
{
|
{
|
||||||
if(fb.data[tk.pos] != ' ' && fb.data[tk.pos] != '\t')
|
if(buffer.data[tokenizer.pos] != ' ' && buffer.data[tokenizer.pos] != '\t')
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.end = tk.pos;
|
token.end = tokenizer.pos;
|
||||||
}
|
}
|
||||||
else if(ch == '\n')
|
else if(ch == '\n')
|
||||||
{
|
{
|
||||||
Token* t = MakeToken(tk, TT.NewLine, tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, TT.NewLine, 1);
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
}
|
}
|
||||||
else if(ch == 'r')
|
else if(ch == 'r')
|
||||||
{
|
{
|
||||||
u8 next = Peek(fb);
|
u8 next = Peek(buffer);
|
||||||
if(next == '"')
|
if(next == '"')
|
||||||
{
|
{
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
ParseStr!('"')(fb);
|
ParseStr!('"')(buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ParseId(fb);
|
ParseId(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(ch >= '0' && ch <= '9')
|
else if(ch >= '0' && ch <= '9')
|
||||||
{
|
{
|
||||||
ParseNum(fb);
|
ParseNum(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(ch == 'P' || ch == 'E' || ch == 'e' || ch == 'p')
|
else if(ch == 'P' || ch == 'E' || ch == 'e' || ch == 'p')
|
||||||
{
|
{
|
||||||
u8 next = Peek(fb);
|
u8 next = Peek(buffer);
|
||||||
if(next == '-' || next == '+' || (next >= '0' && next <= '9'))
|
if(next == '-' || next == '+' || (next >= '0' && next <= '9'))
|
||||||
{
|
{
|
||||||
ParseNum(fb);
|
ParseNum(buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ParseId(fb);
|
ParseId(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(alpha || ch == '_')
|
else if(alpha || ch == '_')
|
||||||
{
|
{
|
||||||
ParseId(fb);
|
ParseId(buffer);
|
||||||
}
|
}
|
||||||
else if(ch < 128 && D_STD_TOKEN[ch] != TT.None)
|
else if(ch < 128 && D_STD_TOKEN[ch] != TT.None)
|
||||||
{
|
{
|
||||||
Token* t = MakeToken(tk, D_STD_TOKEN[ch], tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, D_STD_TOKEN[ch], 1);
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
}
|
}
|
||||||
else if(ch < 128 && D_OP_TOKEN[ch] != TT.None)
|
else if(ch < 128 && D_OP_TOKEN[ch] != TT.None)
|
||||||
{
|
{
|
||||||
Token* t = MakeToken(tk, D_OP_TOKEN[ch], tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, D_OP_TOKEN[ch], 1);
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
FixOpAssign(fb, t);
|
FixOpAssign(buffer, token);
|
||||||
}
|
}
|
||||||
else if(ch < 128 && D_STR_TOKEN[ch] != TT.None)
|
else if(ch < 128 && D_STR_TOKEN[ch] != TT.None)
|
||||||
{
|
{
|
||||||
if(ch == '"')
|
if(ch == '"')
|
||||||
{
|
{
|
||||||
ParseStr!('"')(fb);
|
ParseStr!('"')(buffer);
|
||||||
}
|
}
|
||||||
else if(ch == '`')
|
else if(ch == '`')
|
||||||
{
|
{
|
||||||
ParseStr!('`')(fb);
|
ParseStr!('`')(buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ParseStr!('\'')(fb);
|
ParseStr!('\'')(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -572,108 +570,108 @@ TokenizeD(FlatBuffer* fb)
|
|||||||
{
|
{
|
||||||
case '@':
|
case '@':
|
||||||
{
|
{
|
||||||
Token* t = MakeToken(tk, TT.At, tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, TT.At, 1);
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
|
|
||||||
for(; tk.pos < fb.length; tk.pos += 1)
|
for(; tokenizer.pos < buffer.length; tokenizer.pos += 1)
|
||||||
{
|
{
|
||||||
u8 c = fb.data[tk.pos];
|
u8 c = buffer.data[tokenizer.pos];
|
||||||
|
|
||||||
if(CheckWhiteSpace(c)) break;
|
if(CheckWhiteSpace(c)) break;
|
||||||
if(!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z')) break;
|
if(!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z')) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
t.end = tk.pos;
|
token.end = tokenizer.pos;
|
||||||
} break;
|
} break;
|
||||||
case '.':
|
case '.':
|
||||||
{
|
{
|
||||||
Token* t = MakeToken(tk, TT.Dot, tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, TT.Dot, 1);
|
||||||
|
|
||||||
for(; tk.pos < fb.length; tk.pos += 1)
|
for(; tokenizer.pos < buffer.length; tokenizer.pos += 1)
|
||||||
{
|
{
|
||||||
if(fb.data[tk.pos] != '.') break;
|
if(buffer.data[tokenizer.pos] != '.') break;
|
||||||
}
|
}
|
||||||
|
|
||||||
t.end = tk.pos;
|
token.end = tokenizer.pos;
|
||||||
} break;
|
} break;
|
||||||
case '#':
|
case '#':
|
||||||
{
|
{
|
||||||
Token* t = MakeToken(tk, TT.Import, tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, TT.Import, 1);
|
||||||
|
|
||||||
for(; tk.pos < fb.length; tk.pos += 1)
|
for(; tokenizer.pos < buffer.length; tokenizer.pos += 1)
|
||||||
{
|
{
|
||||||
if(CheckWhiteSpace(fb.data[tk.pos])) break;
|
if(CheckWhiteSpace(buffer.data[tokenizer.pos])) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
t.end = tk.pos;
|
token.end = tokenizer.pos;
|
||||||
} break;
|
} break;
|
||||||
case '/':
|
case '/':
|
||||||
{
|
{
|
||||||
Token* t = MakeToken(tk, TT.Slash, tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, TT.Slash, 1);
|
||||||
|
|
||||||
u8 next = Peek(fb);
|
u8 next = Peek(buffer);
|
||||||
if(next == '/')
|
if(next == '/')
|
||||||
{
|
{
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
t.type = TT.Comment;
|
token.type = TT.Comment;
|
||||||
|
|
||||||
for(; tk.pos < fb.length; tk.pos += 1)
|
for(; tokenizer.pos < buffer.length; tokenizer.pos += 1)
|
||||||
{
|
{
|
||||||
if(CheckEOL(fb.data[tk.pos]))
|
if(CheckEOL(buffer.data[tokenizer.pos]))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.end = tk.pos+1;
|
token.end = tokenizer.pos+1;
|
||||||
}
|
}
|
||||||
else if(next == '*')
|
else if(next == '*')
|
||||||
{
|
{
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
t.type = TT.Comment;
|
token.type = TT.Comment;
|
||||||
|
|
||||||
for(; tk.pos < fb.length; tk.pos += 1)
|
for(; tokenizer.pos < buffer.length; tokenizer.pos += 1)
|
||||||
{
|
{
|
||||||
if(fb.data[tk.pos] == '/' && fb.data[tk.pos-1] == '*')
|
if(buffer.data[tokenizer.pos] == '/' && buffer.data[tokenizer.pos-1] == '*')
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
t.end = tk.pos;
|
token.end = tokenizer.pos;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
FixOpAssign(fb, t);
|
FixOpAssign(buffer, token);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Token* t = MakeToken(tk, TT.None, tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, TT.None, 1);
|
||||||
|
|
||||||
for(; tk.pos < fb.length; tk.pos += 1)
|
for(; tokenizer.pos < buffer.length; tokenizer.pos += 1)
|
||||||
{
|
{
|
||||||
if(CheckWhiteSpace(fb.data[tk.pos]))
|
if(CheckWhiteSpace(buffer.data[tokenizer.pos]))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.end = tk.pos;
|
token.end = tokenizer.pos;
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto n = tk.first; !Nil(n); n = Next(n))
|
for(auto n = tokenizer.first; !Nil(n); n = Next(n))
|
||||||
{
|
{
|
||||||
Token* prev = Prev(n);
|
Token* prev = Prev(n);
|
||||||
Token* next = Next(n);
|
Token* next = Next(n);
|
||||||
|
|
||||||
if(CheckFuncOrTemplateSig(fb, n))
|
if(CheckFuncOrTemplateSig(n))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -688,7 +686,7 @@ TokenizeD(FlatBuffer* fb)
|
|||||||
else if(prev.type == TT.TypeKeyword && n.type == TT.Identifier)
|
else if(prev.type == TT.TypeKeyword && n.type == TT.Identifier)
|
||||||
{
|
{
|
||||||
n.type = TT.Type;
|
n.type = TT.Type;
|
||||||
CheckTypeDeclaration(fb, n);
|
CheckTypeDeclaration(n);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(prev.type == TT.EnumKeyword && n.type == TT.Identifier)
|
else if(prev.type == TT.EnumKeyword && n.type == TT.Identifier)
|
||||||
@ -715,9 +713,9 @@ TokenizeD(FlatBuffer* fb)
|
|||||||
CheckVarDeclaration(n);
|
CheckVarDeclaration(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto token = tk.first; !Nil(token); token = token.next)
|
for(auto token = tokenizer.first; !Nil(token); token = token.next)
|
||||||
{
|
{
|
||||||
tk.tokens[token.start .. token.end] = TOKEN_STYLES[token.type];
|
tokenizer.tokens[token.start .. token.end] = TOKEN_STYLES[token.type];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,20 +765,20 @@ CheckVarDeclaration(Token* token)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CheckTypeDeclaration(FlatBuffer* fb, Token* token)
|
CheckTypeDeclaration(Token* token)
|
||||||
{
|
{
|
||||||
for(Token* tk = Next(token); !Nil(tk) && tk.type != TT.RightBrace; tk = Next(tk))
|
for(Token* next_token = Next(token); !Nil(next_token) && next_token.type != TT.RightBrace; next_token = Next(next_token))
|
||||||
{
|
{
|
||||||
Token* prev = Prev(tk);
|
Token* prev = Prev(next_token);
|
||||||
if(prev.type == TT.LeftBrace || prev.type == TT.Semicolon)
|
if(prev.type == TT.LeftBrace || prev.type == TT.Semicolon)
|
||||||
{
|
{
|
||||||
tk.type = TT.Type;
|
next_token.type = TT.Type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CheckFuncOrTemplateSig(FlatBuffer* fb, Token* token)
|
CheckFuncOrTemplateSig(Token* token)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
@ -825,18 +823,18 @@ CheckFuncOrTemplateSig(FlatBuffer* fb, Token* token)
|
|||||||
}
|
}
|
||||||
|
|
||||||
u8[]
|
u8[]
|
||||||
TokenStr(FlatBuffer* fb, Token* t)
|
TokenStr(Editor* editor, Token* token)
|
||||||
{
|
{
|
||||||
return fb.data[t.start .. t.end];
|
return editor.data[token.start .. token.end];
|
||||||
}
|
}
|
||||||
|
|
||||||
Token*
|
Token*
|
||||||
Prev(types...)(Token* t)
|
Prev(types...)(Token* token)
|
||||||
{
|
{
|
||||||
Token* res = g_NIL_TOKEN;
|
Token* res = g_NIL_TOKEN;
|
||||||
|
|
||||||
PrevMain:
|
PrevMain:
|
||||||
for(auto p = t.prev; !Nil(p); p = p.prev)
|
for(auto p = token.prev; !Nil(p); p = p.prev)
|
||||||
{
|
{
|
||||||
if(p.type == TT.NewLine || p.type == TT.Whitespace || p.type == TT.Comment)
|
if(p.type == TT.NewLine || p.type == TT.Whitespace || p.type == TT.Comment)
|
||||||
{
|
{
|
||||||
@ -865,12 +863,12 @@ PrevMain:
|
|||||||
alias PrevFnToken = Prev!(TT.Identifier, TT.LeftParen, TT.RightParen, TT.Comma, TT.Keyword, TT.Dot, TT.Exclamation, TT.Type);
|
alias PrevFnToken = Prev!(TT.Identifier, TT.LeftParen, TT.RightParen, TT.Comma, TT.Keyword, TT.Dot, TT.Exclamation, TT.Type);
|
||||||
|
|
||||||
Token*
|
Token*
|
||||||
Next(types...)(Token* t)
|
Next(types...)(Token* token)
|
||||||
{
|
{
|
||||||
Token* res = g_NIL_TOKEN;
|
Token* res = g_NIL_TOKEN;
|
||||||
|
|
||||||
NextMain:
|
NextMain:
|
||||||
for(auto n = t.next; !Nil(n); n = n.next)
|
for(auto n = token.next; !Nil(n); n = n.next)
|
||||||
{
|
{
|
||||||
if(n.type == TT.NewLine || n.type == TT.Whitespace || n.type == TT.Comment)
|
if(n.type == TT.NewLine || n.type == TT.Whitespace || n.type == TT.Comment)
|
||||||
{
|
{
|
||||||
@ -899,20 +897,20 @@ NextMain:
|
|||||||
alias NextFnToken = Next!(TT.Identifier, TT.LeftParen, TT.RightParen, TT.Comma, TT.Keyword, TT.Dot, TT.Exclamation, TT.Type);
|
alias NextFnToken = Next!(TT.Identifier, TT.LeftParen, TT.RightParen, TT.Comma, TT.Keyword, TT.Dot, TT.Exclamation, TT.Type);
|
||||||
|
|
||||||
void
|
void
|
||||||
ParseNum(FlatBuffer* fb)
|
ParseNum(T)(T* buffer) if(is(T == Editor) || is(T == FlatBuffer))
|
||||||
{
|
{
|
||||||
Tokenizer* tk = &fb.tk;
|
Tokenizer* tokenizer = &buffer.tokenizer;
|
||||||
|
|
||||||
Token* t = Alloc!(Token)(&tk.arena);
|
Token* token = Alloc!(Token)(&tokenizer.arena);
|
||||||
t.type = TT.Number;
|
token.type = TT.Number;
|
||||||
t.start = tk.pos;
|
token.start = tokenizer.pos;
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
while (tk.pos < fb.length)
|
while (tokenizer.pos < buffer.length)
|
||||||
{
|
{
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
|
|
||||||
u8 ch = fb.data[tk.pos];
|
u8 ch = buffer.data[tokenizer.pos];
|
||||||
|
|
||||||
if(ch != '_' && ch != '.' && !(ch >= '0' && ch <= '9') && ch != 'x' && ch != 'X' && !((ch == '-' || ch == '+') && first))
|
if(ch != '_' && ch != '.' && !(ch >= '0' && ch <= '9') && ch != 'x' && ch != 'X' && !((ch == '-' || ch == '+') && first))
|
||||||
{
|
{
|
||||||
@ -922,76 +920,76 @@ ParseNum(FlatBuffer* fb)
|
|||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (tk.pos < fb.length)
|
while (tokenizer.pos < buffer.length)
|
||||||
{
|
{
|
||||||
u8 ch = fb.data[tk.pos];
|
u8 ch = buffer.data[tokenizer.pos];
|
||||||
if(ch != 'l' && ch != 'u' && ch != 'U' && ch != 'L' && ch != 'f' && ch != 'F')
|
if(ch != 'l' && ch != 'u' && ch != 'U' && ch != 'L' && ch != 'f' && ch != 'F')
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
t.end = tk.pos;
|
token.end = tokenizer.pos;
|
||||||
|
|
||||||
DLLPush(tk, t, g_NIL_TOKEN);
|
DLLPush(tokenizer, token, g_NIL_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ParseStr(u8 str_ch)(FlatBuffer* fb)
|
ParseStr(u8 str_ch, T)(T* buffer) if(is(T == Editor) || is(T == FlatBuffer))
|
||||||
{
|
{
|
||||||
static assert(str_ch == '`' || str_ch == '\'' || str_ch == '"');
|
static assert(str_ch == '`' || str_ch == '\'' || str_ch == '"');
|
||||||
|
|
||||||
Tokenizer* tk = &fb.tk;
|
Tokenizer* tokenizer = &buffer.tokenizer;
|
||||||
|
|
||||||
Token* t = Alloc!(Token)(&tk.arena);
|
Token* token = Alloc!(Token)(&tokenizer.arena);
|
||||||
|
|
||||||
t.type = D_STR_TOKEN[str_ch];
|
token.type = D_STR_TOKEN[str_ch];
|
||||||
t.start = tk.pos;
|
token.start = tokenizer.pos;
|
||||||
|
|
||||||
static if(str_ch == '`') tk.pos += 1;
|
static if(str_ch == '`') tokenizer.pos += 1;
|
||||||
|
|
||||||
bool ignore = str_ch != '`';
|
bool ignore = str_ch != '`';
|
||||||
for(; (fb.data[tk.pos] != str_ch || ignore) && tk.pos < fb.length; tk.pos += 1)
|
for(; (buffer.data[tokenizer.pos] != str_ch || ignore) && tokenizer.pos < buffer.length; tokenizer.pos += 1)
|
||||||
{
|
{
|
||||||
static if(str_ch != '`') ignore = fb.data[tk.pos] == '\\';
|
static if(str_ch != '`') ignore = buffer.data[tokenizer.pos] == '\\';
|
||||||
}
|
}
|
||||||
|
|
||||||
tk.pos += 1;
|
tokenizer.pos += 1;
|
||||||
t.end = tk.pos;
|
token.end = tokenizer.pos;
|
||||||
|
|
||||||
DLLPush(tk, t, g_NIL_TOKEN);
|
DLLPush(tokenizer, token, g_NIL_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ParseId(FlatBuffer* fb)
|
ParseId(T)(T* buffer) if(is(T == Editor) || is(T == FlatBuffer))
|
||||||
{
|
{
|
||||||
Tokenizer* tk = &fb.tk;
|
Tokenizer* tokenizer = &buffer.tokenizer;
|
||||||
Token* t = MakeToken(tk, TT.Identifier, tk.pos, tk.pos+1);
|
Token* token = MakeToken(tokenizer, TT.Identifier, 1);
|
||||||
|
|
||||||
for(; tk.pos < fb.length; tk.pos += 1)
|
for(; tokenizer.pos < buffer.length; tokenizer.pos += 1)
|
||||||
{
|
{
|
||||||
u8 ch = fb.data[tk.pos];
|
u8 ch = buffer.data[tokenizer.pos];
|
||||||
|
|
||||||
if(!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') && ch != '.' && ch != '_' && !(ch >= '0' && ch <= '9'))
|
if(!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') && ch != '.' && ch != '_' && !(ch >= '0' && ch <= '9'))
|
||||||
{
|
{
|
||||||
t.end = tk.pos;
|
token.end = tokenizer.pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 ch = fb.data[t.start];
|
u8 ch = buffer.data[token.start];
|
||||||
if(ch < D_KEYWORDS.length && D_KEYWORDS[ch] != null && D_KEYWORDS[ch].length > 0)
|
if(ch < D_KEYWORDS.length && D_KEYWORDS[ch] != null && D_KEYWORDS[ch].length > 0)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
u8[] id = fb.data[t.start .. t.end];
|
u8[] id = buffer.data[token.start .. token.end];
|
||||||
|
|
||||||
foreach(ref k; D_TYPES[ch])
|
foreach(ref k; D_TYPES[ch])
|
||||||
{
|
{
|
||||||
if(id == k)
|
if(id == k)
|
||||||
{
|
{
|
||||||
t.type = TT.Type;
|
token.type = TT.Type;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1005,19 +1003,19 @@ ParseId(FlatBuffer* fb)
|
|||||||
{
|
{
|
||||||
if(k == r"import")
|
if(k == r"import")
|
||||||
{
|
{
|
||||||
t.type = TT.Import;
|
token.type = TT.Import;
|
||||||
}
|
}
|
||||||
else if(k == r"class" || k == r"struct")
|
else if(k == r"class" || k == r"struct")
|
||||||
{
|
{
|
||||||
t.type = TT.TypeKeyword;
|
token.type = TT.TypeKeyword;
|
||||||
}
|
}
|
||||||
else if(k == r"enum")
|
else if(k == r"enum")
|
||||||
{
|
{
|
||||||
t.type = TT.EnumKeyword;
|
token.type = TT.EnumKeyword;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t.type = TT.Keyword;
|
token.type = TT.Keyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -1025,15 +1023,15 @@ ParseId(FlatBuffer* fb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(t.start < t.end, "ParseId failure: start is lower or equal to end");
|
assert(token.start < token.end, "ParseId failure: start is lower or equal to end");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FixOpAssign(FlatBuffer* fb, Token* t)
|
FixOpAssign(T)(T* buffer, Token* token) if(is(T == Editor) || is(T == FlatBuffer))
|
||||||
{
|
{
|
||||||
if(t.end+1 < fb.length)
|
if(token.end+1 < buffer.length)
|
||||||
{
|
{
|
||||||
u8[] str = fb.data[t.start .. t.end+1];
|
u8[] str = buffer.data[token.start .. token.end+1];
|
||||||
if(
|
if(
|
||||||
str == "/=" ||
|
str == "/=" ||
|
||||||
str == "+=" ||
|
str == "+=" ||
|
||||||
@ -1044,8 +1042,8 @@ FixOpAssign(FlatBuffer* fb, Token* t)
|
|||||||
str == "!="
|
str == "!="
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
fb.tk.pos += 1;
|
buffer.tokenizer.pos += 1;
|
||||||
t.end += 1;
|
token.end += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1072,11 +1070,11 @@ CheckWhiteSpace(u8 ch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SkipWhiteSpace(FlatBuffer* fb)
|
SkipWhiteSpace(Editor* editor)
|
||||||
{
|
{
|
||||||
while (fb.tk.pos < fb.length)
|
while (editor.tokenizer.pos < editor.length)
|
||||||
{
|
{
|
||||||
u8 ch = fb.data[fb.tk.pos];
|
u8 ch = editor.data[editor.tokenizer.pos];
|
||||||
|
|
||||||
bool white_space = CheckWhiteSpace(ch);
|
bool white_space = CheckWhiteSpace(ch);
|
||||||
|
|
||||||
@ -1085,7 +1083,7 @@ SkipWhiteSpace(FlatBuffer* fb)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fb.tk.pos += 1;
|
editor.tokenizer.pos += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
276
src/editor/ui.d
276
src/editor/ui.d
@ -1,6 +1,7 @@
|
|||||||
import dlib;
|
import dlib;
|
||||||
import dlib.util : HTPush = Push;
|
import dlib.util : HTPush = Push;
|
||||||
import dlib.math : Clamp;
|
import dlib.math : Clamp;
|
||||||
|
import dlib.alloc : Reset;
|
||||||
|
|
||||||
import vulkan;
|
import vulkan;
|
||||||
import vulkan : RendererGetExtent = GetExtent;
|
import vulkan : RendererGetExtent = GetExtent;
|
||||||
@ -322,10 +323,27 @@ Attribute[10] attributes = [
|
|||||||
{ binding: 0, location: 9, format: FMT.R_U32, offset: Vertex.has_texture.offsetof },
|
{ binding: 0, location: 9, format: FMT.R_U32, offset: Vertex.has_texture.offsetof },
|
||||||
];
|
];
|
||||||
|
|
||||||
union Rect
|
struct Rect
|
||||||
|
{
|
||||||
|
union
|
||||||
{
|
{
|
||||||
Vec2[2] v;
|
Vec2[2] v;
|
||||||
struct { Vec2 p0, p1; alias p0 pos; };
|
struct
|
||||||
|
{
|
||||||
|
Vec2 p0, p1;
|
||||||
|
alias p0 pos;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ref Vec2 opIndex(usize index)
|
||||||
|
{
|
||||||
|
return this.v[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
ref Vec2 opIndexAssign(usize index, Vec2 value)
|
||||||
|
{
|
||||||
|
return this.v[index] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
alias UIHash = u64;
|
alias UIHash = u64;
|
||||||
@ -341,53 +359,11 @@ struct UIKey
|
|||||||
bool opCast(T)() if(is(T == bool)) => this.hash != 0;
|
bool opCast(T)() if(is(T == bool)) => this.hash != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
"atlas": {
|
|
||||||
"type": "mtsdf",
|
|
||||||
"distanceRange": 2,
|
|
||||||
"distanceRangeMiddle": 0,
|
|
||||||
"size": 32.5,
|
|
||||||
"width": 216,
|
|
||||||
"height": 216,
|
|
||||||
"yOrigin": "bottom"
|
|
||||||
},
|
|
||||||
"metrics": {
|
|
||||||
"emSize": 1,
|
|
||||||
"lineHeight": 1.3200000000000001,
|
|
||||||
"ascender": 1.02,
|
|
||||||
"descender": -0.29999999999999999,
|
|
||||||
"underlineY": -0.17999999999999999,
|
|
||||||
"underlineThickness": 0.050000000000000003
|
|
||||||
},
|
|
||||||
"glyphs": [
|
|
||||||
{
|
|
||||||
"unicode": 32,
|
|
||||||
"advance": 0.59999999999999998
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"unicode": 33,
|
|
||||||
"advance": 0.59999999999999998,
|
|
||||||
"planeBounds": {
|
|
||||||
"left": 0.19230769230769232,
|
|
||||||
"bottom": -0.046153846153846149,
|
|
||||||
"right": 0.40769230769230769,
|
|
||||||
"top": 0.78461538461538449
|
|
||||||
},
|
|
||||||
"atlasBounds": {
|
|
||||||
"left": 19.5,
|
|
||||||
"bottom": 151.5,
|
|
||||||
"right": 26.5,
|
|
||||||
"top": 178.5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum bool KeyType(T) = (StringType!(T) || is(T == UIKey) || is(T == const(UIKey)));
|
enum bool KeyType(T) = (StringType!(T) || is(T == UIKey) || is(T == const(UIKey)));
|
||||||
enum bool ItemAndKeyType(T) = (KeyType!(T) || is(T == UIItem*));
|
enum bool ItemAndKeyType(T) = (KeyType!(T) || is(T == UIItem*));
|
||||||
|
|
||||||
void
|
void
|
||||||
InitUI(Ctx* ctx)
|
InitUI(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
version(ENABLE_RENDERER)
|
version(ENABLE_RENDERER)
|
||||||
{
|
{
|
||||||
@ -445,11 +421,6 @@ InitUI(Ctx* ctx)
|
|||||||
ctx.buffers[i].idx[0 .. $] = [0, 1, 2, 2, 1, 3];
|
ctx.buffers[i].idx[0 .. $] = [0, 1, 2, 2, 1, 3];
|
||||||
ctx.desc_sets[i] = AllocDescSet(ctx.desc_set_layout);
|
ctx.desc_sets[i] = AllocDescSet(ctx.desc_set_layout);
|
||||||
ctx.str_arenas[i] = CreateArena(MB(1));
|
ctx.str_arenas[i] = CreateArena(MB(1));
|
||||||
|
|
||||||
ctx.slug_vertex_buffers[i] = CreateMappedBuffer!(SlugVertex)(BT.Vertex, 1000);
|
|
||||||
ctx.slug_index_buffers[i] = CreateMappedBuffer!(u32)(BT.Index, 1000);
|
|
||||||
ctx.slug_buffers[i].vertices = ctx.slug_vertex_buffers[i].data;
|
|
||||||
ctx.slug_buffers[i].indices = ctx.slug_index_buffers[i].data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GfxPipelineInfo ui_info = {
|
GfxPipelineInfo ui_info = {
|
||||||
@ -551,15 +522,15 @@ PushFree(string next_member = "free_next", T)(T** top, T* node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
f32
|
f32
|
||||||
GetLineHeight(u32 size)
|
GetLineHeight(u32 size) => GetFontSet(size).line_height;
|
||||||
{
|
|
||||||
return GetFontSet(size).line_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
FontSet*
|
FontSet*
|
||||||
GetFontSet(u32 size)
|
GetFontSet(T)(T font_set) if(is(T == FontSet*)) => font_set;
|
||||||
|
|
||||||
|
FontSet*
|
||||||
|
GetFontSet(T)(T size) if(is(T: u32))
|
||||||
{
|
{
|
||||||
Ctx* ctx = GetCtx();
|
ref Ctx ctx = GetCtx();
|
||||||
|
|
||||||
FontSet* fs = null;
|
FontSet* fs = null;
|
||||||
for(u64 i = 0; i < ctx.font_sets_used; i += 1)
|
for(u64 i = 0; i < ctx.font_sets_used; i += 1)
|
||||||
@ -590,30 +561,30 @@ GetFontSet(u32 size)
|
|||||||
void
|
void
|
||||||
LoadFontSet()
|
LoadFontSet()
|
||||||
{
|
{
|
||||||
Ctx* ctx = GetCtx();
|
ref Ctx ctx = GetCtx();
|
||||||
u64 fi = ctx.f_idx;
|
|
||||||
|
|
||||||
for(u64 i = 0; i < ctx.font_sets_used; i += 1)
|
for(u64 i = 0; i < ctx.font_sets_used; i += 1)
|
||||||
{
|
{
|
||||||
FontSet* fs = ctx.font_sets.ptr + i;
|
FontSet* fs = ctx.font_sets.ptr + i;
|
||||||
|
ref bool descriptor_written = fs.descriptor_written[ctx.frame_index];
|
||||||
if(!fs.texture_loaded)
|
if(!fs.texture_loaded)
|
||||||
{
|
{
|
||||||
Transfer!(true)(&ctx.font_descs[i], fs.atlas.data);
|
Transfer!(true)(&ctx.font_descs[i], fs.atlas.data);
|
||||||
fs.texture_loaded = true;
|
fs.texture_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!fs.descriptor_written[fi])
|
if(!descriptor_written)
|
||||||
{
|
{
|
||||||
Write(ctx.desc_sets[fi], ctx.font_descs);
|
Write(ctx.desc_set, ctx.font_descs);
|
||||||
fs.descriptor_written[fi] = true;
|
descriptor_written = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.fonts_to_load[fi] = false;
|
ctx.fonts_to_load[ctx.frame_index] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Scissor(Ctx* ctx, Rect rect, Style* style)
|
Scissor(ref Ctx ctx, Rect rect, Style* style)
|
||||||
{
|
{
|
||||||
DrawUI(ctx);
|
DrawUI(ctx);
|
||||||
|
|
||||||
@ -630,14 +601,14 @@ Scissor(Ctx* ctx, Rect rect, Style* style)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EndScissor(Ctx* ctx)
|
EndScissor(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
DrawUI(ctx);
|
DrawUI(ctx);
|
||||||
ResetScissor();
|
ResetScissor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Panel(Ctx* ctx, UIPanel* panel)
|
Panel(ref Ctx ctx, UIPanel* panel)
|
||||||
{
|
{
|
||||||
panel.item = MakeItem!(PANEL_FLAGS)("###panel_%s", panel.id);
|
panel.item = MakeItem!(PANEL_FLAGS)("###panel_%s", panel.id);
|
||||||
Axis2D p_axis = Nil(panel.parent) ? A2D.X : panel.parent.axis;
|
Axis2D p_axis = Nil(panel.parent) ? A2D.X : panel.parent.axis;
|
||||||
@ -682,16 +653,16 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
panel.move_text_with_cursor = false;
|
panel.move_text_with_cursor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.scroll_target.y = cast(f32)(panel.ed.line_offset)*fs.line_height;
|
panel.scroll_target.y = cast(f32)(panel.ed.view_info.line_offset)*fs.line_height;
|
||||||
|
|
||||||
f32 max_px = panel.ed.buf.line_count*fs.line_height;
|
f32 max_px = panel.ed.line_count*fs.line_height;
|
||||||
f32 offset = -(panel.item.scroll_offset.y%fs.line_height);
|
f32 offset = -(panel.item.scroll_offset.y%fs.line_height);
|
||||||
u64 start_ln = cast(u64)(floor(panel.scroll_offset.y/fs.line_height));
|
u64 start_ln = cast(u64)(floor(panel.scroll_offset.y/fs.line_height));
|
||||||
const f32 PAD = 4.0f;
|
const f32 PAD = 4.0f;
|
||||||
|
|
||||||
// Line counter
|
// Line counter
|
||||||
|
|
||||||
u64 lc_chars = panel.ed.buf.line_count.toChars().length;
|
u64 lc_chars = panel.ed.line_count.toChars().length;
|
||||||
f32 lc_width = PAD*2.0 + cast(f32)(lc_chars)*fs.max_advance;
|
f32 lc_width = PAD*2.0 + cast(f32)(lc_chars)*fs.max_advance;
|
||||||
|
|
||||||
Style style = PANEL_STYLE;
|
Style style = PANEL_STYLE;
|
||||||
@ -709,7 +680,7 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
|
|
||||||
f32 panel_height = Size!(A2D.Y)(line_count_rect);
|
f32 panel_height = Size!(A2D.Y)(line_count_rect);
|
||||||
panel.ed.line_height = cast(i64)ceil(panel_height/fs.line_height);
|
panel.ed.line_height = cast(i64)ceil(panel_height/fs.line_height);
|
||||||
u64 max_ln = Min(panel.ed.line_height + start_ln, panel.ed.buf.line_count);
|
u64 max_ln = Min(panel.ed.line_height + start_ln, panel.ed.line_count);
|
||||||
|
|
||||||
for(u64 i = start_ln; i < max_ln; i += 1)
|
for(u64 i = start_ln; i < max_ln; i += 1)
|
||||||
{
|
{
|
||||||
@ -729,12 +700,12 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
|
|
||||||
text_rect = Pad(text_view_rect, PAD);
|
text_rect = Pad(text_view_rect, PAD);
|
||||||
|
|
||||||
I64Vec2 cursor_coords = VecPos(&panel.ed.buf);
|
I64Vec2 cursor_coords = VecPos(panel.ed);
|
||||||
LineBuffer* current_lbuf = GetLine(&panel.ed.buf, cursor_coords.y);
|
LineBuffer* current_lbuf = GetLine(panel.ed, cursor_coords.y);
|
||||||
UIItem* cursor = MakeItem("###cursor_%s", panel.id);
|
UIItem* cursor = MakeItem("###cursor_%s", panel.id);
|
||||||
if(ctx.focused_panel == panel)
|
if(ctx.focused_panel == panel)
|
||||||
{
|
{
|
||||||
i64 y_pos = cursor_coords.y - panel.ed.line_offset;
|
i64 y_pos = cursor_coords.y - panel.ed.view_info.line_offset;
|
||||||
|
|
||||||
cursor.size.x = Active(ES.InputMode) ? 2.0 : fs.max_advance;
|
cursor.size.x = Active(ES.InputMode) ? 2.0 : fs.max_advance;
|
||||||
cursor.size.y = fs.line_height;
|
cursor.size.y = fs.line_height;
|
||||||
@ -760,7 +731,7 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
{
|
{
|
||||||
if(Active(ES.InputMode) && panel.move_text_with_cursor)
|
if(Active(ES.InputMode) && panel.move_text_with_cursor)
|
||||||
{
|
{
|
||||||
for(LineBuffer* lbuf = GetLine(&panel.ed.buf, i); i < max_ln && !CheckNil(g_NIL_LINE_BUF, lbuf); lbuf = GetLine(&panel.ed.buf, ++i))
|
for(LineBuffer* lbuf = GetLine(panel.ed, i); i < max_ln && !CheckNil(g_NIL_LINE_BUF, lbuf); lbuf = GetLine(panel.ed, ++i))
|
||||||
{
|
{
|
||||||
if(i == cursor_coords.y)
|
if(i == cursor_coords.y)
|
||||||
{
|
{
|
||||||
@ -799,7 +770,7 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
DrawLines(ctx, panel, start_ln, max_ln, text_rect, fs);
|
DrawLines(ctx, panel, start_ln, max_ln, text_rect, fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetBuffer(&panel.ed.buf);
|
ResetBuffer(panel.ed);
|
||||||
|
|
||||||
EndScissor(ctx);
|
EndScissor(ctx);
|
||||||
DrawBorder(ctx, text_view_rect, &style);
|
DrawBorder(ctx, text_view_rect, &style);
|
||||||
@ -844,10 +815,10 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawLines(bool hl = false)(Ctx* ctx, UIPanel* panel, u64 start_line, u64 end_line, Rect text_rect, FontSet* fs, I64Vec2 cursor_coords = I64Vec2(-1))
|
DrawLines(bool hl = false)(ref Ctx ctx, UIPanel* panel, u64 start_line, u64 end_line, Rect text_rect, FontSet* fs, I64Vec2 cursor_coords = I64Vec2(-1))
|
||||||
{
|
{
|
||||||
u64 i = start_line;
|
u64 i = start_line;
|
||||||
for(LineBuffer* lbuf = GetLine(&panel.ed.buf, i); i < end_line && !CheckNil(g_NIL_LINE_BUF, lbuf); lbuf = GetLine(&panel.ed.buf, ++i))
|
for(LineBuffer* lbuf = GetLine(panel.ed, i); i < end_line && !CheckNil(g_NIL_LINE_BUF, lbuf); lbuf = GetLine(panel.ed, ++i))
|
||||||
{
|
{
|
||||||
static if(hl)
|
static if(hl)
|
||||||
{
|
{
|
||||||
@ -873,7 +844,7 @@ struct SearchWindowCtx(T)
|
|||||||
void
|
void
|
||||||
SearchInputWindow(T)(string hash_text, SearchWindowCtx!(T)* window_ctx, bool ready_cond) if(is(T == Command) || is(T == string))
|
SearchInputWindow(T)(string hash_text, SearchWindowCtx!(T)* window_ctx, bool ready_cond) if(is(T == Command) || is(T == string))
|
||||||
{
|
{
|
||||||
Ctx* ctx = GetCtx();
|
ref Ctx ctx = GetCtx();
|
||||||
Vec2 extent = GetExtent();
|
Vec2 extent = GetExtent();
|
||||||
f32 x = extent.x * 0.1;
|
f32 x = extent.x * 0.1;
|
||||||
f32 y = extent.y * 0.2;
|
f32 y = extent.y * 0.2;
|
||||||
@ -955,7 +926,7 @@ SearchInputWindow(T)(string hash_text, SearchWindowCtx!(T)* window_ctx, bool rea
|
|||||||
Rect opt_rect = inner_rect;
|
Rect opt_rect = inner_rect;
|
||||||
opt_rect.p0.y -= opt_start_offset;
|
opt_rect.p0.y -= opt_start_offset;
|
||||||
|
|
||||||
UIItem* selected_opt_item = g_UI_NIL;
|
UIItem* selected_opt_item = g_UI_NIL_ITEM;
|
||||||
if(start_opt_index < options.length) foreach(i; start_opt_index .. options.length)
|
if(start_opt_index < options.length) foreach(i; start_opt_index .. options.length)
|
||||||
{
|
{
|
||||||
Rect[2] opt_rects = Split(opt_rect, full_opt_height, A2D.Y);
|
Rect[2] opt_rects = Split(opt_rect, full_opt_height, A2D.Y);
|
||||||
@ -1058,7 +1029,7 @@ SearchInputWindow(T)(string hash_text, SearchWindowCtx!(T)* window_ctx, bool rea
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SaveFileWindow(Ctx* ctx)
|
SaveFileWindow(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
bool exit;
|
bool exit;
|
||||||
Editor* ed = ctx.focused_panel.ed;
|
Editor* ed = ctx.focused_panel.ed;
|
||||||
@ -1068,7 +1039,6 @@ SaveFileWindow(Ctx* ctx)
|
|||||||
{
|
{
|
||||||
ctx.cmd.exec_cmd_input.data[0 .. ed.file_name.length] = Arr!(u8)(ed.file_name[0 .. $]);
|
ctx.cmd.exec_cmd_input.data[0 .. ed.file_name.length] = Arr!(u8)(ed.file_name[0 .. $]);
|
||||||
ctx.cmd.exec_cmd_input.length = ed.file_name.length;
|
ctx.cmd.exec_cmd_input.length = ed.file_name.length;
|
||||||
init = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PAD = 4.0f;
|
const PAD = 4.0f;
|
||||||
@ -1133,19 +1103,16 @@ SaveFileWindow(Ctx* ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(exit)
|
init = !exit;
|
||||||
{
|
|
||||||
init = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return exit;
|
return exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
OpenFileWindow(Ctx* ctx)
|
OpenFileWindow(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
bool exit;
|
bool exit;
|
||||||
CmdPalette* cmd = &ctx.cmd;
|
ref CmdPalette cmd = ctx.cmd;
|
||||||
|
|
||||||
if(!cmd.exec_cmd_opts.length && !cmd.exec_cmd_input.length)
|
if(!cmd.exec_cmd_opts.length && !cmd.exec_cmd_input.length)
|
||||||
{
|
{
|
||||||
@ -1218,9 +1185,9 @@ OpenFileWindow(Ctx* ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CommandPalette(Ctx* ctx)
|
CommandPalette(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
CmdPalette* cmd = &ctx.cmd;
|
ref CmdPalette cmd = ctx.cmd;
|
||||||
|
|
||||||
bool enter_hit, buffer_changed, selection_changed;
|
bool enter_hit, buffer_changed, selection_changed;
|
||||||
if(ctx.state == ES.CmdPalette)
|
if(ctx.state == ES.CmdPalette)
|
||||||
@ -1417,15 +1384,9 @@ CreatePanel(Editor* ed = null)
|
|||||||
{
|
{
|
||||||
bool allocated;
|
bool allocated;
|
||||||
p = GetOrAlloc(&g_ctx.arena, &g_ctx.free_panels, g_NIL_PANEL, &allocated);
|
p = GetOrAlloc(&g_ctx.arena, &g_ctx.free_panels, g_NIL_PANEL, &allocated);
|
||||||
if(allocated)
|
|
||||||
{
|
|
||||||
p.id = panel_id++;
|
p.id = panel_id++;
|
||||||
}
|
|
||||||
if(!p.ed)
|
|
||||||
{
|
|
||||||
p.ed = CreateEditor();
|
p.ed = CreateEditor();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
p.item = MakeItem!(PANEL_FLAGS)("###panel_%s", p.id);
|
p.item = MakeItem!(PANEL_FLAGS)("###panel_%s", p.id);
|
||||||
p.pct = 1.0;
|
p.pct = 1.0;
|
||||||
@ -1500,7 +1461,7 @@ Hovered(bool current_frame, T, U)(T param, U* ptr, U index)
|
|||||||
bool
|
bool
|
||||||
Hovered(bool current_frame, T)(T param)
|
Hovered(bool current_frame, T)(T param)
|
||||||
{
|
{
|
||||||
Ctx* ctx = GetCtx();
|
ref Ctx ctx = GetCtx();
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
UIKey key = mixin(AssignKey!(T, param));
|
UIKey key = mixin(AssignKey!(T, param));
|
||||||
@ -1521,7 +1482,7 @@ Hovered(bool current_frame, T)(T param)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PushUIEvent(Ctx* ctx, UIInput input)
|
PushUIEvent(ref Ctx ctx, UIInput input)
|
||||||
{
|
{
|
||||||
UIInput* ev = Alloc!(UIInput)(&ctx.temp_arena);
|
UIInput* ev = Alloc!(UIInput)(&ctx.temp_arena);
|
||||||
*ev = input;
|
*ev = input;
|
||||||
@ -1530,7 +1491,7 @@ PushUIEvent(Ctx* ctx, UIInput input)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawUI(Ctx* ctx, u32 atlas_index)
|
DrawUI(ref Ctx ctx, u32 atlas_index)
|
||||||
{
|
{
|
||||||
if(ctx.pc.atlas_index != atlas_index)
|
if(ctx.pc.atlas_index != atlas_index)
|
||||||
{
|
{
|
||||||
@ -1541,33 +1502,17 @@ DrawUI(Ctx* ctx, u32 atlas_index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawSlug(Ctx* ctx)
|
DrawUI(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
version(ENABLE_RENDERER)
|
version(ENABLE_RENDERER)
|
||||||
{
|
{
|
||||||
// TODO: fix this
|
ref UIBuffer buffer = ctx.buffers[ctx.frame_index];
|
||||||
SlugBuffer* buffer = ctx.slug_buffers.ptr + ctx.f_idx;
|
if(buffer.vtx_offset != buffer.count)
|
||||||
|
|
||||||
auto vertex_buffer = ctx.slug_vertex_buffers.ptr + ctx.f_idx;
|
|
||||||
auto index_buffer = ctx.slug_index_buffers.ptr + ctx.f_idx;
|
|
||||||
|
|
||||||
BindBuffers(index_buffer, vertex_buffer);
|
|
||||||
DrawIndexed(buffer.quad_offset*6, 1, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DrawUI(Ctx* ctx)
|
|
||||||
{
|
{
|
||||||
version(ENABLE_RENDERER)
|
u32 count = buffer.count - buffer.vtx_offset;
|
||||||
{
|
BindBuffers(&buffer.m_idx, &buffer.m_vtx);
|
||||||
UIBuffer* b = ctx.buffers.ptr + ctx.f_idx;
|
DrawIndexed(6, count, 0, 0, buffer.vtx_offset);
|
||||||
if(b.vtx_offset != b.count)
|
buffer.vtx_offset += count;
|
||||||
{
|
|
||||||
u32 count = b.count - b.vtx_offset;
|
|
||||||
BindBuffers(&b.m_idx, &b.m_vtx);
|
|
||||||
DrawIndexed(6, count, 0, 0, b.vtx_offset);
|
|
||||||
b.vtx_offset += count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1575,10 +1520,10 @@ DrawUI(Ctx* ctx)
|
|||||||
void
|
void
|
||||||
BeginUI(Inputs* inputs)
|
BeginUI(Inputs* inputs)
|
||||||
{
|
{
|
||||||
Ctx* ctx = GetCtx();
|
ref Ctx ctx = GetCtx();
|
||||||
Arena* a = &ctx.temp_arena;
|
ref Arena arena = ctx.temp_arena;
|
||||||
|
|
||||||
Reset(a);
|
Reset(&arena);
|
||||||
|
|
||||||
// Convert Inputs
|
// Convert Inputs
|
||||||
ctx.events.first = ctx.events.last = null;
|
ctx.events.first = ctx.events.last = null;
|
||||||
@ -1687,11 +1632,11 @@ BeginUI(Inputs* inputs)
|
|||||||
|
|
||||||
// Ctx state
|
// Ctx state
|
||||||
ctx.frame = next_frame;
|
ctx.frame = next_frame;
|
||||||
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
|
ctx.frame_index = ctx.frame%FRAME_OVERLAP;
|
||||||
ctx.inputs = inputs;
|
ctx.inputs = inputs;
|
||||||
ctx.last_item = g_UI_NIL;
|
ctx.last_item = g_UI_NIL_ITEM;
|
||||||
|
|
||||||
Reset(&ctx.str_arenas[ctx.f_idx]);
|
Reset(&ctx.str_arenas[ctx.frame_index]);
|
||||||
|
|
||||||
assert(!mouse_moved || ZeroKey(ctx.hover_key) || (ctx.frame == ctx.last_hover_frame));
|
assert(!mouse_moved || ZeroKey(ctx.hover_key) || (ctx.frame == ctx.last_hover_frame));
|
||||||
|
|
||||||
@ -1704,7 +1649,7 @@ BeginUI(Inputs* inputs)
|
|||||||
{
|
{
|
||||||
BeginFrame();
|
BeginFrame();
|
||||||
|
|
||||||
if(ctx.fonts_to_load[ctx.f_idx])
|
if(ctx.fonts_to_load[ctx.frame_index])
|
||||||
{
|
{
|
||||||
LoadFontSet();
|
LoadFontSet();
|
||||||
}
|
}
|
||||||
@ -1714,22 +1659,19 @@ BeginUI(Inputs* inputs)
|
|||||||
SetStencilTest(false);
|
SetStencilTest(false);
|
||||||
|
|
||||||
PushConstants(ctx.pipeline, &ctx.pc);
|
PushConstants(ctx.pipeline, &ctx.pc);
|
||||||
Bind(ctx.pipeline, ctx.desc_sets[ctx.f_idx]);
|
Bind(ctx.pipeline, ctx.desc_sets[ctx.frame_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
UIBuffer* buffer = ctx.buffers.ptr + ctx.f_idx;
|
UIBuffer* buffer = ctx.buffers.ptr + ctx.frame_index;
|
||||||
SlugBuffer* slug_buffer = ctx.slug_buffers.ptr + ctx.f_idx;
|
|
||||||
|
|
||||||
memset(buffer.vtx.ptr, 0, Vertex.sizeof * buffer.count);
|
memset(buffer.vtx.ptr, 0, Vertex.sizeof * buffer.count);
|
||||||
memset(slug_buffer.vertices.ptr, 0, SlugVertex.sizeof * slug_buffer.quad_offset);
|
|
||||||
|
|
||||||
buffer.count = 0;
|
buffer.count = 0;
|
||||||
buffer.vtx_offset = 0;
|
buffer.vtx_offset = 0;
|
||||||
slug_buffer.quad_offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UIKey
|
UIKey
|
||||||
FindHoverKey(bool priority)(Ctx* ctx)
|
FindHoverKey(bool priority)(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
UIKey hovered;
|
UIKey hovered;
|
||||||
|
|
||||||
@ -1762,11 +1704,11 @@ FindHoverKey(bool priority)(Ctx* ctx)
|
|||||||
void
|
void
|
||||||
EndUI()
|
EndUI()
|
||||||
{
|
{
|
||||||
Ctx* ctx = GetCtx();
|
ref Ctx ctx = GetCtx();
|
||||||
|
|
||||||
if(ctx.dbg)
|
debug if(ctx.dbg)
|
||||||
{
|
{
|
||||||
const PAD = 4.0f;
|
const f32 PAD = 4.0f;
|
||||||
static FontSet* fs;
|
static FontSet* fs;
|
||||||
if(!fs)
|
if(!fs)
|
||||||
{
|
{
|
||||||
@ -1814,7 +1756,7 @@ SetNil(Args...)(Args args)
|
|||||||
{
|
{
|
||||||
static if(is(typeof(Args[i]) == UIItem**))
|
static if(is(typeof(Args[i]) == UIItem**))
|
||||||
{
|
{
|
||||||
*args[i] = g_UI_NIL;
|
*args[i] = g_UI_NIL_ITEM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1824,7 +1766,7 @@ SetNil(Args...)(Args args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Clamp(Ctx* ctx, Vertex* v)
|
Clamp(ref Ctx ctx, Vertex* v)
|
||||||
{
|
{
|
||||||
v.dst_start = Clamp(v.dst_start, Vec2(0.0), cast(Vec2)ctx.pc.resolution);
|
v.dst_start = Clamp(v.dst_start, Vec2(0.0), cast(Vec2)ctx.pc.resolution);
|
||||||
v.dst_end = Clamp(v.dst_end, Vec2(0.0), cast(Vec2)ctx.pc.resolution);
|
v.dst_end = Clamp(v.dst_end, Vec2(0.0), cast(Vec2)ctx.pc.resolution);
|
||||||
@ -1853,7 +1795,7 @@ UpdateState(f32* v, bool cond)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UpdateState(ISF flags)(Ctx* ctx, UIItem* item)
|
UpdateState(ISF flags)(ref Ctx ctx, UIItem* item)
|
||||||
{
|
{
|
||||||
static if(flags & ISF.Hot) UpdateState(&item.hot_t, cast(bool)(flags & ISF.SetHot) || Hovered!(true)(item));
|
static if(flags & ISF.Hot) UpdateState(&item.hot_t, cast(bool)(flags & ISF.SetHot) || Hovered!(true)(item));
|
||||||
static if(flags & ISF.Ready) UpdateState(&item.ready_t, cast(bool)(flags & ISF.SetReady));
|
static if(flags & ISF.Ready) UpdateState(&item.ready_t, cast(bool)(flags & ISF.SetReady));
|
||||||
@ -1892,7 +1834,7 @@ AnimateReady(Args...)(f32 ready, Args cols)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawDropShadow(Ctx* ctx, Rect rect, f32 ready_t = 1.0)
|
DrawDropShadow(ref Ctx ctx, Rect rect, f32 ready_t = 1.0)
|
||||||
{
|
{
|
||||||
Vec2 size = Vec2(rect.p1.x-rect.p0.x, rect.p1.y-rect.p0.y);
|
Vec2 size = Vec2(rect.p1.x-rect.p0.x, rect.p1.y-rect.p0.y);
|
||||||
|
|
||||||
@ -1911,7 +1853,7 @@ DrawDropShadow(Ctx* ctx, Rect rect, f32 ready_t = 1.0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawBorder(Ctx* ctx, Rect rect, Style* style, f32 hot_t = 0.0, f32 ready_t = 1.0)
|
DrawBorder(ref Ctx ctx, Rect rect, Style* style, f32 hot_t = 0.0, f32 ready_t = 1.0)
|
||||||
{
|
{
|
||||||
Vec4 col = style.border_col;
|
Vec4 col = style.border_col;
|
||||||
AnimateHot(hot_t, style.border_hl_col, &col);
|
AnimateHot(hot_t, style.border_hl_col, &col);
|
||||||
@ -1929,7 +1871,7 @@ DrawBorder(Ctx* ctx, Rect rect, Style* style, f32 hot_t = 0.0, f32 ready_t = 1.0
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawRect(Ctx* ctx, Rect rect, Style* style, f32 hot_t = 0.0f, f32 ready_t = 1.0f)
|
DrawRect(ref Ctx ctx, Rect rect, Style* style, f32 hot_t = 0.0f, f32 ready_t = 1.0f)
|
||||||
{
|
{
|
||||||
Vec4 col = style.col;
|
Vec4 col = style.col;
|
||||||
AnimateHot(hot_t, style.hl_col, &col);
|
AnimateHot(hot_t, style.hl_col, &col);
|
||||||
@ -1955,18 +1897,10 @@ enum TextAlign
|
|||||||
} alias TA = TextAlign;
|
} alias TA = TextAlign;
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawText(T, U, V)(Ctx* ctx, T text_param, U col_param, V text_size_param, Rect rect, TextAlign text_align, i64 hl_char = -1, f32 ready = 1.0)
|
DrawText(T, U, V)(ref Ctx ctx, T text_param, U col_param, V text_size_param, Rect rect, TextAlign text_align, i64 hl_char = -1, f32 ready = 1.0)
|
||||||
{
|
if(is(V: u32) || is(V == FontSet*))
|
||||||
static if(is(V == FontSet*))
|
|
||||||
{
|
|
||||||
FontSet* fs = text_size_param;
|
|
||||||
}
|
|
||||||
else if(is(V == u32))
|
|
||||||
{
|
{
|
||||||
FontSet* fs = GetFontSet(text_size_param);
|
FontSet* fs = GetFontSet(text_size_param);
|
||||||
}
|
|
||||||
else static assert(false, "invalid input parameter, V must be FontSet* or u32");
|
|
||||||
|
|
||||||
string text = Str(text_param);
|
string text = Str(text_param);
|
||||||
|
|
||||||
DrawUI(ctx, fs.index);
|
DrawUI(ctx, fs.index);
|
||||||
@ -2031,7 +1965,7 @@ InvertCol(Vec4 col)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BeginScissor(Ctx* ctx, UIItem* item, bool scissor_x = true, bool scissor_y = true)
|
BeginScissor(ref Ctx ctx, UIItem* item, bool scissor_x = true, bool scissor_y = true)
|
||||||
{
|
{
|
||||||
DrawUI(ctx);
|
DrawUI(ctx);
|
||||||
|
|
||||||
@ -2050,7 +1984,10 @@ BeginScissor(Ctx* ctx, UIItem* item, bool scissor_x = true, bool scissor_y = tru
|
|||||||
Vec2
|
Vec2
|
||||||
GetExtent()
|
GetExtent()
|
||||||
{
|
{
|
||||||
version(ENABLE_RENDERER) return Vec2(RendererGetExtent()); else return Vec2(1280, 720);
|
version(ENABLE_RENDERER)
|
||||||
|
return Vec2(RendererGetExtent());
|
||||||
|
else
|
||||||
|
return Vec2(1280, 720);
|
||||||
}
|
}
|
||||||
|
|
||||||
template
|
template
|
||||||
@ -2187,10 +2124,10 @@ ZeroKey(T)(T param) if(is(T == UIItem*) || is(T == UIKey))
|
|||||||
}
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItem*
|
||||||
NewItem(Ctx* ctx)
|
NewItem(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
bool allocated;
|
bool allocated;
|
||||||
return GetOrAlloc(&ctx.arena, &ctx.free_items, g_UI_NIL, &allocated);
|
return GetOrAlloc(&ctx.arena, &ctx.free_items, g_UI_NIL_ITEM, &allocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItem*
|
||||||
@ -2205,7 +2142,7 @@ MakeItem(UIFlags flags = UIF.None, Args...)(string str, Args args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char[] key = sformat(Alloc!(char)(&g_ctx.str_arenas[g_ctx.f_idx], len), str, args);
|
char[] key = sformat(Alloc!(char)(&g_ctx.str_arenas[g_ctx.frame_index], len), str, args);
|
||||||
return MakeItem(key, flags);
|
return MakeItem(key, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2213,7 +2150,7 @@ pragma(inline) UIItem*
|
|||||||
MakeItem(T)(T k, UIFlags flags = UIF.None) if(KeyType!(T))
|
MakeItem(T)(T k, UIFlags flags = UIF.None) if(KeyType!(T))
|
||||||
{
|
{
|
||||||
UIKey key = mixin(AssignKey!(T, k));
|
UIKey key = mixin(AssignKey!(T, k));
|
||||||
Ctx* ctx = GetCtx();
|
ref Ctx ctx = GetCtx();
|
||||||
UIItem* item;
|
UIItem* item;
|
||||||
|
|
||||||
Result!(UIItem*) res = ctx.items[key.hash];
|
Result!(UIItem*) res = ctx.items[key.hash];
|
||||||
@ -2308,15 +2245,8 @@ SetHot(UIItem* item, bool hot)
|
|||||||
|
|
||||||
f32
|
f32
|
||||||
CalcTextWidth(T, U)(T text, U param) if((is(T == string) || StringType!T) && (is(U: u32) || is(U == FontSet*) ))
|
CalcTextWidth(T, U)(T text, U param) if((is(T == string) || StringType!T) && (is(U: u32) || is(U == FontSet*) ))
|
||||||
{
|
|
||||||
static if(is(T == string))
|
|
||||||
{
|
|
||||||
string str = text;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
string str = Str(text);
|
string str = Str(text);
|
||||||
}
|
|
||||||
|
|
||||||
static if(is(U: u32))
|
static if(is(U: u32))
|
||||||
{
|
{
|
||||||
@ -2349,7 +2279,7 @@ DrawGlyph(Rect rect, Glyph* glyph, f32* x_pos, f32 y, f32 line_height, u32 size,
|
|||||||
{
|
{
|
||||||
if(glyph)
|
if(glyph)
|
||||||
{
|
{
|
||||||
Ctx* ctx = GetCtx();
|
ref Ctx ctx = GetCtx();
|
||||||
Vertex* v = null;
|
Vertex* v = null;
|
||||||
f32 advance = glyph.advance;
|
f32 advance = glyph.advance;
|
||||||
|
|
||||||
@ -2412,24 +2342,24 @@ DrawGlyph(Rect rect, Glyph* glyph, f32* x_pos, f32 y, f32 line_height, u32 size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) Vertex*
|
pragma(inline) Vertex*
|
||||||
GetVertex(Ctx* ctx)
|
GetVertex(ref Ctx ctx)
|
||||||
{
|
{
|
||||||
assert(ctx.buffers[ctx.f_idx].count < VERTEX_MAX_COUNT);
|
assert(ctx.buffers[ctx.frame_index].count < VERTEX_MAX_COUNT);
|
||||||
return ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count++;
|
return ctx.buffers[ctx.frame_index].vtx.ptr + ctx.buffers[ctx.frame_index].count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Nil(T)(T item)
|
Nil(T)(T item)
|
||||||
{
|
{
|
||||||
static if(is(T == UIItem*)) return item == null || item == g_UI_NIL;
|
static if(is(T == UIItem*)) return item == null || item == g_UI_NIL_ITEM;
|
||||||
else static if(is(T == UIInput*)) return item == null || item == g_UI_NIL_INPUT;
|
else static if(is(T == UIInput*)) return item == null || item == g_UI_NIL_INPUT;
|
||||||
else static if(is(T == UIPanel*)) return item == null || item == g_NIL_PANEL;
|
else static if(is(T == UIPanel*)) return item == null || item == g_NIL_PANEL;
|
||||||
else static assert(false, "Invalid nil type checked");
|
else static assert(false, "Invalid nil type checked");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Dragged(Ctx* ctx, UIItem* item, IVec2* dragged)
|
Dragged(ref Ctx ctx, UIItem* item, IVec2* dragged)
|
||||||
{
|
{
|
||||||
if(item.key == ctx.drag_key || (!ctx.drag_key && item.key == ctx.hover_key))
|
if(item.key == ctx.drag_key || (!ctx.drag_key && item.key == ctx.hover_key))
|
||||||
{
|
{
|
||||||
@ -2459,7 +2389,7 @@ Dragged(Ctx* ctx, UIItem* item, IVec2* dragged)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Clicked(Ctx* ctx, UIItem* item)
|
Clicked(ref Ctx ctx, UIItem* item)
|
||||||
{
|
{
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
@ -2550,7 +2480,7 @@ OklabToSRGB(Vec4 v)
|
|||||||
string
|
string
|
||||||
EdScratchf(Args...)(string fmt, Args args)
|
EdScratchf(Args...)(string fmt, Args args)
|
||||||
{
|
{
|
||||||
char[] buf = Alloc!(char)(&g_ctx.str_arenas[g_ctx.f_idx], fmt.length < 16 ? 32 : 128);
|
char[] buf = Alloc!(char)(&g_ctx.str_arenas[g_ctx.frame_index], fmt.length < 16 ? 32 : 128);
|
||||||
return Str(sformat(buf, fmt, args));
|
return Str(sformat(buf, fmt, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user