ui panels mostly working
This commit is contained in:
parent
1358683331
commit
988223b675
@ -1 +1 @@
|
|||||||
Subproject commit 65ac576cb0f37e797030365ef25d11a771468654
|
Subproject commit 7a77505fc100da21a5bf804e415be8eb1f36ba19
|
||||||
2
src/dlib
2
src/dlib
@ -1 +1 @@
|
|||||||
Subproject commit 5ff3cd91d73464e88bff3daef94a0a3bea2c3cb7
|
Subproject commit 6757559089314da06956460c32ff632db7d10f88
|
||||||
@ -39,7 +39,7 @@ CreateFlatBuffer(u8[] data)
|
|||||||
u64 line_count = 1;
|
u64 line_count = 1;
|
||||||
for(u64 i = 0; i < cast(u64)data.length; i += 1)
|
for(u64 i = 0; i < cast(u64)data.length; i += 1)
|
||||||
{
|
{
|
||||||
if (data.ptr[i] == '\n')
|
if(data.ptr[i] == '\n')
|
||||||
{
|
{
|
||||||
line_count += 1;
|
line_count += 1;
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ CreateLineBuffers(u64 arena_size)
|
|||||||
void
|
void
|
||||||
Insert(FlatBuffer* buffer, u8[] insert, u64 length, u64 pos)
|
Insert(FlatBuffer* buffer, u8[] insert, u64 length, u64 pos)
|
||||||
{
|
{
|
||||||
if (buffer.length + length > buffer.data.length)
|
if(buffer.length + length > buffer.data.length)
|
||||||
{
|
{
|
||||||
FlatBuffer new_buf = CreateFlatBuffer(buffer.data);
|
FlatBuffer new_buf = CreateFlatBuffer(buffer.data);
|
||||||
MFreeArray(buffer.data);
|
MFreeArray(buffer.data);
|
||||||
@ -79,7 +79,7 @@ Insert(FlatBuffer* buffer, u8[] insert, u64 length, u64 pos)
|
|||||||
|
|
||||||
for(u64 i = 0; i < length; i += 1)
|
for(u64 i = 0; i < length; i += 1)
|
||||||
{
|
{
|
||||||
if (insert.ptr[i] == '\n')
|
if(insert.ptr[i] == '\n')
|
||||||
{
|
{
|
||||||
buffer.line_count += 1;
|
buffer.line_count += 1;
|
||||||
}
|
}
|
||||||
@ -121,19 +121,19 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
|||||||
u64 current_line = 0;
|
u64 current_line = 0;
|
||||||
for(u64 i = 0; i < buffer.length; i += 1)
|
for(u64 i = 0; i < buffer.length; i += 1)
|
||||||
{
|
{
|
||||||
if (current_line == length)
|
if(current_line == length)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool new_line = (buffer.data.ptr[i] == '\n');
|
bool new_line = (buffer.data.ptr[i] == '\n');
|
||||||
if (line < start_line && new_line)
|
if(line < start_line && new_line)
|
||||||
{
|
{
|
||||||
line += 1;
|
line += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start < 0 && new_line)
|
if(start < 0 && new_line)
|
||||||
{
|
{
|
||||||
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, 1);
|
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, 1);
|
||||||
linebufs.lines[current_line][0] = '\n';
|
linebufs.lines[current_line][0] = '\n';
|
||||||
@ -141,13 +141,13 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start < 0)
|
if(start < 0)
|
||||||
{
|
{
|
||||||
start = cast(i64)i;
|
start = cast(i64)i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_line)
|
if(new_line)
|
||||||
{
|
{
|
||||||
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, (i-start));
|
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, (i-start));
|
||||||
linebufs.lines[current_line][0 .. i-start] = buffer.data[start .. i];
|
linebufs.lines[current_line][0 .. i-start] = buffer.data[start .. i];
|
||||||
@ -156,7 +156,7 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == buffer.length-1)
|
if(i == buffer.length-1)
|
||||||
{
|
{
|
||||||
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, (buffer.length-start));
|
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, (buffer.length-start));
|
||||||
linebufs.lines[current_line][0 .. buffer.length-start] = buffer.data[start .. buffer.length];
|
linebufs.lines[current_line][0 .. buffer.length-start] = buffer.data[start .. buffer.length];
|
||||||
@ -171,13 +171,13 @@ RangeToPos(FlatBuffer* buffer, Range range)
|
|||||||
u32 line, col;
|
u32 line, col;
|
||||||
for(u64 i = 0; i < buffer.length; i += 1)
|
for(u64 i = 0; i < buffer.length; i += 1)
|
||||||
{
|
{
|
||||||
if (range.y == line)
|
if(range.y == line)
|
||||||
{
|
{
|
||||||
buffer_pos = i;
|
buffer_pos = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer.data.ptr[i] == '\n')
|
if(buffer.data.ptr[i] == '\n')
|
||||||
{
|
{
|
||||||
line += 1;
|
line += 1;
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ RangeToPos(FlatBuffer* buffer, Range range)
|
|||||||
|
|
||||||
for(u64 i = buffer_pos; i < buffer.length; i += 1)
|
for(u64 i = buffer_pos; i < buffer.length; i += 1)
|
||||||
{
|
{
|
||||||
if (col == range.x)
|
if(col == range.x)
|
||||||
{
|
{
|
||||||
buffer_pos = i;
|
buffer_pos = i;
|
||||||
break;
|
break;
|
||||||
@ -206,7 +206,7 @@ Delete(FlatBuffer* buffer, u64 length, u64 pos)
|
|||||||
assert(end <= buffer.length, "Delete failure: pos+length is not in range");
|
assert(end <= buffer.length, "Delete failure: pos+length is not in range");
|
||||||
|
|
||||||
u8[] temp;
|
u8[] temp;
|
||||||
if (end != buffer.length)
|
if(end != buffer.length)
|
||||||
{
|
{
|
||||||
temp = AllocArray!(u8)(&buffer.arena, buffer.length-end);
|
temp = AllocArray!(u8)(&buffer.arena, buffer.length-end);
|
||||||
temp[0 .. temp.length] = buffer.data[end .. buffer.length];
|
temp[0 .. temp.length] = buffer.data[end .. buffer.length];
|
||||||
@ -351,7 +351,7 @@ Advance(FlatBuffer* fb)
|
|||||||
bool delim = CheckDelimiter(ch);
|
bool delim = CheckDelimiter(ch);
|
||||||
bool str = CheckString(ch);
|
bool str = CheckString(ch);
|
||||||
|
|
||||||
if (!started && delim)
|
if(!started && delim)
|
||||||
{
|
{
|
||||||
tk.pos = i;
|
tk.pos = i;
|
||||||
tk.pos_end = i+1;
|
tk.pos_end = i+1;
|
||||||
@ -359,7 +359,7 @@ Advance(FlatBuffer* fb)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!started && !space)
|
if(!started && !space)
|
||||||
{
|
{
|
||||||
tk.pos = i;
|
tk.pos = i;
|
||||||
started = true;
|
started = true;
|
||||||
@ -367,12 +367,12 @@ Advance(FlatBuffer* fb)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (started && (delim || space) && !str_started)
|
if(started && (delim || space) && !str_started)
|
||||||
{
|
{
|
||||||
result = true;
|
result = true;
|
||||||
tk.pos_end = i;
|
tk.pos_end = i;
|
||||||
|
|
||||||
if (ch == EOF)
|
if(ch == EOF)
|
||||||
{
|
{
|
||||||
Logf("final token");
|
Logf("final token");
|
||||||
tk.final_token = true;
|
tk.final_token = true;
|
||||||
@ -388,7 +388,7 @@ Advance(FlatBuffer* fb)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (started && str_started && str)
|
if(started && str_started && str)
|
||||||
{
|
{
|
||||||
result = true;
|
result = true;
|
||||||
tk.pos_end = i+1;
|
tk.pos_end = i+1;
|
||||||
@ -562,7 +562,7 @@ Highlight(FlatBuffer* fb)
|
|||||||
u8[] token;
|
u8[] token;
|
||||||
u8[] prev_token;
|
u8[] prev_token;
|
||||||
|
|
||||||
if (tk.final_token)
|
if(tk.final_token)
|
||||||
{
|
{
|
||||||
goto InnerTokenStream;
|
goto InnerTokenStream;
|
||||||
}
|
}
|
||||||
@ -574,48 +574,48 @@ InnerTokenStream:
|
|||||||
token = fb.data[tk.pos .. tk.pos_end];
|
token = fb.data[tk.pos .. tk.pos_end];
|
||||||
scope(exit) prev_token = token;
|
scope(exit) prev_token = token;
|
||||||
|
|
||||||
if (token.length == 0) break;
|
if(token.length == 0) break;
|
||||||
|
|
||||||
if (token.length == 1 && CheckDelimiter(token.ptr[0]))
|
if(token.length == 1 && CheckDelimiter(token.ptr[0]))
|
||||||
{
|
{
|
||||||
tk.buffer[tk.pos] = TS.Bracket;
|
tk.buffer[tk.pos] = TS.Bracket;
|
||||||
continue TokenStream;
|
continue TokenStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckString(token[0]) && CheckString(token[token.length-1]) && token[0] == token[token.length-1])
|
if(CheckString(token[0]) && CheckString(token[token.length-1]) && token[0] == token[token.length-1])
|
||||||
{
|
{
|
||||||
tk.buffer[tk.pos .. tk.pos_end] = TS.String;
|
tk.buffer[tk.pos .. tk.pos_end] = TS.String;
|
||||||
continue TokenStream;
|
continue TokenStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token[0] >= '0' && token[0] <= '9')
|
if(token[0] >= '0' && token[0] <= '9')
|
||||||
{
|
{
|
||||||
tk.buffer[tk.pos .. tk.pos_end] = TS.Number;
|
tk.buffer[tk.pos .. tk.pos_end] = TS.Number;
|
||||||
continue TokenStream;
|
continue TokenStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((token[0] >= 'a' && token[0] <= 'z') || (token[0] >= 'A' && token[0] <= 'Z') || token[0] == '_')
|
if((token[0] >= 'a' && token[0] <= 'z') || (token[0] >= 'A' && token[0] <= 'Z') || token[0] == '_')
|
||||||
{
|
{
|
||||||
if (prev_token == r"import")
|
if(prev_token == r"import")
|
||||||
{
|
{
|
||||||
tk.buffer[tk.pos .. tk.pos_end] = TS.ImportTarget;
|
tk.buffer[tk.pos .. tk.pos_end] = TS.ImportTarget;
|
||||||
continue TokenStream;
|
continue TokenStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tk.next_type == TS.Exclamation)
|
if(tk.next_type == TS.Exclamation)
|
||||||
{
|
{
|
||||||
tk.buffer[tk.pos .. tk.pos_end] = TS.Macro;
|
tk.buffer[tk.pos .. tk.pos_end] = TS.Macro;
|
||||||
continue TokenStream;
|
continue TokenStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 index = cast(u8)(token[0]-cast(u8)95);
|
u8 index = cast(u8)(token[0]-cast(u8)95);
|
||||||
if (index > 0 && index < keywords.length)
|
if(index > 0 && index < keywords.length)
|
||||||
{
|
{
|
||||||
// TODO: look at simd string comparison
|
// TODO: look at simd string comparison
|
||||||
const(u8[])[] key_table = keywords[index];
|
const(u8[])[] key_table = keywords[index];
|
||||||
foreach(key; key_table)
|
foreach(key; key_table)
|
||||||
{
|
{
|
||||||
if (token == key)
|
if(token == key)
|
||||||
{
|
{
|
||||||
tk.buffer[tk.pos .. tk.pos_end] = TS.Keyword;
|
tk.buffer[tk.pos .. tk.pos_end] = TS.Keyword;
|
||||||
continue TokenStream;
|
continue TokenStream;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import std.format : sformat;
|
|||||||
import dlib.alloc;
|
import dlib.alloc;
|
||||||
import buffer;
|
import buffer;
|
||||||
import ui;
|
import ui;
|
||||||
|
import widgets : Nil;
|
||||||
import widgets;
|
import widgets;
|
||||||
|
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
@ -15,12 +16,12 @@ import std.exception;
|
|||||||
|
|
||||||
f32 g_delta = 0.0;
|
f32 g_delta = 0.0;
|
||||||
|
|
||||||
EditorCtx g_ed_ctx;
|
|
||||||
|
|
||||||
struct EditorCtx
|
struct EditorCtx
|
||||||
{
|
{
|
||||||
Arena arena;
|
Arena arena;
|
||||||
UIPanel* base_panel;
|
UIPanel* base_panel;
|
||||||
|
u64 panel_id;
|
||||||
|
EditState state;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Editor
|
struct Editor
|
||||||
@ -40,26 +41,33 @@ struct Editor
|
|||||||
u64 line_offset;
|
u64 line_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EditState
|
||||||
|
{
|
||||||
|
NormalMode,
|
||||||
|
InputMode,
|
||||||
|
CmdOpen,
|
||||||
|
SetPanelFocus,
|
||||||
|
}
|
||||||
|
|
||||||
|
alias ES = EditState;
|
||||||
|
|
||||||
void
|
void
|
||||||
Cycle(Inputs* inputs)
|
Cycle(EditorCtx* ctx, Inputs* inputs)
|
||||||
{
|
{
|
||||||
ResetScratch(MB(4));
|
ResetScratch(MB(4));
|
||||||
|
|
||||||
|
assert(Nil(ctx.base_panel.next));
|
||||||
|
|
||||||
|
HandleInputs(ctx, inputs);
|
||||||
|
|
||||||
BeginBuild(inputs);
|
BeginBuild(inputs);
|
||||||
|
|
||||||
static UIPanel panel = {
|
DrawPanels(ctx.base_panel);
|
||||||
id: CastStr!(u8)("##base"),
|
|
||||||
axis: A2D.Y,
|
|
||||||
pct: 1.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
Panel(&panel);
|
|
||||||
EndPanel();
|
|
||||||
|
|
||||||
EndBuild();
|
EndBuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
EditorCtx
|
||||||
InitEditorCtx(PlatformWindow* window)
|
InitEditorCtx(PlatformWindow* window)
|
||||||
{
|
{
|
||||||
InitFreeType();
|
InitFreeType();
|
||||||
@ -70,7 +78,197 @@ InitEditorCtx(PlatformWindow* window)
|
|||||||
arena: CreateArena(MB(2)),
|
arena: CreateArena(MB(2)),
|
||||||
};
|
};
|
||||||
|
|
||||||
g_ed_ctx = ctx;
|
ctx.base_panel = CreatePanel(&ctx);
|
||||||
|
ctx.base_panel.ed = CreateEditor(&ctx);
|
||||||
|
SetFocusedPanel(ctx.base_panel);
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIPanel*
|
||||||
|
CreatePanel(EditorCtx* ctx)
|
||||||
|
{
|
||||||
|
UIPanel* p = Alloc!(UIPanel)(&ctx.arena);
|
||||||
|
p.axis = A2D.Y;
|
||||||
|
p.id = AllocArray!(u8)(&ctx.arena, 10);
|
||||||
|
p.pct = 1.0;
|
||||||
|
(cast(char[])p.id).sformat("##%08s", ctx.panel_id);
|
||||||
|
p.parent = p.first = p.last = p.next = p.prev = g_UI_NIL_PANEL;
|
||||||
|
|
||||||
|
ctx.panel_id += 1;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load all files then move things into editor after being created when selected
|
||||||
|
|
||||||
|
Editor*
|
||||||
|
CreateEditor(EditorCtx* ctx)
|
||||||
|
{
|
||||||
|
Editor* ed = Alloc!(Editor)(&ctx.arena);
|
||||||
|
|
||||||
|
ed.arena = CreateArena(MB(4));
|
||||||
|
|
||||||
|
return ed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AddEditor(EditorCtx* ctx, UIPanel* target, Axis2D axis)
|
||||||
|
{
|
||||||
|
if(Nil(target.parent) || target.parent.axis != axis)
|
||||||
|
{
|
||||||
|
UIPanel* first = CreatePanel(ctx);
|
||||||
|
UIPanel* second = CreatePanel(ctx);
|
||||||
|
|
||||||
|
first.ed = target.ed;
|
||||||
|
second.ed = CreateEditor(ctx);
|
||||||
|
|
||||||
|
first.pct = second.pct = 0.5;
|
||||||
|
|
||||||
|
target.axis = axis;
|
||||||
|
target.ed = null;
|
||||||
|
|
||||||
|
PushPanel(target, first);
|
||||||
|
PushPanel(target, second);
|
||||||
|
|
||||||
|
SetFocusedPanel(second);
|
||||||
|
}
|
||||||
|
else if(target.parent.axis == axis)
|
||||||
|
{
|
||||||
|
UIPanel* panel = CreatePanel(ctx);
|
||||||
|
panel.ed = CreateEditor(ctx);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetFocusedPanel(panel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
||||||
|
{
|
||||||
|
for(auto node = inputs.list.first; node != null; node = node.next)
|
||||||
|
{
|
||||||
|
bool taken = false;
|
||||||
|
|
||||||
|
Input key = node.value.key;
|
||||||
|
bool pressed = node.value.pressed;
|
||||||
|
|
||||||
|
if (pressed)
|
||||||
|
{
|
||||||
|
switch(key)
|
||||||
|
{
|
||||||
|
case Input.i:
|
||||||
|
{
|
||||||
|
if(ctx.state == ES.NormalMode)
|
||||||
|
{
|
||||||
|
ctx.state = ES.InputMode;
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case Input.Esc:
|
||||||
|
{
|
||||||
|
if(ctx.state == ES.InputMode || ctx.state == ES.CmdOpen)
|
||||||
|
{
|
||||||
|
ctx.state = ES.NormalMode;
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case Input.Semicolon:
|
||||||
|
{
|
||||||
|
if(node.value.md & (MD.LeftShift | MD.RightShift))
|
||||||
|
{
|
||||||
|
if(ctx.state != ES.NormalMode)
|
||||||
|
{
|
||||||
|
ctx.state = ES.CmdOpen;
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case Input.w:
|
||||||
|
{
|
||||||
|
if(ctx.state == ES.NormalMode && node.value.md & (MD.LeftCtrl | MD.RightCtrl))
|
||||||
|
{
|
||||||
|
ctx.state = ES.SetPanelFocus;
|
||||||
|
taken = true;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case Input.v:
|
||||||
|
{
|
||||||
|
if(ctx.state == ES.NormalMode)
|
||||||
|
{
|
||||||
|
AddEditor(ctx, GetFocusedPanel(), A2D.X);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case Input.c:
|
||||||
|
{
|
||||||
|
if(ctx.state == ES.NormalMode)
|
||||||
|
{
|
||||||
|
AddEditor(ctx, GetFocusedPanel(), A2D.Y);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case Input.Up:
|
||||||
|
case Input.Down:
|
||||||
|
case Input.Left:
|
||||||
|
case Input.Right:
|
||||||
|
{
|
||||||
|
if(false)
|
||||||
|
{
|
||||||
|
UIPanel* panel = GetFocusedPanel();
|
||||||
|
UIPanel* focused = g_UI_NIL_PANEL;
|
||||||
|
for(UIPanel* p = panel; !Nil(p); p = p.parent)
|
||||||
|
{
|
||||||
|
if(p.parent.axis == A2D.X)
|
||||||
|
{
|
||||||
|
if(key == Input.Left && !Nil(p.prev) && p.prev.ed != null)
|
||||||
|
{
|
||||||
|
focused = p.prev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(key == Input.Right && !Nil(p.next) && p.next.ed != null)
|
||||||
|
{
|
||||||
|
focused = p.next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(key == Input.Up && !Nil(p.prev) && p.prev.ed != null)
|
||||||
|
{
|
||||||
|
focused = p.prev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(key == Input.Down && !Nil(p.next) && p.next.ed != null)
|
||||||
|
{
|
||||||
|
focused = p.next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetFocusedPanel(focused);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(taken)
|
||||||
|
{
|
||||||
|
DLLRemove(&inputs.list, node, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -102,13 +300,13 @@ DrawBuffer(Editor* ed, f32 x, f32 y, f32 px, FlatBuffer* fb)
|
|||||||
{
|
{
|
||||||
u8 ch = fb.data[i];
|
u8 ch = fb.data[i];
|
||||||
|
|
||||||
if (ch > 0 && ch < ed.atlas_buf.atlas.glyphs.length)
|
if(ch > 0 && ch < ed.atlas_buf.atlas.glyphs.length)
|
||||||
{
|
{
|
||||||
Glyph* g = ed.atlas_buf.atlas.glyphs.ptr + ch;
|
Glyph* g = ed.atlas_buf.atlas.glyphs.ptr + ch;
|
||||||
|
|
||||||
if (g.advance > 0.0)
|
if(g.advance > 0.0)
|
||||||
{
|
{
|
||||||
if (ch == '\t')
|
if(ch == '\t')
|
||||||
{
|
{
|
||||||
g.atlas_left = g.atlas_right = 0.0;
|
g.atlas_left = g.atlas_right = 0.0;
|
||||||
foreach(j; 0 .. tab_count)
|
foreach(j; 0 .. tab_count)
|
||||||
@ -116,7 +314,7 @@ DrawBuffer(Editor* ed, f32 x, f32 y, f32 px, FlatBuffer* fb)
|
|||||||
DrawGlyph(g, scale, &x_pos, y_pos);
|
DrawGlyph(g, scale, &x_pos, y_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ch == '\n')
|
else if(ch == '\n')
|
||||||
{
|
{
|
||||||
g.atlas_left = g.atlas_right = 0.0;
|
g.atlas_left = g.atlas_right = 0.0;
|
||||||
DrawGlyph(g, scale, &x_pos, y_pos);
|
DrawGlyph(g, scale, &x_pos, y_pos);
|
||||||
|
|||||||
@ -9,7 +9,7 @@ void main(string[] argv)
|
|||||||
{
|
{
|
||||||
u8[] buffer = null;
|
u8[] buffer = null;
|
||||||
u8[] buffer_name = null;
|
u8[] buffer_name = null;
|
||||||
if (argv.length > 1)
|
if(argv.length > 1)
|
||||||
{
|
{
|
||||||
buffer_name = (cast(u8*)argv[1].ptr)[0 .. argv[1].length];
|
buffer_name = (cast(u8*)argv[1].ptr)[0 .. argv[1].length];
|
||||||
File f = File(argv[1], "rb");
|
File f = File(argv[1], "rb");
|
||||||
@ -21,16 +21,16 @@ void main(string[] argv)
|
|||||||
PlatformWindow window = CreateWindow("Editor", 1920, 1080);
|
PlatformWindow window = CreateWindow("Editor", 1920, 1080);
|
||||||
StartPlatformThread(&window);
|
StartPlatformThread(&window);
|
||||||
|
|
||||||
InitEditorCtx(&window);
|
EditorCtx ctx = InitEditorCtx(&window);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Inputs* inputs = GetEvents(&window);
|
Inputs* inputs = GetEvents(&window);
|
||||||
if (window.close)
|
if(window.close)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cycle(inputs);
|
Cycle(&ctx, inputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -154,7 +154,7 @@ Tokenize(FlatBuffer* fb)
|
|||||||
u64 semi_count;
|
u64 semi_count;
|
||||||
foreach(i; 0 .. fb.length)
|
foreach(i; 0 .. fb.length)
|
||||||
{
|
{
|
||||||
if (fb.data.ptr[i] == ';')
|
if(fb.data.ptr[i] == ';')
|
||||||
{
|
{
|
||||||
semi_count += 1;
|
semi_count += 1;
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ Tokenize(FlatBuffer* fb)
|
|||||||
{
|
{
|
||||||
scope(exit) tk.tk_count += 1;
|
scope(exit) tk.tk_count += 1;
|
||||||
Token* t = NextToken(fb);
|
Token* t = NextToken(fb);
|
||||||
if (t == null) break;
|
if(t == null) break;
|
||||||
|
|
||||||
switch(t.type)
|
switch(t.type)
|
||||||
{
|
{
|
||||||
@ -201,16 +201,16 @@ Tokenize(FlatBuffer* fb)
|
|||||||
} break;
|
} break;
|
||||||
case TT.LeftBracket:
|
case TT.LeftBracket:
|
||||||
{
|
{
|
||||||
if (prev != null && _macro && prev.type != TT.Exclamation)
|
if(prev != null && _macro && prev.type != TT.Exclamation)
|
||||||
{
|
{
|
||||||
_macro = false;
|
_macro = false;
|
||||||
}
|
}
|
||||||
} goto case TT.Comma;
|
} goto case TT.Comma;
|
||||||
case TT.LeftBrace:
|
case TT.LeftBrace:
|
||||||
{
|
{
|
||||||
if (prev)
|
if(prev)
|
||||||
{
|
{
|
||||||
if (prev.type == TT.RightBracket)
|
if(prev.type == TT.RightBracket)
|
||||||
{
|
{
|
||||||
i64 i = tk.tk_count - 2;
|
i64 i = tk.tk_count - 2;
|
||||||
Token* pt = null;
|
Token* pt = null;
|
||||||
@ -221,24 +221,24 @@ Tokenize(FlatBuffer* fb)
|
|||||||
pt = tk.tokens.ptr + i;
|
pt = tk.tokens.ptr + i;
|
||||||
i -= 1;
|
i -= 1;
|
||||||
|
|
||||||
if (pt.type == TT.Keyword && brackets == 0) break;
|
if(pt.type == TT.Keyword && brackets == 0) break;
|
||||||
|
|
||||||
if (pt.type == TT.LeftBracket)
|
if(pt.type == TT.LeftBracket)
|
||||||
{
|
{
|
||||||
brackets -= 1;
|
brackets -= 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pt.type == TT.RightBracket)
|
if(pt.type == TT.RightBracket)
|
||||||
{
|
{
|
||||||
brackets += 1;
|
brackets += 1;
|
||||||
is_macro = true;
|
is_macro = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pt.type == TT.Identifier && brackets == 0)
|
if(pt.type == TT.Identifier && brackets == 0)
|
||||||
{
|
{
|
||||||
if (i >= 0)
|
if(i >= 0)
|
||||||
{
|
{
|
||||||
Token* tmp = tk.tokens.ptr + i;
|
Token* tmp = tk.tokens.ptr + i;
|
||||||
tmp.type = TT.Type;
|
tmp.type = TT.Type;
|
||||||
@ -258,24 +258,24 @@ Tokenize(FlatBuffer* fb)
|
|||||||
|
|
||||||
bool id_keyword = pt.type == TT.Identifier || pt.type == TT.Keyword;
|
bool id_keyword = pt.type == TT.Identifier || pt.type == TT.Keyword;
|
||||||
|
|
||||||
if ( is_macro && brackets == 4) break;
|
if( is_macro && brackets == 4) break;
|
||||||
if (!is_macro && brackets == 2) break;
|
if(!is_macro && brackets == 2) break;
|
||||||
|
|
||||||
if (is_macro && brackets < 2 && id_keyword)
|
if(is_macro && brackets < 2 && id_keyword)
|
||||||
{
|
{
|
||||||
pt.type = TT.Type;
|
pt.type = TT.Type;
|
||||||
tk.buffer[pt.start .. pt.end] = TS.Type;
|
tk.buffer[pt.start .. pt.end] = TS.Type;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((!is_macro && brackets < 2) || (is_macro && brackets == 3)) && id_keyword && (ppt.type == TT.LeftBracket || ppt.type == TT.Comma))
|
if(((!is_macro && brackets < 2) || (is_macro && brackets == 3)) && id_keyword && (ppt.type == TT.LeftBracket || ppt.type == TT.Comma))
|
||||||
{
|
{
|
||||||
pt.type = TT.Type;
|
pt.type = TT.Type;
|
||||||
tk.buffer[pt.start .. pt.end] = TS.Type;
|
tk.buffer[pt.start .. pt.end] = TS.Type;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pt.type == TT.LeftBracket || pt.type == TT.RightBracket)
|
if(pt.type == TT.LeftBracket || pt.type == TT.RightBracket)
|
||||||
{
|
{
|
||||||
brackets += 1;
|
brackets += 1;
|
||||||
continue;
|
continue;
|
||||||
@ -347,17 +347,17 @@ NextToken(FlatBuffer* fb)
|
|||||||
u8 ch = fb.data[tk.pos];
|
u8 ch = fb.data[tk.pos];
|
||||||
|
|
||||||
Token* t = null;
|
Token* t = null;
|
||||||
if (tk.pos < fb.length)
|
if(tk.pos < fb.length)
|
||||||
{
|
{
|
||||||
t = tk.tokens.ptr + tk.tk_count;
|
t = tk.tokens.ptr + tk.tk_count;
|
||||||
t.start = tk.pos;
|
t.start = tk.pos;
|
||||||
|
|
||||||
bool ascii = (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
|
bool ascii = (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
|
||||||
|
|
||||||
if (ch == 'r')
|
if(ch == 'r')
|
||||||
{
|
{
|
||||||
u8 next = PeekNextChar(fb);
|
u8 next = PeekNextChar(fb);
|
||||||
if (next == '"')
|
if(next == '"')
|
||||||
{
|
{
|
||||||
tk.pos += 1;
|
tk.pos += 1;
|
||||||
ParseStr(fb);
|
ParseStr(fb);
|
||||||
@ -367,14 +367,14 @@ NextToken(FlatBuffer* fb)
|
|||||||
ParseId(fb);
|
ParseId(fb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ch >= '0' && ch <= '9')
|
else if(ch >= '0' && ch <= '9')
|
||||||
{
|
{
|
||||||
ParseNum(fb);
|
ParseNum(fb);
|
||||||
}
|
}
|
||||||
else if (ch == 'P' || ch == 'E' || ch == 'e' || ch == 'p')
|
else if(ch == 'P' || ch == 'E' || ch == 'e' || ch == 'p')
|
||||||
{
|
{
|
||||||
u8 next = PeekNextChar(fb);
|
u8 next = PeekNextChar(fb);
|
||||||
if (next == '-' || next == '+' || (next >= '0' && next <= '9'))
|
if(next == '-' || next == '+' || (next >= '0' && next <= '9'))
|
||||||
{
|
{
|
||||||
ParseNum(fb);
|
ParseNum(fb);
|
||||||
}
|
}
|
||||||
@ -383,7 +383,7 @@ NextToken(FlatBuffer* fb)
|
|||||||
ParseId(fb);
|
ParseId(fb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ascii || ch == '_')
|
else if(ascii || ch == '_')
|
||||||
{
|
{
|
||||||
ParseId(fb);
|
ParseId(fb);
|
||||||
}
|
}
|
||||||
@ -453,8 +453,8 @@ NextToken(FlatBuffer* fb)
|
|||||||
tk.pos += 1;
|
tk.pos += 1;
|
||||||
u8 c = fb.data[tk.pos];
|
u8 c = fb.data[tk.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;
|
t.end = tk.pos;
|
||||||
@ -465,7 +465,7 @@ NextToken(FlatBuffer* fb)
|
|||||||
while (tk.pos < fb.length)
|
while (tk.pos < fb.length)
|
||||||
{
|
{
|
||||||
tk.pos += 1;
|
tk.pos += 1;
|
||||||
if (tk.pos != '.') break;
|
if(tk.pos != '.') break;
|
||||||
}
|
}
|
||||||
t.end = tk.pos;
|
t.end = tk.pos;
|
||||||
} break;
|
} break;
|
||||||
@ -473,7 +473,7 @@ NextToken(FlatBuffer* fb)
|
|||||||
{
|
{
|
||||||
t.type = TT.Slash;
|
t.type = TT.Slash;
|
||||||
u8 next = PeekNextChar(fb);
|
u8 next = PeekNextChar(fb);
|
||||||
if (next == '/')
|
if(next == '/')
|
||||||
{
|
{
|
||||||
tk.pos += 1;
|
tk.pos += 1;
|
||||||
t.type = TT.Comment;
|
t.type = TT.Comment;
|
||||||
@ -482,7 +482,7 @@ NextToken(FlatBuffer* fb)
|
|||||||
{
|
{
|
||||||
tk.pos += 1;
|
tk.pos += 1;
|
||||||
|
|
||||||
if (CheckEOL(fb.data[tk.pos]))
|
if(CheckEOL(fb.data[tk.pos]))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -498,7 +498,7 @@ NextToken(FlatBuffer* fb)
|
|||||||
case 251:
|
case 251:
|
||||||
{
|
{
|
||||||
u8 next = PeekNextChar(fb);
|
u8 next = PeekNextChar(fb);
|
||||||
if (next == '=')
|
if(next == '=')
|
||||||
{
|
{
|
||||||
tk.pos += 1;
|
tk.pos += 1;
|
||||||
}
|
}
|
||||||
@ -538,7 +538,7 @@ ParseNum(FlatBuffer* fb)
|
|||||||
|
|
||||||
u8 ch = fb.data[tk.pos];
|
u8 ch = fb.data[tk.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))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -549,7 +549,7 @@ ParseNum(FlatBuffer* fb)
|
|||||||
while (tk.pos < fb.length)
|
while (tk.pos < fb.length)
|
||||||
{
|
{
|
||||||
u8 ch = fb.data[tk.pos];
|
u8 ch = fb.data[tk.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;
|
||||||
}
|
}
|
||||||
@ -593,7 +593,7 @@ ParseId(FlatBuffer* fb)
|
|||||||
|
|
||||||
u8 ch = fb.data[tk.pos];
|
u8 ch = fb.data[tk.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'))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -602,12 +602,12 @@ ParseId(FlatBuffer* fb)
|
|||||||
t.end = tk.pos;
|
t.end = tk.pos;
|
||||||
|
|
||||||
u8 ch = cast(u8)(fb.data[t.start] - cast(u8)(95)); // Index into keywords lookup
|
u8 ch = cast(u8)(fb.data[t.start] - cast(u8)(95)); // Index into keywords lookup
|
||||||
if (ch < D_KEYWORDS.length && D_KEYWORDS[ch].length > 0)
|
if(ch < D_KEYWORDS.length && D_KEYWORDS[ch].length > 0)
|
||||||
{
|
{
|
||||||
u8[] id = fb.data[t.start .. t.end];
|
u8[] id = fb.data[t.start .. t.end];
|
||||||
foreach(k; D_KEYWORDS[ch])
|
foreach(k; D_KEYWORDS[ch])
|
||||||
{
|
{
|
||||||
if (id == k)
|
if(id == k)
|
||||||
{
|
{
|
||||||
t.type = TT.Keyword;
|
t.type = TT.Keyword;
|
||||||
break;
|
break;
|
||||||
@ -648,7 +648,7 @@ SkipWhiteSpace(FlatBuffer* fb)
|
|||||||
|
|
||||||
bool white_space = CheckWhiteSpace(ch);
|
bool white_space = CheckWhiteSpace(ch);
|
||||||
|
|
||||||
if (!white_space)
|
if(!white_space)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
170
src/editor/ui.d
170
src/editor/ui.d
@ -7,6 +7,7 @@ import dlib.fonts;
|
|||||||
import vulkan;
|
import vulkan;
|
||||||
import widgets;
|
import widgets;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
import std.math.traits : isNaN;
|
||||||
import std.math.rounding : ceil;
|
import std.math.rounding : ceil;
|
||||||
import std.format : sformat;
|
import std.format : sformat;
|
||||||
import core.stdc.string : memset;
|
import core.stdc.string : memset;
|
||||||
@ -44,6 +45,7 @@ enum UIFlags
|
|||||||
DrawBorder = 0x04,
|
DrawBorder = 0x04,
|
||||||
Clickable = 0x08,
|
Clickable = 0x08,
|
||||||
Draggable = 0x10,
|
Draggable = 0x10,
|
||||||
|
TextInput = 0x20,
|
||||||
}
|
}
|
||||||
|
|
||||||
alias UIF = UIFlags;
|
alias UIF = UIFlags;
|
||||||
@ -69,6 +71,7 @@ struct UICtx
|
|||||||
{
|
{
|
||||||
HashTable!(UIHash, UIItem*) items;
|
HashTable!(UIHash, UIItem*) items;
|
||||||
Arena arena;
|
Arena arena;
|
||||||
|
Arena temp_arena;
|
||||||
Inputs* inputs;
|
Inputs* inputs;
|
||||||
u64 frame;
|
u64 frame;
|
||||||
u64 f_idx;
|
u64 f_idx;
|
||||||
@ -94,10 +97,10 @@ struct UICtx
|
|||||||
UIItemNode* prev_sibling;
|
UIItemNode* prev_sibling;
|
||||||
u32 panel_level;
|
u32 panel_level;
|
||||||
UIItem* drag_item;
|
UIItem* drag_item;
|
||||||
|
UIItem* focused;
|
||||||
|
|
||||||
UIItemStackList stack_free_list;
|
UIItemStackList stack_free_list;
|
||||||
|
|
||||||
FontAtlas atlas;
|
|
||||||
Vec4[4] color;
|
Vec4[4] color;
|
||||||
Vec4[4] border_color;
|
Vec4[4] border_color;
|
||||||
Vec4 text_color;
|
Vec4 text_color;
|
||||||
@ -108,6 +111,9 @@ struct UICtx
|
|||||||
f32 border_thickness;
|
f32 border_thickness;
|
||||||
f32 corner_radius;
|
f32 corner_radius;
|
||||||
f32 edge_softness;
|
f32 edge_softness;
|
||||||
|
|
||||||
|
debug u32 item_count;
|
||||||
|
debug u32 final_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIItemStackList
|
struct UIItemStackList
|
||||||
@ -134,6 +140,7 @@ struct UIItem
|
|||||||
UIItem* last; // last child
|
UIItem* last; // last child
|
||||||
UIItem* parent;
|
UIItem* parent;
|
||||||
|
|
||||||
|
u64 last_frame;
|
||||||
u32 level;
|
u32 level;
|
||||||
Vec2 dragged;
|
Vec2 dragged;
|
||||||
|
|
||||||
@ -246,11 +253,13 @@ InitUICtx(PlatformWindow* window)
|
|||||||
rd: InitRenderer(handles, MB(16), MB(8)),
|
rd: InitRenderer(handles, MB(16), MB(8)),
|
||||||
items: CreateHashTable!(UIHash, UIItem*)(12),
|
items: CreateHashTable!(UIHash, UIItem*)(12),
|
||||||
arena: arena,
|
arena: arena,
|
||||||
|
temp_arena: CreateArena(MB(1)),
|
||||||
root: g_UI_NIL,
|
root: g_UI_NIL,
|
||||||
top_parent: g_UI_NIL_NODE,
|
top_parent: g_UI_NIL_NODE,
|
||||||
prev_sibling: g_UI_NIL_NODE,
|
prev_sibling: g_UI_NIL_NODE,
|
||||||
drag_item: g_UI_NIL,
|
drag_item: g_UI_NIL,
|
||||||
text_size: 14.0,
|
focused: g_UI_NIL,
|
||||||
|
text_size: 16.0,
|
||||||
tab_width: 2,
|
tab_width: 2,
|
||||||
border_thickness: 0.0,
|
border_thickness: 0.0,
|
||||||
corner_radius: 0.0,
|
corner_radius: 0.0,
|
||||||
@ -260,6 +269,7 @@ InitUICtx(PlatformWindow* window)
|
|||||||
atlas_buf: atlas_buf,
|
atlas_buf: atlas_buf,
|
||||||
font: font,
|
font: font,
|
||||||
font_data: cast(u8[])FONT_BYTES,
|
font_data: cast(u8[])FONT_BYTES,
|
||||||
|
adjustment: 0.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 vertex_size = 10000;
|
u64 vertex_size = 10000;
|
||||||
@ -330,7 +340,7 @@ PopItemNode()
|
|||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
|
|
||||||
UIItemNode* node;
|
UIItemNode* node;
|
||||||
if (!CheckNil(g_UI_NIL_NODE, ctx.stack_free_list.first))
|
if(!CheckNil(g_UI_NIL_NODE, ctx.stack_free_list.first))
|
||||||
{
|
{
|
||||||
node = SLLPop(&ctx.stack_free_list, g_UI_NIL_NODE);
|
node = SLLPop(&ctx.stack_free_list, g_UI_NIL_NODE);
|
||||||
}
|
}
|
||||||
@ -370,7 +380,7 @@ PopSiblingPanel()
|
|||||||
UIItem* panel = g_UI_NIL;
|
UIItem* panel = g_UI_NIL;
|
||||||
UIItemNode* node = ctx.prev_sibling;
|
UIItemNode* node = ctx.prev_sibling;
|
||||||
|
|
||||||
if (node != g_UI_NIL_NODE)
|
if(node != g_UI_NIL_NODE)
|
||||||
{
|
{
|
||||||
panel = node.item;
|
panel = node.item;
|
||||||
ctx.prev_sibling = node.next;
|
ctx.prev_sibling = node.next;
|
||||||
@ -404,22 +414,22 @@ PrevSiblingPanel(UIItem* panel)
|
|||||||
UIItemNode* prev = ctx.prev_sibling;
|
UIItemNode* prev = ctx.prev_sibling;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
if (panel == prev.item)
|
if(panel == prev.item)
|
||||||
{
|
{
|
||||||
prev = prev.next;
|
prev = prev.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev == g_UI_NIL_NODE)
|
if(prev == g_UI_NIL_NODE)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev.item.level < panel.level)
|
if(prev.item.level < panel.level)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev.item.level == panel.level)
|
if(prev.item.level == panel.level)
|
||||||
{
|
{
|
||||||
result = prev.item;
|
result = prev.item;
|
||||||
break;
|
break;
|
||||||
@ -538,6 +548,21 @@ BeginBuild(Inputs* inputs)
|
|||||||
{
|
{
|
||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
|
|
||||||
|
debug ctx.item_count = 0;
|
||||||
|
debug ctx.final_count = 0;
|
||||||
|
|
||||||
|
Reset(&ctx.temp_arena);
|
||||||
|
|
||||||
|
KVPair!(u64, UIItem*)*[] items = GetAllNodes(&ctx.temp_arena, &ctx.items);
|
||||||
|
for(u64 i = 0; i < items.length; i += 1)
|
||||||
|
{
|
||||||
|
UIItem* item = items[i].value;
|
||||||
|
if(item.last_frame != ctx.frame-1)
|
||||||
|
{
|
||||||
|
Delete(&ctx.items, items[i].key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
|
ctx.f_idx = ctx.frame%FRAME_OVERLAP;
|
||||||
|
|
||||||
ctx.inputs = inputs;
|
ctx.inputs = inputs;
|
||||||
@ -573,6 +598,8 @@ EndBuild()
|
|||||||
|
|
||||||
DrawUI(ctx, ctx.root);
|
DrawUI(ctx, ctx.root);
|
||||||
|
|
||||||
|
debug assert(ctx.item_count == ctx.final_count);
|
||||||
|
|
||||||
BindBuffers(&ctx.rd, &ctx.buffers[ctx.f_idx].m_idx, &ctx.buffers[ctx.f_idx].m_vtx);
|
BindBuffers(&ctx.rd, &ctx.buffers[ctx.f_idx].m_idx, &ctx.buffers[ctx.f_idx].m_vtx);
|
||||||
DrawIndexed(&ctx.rd, 6, ctx.buffers[ctx.f_idx].count, 0);
|
DrawIndexed(&ctx.rd, 6, ctx.buffers[ctx.f_idx].count, 0);
|
||||||
|
|
||||||
@ -582,11 +609,11 @@ EndBuild()
|
|||||||
|
|
||||||
debug
|
debug
|
||||||
{
|
{
|
||||||
static bool first = false;
|
static u32 prev_count = 0;
|
||||||
if (!first)
|
if(prev_count != ctx.item_count)
|
||||||
{
|
{
|
||||||
PrintNodes(ctx.root);
|
//PrintNodes(ctx.root);
|
||||||
first = true;
|
prev_count = ctx.item_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -599,7 +626,7 @@ PrepRendering(UICtx* ctx)
|
|||||||
BeginRendering(&ctx.rd);
|
BeginRendering(&ctx.rd);
|
||||||
|
|
||||||
Vec2 ext = GetExtent(&ctx.rd);
|
Vec2 ext = GetExtent(&ctx.rd);
|
||||||
if (ext != ctx.res)
|
if(ext != ctx.res)
|
||||||
{
|
{
|
||||||
ctx.res = ext;
|
ctx.res = ext;
|
||||||
Ortho(&ctx.pc.projection, 0.0, 0.0, ext.x, ext.y, 1000.0, 0.1);
|
Ortho(&ctx.pc.projection, 0.0, 0.0, ext.x, ext.y, 1000.0, 0.1);
|
||||||
@ -620,7 +647,7 @@ CompleteRendering(UICtx* ctx)
|
|||||||
void
|
void
|
||||||
PrintNodes(UIItem* item)
|
PrintNodes(UIItem* item)
|
||||||
{
|
{
|
||||||
if (!Nil(item))
|
if(!Nil(item))
|
||||||
{
|
{
|
||||||
Logf("x0 %s x1 %s y0 %s y1 %s", item.rect.x0, item.rect.x1, item.rect.y0, item.rect.y1);
|
Logf("x0 %s x1 %s y0 %s y1 %s", item.rect.x0, item.rect.x1, item.rect.y0, item.rect.y1);
|
||||||
|
|
||||||
@ -636,9 +663,10 @@ CalcFixedSizes(UIItem* item)
|
|||||||
{
|
{
|
||||||
static foreach(axis; A2D.min .. A2D.max)
|
static foreach(axis; A2D.min .. A2D.max)
|
||||||
{
|
{
|
||||||
if (i.size_info[axis].type == ST.Pixels)
|
if(i.size_info[axis].type == ST.Pixels)
|
||||||
{
|
{
|
||||||
i.size.v[axis] = i.size_info[axis].value + i.adjustment.v[axis];
|
i.size.v[axis] = i.size_info[axis].value + i.adjustment.v[axis];
|
||||||
|
assert(!isNaN(i.size.v[axis]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -651,9 +679,10 @@ CalcPercentageSizes(UIItem* item)
|
|||||||
{
|
{
|
||||||
static foreach(axis; A2D.min .. A2D.max)
|
static foreach(axis; A2D.min .. A2D.max)
|
||||||
{
|
{
|
||||||
if (i.size_info[axis].type == ST.Percentage)
|
if(i.size_info[axis].type == ST.Percentage)
|
||||||
{
|
{
|
||||||
i.size.v[axis] = (i.parent.size.v[axis]*i.size_info[axis].value) + i.adjustment.v[axis];
|
i.size.v[axis] = (i.parent.size.v[axis]*i.size_info[axis].value) + i.adjustment.v[axis];
|
||||||
|
assert(!isNaN(i.size.v[axis]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,18 +698,21 @@ CalcPositions(alias axis)(UIItem* item)
|
|||||||
i.rect.vec0.v[axis] = pos;
|
i.rect.vec0.v[axis] = pos;
|
||||||
i.rect.vec1.v[axis] = end_pos;
|
i.rect.vec1.v[axis] = end_pos;
|
||||||
|
|
||||||
|
assert(!isNaN(i.rect.vec0.v[axis]));
|
||||||
|
assert(!isNaN(i.rect.vec1.v[axis]));
|
||||||
|
|
||||||
f32 next_pos = i.parent.layout_axis == axis ? end_pos : pos;
|
f32 next_pos = i.parent.layout_axis == axis ? end_pos : pos;
|
||||||
|
|
||||||
if (!Nil(i.first))
|
if(!Nil(i.first))
|
||||||
{
|
{
|
||||||
i = i.first;
|
i = i.first;
|
||||||
}
|
}
|
||||||
else if (!Nil(i.next))
|
else if(!Nil(i.next))
|
||||||
{
|
{
|
||||||
i = i.next;
|
i = i.next;
|
||||||
pos = next_pos;
|
pos = next_pos;
|
||||||
}
|
}
|
||||||
else if (!Nil(i.parent.next))
|
else if(!Nil(i.parent.next))
|
||||||
{
|
{
|
||||||
i = i.parent.next;
|
i = i.parent.next;
|
||||||
pos = i.parent.layout_axis == axis ? i.prev.rect.vec1.v[axis] : i.prev.rect.vec0.v[axis];
|
pos = i.parent.layout_axis == axis ? i.prev.rect.vec1.v[axis] : i.prev.rect.vec0.v[axis];
|
||||||
@ -697,20 +729,22 @@ DrawUI(UICtx* ctx, UIItem* item)
|
|||||||
{
|
{
|
||||||
for(UIItem* i = item; !Nil(i); i = Recurse(i))
|
for(UIItem* i = item; !Nil(i); i = Recurse(i))
|
||||||
{
|
{
|
||||||
if (i.flags & UIF.DrawBackground)
|
if(i.flags & UIF.DrawBackground)
|
||||||
{
|
{
|
||||||
DrawRect(ctx, i);
|
DrawRect(ctx, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.flags & UIF.DrawBorder)
|
if(i.flags & UIF.DrawBorder)
|
||||||
{
|
{
|
||||||
DrawBorder(ctx, i);
|
DrawBorder(ctx, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.flags & UIF.DrawText)
|
if(i.flags & UIF.DrawText)
|
||||||
{
|
{
|
||||||
DrawLine(i);
|
DrawLine(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug ctx.final_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,17 +752,21 @@ UIItem*
|
|||||||
Recurse(UIItem* item)
|
Recurse(UIItem* item)
|
||||||
{
|
{
|
||||||
UIItem* result = g_UI_NIL;
|
UIItem* result = g_UI_NIL;
|
||||||
if (!Nil(item.first))
|
if(!Nil(item.first))
|
||||||
{
|
{
|
||||||
result = item.first;
|
result = item.first;
|
||||||
}
|
}
|
||||||
else if (!Nil(item.next))
|
else if(!Nil(item.next))
|
||||||
{
|
{
|
||||||
result = item.next;
|
result = item.next;
|
||||||
}
|
}
|
||||||
else if (!Nil(item.parent.next))
|
else for(UIItem* i = item.parent; !Nil(i); i = i.parent)
|
||||||
{
|
{
|
||||||
result = item.parent.next;
|
if(!Nil(i.next))
|
||||||
|
{
|
||||||
|
result = i.next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -752,15 +790,18 @@ BuildItem(UIItem* item, UISize size_x, UISize size_y, UIFlags properties)
|
|||||||
item.border_thickness = ctx.border_thickness;
|
item.border_thickness = ctx.border_thickness;
|
||||||
item.corner_radius = ctx.corner_radius;
|
item.corner_radius = ctx.corner_radius;
|
||||||
item.edge_softness = ctx.edge_softness;
|
item.edge_softness = ctx.edge_softness;
|
||||||
|
item.last_frame = ctx.frame;
|
||||||
|
|
||||||
item.parent = ctx.top_parent == g_UI_NIL_NODE ? g_UI_NIL : ctx.top_parent.item;
|
item.parent = ctx.top_parent == g_UI_NIL_NODE ? g_UI_NIL : ctx.top_parent.item;
|
||||||
if (!Nil(item.parent))
|
if(!Nil(item.parent))
|
||||||
{
|
{
|
||||||
DLLPush(item.parent, item, g_UI_NIL);
|
DLLPush(item.parent, item, g_UI_NIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset any once off values here
|
// Reset any once off values here
|
||||||
ctx.adjustment = Vec2(0.0);
|
ctx.adjustment = Vec2(0.0);
|
||||||
|
|
||||||
|
debug ctx.item_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -775,7 +816,7 @@ Signal(UIItem* item)
|
|||||||
{
|
{
|
||||||
bool taken = false;
|
bool taken = false;
|
||||||
|
|
||||||
if (item.flags & UIF.Clickable && Clicked(item, n))
|
if(item.flags & UIF.Clickable && Clicked(item, n))
|
||||||
{
|
{
|
||||||
Logf("Clicked");
|
Logf("Clicked");
|
||||||
item.last_click_pos = Vec2(n.value.x, n.value.y) - item.rect.vec0;
|
item.last_click_pos = Vec2(n.value.x, n.value.y) - item.rect.vec0;
|
||||||
@ -783,7 +824,7 @@ Signal(UIItem* item)
|
|||||||
taken = true;
|
taken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.flags & UIF.Draggable && Clicked(item, n) && Nil(ctx.drag_item))
|
if(item.flags & UIF.Draggable && Clicked(item, n) && Nil(ctx.drag_item))
|
||||||
{
|
{
|
||||||
Logf("Dragged");
|
Logf("Dragged");
|
||||||
item.signal |= UIS.Dragged;
|
item.signal |= UIS.Dragged;
|
||||||
@ -791,14 +832,14 @@ Signal(UIItem* item)
|
|||||||
taken = true;
|
taken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.drag_item == item && n.value.key == Input.LeftClick && !n.value.pressed)
|
if(ctx.drag_item == item && n.value.key == Input.LeftClick && !n.value.pressed)
|
||||||
{
|
{
|
||||||
Logf("Released");
|
Logf("Released");
|
||||||
ctx.drag_item = g_UI_NIL;
|
ctx.drag_item = g_UI_NIL;
|
||||||
taken = true;
|
taken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.drag_item == item && n.value.key == Input.MouseMotion)
|
if(ctx.drag_item == item && n.value.key == Input.MouseMotion)
|
||||||
{
|
{
|
||||||
item.signal |= UIS.Dragged;
|
item.signal |= UIS.Dragged;
|
||||||
item.dragged.x += cast(f32)n.value.rel_x;
|
item.dragged.x += cast(f32)n.value.rel_x;
|
||||||
@ -806,7 +847,7 @@ Signal(UIItem* item)
|
|||||||
taken = true;
|
taken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taken)
|
if(taken)
|
||||||
{
|
{
|
||||||
DLLRemove(&ctx.inputs.list, n, null);
|
DLLRemove(&ctx.inputs.list, n, null);
|
||||||
}
|
}
|
||||||
@ -847,9 +888,9 @@ MakeKey(u8[] id)
|
|||||||
u32 hash_count = 0;
|
u32 hash_count = 0;
|
||||||
for(i64 i = id.length-1; i >= 0; i -= 1)
|
for(i64 i = id.length-1; i >= 0; i -= 1)
|
||||||
{
|
{
|
||||||
if (hash_count == 2)
|
if(hash_count == 2)
|
||||||
{
|
{
|
||||||
if (id[i] == '#')
|
if(id[i] == '#')
|
||||||
{
|
{
|
||||||
hash_count += 1;
|
hash_count += 1;
|
||||||
pos = i;
|
pos = i;
|
||||||
@ -858,19 +899,19 @@ MakeKey(u8[] id)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id[i] == '#')
|
if(id[i] == '#')
|
||||||
{
|
{
|
||||||
pos = i;
|
pos = i;
|
||||||
hash_count += 1;
|
hash_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hash_count == 2)
|
if(hash_count == 2)
|
||||||
{
|
{
|
||||||
key.text = id[0 .. pos];
|
key.text = id[0 .. pos];
|
||||||
key.hash = Hash(id);
|
key.hash = Hash(id);
|
||||||
}
|
}
|
||||||
else if (hash_count == 3)
|
else if(hash_count == 3)
|
||||||
{
|
{
|
||||||
key.text = id[0 .. pos];
|
key.text = id[0 .. pos];
|
||||||
key.hash = Hash(id[pos+hash_count .. $]);
|
key.hash = Hash(id[pos+hash_count .. $]);
|
||||||
@ -888,7 +929,7 @@ pragma(inline) UIItem*
|
|||||||
Get(UIKey key)
|
Get(UIKey key)
|
||||||
{
|
{
|
||||||
Result!(UIItem*) result = g_ui_ctx.items[key.hash];
|
Result!(UIItem*) result = g_ui_ctx.items[key.hash];
|
||||||
if (!result.ok)
|
if(!result.ok)
|
||||||
{
|
{
|
||||||
result.value = Alloc!(UIItem)(&g_ui_ctx.arena);
|
result.value = Alloc!(UIItem)(&g_ui_ctx.arena);
|
||||||
Push(&g_ui_ctx.items, key.hash, result.value);
|
Push(&g_ui_ctx.items, key.hash, result.value);
|
||||||
@ -917,12 +958,12 @@ f32
|
|||||||
CalcTextWidth(u8[] str)
|
CalcTextWidth(u8[] str)
|
||||||
{
|
{
|
||||||
u32 tab_width = g_ui_ctx.tab_width;
|
u32 tab_width = g_ui_ctx.tab_width;
|
||||||
Glyph* space = g_ui_ctx.atlas.glyphs.ptr + ' ';
|
Glyph* space = g_ui_ctx.atlas_buf.atlas.glyphs.ptr + ' ';
|
||||||
|
|
||||||
f32 width = 0.0;
|
f32 width = 0.0;
|
||||||
for(u64 i = 0; i < str.length; i += 1)
|
for(u64 i = 0; i < str.length; i += 1)
|
||||||
{
|
{
|
||||||
width += GlyphWidth(g_ui_ctx.atlas.glyphs.ptr + str.ptr[i]);
|
width += GlyphWidth(g_ui_ctx.atlas_buf.atlas.glyphs.ptr + str.ptr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
@ -932,9 +973,9 @@ pragma(inline) f32
|
|||||||
GlyphWidth(Glyph* g)
|
GlyphWidth(Glyph* g)
|
||||||
{
|
{
|
||||||
f32 width = 0.0;
|
f32 width = 0.0;
|
||||||
if (g.ch == '\t')
|
if(g.ch == '\t')
|
||||||
{
|
{
|
||||||
width += g_ui_ctx.atlas.glyphs[' '].advance * cast(f32)(g_ui_ctx.tab_width);
|
width += g_ui_ctx.atlas_buf.atlas.glyphs[' '].advance * cast(f32)(g_ui_ctx.tab_width);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -945,28 +986,28 @@ GlyphWidth(Glyph* g)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Node!(u8[])*
|
Node!(u8[])*
|
||||||
MakeMultiline(u8[] text, f32 width, u64 line_no)
|
MakeMultiline(u8[] text, f32 width, u8[] parent_id, u64 line_no)
|
||||||
{
|
{
|
||||||
f32 scaled_width = width * (g_ui_ctx.atlas.size/g_ui_ctx.text_size);
|
f32 scaled_width = width * (g_ui_ctx.atlas_buf.atlas.size/g_ui_ctx.text_size);
|
||||||
f32 text_width = CalcTextWidth(text);
|
f32 text_width = CalcTextWidth(text);
|
||||||
|
|
||||||
u64 line_count = cast(u64)(ceil(text_width/scaled_width));
|
u64 line_count = cast(u64)(ceil(text_width/scaled_width));
|
||||||
Node!(u8[])* node = null;
|
Node!(u8[])* node = null;
|
||||||
if (line_count > 0)
|
if(line_count > 0)
|
||||||
{
|
{
|
||||||
f32 w = 0.0;
|
f32 w = 0.0;
|
||||||
u64 line = 0;
|
u64 line = 0;
|
||||||
u64 start = 0;
|
u64 start = 0;
|
||||||
const u64 extra_buf = 10;
|
const u64 extra_buf = 20;
|
||||||
for(u64 i = 0; i < text.length; i += 1)
|
for(u64 i = 0; i < text.length; i += 1)
|
||||||
{
|
{
|
||||||
f32 ch_w = GlyphWidth(g_ui_ctx.atlas.glyphs.ptr + text[i]);
|
f32 ch_w = GlyphWidth(g_ui_ctx.atlas_buf.atlas.glyphs.ptr + text[i]);
|
||||||
|
|
||||||
if (ch_w + w > scaled_width || i == text.length-1)
|
if(ch_w + w > scaled_width || i == text.length-1)
|
||||||
{
|
{
|
||||||
u64 len = i-start+1;
|
u64 len = i-start+1;
|
||||||
u8[10] buf = 0;
|
u8[extra_buf] buf = 0;
|
||||||
(cast(char[])buf).sformat("##%04s%04s", line_no, line);
|
(cast(char[])buf).sformat("%s%05s%05s", cast(char[])parent_id, line_no, line);
|
||||||
|
|
||||||
u8[] str = ScratchAlloc!(u8)(len+extra_buf);
|
u8[] str = ScratchAlloc!(u8)(len+extra_buf);
|
||||||
str[0 .. len] = text[start .. start+len];
|
str[0 .. len] = text[start .. start+len];
|
||||||
@ -975,7 +1016,7 @@ MakeMultiline(u8[] text, f32 width, u64 line_no)
|
|||||||
Node!(u8[])* n = node;
|
Node!(u8[])* n = node;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
if (node == null)
|
if(node == null)
|
||||||
{
|
{
|
||||||
node = ScratchAlloc!(Node!(u8[]))();
|
node = ScratchAlloc!(Node!(u8[]))();
|
||||||
node.value = str;
|
node.value = str;
|
||||||
@ -983,7 +1024,7 @@ MakeMultiline(u8[] text, f32 width, u64 line_no)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n.next == null)
|
if(n.next == null)
|
||||||
{
|
{
|
||||||
n.next = ScratchAlloc!(Node!(u8[]))();
|
n.next = ScratchAlloc!(Node!(u8[]))();
|
||||||
n.next.value = str;
|
n.next.value = str;
|
||||||
@ -1013,12 +1054,12 @@ DrawLine(UIItem* item)
|
|||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
f32 y = item.rect.y0 + ctx.text_size;
|
f32 y = item.rect.y0 + ctx.text_size;
|
||||||
f32 x = item.rect.x0;
|
f32 x = item.rect.x0;
|
||||||
FontAtlas* atlas = &ctx.atlas;
|
FontAtlas* atlas = &ctx.atlas_buf.atlas;
|
||||||
|
|
||||||
for(u64 i = 0; i < item.key.text.length && item.key.text[i] != '\0'; i += 1)
|
for(u64 i = 0; i < item.key.text.length && item.key.text[i] != '\0'; i += 1)
|
||||||
{
|
{
|
||||||
u8 ch = item.key.text.ptr[i];
|
u8 ch = item.key.text.ptr[i];
|
||||||
if (ch < 128)
|
if(ch < 128)
|
||||||
{
|
{
|
||||||
DrawGlyph(&atlas.glyphs[ch], atlas.size/ctx.text_size, &x, y);
|
DrawGlyph(&atlas.glyphs[ch], atlas.size/ctx.text_size, &x, y);
|
||||||
}
|
}
|
||||||
@ -1031,13 +1072,13 @@ DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y, bool draw_bg = false, Vec4
|
|||||||
UICtx* ctx = GetCtx();
|
UICtx* ctx = GetCtx();
|
||||||
Vertex* bg_v = null, v = null;
|
Vertex* bg_v = null, v = null;
|
||||||
f32 h;
|
f32 h;
|
||||||
if (draw_bg)
|
if(draw_bg)
|
||||||
{
|
{
|
||||||
bg_v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
bg_v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
||||||
AddUIIndices(ctx);
|
AddUIIndices(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glyph.ch == '\t')
|
if(glyph.ch == '\t')
|
||||||
{
|
{
|
||||||
*x_pos += glyph.advance * (GetCtx().tab_width - 1);
|
*x_pos += glyph.advance * (GetCtx().tab_width - 1);
|
||||||
}
|
}
|
||||||
@ -1055,7 +1096,7 @@ DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y, bool draw_bg = false, Vec4
|
|||||||
v.dst_end.x = *x_pos + w + l;
|
v.dst_end.x = *x_pos + w + l;
|
||||||
v.dst_end.y = y + h - y_pos;
|
v.dst_end.y = y + h - y_pos;
|
||||||
|
|
||||||
if (glyph.ch != '\t' && glyph.ch != '\n')
|
if(glyph.ch != '\t' && glyph.ch != '\n')
|
||||||
{
|
{
|
||||||
v.src_start.x = glyph.atlas_left;
|
v.src_start.x = glyph.atlas_left;
|
||||||
v.src_start.y = glyph.atlas_top;
|
v.src_start.y = glyph.atlas_top;
|
||||||
@ -1071,7 +1112,7 @@ DrawGlyph(Glyph* glyph, f32 scale, f32* x_pos, f32 y, bool draw_bg = false, Vec4
|
|||||||
|
|
||||||
*x_pos += glyph.advance * scale;
|
*x_pos += glyph.advance * scale;
|
||||||
|
|
||||||
if (draw_bg)
|
if(draw_bg)
|
||||||
{
|
{
|
||||||
Vec4 white = Vec4(1.0);
|
Vec4 white = Vec4(1.0);
|
||||||
|
|
||||||
@ -1139,10 +1180,10 @@ ClickedCharIndex(UIItem* item)
|
|||||||
for(u64 i = 0; i < item.key.text.length; i += 1)
|
for(u64 i = 0; i < item.key.text.length; i += 1)
|
||||||
{
|
{
|
||||||
u8 ch = item.key.text[i];
|
u8 ch = item.key.text[i];
|
||||||
if (ch < ctx.atlas.glyphs.length)
|
if(ch < ctx.atlas_buf.atlas.glyphs.length)
|
||||||
{
|
{
|
||||||
f32 ch_w = GlyphWidth(ctx.atlas.glyphs.ptr + ch);
|
f32 ch_w = GlyphWidth(ctx.atlas_buf.atlas.glyphs.ptr + ch);
|
||||||
if (ch_w + w > item.last_click_pos.x)
|
if(ch_w + w > item.last_click_pos.x)
|
||||||
{
|
{
|
||||||
Logf("char clicked");
|
Logf("char clicked");
|
||||||
//item.clicked_char_idx = i;
|
//item.clicked_char_idx = i;
|
||||||
@ -1159,7 +1200,7 @@ Clicked(UIItem* item, DNode!(InputEvent)* n)
|
|||||||
bool result = false;
|
bool result = false;
|
||||||
InputEvent* ev = &n.value;
|
InputEvent* ev = &n.value;
|
||||||
|
|
||||||
if (
|
if(
|
||||||
ev.key == Input.LeftClick &&
|
ev.key == Input.LeftClick &&
|
||||||
ev.x >= item.rect.x0 &&
|
ev.x >= item.rect.x0 &&
|
||||||
ev.x <= item.rect.x1 &&
|
ev.x <= item.rect.x1 &&
|
||||||
@ -1174,6 +1215,11 @@ Clicked(UIItem* item, DNode!(InputEvent)* n)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetFocus(UIItem* item)
|
||||||
|
{
|
||||||
|
g_ui_ctx.focused = item;
|
||||||
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import dlib;
|
import dlib;
|
||||||
|
|
||||||
import buffer;
|
import buffer;
|
||||||
|
import ui : Nil;
|
||||||
import ui;
|
import ui;
|
||||||
import editor;
|
import editor;
|
||||||
import std.format : sformat;
|
import std.format : sformat;
|
||||||
@ -15,11 +16,13 @@ WidgetCtx g_widget_ctx;
|
|||||||
struct WidgetCtx
|
struct WidgetCtx
|
||||||
{
|
{
|
||||||
UIPanel* parent;
|
UIPanel* parent;
|
||||||
|
UIPanel* focused_panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UIPanel
|
struct UIPanel
|
||||||
{
|
{
|
||||||
u8[] id;
|
u8[] id;
|
||||||
|
Editor* ed;
|
||||||
|
|
||||||
UIPanel* parent;
|
UIPanel* parent;
|
||||||
UIPanel* next;
|
UIPanel* next;
|
||||||
@ -34,34 +37,25 @@ struct UIPanel
|
|||||||
Vec4 color;
|
Vec4 color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
struct TextPart
|
||||||
PushPanel(UIPanel* parent)
|
|
||||||
{
|
{
|
||||||
parent.list_next = g_widget_ctx.parent;
|
UIItem* item;
|
||||||
g_widget_ctx.parent = parent;
|
TextPart* next;
|
||||||
}
|
|
||||||
|
|
||||||
UIPanel*
|
|
||||||
PopPanel()
|
|
||||||
{
|
|
||||||
UIPanel* parent = g_widget_ctx.parent;
|
|
||||||
g_widget_ctx.parent = parent.list_next;
|
|
||||||
parent.list_next = g_UI_NIL_PANEL;
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
InitWidgets()
|
|
||||||
{
|
|
||||||
g_UI_NIL_PANEL = cast(UIPanel*)&g_ui_nil_panel;
|
|
||||||
g_widget_ctx.parent = g_UI_NIL_PANEL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UIItem*
|
UIItem*
|
||||||
Root()
|
Root()
|
||||||
{
|
{
|
||||||
Vec2 d = RootSize();
|
Vec2 d = RootSize();
|
||||||
|
|
||||||
|
SetColor(
|
||||||
|
Vec4(0.3, 0.65, 0.86, 1.0),
|
||||||
|
Vec4(0.25, 0.60, 0.81, 1.0),
|
||||||
|
Vec4(0.25, 0.60, 0.81, 1.0),
|
||||||
|
Vec4(0.3, 0.65, 0.86, 1.0),
|
||||||
|
);
|
||||||
SetLayoutAxis(A2D.Y);
|
SetLayoutAxis(A2D.Y);
|
||||||
|
|
||||||
UIItem* root = Get("##root_item");
|
UIItem* root = Get("##root_item");
|
||||||
BuildItem(root, UISize(ST.Pixels, d.x), UISize(ST.Pixels, d.y), UIF.DrawBackground);
|
BuildItem(root, UISize(ST.Pixels, d.x), UISize(ST.Pixels, d.y), UIF.DrawBackground);
|
||||||
|
|
||||||
@ -81,60 +75,28 @@ Panel(UIPanel* panel)
|
|||||||
UIItem* item = Get(panel.id);
|
UIItem* item = Get(panel.id);
|
||||||
UIItem* separator = g_UI_NIL;
|
UIItem* separator = g_UI_NIL;
|
||||||
|
|
||||||
UIItem* prev_panel = PeekSiblingPanel();
|
UIPanel* parent_pn = panel.parent;
|
||||||
UIItem* parent = PeekParent();
|
|
||||||
|
|
||||||
UIPanel* parent_pn = g_widget_ctx.parent;
|
UIItem* prev_panel = !Nil(panel.prev) ? Get(panel.prev.id) : g_UI_NIL;
|
||||||
|
UIItem* parent = !Nil(parent_pn) ? Get(parent_pn.id) : PeekParent();
|
||||||
DLLPush(parent_pn, panel, g_UI_NIL_PANEL);
|
|
||||||
|
|
||||||
f32 x_pct = 1.0, y_pct = 1.0;
|
f32 x_pct = 1.0, y_pct = 1.0;
|
||||||
if (parent_pn != g_UI_NIL_PANEL)
|
if(!Nil(parent_pn))
|
||||||
{
|
{
|
||||||
x_pct = parent_pn.axis == A2D.X ? panel.pct : 1.0;
|
x_pct = parent_pn.axis == A2D.X ? panel.pct : 1.0;
|
||||||
y_pct = parent_pn.axis == A2D.Y ? panel.pct : 1.0;
|
y_pct = parent_pn.axis == A2D.Y ? panel.pct : 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Signal(item);
|
if(item.signal & UIS.Clicked)
|
||||||
|
{
|
||||||
|
Logf("%s clicked", cast(char[])panel.id);
|
||||||
|
SetFocusedPanel(panel);
|
||||||
|
}
|
||||||
|
|
||||||
f32 adj_x = 0.0, adj_y = 0.0;
|
f32 adj_x = 0.0, adj_y = 0.0;
|
||||||
if (!Nil(prev_panel) && parent != prev_panel)
|
if(!Nil(prev_panel))
|
||||||
{
|
{
|
||||||
f32 sep_y = 1.0, sep_x = 1.0, parent_start = 0.0, parent_end = 0.0;
|
Separator(panel, parent, &adj_x, &adj_y);
|
||||||
if (parent.layout_axis == A2D.X)
|
|
||||||
{
|
|
||||||
sep_x = 5.0;
|
|
||||||
adj_x = -5.0;
|
|
||||||
parent_start = parent.rect.vec0.x;
|
|
||||||
parent_end = parent.rect.vec1.x;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sep_y = 5.0;
|
|
||||||
adj_y = -5.0;
|
|
||||||
parent_start = parent.rect.vec0.y;
|
|
||||||
parent_end = parent.rect.vec1.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8[] buf = ScratchAlloc!(u8)(panel.id.length + 5);
|
|
||||||
(cast(char[])buf).sformat("%s_sep", cast(char[])panel.id);
|
|
||||||
|
|
||||||
separator = Get(buf);
|
|
||||||
|
|
||||||
Separator(separator, sep_x, sep_y, parent.layout_axis);
|
|
||||||
|
|
||||||
Signal(separator);
|
|
||||||
|
|
||||||
f32 pos = separator.dragged.v[parent.layout_axis];
|
|
||||||
if (separator.signal & UIS.Dragged && pos != 0.0)
|
|
||||||
{
|
|
||||||
f32 pct = Remap(pos, 0.0, parent_start-parent_end, 0.0, 1.0);
|
|
||||||
if (CheckPanelBounds(panel.pct - pct) && CheckPanelBounds(panel.prev.pct + pct))
|
|
||||||
{
|
|
||||||
panel.pct -= pct;
|
|
||||||
panel.prev.pct += pct;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetColor(
|
SetColor(
|
||||||
@ -145,18 +107,216 @@ Panel(UIPanel* panel)
|
|||||||
);
|
);
|
||||||
SetLayoutAxis(panel.axis);
|
SetLayoutAxis(panel.axis);
|
||||||
|
|
||||||
BuildItem(item, UISize(ST.Percentage, x_pct), UISize(ST.Percentage, y_pct), UIF.DrawBackground);
|
BuildItem(item, UISize(ST.Percentage, x_pct), UISize(ST.Percentage, y_pct), UIF.DrawBackground|UIF.Clickable);
|
||||||
|
|
||||||
UIItem* sibling = PrevSiblingPanel(item);
|
|
||||||
|
|
||||||
PushSiblingPanel(item);
|
|
||||||
PushParent(item);
|
PushParent(item);
|
||||||
|
|
||||||
PushPanel(panel);
|
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Separator(UIPanel* panel, UIItem* parent, f32* adj_x, f32* adj_y)
|
||||||
|
{
|
||||||
|
Axis2D axis = parent.layout_axis;
|
||||||
|
|
||||||
|
f32 sep_y = 1.0, sep_x = 1.0, parent_start = 0.0, parent_end = 0.0;
|
||||||
|
if(axis == A2D.X)
|
||||||
|
{
|
||||||
|
sep_x = 5.0;
|
||||||
|
*adj_x = -5.0;
|
||||||
|
parent_start = parent.rect.vec0.x;
|
||||||
|
parent_end = parent.rect.vec1.x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sep_y = 5.0;
|
||||||
|
*adj_y = -5.0;
|
||||||
|
parent_start = parent.rect.vec0.y;
|
||||||
|
parent_end = parent.rect.vec1.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8[] buf = ScratchAlloc!(u8)(panel.id.length + 5);
|
||||||
|
(cast(char[])buf).sformat("%s_sep", cast(char[])panel.id);
|
||||||
|
|
||||||
|
SetColor(Vec4(0.1, 0.2, 0.6, 1.0));
|
||||||
|
|
||||||
|
SizeType x_t = axis == A2D.X ? ST.Pixels : ST.Percentage;
|
||||||
|
SizeType y_t = axis == A2D.Y ? ST.Pixels : ST.Percentage;
|
||||||
|
|
||||||
|
UIItem* item = Get(buf);
|
||||||
|
|
||||||
|
BuildItem(item, UISize(x_t, sep_x), UISize(y_t, sep_y), UIF.DrawBackground|UIF.Draggable);
|
||||||
|
|
||||||
|
Signal(item);
|
||||||
|
|
||||||
|
f32 pos = item.dragged.v[parent.layout_axis];
|
||||||
|
if(item.signal & UIS.Dragged && pos != 0.0)
|
||||||
|
{
|
||||||
|
f32 pct = Remap(pos, 0.0, parent_start-parent_end, 0.0, 1.0);
|
||||||
|
if(CheckPanelBounds(panel.pct - pct) && CheckPanelBounds(panel.prev.pct + pct))
|
||||||
|
{
|
||||||
|
panel.pct -= pct;
|
||||||
|
panel.prev.pct += pct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextLine(u8[] text)
|
||||||
|
{
|
||||||
|
UIItem* parent = PeekParent();
|
||||||
|
|
||||||
|
UIItem* item = Get(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EditorView(UIPanel* panel)
|
||||||
|
{
|
||||||
|
UICtx* ctx = GetCtx();
|
||||||
|
UIItem* item = Panel(panel);
|
||||||
|
|
||||||
|
TextPart* tp = WrappedTextLine(CastStr!(u8)("Test 1234"), panel.id, 14.0, 0);
|
||||||
|
if(TextClicked(tp)) SetFocusedPanel(panel);
|
||||||
|
tp = WrappedTextLine(CastStr!(u8)("Test 1234"), panel.id, 14.0, 1);
|
||||||
|
if(TextClicked(tp)) SetFocusedPanel(panel);
|
||||||
|
tp = WrappedTextLine(CastStr!(u8)("Test 1234"), panel.id, 14.0, 2);
|
||||||
|
if(TextClicked(tp)) SetFocusedPanel(panel);
|
||||||
|
tp = WrappedTextLine(CastStr!(u8)("Test 1234"), panel.id, 14.0, 3);
|
||||||
|
if(TextClicked(tp)) SetFocusedPanel(panel);
|
||||||
|
|
||||||
|
Signal(item);
|
||||||
|
|
||||||
|
if(item.signal & UIS.Clicked)
|
||||||
|
{
|
||||||
|
SetFocusedPanel(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
EndPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TextClicked(TextPart* text_part)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
for(TextPart* tp = text_part; !Nil(tp.item); tp = tp.next)
|
||||||
|
{
|
||||||
|
if(tp.item.signal & UIS.Clicked)
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextPart*
|
||||||
|
WrappedTextLine(u8[] text, u8[] parent_id, f32 text_size, u64 line_no)
|
||||||
|
{
|
||||||
|
UIItem* parent = PeekParent();
|
||||||
|
TextPart* part = ScratchAlloc!(TextPart)();
|
||||||
|
part.item = g_UI_NIL;
|
||||||
|
|
||||||
|
SetColor(Vec4(1.0));
|
||||||
|
SetTextSize(text_size);
|
||||||
|
|
||||||
|
TextPart* tp = part;
|
||||||
|
Node!(u8[])* lines = MakeMultiline(text, parent.size.x, parent_id, line_no);
|
||||||
|
for(Node!(u8[])* line = lines; line != null; line = line.next, tp = tp.next)
|
||||||
|
{
|
||||||
|
tp.item = Get(line.value);
|
||||||
|
tp.next = ScratchAlloc!(TextPart)();
|
||||||
|
tp.next.item = g_UI_NIL;
|
||||||
|
|
||||||
|
Signal(tp.item);
|
||||||
|
|
||||||
|
if(tp.item.signal & UIS.Clicked)
|
||||||
|
{
|
||||||
|
ClickedCharIndex(tp.item);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildItem(tp.item, UISize(ST.Percentage, 1.0), UISize(ST.Pixels, text_size), UIF.DrawText|UIF.Clickable|UIF.Draggable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EndPanel()
|
||||||
|
{
|
||||||
|
PopParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DrawPanels(UIPanel* panel)
|
||||||
|
{
|
||||||
|
if(!Nil(panel))
|
||||||
|
{
|
||||||
|
debug
|
||||||
|
{
|
||||||
|
import core.stdc.math : fabsf;
|
||||||
|
|
||||||
|
if(!Nil(panel.first))
|
||||||
|
{
|
||||||
|
f32 total = 1.0;
|
||||||
|
for(UIPanel* child = panel.first; !Nil(child); child = child.next)
|
||||||
|
{
|
||||||
|
total -= child.pct;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(total > 0.00009)
|
||||||
|
{
|
||||||
|
Logf("%s failed with %f", cast(char[])panel.id, total);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(panel.ed)
|
||||||
|
{
|
||||||
|
EditorView(panel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Panel(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawPanels(panel.first);
|
||||||
|
|
||||||
|
if(panel.ed == null)
|
||||||
|
{
|
||||||
|
EndPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawPanels(panel.next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UIPanel*
|
||||||
|
Recurse(UIPanel* panel)
|
||||||
|
{
|
||||||
|
UIPanel* result = g_UI_NIL_PANEL;
|
||||||
|
if(!Nil(panel.first))
|
||||||
|
{
|
||||||
|
result = panel.first;
|
||||||
|
}
|
||||||
|
else if(!Nil(panel.next))
|
||||||
|
{
|
||||||
|
result = panel.next;
|
||||||
|
}
|
||||||
|
else for(UIPanel* p = panel.parent; !Nil(p); p = p.parent)
|
||||||
|
{
|
||||||
|
if(!Nil(p.next))
|
||||||
|
{
|
||||||
|
result = p.next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CheckPanelBounds(f32 pct)
|
CheckPanelBounds(f32 pct)
|
||||||
{
|
{
|
||||||
@ -164,58 +324,44 @@ CheckPanelBounds(f32 pct)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Separator(UIItem* item, f32 x_size, f32 y_size, Axis2D axis)
|
PushPanel(UIPanel* parent, UIPanel* panel)
|
||||||
{
|
{
|
||||||
SetColor(Vec4(0.1, 0.2, 0.6, 1.0));
|
DLLPush(parent, panel, g_UI_NIL_PANEL);
|
||||||
|
panel.parent = parent;
|
||||||
SizeType x_t = axis == A2D.X ? ST.Pixels : ST.Percentage;
|
|
||||||
SizeType y_t = axis == A2D.Y ? ST.Pixels : ST.Percentage;
|
|
||||||
|
|
||||||
BuildItem(item, UISize(x_t, x_size), UISize(y_t, y_size), UIF.DrawBackground|UIF.Draggable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EditorView(Editor* ed)
|
InsertPanel(UIPanel* parent, UIPanel* prev, UIPanel* panel)
|
||||||
{
|
{
|
||||||
UICtx* ctx = GetCtx();
|
DLLInsert(parent, panel, prev, g_UI_NIL_PANEL);
|
||||||
UIItem* parent = PeekParent();
|
panel.parent = prev.parent;
|
||||||
|
|
||||||
if (ed.buf.length > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UIItem*
|
|
||||||
TextLine(u8[] text, f32 text_size, u64 line_no)
|
|
||||||
{
|
|
||||||
UIItem* item = g_UI_NIL;
|
|
||||||
UIItem* parent = PeekParent();
|
|
||||||
|
|
||||||
SetColor(Vec4(1.0));
|
|
||||||
SetTextSize(text_size);
|
|
||||||
|
|
||||||
Node!(u8[])* lines = MakeMultiline(text, parent.size.x, line_no);
|
|
||||||
for(Node!(u8[])* line = lines; line != null; line = line.next)
|
|
||||||
{
|
|
||||||
item = Get(line.value);
|
|
||||||
|
|
||||||
Signal(item);
|
|
||||||
|
|
||||||
if (item.signal & UIS.Clicked)
|
|
||||||
{
|
|
||||||
ClickedCharIndex(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildItem(item, UISize(ST.Percentage, 1.0), UISize(ST.Pixels, text_size), UIF.DrawText|UIF.Clickable|UIF.Draggable);
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EndPanel()
|
InitWidgets()
|
||||||
{
|
{
|
||||||
PopParent();
|
g_UI_NIL_PANEL = cast(UIPanel*)&g_ui_nil_panel;
|
||||||
PopPanel();
|
g_widget_ctx.parent = g_UI_NIL_PANEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetFocusedPanel(UIPanel* panel)
|
||||||
|
{
|
||||||
|
if(!CheckNil(g_UI_NIL_PANEL, panel))
|
||||||
|
{
|
||||||
|
g_widget_ctx.focused_panel = panel;
|
||||||
|
SetFocus(panel.ed != null ? Get(panel.ed.filename) : Get(panel.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UIPanel*
|
||||||
|
GetFocusedPanel()
|
||||||
|
{
|
||||||
|
return Nil(g_widget_ctx.focused_panel) ? g_UI_NIL_PANEL : g_widget_ctx.focused_panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Nil(UIPanel* panel)
|
||||||
|
{
|
||||||
|
return panel == null || panel == g_UI_NIL_PANEL;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,7 +54,7 @@ void main()
|
|||||||
float sdf_factor = 1.0 - smoothstep(0, 2*softness, dist);
|
float sdf_factor = 1.0 - smoothstep(0, 2*softness, dist);
|
||||||
|
|
||||||
float border_factor = 1.0;
|
float border_factor = 1.0;
|
||||||
if (FD.border_thickness != 0.0)
|
if(FD.border_thickness != 0.0)
|
||||||
{
|
{
|
||||||
vec2 interior_half_size = FD.dst_half_size - vec2(FD.border_thickness);
|
vec2 interior_half_size = FD.dst_half_size - vec2(FD.border_thickness);
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ void main()
|
|||||||
vec4 gamma = vec4(1.0/1.4);
|
vec4 gamma = vec4(1.0/1.4);
|
||||||
|
|
||||||
vec4 tex_color = vec4(1.0);
|
vec4 tex_color = vec4(1.0);
|
||||||
if (in_has_texture != 0)
|
if(in_has_texture != 0)
|
||||||
{
|
{
|
||||||
tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FD.uv);
|
tex_color = texture(sampler2D(SpriteAtlas, SamplerNearest), FD.uv);
|
||||||
//tex_color = pow(tex_color, gamma);
|
//tex_color = pow(tex_color, gamma);
|
||||||
|
|||||||
@ -25,7 +25,7 @@ Test()
|
|||||||
x ~= x;
|
x ~= x;
|
||||||
|
|
||||||
// Commented here
|
// Commented here
|
||||||
if (x > 1L && y < 2u || x <= 3U && y >= 4Lu || x == 5LU && x != 6uL || x == 7UL)
|
if(x > 1L && y < 2u || x <= 3U && y >= 4Lu || x == 5LU && x != 6uL || x == 7UL)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user