replace ui double buffering with persistent cmd-driven state

This commit is contained in:
jacob 2025-11-08 18:14:54 -06:00
parent a7c286d912
commit 9850de005c
8 changed files with 606 additions and 482 deletions

View File

@ -434,8 +434,10 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
#endif
//- struct region
#define StructRegion(name) i8 name
#define CopyStructRegion(dst, src, r0, r1) CopyBytes(&dst->r0, &src->r0, (u8 *)&dst->r1 - (u8 *)&dst->r0)
#define BeginFieldRegion(name) i8 __begfieldreg__##name
#define EndFieldRegion(name) i8 __endfieldreg___##name
#define CopyFieldRegion(dst, src, r) CopyBytes(&dst->(__begfieldreg__##r), &src->(__begfieldreg__##r), (u8 *)&dst->(__endfieldreg__##r) - (u8 *)&dst->(__begfieldreg__##r))
#define ZeroFieldRegion(dst, src, r) ZeroBytes(&dst->(__begfieldreg__##r), &src->(__begfieldreg__##r), (u8 *)&dst->(__endfieldreg__##r) - (u8 *)&dst->(__begfieldreg__##r))
//- Packed
#if CompilerIsMsvc

View File

@ -113,9 +113,11 @@ JobDef(PP_VisWorker, sig, job_id)
{
PP_CommandsWidget commands_widget;
b32 ui_debug;
b32 show_console;
};
VisPersist persist = ZI;
String window_restore = ZI;
// persist.ui_debug = 1;
//////////////////////////////
//- Swap in
@ -174,6 +176,7 @@ JobDef(PP_VisWorker, sig, job_id)
//////////////////////////////
//- Build console
if (persist.show_console)
{
b32 minimized = 1;
PP_BuildConsoleWidget(minimized);
@ -188,6 +191,15 @@ JobDef(PP_VisWorker, sig, job_id)
{
persist.ui_debug = !persist.ui_debug;
}
if (PP_PushCommandsWidgetItem(&persist.commands_widget, Lit("Console")).m1_presses > 0)
{
b32 new = !persist.show_console;
if (new)
{
LogInfoF("Enabled console");
}
persist.show_console = new;
}
if (PP_PushCommandsWidgetItem(&persist.commands_widget, Lit("Fullscreen")).m1_presses > 0)
{
b32 new = !window_frame.fullscreen;

View File

@ -32,16 +32,16 @@ void PP_PushWidgetThemeStyles(PP_WidgetTheme theme)
void PP_BeginCommandsWidget(PP_CommandsWidget *widget)
{
ZeroStruct(&widget->build);
widget->build.cp = UI_PushCP(0);
widget->build.cp = UI_PushCP(UI_NilKey);
UI_Push(Tag, HashF("commands widget"));
}
UI_Report PP_PushCommandsWidgetItem(PP_CommandsWidget *widget, String name)
{
Arena *build_arena = UI_GetFrameArena();
Arena *frame_arena = UI_FrameArena();
UI_Key key = UI_KeyF("btn%F", FmtSint(widget->build.num_items));
PP_CommandsWidgetItem *item = PushStruct(build_arena, PP_CommandsWidgetItem);
PP_CommandsWidgetItem *item = PushStruct(frame_arena, PP_CommandsWidgetItem);
item->name = name;
item->key = key;
QueuePush(widget->build.first_item, widget->build.last_item, item);
@ -53,7 +53,7 @@ UI_Report PP_PushCommandsWidgetItem(PP_CommandsWidget *widget, String name)
void PP_EndCommandsWidget(PP_CommandsWidget *widget)
{
PP_WidgetTheme theme = PP_GetWidgetTheme();
Vec2 cursor_pos = UI_GetCursorPos();
Vec2 cursor_pos = UI_CursorPos();
UI_Push(Tag, HashF("commands widget"));
@ -83,10 +83,10 @@ void PP_EndCommandsWidget(PP_CommandsWidget *widget)
UI_Push(ChildLayoutAxis, Axis_Y);
UI_Push(FloatingPos, widget->pos);
UI_SetNext(Flags, UI_BoxFlag_Floating);
UI_PushCP(UI_BuildBox(UI_KeyF("titlebar")));
UI_PushCP(UI_BuildBoxEx(UI_KeyF("titlebar")));
{
/* Title bar */
UI_PushCP(0);
UI_PushCP(UI_NilKey);
{
UI_Push(BackgroundColor, titlebar_color);
UI_Push(BorderColor, titlebar_border_color);
@ -95,13 +95,13 @@ void PP_EndCommandsWidget(PP_CommandsWidget *widget)
UI_Push(Width, UI_GROW(1, 0));
UI_Push(Height, UI_FNT(2, 1));
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_PushCP(UI_BuildBox(titlebar_key));
UI_PushCP(UI_BuildBoxEx(titlebar_key));
{
UI_Push(Width, UI_GROW(1, 0));
UI_Push(BorderColor, 0);
/* Left title box */
UI_BuildRow(UI_NilKey);
UI_BuildRow();
/* Title box */
UI_SetNext(FontSize, theme.window_title_font_size);
@ -109,10 +109,10 @@ void PP_EndCommandsWidget(PP_CommandsWidget *widget)
UI_SetNext(Width, UI_SHRINK(0, 1));
UI_SetNext(Text, Lit("Commands"));
UI_SetNext(Flags, UI_BoxFlag_DrawText);
UI_BuildBox(UI_NilKey);
UI_BuildBox();
/* Right title box */
UI_BuildRow(UI_NilKey);
UI_BuildRow();
}
UI_PopCP(UI_TopCP());
}
@ -122,18 +122,18 @@ void PP_EndCommandsWidget(PP_CommandsWidget *widget)
f32 padding = theme.window_border;
UI_SetNext(Tint, 0);
UI_SetNext(Rounding, 0);
UI_PushCP(UI_BuildRow(UI_NilKey));
UI_PushCP(UI_BuildRow());
{
UI_BuildSpacer(UI_PIX(padding, 1));
UI_BuildSpacer(UI_PIX(padding, 1), Axis_X);
{
UI_SetNext(Tint, 0);
UI_SetNext(Rounding, 0);
UI_SetNext(Width, UI_GROW(1, 0));
UI_PushCP(UI_BuildColumn(UI_NilKey));
UI_PushCP(UI_BuildColumn());
{
for (PP_CommandsWidgetItem *item = widget->build.first_item; item; item = item->next)
{
UI_BuildDivider(UI_PIX(1, 1), theme.divider_color);
UI_BuildDivider(UI_PIX(1, 1), theme.divider_color, Axis_Y);
UI_Key btn_key = item->key;
UI_Report btn_rep = UI_ReportFromKey(btn_key);
@ -153,7 +153,7 @@ void PP_EndCommandsWidget(PP_CommandsWidget *widget)
UI_SetNext(Rounding, 0);
UI_SetNext(Tint, 0);
UI_PushCP(UI_BuildRow(UI_NilKey));
UI_PushCP(UI_BuildRow());
{
UI_SetNext(BorderColor, border_color);
UI_SetNext(BackgroundColor, color);
@ -162,16 +162,16 @@ void PP_EndCommandsWidget(PP_CommandsWidget *widget)
UI_SetNext(Height, UI_FNT(1.5, 1));
UI_SetNext(ChildAlignment, UI_Alignment_Left);
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_PushCP(UI_BuildRow(btn_key));
UI_PushCP(UI_BuildRowEx(btn_key));
{
/* Begin spacer */
UI_BuildSpacer(UI_PIX(20, 1));
UI_BuildSpacer(UI_PIX(20, 1), Axis_X);
/* Command label */
UI_BuildLabel(item->name);
/* Middle spacer */
UI_BuildSpacer(UI_GROW(1, 0));
UI_BuildSpacer(UI_GROW(1, 0), Axis_X);
/* Command hotkey button */
UI_SetNext(Text, UI_StringF("Test"));
@ -182,14 +182,14 @@ void PP_EndCommandsWidget(PP_CommandsWidget *widget)
UI_SetNext(BackgroundColor, Color_Cyan);
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_PushCP(UI_BuildRow(UI_NilKey));
UI_PushCP(UI_BuildRow());
{
}
UI_PopCP(UI_TopCP());
/* End spacer */
UI_BuildSpacer(UI_PIX(20, 1));
UI_BuildSpacer(UI_PIX(20, 1), Axis_X);
}
UI_PopCP(UI_TopCP());
}
@ -198,18 +198,18 @@ void PP_EndCommandsWidget(PP_CommandsWidget *widget)
}
UI_PopCP(UI_TopCP());
}
UI_BuildSpacer(UI_PIX(padding, 1));
UI_BuildSpacer(UI_PIX(padding, 1), Axis_X);
}
UI_PopCP(UI_TopCP());
UI_BuildSpacer(UI_PIX(padding, 1));
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
UI_PopCP(UI_TopCP());
}
////////////////////////////////////////////////////////////
//~ Console widget
UI_Box *PP_BuildConsoleWidget(b32 minimized)
UI_Key PP_BuildConsoleWidget(b32 minimized)
{
/* TODO: Remove this whole thing */
__prof;
@ -246,7 +246,7 @@ UI_Box *PP_BuildConsoleWidget(b32 minimized)
f32 fade_curve = 0.5;
i64 now_ns = TimeNs();
UI_Box *console_box = 0;
UI_Key console_box = ZI;
{
UI_SetNext(Border, 0);
if (minimized)
@ -261,7 +261,7 @@ UI_Box *PP_BuildConsoleWidget(b32 minimized)
UI_SetNext(Width, UI_GROW(1, 0));
UI_SetNext(Height, UI_SHRINK(0, 1));
}
console_box = UI_BuildColumn(UI_KeyF("Console box"));
console_box = UI_BuildColumnEx(UI_KeyF("Console box"));
UI_PushCP(console_box);
{
/* Gather display logs */
@ -312,7 +312,7 @@ UI_Box *PP_BuildConsoleWidget(b32 minimized)
FmtUintZ(datetime.milliseconds, 3),
FmtString(text));
}
UI_PushCP(0);
UI_PushCP(UI_NilKey);
{
Vec4 tint = VEC4(1, 1, 1, opacity);
UI_Push(Tint, tint);
@ -325,17 +325,17 @@ UI_Box *PP_BuildConsoleWidget(b32 minimized)
UI_Push(Rounding, UI_RPIX(0));
UI_Push(Border, 1);
UI_Push(ChildAlignment, UI_Alignment_Left);
UI_PushCP(UI_BuildRow(UI_NilKey));
UI_PushCP(UI_BuildRow());
{
// UI_SetNext(Height, UI_PIX(100, 0));
UI_BuildSpacer(UI_PIX(10, 0));
UI_BuildSpacer(UI_PIX(10, 0), Axis_X);
UI_Push(BackgroundColor, 0);
UI_Push(Border, 0);
UI_Push(Text, text);
UI_Push(Width, UI_GROW(1, 0));
UI_Push(Height, UI_SHRINK(0, 1));
UI_Push(Flags, UI_BoxFlag_DrawText);
UI_BuildBox(UI_NilKey);
UI_BuildBox();
}
UI_PopCP(UI_TopCP());
}

View File

@ -60,4 +60,4 @@ void PP_EndCommandsWidget(PP_CommandsWidget *widget);
////////////////////////////////////////////////////////////
//~ Console widget
UI_Box *PP_BuildConsoleWidget(b32 minimized);
UI_Key PP_BuildConsoleWidget(b32 minimized);

View File

@ -1,15 +1,15 @@
////////////////////////////////////////////////////////////
//~ Label helpers
UI_Box *UI_BuildLabel(String text)
UI_Key UI_BuildLabel(String text)
{
UI_Box *parent = UI_UseTop(Parent);
UI_Key parent = UI_UseTop(Parent);
ResourceKey font = UI_UseTop(Font);
f32 font_size = UI_UseTop(FontSize);
Vec4 tint = UI_UseTop(Tint);
UI_Box *box = 0;
UI_PushCP(0);
UI_Key key = ZI;
UI_PushCP(UI_NilKey);
{
UI_PushDefaults();
UI_Push(Parent, parent);
@ -20,13 +20,13 @@ UI_Box *UI_BuildLabel(String text)
UI_SetNext(Height, UI_SHRINK(0, 1));
UI_SetNext(Text, text);
UI_SetNext(Flags, UI_BoxFlag_DrawText);
box = UI_BuildBox(UI_NilKey);
key = UI_BuildBox();
}
UI_PopCP(UI_TopCP());
return box;
return key;
}
UI_Box *UI_BuildLabelF_(char *fmt_cstr, ...)
UI_Key UI_BuildLabelF_(char *fmt_cstr, ...)
{
TempArena scratch = BeginScratchNoConflict();
String str = ZI;
@ -36,39 +36,37 @@ UI_Box *UI_BuildLabelF_(char *fmt_cstr, ...)
str = FormatStringV(scratch.arena, StringFromCstrNoLimit(fmt_cstr), va);
va_end(va);
}
UI_Box *box = UI_BuildLabel(str);
UI_Key key = UI_BuildLabel(str);
EndScratch(scratch);
return box;
return key;
}
////////////////////////////////////////////////////////////
//~ Spacing helpers
UI_Box *UI_BuildSpacer(UI_Size size)
UI_Key UI_BuildSpacer(UI_Size size, Axis axis)
{
UI_Box *box = 0;
UI_Box *parent = UI_UseTop(Parent);
Axis axis = parent->child_layout_axis;
UI_PushCP(0);
UI_Key parent = UI_UseTop(Parent);
UI_Key key = ZI;
UI_PushCP(UI_NilKey);
{
UI_PushDefaults();
UI_Push(Parent, parent);
UI_Push(Tint, 0);
UI_Push(AxisSize, UI_GROW(1, 0), .axis = !axis);
UI_Push(AxisSize, size, .axis = axis);
box = UI_BuildBox(UI_NilKey);
key = UI_BuildBox();
}
UI_PopCP(UI_TopCP());
return box;
return key;
}
UI_Box *UI_BuildDivider(UI_Size size, Vec4 color)
UI_Key UI_BuildDivider(UI_Size size, Vec4 color, Axis axis)
{
UI_Box *box = 0;
UI_Box *parent = UI_UseTop(Parent);
UI_Key key = ZI;
UI_Key parent = UI_UseTop(Parent);
Vec4 tint = UI_UseTop(Tint);
Axis axis = parent->child_layout_axis;
UI_PushCP(0);
UI_PushCP(UI_NilKey);
{
UI_PushDefaults();
UI_Push(Parent, parent);
@ -76,25 +74,23 @@ UI_Box *UI_BuildDivider(UI_Size size, Vec4 color)
UI_Push(BackgroundColor, color);
UI_Push(AxisSize, UI_GROW(1, 0), .axis = !axis);
UI_Push(AxisSize, size, .axis = axis);
box = UI_BuildBox(UI_NilKey);
key = UI_BuildBox();
}
UI_PopCP(UI_TopCP());
return box;
return key;
}
////////////////////////////////////////////////////////////
//~ Layout helpers
UI_Box *UI_BuildColumn(UI_Key key)
UI_Key UI_BuildColumnEx(UI_Key key)
{
UI_SetNext(ChildLayoutAxis, Axis_Y);
UI_Box *box = UI_BuildBox(key);
return box;
return UI_BuildBoxEx(key);
}
UI_Box *UI_BuildRow(UI_Key key)
UI_Key UI_BuildRowEx(UI_Key key)
{
UI_SetNext(ChildLayoutAxis, Axis_X);
UI_Box *box = UI_BuildBox(key);
return box;
return UI_BuildBoxEx(key);
}

View File

@ -1,18 +1,21 @@
////////////////////////////////////////////////////////////
//~ Label helpers
UI_Box *UI_BuildLabel(String text);
UI_Key UI_BuildLabel(String text);
#define UI_BuildLabelF(fmt_cstr, ...) UI_BuildLabelF_(fmt_cstr, __VA_ARGS__, FmtEnd)
UI_Box *UI_BuildLabelF_(char *fmt_cstr, ...);
UI_Key UI_BuildLabelF_(char *fmt_cstr, ...);
////////////////////////////////////////////////////////////
//~ Spacing helpers
UI_Box *UI_BuildSpacer(UI_Size size);
UI_Box *UI_BuildDivider(UI_Size size, Vec4 color);
UI_Key UI_BuildSpacer(UI_Size size, Axis axis);
UI_Key UI_BuildDivider(UI_Size size, Vec4 color, Axis axis);
////////////////////////////////////////////////////////////
//~ Layout helpers
UI_Box *UI_BuildColumn(UI_Key key);
UI_Box *UI_BuildRow(UI_Key key);
UI_Key UI_BuildColumnEx(UI_Key key);
UI_Key UI_BuildRowEx(UI_Key key);
#define UI_BuildColumn() UI_BuildColumnEx(UI_TransKey())
#define UI_BuildRow() UI_BuildRowEx(UI_TransKey())

File diff suppressed because it is too large Load Diff

View File

@ -90,32 +90,35 @@ Enum(UI_BoxFlag)
////////////////////////////////////////////////////////////
//~ Style types
#define UI_StyleKindsXMacro(x) \
x(Flags, UI_BoxFlag) \
x(Parent, struct UI_Box *) \
x(Tag, u64) \
x(ChildLayoutAxis, Axis) \
x(ChildAlignmentX, UI_AxisAlignment) \
x(ChildAlignmentY, UI_AxisAlignment) \
x(Width, UI_Size) \
x(Height, UI_Size) \
x(BackgroundColor, Vec4) \
x(BorderColor, Vec4) \
x(DebugColor, Vec4) \
x(Tint, Vec4) \
x(Border, f32) \
x(FloatingPos, Vec2) \
x(Rounding, UI_Round) \
x(Font, ResourceKey) \
x(FontSize, u32) \
x(Text, String) \
/* ----------------------------------- */ \
/* --------- Virtual styles --------- */ \
/* ----------------------------------- */ \
x(BeginVirtualStyles_, i8) \
x(ChildAlignment, UI_Alignment) \
x(AxisSize, UI_Size) \
/* ------------------------------------------- */
#define UI_StyleKindsXMacro(X) \
X(Flags, UI_BoxFlag) \
X(Parent, UI_Key) \
X(Tag, u64) \
X(ChildLayoutAxis, Axis) \
X(ChildAlignmentX, UI_AxisAlignment) \
X(ChildAlignmentY, UI_AxisAlignment) \
X(Width, UI_Size) \
X(Height, UI_Size) \
X(BackgroundColor, Vec4) \
X(BorderColor, Vec4) \
X(DebugColor, Vec4) \
X(Tint, Vec4) \
X(Border, f32) \
X(FloatingPos, Vec2) \
X(Rounding, UI_Round) \
X(Font, ResourceKey) \
X(FontSize, u32) \
X(Text, String) \
X(BackgroundTexture, GPU_Resource *) \
X(BackgroundTextureUv0, Vec2) \
X(BackgroundTextureUv1, Vec2) \
/* --------------------------------------- */ \
/* ----------- Virtual styles ----------- */ \
/* --------------------------------------- */ \
X(BeginVirtualStyles_, i8) \
X(ChildAlignment, UI_Alignment) \
X(AxisSize, UI_Size) \
/* -------------------------------------------------- */
Enum(UI_StyleKind)
{
@ -189,29 +192,15 @@ Struct(UI_Report)
};
////////////////////////////////////////////////////////////
//~ Box types
//~ Command types
Struct(UI_Box)
Struct(UI_Cmd)
{
//- Hash list
UI_Box *next_in_bin;
UI_Box *prev_in_bin;
//- Tree
UI_Box *parent;
UI_Box *first;
UI_Box *last;
UI_Box *next;
UI_Box *prev;
u64 count;
//- Persistent data
UI_Key key;
UI_Report report;
//- Per-build data
UI_BoxFlag flags;
UI_Key key;
UI_Key parent;
GPU_Resource *background_texture;
Vec2 background_texture_uv0;
Vec2 background_texture_uv1;
@ -229,6 +218,37 @@ Struct(UI_Box)
f32 font_size;
Axis child_layout_axis;
UI_AxisAlignment child_alignment[Axis_CountXY];
};
Struct(UI_CmdNode)
{
UI_CmdNode *next;
UI_Cmd cmd;
};
////////////////////////////////////////////////////////////
//~ Box types
Struct(UI_Box)
{
UI_Key key;
//- Persistent data
UI_Box *next_in_bin;
UI_Box *prev_in_bin;
UI_Report report;
u64 last_updated_tick;
//- Tree links
UI_Box *parent;
UI_Box *first;
UI_Box *last;
UI_Box *next;
UI_Box *prev;
u64 count;
//- Cmd data
UI_Cmd cmd;
//- Pre-layout data
u64 pre_index;
@ -241,7 +261,7 @@ Struct(UI_Box)
f32 solved_dims[Axis_CountXY];
f32 final_children_size_accum[Axis_CountXY];
//- Post-layout data
//- Layout results
Vec2 p0;
Vec2 p1;
f32 rounding_tl;
@ -277,47 +297,71 @@ Struct(UI_Frame)
#define UI_NumBoxLookupBins 16384
Struct(UI_SharedState)
Struct(UI_BFrameState);
Struct(UI_EFrameState);
Struct(UI_State)
{
//- Control state
i64 last_frame_begin_ns;
//////////////////////////////
//- Persistent sate
Arena *box_arena;
UI_BoxBin *box_bins;
u64 boxes_count;
UI_Box *first_free_box;
//////////////////////////////
//- Frame-begin state
struct UI_BFrameState
{
Arena *cmds_arena;
WND_Frame window_frame;
u64 transient_key_seed;
/* Time */
u64 tick;
i64 time_ns;
i64 dt_ns;
/* Control */
Vec2 cursor_pos;
UI_Key hovered_box;
UI_Key active_box;
//- Build state
Arena *build_arena;
Arena *back_build_arena;
/* Cmds */
UI_FrameFlag frame_flags;
UI_FrameFlag back_frame_flags;
UI_BoxBin *box_bins;
UI_BoxBin *back_box_bins;
UI_Box *root_box;
UI_Box *back_root_box;
u64 boxes_count;
u64 back_boxes_count;
UI_CmdNode *first_cmd_node;
UI_CmdNode *last_cmd_node;
u64 cmds_count;
/* Style stack */
UI_Stack *top_stack;
UI_StyleNode *first_free_style_node;
} bframe;
//- Layout state
UI_Box **boxes_pre;
UI_Box **boxes_post;
UI_Box **back_boxes_pre;
UI_Box **back_boxes_post;
//////////////////////////////
//- Frame-end state
//- Render state
struct UI_EFrameState
{
Arena *layout_arena;
Arena *rects_arena;
u64 tick;
/* Render */
GPU_Resource *render_target;
GPU_Swapchain *swapchain;
i64 gpu_submit_fence_target;
GPU_TransientBuffer draw_rects_tbuff;
Arena *draw_rects_arena;
} extern UI_shared_state;
/* Layout */
UI_Box *root_box;
UI_Box **boxes_pre;
UI_Box **boxes_post;
} eframe;
} extern UI_state;
////////////////////////////////////////////////////////////
//~ Startup
@ -336,8 +380,9 @@ UI_Key UI_KeyFromString(String str);
UI_Key UI_KeyF_(String fmt, ...);
#define UI_KeyF(fmt_cstr, ...) UI_KeyF_(StringFromCstrNoLimit(fmt_cstr), __VA_ARGS__, FmtEnd)
UI_Box *UI_BackBoxFromKey(UI_Key key);
UI_Box *UI_FrontBoxFromKey(UI_Key key);
UI_Key UI_TransKey(void);
UI_Box *UI_BoxFromKey(UI_Key key);
////////////////////////////////////////////////////////////
//~ String helpers
@ -348,7 +393,7 @@ String UI_StringF_(String fmt, ...);
////////////////////////////////////////////////////////////
//~ Checkpoint helpers
UI_Checkpoint UI_PushCP(UI_Box *parent);
UI_Checkpoint UI_PushCP(UI_Key parent);
void UI_PopCP(UI_Checkpoint pop_to);
UI_Checkpoint UI_TopCP(void);
@ -397,12 +442,10 @@ UI_Style UI_PopStyle(UI_StyleDesc desc);
#define UI_RGROW(_v) UI_ROUND(UI_RoundKind_Fill, (_v))
////////////////////////////////////////////////////////////
//~ Box
//~ Command helpers
UI_Box *UI_BuildBox(UI_Key key);
void UI_SetBackgroundTexture(UI_Box *box, GPU_Resource *texture, Vec2 uv0, Vec2 uv1);
b32 UI_IsPointInBox(UI_Box *box, Vec2 point);
UI_Key UI_BuildBoxEx(UI_Key key);
#define UI_BuildBox() UI_BuildBoxEx(UI_TransKey())
////////////////////////////////////////////////////////////
//~ Report
@ -417,8 +460,8 @@ UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags);
////////////////////////////////////////////////////////////
//~ Frame helpers
Arena *UI_GetFrameArena(void);
Vec2 UI_GetCursorPos(void);
Arena *UI_FrameArena(void);
Vec2 UI_CursorPos(void);
////////////////////////////////////////////////////////////
//~ End frame