wip (some things are badly broken)
This commit is contained in:
parent
f4f311a49c
commit
62cd8c471f
@ -15,7 +15,7 @@ struct FlatBuffer
|
||||
LineBuffers linebufs;
|
||||
BufferInfo info;
|
||||
|
||||
u8[] file_name;
|
||||
string file_name;
|
||||
u8[] data;
|
||||
u64 length;
|
||||
|
||||
@ -116,7 +116,7 @@ const u64 SPACING = 2;
|
||||
const u64 BUF_START = 1;
|
||||
|
||||
FlatBuffer
|
||||
CreateFlatBuffer(u8[] data, u8[] file_name)
|
||||
CreateFlatBuffer(u8[] data, string file_name)
|
||||
{
|
||||
FlatBuffer fb = {
|
||||
arena: CreateArena(MB(1)),
|
||||
@ -133,7 +133,7 @@ CreateFlatBuffer(u8[] data, u8[] file_name)
|
||||
}
|
||||
|
||||
void
|
||||
Init(FlatBuffer* fb, u8[] data, u8[] file_name)
|
||||
Init(FlatBuffer* fb, u8[] data, string file_name)
|
||||
{
|
||||
u64 capacity = data.length > 0 ? RoundUp(cast(u64)(data.length)*2, KB(4)) : KB(4);
|
||||
|
||||
@ -158,7 +158,7 @@ SetBuffers(FlatBuffer* fb, u8[] data)
|
||||
}
|
||||
|
||||
void
|
||||
Change(FlatBuffer* fb, u8[] data, u8[] file_name)
|
||||
Change(FlatBuffer* fb, u8[] data, string file_name)
|
||||
{
|
||||
Free(fb.data);
|
||||
Reset(&fb.linebufs.arena);
|
||||
|
||||
@ -17,8 +17,6 @@ import std.string;
|
||||
import core.stdc.stdio;
|
||||
|
||||
f32 g_delta = 0.0;
|
||||
debug bool g_frame_step = false;
|
||||
debug bool g_frame_continue = false;
|
||||
|
||||
struct EditorCtx
|
||||
{
|
||||
@ -31,7 +29,7 @@ struct EditorCtx
|
||||
u64 editor_id_incr;
|
||||
Timer timer;
|
||||
CmdPalette cmd;
|
||||
u8[][] file_names;
|
||||
string[] file_names;
|
||||
u64 panel_id;
|
||||
|
||||
Editor* focused_editor;
|
||||
@ -44,7 +42,7 @@ struct CmdPalette
|
||||
u8[] buffer;
|
||||
u32 icount;
|
||||
Command[] commands;
|
||||
u8[][] opt_strs;
|
||||
string[] opt_strs;
|
||||
i64 selected;
|
||||
Command current;
|
||||
Parameter[] params;
|
||||
@ -83,13 +81,15 @@ struct EditorChange
|
||||
|
||||
struct Command
|
||||
{
|
||||
u8[] name;
|
||||
string name;
|
||||
string desc;
|
||||
string cmd;
|
||||
CmdType type;
|
||||
}
|
||||
|
||||
struct Parameter
|
||||
{
|
||||
u8[] value;
|
||||
string value;
|
||||
bool visible;
|
||||
}
|
||||
|
||||
@ -123,6 +123,45 @@ const Command NO_CMD = {
|
||||
type: CT.None,
|
||||
};
|
||||
|
||||
const Command[] CMD_LIST = [
|
||||
{
|
||||
name: "Open",
|
||||
cmd: "open",
|
||||
desc: "Open a file in the focused editor view.",
|
||||
type: CT.OpenFile,
|
||||
},
|
||||
{
|
||||
name: "Save",
|
||||
cmd: "save",
|
||||
desc: "Save the current file in the focused editor view.",
|
||||
type: CT.SaveFile,
|
||||
},
|
||||
{
|
||||
name: "New File",
|
||||
cmd: "new file",
|
||||
desc: "Create a new file with a specified name and location.",
|
||||
type: CT.CreateFile,
|
||||
},
|
||||
{
|
||||
name: "Vertical Split",
|
||||
cmd: "vsplit",
|
||||
desc: "Split the current editor view vertically.",
|
||||
type: CT.VSplit,
|
||||
},
|
||||
{
|
||||
name: "Horizontal Split",
|
||||
cmd: "hsplit",
|
||||
desc: "Split the current editor view horizontally.",
|
||||
type: CT.HSplit,
|
||||
},
|
||||
];
|
||||
|
||||
bool
|
||||
Active(EditState state)
|
||||
{
|
||||
return g_ed_ctx.state == state;
|
||||
}
|
||||
|
||||
void
|
||||
Cycle(Inputs* inputs)
|
||||
{
|
||||
@ -130,18 +169,7 @@ Cycle(Inputs* inputs)
|
||||
|
||||
g_delta = DeltaTime(&g_ed_ctx.timer);
|
||||
|
||||
debug if(g_frame_step)
|
||||
{
|
||||
g_delta = 0.01;
|
||||
}
|
||||
|
||||
|
||||
//HandleInputs(ctx, inputs);
|
||||
|
||||
debug if(g_frame_step && !g_frame_continue) return;
|
||||
debug g_frame_continue = false;
|
||||
|
||||
g_input_mode = g_ed_ctx.state == ES.InputMode;
|
||||
g_input_mode = Active(ES.InputMode);
|
||||
|
||||
BeginUI(inputs);
|
||||
|
||||
@ -162,11 +190,7 @@ Cycle(Inputs* inputs)
|
||||
}
|
||||
|
||||
UIItem* container = Container(A2D.Y, UIS2());
|
||||
Push!("parent")(container);
|
||||
|
||||
UIItem* ed_container = Container(A2D.X, UISY(ST.Percentage, 0.98));
|
||||
|
||||
Push!("parent")(ed_container);
|
||||
EditorView(g_ed_ctx.base_panel);
|
||||
Pop!("parent");
|
||||
|
||||
@ -174,9 +198,12 @@ Cycle(Inputs* inputs)
|
||||
|
||||
StatusBar(&g_ed_ctx);
|
||||
|
||||
if(g_ed_ctx.state == ES.CmdOpen)
|
||||
UIItem* cmd_item = Get("###cmd_palette");
|
||||
|
||||
bool cmd_active = Active(ES.CmdOpen);
|
||||
if(cmd_active || Ready(cmd_item))
|
||||
{
|
||||
CommandPalette(&g_ed_ctx.cmd);
|
||||
CommandPalette(&g_ed_ctx.cmd, cmd_active);
|
||||
}
|
||||
|
||||
EndUI();
|
||||
@ -213,7 +240,7 @@ InitEditorCtx(PlatformWindow* window)
|
||||
count += 1;
|
||||
}
|
||||
|
||||
ctx.file_names = Alloc!(u8[])(&ctx.arena, count);
|
||||
ctx.file_names = Alloc!(string)(&ctx.arena, count);
|
||||
|
||||
count = 0;
|
||||
foreach(DirEntry e; dirEntries(".", SpanMode.breadth))
|
||||
@ -221,7 +248,7 @@ InitEditorCtx(PlatformWindow* window)
|
||||
if(indexOf(e.name, ".git") != -1 || e.isDir) continue;
|
||||
|
||||
u64 start = indexOf(e.name, "./") == 0 ? 2 : 0;
|
||||
ctx.file_names[count++] = Alloc!(u8)(&ctx.arena, CastStr!(u8)(e.name[start .. $]));
|
||||
ctx.file_names[count++] = Alloc(&ctx.arena, e.name);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
@ -260,7 +287,7 @@ EditModeActive()
|
||||
}
|
||||
|
||||
char[]
|
||||
ToAbsolutePath(u8[] file_name)
|
||||
ToAbsolutePath(string file_name)
|
||||
{
|
||||
import core.stdc.string : strlen;
|
||||
|
||||
@ -294,7 +321,7 @@ ToAbsolutePath(u8[] file_name)
|
||||
|
||||
version(Windows)
|
||||
{
|
||||
name_buf.sformat("%s/%s", wd, cast(char[])file_name);
|
||||
name_buf.sformat("%s/%s", wd, cast(char[])file_name);
|
||||
}
|
||||
|
||||
char[] path_buf = ScratchAlloc!(char)(strlen(name_buf.ptr)+1);
|
||||
@ -304,11 +331,11 @@ name_buf.sformat("%s/%s", wd, cast(char[])file_name);
|
||||
}
|
||||
|
||||
void
|
||||
SaveFile(Editor* ed, u8[] file_name)
|
||||
SaveFile(Editor* ed, string file_name)
|
||||
{
|
||||
import core.stdc.stdio;
|
||||
|
||||
file_name = file_name.length == 0 ? ed.buf.file_name : file_name;
|
||||
file_name = file_name.length == 0 ? Str(ed.buf.file_name) : file_name;
|
||||
|
||||
if(file_name.length > 0)
|
||||
{
|
||||
@ -353,7 +380,7 @@ SaveFile(Editor* ed, u8[] file_name)
|
||||
}
|
||||
|
||||
void
|
||||
OpenFile(Editor* ed, u8[] file_name)
|
||||
OpenFile(Editor* ed, string file_name)
|
||||
{
|
||||
import core.stdc.stdio;
|
||||
import std.file;
|
||||
@ -591,6 +618,9 @@ HandleInputs(Panel* p, LinkedList!(UIInput)* inputs)
|
||||
if(Shift(node.md))
|
||||
{
|
||||
ctx.state = ES.CmdOpen;
|
||||
ctx.cmd.commands = cast(Command[])CMD_LIST;
|
||||
ctx.cmd.icount = 0;
|
||||
ctx.cmd.params = [];
|
||||
taken = true;
|
||||
}
|
||||
} break;
|
||||
@ -624,18 +654,6 @@ HandleInputs(Panel* p, LinkedList!(UIInput)* inputs)
|
||||
ctx.state = ES.SetPanelFocus;
|
||||
}
|
||||
} break;
|
||||
debug case d:
|
||||
{
|
||||
g_ui_ctx.dbg = !g_ui_ctx.dbg;
|
||||
} break;
|
||||
debug case g:
|
||||
{
|
||||
g_frame_step = !g_frame_step;
|
||||
} break;
|
||||
debug case s:
|
||||
{
|
||||
g_frame_continue = true;
|
||||
} break;
|
||||
default: taken = Move(fb, key, md); break;
|
||||
}
|
||||
}
|
||||
@ -746,14 +764,32 @@ Lower(u8 ch)
|
||||
}
|
||||
|
||||
bool
|
||||
StrContains(bool begins_with)(const u8[] str, u8[] match)
|
||||
StrContains(bool begins_with)(u8[] str, u8[] match)
|
||||
{
|
||||
return StrContains!(begins_with)(cast(u8[])str, match);
|
||||
return StrContains!(begins_with)(Str(str), match);
|
||||
}
|
||||
|
||||
bool
|
||||
StrContains(bool begins_with)(u8[] str, u8[] match)
|
||||
StrContains(bool begins_with, T, U)(T str_param, U match_param) if(StringType!(T) && StringType!(U))
|
||||
{
|
||||
static if(!is(T == string))
|
||||
{
|
||||
string str = Str(str_param);
|
||||
}
|
||||
else
|
||||
{
|
||||
string str = str_param;
|
||||
}
|
||||
|
||||
static if(!is(U == string))
|
||||
{
|
||||
string match = Str(match_param);
|
||||
}
|
||||
else
|
||||
{
|
||||
string match = match_param;
|
||||
}
|
||||
|
||||
u64 count;
|
||||
for(u64 i = 0; i < str.length; i += 1)
|
||||
{
|
||||
@ -783,62 +819,26 @@ StrContains(bool begins_with)(u8[] str, u8[] match)
|
||||
void
|
||||
GetCommands(CmdPalette* cmd)
|
||||
{
|
||||
const Command[] cmd_list = [
|
||||
{
|
||||
name: CastStr!(u8)("open"),
|
||||
type: CT.OpenFile,
|
||||
},
|
||||
{
|
||||
name: CastStr!(u8)("save"),
|
||||
type: CT.SaveFile,
|
||||
},
|
||||
{
|
||||
name: CastStr!(u8)("create"),
|
||||
type: CT.CreateFile,
|
||||
},
|
||||
{
|
||||
name: CastStr!(u8)("vsplit"),
|
||||
type: CT.VSplit,
|
||||
},
|
||||
{
|
||||
name: CastStr!(u8)("hsplit"),
|
||||
type: CT.HSplit,
|
||||
},
|
||||
];
|
||||
|
||||
Reset(&cmd.arena);
|
||||
cmd.commands = Alloc!(Command)(&cmd.arena, cmd_list.length);
|
||||
cmd.params = [];
|
||||
|
||||
cmd.commands = Alloc!(Command)(&cmd.arena, CMD_LIST.length);
|
||||
cmd.params = [];
|
||||
u8[] str = cmd.buffer[0 .. cmd.icount];
|
||||
|
||||
u64 count = 0;
|
||||
u64 count;
|
||||
if(str.length > 0)
|
||||
{
|
||||
for(u64 i = 0; i < cmd_list.length; i += 1)
|
||||
for(u64 i = 0; i < CMD_LIST.length; i += 1)
|
||||
{
|
||||
if(StrContains!(true)(cmd_list[i].name, str))
|
||||
if(StrContains!(true)(CMD_LIST[i].cmd, str) || StrContains!(true)(CMD_LIST[i].name, str))
|
||||
{
|
||||
cmd.commands[count] = cast(Command)cmd_list[i];
|
||||
cmd.commands[count] = cast(Command)CMD_LIST[i];
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(count == 0 && cmd.icount == 0)
|
||||
{
|
||||
cmd.commands[] = cast(Command[])cmd_list[];
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd.commands = cmd.commands[0 .. count];
|
||||
}
|
||||
|
||||
cmd.opt_strs = Alloc!(u8[])(&cmd.arena, cmd.commands.length);
|
||||
for(u64 i = 0; i < cmd.commands.length; i += 1)
|
||||
{
|
||||
cmd.opt_strs[i] = cmd.commands[i].name;
|
||||
}
|
||||
cmd.commands = count ? cmd.commands[0 .. count] : cast(Command[])CMD_LIST;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -904,7 +904,7 @@ HandleCmdMode(EditorCtx* ctx, Panel* panel, UIInput* ev)
|
||||
if(cmd.commands.length > 0)
|
||||
{
|
||||
cmd.current = cmd.commands[cmd.selected];
|
||||
cmd.buffer[0 .. cmd.current.name.length] = cmd.current.name[0 .. $];
|
||||
cmd.buffer[0 .. cmd.current.name.length] = Arr!(u8)(cmd.current.name[0 .. $]);
|
||||
cmd.icount = cast(u32)cmd.current.name.length;
|
||||
cmd.buffer[cmd.icount++] = ' ';
|
||||
}
|
||||
@ -923,7 +923,7 @@ HandleCmdMode(EditorCtx* ctx, Panel* panel, UIInput* ev)
|
||||
} break;
|
||||
}
|
||||
|
||||
if(cmd.current.type == CT.None && (cmd.commands.length == 0 || prev_count != cmd.icount))
|
||||
if(cmd.current.type == CT.None && prev_count != cmd.icount)
|
||||
{
|
||||
GetCommands(cmd);
|
||||
}
|
||||
@ -937,7 +937,7 @@ HandleCmdMode(EditorCtx* ctx, Panel* panel, UIInput* ev)
|
||||
} break;
|
||||
case SaveFile:
|
||||
{
|
||||
u8[] param = GetParam(cmd);
|
||||
string param = GetParam(cmd);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
@ -957,15 +957,15 @@ Check(CmdPalette* cmd, u64 length)
|
||||
}
|
||||
}
|
||||
|
||||
u8[]
|
||||
string
|
||||
GetParam(CmdPalette* cmd)
|
||||
{
|
||||
u8[] param = [];
|
||||
string param;
|
||||
for(u64 i = cmd.current.name.length; i < cmd.icount; i += 1)
|
||||
{
|
||||
if(cmd.buffer[i] != ' ')
|
||||
{
|
||||
param = cmd.buffer[i .. cmd.icount];
|
||||
param = Str(cmd.buffer[i .. cmd.icount]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -974,13 +974,13 @@ GetParam(CmdPalette* cmd)
|
||||
}
|
||||
|
||||
void
|
||||
PopulateParams(CmdPalette* cmd, u8[][] strs)
|
||||
PopulateParams(CmdPalette* cmd, string[] strs)
|
||||
{
|
||||
u8[] param = GetParam(cmd);
|
||||
string param = GetParam(cmd);
|
||||
if(cmd.params.length == 0 || !param.length)
|
||||
{
|
||||
cmd.params = Alloc!(Parameter)(&cmd.cmd_arena, strs.length);
|
||||
cmd.opt_strs = Alloc!(u8[])(&cmd.cmd_arena, strs.length);
|
||||
cmd.opt_strs = Alloc!(string)(&cmd.cmd_arena, strs.length);
|
||||
|
||||
for(u64 i = 0; i < cmd.params.length; i += 1)
|
||||
{
|
||||
@ -992,7 +992,7 @@ PopulateParams(CmdPalette* cmd, u8[][] strs)
|
||||
|
||||
if(param.length)
|
||||
{
|
||||
cmd.opt_strs = Alloc!(u8[])(&cmd.cmd_arena, strs.length);
|
||||
cmd.opt_strs = Alloc!(string)(&cmd.cmd_arena, strs.length);
|
||||
|
||||
u64 matches;
|
||||
for(u64 i = 0; i < cmd.params.length; i += 1)
|
||||
|
||||
290
src/editor/ui.d
290
src/editor/ui.d
@ -1,5 +1,6 @@
|
||||
import dlib;
|
||||
import dlib.util : HTPush = Push;
|
||||
import dlib.math : Clamp;
|
||||
|
||||
import vulkan;
|
||||
import vulkan : RendererGetExtent = GetExtent;
|
||||
@ -130,9 +131,11 @@ enum UIFlags : u64
|
||||
VerticalAlignText = 1<<24,
|
||||
SetHot = 1<<25,
|
||||
SetReady = 1<<26,
|
||||
AnimateReady = 1<<27, // Fade in/out
|
||||
AnimateHot = 1<<28, // Hover highlight
|
||||
AnimateActive = 1<<29, // Animate selected (probably do later)
|
||||
SetActive = 1<<27,
|
||||
AnimateReady = 1<<28, // Fade in/out
|
||||
AnimateHot = 1<<29, // Hover highlight
|
||||
AnimateActive = 1<<30, // Animate selected (probably do later)
|
||||
DrawDropShadow = 1<<31,
|
||||
|
||||
Clamp = UIFlags.ClampX | UIFlags.ClampY,
|
||||
PortalView = UIFlags.PortalViewX | UIFlags.PortalViewY,
|
||||
@ -142,7 +145,7 @@ enum UIFlags : u64
|
||||
alias UIF = UIFlags;
|
||||
|
||||
const UIFlags AUTO_FLAGS = UIF.ResizeAdjacent;
|
||||
const UIFlags DRAW_FLAGS = UIF.DrawBackground|UIF.DrawBorder|UIF.DrawText|UIF.PortalView;
|
||||
const UIFlags DRAW_FLAGS = UIF.DrawBackground|UIF.DrawBorder|UIF.DrawText|UIF.PortalView|UIF.DrawDropShadow;
|
||||
|
||||
enum UISignal
|
||||
{
|
||||
@ -229,6 +232,9 @@ CtxMemberInfo(int i)
|
||||
|
||||
struct UICtx
|
||||
{
|
||||
enum FO = FRAME_OVERLAP;
|
||||
enum FS = FONT_SIZES;
|
||||
|
||||
HashTable!(UIHash, UIItem*) items;
|
||||
UIItem* free_items;
|
||||
UIItem* transient_items;
|
||||
@ -244,21 +250,22 @@ struct UICtx
|
||||
|
||||
PlatformWindow* window;
|
||||
Renderer rd;
|
||||
Descriptor[FONT_SIZES] font_descs;
|
||||
Descriptor[FS][FO] font_descs;
|
||||
Descriptor default_tex;
|
||||
Descriptor sampler;
|
||||
Pipeline pipeline;
|
||||
DescSetLayout desc_set_layout;
|
||||
DescSet desc_set;
|
||||
DescSet[FO] desc_sets;
|
||||
PipelineLayout pipeline_layout;
|
||||
Mat4 projection;
|
||||
Vec2 res;
|
||||
|
||||
FontFace font;
|
||||
FontGlyphs[FONT_SIZES] glyph_sets;
|
||||
FontGlyphs[FS] glyph_sets;
|
||||
u32 glyph_sets_used;
|
||||
bool[FO] glyphs_to_load;
|
||||
|
||||
UIBuffer[FRAME_OVERLAP] buffers;
|
||||
UIBuffer[FO] buffers;
|
||||
|
||||
u32 tab_width;
|
||||
Vec4[TS.max][UISH.max] syntax_colors;
|
||||
@ -271,6 +278,7 @@ struct UICtx
|
||||
|
||||
f32 scroll_rate;
|
||||
f32 animation_rate;
|
||||
f32 fade_rate;
|
||||
|
||||
mixin UICtxParameter!(Vec4, "bg_col");
|
||||
mixin UICtxParameter!(Vec4, "bg_col_end");
|
||||
@ -301,9 +309,10 @@ struct UICtx
|
||||
|
||||
struct FontGlyphs
|
||||
{
|
||||
FontAtlasBuf abuf;
|
||||
u32 size;
|
||||
u32 index;
|
||||
FontAtlasBuf abuf;
|
||||
bool[FRAME_OVERLAP] loaded;
|
||||
}
|
||||
|
||||
struct Stack(T)
|
||||
@ -417,7 +426,6 @@ struct Vertex
|
||||
Vec4 cols;
|
||||
Vec4 cols_end;
|
||||
Vec4 corner_radius;
|
||||
Vec2[2] bounds;
|
||||
union
|
||||
{
|
||||
VPos[2] pos;
|
||||
@ -530,6 +538,14 @@ InitUICtx(PlatformWindow* window)
|
||||
{
|
||||
ctx.rd = InitRenderer(handles, MB(16), MB(8));
|
||||
|
||||
DescLayoutBinding[2] layout_bindings = [
|
||||
{ binding: 0, descriptorType: DT.Image, descriptorCount: FONT_SIZES, stageFlags: SS.All },
|
||||
{ binding: 1, descriptorType: DT.Sampler, descriptorCount: 1, stageFlags: SS.All },
|
||||
];
|
||||
|
||||
ctx.desc_set_layout = CreateDescSetLayout(&ctx.rd, layout_bindings);
|
||||
ctx.pipeline_layout = CreatePipelineLayout(&ctx.rd, ctx.desc_set_layout, Mat4.sizeof);
|
||||
|
||||
for(u64 i = 0; i < FRAME_OVERLAP; i += 1)
|
||||
{
|
||||
ctx.buffers[i].m_vtx = CreateMappedBuffer!(Vertex)(&ctx.rd, BT.Vertex, VERTEX_MAX_COUNT);
|
||||
@ -537,18 +553,9 @@ InitUICtx(PlatformWindow* window)
|
||||
ctx.buffers[i].vtx = ctx.buffers[i].m_vtx.data;
|
||||
ctx.buffers[i].idx = ctx.buffers[i].m_idx.data;
|
||||
ctx.buffers[i].idx[0 .. $] = [0, 1, 2, 2, 1, 3];
|
||||
ctx.desc_sets[i] = AllocDescSet(&ctx.rd, ctx.desc_set_layout);
|
||||
}
|
||||
|
||||
DescLayoutBinding[2] layout_bindings = [
|
||||
{ binding: 0, descriptorType: DT.Image, descriptorCount: FONT_SIZES, stageFlags: SS.All },
|
||||
{ binding: 1, descriptorType: DT.Sampler, descriptorCount: 1, stageFlags: SS.All },
|
||||
];
|
||||
|
||||
ctx.desc_set_layout = CreateDescSetLayout(&ctx.rd, layout_bindings);
|
||||
ctx.desc_set = AllocDescSet(&ctx.rd, ctx.desc_set_layout);
|
||||
ctx.pipeline_layout = CreatePipelineLayout(&ctx.rd, ctx.desc_set_layout, Mat4.sizeof);
|
||||
|
||||
|
||||
GfxPipelineInfo ui_info = {
|
||||
vertex_shader: cast(u8[])VERTEX_BYTES,
|
||||
frag_shader: cast(u8[])FRAGMENT_BYTES,
|
||||
@ -564,25 +571,37 @@ InitUICtx(PlatformWindow* window)
|
||||
alpha_op: BO.Add,
|
||||
};
|
||||
|
||||
for(u32 i = 0; i < ctx.font_descs.length; i += 1)
|
||||
for(u64 i = 0; i < ctx.font_descs.length; i += 1)
|
||||
{
|
||||
CreateImageViewTex(&ctx.rd, &ctx.font_descs[i], ATLAS_DIMENSION, ATLAS_DIMENSION, DT.Image, 0, i);
|
||||
ctx.glyph_sets[i].index = i;
|
||||
for(u32 j = 0; j < ctx.font_descs[i].length; j += 1)
|
||||
{
|
||||
CreateImageViewTex(&ctx.rd, &ctx.font_descs[i][j], ATLAS_DIMENSION, ATLAS_DIMENSION, DT.Image, 0, j);
|
||||
ctx.glyph_sets[j].index = j;
|
||||
}
|
||||
}
|
||||
|
||||
FontAtlasBuf* abuf = GetFontAtlas(g_text_size_default);
|
||||
|
||||
LoadFontGlyphs();
|
||||
|
||||
CreateGraphicsPipeline(&ctx.rd, &ctx.pipeline, &ui_info);
|
||||
ctx.sampler = CreateSampler(&ctx.rd, MipmapMode.Nearest, 1);
|
||||
|
||||
u8[512*512*4] white_tex = 255;
|
||||
for(u32 i = 1; i < ctx.font_descs.length; i += 1)
|
||||
for(u64 i = 0; i < ctx.font_descs.length; i += 1)
|
||||
{
|
||||
Transfer(&ctx.rd, &ctx.font_descs[i].view, white_tex, ATLAS_DIMENSION, ATLAS_DIMENSION);
|
||||
for(u32 j = 1; j < ctx.font_descs[i].length; j += 1)
|
||||
{
|
||||
Transfer(&ctx.rd, &ctx.font_descs[i][j].view, white_tex, ATLAS_DIMENSION, ATLAS_DIMENSION);
|
||||
}
|
||||
}
|
||||
|
||||
for(u64 i = 0; i < FRAME_OVERLAP; i += 1)
|
||||
{
|
||||
Write(&ctx.rd, ctx.desc_sets[i], ctx.font_descs[i]);
|
||||
Write(&ctx.rd, ctx.desc_sets[i], &ctx.sampler);
|
||||
}
|
||||
|
||||
Write(&ctx.rd, ctx.desc_set, ctx.font_descs);
|
||||
Write(&ctx.rd, ctx.desc_set, &ctx.sampler);
|
||||
SetClearColors(&ctx.rd, [0.0, 0.0, 0.0, 1.0], [0.0, 0.0, 0.0, 0.0]);
|
||||
}
|
||||
|
||||
@ -619,16 +638,39 @@ GetFontGlyphs(u32 size)
|
||||
|
||||
fg.abuf = CreateAtlas(&ctx.arena, ctx.font, cast(f32)size, ATLAS_DIMENSION);
|
||||
fg.size = size;
|
||||
fg.loaded = false;
|
||||
|
||||
Transfer(&ctx.rd, &ctx.font_descs[i].view, fg.abuf.data, ATLAS_DIMENSION, ATLAS_DIMENSION);
|
||||
Write(&ctx.rd, ctx.desc_set, &ctx.font_descs[i]);
|
||||
Logf("setting size %s to %s", size, i);
|
||||
|
||||
ctx.glyphs_to_load = true;
|
||||
ctx.glyph_sets_used += 1;
|
||||
}
|
||||
|
||||
return fg;
|
||||
}
|
||||
|
||||
void
|
||||
LoadFontGlyphs()
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
u64 fi = ctx.f_idx;
|
||||
|
||||
for(u64 i = 0; i < ctx.glyph_sets_used; i += 1)
|
||||
{
|
||||
FontGlyphs* fg = ctx.glyph_sets.ptr + i;
|
||||
if(!fg.loaded[fi])
|
||||
{
|
||||
Logf("loading %s frame index %s", i, fi);
|
||||
Transfer(&ctx.rd, &ctx.font_descs[fi][i].view, fg.abuf.data, ATLAS_DIMENSION, ATLAS_DIMENSION);
|
||||
fg.loaded[fi] = true;
|
||||
}
|
||||
}
|
||||
|
||||
Write(&ctx.rd, ctx.desc_sets[fi], ctx.font_descs[fi]);
|
||||
|
||||
ctx.glyphs_to_load[fi] = false;
|
||||
}
|
||||
|
||||
void
|
||||
Set(UIItem* item, UICtx* ctx)
|
||||
{
|
||||
@ -789,11 +831,9 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
||||
|
||||
if(item.flags & UIF.AnimateReady)
|
||||
{
|
||||
item.ready_t += ctx.animation_rate * (1.0 - item.ready_t);
|
||||
item.bg_col.a *= item.ready_t;
|
||||
item.bg_col_end.a *= item.ready_t;
|
||||
item.text_col.a *= item.ready_t;
|
||||
item.border_col.a *= item.ready_t;
|
||||
bool is_ready = cast(bool)(item.flags & UIF.SetReady);
|
||||
item.ready_t += ctx.fade_rate * (cast(f32)(is_ready) - item.ready_t);
|
||||
SetColorTransparency(item, item.ready_t);
|
||||
}
|
||||
|
||||
if(item.flags & UIF.DrawBorder && item.border_thickness < 0.0009)
|
||||
@ -807,6 +847,33 @@ MakeItem(T)(T k, UIFlags flags = UIF.None) if(is(T: UIKey) || StringType!T)
|
||||
return item;
|
||||
}
|
||||
|
||||
void
|
||||
SetColorTransparency(UIItem* item, f32 v)
|
||||
{
|
||||
item.bg_col.a *= v;
|
||||
item.bg_col_end.a *= v;
|
||||
item.text_col.a *= v;
|
||||
item.border_col.a *= v;
|
||||
}
|
||||
|
||||
bool
|
||||
Ready(UIItem* item)
|
||||
{
|
||||
return item.ready_t > 0.0001;
|
||||
}
|
||||
|
||||
bool
|
||||
Hovered(bool current_frame, T, U)(T param, U* ptr, U index)
|
||||
{
|
||||
bool result = Hovered!(current_frame)(param);
|
||||
if(result)
|
||||
{
|
||||
*ptr = index;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
Hovered(bool current_frame, T)(T param)
|
||||
{
|
||||
@ -997,7 +1064,6 @@ BeginUI(Inputs* inputs)
|
||||
UIKey hovered = ZeroKey();
|
||||
for(UIItem* item = last; !Nil(item); item = Recurse!(false)(item, g_UI_NIL))
|
||||
{
|
||||
Logf("key %s pos %s rect %s %s", item.key.hash_text, ctx.mouse_pos.v, item.rect.p0.v, item.rect.p1.v);
|
||||
if(InBounds(ctx.mouse_pos, &item.rect) && !ZeroKey(item.key))
|
||||
{
|
||||
hovered = item.key;
|
||||
@ -1050,30 +1116,8 @@ BeginUI(Inputs* inputs)
|
||||
|
||||
ResetStacks(ctx);
|
||||
|
||||
version(ENABLE_RENDERER)
|
||||
{
|
||||
BeginFrame(&ctx.rd);
|
||||
BeginRendering(&ctx.rd);
|
||||
}
|
||||
|
||||
Vec2 ext = GetExtent();
|
||||
if(ext != ctx.res)
|
||||
{
|
||||
ctx.res = ext;
|
||||
Ortho(&ctx.projection, 0.0, 0.0, ext.x, ext.y, -10.0, 10.0);
|
||||
}
|
||||
|
||||
version(ENABLE_RENDERER)
|
||||
{
|
||||
PushConstants(&ctx.rd, ctx.pipeline, &ctx.projection);
|
||||
Bind(&ctx.rd, ctx.pipeline, ctx.desc_set);
|
||||
}
|
||||
|
||||
memset(ctx.buffers[ctx.f_idx].vtx.ptr, 0, Vertex.sizeof * ctx.buffers[ctx.f_idx].count);
|
||||
ctx.buffers[ctx.f_idx].count = 0;
|
||||
ctx.buffers[ctx.f_idx].vtx_offset = 0;
|
||||
|
||||
ctx.animation_rate = 1.0 - pow(2.0, (-30.0f * g_delta));
|
||||
ctx.fade_rate = 1.0 - pow(2.0, (-50.0f * g_delta));
|
||||
ctx.scroll_rate = 1.0 - pow(2.0, (-60.0f * g_delta));
|
||||
|
||||
// Root Item
|
||||
@ -1086,6 +1130,40 @@ EndUI()
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
|
||||
version(ENABLE_RENDERER)
|
||||
{
|
||||
BeginFrame(&ctx.rd);
|
||||
|
||||
if(ctx.glyphs_to_load[ctx.f_idx])
|
||||
{
|
||||
LoadFontGlyphs();
|
||||
}
|
||||
|
||||
BeginRendering(&ctx.rd);
|
||||
|
||||
Vec2 ext = GetExtent();
|
||||
if(ext != ctx.res)
|
||||
{
|
||||
ctx.res = ext;
|
||||
Ortho(&ctx.projection, 0.0, 0.0, ext.x, ext.y, -10.0, 10.0);
|
||||
}
|
||||
|
||||
PushConstants(&ctx.rd, ctx.pipeline, &ctx.projection);
|
||||
Bind(&ctx.rd, ctx.pipeline, ctx.desc_sets[ctx.f_idx]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec2 ext = GetExtent();
|
||||
if(ext != ctx.res)
|
||||
{
|
||||
ctx.res = ext;
|
||||
}
|
||||
}
|
||||
|
||||
memset(ctx.buffers[ctx.f_idx].vtx.ptr, 0, Vertex.sizeof * ctx.buffers[ctx.f_idx].count);
|
||||
ctx.buffers[ctx.f_idx].count = 0;
|
||||
ctx.buffers[ctx.f_idx].vtx_offset = 0;
|
||||
|
||||
// Automatic signals
|
||||
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(false)(item, g_UI_NIL))
|
||||
{
|
||||
@ -1296,6 +1374,28 @@ EndUI()
|
||||
// Render Items
|
||||
for(UIItem* item = ctx.root_first; !Nil(item); item = Recurse!(true)(item, g_UI_NIL))
|
||||
{
|
||||
if(item.flags & UIF.AnimateReady && item.ready_t < 1.0)
|
||||
{
|
||||
UIItem* first = item.first, last = item.last;
|
||||
|
||||
item.first = item.last = g_UI_NIL;
|
||||
|
||||
UIItem* next = Recurse!(true)(item, g_UI_NIL);
|
||||
|
||||
item.first = first;
|
||||
item.last = last;
|
||||
|
||||
for(UIItem* c = item.first; !Nil(c) && c != next; c = Recurse!(true)(c, g_UI_NIL))
|
||||
{
|
||||
if(!(c.flags & UIF.AnimateReady))
|
||||
{
|
||||
c.flags |= UIF.AnimateReady;
|
||||
c.ready_t = item.ready_t;
|
||||
SetColorTransparency(c, item.ready_t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RenderItem(ctx, item);
|
||||
}
|
||||
|
||||
@ -1326,6 +1426,13 @@ FocusItem(Args...)(string str, Args args)
|
||||
g_ui_ctx.focus_item = Get(str, args);
|
||||
}
|
||||
|
||||
void
|
||||
Clamp(UICtx* ctx, Vertex* v)
|
||||
{
|
||||
v.dst_start = Clamp(v.dst_start, Vec2(0.0), Vec2(ctx.res));
|
||||
v.dst_end = Clamp(v.dst_end, Vec2(0.0), Vec2(ctx.res));
|
||||
}
|
||||
|
||||
void
|
||||
FocusItem(T)(T focus) if(is(T == UIKey) || StringType!T || is(T == UIItem*))
|
||||
{
|
||||
@ -1346,41 +1453,57 @@ RenderItem(UICtx* ctx, UIItem* item)
|
||||
if(item.rendered) return;
|
||||
if(!(item.flags & DRAW_FLAGS)) return;
|
||||
|
||||
Vertex* v = null;
|
||||
Vec2 border_p0 = item.rect.p0 - Vec2(InnerOffset!(A2D.X, true )(item), InnerOffset!(A2D.Y, true )(item));
|
||||
Vec2 border_p1 = item.rect.p1 + Vec2(InnerOffset!(A2D.X, false)(item), InnerOffset!(A2D.Y, false)(item));
|
||||
|
||||
assert(border_p0.x <= item.rect.p0.x && border_p0.y <= item.rect.p0.y);
|
||||
assert(border_p1.x >= item.rect.p1.x && border_p1.y >= item.rect.p1.y);
|
||||
|
||||
if(item.flags & UIF.DrawDropShadow)
|
||||
{
|
||||
f32 px = clamp(((item.size.x+item.size.y)/2.0)*0.004, 1.0, f32.max);
|
||||
f32 alpha = 0.1;
|
||||
if(item.flags & UIF.AnimateReady)
|
||||
{
|
||||
alpha *= item.ready_t;
|
||||
}
|
||||
|
||||
Vertex* v = GetVertex(ctx);
|
||||
v.dst_start = border_p0 - Vec2(px);
|
||||
v.dst_end = border_p1 + Vec2(px);
|
||||
v.cols = Vec4(0.0, 0.0, 0.0, alpha);
|
||||
v.cols_end = Vec4(0.0, 0.0, 0.0, alpha);
|
||||
v.corner_radius = 0.8f;
|
||||
v.edge_softness = 8.0f;
|
||||
|
||||
Clamp(ctx, v);
|
||||
}
|
||||
|
||||
if(item.flags & UIF.DrawBackground)
|
||||
{
|
||||
v = GetVertex(ctx);
|
||||
Vertex* v = GetVertex(ctx);
|
||||
v.dst_start = item.rect.p0;
|
||||
v.dst_end = item.rect.p1;
|
||||
v.cols = item.bg_col;
|
||||
v.cols_end = item.flags & UIF.Gradient ? item.bg_col_end : item.bg_col;
|
||||
v.corner_radius = item.flags & UIF.DrawBorder ? item.corner_radius*0.5 : item.corner_radius;
|
||||
v.edge_softness = item.edge_softness;
|
||||
v.bounds = ItemBounds(item.parent);
|
||||
|
||||
AddVertexCount(ctx);
|
||||
Clamp(ctx, v);
|
||||
}
|
||||
|
||||
if(item.flags & UIF.DrawBorder)
|
||||
{
|
||||
v = GetVertex(ctx);
|
||||
v.dst_start = item.rect.p0 - Vec2(InnerOffset!(A2D.X, true )(item), InnerOffset!(A2D.Y, true )(item));
|
||||
v.dst_end = item.rect.p1 + Vec2(InnerOffset!(A2D.X, false)(item), InnerOffset!(A2D.Y, false)(item));
|
||||
Vertex* v = GetVertex(ctx);
|
||||
v.dst_start = border_p0;
|
||||
v.dst_end = border_p1;
|
||||
v.cols = item.border_col;
|
||||
v.cols_end = item.flags & UIF.Gradient ? item.bg_col_end : item.bg_col;
|
||||
v.corner_radius = item.corner_radius;
|
||||
v.border_thickness = item.border_thickness;
|
||||
v.edge_softness = item.edge_softness;
|
||||
v.bounds = ItemBounds(item.parent);
|
||||
|
||||
AddVertexCount(ctx);
|
||||
}
|
||||
|
||||
if(v)
|
||||
{
|
||||
v.dst_start = Clamp(v.dst_start, Vec2(0.0), Vec2(ctx.res));
|
||||
v.dst_end = Clamp(v.dst_end, Vec2(0.0), Vec2(ctx.res));
|
||||
Clamp(ctx, v);
|
||||
}
|
||||
|
||||
if(item.flags & UIF.DrawText || item.display_string)
|
||||
@ -1960,7 +2083,7 @@ DrawGlyph(UIItem* item, Glyph* glyph, u32 atlas_index, f32* x_pos, f32 y, f32 li
|
||||
f32 w = glyph.plane_right-glyph.plane_left;
|
||||
f32 h = glyph.plane_bottom-glyph.plane_top;
|
||||
|
||||
v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
||||
v = GetVertex(ctx);
|
||||
|
||||
f32 y_pos = y + glyph.plane_top;
|
||||
|
||||
@ -1969,7 +2092,6 @@ DrawGlyph(UIItem* item, Glyph* glyph, u32 atlas_index, f32* x_pos, f32 y, f32 li
|
||||
v.cols = col;
|
||||
v.cols_end = col;
|
||||
v.texture = true;
|
||||
v.bounds = ItemBounds(item);
|
||||
v.atlas_index = index;
|
||||
v.src_start = Vec2(glyph.atlas_left, glyph.atlas_top);
|
||||
v.src_end = Vec2(glyph.atlas_right, glyph.atlas_bottom);
|
||||
@ -2001,19 +2123,11 @@ DrawGlyph(UIItem* item, Glyph* glyph, u32 atlas_index, f32* x_pos, f32 y, f32 li
|
||||
}
|
||||
}
|
||||
|
||||
AddVertexCount(ctx);
|
||||
|
||||
*x_pos += advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pragma(inline) Vec2[2]
|
||||
ItemBounds(UIItem* item)
|
||||
{
|
||||
return [item.rect.p0, item.rect.p1];
|
||||
}
|
||||
|
||||
pragma(inline) f32
|
||||
AxisPadding(Axis2D axis)(UIItem* item)
|
||||
{
|
||||
@ -2041,7 +2155,8 @@ InnerOffset(Axis2D axis, bool start)(UIItem* item)
|
||||
pragma(inline) Vertex*
|
||||
GetVertex(UICtx* ctx)
|
||||
{
|
||||
return ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
||||
assert(ctx.buffers[ctx.f_idx].count < VERTEX_MAX_COUNT);
|
||||
return ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count++;
|
||||
}
|
||||
|
||||
static UISize[2]
|
||||
@ -2062,13 +2177,6 @@ UISY(SizeType type, f32 value = 1.0, f32 strictness = 1.0)
|
||||
return [UISize(ST.Percentage, 1.0), UISize(type, value, strictness)];
|
||||
}
|
||||
|
||||
pragma(inline) void
|
||||
AddVertexCount(UICtx* ctx)
|
||||
{
|
||||
ctx.buffers[ctx.f_idx].count += 1;
|
||||
assert(ctx.buffers[ctx.f_idx].count < VERTEX_MAX_COUNT);
|
||||
}
|
||||
|
||||
bool
|
||||
Nil(UIItem* item)
|
||||
{
|
||||
|
||||
@ -15,10 +15,13 @@ __gshared Editor* g_NIL_ED;
|
||||
__gshared const UIKey ZERO = ZeroKey();
|
||||
|
||||
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);
|
||||
Vec4 CMD_COL = Vec4(0.22, 0.22, 0.22, 1.0);
|
||||
Vec4 CMD_BORDER_COL = Vec4(0.48, 0.48, 0.48, 1.0);
|
||||
Vec4 CMD_INPUT_COL = Vec4(0.130, 0.420, 0.640, 1.0);
|
||||
Vec4 GREY = Vec4(0.45, 0.45, 0.45, 1.0);
|
||||
Vec4 WHITE = HexCol(0xFFFFFF);
|
||||
Vec4 BLUE = HexCol(0x4EA9FF);
|
||||
Vec4 RED = HexCol(0xFF3268);
|
||||
Vec4 YELLOW = HexCol(0xF7C443);
|
||||
@ -239,27 +242,33 @@ EditorView(Panel* p)
|
||||
}
|
||||
|
||||
void
|
||||
CommandPalette(CmdPalette* cmd)
|
||||
CommandPalette(CmdPalette* cmd, bool active)
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
Vec2 ext = GetExtent();
|
||||
FontAtlasBuf* abuf = &g_ui_ctx.glyph_sets[0].abuf;
|
||||
|
||||
f32 w = ext.x*0.4;
|
||||
f32 w = ext.x*0.6;
|
||||
f32 h = ext.y*0.7;
|
||||
|
||||
enum UIPushInfo[] cmd_params = [
|
||||
{ "layout_axis", q{ A2D.Y } },
|
||||
{ "fixed_pos", q{ Vec2(ext.x*0.3, ext.y*0.1) } },
|
||||
{ "fixed_pos", q{ Vec2(ext.x*0.2, ext.y*0.1) } },
|
||||
{ "bg_col", q{ BG_COL } },
|
||||
{ "border_col", q{ HL_BORDER_COL } },
|
||||
{ "border_thickness", q{ 4.0 } },
|
||||
{ "corner_radius", q{ Vec4(8.0) } },
|
||||
{ "size_info", q{ UIS2(ST.Pixels, ST.Pixels, w, h) } },
|
||||
];
|
||||
|
||||
mixin(PushOnce!(cmd_params));
|
||||
UIItem* cmd_item = MakeItem("###cmd_palette", UIF.Window|UIF.FixedPosition|UIF.DrawBackground|UIF.DrawBorder|UIF.AnimateReady);
|
||||
|
||||
UIFlags cmd_flags = UIF.Window|UIF.FixedPosition|UIF.AnimateReady|UIF.DrawDropShadow|UIF.DrawBackground;
|
||||
if(active)
|
||||
{
|
||||
cmd_flags |= UIF.SetReady;
|
||||
}
|
||||
|
||||
UIItem* cmd_item = MakeItem("###cmd_palette", cmd_flags);
|
||||
|
||||
f32 padding_y = 4.0;
|
||||
|
||||
@ -267,54 +276,105 @@ CommandPalette(CmdPalette* cmd)
|
||||
mixin(PushScope!("padding", q{ Vec2(4.0, padding_y) }));
|
||||
|
||||
enum UIPushInfo[] cmd_input_params = [
|
||||
{ "bg_col", q{ HL_BG_COL } },
|
||||
{ "bg_col", q{ CMD_COL } },
|
||||
{ "border_col", q{ CMD_BORDER_COL } },
|
||||
{ "border_thickness", q{ 1.0 }},
|
||||
{ "text_size", q{ 18 }},
|
||||
{ "corner_radius", q{ Vec4(12.0, 12.0, 0.0, 0.0)}},
|
||||
{ "edge_softness", q{ 1.0 }},
|
||||
{ "size_info", q{ UISY(ST.TextSize) } },
|
||||
{ "padding", q{ Vec2A2(6.0, 6.0, 10.0, 10.0)} },
|
||||
{ "display_string", q{ Str(cmd.buffer[0 .. cmd.icount]) } },
|
||||
];
|
||||
|
||||
mixin(PushOnce!(cmd_input_params));
|
||||
|
||||
UIKey zero = ZeroKey();
|
||||
MakeItem(zero, UIF.DrawBorder|UIF.DrawBackground|UIF.DrawText|UIF.Overflow);
|
||||
MakeItem(ZERO, UIF.DrawBorder|UIF.DrawBackground|UIF.DrawText|UIF.Overflow|UIF.VerticalAlignText);
|
||||
|
||||
enum UIPushInfo[] sep_params = [
|
||||
{ "padding", q{ Vec2(0.0) } },
|
||||
{ "size_info", q{ UISY(ST.Pixels, 4.0) } },
|
||||
{ "bg_col", q{ HL_BORDER_COL } },
|
||||
// the two sizes seems to fuck this up somehow
|
||||
u32 title_px = 16;
|
||||
u32 sub_px = 16;
|
||||
f32 title_pad = 2.0f;
|
||||
f32 opt_y_pad = 4.0;
|
||||
f32 opt_x_pad = 8.0;
|
||||
f32 opt_height = cast(f32)(title_px + sub_px) + opt_y_pad*2.0 + title_pad;
|
||||
|
||||
enum UIPushInfo[] cmd_opts_box_params = [
|
||||
{ "layout_axis", q{ A2D.Y }},
|
||||
{ "border_col", q{ CMD_BORDER_COL } },
|
||||
{ "border_thickness", q{ 1.0 } },
|
||||
{ "corner_radius", q{ Vec4(0.0, 0.0, 12.0, 12.0) } },
|
||||
{ "edge_softness", q{ 1.0 }},
|
||||
{ "size_info", q{ UISY(ST.Pixels, h-opt_height) } },
|
||||
];
|
||||
|
||||
mixin(PushOnce!(sep_params));
|
||||
MakeItem(zero, UIF.DrawBackground);
|
||||
mixin(PushOnce!(cmd_opts_box_params));
|
||||
|
||||
mixin(PushScope!("padding", q{ Vec2(4.0) } ));
|
||||
mixin(PushScope!("size_info", q{ UISY(ST.TextSize) } ));
|
||||
UIItem* opt_box = MakeItem(ZERO, UIF.DrawBorder);
|
||||
|
||||
u64 max_opts = cast(u64)ceil(h/abuf.atlas.line_height);
|
||||
mixin(PushScope!("parent", q{ opt_box }));
|
||||
mixin(PushScope!("padding", q{ Vec2A2(opt_x_pad, opt_x_pad, opt_y_pad, opt_y_pad) } ));
|
||||
mixin(PushScope!("size_info", q{ UISY(ST.Pixels, opt_height) } ));
|
||||
|
||||
u64 max_opts = cast(u64)ceil(h/opt_height);
|
||||
|
||||
Vec4[2] opt_cols = [
|
||||
Vec4(0.22, 0.22, 0.22, 1.0),
|
||||
Vec4(0.35, 0.35, 0.35, 1.0),
|
||||
];
|
||||
|
||||
// Active should be highlights around the item like File Pilot
|
||||
// Active should be highlights around the item like File Pilot (maybe not)
|
||||
|
||||
bool opts = cast(bool)cmd.opt_strs.length;
|
||||
if(opts)
|
||||
{
|
||||
for(u64 i = 0; i < cmd.opt_strs.length && i < max_opts; i += 1)
|
||||
{
|
||||
PushDisplayString(Str(cmd.opt_strs[i]), true);
|
||||
PushBgCol(opt_cols[i%2], true);
|
||||
|
||||
UIKey k = MakeKey("###copt_%s", i);
|
||||
if(Hovered!(true)(k))
|
||||
{
|
||||
cmd.selected = i;
|
||||
}
|
||||
UIKey k = MakeKey("###opt_%s", i);
|
||||
Hovered!(true)(k, &cmd.selected, i);
|
||||
|
||||
MakeItem(k, UIF.DrawBackground|UIF.DrawText|UIF.AnimateHot|(cmd.selected == i ? UIF.SetHot : UIF.None));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(u64 i = 0; i < cmd.commands.length && i < max_opts; i += 1)
|
||||
{
|
||||
PushBgCol(opt_cols[i%2], true);
|
||||
PushLayoutAxis(A2D.Y, true);
|
||||
|
||||
UIKey k = MakeKey("###optc_%s", i);
|
||||
Hovered!(true)(k, &cmd.selected, i);
|
||||
|
||||
UIItem* optc = MakeItem(k, UIF.DrawBackground|UIF.AnimateHot|(cmd.selected == i ? UIF.SetHot : UIF.None));
|
||||
PushParent(optc);
|
||||
|
||||
PushSizeInfo(UISY(ST.TextSize));
|
||||
|
||||
PushTextSize(title_px, true);
|
||||
PushTextCol(WHITE, true);
|
||||
PushPadding(Vec2A2(opt_x_pad, opt_x_pad, 0.0, title_pad), true);
|
||||
PushDisplayString(ScratchAlloc(cmd.commands[i].name), true);
|
||||
|
||||
MakeItem(ZERO, UIF.DrawText);
|
||||
|
||||
PushTextSize(sub_px, true);
|
||||
PushTextCol(GREY, true);
|
||||
PushPadding(Vec2A2(opt_x_pad, opt_x_pad, 0.0, 0.0), true);
|
||||
PushDisplayString(ScratchAlloc(cmd.commands[i].desc), true);
|
||||
|
||||
MakeItem(ZERO, UIF.DrawText);
|
||||
|
||||
Pop!("parent", "size_info");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UIItem*
|
||||
Container(Axis2D axis, UISize[2] size_info)
|
||||
Container(bool push = true)(Axis2D axis, UISize[2] size_info)
|
||||
{
|
||||
enum UIPushInfo[] container_info = [
|
||||
{ "layout_axis", q{ axis } },
|
||||
@ -323,7 +383,14 @@ Container(Axis2D axis, UISize[2] size_info)
|
||||
|
||||
mixin(PushOnce!(container_info));
|
||||
|
||||
return MakeItem(ZeroKey());
|
||||
UIItem* item = MakeItem(ZERO);
|
||||
|
||||
static if(push)
|
||||
{
|
||||
Push!("parent")(item);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user