command palette is back, many other fixes i dont remember
This commit is contained in:
parent
ace749228d
commit
94e64fef9e
Binary file not shown.
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit 809814577db807d5911e79216d6e114a2d5a2dfd
|
Subproject commit bda9abf8b9c74844cb30edb32e81543cbd5ae89d
|
||||||
@ -397,36 +397,36 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length)
|
|||||||
Insert(fb, insert, length, fb.pos);
|
Insert(fb, insert, length, fb.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) u64
|
pragma(inline) i64
|
||||||
CurrentLine(FlatBuffer* fb)
|
CurrentLine(FlatBuffer* fb)
|
||||||
{
|
{
|
||||||
return LineFromPos(fb, fb.pos);
|
return LineFromPos(fb, fb.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) u64
|
pragma(inline) i64
|
||||||
CurrentCol(FlatBuffer* fb)
|
CurrentCol(FlatBuffer* fb)
|
||||||
{
|
{
|
||||||
return LinePos(fb, fb.pos);
|
return LinePos(fb, fb.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) u64
|
pragma(inline) i64
|
||||||
LinePos(FlatBuffer* fb, u64 pos)
|
LinePos(FlatBuffer* fb, u64 pos)
|
||||||
{
|
{
|
||||||
u64 line = LineFromPos(fb, pos);
|
u64 line = LineFromPos(fb, pos);
|
||||||
return pos - fb.lines[line].pos;
|
return pos - fb.lines[line].pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) U64Vec2
|
pragma(inline) I64Vec2
|
||||||
VecPos(FlatBuffer* fb)
|
VecPos(FlatBuffer* fb)
|
||||||
{
|
{
|
||||||
return U64Vec2(CurrentCol(fb), CurrentLine(fb));
|
return I64Vec2(CurrentCol(fb), CurrentLine(fb));
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) u64
|
pragma(inline) i64
|
||||||
LineFromPos(FlatBuffer* fb, u64 pos)
|
LineFromPos(FlatBuffer* fb, u64 pos)
|
||||||
{
|
{
|
||||||
u64 line = 0;
|
i64 line = 0;
|
||||||
for(u64 i = 0; i < fb.line_count; i += 1)
|
for(i64 i = 0; i < fb.line_count; i += 1)
|
||||||
{
|
{
|
||||||
if(fb.lines[i].pos > pos)
|
if(fb.lines[i].pos > pos)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import ui;
|
|||||||
import parsing;
|
import parsing;
|
||||||
import views;
|
import views;
|
||||||
|
|
||||||
|
import std.algorithm.comparison : clamp;
|
||||||
import std.format;
|
import std.format;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.exception;
|
import std.exception;
|
||||||
@ -23,8 +24,7 @@ struct EditorCtx
|
|||||||
{
|
{
|
||||||
Arena arena;
|
Arena arena;
|
||||||
PlatformWindow* window;
|
PlatformWindow* window;
|
||||||
UIPanel* base_panel;
|
Panel* base_panel;
|
||||||
u64 panel_id;
|
|
||||||
EditState state;
|
EditState state;
|
||||||
u8[128] input_buf;
|
u8[128] input_buf;
|
||||||
u32 icount;
|
u32 icount;
|
||||||
@ -32,6 +32,9 @@ struct EditorCtx
|
|||||||
Timer timer;
|
Timer timer;
|
||||||
CmdPalette cmd;
|
CmdPalette cmd;
|
||||||
u8[][] file_names;
|
u8[][] file_names;
|
||||||
|
u64 panel_id;
|
||||||
|
|
||||||
|
Editor* focused_editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CmdPalette
|
struct CmdPalette
|
||||||
@ -55,11 +58,11 @@ struct Editor
|
|||||||
FlatBuffer buf;
|
FlatBuffer buf;
|
||||||
Tokenizer tk;
|
Tokenizer tk;
|
||||||
|
|
||||||
U64Vec2 cursor_pos;
|
I64Vec2 cursor_pos;
|
||||||
Vec2 select_start;
|
Vec2 select_start;
|
||||||
Vec2 select_end;
|
Vec2 select_end;
|
||||||
|
|
||||||
u64 line_offset;
|
i64 line_offset;
|
||||||
|
|
||||||
f32 text_size;
|
f32 text_size;
|
||||||
}
|
}
|
||||||
@ -115,7 +118,8 @@ enum EditState
|
|||||||
|
|
||||||
alias ES = EditState;
|
alias ES = EditState;
|
||||||
|
|
||||||
bool g_input_mode = false;
|
__gshared bool g_input_mode = false;
|
||||||
|
__gshared EditorCtx g_ed_ctx;
|
||||||
|
|
||||||
const Command NO_CMD = {
|
const Command NO_CMD = {
|
||||||
name: [],
|
name: [],
|
||||||
@ -123,40 +127,34 @@ const Command NO_CMD = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
Cycle(EditorCtx* ctx, Inputs* inputs)
|
Cycle(Inputs* inputs)
|
||||||
{
|
{
|
||||||
ResetScratch(MB(4));
|
ResetScratch(MB(4));
|
||||||
|
|
||||||
g_delta = DeltaTime(&ctx.timer);
|
g_delta = DeltaTime(&g_ed_ctx.timer);
|
||||||
|
|
||||||
debug if(g_frame_step)
|
debug if(g_frame_step)
|
||||||
{
|
{
|
||||||
g_delta = 0.01;
|
g_delta = 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Nil(ctx.base_panel.next));
|
|
||||||
|
|
||||||
//HandleInputs(ctx, inputs);
|
//HandleInputs(ctx, inputs);
|
||||||
|
|
||||||
debug if(g_frame_step && !g_frame_continue) return;
|
debug if(g_frame_step && !g_frame_continue) return;
|
||||||
debug g_frame_continue = false;
|
debug g_frame_continue = false;
|
||||||
|
|
||||||
g_input_mode = ctx.state == ES.InputMode;
|
g_input_mode = g_ed_ctx.state == ES.InputMode;
|
||||||
|
|
||||||
BeginUI(inputs);
|
BeginUI(inputs);
|
||||||
|
|
||||||
UICtx* ui_ctx = GetCtx();
|
UICtx* ui_ctx = GetCtx();
|
||||||
|
|
||||||
static Editor* ed;
|
EditorView(g_ed_ctx.base_panel);
|
||||||
|
|
||||||
if(!ed)
|
if(g_ed_ctx.state == ES.CmdOpen)
|
||||||
{
|
{
|
||||||
ed = CreateEditor(ctx);
|
CommandPalette(&g_ed_ctx.cmd);
|
||||||
OpenFile(ed, CastStr!(u8)("src/editor/ui.d"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorView(ed);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
UIPanel* root = ctx.base_panel;
|
UIPanel* root = ctx.base_panel;
|
||||||
|
|
||||||
@ -203,26 +201,22 @@ Cycle(EditorCtx* ctx, Inputs* inputs)
|
|||||||
EndUI();
|
EndUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
EditorCtx
|
|
||||||
InitEditorCtx(PlatformWindow* window)
|
InitEditorCtx(PlatformWindow* window)
|
||||||
{
|
{
|
||||||
InitUICtx(window);
|
InitUICtx(window);
|
||||||
|
|
||||||
EditorCtx ctx = {
|
EditorCtx* ctx = &g_ed_ctx;
|
||||||
window: window,
|
|
||||||
arena: CreateArena(MB(2)),
|
|
||||||
cmd: {
|
|
||||||
arena: CreateArena(MB(1)),
|
|
||||||
cmd_arena: CreateArena(MB(1)),
|
|
||||||
buffer: Alloc!(u8)(1024),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.base_panel = CreatePanel(&ctx);
|
ctx.window = window;
|
||||||
ctx.base_panel.ed = CreateEditor(&ctx);
|
ctx.arena = CreateArena(MB(2));
|
||||||
|
ctx.cmd.arena = CreateArena(MB(1));
|
||||||
|
ctx.cmd.cmd_arena = CreateArena(MB(1));
|
||||||
|
ctx.cmd.buffer = Alloc!(u8)(1024);
|
||||||
|
ctx.base_panel = CreatePanel(ctx, CreateEditor(ctx));
|
||||||
ctx.timer = CreateTimer();
|
ctx.timer = CreateTimer();
|
||||||
//SetFocusedPanel(ctx.base_panel);
|
|
||||||
|
FocusEditor(ctx.base_panel.ed);
|
||||||
|
|
||||||
if(getcwd() != "/")
|
if(getcwd() != "/")
|
||||||
{
|
{
|
||||||
@ -254,24 +248,25 @@ InitEditorCtx(PlatformWindow* window)
|
|||||||
Logf("failed to open directory for filenames");
|
Logf("failed to open directory for filenames");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UIPanel*
|
void
|
||||||
CreatePanel(EditorCtx* ctx, SizeType size_type = ST.Percentage)
|
FocusEditor(Editor* ed)
|
||||||
{
|
{
|
||||||
UIPanel* p = Alloc!(UIPanel)(&ctx.arena);
|
assert(ed);
|
||||||
p.axis = A2D.Y;
|
g_ed_ctx.focused_editor = ed;
|
||||||
p.id = Alloc!(u8)(&ctx.arena, 10);
|
Logf("editor %s", ed.editor_id);
|
||||||
p.pct = 1.0;
|
}
|
||||||
p.scroll_offset = 0.0;
|
|
||||||
p.scroll_target = 0.0;
|
|
||||||
|
|
||||||
(cast(char[])p.id).sformat("##%08s", ctx.panel_id);
|
Panel*
|
||||||
p.parent = p.first = p.last = p.next = p.prev = g_UI_NIL_PANEL;
|
CreatePanel(EditorCtx* ctx, Editor* ed = null)
|
||||||
|
{
|
||||||
|
Panel* p = Alloc!(Panel)(&ctx.arena);
|
||||||
|
|
||||||
ctx.panel_id += 1;
|
p.layout_axis = A2D.Y;
|
||||||
|
p.ed = ed;
|
||||||
|
p.id = ctx.panel_id++;
|
||||||
|
p.parent = p.first = p.last = p.next = p.prev = g_NIL_PANEL;
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -409,8 +404,6 @@ OpenFile(Editor* ed, u8[] file_name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all files then move things into editor after being created when selected
|
|
||||||
|
|
||||||
Editor*
|
Editor*
|
||||||
CreateEditor(EditorCtx* ctx)
|
CreateEditor(EditorCtx* ctx)
|
||||||
{
|
{
|
||||||
@ -423,107 +416,71 @@ CreateEditor(EditorCtx* ctx)
|
|||||||
return ed;
|
return ed;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug
|
|
||||||
{
|
|
||||||
__gshared u64 panel_count = 0;
|
|
||||||
__gshared UIPanel*[1024] panels = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AddEditor(EditorCtx* ctx, UIPanel* target, Axis2D axis)
|
AddEditor(EditorCtx* ctx, Panel* target, Axis2D axis)
|
||||||
{
|
{
|
||||||
if(Nil(target.parent) || target.parent.axis != axis)
|
if(CheckNil(g_NIL_PANEL, target.parent) || target.parent.layout_axis != axis)
|
||||||
{
|
{
|
||||||
UIPanel* first = CreatePanel(ctx);
|
Panel* first = CreatePanel(ctx, target.ed);
|
||||||
UIPanel* second = CreatePanel(ctx);
|
Panel* second = CreatePanel(ctx, CreateEditor(ctx));
|
||||||
|
|
||||||
first.ed = target.ed;
|
target.layout_axis = axis;
|
||||||
second.ed = CreateEditor(ctx);
|
|
||||||
|
|
||||||
first.pct = second.pct = 0.5;
|
|
||||||
|
|
||||||
target.axis = axis;
|
|
||||||
target.ed = null;
|
target.ed = null;
|
||||||
|
|
||||||
//PushPanel(target, first);
|
DLLPush(target, first, g_NIL_PANEL);
|
||||||
//PushPanel(target, second);
|
DLLPush(target, second, g_NIL_PANEL);
|
||||||
|
|
||||||
//SetFocusedPanel(second);
|
first.parent = second.parent = target;
|
||||||
|
|
||||||
debug
|
FocusEditor(second.ed);
|
||||||
|
}
|
||||||
|
else if(target.parent.layout_axis == axis)
|
||||||
{
|
{
|
||||||
panels[panel_count+0] = first;
|
Panel* panel = CreatePanel(ctx, CreateEditor(ctx));
|
||||||
panels[panel_count+1] = second;
|
|
||||||
|
|
||||||
panel_count += 2;
|
DLLPush(target.parent, target, panel);
|
||||||
}
|
panel.parent = target.parent;
|
||||||
}
|
|
||||||
else if(target.parent.axis == axis)
|
UIItem* ed_item = GetEditorItem(panel.ed);
|
||||||
|
if(!Nil(ed_item.parent))
|
||||||
{
|
{
|
||||||
UIPanel* panel = CreatePanel(ctx);
|
u64 count;
|
||||||
panel.ed = CreateEditor(ctx);
|
for(UIItem* c = ed_item.parent.first; !Nil(c); c = c.next)
|
||||||
|
|
||||||
//InsertPanel(target.parent, target, panel);
|
|
||||||
|
|
||||||
u64 count = 0;
|
|
||||||
for(UIPanel* p = target.parent.first; !Nil(p); p = p.next, count += 1) {}
|
|
||||||
|
|
||||||
f32 pct = 1.0/count;
|
|
||||||
for(UIPanel* p = target.parent.first; !Nil(p); p = p.next)
|
|
||||||
{
|
{
|
||||||
p.pct = pct;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//SetFocusedPanel(panel);
|
f32 pct = 1.0/cast(f32)count;
|
||||||
|
for(UIItem* c = ed_item.parent.first; !Nil(c); c = c.next)
|
||||||
debug
|
|
||||||
{
|
{
|
||||||
panels[panel_count] = panel;
|
c.resize_pct = pct;
|
||||||
|
|
||||||
panel_count += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug for(u64 i = 0; i < panel_count; i += 1)
|
FocusEditor(panel.ed);
|
||||||
{
|
|
||||||
bool root_found = false;
|
|
||||||
for(UIPanel* p = panels[i]; !Nil(p); p = p.parent)
|
|
||||||
{
|
|
||||||
if(p == ctx.base_panel)
|
|
||||||
{
|
|
||||||
root_found = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!root_found)
|
UIItem*
|
||||||
|
GetEditorItem(Editor* ed)
|
||||||
{
|
{
|
||||||
Logf("[DEBUG] panel %s unable to reach root", cast(char[])panels[panel_count].id);
|
return Get("###ed_%s", ed.editor_id);
|
||||||
assert(root_found);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
InsertInputToBuf(EditorCtx* ctx)
|
InsertInputToBuf(EditorCtx* ctx, Editor* ed)
|
||||||
{
|
{
|
||||||
if(ctx.icount > 0)
|
if(ctx.icount > 0)
|
||||||
{
|
{
|
||||||
/*
|
Insert(&ed.buf, ctx.input_buf, ctx.icount);
|
||||||
UIPanel* p = GetFocusedPanel();
|
|
||||||
if(!Nil(p))
|
|
||||||
{
|
|
||||||
Insert(&p.ed.buf, ctx.input_buf, ctx.icount);
|
|
||||||
ctx.icount = 0;
|
ctx.icount = 0;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ResetCtx(EditorCtx* ctx)
|
ResetCtx(EditorCtx* ctx, Editor* ed)
|
||||||
{
|
{
|
||||||
InsertInputToBuf(ctx);
|
InsertInputToBuf(ctx, ed);
|
||||||
|
|
||||||
ctx.state = ES.NormalMode;
|
ctx.state = ES.NormalMode;
|
||||||
ctx.cmd.icount = 0;
|
ctx.cmd.icount = 0;
|
||||||
@ -586,11 +543,12 @@ MovePanelFocus(A2D axis, bool prev)(UIPanel* panel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
HandleInputs(Panel* p, LinkedList!(UIInput)* inputs)
|
||||||
{
|
{
|
||||||
|
Editor* ed = p.ed;
|
||||||
|
EditorCtx* ctx = &g_ed_ctx;
|
||||||
u8[] cb_text;
|
u8[] cb_text;
|
||||||
UIPanel* panel = g_UI_NIL_PANEL;//GetFocusedPanel();
|
FlatBuffer* fb = &ed.buf;
|
||||||
FlatBuffer* fb = !Nil(panel) ? &panel.ed.buf : null;
|
|
||||||
|
|
||||||
for(auto node = inputs.first; node != null; node = node.next)
|
for(auto node = inputs.first; node != null; node = node.next)
|
||||||
{
|
{
|
||||||
@ -598,46 +556,27 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
|||||||
|
|
||||||
Input key = node.key;
|
Input key = node.key;
|
||||||
Modifier md = node.md;
|
Modifier md = node.md;
|
||||||
bool pressed = node.pressed;
|
|
||||||
|
|
||||||
if (pressed)
|
|
||||||
{
|
|
||||||
if(key == Input.Escape)
|
if(key == Input.Escape)
|
||||||
{
|
{
|
||||||
ResetCtx(ctx);
|
ResetCtx(ctx, ed);
|
||||||
taken = true;
|
taken = true;
|
||||||
}
|
}
|
||||||
else if(ctx.state == ES.InputMode)
|
else if(ctx.state == ES.InputMode)
|
||||||
{
|
{
|
||||||
taken = HandleInputMode(ctx, node);
|
taken = HandleInputMode(ctx, p, node);
|
||||||
}
|
}
|
||||||
else if(ctx.state == ES.CmdOpen)
|
else if(ctx.state == ES.CmdOpen)
|
||||||
{
|
{
|
||||||
taken = HandleCmdMode(ctx, node);
|
taken = HandleCmdMode(ctx, p, node);
|
||||||
}
|
}
|
||||||
else if(ctx.state == ES.SetPanelFocus)
|
else if(ctx.state == ES.SetPanelFocus)
|
||||||
{
|
{
|
||||||
switch(key) with(Input)
|
switch(key) with(Input)
|
||||||
{
|
{
|
||||||
case Up:
|
|
||||||
{
|
|
||||||
if(MovePanelFocus!(A2D.Y, true )(panel)) goto case Escape;
|
|
||||||
} break;
|
|
||||||
case Down:
|
|
||||||
{
|
|
||||||
if(MovePanelFocus!(A2D.Y, false)(panel)) goto case Escape;
|
|
||||||
} break;
|
|
||||||
case Left:
|
|
||||||
{
|
|
||||||
if(MovePanelFocus!(A2D.X, true )(panel)) goto case Escape;
|
|
||||||
} break;
|
|
||||||
case Right:
|
|
||||||
{
|
|
||||||
if(MovePanelFocus!(A2D.X, false)(panel)) goto case Escape;
|
|
||||||
} break;
|
|
||||||
case Escape:
|
case Escape:
|
||||||
{
|
{
|
||||||
ResetCtx(ctx);
|
ResetCtx(ctx, ed);
|
||||||
taken = true;
|
taken = true;
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
@ -718,7 +657,6 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
|||||||
default: taken = Move(fb, key, md); break;
|
default: taken = Move(fb, key, md); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(taken)
|
if(taken)
|
||||||
{
|
{
|
||||||
@ -726,7 +664,7 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InsertInputToBuf(ctx);
|
InsertInputToBuf(ctx, ed);
|
||||||
|
|
||||||
if(cb_text.length > 0)
|
if(cb_text.length > 0)
|
||||||
{
|
{
|
||||||
@ -735,22 +673,15 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MoveCursor(InputEvent* ev)
|
MoveCursor(Editor* ed, UIInput* ev)
|
||||||
{
|
{
|
||||||
UIPanel* p = g_UI_NIL_PANEL;//GetFocusedPanel();
|
|
||||||
|
|
||||||
if(!Nil(p))
|
|
||||||
{
|
|
||||||
FlatBuffer* fb = &p.ed.buf;
|
|
||||||
switch(ev.key) with(Input)
|
switch(ev.key) with(Input)
|
||||||
{
|
{
|
||||||
case Up, Down, Left, Right: Move(fb, ev.key, ev.md); break;
|
case Up, Down, Left, Right: Move(&ed.buf, ev.key, ev.md); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
InsertChar(EditorCtx* ctx, Input input, bool modified)
|
InsertChar(EditorCtx* ctx, Input input, bool modified)
|
||||||
{
|
{
|
||||||
@ -775,7 +706,7 @@ CharCases()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
HandleInputMode(EditorCtx* ctx, InputEvent* ev)
|
HandleInputMode(EditorCtx* ctx, Panel* p, UIInput* ev)
|
||||||
{
|
{
|
||||||
bool taken = false;
|
bool taken = false;
|
||||||
|
|
||||||
@ -783,18 +714,14 @@ HandleInputMode(EditorCtx* ctx, InputEvent* ev)
|
|||||||
{
|
{
|
||||||
mixin(CharCases());
|
mixin(CharCases());
|
||||||
case Input.Backspace:
|
case Input.Backspace:
|
||||||
{
|
|
||||||
UIPanel* p = g_UI_NIL_PANEL;//GetFocusedPanel();
|
|
||||||
if(!Nil(p))
|
|
||||||
{
|
{
|
||||||
Backspace(&p.ed.buf);
|
Backspace(&p.ed.buf);
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case Input.Escape:
|
case Input.Escape:
|
||||||
{
|
{
|
||||||
ctx.state = ES.NormalMode;
|
ctx.state = ES.NormalMode;
|
||||||
} break;
|
} break;
|
||||||
default: MoveCursor(ev); break;
|
default: MoveCursor(p.ed, ev); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return taken;
|
return taken;
|
||||||
@ -933,11 +860,11 @@ GetCommands(CmdPalette* cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
HandleCmdMode(EditorCtx* ctx, InputEvent* ev)
|
HandleCmdMode(EditorCtx* ctx, Panel* panel, UIInput* ev)
|
||||||
{
|
{
|
||||||
u8 result = 0;
|
bool taken;
|
||||||
bool taken = false;
|
|
||||||
CmdPalette* cmd = &ctx.cmd;
|
CmdPalette* cmd = &ctx.cmd;
|
||||||
|
Editor* ed = panel.ed;
|
||||||
|
|
||||||
u64 prev_count = cmd.icount;
|
u64 prev_count = cmd.icount;
|
||||||
switch(ev.key) with(Input)
|
switch(ev.key) with(Input)
|
||||||
@ -956,36 +883,31 @@ HandleCmdMode(EditorCtx* ctx, InputEvent* ev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UIPanel* p = g_UI_NIL_PANEL;//GetFocusedPanel();
|
|
||||||
|
|
||||||
switch(cmd.current.type)
|
switch(cmd.current.type)
|
||||||
{
|
{
|
||||||
case CT.OpenFile:
|
case CT.OpenFile:
|
||||||
{
|
{
|
||||||
if(!Nil(p) && cmd.selected >= 0 && cmd.selected < cmd.opt_strs.length)
|
if(cmd.selected >= 0 && cmd.selected < cmd.opt_strs.length)
|
||||||
{
|
{
|
||||||
OpenFile(p.ed, cmd.opt_strs[cmd.selected]);
|
OpenFile(ed, cmd.opt_strs[cmd.selected]);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case CT.SaveFile:
|
case CT.SaveFile:
|
||||||
{
|
{
|
||||||
if(!Nil(p))
|
SaveFile(ed, GetParam(cmd));
|
||||||
{
|
|
||||||
SaveFile(p.ed, GetParam(cmd));
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case CT.VSplit, CT.HSplit:
|
case CT.VSplit, CT.HSplit:
|
||||||
{
|
{
|
||||||
AddEditor(ctx, p, cmd.current.type == CT.VSplit ? A2D.X : A2D.Y);
|
AddEditor(ctx, panel, cmd.current.type == CT.VSplit ? A2D.X : A2D.Y);
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetCtx(ctx);
|
ResetCtx(ctx, ed);
|
||||||
} goto CmdInputEnd;
|
} goto CmdInputEnd;
|
||||||
case Backspace:
|
case Backspace:
|
||||||
{
|
{
|
||||||
if(CondIncr!(-1)(cmd.icount > 0, &cmd.icount) && cmd.buffer[cmd.icount] == ' ')
|
if(cmd.icount > 0 && cmd.buffer[--cmd.icount] == ' ')
|
||||||
{
|
{
|
||||||
cmd.current = cast(Command)NO_CMD;
|
cmd.current = cast(Command)NO_CMD;
|
||||||
}
|
}
|
||||||
@ -1005,22 +927,18 @@ HandleCmdMode(EditorCtx* ctx, InputEvent* ev)
|
|||||||
cmd.buffer[cmd.icount++] = ' ';
|
cmd.buffer[cmd.icount++] = ' ';
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Up:
|
case Up, Down:
|
||||||
{
|
{
|
||||||
CondIncr!(-1)(cmd.selected > 0, &cmd.selected);
|
cmd.selected = clamp(cmd.selected+(ev.key == Up ? -1 : +1), 0, cmd.opt_strs.length-1);
|
||||||
} break;
|
} break;
|
||||||
case Down:
|
default:
|
||||||
{
|
{
|
||||||
CondIncr!(+1)(cmd.selected < cmd.opt_strs.length-1, &cmd.selected);
|
if(ev.text.length)
|
||||||
} break;
|
{
|
||||||
mixin(TextLineCharCases());
|
cmd.buffer[cmd.icount .. cmd.icount+ev.text.length] = cast(u8[])ev.text[0 .. $];
|
||||||
default: break;
|
cmd.icount += ev.text.length;
|
||||||
}
|
}
|
||||||
|
} break;
|
||||||
if(result != 0)
|
|
||||||
{
|
|
||||||
Check(cmd, 1);
|
|
||||||
cmd.buffer[cmd.icount++] = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cmd.current.type == CT.None && (cmd.commands.length == 0 || prev_count != cmd.icount))
|
if(cmd.current.type == CT.None && (cmd.commands.length == 0 || prev_count != cmd.icount))
|
||||||
|
|||||||
@ -27,7 +27,7 @@ void main(string[] argv)
|
|||||||
|
|
||||||
StartPlatformThread(&window);
|
StartPlatformThread(&window);
|
||||||
|
|
||||||
EditorCtx ctx = InitEditorCtx(&window);
|
InitEditorCtx(&window);
|
||||||
|
|
||||||
import ui;
|
import ui;
|
||||||
import vulkan;
|
import vulkan;
|
||||||
@ -58,6 +58,6 @@ void main(string[] argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cycle(&ctx, inputs);
|
Cycle(inputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,6 +89,7 @@ const Vec4 GREEN = Vec4(0.0, 1.0, 0.0, 1.0);
|
|||||||
const Vec4 TURQUOISE = Vec4(0.15, 0.59, 0.76, 1.0);
|
const Vec4 TURQUOISE = Vec4(0.15, 0.59, 0.76, 1.0);
|
||||||
const Vec4 PINK = Vec4(0.85, 0.48, 0.60, 1.0);
|
const Vec4 PINK = Vec4(0.85, 0.48, 0.60, 1.0);
|
||||||
|
|
||||||
|
const Vec4[TS.max] DEFAULT_COLORS = Vec4(1.0);
|
||||||
const Vec4[TS.max] SYNTAX_COLORS = SyntaxCols();
|
const Vec4[TS.max] SYNTAX_COLORS = SyntaxCols();
|
||||||
|
|
||||||
static Vec4[TS.max]
|
static Vec4[TS.max]
|
||||||
|
|||||||
564
src/editor/ui.d
564
src/editor/ui.d
@ -6,7 +6,6 @@ import vulkan : RendererGetExtent = GetExtent;
|
|||||||
import buffer;
|
import buffer;
|
||||||
import parsing;
|
import parsing;
|
||||||
import editor;
|
import editor;
|
||||||
import views : Nil;
|
|
||||||
import views;
|
import views;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
@ -29,10 +28,10 @@ import core.stdc.stdio : sprintf;
|
|||||||
|
|
||||||
*********************************/
|
*********************************/
|
||||||
|
|
||||||
enum Vec4[4] BG_COL = Vec4(0.13, 0.13, 0.13, 1.0);
|
enum Vec4 BG_COL = Vec4(0.13, 0.13, 0.13, 1.0);
|
||||||
enum Vec4[4] BG_HL_COL = Vec4(0.24, 0.45, 0.81, 1.0);
|
enum Vec4 BG_HL_COL = Vec4(0.24, 0.45, 0.81, 1.0);
|
||||||
enum Vec4[4] BORDER_COL = Vec4(0.254, 0.254, 0.266, 1.0);
|
enum Vec4 BORDER_COL = Vec4(0.254, 0.254, 0.266, 1.0);
|
||||||
enum Vec4[4] BORDER_HL_COL = Vec4(0.035, 0.549, 0.824, 1.0);
|
enum Vec4 BORDER_HL_COL = Vec4(0.035, 0.549, 0.824, 1.0);
|
||||||
enum Vec4 TEXT_COL = Vec4(1.0);
|
enum Vec4 TEXT_COL = Vec4(1.0);
|
||||||
enum Vec4 TEXT_HL_COL = Vec4(0.0, 0.0, 0.0, 1.0);
|
enum Vec4 TEXT_HL_COL = Vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
@ -44,20 +43,20 @@ 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;
|
||||||
|
|
||||||
UIPanel g_root_panel;
|
__gshared UICtx g_ui_ctx;
|
||||||
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[] VERTEX_BYTES = import("gui.vert.spv");
|
const u8[] VERTEX_BYTES = import("gui.vert.spv");
|
||||||
const u8[] FRAGMENT_BYTES = import("gui.frag.spv");
|
const u8[] FRAGMENT_BYTES = import("gui.frag.spv");
|
||||||
|
|
||||||
f32 g_corner_radius_default = 2.0;
|
Vec4 g_corner_radius_default = 0.0;
|
||||||
f32 g_edge_softness_default = 0.1;
|
f32 g_edge_softness_default = 0.8;
|
||||||
f32 g_border_thickness_default = 0.0;
|
f32 g_border_thickness_default = 0.0;
|
||||||
Vec4[4] g_bg_col_default = BG_COL;
|
Vec4 g_bg_col_default = BG_COL;
|
||||||
Vec4[4] g_bg_hl_col_default = BG_HL_COL;
|
Vec4 g_bg_hl_col_default = BG_HL_COL;
|
||||||
Vec4[4] g_border_col_default = BORDER_COL;
|
Vec4 g_border_col_default = BORDER_COL;
|
||||||
Vec4[4] g_border_hl_col_default = BORDER_HL_COL;
|
Vec4 g_border_hl_col_default = BORDER_HL_COL;
|
||||||
Vec4 g_text_col_default = TEXT_COL;
|
Vec4 g_text_col_default = TEXT_COL;
|
||||||
Vec4 g_text_hl_col_default = TEXT_HL_COL;
|
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)];
|
||||||
@ -68,12 +67,13 @@ 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);
|
||||||
string g_display_string_default = null;
|
string g_display_string_default = null;
|
||||||
|
UISH g_syntax_highlight_default = UISH.None;
|
||||||
|
u8[] g_syntax_tokens_default = [];
|
||||||
|
Vec2 g_fixed_pos_default = Vec2(0.0);
|
||||||
alias g_parent_default = g_UI_NIL;
|
alias g_parent_default = g_UI_NIL;
|
||||||
|
|
||||||
const UI_COUNT = 5000;
|
const UI_COUNT = 5000;
|
||||||
|
|
||||||
__gshared const UIPanel g_ui_nil_panel;
|
|
||||||
__gshared UIPanel* g_UI_NIL_PANEL;
|
|
||||||
__gshared const UIItem g_ui_nil_item;
|
__gshared const UIItem g_ui_nil_item;
|
||||||
__gshared UIItem* g_UI_NIL;
|
__gshared UIItem* g_UI_NIL;
|
||||||
__gshared const UIInput g_ui_nil_input;
|
__gshared const UIInput g_ui_nil_input;
|
||||||
@ -87,7 +87,6 @@ __gshared Stack!Vec4* g_NIL_VEC4_STACK;
|
|||||||
__gshared const Stack!u32 g_nil_u32_stack;
|
__gshared const Stack!u32 g_nil_u32_stack;
|
||||||
__gshared Stack!u32* g_NIL_U32_STACK;
|
__gshared Stack!u32* g_NIL_U32_STACK;
|
||||||
|
|
||||||
|
|
||||||
enum Axis2D
|
enum Axis2D
|
||||||
{
|
{
|
||||||
X,
|
X,
|
||||||
@ -111,18 +110,23 @@ enum UIFlags
|
|||||||
ClampY = 1<<8,
|
ClampY = 1<<8,
|
||||||
Resizeable = 1<<9,
|
Resizeable = 1<<9,
|
||||||
ResizeAdjacent = 1<<10,
|
ResizeAdjacent = 1<<10,
|
||||||
FloatingWindow = 1<<11,
|
FloatingWindow = 1<<11, // todo
|
||||||
CenteredWindow = 1<<12,
|
Window = 1<<12,
|
||||||
TextInput = 1<<13, // todo
|
TextInput = 1<<13, // todo
|
||||||
RightAlignText = 1<<14,
|
RightAlignText = 1<<14,
|
||||||
CenterAlignText = 1<<15, // todo
|
CenterAlignText = 1<<15, // todo
|
||||||
TextWrap = 1<<16,
|
TextWrap = 1<<16,
|
||||||
PortalViewX = 1<<17, // Stencil mask this area, no bounds checking children within (for views to drag and view elements)
|
PortalViewX = 1<<17,
|
||||||
PortalViewY = 1<<18,
|
PortalViewY = 1<<18,
|
||||||
|
FixedPosition = 1<<19,
|
||||||
|
FixedPosAnimated = 1<<20, // todo: add fixed_pos_target then interpolate position every frame
|
||||||
|
OverflowX = 1<<21,
|
||||||
|
OverflowY = 1<<22,
|
||||||
|
|
||||||
Clamp = UIFlags.ClampX | UIFlags.ClampY,
|
Clamp = UIFlags.ClampX | UIFlags.ClampY,
|
||||||
PortalView = UIFlags.PortalViewX | UIFlags.PortalViewY,
|
PortalView = UIFlags.PortalViewX | UIFlags.PortalViewY,
|
||||||
Scroll = UIFlags.ScrollX | UIFlags.ScrollY,
|
Scroll = UIFlags.ScrollX | UIFlags.ScrollY,
|
||||||
|
Overflow = UIFlags.OverflowX | UIFlags.OverflowY,
|
||||||
}
|
}
|
||||||
alias UIF = UIFlags;
|
alias UIF = UIFlags;
|
||||||
|
|
||||||
@ -145,6 +149,7 @@ enum UIEvent
|
|||||||
Drag = 1<<2,
|
Drag = 1<<2,
|
||||||
DragStart = 1<<3,
|
DragStart = 1<<3,
|
||||||
Press = 1<<4,
|
Press = 1<<4,
|
||||||
|
Scroll = 1<<5,
|
||||||
}
|
}
|
||||||
alias UIE = UIEvent;
|
alias UIE = UIEvent;
|
||||||
|
|
||||||
@ -152,6 +157,7 @@ struct UIInput
|
|||||||
{
|
{
|
||||||
UIEvent type;
|
UIEvent type;
|
||||||
UIInput* next, prev;
|
UIInput* next, prev;
|
||||||
|
Modifier md;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
@ -161,9 +167,18 @@ struct UIInput
|
|||||||
};
|
};
|
||||||
IVec2 rel;
|
IVec2 rel;
|
||||||
IVec2 pos;
|
IVec2 pos;
|
||||||
|
i32 scroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum UISyntaxHighlight
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
D,
|
||||||
|
Max,
|
||||||
|
}
|
||||||
|
alias UISH = UISyntaxHighlight;
|
||||||
|
|
||||||
mixin template
|
mixin template
|
||||||
UICtxParameter(T, string name)
|
UICtxParameter(T, string name)
|
||||||
{
|
{
|
||||||
@ -237,17 +252,17 @@ struct UICtx
|
|||||||
|
|
||||||
u32 tab_width;
|
u32 tab_width;
|
||||||
f32 text_size;
|
f32 text_size;
|
||||||
|
Vec4[TS.max][UISH.max] syntax_colors;
|
||||||
|
|
||||||
UIItem* window_root;
|
UIItem* window_root;
|
||||||
UIItem* root;
|
UIItem* root;
|
||||||
UIItem* drag_item;
|
UIItem* drag_item;
|
||||||
UIPanel* parent_panel;
|
UIItem* focus_item;
|
||||||
UIPanel* focused_panel;
|
|
||||||
|
|
||||||
mixin UICtxParameter!(Vec4[4], "bg_col");
|
mixin UICtxParameter!(Vec4, "bg_col");
|
||||||
mixin UICtxParameter!(Vec4[4], "bg_hl_col");
|
mixin UICtxParameter!(Vec4, "bg_hl_col");
|
||||||
mixin UICtxParameter!(Vec4[4], "border_col");
|
mixin UICtxParameter!(Vec4, "border_col");
|
||||||
mixin UICtxParameter!(Vec4[4], "border_hl_col");
|
mixin UICtxParameter!(Vec4, "border_hl_col");
|
||||||
mixin UICtxParameter!(UISize[2], "size_info");
|
mixin UICtxParameter!(UISize[2], "size_info");
|
||||||
mixin UICtxParameter!(Vec4, "text_col");
|
mixin UICtxParameter!(Vec4, "text_col");
|
||||||
mixin UICtxParameter!(Vec4, "text_hl_col");
|
mixin UICtxParameter!(Vec4, "text_hl_col");
|
||||||
@ -255,13 +270,16 @@ struct UICtx
|
|||||||
mixin UICtxParameter!(Vec2, "scroll_target");
|
mixin UICtxParameter!(Vec2, "scroll_target");
|
||||||
mixin UICtxParameter!(Vec2, "padding");
|
mixin UICtxParameter!(Vec2, "padding");
|
||||||
mixin UICtxParameter!(Vec2, "view_offset");
|
mixin UICtxParameter!(Vec2, "view_offset");
|
||||||
|
mixin UICtxParameter!(Vec2, "fixed_pos");
|
||||||
mixin UICtxParameter!(UIItem*, "parent");
|
mixin UICtxParameter!(UIItem*, "parent");
|
||||||
mixin UICtxParameter!(string, "display_string");
|
mixin UICtxParameter!(string, "display_string");
|
||||||
|
mixin UICtxParameter!(u8[], "syntax_tokens");
|
||||||
mixin UICtxParameter!(Axis2D, "layout_axis");
|
mixin UICtxParameter!(Axis2D, "layout_axis");
|
||||||
mixin UICtxParameter!(f32, "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!(f32, "text_scale");
|
||||||
|
mixin UICtxParameter!(UISyntaxHighlight, "syntax_highlight");
|
||||||
|
|
||||||
debug bool dbg;
|
debug bool dbg;
|
||||||
}
|
}
|
||||||
@ -324,13 +342,15 @@ struct UIItem
|
|||||||
Vec2 size;
|
Vec2 size;
|
||||||
|
|
||||||
string[] text_lines;
|
string[] text_lines;
|
||||||
|
u8[][] token_lines;
|
||||||
|
Vec2 scroll_offset;
|
||||||
|
Vec2 pos_offset;
|
||||||
|
u8[] text_buffer;
|
||||||
f32 max_text_width;
|
f32 max_text_width;
|
||||||
f32 resize_pct;
|
f32 resize_pct;
|
||||||
Vec2 scroll_offset;
|
bool rendered;
|
||||||
|
|
||||||
mixin UIItemParameters!();
|
mixin UIItemParameters!();
|
||||||
|
|
||||||
bool rendered;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SizeType
|
enum SizeType
|
||||||
@ -374,7 +394,8 @@ struct VPos
|
|||||||
|
|
||||||
struct Vertex
|
struct Vertex
|
||||||
{
|
{
|
||||||
Vec4[4] cols;
|
Vec4 cols;
|
||||||
|
Vec4 corner_radius;
|
||||||
Vec2[2] bounds;
|
Vec2[2] bounds;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@ -388,7 +409,6 @@ struct Vertex
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
f32 border_thickness;
|
f32 border_thickness;
|
||||||
f32 corner_radius;
|
|
||||||
f32 edge_softness;
|
f32 edge_softness;
|
||||||
f32 raised;
|
f32 raised;
|
||||||
u32 texture;
|
u32 texture;
|
||||||
@ -410,30 +430,6 @@ struct UIKey
|
|||||||
u64 hash;
|
u64 hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIPanel
|
|
||||||
{
|
|
||||||
u8[] id;
|
|
||||||
Editor* ed;
|
|
||||||
|
|
||||||
UIPanel* parent, next, prev, first, last, list_next;
|
|
||||||
Axis2D axis;
|
|
||||||
f32 pct;
|
|
||||||
Vec4 color;
|
|
||||||
|
|
||||||
Rect rect;
|
|
||||||
Vec2 size;
|
|
||||||
|
|
||||||
i64 start_ln, end_ln, vis_lines, prev_start_ln;
|
|
||||||
f32 scroll_offset, scroll_target;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TextPart
|
|
||||||
{
|
|
||||||
UIItem* item;
|
|
||||||
TextPart* next;
|
|
||||||
u32 count;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum bool StringType(T) = (is(T: string) || is(T: u8[]) || is(T: char[]));
|
enum bool StringType(T) = (is(T: string) || is(T: u8[]) || is(T: char[]));
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -456,15 +452,12 @@ InitUICtx(PlatformWindow* window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_UI_NIL = cast(UIItem*)&g_ui_nil_item;
|
g_UI_NIL = cast(UIItem*)&g_ui_nil_item;
|
||||||
g_UI_NIL_PANEL = cast(UIPanel*)&g_ui_nil_panel;
|
|
||||||
g_UI_NIL_INPUT = cast(UIInput*)&g_ui_nil_input;
|
g_UI_NIL_INPUT = cast(UIInput*)&g_ui_nil_input;
|
||||||
g_NIL_F32_STACK = cast(Stack!f32*)&g_nil_f32_stack;
|
g_NIL_F32_STACK = cast(Stack!f32*)&g_nil_f32_stack;
|
||||||
g_NIL_GRAD_COL_STACK = cast(Stack!Vec4[4]*)&g_nil_gradient_col_stack;
|
g_NIL_GRAD_COL_STACK = cast(Stack!Vec4[4]*)&g_nil_gradient_col_stack;
|
||||||
g_NIL_VEC4_STACK = cast(Stack!Vec4*)&g_nil_vec4_stack;
|
g_NIL_VEC4_STACK = cast(Stack!Vec4*)&g_nil_vec4_stack;
|
||||||
g_NIL_U32_STACK = cast(Stack!u32*)&g_nil_u32_stack;
|
g_NIL_U32_STACK = cast(Stack!u32*)&g_nil_u32_stack;
|
||||||
|
|
||||||
g_ui_ctx.parent_panel = g_UI_NIL_PANEL;
|
|
||||||
|
|
||||||
Arena arena = CreateArena(MB(4));
|
Arena arena = CreateArena(MB(4));
|
||||||
|
|
||||||
UIBuffer[FRAME_OVERLAP] buffers;
|
UIBuffer[FRAME_OVERLAP] buffers;
|
||||||
@ -480,6 +473,7 @@ InitUICtx(PlatformWindow* window)
|
|||||||
font_data: cast(u8[])FONT_BYTES,
|
font_data: cast(u8[])FONT_BYTES,
|
||||||
text_size: 16.0,
|
text_size: 16.0,
|
||||||
tab_width: 2,
|
tab_width: 2,
|
||||||
|
syntax_colors: [DEFAULT_COLORS, SYNTAX_COLORS],
|
||||||
};
|
};
|
||||||
|
|
||||||
UIItem* fi = ctx.free_items;
|
UIItem* fi = ctx.free_items;
|
||||||
@ -511,16 +505,16 @@ InitUICtx(PlatformWindow* window)
|
|||||||
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[13] attributes = [
|
||||||
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof + Vec4.sizeof * 0 },
|
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof },
|
||||||
{ binding: 0, location: 1, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof + Vec4.sizeof * 1 },
|
{ binding: 0, location: 1, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof + f32.sizeof*0 },
|
||||||
{ binding: 0, location: 2, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof + Vec4.sizeof * 2 },
|
{ binding: 0, location: 2, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof + f32.sizeof*1 },
|
||||||
{ binding: 0, location: 3, format: FMT.RGBA_F32, offset: Vertex.cols.offsetof + Vec4.sizeof * 3 },
|
{ binding: 0, location: 3, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof + f32.sizeof*2 },
|
||||||
{ binding: 0, location: 4, format: FMT.RG_F32, offset: Vertex.dst_start.offsetof },
|
{ binding: 0, location: 4, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof + f32.sizeof*3 },
|
||||||
{ binding: 0, location: 5, format: FMT.RG_F32, offset: Vertex.dst_end.offsetof },
|
{ binding: 0, location: 5, format: FMT.RG_F32, offset: Vertex.dst_start.offsetof },
|
||||||
{ binding: 0, location: 6, format: FMT.RG_F32, offset: Vertex.src_start.offsetof },
|
{ binding: 0, location: 6, format: FMT.RG_F32, offset: Vertex.dst_end.offsetof },
|
||||||
{ binding: 0, location: 7, format: FMT.RG_F32, offset: Vertex.src_end.offsetof },
|
{ binding: 0, location: 7, format: FMT.RG_F32, offset: Vertex.src_start.offsetof },
|
||||||
{ binding: 0, location: 8, format: FMT.R_F32, offset: Vertex.border_thickness.offsetof } ,
|
{ binding: 0, location: 8, format: FMT.RG_F32, offset: Vertex.src_end.offsetof },
|
||||||
{ binding: 0, location: 9, format: FMT.R_F32, offset: Vertex.corner_radius.offsetof },
|
{ binding: 0, location: 9, format: FMT.R_F32, offset: Vertex.border_thickness.offsetof },
|
||||||
{ 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 },
|
||||||
@ -601,15 +595,22 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
item.flags = flags;
|
item.flags = flags;
|
||||||
|
|
||||||
Set(item, ctx);
|
Set(item, ctx);
|
||||||
if(item.flags & (UIF.CenteredWindow | UIF.FloatingWindow))
|
if(item.flags & (UIF.Window | UIF.FloatingWindow))
|
||||||
{
|
{
|
||||||
item.parent = ctx.window_root;
|
item.parent = g_UI_NIL;
|
||||||
DLLPush(item.parent, item, g_UI_NIL);
|
UIItem* next = ctx.root;
|
||||||
|
while(!Nil(next.next))
|
||||||
|
{
|
||||||
|
next = next.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
next.next = item;
|
||||||
}
|
}
|
||||||
else if(!Nil(item.parent))
|
else if(!Nil(item.parent))
|
||||||
{
|
{
|
||||||
DLLPush(item.parent, item, g_UI_NIL);
|
DLLPush(item.parent, item, g_UI_NIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoPopStacks(ctx);
|
AutoPopStacks(ctx);
|
||||||
|
|
||||||
if(item.last_frame != ctx.frame-1 && item.flags & UIF.Resizeable)
|
if(item.last_frame != ctx.frame-1 && item.flags & UIF.Resizeable)
|
||||||
@ -638,6 +639,13 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
u64 lines = cast(u64)(ceil(text_width/width));
|
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);
|
||||||
|
|
||||||
|
if(item.syntax_tokens.length)
|
||||||
|
{
|
||||||
|
item.token_lines = ScratchAlloc!(u8[])(lines);
|
||||||
|
}
|
||||||
|
|
||||||
f32 w = 0.0;
|
f32 w = 0.0;
|
||||||
u64 line = 0;
|
u64 line = 0;
|
||||||
u64 ch_start = 0;
|
u64 ch_start = 0;
|
||||||
@ -650,7 +658,13 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
f32 glyph_w = GlyphWidth(g);
|
f32 glyph_w = GlyphWidth(g);
|
||||||
if(glyph_w+w > width)
|
if(glyph_w+w > width)
|
||||||
{
|
{
|
||||||
item.text_lines[line++] = str[ch_start .. i];
|
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;
|
ch_start = i;
|
||||||
|
|
||||||
item.max_text_width = item.max_text_width < w ? w : item.max_text_width;
|
item.max_text_width = item.max_text_width < w ? w : item.max_text_width;
|
||||||
@ -658,6 +672,11 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
|||||||
if(line == lines-1)
|
if(line == lines-1)
|
||||||
{
|
{
|
||||||
item.text_lines[line] = str[ch_start .. $];
|
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]);
|
w = CalcTextWidth(item.text_lines[line]);
|
||||||
item.max_text_width = item.max_text_width < w ? w : item.max_text_width;
|
item.max_text_width = item.max_text_width < w ? w : item.max_text_width;
|
||||||
|
|
||||||
@ -676,6 +695,12 @@ 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]);
|
item.max_text_width = CalcTextWidth(item.text_lines[0]);
|
||||||
|
|
||||||
|
if(item.syntax_tokens.length)
|
||||||
|
{
|
||||||
|
item.token_lines = ScratchAlloc!(u8[])(1);
|
||||||
|
item.token_lines[0] = item.syntax_tokens;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 scroll_speed = 1 - pow(2, (-60.0f * g_delta));
|
f32 scroll_speed = 1 - pow(2, (-60.0f * g_delta));
|
||||||
@ -795,9 +820,10 @@ BeginUI(Inputs* inputs)
|
|||||||
|
|
||||||
// Convert Inputs
|
// Convert Inputs
|
||||||
ctx.events.first = ctx.events.last = null;
|
ctx.events.first = ctx.events.last = null;
|
||||||
|
|
||||||
static bool dragging;
|
static bool dragging;
|
||||||
static bool mouse_down;
|
static bool mouse_down;
|
||||||
for(auto i = inputs.first; i; i = i.next)
|
for(InputEvent* i = inputs.first; i; i = i.next)
|
||||||
{
|
{
|
||||||
switch(i.key)
|
switch(i.key)
|
||||||
{
|
{
|
||||||
@ -830,9 +856,19 @@ BeginUI(Inputs* inputs)
|
|||||||
PushUIEvent(ctx, UIInput(type: UIE.Drag, rel: IVec2(i.rel_x, i.rel_y)));
|
PushUIEvent(ctx, UIInput(type: UIE.Drag, rel: IVec2(i.rel_x, i.rel_y)));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case Input.ScrollUp, Input.ScrollDown:
|
||||||
|
{
|
||||||
|
if(i.pressed)
|
||||||
|
{
|
||||||
|
PushUIEvent(ctx, UIInput(type: UIE.Scroll, md: i.md, scroll: i.key == Input.ScrollUp ? -1 : 1));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
PushUIEvent(ctx, UIInput(type: UIE.Press, key: i.key, text: i.pressed ? i.text : []));
|
if(i.pressed)
|
||||||
|
{
|
||||||
|
PushUIEvent(ctx, UIInput(type: UIE.Press, md: i.md, key: i.key, text: i.pressed ? i.text : []));
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -871,7 +907,7 @@ BeginUI(Inputs* inputs)
|
|||||||
BeginRendering(&ctx.rd);
|
BeginRendering(&ctx.rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 ext = GetExtent(&ctx.rd);
|
Vec2 ext = GetExtent();
|
||||||
if(ext != ctx.res)
|
if(ext != ctx.res)
|
||||||
{
|
{
|
||||||
ctx.res = ext;
|
ctx.res = ext;
|
||||||
@ -1027,6 +1063,11 @@ EndUI()
|
|||||||
f32 excess = children_size - size;
|
f32 excess = children_size - size;
|
||||||
for(UIItem* c = item.last; !Nil(c); c = c.prev)
|
for(UIItem* c = item.last; !Nil(c); c = c.prev)
|
||||||
{
|
{
|
||||||
|
if(c.flags & (UIF.FixedPosition | (UIF.OverflowX<<axis)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
f32 leniency = c.size.v[axis] - c.size.v[axis]*c.size_info[axis].strictness;
|
f32 leniency = c.size.v[axis] - c.size.v[axis]*c.size_info[axis].strictness;
|
||||||
f32 reduced = Min(excess, leniency);
|
f32 reduced = Min(excess, leniency);
|
||||||
|
|
||||||
@ -1043,6 +1084,11 @@ EndUI()
|
|||||||
{
|
{
|
||||||
for(UIItem* c = item.last; !Nil(c); c = c.prev)
|
for(UIItem* c = item.last; !Nil(c); c = c.prev)
|
||||||
{
|
{
|
||||||
|
if(c.flags & (UIF.FixedPosition | (UIF.OverflowX<<axis)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
f32 reduced = Min(excess, c.size[axis]);
|
f32 reduced = Min(excess, c.size[axis]);
|
||||||
excess -= reduced;
|
excess -= reduced;
|
||||||
c.size.v[axis] -= reduced;
|
c.size.v[axis] -= reduced;
|
||||||
@ -1052,8 +1098,6 @@ EndUI()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(excess < 0.0009);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1061,6 +1105,11 @@ EndUI()
|
|||||||
{
|
{
|
||||||
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||||
{
|
{
|
||||||
|
if(c.flags & (UIF.FixedPosition | (UIF.OverflowX<<axis)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
c.size.v[axis] = c.size.v[axis] > size ? size : c.size.v[axis];
|
c.size.v[axis] = c.size.v[axis] > size ? size : c.size.v[axis];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1071,51 +1120,46 @@ EndUI()
|
|||||||
f32 pos = 0.0;
|
f32 pos = 0.0;
|
||||||
for(UIItem* item = ctx.root; !Nil(item);)
|
for(UIItem* item = ctx.root; !Nil(item);)
|
||||||
{
|
{
|
||||||
if(item.parent.layout_axis != axis)
|
bool fixed = cast(bool)(item.flags & UIF.FixedPosition);
|
||||||
|
|
||||||
|
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];
|
pos = item.parent.rect.p0.v[axis] + item.parent.padding.v[axis];
|
||||||
}
|
}
|
||||||
else if(item == item.parent.first)
|
|
||||||
|
if(item.view_offset.x != 0.0 || item.view_offset.y != 0.0)
|
||||||
{
|
{
|
||||||
pos += item.parent.padding.v[axis] + item.parent.view_offset.v[axis];
|
for(UIItem* c = item.first; !Nil(c); c = c.next)
|
||||||
|
{
|
||||||
|
if(!(c.flags & UIF.FixedPosition))
|
||||||
|
{
|
||||||
|
c.pos_offset = item.view_offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 inner_pos = pos;
|
|
||||||
f32 next_pos = 0.0;
|
f32 next_pos = 0.0;
|
||||||
f32 end_pos = inner_pos + item.size.v[axis];
|
if(fixed)
|
||||||
|
{
|
||||||
|
item.rect.p0.v[axis] = item.fixed_pos.v[axis] + item.parent.rect.p0.v[axis];
|
||||||
|
item.rect.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis];
|
||||||
|
|
||||||
item.rect.p0.v[axis] = inner_pos;
|
next_pos = pos;
|
||||||
item.rect.p1.v[axis] = end_pos;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.rect.p0.v[axis] = pos + item.pos_offset.v[axis];
|
||||||
|
item.rect.p1.v[axis] = item.rect.p0.v[axis] + item.size.v[axis];
|
||||||
|
|
||||||
next_pos = item.parent.layout_axis == axis ? end_pos : pos;
|
next_pos = item.parent.layout_axis == axis ? item.rect.p1.v[axis] : item.rect.p0.v[axis];
|
||||||
|
}
|
||||||
|
|
||||||
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]));
|
||||||
|
|
||||||
/*
|
|
||||||
debug
|
|
||||||
{
|
|
||||||
bool portal = cast(bool)(item.parent.flags & (UIF.PortalViewX << axis));
|
|
||||||
|
|
||||||
if(!portal && item != ctx.root)
|
|
||||||
{
|
|
||||||
UIItem* p = item.parent;
|
|
||||||
f32 i0 = item.rect.p0.v[axis];
|
|
||||||
f32 i1 = item.rect.p1.v[axis];
|
|
||||||
f32 p0 = item.parent.rect.p0.v[axis] + item.parent.border_thickness;
|
|
||||||
f32 p1 = item.parent.rect.p1.v[axis] - item.parent.border_thickness;
|
|
||||||
|
|
||||||
bool in_bounds_start = i0 >= p0;
|
|
||||||
bool in_bounds_end = i1 <= p1;
|
|
||||||
if(!in_bounds_start || !in_bounds_end)
|
|
||||||
{
|
|
||||||
Errf("[%s] failed bounds check, item bounds: [%s] parent bounds: [%s]", item.key.hash_text, [i0, i1], [p0, p1]);
|
|
||||||
}
|
|
||||||
assert(in_bounds_start && in_bounds_end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(!Nil(item.first))
|
if(!Nil(item.first))
|
||||||
{
|
{
|
||||||
item = item.first;
|
item = item.first;
|
||||||
@ -1169,6 +1213,26 @@ EndUI()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FocusItem(Args...)(string str, Args args)
|
||||||
|
{
|
||||||
|
g_ui_ctx.focus_item = Get(str, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FocusItem(T)(T focus) if(is(T == UIKey) || StringType!T || is(T == UIItem*))
|
||||||
|
{
|
||||||
|
static if(is(T == UIItem*))
|
||||||
|
{
|
||||||
|
assert(!Nil(focus));
|
||||||
|
g_ui_ctx.focus_item = focus;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_ui_ctx.focus_item = Get(focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RenderItem(UICtx* ctx, UIItem* item)
|
RenderItem(UICtx* ctx, UIItem* item)
|
||||||
{
|
{
|
||||||
@ -1194,7 +1258,7 @@ RenderItem(UICtx* ctx, UIItem* item)
|
|||||||
v.dst_start = item.rect.p0 + item.border_thickness;
|
v.dst_start = item.rect.p0 + item.border_thickness;
|
||||||
v.dst_end = item.rect.p1 - item.border_thickness;
|
v.dst_end = item.rect.p1 - item.border_thickness;
|
||||||
v.cols = item.bg_col;
|
v.cols = item.bg_col;
|
||||||
v.corner_radius = item.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);
|
||||||
|
|
||||||
AddVertexCount(ctx);
|
AddVertexCount(ctx);
|
||||||
@ -1222,24 +1286,37 @@ RenderItem(UICtx* ctx, UIItem* item)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// The math around all this is fucked
|
||||||
FontAtlas* atl = &ctx.atlas_buf.atlas;
|
FontAtlas* atl = &ctx.atlas_buf.atlas;
|
||||||
|
|
||||||
f32 y_pos = item.rect.p0.y + item.padding.y;
|
f32 y_pos = item.rect.p0.y + item.padding.y;
|
||||||
|
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] : [];
|
||||||
f32 x_pos = item.flags & UIF.RightAlignText ? item.rect.p1.x - item.padding.x - CalcTextWidth(str) :
|
f32 x_pos = item.flags & UIF.RightAlignText ? item.rect.p1.x - item.padding.x - CalcTextWidth(str) :
|
||||||
item.rect.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, item.rect.p0.x, item.rect.p1.x);
|
||||||
|
|
||||||
|
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 < atl.glyphs.length ? atl.glyphs.ptr + ch : null;
|
||||||
DrawGlyph(item, g, &x_pos, y_pos);
|
DrawGlyph(item, g, &x_pos, y_pos, syntax_cols[tks[j]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach(j; 0 .. str.length)
|
||||||
|
{
|
||||||
|
u8 ch = str[j];
|
||||||
|
Glyph* g = ch < atl.glyphs.length ? atl.glyphs.ptr + ch : null;
|
||||||
|
DrawGlyph(item, g, &x_pos, y_pos, item.text_col);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y_pos += TEXT_SIZE;
|
y_pos += TEXT_SIZE;
|
||||||
@ -1282,16 +1359,9 @@ RenderItems(UIItem* root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32[2]
|
u32[2]
|
||||||
GetExtent(Renderer* rd)
|
GetExtent()
|
||||||
{
|
{
|
||||||
version(ENABLE_RENDERER)
|
version(ENABLE_RENDERER) return RendererGetExtent(&g_ui_ctx.rd); else return [1280, 720];
|
||||||
{
|
|
||||||
return RendererGetExtent(rd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return [1280, 720];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template
|
template
|
||||||
@ -1330,6 +1400,13 @@ PushSizeInfoY(SizeType type, f32 value, f32 strictness = 1.0, bool auto_pop = fa
|
|||||||
PushSizeInfoVec!(1)(type, value, strictness, auto_pop);
|
PushSizeInfoVec!(1)(type, value, strictness, auto_pop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PushCornerRadius(f32 v, bool auto_pop)
|
||||||
|
{
|
||||||
|
Vec4 value = v;
|
||||||
|
Push!("corner_radius")(value, auto_pop);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PushScrollClampVec(int i)(Vec2 clamp, bool auto_pop)
|
PushScrollClampVec(int i)(Vec2 clamp, bool auto_pop)
|
||||||
{
|
{
|
||||||
@ -1350,20 +1427,6 @@ PushScrollClampY(f32 start, f32 end, bool auto_pop = false)
|
|||||||
PushScrollClampVec!(1)(Vec2(start, end), auto_pop);
|
PushScrollClampVec!(1)(Vec2(start, end), auto_pop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PushBorderCol(Vec4 col, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
Vec4[4] arr = col;
|
|
||||||
PushBorderCol(arr, auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PushBgCol(Vec4 col, bool auto_pop = false)
|
|
||||||
{
|
|
||||||
Vec4[4] arr = col;
|
|
||||||
PushBgCol(arr, auto_pop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PushPaddingX(f32 padding, bool auto_pop = false)
|
PushPaddingX(f32 padding, bool auto_pop = false)
|
||||||
{
|
{
|
||||||
@ -1602,53 +1665,6 @@ Recurse(bool pre = true, T)(T* node, T* nil)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
f32
|
|
||||||
LineCounterWidth(u32 char_width)
|
|
||||||
{
|
|
||||||
return f32(char_width)*GetCtx().char_width + LINE_COUNT_PADDING*2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2
|
|
||||||
InnerSize(UIPanel* panel)
|
|
||||||
{
|
|
||||||
return panel.size - Vec2(g_ui_ctx.border_thickness_top.value*2.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SetScrollOffset(UIPanel* panel)
|
|
||||||
{
|
|
||||||
f32 scroll_speed = 5.0;
|
|
||||||
|
|
||||||
U64Vec2 pos = VecPos(&panel.ed.buf);
|
|
||||||
|
|
||||||
f32 c_start = TEXT_SIZE * pos.y+1;
|
|
||||||
f32 c_end = c_start + TEXT_SIZE;
|
|
||||||
f32 height = f32(panel.vis_lines)*TEXT_SIZE;
|
|
||||||
|
|
||||||
f32 boundary_buf = TEXT_SIZE*4.0;
|
|
||||||
f32 top_boundary = panel.scroll_offset+boundary_buf;
|
|
||||||
f32 bot_boundary = panel.scroll_offset+height-boundary_buf;
|
|
||||||
|
|
||||||
if(panel.scroll_offset != 0.0 && c_start < top_boundary)
|
|
||||||
{
|
|
||||||
panel.scroll_target = Max(0.0, c_start-boundary_buf);
|
|
||||||
}
|
|
||||||
else if(c_end > bot_boundary)
|
|
||||||
{
|
|
||||||
panel.scroll_target = panel.scroll_offset + (c_end-bot_boundary);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(panel.scroll_offset != panel.scroll_target)
|
|
||||||
{
|
|
||||||
panel.scroll_offset += (scroll_speed * (panel.scroll_target - panel.scroll_offset)) * (g_delta * 2.0);
|
|
||||||
|
|
||||||
if(fabsf(panel.scroll_offset-panel.scroll_target) < 0.0009)
|
|
||||||
{
|
|
||||||
panel.scroll_offset = panel.scroll_target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UICtx*
|
UICtx*
|
||||||
GetCtx()
|
GetCtx()
|
||||||
{
|
{
|
||||||
@ -1658,7 +1674,7 @@ GetCtx()
|
|||||||
Vec2
|
Vec2
|
||||||
RootSize()
|
RootSize()
|
||||||
{
|
{
|
||||||
return cast(Vec2)GetExtent(&g_ui_ctx.rd);
|
return cast(Vec2)GetExtent();
|
||||||
}
|
}
|
||||||
|
|
||||||
UIKey
|
UIKey
|
||||||
@ -1761,7 +1777,7 @@ NewItem(UICtx* ctx)
|
|||||||
UIItem*
|
UIItem*
|
||||||
Get(Args...)(string str, Args args)
|
Get(Args...)(string str, Args args)
|
||||||
{
|
{
|
||||||
char[] key = sformat(ScratchAlloc!(cast(u64)(str.length*1.5), str, args));
|
char[] key = sformat(ScratchAlloc!(char)(cast(u64)(str.length*1.5)), str, args);
|
||||||
return Get(key);
|
return Get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1807,8 +1823,17 @@ Get(T)(T k) if(is(T: UIKey) || StringType!T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
f32
|
f32
|
||||||
CalcTextWidth(string str)
|
CalcTextWidth(T)(T text) if(is(T == string) || StringType!T)
|
||||||
{
|
{
|
||||||
|
static if(is(T == string))
|
||||||
|
{
|
||||||
|
string str = text;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string str = ConvToStr(text);
|
||||||
|
}
|
||||||
|
|
||||||
u32 tab_width = g_ui_ctx.tab_width;
|
u32 tab_width = g_ui_ctx.tab_width;
|
||||||
Glyph* space = g_ui_ctx.atlas_buf.atlas.glyphs.ptr + ' ';
|
Glyph* space = g_ui_ctx.atlas_buf.atlas.glyphs.ptr + ' ';
|
||||||
|
|
||||||
@ -1824,20 +1849,11 @@ CalcTextWidth(string str)
|
|||||||
pragma(inline) f32
|
pragma(inline) f32
|
||||||
GlyphWidth(Glyph* g)
|
GlyphWidth(Glyph* g)
|
||||||
{
|
{
|
||||||
f32 width = g.ch == '\t' ? (g_ui_ctx.atlas_buf.atlas.glyphs[' '].advance*cast(f32)(g_ui_ctx.tab_width)) : g.advance;
|
return g.ch == '\t' ? (g_ui_ctx.atlas_buf.atlas.glyphs[' '].advance*cast(f32)(g_ui_ctx.tab_width)) : g.advance;
|
||||||
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TextBuffer
|
|
||||||
{
|
|
||||||
u8[] text;
|
|
||||||
TS[] style;
|
|
||||||
TextBuffer* next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y)
|
DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y, Vec4 col = Vec4(1.0))
|
||||||
{
|
{
|
||||||
if(glyph)
|
if(glyph)
|
||||||
{
|
{
|
||||||
@ -1870,9 +1886,11 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y)
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
v.dst_start = Vec2(*x_pos+gb.l, y);
|
f32 y_pos = (y - gb.t) + TEXT_SIZE;
|
||||||
v.dst_end = Vec2(*x_pos+gb.w+gb.l, y+gb.h);
|
|
||||||
v.cols = item.text_col;
|
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.cols = col;
|
||||||
v.texture = true;
|
v.texture = true;
|
||||||
v.bounds = ItemBounds(item);
|
v.bounds = ItemBounds(item);
|
||||||
|
|
||||||
@ -1933,31 +1951,6 @@ GetVertex(UICtx* ctx)
|
|||||||
return ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
return ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
|
||||||
DrawCmdRect(Vec2 pos, Vec2 size, bool edit)
|
|
||||||
{
|
|
||||||
UICtx* ctx = GetCtx();
|
|
||||||
|
|
||||||
Vec4[4] bg_col = edit ? ctx.bg_hl_col_top.value : ctx.bg_col_top.value;
|
|
||||||
Vec4[4] border_col = edit ? ctx.border_hl_col_top.value : ctx.border_col_top.value;
|
|
||||||
|
|
||||||
DrawRect(pos, size, ctx.corner_radius_top.value, ctx.border_thickness_top.value, bg_col);
|
|
||||||
DrawBorder(pos, size, ctx.border_thickness_top.value, ctx.corner_radius_top.value, ctx.edge_softness_top.value, border_col);
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline) void
|
|
||||||
DrawPanel(UIPanel* panel, f32 lc_w, bool focus)
|
|
||||||
{
|
|
||||||
UICtx* ctx = GetCtx();
|
|
||||||
|
|
||||||
Vec2 pos = panel.rect.p0;
|
|
||||||
Vec2 size = panel.size;
|
|
||||||
|
|
||||||
DrawRect(pos, size, ctx.corner_radius_top.value, ctx.border_thickness_top.value, ctx.bg_col_top.value);
|
|
||||||
DrawRect(pos, Vec2(lc_w, size.y), 0.0, 0.0, focus ? ctx.bg_hl_col_top.value : ctx.bg_col_top.value);
|
|
||||||
DrawBorder(pos, size, ctx.border_thickness_top.value, ctx.corner_radius_top.value, ctx.edge_softness_top.value, focus ? ctx.border_hl_col_top.value : ctx.border_col_top.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static UISize[2]
|
static UISize[2]
|
||||||
MakeUISize(UISize x, UISize y)
|
MakeUISize(UISize x, UISize y)
|
||||||
{
|
{
|
||||||
@ -1983,62 +1976,6 @@ GetGlyph(u8 ch)
|
|||||||
return ch < a.glyphs.length ? a.glyphs.ptr + ch : a.glyphs.ptr;
|
return ch < a.glyphs.length ? a.glyphs.ptr + ch : a.glyphs.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
|
||||||
DrawRect(f32 x, f32 y, u8 ch, Vec4 col, bool edit_mode)
|
|
||||||
{
|
|
||||||
Glyph* g = GetGlyph(ch);
|
|
||||||
Vec4[4] cols = col;
|
|
||||||
DrawRect(Vec2(x, y-TEXT_SIZE*0.8), Vec2(edit_mode ? 1.0 : g.advance, TEXT_SIZE), 0.0, 0.0, cols);
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline) void
|
|
||||||
DrawRect(Vec2 pos, Vec2 size, f32 corner_radius, f32 border_thickness, Vec4[4] cols)
|
|
||||||
{
|
|
||||||
UICtx* ctx = GetCtx();
|
|
||||||
DrawRect(pos.x, pos.y, size.x, size.y, corner_radius, border_thickness, cols);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DrawRect(f32 x, f32 y, f32 w, f32 h, f32 corner_radius, f32 border, Vec4[4] cols)
|
|
||||||
{
|
|
||||||
UICtx* ctx = GetCtx();
|
|
||||||
|
|
||||||
Vertex* v = GetVertex(ctx);
|
|
||||||
v.dst_start.x = x;
|
|
||||||
v.dst_start.y = y;
|
|
||||||
v.dst_end.x = x+w;
|
|
||||||
v.dst_end.y = y+h;
|
|
||||||
v.cols = cols;
|
|
||||||
v.corner_radius = corner_radius;
|
|
||||||
|
|
||||||
v.border_thickness = v.edge_softness = v.raised = 0.0;
|
|
||||||
|
|
||||||
if(border > 0.0)
|
|
||||||
{
|
|
||||||
v.dst_start += border;
|
|
||||||
v.dst_end -= border;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddVertexCount(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DrawBorder(Vec2 pos, Vec2 size, f32 border, f32 radius, f32 softness, Vec4[4] cols)
|
|
||||||
{
|
|
||||||
UICtx* ctx = GetCtx();
|
|
||||||
|
|
||||||
Vertex* v = GetVertex(ctx);
|
|
||||||
v.dst_start = pos;
|
|
||||||
v.dst_end = pos + size;
|
|
||||||
v.cols = cols;
|
|
||||||
v.corner_radius = radius;
|
|
||||||
v.border_thickness = border;
|
|
||||||
v.edge_softness = softness;
|
|
||||||
v.raised = 0.0;
|
|
||||||
|
|
||||||
AddVertexCount(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
AddVertexCount(UICtx* ctx)
|
AddVertexCount(UICtx* ctx)
|
||||||
{
|
{
|
||||||
@ -2058,67 +1995,6 @@ InBounds(T)(T pos, Rect* rect)
|
|||||||
return pos.x >= rect.p0.x && pos.x <= rect.p1.x && pos.y >= rect.p0.y && pos.y <= rect.p1.y;
|
return pos.x >= rect.p0.x && pos.x <= rect.p1.x && pos.y >= rect.p0.y && pos.y <= rect.p1.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
Clicked(UIItem* item, Rect* rect)
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
UICtx* ctx = GetCtx();
|
|
||||||
|
|
||||||
for(auto n = ctx.inputs.first; !CheckNil(null, n) && Nil(ctx.drag_item); n = n.next)
|
|
||||||
{
|
|
||||||
InputEvent* ev = n;
|
|
||||||
|
|
||||||
if(ev.key == Input.LeftClick && ev.pressed && InBounds(ev, rect))
|
|
||||||
{
|
|
||||||
result = true;
|
|
||||||
DLLRemove(ctx.inputs, n, null);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Dragged(UIItem* item, Rect* rect)
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
UICtx* ctx = GetCtx();
|
|
||||||
|
|
||||||
item.dragged = 0;
|
|
||||||
|
|
||||||
if(Nil(ctx.drag_item) && Clicked(item, rect))
|
|
||||||
{
|
|
||||||
ctx.drag_item = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto n = ctx.inputs.first; !CheckNil(null, n) && ctx.drag_item == item; n = n.next)
|
|
||||||
{
|
|
||||||
InputEvent* ev = n;
|
|
||||||
bool taken;
|
|
||||||
|
|
||||||
if(ev.key == Input.MouseMotion)
|
|
||||||
{
|
|
||||||
item.dragged.x += ev.rel_x;
|
|
||||||
item.dragged.y += ev.rel_y;
|
|
||||||
result = true;
|
|
||||||
taken = true;
|
|
||||||
}
|
|
||||||
else if(ev.key == Input.LeftClick && !ev.pressed)
|
|
||||||
{
|
|
||||||
ctx.drag_item = g_UI_NIL;
|
|
||||||
taken = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(taken)
|
|
||||||
{
|
|
||||||
DLLRemove(ctx.inputs, n, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Vec4[4]
|
static Vec4[4]
|
||||||
Vec4Arr(Vec4 vec)
|
Vec4Arr(Vec4 vec)
|
||||||
{
|
{
|
||||||
@ -2168,7 +2044,7 @@ unittest
|
|||||||
|
|
||||||
EndUI();
|
EndUI();
|
||||||
|
|
||||||
Vec2 extent = GetExtent(null);
|
Vec2 extent = GetExtent();
|
||||||
assert(extent == ctx.root.size);
|
assert(extent == ctx.root.size);
|
||||||
|
|
||||||
BeginUI(&inputs);
|
BeginUI(&inputs);
|
||||||
|
|||||||
@ -8,14 +8,33 @@ import std.algorithm.comparison : clamp;
|
|||||||
import std.format;
|
import std.format;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
|
|
||||||
bool
|
__gshared const Panel g_nil_panel;
|
||||||
Nil(UIPanel* panel)
|
__gshared Panel* g_NIL_PANEL;
|
||||||
|
__gshared const Editor g_nil_ed;
|
||||||
|
__gshared Editor* g_NIL_ED;
|
||||||
|
|
||||||
|
Vec4 BG_COL = Vec4(0.18, 0.18, 0.18, 1.0);
|
||||||
|
|
||||||
|
Vec4 CMD_COL = Vec4(0.22, 0.22, 0.22, 1.0);
|
||||||
|
Vec4 HL_BG_COL = Vec4(0.160, 0.533, 0.803, 1.0);
|
||||||
|
Vec4 HL_BORDER_COL = Vec4(0.172, 0.643, 0.988, 1.0);
|
||||||
|
|
||||||
|
shared static this()
|
||||||
{
|
{
|
||||||
return panel == null || panel == g_UI_NIL_PANEL;
|
g_NIL_PANEL = cast(Panel* )&g_nil_panel;
|
||||||
|
g_NIL_ED = cast(Editor*)&g_nil_ed;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Panel
|
||||||
|
{
|
||||||
|
Panel* first, last, next, prev, parent;
|
||||||
|
Axis2D layout_axis;
|
||||||
|
Editor* ed;
|
||||||
|
u64 id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LineCounterView(u64 max_line, u64 lines, u64 line_offset, f32 view_offset)
|
LineCounterView(u64 max_line, u64 lines, i64 line_offset, f32 view_offset)
|
||||||
{
|
{
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
UIKey zero = ZeroKey();
|
UIKey zero = ZeroKey();
|
||||||
@ -35,7 +54,7 @@ LineCounterView(u64 max_line, u64 lines, u64 line_offset, f32 view_offset)
|
|||||||
PushParent(line_count);
|
PushParent(line_count);
|
||||||
|
|
||||||
u64 end_line = lines+line_offset;
|
u64 end_line = lines+line_offset;
|
||||||
for(u64 i = line_offset; i < end_line; i += 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(buf, "%s", i)), true);
|
||||||
@ -46,8 +65,10 @@ LineCounterView(u64 max_line, u64 lines, u64 line_offset, f32 view_offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EditorTextView(UIItem* editor, Editor* ed, u64 lines, u64 line_offset, f32 view_offset)
|
EditorTextView(UIItem* editor, Panel* p, u64 lines, i64 line_offset, f32 view_offset)
|
||||||
{
|
{
|
||||||
|
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 clamp_y = cast(f32)(ed.buf.line_count-lines)*TEXT_SIZE;
|
||||||
@ -60,59 +81,61 @@ EditorTextView(UIItem* editor, Editor* ed, u64 lines, u64 line_offset, f32 view_
|
|||||||
PushScrollTargetY(scroll_pos, true);
|
PushScrollTargetY(scroll_pos, true);
|
||||||
PushViewOffsetY(view_offset, true);
|
PushViewOffsetY(view_offset, true);
|
||||||
|
|
||||||
static bool end;
|
|
||||||
static f32 count = 0.0;
|
|
||||||
|
|
||||||
if(!end)
|
|
||||||
{
|
|
||||||
ed.cursor_pos.y = 500;
|
|
||||||
count += g_delta;
|
|
||||||
if(count > 0.5)
|
|
||||||
{
|
|
||||||
end = !end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ed.cursor_pos.y = 0;
|
|
||||||
count -= g_delta;
|
|
||||||
if(count <= 0.0)
|
|
||||||
{
|
|
||||||
end = !end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
editor = MakeItem(editor.key, UIF.DrawBorder|UIF.ScrollY|UIF.ClampY);
|
editor = MakeItem(editor.key, UIF.DrawBorder|UIF.ScrollY|UIF.ClampY);
|
||||||
|
|
||||||
u64 end_line = line_offset+lines;
|
PushParent(editor);
|
||||||
|
|
||||||
UIKey zero = ZeroKey();
|
UIKey zero = ZeroKey();
|
||||||
|
|
||||||
PushSizeInfoY(ST.TextSize, 1.0);
|
// Cursor
|
||||||
PushParent(editor);
|
{
|
||||||
|
LineBuffer* lb = GetLine(&ed.buf, ed.cursor_pos.y);
|
||||||
|
|
||||||
scope(exit) Pop!("size_info", "parent");
|
f32 cursor_x = CalcTextWidth(lb.text[0 .. ed.cursor_pos.x]);
|
||||||
|
f32 cursor_y = cast(f32)(ed.cursor_pos.y - line_offset)*TEXT_SIZE + view_offset;
|
||||||
|
PushSizeInfo(MakeUISize(UISize(ST.Pixels, GetCtx().char_width), UISize(ST.Pixels, TEXT_SIZE)), true);
|
||||||
|
PushFixedPos(Vec2(cursor_x, cursor_y), true);
|
||||||
|
PushBgCol(Vec4(1.0), true);
|
||||||
|
MakeItem(zero, UIF.DrawBackground|UIF.FixedPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 end_line = line_offset+lines;
|
||||||
|
PushSizeInfoY(ST.TextSize, 1.0);
|
||||||
|
PushSyntaxHighlight(UISH.D);
|
||||||
|
|
||||||
|
scope(exit) Pop!("size_info", "parent", "syntax_highlight");
|
||||||
|
|
||||||
u64 i = line_offset;
|
u64 i = line_offset;
|
||||||
for(LineBuffer* lb = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, lb) && i < line_offset+lines; i += 1, lb = GetLine(&ed.buf, i))
|
for(LineBuffer* lb = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, lb) && i < line_offset+lines; i += 1, lb = GetLine(&ed.buf, i))
|
||||||
{
|
{
|
||||||
PushDisplayString(ConvToStr(lb.text), true);
|
PushDisplayString(ConvToStr(lb.text), true);
|
||||||
|
PushSyntaxTokens(cast(u8[])lb.style, true);
|
||||||
UIItem* line = MakeItem(zero, UIF.DrawText);
|
UIItem* line = MakeItem(zero, UIF.DrawText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EditorView(Editor* ed)
|
EditorView(Panel* p)
|
||||||
{
|
{
|
||||||
|
Editor* ed = p.ed;
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
UIKey zero = ZeroKey();
|
UIKey zero = ZeroKey();
|
||||||
|
|
||||||
|
if(CheckNil(g_NIL_ED, ed))
|
||||||
|
{
|
||||||
|
for(Panel* c = p.first; !CheckNil(g_NIL_PANEL, c); c = c.next)
|
||||||
|
{
|
||||||
|
EditorView(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
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;
|
u64 frame_line_offset = ed.line_offset;
|
||||||
f32 frame_view_offset = -(editor.scroll_offset.y%TEXT_SIZE);
|
f32 frame_view_offset = -(editor.scroll_offset.y%TEXT_SIZE);
|
||||||
|
|
||||||
PushBgCol(Vec4(0.2, 0.3, 0.8, 1.0), true);
|
PushBgCol(BG_COL, true);
|
||||||
PushSizeInfoX(ST.Percentage, 1.0, 1.0, true);
|
PushSizeInfoX(ST.Percentage, 1.0, 1.0, true);
|
||||||
|
|
||||||
UIItem* container = MakeItem(zero, UIF.DrawBackground);
|
UIItem* container = MakeItem(zero, UIF.DrawBackground);
|
||||||
@ -144,10 +167,95 @@ EditorView(Editor* ed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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(ed.buf.line_count, view_lines, start, frame_view_offset);
|
||||||
|
EditorTextView(editor, p, view_lines, start, frame_view_offset);
|
||||||
|
|
||||||
EditorTextView(editor, ed, 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)
|
||||||
|
{
|
||||||
|
bool taken;
|
||||||
|
|
||||||
|
if(i.type == UIE.Scroll)
|
||||||
|
{
|
||||||
|
ed.line_offset = clamp(ed.line_offset+(i.scroll*2), 0, ed.buf.line_count);
|
||||||
|
if(ed.cursor_pos.y < ed.line_offset)
|
||||||
|
{
|
||||||
|
ed.cursor_pos.y = ed.line_offset;
|
||||||
|
}
|
||||||
|
else if(ed.cursor_pos.y > ed.line_offset+view_lines)
|
||||||
|
{
|
||||||
|
ed.cursor_pos.y = ed.line_offset+view_lines-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleInputs(p, &ctx.events);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(taken)
|
||||||
|
{
|
||||||
|
DLLRemove(&ctx.events, i, g_UI_NIL_INPUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ed.cursor_pos = VecPos(&ed.buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CommandPalette(CmdPalette* cmd)
|
||||||
|
{
|
||||||
|
UICtx* ctx = GetCtx();
|
||||||
|
Vec2 ext = GetExtent();
|
||||||
|
|
||||||
|
f32 w = ext.x*0.4;
|
||||||
|
f32 h = ext.y*0.7;
|
||||||
|
|
||||||
|
PushFixedPos(Vec2(ext.x*0.3, ext.y*0.1), true);
|
||||||
|
PushBgCol(BG_COL, true);
|
||||||
|
PushBorderCol(HL_BORDER_COL, true);
|
||||||
|
PushBorderThickness(2.0f, true);
|
||||||
|
PushCornerRadius(8.0f, true);
|
||||||
|
PushViewOffset(Vec2(-2.0f), true);
|
||||||
|
PushLayoutAxis(A2D.Y, true);
|
||||||
|
PushSizeInfo(MakeUISize(UISize(ST.Pixels, w), UISize(ST.Pixels, h)));
|
||||||
|
|
||||||
|
UIItem* cmd_item = MakeItem("###cmd_palette", UIF.Window|UIF.FixedPosition|UIF.DrawBackground|UIF.DrawBorder);
|
||||||
|
|
||||||
|
f32 padding_y = 8.0;
|
||||||
|
PushParent(cmd_item);
|
||||||
|
PushPadding(Vec2(4.0, padding_y), true);
|
||||||
|
scope(exit) Pop!("parent", "padding")();
|
||||||
|
|
||||||
|
PushBgCol(HL_BG_COL, true);
|
||||||
|
PushBorderCol(HL_BORDER_COL);
|
||||||
|
PushBorderThickness(2.0f, true);
|
||||||
|
PushCornerRadius(Vec4(8.0, 8.0, 0.0, 0.0), true);
|
||||||
|
PushSizeInfo(MakeUISize(UISize(ST.Pixels, w-padding_y), UISize(ST.TextSize, 1.0)), true);
|
||||||
|
PushDisplayString(ConvToStr(cmd.buffer[0 .. cmd.icount]), true);
|
||||||
|
|
||||||
|
UIKey zero = ZeroKey();
|
||||||
|
|
||||||
|
MakeItem(zero, UIF.DrawBorder|UIF.DrawBackground|UIF.DrawText|UIF.Overflow);
|
||||||
|
|
||||||
|
PushPadding(Vec2(4.0));
|
||||||
|
PushSizeInfoY(ST.TextSize, 1.0);
|
||||||
|
scope(exit) Pop!("size_info", "padding")();
|
||||||
|
|
||||||
|
Vec4[2] opt_cols = [
|
||||||
|
Vec4(0.22, 0.22, 0.22, 1.0),
|
||||||
|
Vec4(0.35, 0.35, 0.35, 1.0),
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach(i; 0 .. cmd.opt_strs.length)
|
||||||
|
{
|
||||||
|
PushDisplayString(ConvToStr(cmd.opt_strs[i]), true);
|
||||||
|
PushBgCol(cmd.selected == i ? HL_BG_COL : opt_cols[i%2], true);
|
||||||
|
MakeItem(zero, UIF.DrawBackground|UIF.DrawText);
|
||||||
|
}
|
||||||
|
|
||||||
|
//PushDisplayString(ConvToStr(cmd.buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -4,16 +4,16 @@
|
|||||||
|
|
||||||
#include "gui.layout"
|
#include "gui.layout"
|
||||||
|
|
||||||
layout (location = 0) in vec4 in_col_1;
|
layout (location = 0) in vec4 in_col;
|
||||||
layout (location = 1) in vec4 in_col_2;
|
layout (location = 1) in float in_corner_radius_x0y0;
|
||||||
layout (location = 2) in vec4 in_col_3;
|
layout (location = 2) in float in_corner_radius_x1y0;
|
||||||
layout (location = 3) in vec4 in_col_4;
|
layout (location = 3) in float in_corner_radius_x0y1;
|
||||||
layout (location = 4) in vec2 in_dst_start;
|
layout (location = 4) in float in_corner_radius_x1y1;
|
||||||
layout (location = 5) in vec2 in_dst_end;
|
layout (location = 5) in vec2 in_dst_start;
|
||||||
layout (location = 6) in vec2 in_src_start;
|
layout (location = 6) in vec2 in_dst_end;
|
||||||
layout (location = 7) in vec2 in_src_end;
|
layout (location = 7) in vec2 in_src_start;
|
||||||
layout (location = 8) in float border_thickness;
|
layout (location = 8) in vec2 in_src_end;
|
||||||
layout (location = 9) in float corner_radius;
|
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;
|
||||||
@ -33,7 +33,6 @@ layout (location = 1) out struct FragDataOut {
|
|||||||
float border_thickness;
|
float border_thickness;
|
||||||
} FragData;
|
} FragData;
|
||||||
|
|
||||||
|
|
||||||
vec2 Vertices[4] = vec2[4](
|
vec2 Vertices[4] = vec2[4](
|
||||||
vec2(-1.0, -1.0),
|
vec2(-1.0, -1.0),
|
||||||
vec2(-1.0, +1.0),
|
vec2(-1.0, +1.0),
|
||||||
@ -68,22 +67,22 @@ void main()
|
|||||||
vec2(in_src_end.x, in_src_end.y)
|
vec2(in_src_end.x, in_src_end.y)
|
||||||
);
|
);
|
||||||
|
|
||||||
vec4 cols[4] = vec4[4](
|
float corner_radius[4] = float[4](
|
||||||
in_col_1,
|
in_corner_radius_x0y0,
|
||||||
in_col_2,
|
in_corner_radius_x0y1,
|
||||||
in_col_3,
|
in_corner_radius_x1y0,
|
||||||
in_col_4
|
in_corner_radius_x1y1
|
||||||
);
|
);
|
||||||
|
|
||||||
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 = cols[gl_VertexIndex];
|
FragData.color = in_col;
|
||||||
FragData.uv = uvs[gl_VertexIndex] / tex_size;
|
FragData.uv = uvs[gl_VertexIndex] / tex_size;
|
||||||
FragData.dst_pos = pos;
|
FragData.dst_pos = pos;
|
||||||
FragData.dst_center = center;
|
FragData.dst_center = center;
|
||||||
FragData.dst_half_size = half_size;
|
FragData.dst_half_size = half_size;
|
||||||
FragData.corner_radius = corner_radius;
|
FragData.corner_radius = corner_radius[gl_VertexIndex];
|
||||||
FragData.softness = edge_softness;
|
FragData.softness = edge_softness;
|
||||||
FragData.raised = raised;
|
FragData.raised = raised;
|
||||||
FragData.border_thickness = border_thickness;
|
FragData.border_thickness = border_thickness;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user