working tweak vars

This commit is contained in:
jacob 2025-12-29 22:53:04 -06:00
parent 4f00af6044
commit e8b5edb371
9 changed files with 438 additions and 317 deletions

View File

@ -431,7 +431,7 @@
#define IsFixedArray(a) (IsIndexable(a) && (((void *)&a) == ((void *)a))) #define IsFixedArray(a) (IsIndexable(a) && (((void *)&a) == ((void *)a)))
//- offsetof //- offsetof
#if !IsCompilerMsvc #if IsCompilerMsvc
#ifdef _CRT_USE_BUILTIN_OFFSETOF #ifdef _CRT_USE_BUILTIN_OFFSETOF
#define offsetof(type, field) __builtin_offsetof(type, field) #define offsetof(type, field) __builtin_offsetof(type, field)
#else #else

View File

@ -3,11 +3,11 @@
Struct(BaseCtx) Struct(BaseCtx)
{ {
TweakVarsCtx tweak;
CmdLineCtx cmdline; CmdLineCtx cmdline;
ResourceCtx resource; ResourceCtx resource;
GstatCtx gstat; GstatCtx gstat;
AsyncCtx async; AsyncCtx async;
TweakVarsCtx tweak;
}; };
extern BaseCtx Base; extern BaseCtx Base;

View File

@ -1,39 +1,81 @@
////////////////////////////////////////////////////////////
//~ Bootstrap
void BootstrapTweakVars(void)
{
// TODO: Swap in/out for persistence
#define X(name, type, default_value) Base.tweak.shared_vars.##name = default_value;
TweakVarsXMacro(X);
#undef X
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Tweak var get/set //~ Tweak var get/set
//- Auto-generated functions //- Auto-generated functions
#define X(name, type, default_value) \ #define X(name, type, default_value) \
type GetTweak_##name(void) \ type GetGlobalTweakVar_TweakVarKind_##name(void) \
{ \ { \
type result = Zi; \ type result = Zi; \
LockTicketMutex(&Base.tweak.mutex); \ LockTicketMutex(&Base.tweak.tm); \
{ \ { \
result = Base.tweak.shared_vars.##name; \ result = Base.tweak.shared_vars.##name; \
} \ } \
UnlockTicketMutex(&Base.tweak.mutex); \ UnlockTicketMutex(&Base.tweak.tm); \
return result; \ return result; \
} \ } \
void SetTweak_##name(type v) \ void SetGlobalTweakVar_TweakVarKind_##name(type v) \
{ \ { \
LockTicketMutex(&Base.tweak.mutex); \ LockTicketMutex(&Base.tweak.tm); \
{ \ { \
Base.tweak.shared_vars.name = v; \ Base.tweak.shared_vars.name = v; \
} \ } \
UnlockTicketMutex(&Base.tweak.mutex); \ UnlockTicketMutex(&Base.tweak.tm); \
} }
TweakVarsXMacro(X); TweakVarsXMacro(X);
#undef X #undef X
//- Helpers //- Helpers
TweakVars GetAllTweakVars(void) TweakVarDesc TweakVarDescFromKind(TweakVarKind kind)
{
Readonly PERSIST TweakVarDesc descs[TweakVarKind_COUNT] = {
#define X(_name, _type, _default_value) \
{ \
.name = CompLit(#_name), \
.type = TweakVarType_##_type, \
.offset = offsetof(TweakVars, _name), \
.default_##_type = (_default_value), \
},
TweakVarsXMacro(X)
#undef X
};
TweakVarDesc result = Zi;
if (kind >= 0 && kind < countof(descs))
{
result = descs[kind];
}
return result;
}
TweakVars GetAllGlobalTweakVars(void)
{ {
TweakVars result; TweakVars result;
LockTicketMutex(&Base.tweak.mutex); LockTicketMutex(&Base.tweak.tm);
{ {
result = Base.tweak.shared_vars; result = Base.tweak.shared_vars;
} }
UnlockTicketMutex(&Base.tweak.mutex); UnlockTicketMutex(&Base.tweak.tm);
return result; return result;
} }
void SetAllGlobalTweakVars(TweakVars *v)
{
LockTicketMutex(&Base.tweak.tm);
{
CopyStruct(&Base.tweak.shared_vars, v);
}
UnlockTicketMutex(&Base.tweak.tm);
}

View File

@ -22,22 +22,43 @@ Struct(TweakVars)
i32 __; // Prevent empty struct i32 __; // Prevent empty struct
}; };
Struct(TweakVarDesc)
{
String name;
TweakVarType type;
i32 offset;
union
{
b32 default_b32;
};
};
////////////////////////////////////////////////////////////
//~ State types
Struct(TweakVarsCtx) Struct(TweakVarsCtx)
{ {
TicketMutex mutex; TicketMutex tm;
TweakVars shared_vars; TweakVars shared_vars;
}; };
////////////////////////////////////////////////////////////
//~ Bootstrap
void BootstrapTweakVars(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Tweak var operations //~ Tweak var operations
//- Auto-generated functions //- Auto-generated functions
#define X(name, type, ...) \ #define X(name, type, ...) \
type GetTweak_##name(void); \ type GetGlobalTweakVar_##name(void); \
void SetTweak_##name(type v); void SetGlobalTweakVar_##name(type v);
#undef X #undef X
//- Helpers //- Helpers
TweakVars GetAllTweakVars(void); TweakVarDesc TweakVarDescFromKind(TweakVarKind kind);
#define GetTweak(name) GetTweak_##name() TweakVars GetAllGlobalTweakVars(void);
#define SetTweak(name, v) SetTweak_##name((v)) void SetAllGlobalTweakVars(TweakVars *v);
#define GetGlobalTweakVar(name) GetGlobalTweakVar_TweakVarKind_##name()
#define SetGlobalTweakVar(name, v) SetGlobalTweakVar_TweakVarKind_##name((v))

View File

@ -451,6 +451,9 @@ i32 W32_Main(void)
////////////////////////////// //////////////////////////////
//- Bootstrap //- Bootstrap
// Bootstrap tweak vars
BootstrapTweakVars();
// Bootstrap command line // Bootstrap command line
BootstrapCmdline(); BootstrapCmdline();

View File

@ -2,7 +2,7 @@
//~ Debug tweak vars //~ Debug tweak vars
#define TweakVarsXMacro(X) \ #define TweakVarsXMacro(X) \
X(CeilGlyphAdvances, b32, 1) \ X(CeilGlyphAdvances, b32, 0) \
/* --------------------------------- */ /* --------------------------------- */
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -180,7 +180,7 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size
GC_RunRect *rect = &result.rects[glyph_idx]; GC_RunRect *rect = &result.rects[glyph_idx];
f32 advance = 0; f32 advance = 0;
if (GetTweak(CeilGlyphAdvances)) if (GetGlobalTweakVar(CeilGlyphAdvances))
{ {
advance = CeilF32(glyph->advance * scale); advance = CeilF32(glyph->advance * scale);
} }

View File

@ -28,6 +28,19 @@ V_Frame *V_LastFrame(void)
return &V.frames[(V.current_frame_tick - 1) % countof(V.frames)]; return &V.frames[(V.current_frame_tick - 1) % countof(V.frames)];
} }
V_Cmd *V_PushVisCmd(String name)
{
V_Frame *frame = V_CurrentFrame();
V_CmdNode *cmd_node = PushStruct(frame->arena, V_CmdNode);
V_Cmd *cmd = &cmd_node->cmd;
{
cmd->name = name;
}
++frame->cmds_count;
SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, cmd_node);
return cmd;
}
S_Cmd *V_PushSimCmd(S_CmdKind kind) S_Cmd *V_PushSimCmd(S_CmdKind kind)
{ {
V_Frame *frame = V_CurrentFrame(); V_Frame *frame = V_CurrentFrame();
@ -87,6 +100,9 @@ V_WidgetTheme V_GetWidgetTheme(void)
theme.button_hot_color = Rgb32(0x103c4c); theme.button_hot_color = Rgb32(0x103c4c);
theme.button_selected_color = Rgb32(0x00668D); theme.button_selected_color = Rgb32(0x00668D);
theme.color_positive = VEC4(0.25, 0.5, 0.25, 1);
theme.color_negative = VEC4(0.5, 0.25, 0.25, 1);
theme.window_title_font_size = 16; theme.window_title_font_size = 16;
theme.text_padding_x = 5; theme.text_padding_x = 5;
theme.text_padding_y = 5; theme.text_padding_y = 5;
@ -100,227 +116,6 @@ void V_PushWidgetThemeStyles(V_WidgetTheme theme)
UI_Push(FontSize, theme.font_size); UI_Push(FontSize, theme.font_size);
} }
////////////////////////////////////////////////////////////
//~ Palette
void V_BeginPalette(V_Palette *widget)
{
ZeroStruct(&widget->build);
widget->build.cp = UI_PushCP(UI_NilKey);
widget->key = UI_KeyF("commands palette");
UI_Push(Tag, widget->key.hash);
}
V_PaletteItemReport V_PushPaletteItem(V_Palette *widget, V_PaletteItemDesc desc)
{
Arena *frame_arena = UI_FrameArena();
UI_Key key = UI_KeyF("btn%F", FmtSint(widget->build.num_items));
{
V_PaletteItem *item = PushStruct(frame_arena, V_PaletteItem);
item->key = key;
item->desc = desc;
SllQueuePush(widget->build.first_item, widget->build.last_item, item);
++widget->build.num_items;
}
V_PaletteItemReport result = Zi;
UI_Report rep = UI_ReportFromKey(key);
result.ui_report = rep;
result.pressed = rep.m1.presses > 0;
CopyStructs(result.new_hotkeys, desc.hotkeys, MinU32(countof(result.new_hotkeys), countof(desc.hotkeys)));
return result;
}
void V_EndPalette(V_Palette *widget)
{
V_Frame *frame = V_CurrentFrame();
V_WidgetTheme theme = V_GetWidgetTheme();
Vec2 cursor_pos = UI_CursorPos();
UI_Key titlebar_key = UI_KeyF("title bar");
UI_Report titlebar_rep = UI_ReportFromKey(titlebar_key);
UI_Report widget_rep = UI_ReportFromKey(widget->key);
Vec2 widget_half_dims = MulVec2(DimsFromRng2(widget_rep.screen_rect), 0.5);
Vec4 window_background_color = theme.window_background_color;
// Vec4 window_background_color = VEC4(0, 0, 0, 0);
Vec4 window_border_color = theme.window_border_color;
Vec4 titlebar_color = Zi;
Vec4 titlebar_border_color = Zi;
Vec4 divider_color = theme.divider_color;
if (titlebar_rep.m1.held)
{
widget->pos = AddVec2(SubVec2(cursor_pos, titlebar_rep.last_mouse_down_cursor_offset), widget_half_dims);
}
window_border_color = LerpSrgb(window_border_color, Rgb32(0x0078a6), titlebar_rep.hot);
UI_Push(Scale, LerpF32(0.75, 1, widget_rep.selected));
UI_Push(Tint, VEC4(1, 1, 1, widget_rep.selected));
if (widget_rep.selected < 0.25)
{
UI_Push(OmitFlags, UI_UseTop(OmitFlags) | UI_BoxFlag_Interactable);
}
UI_Push(BackgroundColor, window_background_color);
UI_Push(BorderColor, window_border_color);
UI_Push(Border, theme.window_border);
UI_Push(Rounding, UI_RPIX(15));
UI_Push(Width, UI_PIX(theme.window_width, 0));
UI_Push(Height, UI_SHRINK(0, 0));
UI_Push(ChildLayoutAxis, Axis_Y);
UI_Push(FloatingPos, SubVec2(widget->pos, widget_half_dims));
UI_SetNext(Flags, UI_BoxFlag_Floating | (UI_BoxFlag_Selected * frame->show_palette));
UI_PushCP(UI_BuildBoxEx(widget->key));
{
// Title bar
UI_PushCP(UI_NilKey);
{
UI_Push(BackgroundColor, titlebar_color);
UI_Push(BorderColor, titlebar_border_color);
UI_Push(Rounding, UI_RPIX(0));
UI_Push(ChildLayoutAxis, Axis_X);
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_BuildBoxEx(titlebar_key));
{
UI_Push(Width, UI_GROW(1, 0));
UI_Push(BorderColor, 0);
// Left title box
UI_BuildRow();
// Title box
UI_SetNext(FontSize, theme.window_title_font_size);
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Width, UI_SHRINK(0, 1));
UI_SetNext(Text, Lit("Command Palette"));
UI_SetNext(Flags, UI_BoxFlag_DrawText);
UI_BuildBox();
// Right title box
UI_BuildRow();
}
UI_PopCP(UI_TopCP());
}
UI_PopCP(UI_TopCP());
}
f32 padding = theme.window_border;
UI_SetNext(Tint, 0);
UI_SetNext(Rounding, 0);
UI_PushCP(UI_BuildRow());
{
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());
{
for (V_PaletteItem *item = widget->build.first_item; item; item = item->next)
{
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);
Vec4 btn_color = theme.window_background_color;
btn_color = LerpSrgb(btn_color, theme.button_hot_color, btn_rep.hot);
btn_color = LerpSrgb(btn_color, theme.button_active_color, btn_rep.active);
Vec4 btn_border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.button_active_color, btn_rep.hot);
UI_SetNext(Rounding, 0);
UI_SetNext(Tint, 0);
UI_PushCP(UI_BuildRow());
{
UI_SetNext(BorderColor, btn_border_color);
UI_SetNext(BackgroundColor, btn_color);
UI_SetNext(Rounding, UI_RPIX(5));
UI_SetNext(Width, UI_GROW(1, 0));
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_BuildRowEx(btn_key));
{
UI_Push(Tag, btn_key.hash);
// Begin spacer
UI_BuildSpacer(UI_PIX(20, 1), Axis_X);
// Command label
// UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(ChildAlignment, UI_Alignment_Left);
UI_BuildLabel(item->desc.display_name);
// Middle spacer
UI_BuildSpacer(UI_GROW(1, 0), Axis_X);
// Command hotkey buttons
for (u64 i = 0; i < countof(item->desc.hotkeys); ++i)
{
UI_Key hotkey_key = UI_KeyF("hotkey%F", FmtUint(i));
UI_Report hotkey_rep = UI_ReportFromKey(hotkey_key);
Vec4 hotkey_color = Zi;
Vec4 hotkey_border_color = Zi;
{
Vec4 hovered_color = Rgb32(0x103c4c);
Vec4 pressed_color = hovered_color;
pressed_color.w = 0.2;
f32 hotkey_hot = hotkey_rep.hot;
f32 hotkey_active = hotkey_rep.active;
f32 hotkey_hovered = hotkey_rep.hovered;
hotkey_color = LerpSrgb(hotkey_color, hovered_color, hotkey_hot);
hotkey_color = LerpSrgb(hotkey_color, pressed_color, hotkey_active * hotkey_hovered);
hotkey_border_color = LerpSrgb(hotkey_border_color, Rgb32(0x0078a6), hotkey_hot);
}
V_Hotkey hotkey = item->desc.hotkeys[i];
if (hotkey.button == Button_None)
{
break;
}
else
{
UI_BuildSpacer(UI_PIX(10, 1), Axis_X);
String hotkey_name = V_StringFromHotkey(UI_FrameArena(), hotkey);
UI_SetNext(BackgroundColor, hotkey_color);
UI_SetNext(BorderColor, hotkey_border_color);
UI_SetNext(Text, hotkey_name);
UI_SetNext(Width, UI_SHRINK(theme.text_padding_x, 1));
UI_SetNext(Height, UI_GROW(1, 0));
UI_SetNext(Rounding, UI_RPIX(5));
UI_SetNext(Border, 1);
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_PushCP(UI_BuildRowEx(hotkey_key));
{
}
UI_PopCP(UI_TopCP());
}
}
// End spacer
UI_BuildSpacer(UI_PIX(20, 1), Axis_X);
}
UI_PopCP(UI_TopCP());
}
UI_PopCP(UI_TopCP());
}
}
UI_PopCP(UI_TopCP());
}
UI_BuildSpacer(UI_PIX(padding, 1), Axis_X);
}
UI_PopCP(UI_TopCP());
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
UI_PopCP(widget->build.cp);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Vis tick //~ Vis tick
@ -610,10 +405,6 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Process controller events into vis cmds //- Process controller events into vis cmds
u64 cmds_count = 0;
V_CmdNode *first_cmd_node = 0;
V_CmdNode *last_cmd_node = 0;
b32 has_mouse_focus = UI_IsKeyNil(ui_frame->hot_box) || UI_MatchKey(ui_frame->hot_box, vis_box); b32 has_mouse_focus = UI_IsKeyNil(ui_frame->hot_box) || UI_MatchKey(ui_frame->hot_box, vis_box);
b32 has_keyboard_focus = 1; b32 has_keyboard_focus = 1;
if (!window_frame.has_focus) if (!window_frame.has_focus)
@ -685,10 +476,7 @@ void V_TickForever(WaveLaneCtx *lane)
} }
if (shortcut != 0 && down) if (shortcut != 0 && down)
{ {
V_CmdNode *cmd_node = PushStruct(frame->arena, V_CmdNode); V_PushVisCmd(shortcut->cmd_name);
cmd_node->cmd.name = shortcut->cmd_name;
SllQueuePush(first_cmd_node, last_cmd_node, cmd_node);
++cmds_count;
} }
} }
frame->held_buttons[hotkey.button] = down; frame->held_buttons[hotkey.button] = down;
@ -1496,30 +1284,324 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Build command palette //- Build command palette
V_Palette *palette = &frame->palette;
{ {
V_BeginPalette(&frame->palette); palette->key = UI_KeyF("command palette");
UI_Checkpoint palette_cp = UI_PushCP(UI_NilKey);
{ {
// Push cmd items to palette UI_Push(Tag, palette->key.hash);
for (u64 i = 0; i < countof(V_cmd_descs); ++i) UI_Key titlebar_key = UI_KeyF("title bar");
UI_Report titlebar_rep = UI_ReportFromKey(titlebar_key);
UI_Report widget_rep = UI_ReportFromKey(palette->key);
Vec2 widget_half_dims = MulVec2(DimsFromRng2(widget_rep.screen_rect), 0.5);
Vec4 window_background_color = theme.window_background_color;
// Vec4 window_background_color = VEC4(0, 0, 0, 0);
Vec4 window_border_color = theme.window_border_color;
Vec4 titlebar_color = Zi;
Vec4 titlebar_border_color = Zi;
Vec4 divider_color = theme.divider_color;
if (titlebar_rep.m1.held)
{ {
V_CmdDesc cmd_desc = V_cmd_descs[i]; palette->pos = AddVec2(SubVec2(frame->ui_cursor, titlebar_rep.last_mouse_down_cursor_offset), widget_half_dims);
if (!cmd_desc.flags & V_CmdDescFlag_HideFromPalette)
{
V_PaletteItemDesc item_desc = Zi;
item_desc.display_name = cmd_desc.display_name;
// FIXME: Attach active shortcuts instead of default hotkeys
CopyStructs(item_desc.hotkeys, cmd_desc.default_hotkeys, MinU32(countof(item_desc.hotkeys), countof(cmd_desc.default_hotkeys)));
if (V_PushPaletteItem(&frame->palette, item_desc).pressed > 0)
{
V_CmdNode *cmd_node = PushStruct(frame->arena, V_CmdNode);
cmd_node->cmd.name = cmd_desc.name;
SllQueuePush(first_cmd_node, last_cmd_node, cmd_node);
++cmds_count;
}
}
} }
window_border_color = LerpSrgb(window_border_color, Rgb32(0x0078a6), titlebar_rep.hot);
UI_Push(Scale, LerpF32(0.75, 1, widget_rep.selected));
UI_Push(Tint, VEC4(1, 1, 1, widget_rep.selected));
if (widget_rep.selected < 0.25)
{
UI_Push(OmitFlags, UI_UseTop(OmitFlags) | UI_BoxFlag_Interactable);
}
UI_Push(BackgroundColor, window_background_color);
UI_Push(BorderColor, window_border_color);
UI_Push(Border, theme.window_border);
UI_Push(Rounding, UI_RPIX(15));
UI_Push(Width, UI_PIX(theme.window_width, 0));
UI_Push(Height, UI_SHRINK(0, 0));
UI_Push(ChildLayoutAxis, Axis_Y);
UI_Push(FloatingPos, SubVec2(palette->pos, widget_half_dims));
UI_SetNext(Flags, UI_BoxFlag_Floating | (UI_BoxFlag_Selected * frame->show_palette));
UI_PushCP(UI_BuildBoxEx(palette->key));
{
// Title bar
UI_PushCP(UI_NilKey);
{
UI_Push(BackgroundColor, titlebar_color);
UI_Push(BorderColor, titlebar_border_color);
UI_Push(Rounding, UI_RPIX(0));
UI_Push(ChildLayoutAxis, Axis_X);
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_BuildBoxEx(titlebar_key));
{
UI_Push(Width, UI_GROW(1, 0));
UI_Push(BorderColor, 0);
// Left title box
UI_BuildRow();
// Title box
UI_SetNext(FontSize, theme.window_title_font_size);
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Width, UI_SHRINK(0, 1));
UI_SetNext(Text, Lit("Command Palette"));
UI_SetNext(Flags, UI_BoxFlag_DrawText);
UI_BuildBox();
// Right title box
UI_BuildRow();
}
UI_PopCP(UI_TopCP());
}
UI_PopCP(UI_TopCP());
}
//////////////////////////////
//- Build palette items list
f32 padding = theme.window_border;
UI_SetNext(Tint, 0);
UI_SetNext(Rounding, 0);
UI_PushCP(UI_BuildRow());
{
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());
{
Enum(PaletteItemFlag)
{
PaletteItemFlag_None = 0,
PaletteItemFlag_IsCmd = (1 << 0),
PaletteItemFlag_IsTweakVar = (2 << 0),
};
Struct(PaletteItem)
{
PaletteItem *next;
PaletteItem *prev;
UI_Key key;
PaletteItemFlag flags;
V_Hotkey hotkeys[8];
String display_name;
V_CmdDesc cmd_desc;
TweakVarDesc tweak_desc;
};
PaletteItem *first_item = 0;
PaletteItem *last_item = 0;
//////////////////////////////
//- Push command items
{
for (u64 cmd_desc_idx = 0; cmd_desc_idx < countof(V_cmd_descs); ++cmd_desc_idx)
{
V_CmdDesc cmd_desc = V_cmd_descs[cmd_desc_idx];
if (!cmd_desc.flags & V_CmdDescFlag_HideFromPalette)
{
PaletteItem *item = PushStruct(frame->arena, PaletteItem);
{
item->key = UI_KeyF("cmd palette item %F", FmtString(cmd_desc.name));
item->display_name = cmd_desc.display_name;
item->flags |= PaletteItemFlag_IsCmd;
item->cmd_desc = cmd_desc;
// FIXME: Attach active shortcuts instead of default hotkeys
CopyStructs(item->hotkeys, cmd_desc.default_hotkeys, MinU32(countof(item->hotkeys), countof(cmd_desc.default_hotkeys)));
}
DllQueuePush(first_item, last_item, item);
}
}
}
//////////////////////////////
//- Push tweak variables
{
for (TweakVarKind tweak_var_kind = 0; tweak_var_kind < TweakVarKind_COUNT; ++tweak_var_kind)
{
TweakVarDesc tweak_desc = TweakVarDescFromKind(tweak_var_kind);
PaletteItem *item = PushStruct(frame->arena, PaletteItem);
{
item->key = UI_KeyF("tweak var palette item %F", FmtString(tweak_desc.name));
item->display_name = tweak_desc.name;
item->flags |= PaletteItemFlag_IsTweakVar;
item->tweak_desc = tweak_desc;
}
DllQueuePush(first_item, last_item, item);
}
}
//////////////////////////////
//- Build items
TweakVars tweak_vars = GetAllGlobalTweakVars();
for (PaletteItem *item = first_item; item; item = item->next)
{
UI_BuildDivider(UI_PIX(1, 1), theme.divider_color, Axis_Y);
UI_Report item_rep = UI_ReportFromKey(item->key);
if (item_rep.m1.presses)
{
if (item->flags & PaletteItemFlag_IsCmd)
{
String cmd_name = item->cmd_desc.name;
V_PushVisCmd(cmd_name);
}
}
Vec4 item_color = theme.window_background_color;
item_color = LerpSrgb(item_color, theme.button_hot_color, item_rep.hot);
item_color = LerpSrgb(item_color, theme.button_active_color, item_rep.active);
Vec4 item_border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.button_active_color, item_rep.hot);
UI_SetNext(BorderColor, 0);
UI_SetNext(Rounding, UI_RPIX(0));
UI_PushCP(UI_BuildRow());
{
UI_SetNext(BorderColor, item_border_color);
UI_SetNext(BackgroundColor, item_color);
UI_SetNext(Rounding, UI_RPIX(5));
UI_SetNext(Width, UI_GROW(1, 0));
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_BuildRowEx(item->key));
{
UI_Push(Tag, item->key.hash);
// Begin spacer
UI_BuildSpacer(UI_PIX(20, 1), Axis_X);
// Command label
UI_SetNext(ChildAlignment, UI_Alignment_Left);
UI_BuildLabel(item->display_name);
// Middle spacer
UI_BuildSpacer(UI_GROW(1, 0), Axis_X);
// Tweak
if (item->flags & PaletteItemFlag_IsTweakVar)
{
TweakVarDesc tweak_desc = item->tweak_desc;
UI_Key tweak_key = UI_KeyF("tweak");
UI_Report tweak_rep = UI_ReportFromKey(tweak_key);
switch (tweak_desc.type)
{
// Tweak checkbox
case TweakVarType_b32:
{
b32 *tweak_val = (b32 *)(&tweak_vars + tweak_desc.offset);
Vec4 tweak_bg_color = Zi;
if (*tweak_val)
{
tweak_bg_color = theme.color_positive;
}
else
{
tweak_bg_color = theme.color_negative;
}
Vec4 tweak_border_color = Zi;
tweak_border_color = LerpSrgb(tweak_border_color, theme.button_hot_color, tweak_rep.hot);
tweak_border_color = LerpSrgb(tweak_border_color, theme.button_active_color, tweak_rep.active);
if (tweak_rep.m1.downs)
{
*tweak_val = !*tweak_val;
}
UI_SetNext(BackgroundColor, tweak_bg_color);
UI_SetNext(BorderColor, tweak_border_color);
UI_SetNext(Rounding, UI_RGROW(0.5));
UI_SetNext(Border, 2);
UI_SetNext(Width, UI_FNT(1.25, 1));
UI_SetNext(Height, UI_FNT(1.25, 1));
UI_SetNext(Flags, UI_BoxFlag_Interactable);
UI_PushCP(UI_BuildRowEx(tweak_key));
{
}
UI_PopCP(UI_TopCP());
} break;
}
}
// Command hotkey buttons
for (u64 i = 0; i < countof(item->hotkeys); ++i)
{
UI_Key hotkey_key = UI_KeyF("hotkey%F", FmtUint(i));
UI_Report hotkey_rep = UI_ReportFromKey(hotkey_key);
Vec4 hotkey_color = Zi;
Vec4 hotkey_border_color = Zi;
{
Vec4 hovered_color = Rgb32(0x103c4c);
Vec4 pressed_color = hovered_color;
pressed_color.w = 0.2;
f32 hotkey_hot = hotkey_rep.hot;
f32 hotkey_active = hotkey_rep.active;
f32 hotkey_hovered = hotkey_rep.hovered;
hotkey_color = LerpSrgb(hotkey_color, hovered_color, hotkey_hot);
hotkey_color = LerpSrgb(hotkey_color, pressed_color, hotkey_active * hotkey_hovered);
hotkey_border_color = LerpSrgb(hotkey_border_color, Rgb32(0x0078a6), hotkey_hot);
}
V_Hotkey hotkey = item->hotkeys[i];
if (hotkey.button == Button_None)
{
break;
}
else
{
UI_BuildSpacer(UI_PIX(10, 1), Axis_X);
String hotkey_name = V_StringFromHotkey(UI_FrameArena(), hotkey);
UI_SetNext(BackgroundColor, hotkey_color);
UI_SetNext(BorderColor, hotkey_border_color);
UI_SetNext(Text, hotkey_name);
UI_SetNext(Width, UI_SHRINK(theme.text_padding_x, 1));
UI_SetNext(Height, UI_GROW(1, 0));
UI_SetNext(Rounding, UI_RPIX(5));
UI_SetNext(Border, 1);
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_PushCP(UI_BuildRowEx(hotkey_key));
{
}
UI_PopCP(UI_TopCP());
}
}
// End spacer
UI_BuildSpacer(UI_PIX(20, 1), Axis_X);
}
UI_PopCP(UI_TopCP());
}
UI_PopCP(UI_TopCP());
}
SetAllGlobalTweakVars(&tweak_vars);
}
UI_PopCP(UI_TopCP());
}
UI_BuildSpacer(UI_PIX(padding, 1), Axis_X);
}
UI_PopCP(UI_TopCP());
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
} }
V_EndPalette(&frame->palette); // UI_PopCP(UI_TopCP());
UI_PopCP(palette_cp);
} }
////////////////////////////// //////////////////////////////
@ -1559,6 +1641,7 @@ void V_TickForever(WaveLaneCtx *lane)
Vec2I32 tile_pos = S_TilePosFromWorldPos(frame->world_cursor); Vec2I32 tile_pos = S_TilePosFromWorldPos(frame->world_cursor);
i32 tile_idx = S_TileIdxFromTilePos(tile_pos); i32 tile_idx = S_TileIdxFromTilePos(tile_pos);
{ {
UI_BuildLabelF("Camera pos: %F", FmtFloat2(frame->camera_pos));
UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor)); UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor));
UI_BuildLabelF("Cursor tile pos: %F", FmtSint2(tile_pos)); UI_BuildLabelF("Cursor tile pos: %F", FmtSint2(tile_pos));
UI_BuildLabelF("Cursor tile idx: %F", FmtSint(tile_idx)); UI_BuildLabelF("Cursor tile idx: %F", FmtSint(tile_idx));
@ -1740,7 +1823,7 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Process vis commands //- Process vis commands
for (V_CmdNode *cmd_node = first_cmd_node; cmd_node; cmd_node = cmd_node->next) for (V_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
{ {
String cmd_name = cmd_node->cmd.name; String cmd_name = cmd_node->cmd.name;
V_CmdKind kind = V_CmdKind_nop; V_CmdKind kind = V_CmdKind_nop;

View File

@ -36,6 +36,9 @@ Struct(V_WidgetTheme)
Vec4 button_active_color; Vec4 button_active_color;
Vec4 button_selected_color; Vec4 button_selected_color;
Vec4 color_positive;
Vec4 color_negative;
f32 text_padding_x; f32 text_padding_x;
f32 text_padding_y; f32 text_padding_y;
}; };
@ -112,41 +115,11 @@ Global Readonly V_CmdDesc V_cmd_descs[V_CmdKind_COUNT] = {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Palette types //~ Palette types
Struct(V_PaletteItemReport)
{
b32 pressed;
b32 hotkey_changed;
UI_Report ui_report;
V_Hotkey new_hotkeys[8];
};
Struct(V_PaletteItemDesc)
{
String display_name;
V_Hotkey hotkeys[8];
};
Struct(V_PaletteItem)
{
V_PaletteItem *next;
UI_Key key;
V_PaletteItemDesc desc;
};
Struct(V_Palette) Struct(V_Palette)
{ {
// Persistent state // Persistent state
Vec2 pos; Vec2 pos;
UI_Key key; UI_Key key;
// Per-build state
struct
{
UI_Checkpoint cp;
V_PaletteItem *first_item;
V_PaletteItem *last_item;
u64 num_items;
} build;
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -264,6 +237,11 @@ Struct(V_Frame)
Rng2 draw_selection; Rng2 draw_selection;
Rng2 world_selection; Rng2 world_selection;
// Commands
i64 cmds_count;
V_CmdNode *first_cmd_node;
V_CmdNode *last_cmd_node;
// Control // Control
Vec2 move; Vec2 move;
Vec2 look; Vec2 look;
@ -306,6 +284,7 @@ void V_Shutdown(void);
V_Frame *V_CurrentFrame(void); V_Frame *V_CurrentFrame(void);
V_Frame *V_LastFrame(void); V_Frame *V_LastFrame(void);
V_Cmd *V_PushVisCmd(String name);
S_Cmd *V_PushSimCmd(S_CmdKind kind); S_Cmd *V_PushSimCmd(S_CmdKind kind);
String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey); String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey);
@ -315,13 +294,6 @@ String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey);
V_WidgetTheme V_GetWidgetTheme(void); V_WidgetTheme V_GetWidgetTheme(void);
void V_PushWidgetThemeStyles(V_WidgetTheme theme); void V_PushWidgetThemeStyles(V_WidgetTheme theme);
////////////////////////////////////////////////////////////
//~ Palette
void V_BeginPalette(V_Palette *widget);
V_PaletteItemReport V_PushPaletteItem(V_Palette *widget, V_PaletteItemDesc desc);
void V_EndPalette(V_Palette *widget);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Vis tick //~ Vis tick