explicit checkpoint push/pop

This commit is contained in:
jacob 2025-11-07 17:10:10 -06:00
parent 54861e0935
commit 9c8f585bf4
6 changed files with 106 additions and 170 deletions

View File

@ -111,7 +111,7 @@ JobDef(PP_VisWorker, sig, job_id)
Struct(VisPersist)
{
PP_ListerWidget lister;
PP_CommandsWidget commands_widget;
b32 ui_debug;
};
VisPersist persist = ZI;
@ -173,36 +173,36 @@ JobDef(PP_VisWorker, sig, job_id)
{
b32 minimized = 1;
PP_BuildDebugConsoleWidget(minimized);
PP_BuildConsoleWidget(minimized);
}
//////////////////////////////
//- Build lister
//- Build commands widget
PP_BeginListerWidget(&persist.lister);
PP_BeginCommandsWidget(&persist.commands_widget);
{
if (PP_BuildListerButton(&persist.lister, Lit("Debug UI")).m1_presses > 0)
if (PP_PushItemToCommandsWidget(&persist.commands_widget, Lit("Debug UI")).m1_presses > 0)
{
persist.ui_debug = !persist.ui_debug;
}
if (PP_BuildListerButton(&persist.lister, Lit("Fullscreen")).m1_presses > 0)
if (PP_PushItemToCommandsWidget(&persist.commands_widget, Lit("Fullscreen")).m1_presses > 0)
{
b32 new = !window_frame.fullscreen;
WND_PushCmd(window_frame, .kind = WND_CmdKind_SetFullscreen, .v = new);
LogInfoF("Toggled fullscreen: %F", FmtSint(new));
}
if (PP_BuildListerButton(&persist.lister, Lit("Topmost")).m1_presses > 0)
if (PP_PushItemToCommandsWidget(&persist.commands_widget, Lit("Topmost")).m1_presses > 0)
{
b32 new = !window_frame.forced_top;
WND_PushCmd(window_frame, .kind = WND_CmdKind_SetForcedTop, .v = new);
LogInfoF("Toggled topmost: %F", FmtSint(new));
}
if (PP_BuildListerButton(&persist.lister, Lit("Spawn")).m1_presses > 0)
if (PP_PushItemToCommandsWidget(&persist.commands_widget, Lit("Spawn")).m1_presses > 0)
{
LogErrorF("RAAAAH");
}
}
PP_EndListerWidget(&persist.lister);
PP_EndCommandsWidget(&persist.commands_widget);
//////////////////////////////
//- Submit sim commands

View File

@ -23,17 +23,19 @@ void PP_PushWidgetThemeStyles(PP_WidgetTheme theme)
}
////////////////////////////////////////////////////////////
//~ Lister widgets
//~ Commands widget
void PP_BeginListerWidget(PP_ListerWidget *lister)
void PP_BeginCommandsWidget(PP_CommandsWidget *widget)
{
widget->window_cp = UI_PushCP(0);
PP_WidgetTheme theme = PP_GetWidgetTheme();
Vec2 cursor_pos = UI_GetCursorPos();
lister->num_buttons = 0;
widget->num_items = 0;
UI_Push(Tag, HashF("commands widget"));
UI_Push(Tag, HashF("lister"));
UI_Key titlebar_key = UI_KeyF("lister title bar");
UI_Key titlebar_key = UI_KeyF("title bar");
Vec4 window_background_color = theme.window_background_color;
Vec4 window_border_color = theme.window_border_color;
@ -44,7 +46,7 @@ void PP_BeginListerWidget(PP_ListerWidget *lister)
UI_Report rep = UI_ReportFromKey(titlebar_key);
if (rep.m1_held)
{
lister->pos = SubVec2(cursor_pos, rep.last_m1_offset);
widget->pos = SubVec2(cursor_pos, rep.last_m1_offset);
}
window_border_color = BlendSrgb(window_border_color, Rgb(0.5, 0.5, 0.5), rep.hot);
}
@ -57,9 +59,9 @@ void PP_BeginListerWidget(PP_ListerWidget *lister)
UI_Push(Width, UI_PIX(theme.window_width, 0));
UI_Push(Height, UI_FIT(0));
UI_Push(ChildLayoutAxis, Axis_Y);
UI_Push(FloatingPos, lister->pos);
UI_Push(FloatingPos, widget->pos);
UI_SetNext(Flags, UI_BoxFlag_Floating);
UI_PushCP(UI_BuildBox(UI_KeyF("lister")));
UI_PushCP(UI_BuildBox(UI_KeyF("titlebar")));
{
/* Title bar */
UI_PushCP(0);
@ -83,16 +85,16 @@ void PP_BeginListerWidget(PP_ListerWidget *lister)
UI_SetNext(FontSize, theme.window_title_font_size);
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Width, UI_FIT(1));
UI_SetNext(Text, Lit("Lister"));
UI_SetNext(Text, Lit("Commands"));
UI_SetNext(Flags, UI_BoxFlag_DrawText);
UI_BuildBox(UI_NilKey);
/* Right title box */
UI_BuildRow(UI_NilKey);
}
UI_PopCP();
UI_PopCP(UI_TopCP());
}
UI_PopCP();
UI_PopCP(UI_TopCP());
}
UI_SetNext(Tint, 0);
@ -110,12 +112,12 @@ void PP_BeginListerWidget(PP_ListerWidget *lister)
}
}
UI_Report PP_BuildListerButton(PP_ListerWidget *lister, String text)
UI_Report PP_PushItemToCommandsWidget(PP_CommandsWidget *widget, String text)
{
PP_WidgetTheme theme = PP_GetWidgetTheme();
UI_BuildDivider(UI_PIX(1, 1), theme.divider_color);
UI_Key btn_key = UI_KeyF("btn%F", FmtSint(lister->num_buttons));
UI_Key btn_key = UI_KeyF("btn%F", FmtSint(widget->num_items));
UI_Report rep = UI_ReportFromKey(btn_key);
Vec4 hovered_color = Rgb32(0x103c4c);
@ -149,30 +151,29 @@ UI_Report PP_BuildListerButton(PP_ListerWidget *lister, String text)
UI_BuildSpacer(UI_PIX(20, 1));
UI_BuildLabel(text);
}
UI_PopCP();
UI_PopCP(UI_TopCP());
}
UI_PopCP();
UI_PopCP(UI_TopCP());
++lister->num_buttons;
++widget->num_items;
return rep;
}
void PP_EndListerWidget(PP_ListerWidget *lister)
void PP_EndCommandsWidget(PP_CommandsWidget *widget)
{
PP_WidgetTheme theme = PP_GetWidgetTheme();
f32 padding = theme.window_border;
UI_BuildSpacer(UI_PIX(padding, 1));
UI_PopCP();
UI_PopCP(UI_TopCP());
UI_BuildSpacer(UI_PIX(padding, 1));
UI_PopCP();
UI_PopCP();
UI_PopCP(widget->window_cp);
}
////////////////////////////////////////////////////////////
//~ Debug console widgets
//~ Console widget
UI_Box *PP_BuildDebugConsoleWidget(b32 minimized)
UI_Box *PP_BuildConsoleWidget(b32 minimized)
{
/* TODO: Remove this whole thing */
__prof;
@ -300,13 +301,13 @@ UI_Box *PP_BuildDebugConsoleWidget(b32 minimized)
UI_Push(Flags, UI_BoxFlag_DrawText);
UI_BuildBox(UI_NilKey);
}
UI_PopCP();
UI_PopCP(UI_TopCP());
}
}
UI_PopCP();
UI_PopCP(UI_TopCP());
}
}
UI_PopCP();
UI_PopCP(UI_TopCP());
}
EndScratch(scratch);

View File

@ -16,15 +16,16 @@ Struct(PP_WidgetTheme)
};
////////////////////////////////////////////////////////////
//~ Lister types
//~ Commands widget types
Struct(PP_ListerWidget)
Struct(PP_CommandsWidget)
{
/* Persistent state */
Vec2 pos;
/* Per-build state */
i64 num_buttons;
UI_Checkpoint window_cp;
i64 num_items;
};
////////////////////////////////////////////////////////////
@ -34,11 +35,13 @@ PP_WidgetTheme PP_GetWidgetThemeStyles(void);
void PP_PushWidgetTheme(PP_WidgetTheme theme);
////////////////////////////////////////////////////////////
//~ Lister widgets
//~ Commands widget
/* FIXME */
void PP_BeginCommandsWidget(PP_CommandsWidget *widget);
UI_Report PP_PushItemToCommandsWidget(PP_CommandsWidget *widget, String text);
void PP_EndCommandsWidget(PP_CommandsWidget *widget);
////////////////////////////////////////////////////////////
//~ Debug console widgets
//~ Console widget
UI_Box *PP_BuildDebugConsoleWidget(b32 minimized);
UI_Box *PP_BuildConsoleWidget(b32 minimized);

View File

@ -8,10 +8,11 @@ UI_Box *UI_BuildLabel(String text)
Vec4 tint = UI_UseTop(Tint);
UI_Box *box = 0;
UI_PushEmptyStack();
UI_PushCP(0);
{
UI_PushDefaults();
UI_Push(Parent, parent);
UI_SetNext(Tint, tint);
UI_SetNext(Parent, parent);
UI_SetNext(Font, font);
UI_SetNext(FontSize, font_size);
UI_SetNext(Width, UI_FIT(0));
@ -20,7 +21,7 @@ UI_Box *UI_BuildLabel(String text)
UI_SetNext(Flags, UI_BoxFlag_DrawText);
box = UI_BuildBox(UI_NilKey);
}
UI_PopStack();
UI_PopCP(UI_TopCP());
return box;
}
@ -47,15 +48,16 @@ UI_Box *UI_BuildSpacer(UI_Size size)
UI_Box *box = 0;
UI_Box *parent = UI_UseTop(Parent);
Axis axis = parent->child_layout_axis;
UI_PushEmptyStack();
UI_PushCP(0);
{
UI_Push(Tint, 0);
UI_PushDefaults();
UI_Push(Parent, parent);
UI_Push(Tint, 0);
UI_Push(AxisSize, UI_FILL(1, 0), .axis = !axis);
UI_Push(AxisSize, size, .axis = axis);
box = UI_BuildBox(UI_NilKey);
}
UI_PopStack();
UI_PopCP(UI_TopCP());
return box;
}
@ -65,8 +67,9 @@ UI_Box *UI_BuildDivider(UI_Size size, Vec4 color)
UI_Box *parent = UI_UseTop(Parent);
Vec4 tint = UI_UseTop(Tint);
Axis axis = parent->child_layout_axis;
UI_PushEmptyStack();
UI_PushCP(0);
{
UI_PushDefaults();
UI_Push(Parent, parent);
UI_Push(Tint, tint);
UI_Push(BackgroundColor, color);
@ -74,7 +77,7 @@ UI_Box *UI_BuildDivider(UI_Size size, Vec4 color)
UI_Push(AxisSize, size, .axis = axis);
box = UI_BuildBox(UI_NilKey);
}
UI_PopStack();
UI_PopCP(UI_TopCP());
return box;
}

View File

@ -98,41 +98,26 @@ String UI_StringF_(String fmt, ...)
////////////////////////////////////////////////////////////
//~ Checkpoint helpers
UI_Box *UI_PushCP(UI_Box *parent)
UI_Checkpoint UI_PushCP(UI_Box *parent)
{
UI_SharedState *g = &UI_shared_state;
UI_Stack *stack = g->top_stack;
UI_Checkpoint *cp = g->first_free_checkpoint;
if (cp)
{
g->first_free_checkpoint = cp->next;
ZeroStruct(cp);
}
else
{
cp = PushStruct(g->build_arena, UI_Checkpoint);
}
cp->next = stack->top_checkpoint;
cp->v = stack->top_checkpoint->v + 1;
stack->top_checkpoint = cp;
stack->top_checkpoint.v += 1;
if (parent != 0)
{
UI_Push(Parent, parent);
}
return parent;
return stack->top_checkpoint;
}
void UI_PopCP(void)
void UI_PopCP(UI_Checkpoint cp)
{
UI_SharedState *g = &UI_shared_state;
UI_Stack *stack = g->top_stack;
UI_Checkpoint *cp = stack->top_checkpoint;
u64 v = cp->v;
/* Pop styles */
for (UI_StyleKind kind = UI_StyleKind_None; kind < UI_StyleKind_Count; ++kind)
{
UI_StyleNode *n = stack->style_tops[kind];
while (n && n->checkpoint >= v)
while (n && n->checkpoint.v >= cp.v)
{
UI_StyleNode *next = n->next;
n->next = g->first_free_style_node;
@ -141,98 +126,44 @@ void UI_PopCP(void)
n = next;
}
}
stack->top_checkpoint = cp->next;
cp->next = g->first_free_checkpoint;
g->first_free_checkpoint = cp;
stack->top_checkpoint.v = cp.v - 1;
}
UI_Checkpoint UI_TopCP(void)
{
UI_SharedState *g = &UI_shared_state;
UI_Stack *stack = g->top_stack;
return stack->top_checkpoint;
}
////////////////////////////////////////////////////////////
//~ Style stack helpers
void UI_PushEmptyStack(void)
{
UI_SharedState *g = &UI_shared_state;
UI_Stack *stack = PushStruct(g->build_arena, UI_Stack);
/* Init checkpoint */
{
UI_Checkpoint *cp = g->first_free_checkpoint;
if (cp)
{
g->first_free_checkpoint = cp->next;
ZeroStruct(cp);
}
else
{
cp = PushStruct(g->build_arena, UI_Checkpoint);
}
stack->top_checkpoint = cp;
}
/* Init styles */
{
for (UI_StyleKind kind = UI_StyleKind_None; kind < UI_StyleKind_Count; ++kind)
{
UI_StyleNode *n = g->first_free_style_node;
if (n)
{
g->first_free_style_node = n->next;
ZeroStruct(n);
}
else
{
n = PushStruct(g->build_arena, UI_StyleNode);
}
n->style.kind = kind;
stack->style_tops[kind] = n;
}
stack->style_tops[UI_StyleKind_Parent]->style.Parent = g->root_box;
stack->style_tops[UI_StyleKind_Width]->style.Width = UI_FILL(1, 0);
stack->style_tops[UI_StyleKind_Height]->style.Height = UI_FILL(1, 0);
stack->style_tops[UI_StyleKind_Font]->style.Font = UI_GetDefaultFontResource();
stack->style_tops[UI_StyleKind_FontSize]->style.FontSize = 16.0f;
stack->style_tops[UI_StyleKind_Tint]->style.Tint = Color_White;
stack->style_tops[UI_StyleKind_Tag]->style.Tag = HashFnv64(Fnv64Basis, Lit("root"));
stack->style_tops[UI_StyleKind_DebugColor]->style.DebugColor = Rgba(1, 0, 1, 0.5);
}
stack->next = g->top_stack;
g->top_stack = stack;
}
void UI_PopStack(void)
void UI_PushDefaults(void)
{
UI_SharedState *g = &UI_shared_state;
UI_Stack *stack = g->top_stack;
/* Free checkpoints */
UI_Checkpoint checkpoint = stack->top_checkpoint;
{
UI_Checkpoint *cp = stack->top_checkpoint;
while (cp)
for (UI_StyleKind kind = UI_StyleKind_None; kind < UI_StyleKind_Count; ++kind)
{
UI_Checkpoint *next = cp->next;
cp->next = g->first_free_checkpoint;
g->first_free_checkpoint = cp;
cp = next;
UI_StyleDesc desc = ZI;
desc.style.kind = kind;
switch (kind)
{
default: break;
case UI_StyleKind_Parent: { desc.style.Parent = g->root_box; } break;
case UI_StyleKind_Width: { desc.style.Width = UI_FILL(1, 0); } break;
case UI_StyleKind_Height: { desc.style.Height = UI_FILL(1, 0); } break;
case UI_StyleKind_Font: { desc.style.Font = UI_GetDefaultFontResource(); } break;
case UI_StyleKind_FontSize: { desc.style.FontSize = 16.0f; } break;
case UI_StyleKind_Tint: { desc.style.Tint = Color_White; } break;
case UI_StyleKind_Tag: { desc.style.Tag = HashFnv64(Fnv64Basis, Lit("root")); } break;
case UI_StyleKind_DebugColor: { desc.style.DebugColor = Rgba(1, 0, 1, 0.5); } break;
};
UI_PushStyle(desc);
}
}
/* Free style nodes */
for (UI_StyleKind kind = UI_StyleKind_None; kind < UI_StyleKind_Count; ++kind)
{
UI_StyleNode *n = stack->style_tops[kind];
while (n)
{
UI_StyleNode *next = n->next;
n->next = g->first_free_style_node;
g->first_free_style_node = n;
n = next;
}
}
g->top_stack = stack->next;
stack->next = g->first_free_stack;
g->first_free_stack = stack;
}
void UI_PushStyle(UI_StyleDesc desc)
@ -313,10 +244,10 @@ void UI_PushStyle(UI_StyleDesc desc)
else
{
UI_StyleNode *n = stack->style_tops[kind];
if (!n->override)
if (!(n && n->override))
{
{
if (n->pop_when_used)
if (n && n->pop_when_used)
{
UI_StyleNode *next = n->next;
ZeroStruct(n);
@ -340,7 +271,7 @@ void UI_PushStyle(UI_StyleDesc desc)
n->style = desc.style;
n->pop_when_used = desc.pop_when_used;
n->override = desc.override;
n->checkpoint = stack->top_checkpoint->v;
n->checkpoint = stack->top_checkpoint;
}
/* Initialize style data from desc */
@ -355,7 +286,10 @@ void UI_PushStyle(UI_StyleDesc desc)
case UI_StyleKind_Tag:
{
n->style.Tag = RandU64FromSeeds(n->next->style.Tag, n->style.Tag);
if (n->next != 0)
{
n->style.Tag = RandU64FromSeeds(n->next->style.Tag, n->style.Tag);
}
} break;
}
}
@ -686,8 +620,6 @@ UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags)
ResetArena(g->build_arena);
g->boxes_count = 0;
g->first_free_style_node = 0;
g->first_free_checkpoint = 0;
g->first_free_stack = 0;
g->frame_flags = frame_flags;
@ -711,7 +643,8 @@ UI_Frame UI_BeginFrame(UI_FrameFlag frame_flags)
//////////////////////////////
//- Init style stack
UI_PushEmptyStack();
g->top_stack = PushStruct(g->build_arena, UI_Stack);
UI_PushDefaults();
frame.cursor_pos = g->cursor_pos;
return frame;

View File

@ -71,7 +71,6 @@ Enum(UI_AxisAlignment)
Struct(UI_Checkpoint)
{
UI_Checkpoint *next;
u64 v;
};
@ -157,17 +156,15 @@ Struct(UI_StyleNode)
{
UI_StyleNode *next;
UI_Style style;
UI_Checkpoint checkpoint;
b32 pop_when_used;
b32 override;
u64 checkpoint;
};
Struct(UI_Stack)
{
UI_Stack *next;
UI_Checkpoint *top_checkpoint;
UI_StyleNode *style_tops[UI_StyleKind_Count];
UI_Checkpoint top_checkpoint;
};
////////////////////////////////////////////////////////////
@ -305,8 +302,6 @@ Struct(UI_SharedState)
u64 back_boxes_count;
UI_Stack *top_stack;
UI_Stack *first_free_stack;
UI_Checkpoint *first_free_checkpoint;
UI_StyleNode *first_free_style_node;
//- Layout state
@ -353,14 +348,15 @@ String UI_StringF_(String fmt, ...);
////////////////////////////////////////////////////////////
//~ Checkpoint helpers
UI_Box *UI_PushCP(UI_Box *parent);
void UI_PopCP(void);
UI_Checkpoint UI_PushCP(UI_Box *parent);
void UI_PopCP(UI_Checkpoint pop_to);
UI_Checkpoint UI_TopCP(void);
////////////////////////////////////////////////////////////
//~ Style stack helpers
void UI_PushEmptyStack(void);
void UI_PopStack(void);
void UI_PushDefaults(void);
void UI_PushStyle(UI_StyleDesc desc);
UI_Style UI_PopStyle(UI_StyleDesc desc);
@ -369,9 +365,9 @@ UI_Style UI_PopStyle(UI_StyleDesc desc);
#define UI_SetNext(name, ...) UI_PushStyle(UI_STYLEDESC(name, .pop_when_used = 1, .style.name = __VA_ARGS__))
#define UI_Push(name, ...) UI_PushStyle(UI_STYLEDESC(name, .style.name = __VA_ARGS__))
#define UI_ForceNext(name, ...) UI_PushStyle(UI_STYLEDESC(name, .pop_when_used = 1, .forced = 1, .style.name = __VA_ARGS__))
#define UI_ForcePush(name, ...) UI_PushStyle(UI_STYLEDESC(name, .forced = 1, .style.name = __VA_ARGS__))
#define UI_Pop(name, ...) UI_PopStyle(UI_STYLEDESC(name, .forced_pop = 1, __VA_ARGS__)).name
#define UI_ForceNext(name, ...) UI_PushStyle(UI_STYLEDESC(name, .pop_when_used = 1, .override = 1, .style.name = __VA_ARGS__))
#define UI_ForcePush(name, ...) UI_PushStyle(UI_STYLEDESC(name, .override = 1, .style.name = __VA_ARGS__))
#define UI_Pop(name, ...) UI_PopStyle(UI_STYLEDESC(name, .force_pop = 1, __VA_ARGS__)).name
#define UI_PeekTop(name, ...) UI_PopStyle(UI_STYLEDESC(name, __VA_ARGS__)).name
#define UI_UseTop(name, ...) UI_PopStyle(UI_STYLEDESC(name, .use = 1, __VA_ARGS__)).name