panel styling

This commit is contained in:
jacob 2025-12-28 21:57:15 -06:00
parent 6a418b8f9c
commit 10a9aa4a84
6 changed files with 185 additions and 112 deletions

View File

@ -69,11 +69,12 @@ S_Key S_RandKey(void)
String S_NameFromTileKind(S_TileKind kind) String S_NameFromTileKind(S_TileKind kind)
{ {
// Tile names array // Tile names array
#define X(name, ...) [S_TileKind_##name] = CompLit(#name), #define X(name, ...) [S_TileKind_##name] = CompLit(#name),
PERSIST Readonly String tile_names[] = { PERSIST Readonly String tile_names[] = {
S_TilesXMacro(X) S_TilesXMacro(X)
}; };
#undef X #undef X
String result = Lit("Unknown"); String result = Lit("Unknown");
if (kind >= 0 && kind < countof(tile_names)) if (kind >= 0 && kind < countof(tile_names))
{ {

View File

@ -10,13 +10,13 @@
/* -------------------- */ /* -------------------- */
// Tiles enum // Tiles enum
Enum(S_TileKind)
{
#define X(name, ...) S_TileKind_##name, #define X(name, ...) S_TileKind_##name,
Enum(S_TileKind)
{
S_TilesXMacro(X) S_TilesXMacro(X)
S_TileKind_COUNT
};
#undef X #undef X
S_TileKind_COUNT
};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Tile helpers //~ Tile helpers

View File

@ -82,6 +82,11 @@ V_WidgetTheme V_GetWidgetTheme(void)
theme.window_padding = theme.window_border - 1; theme.window_padding = theme.window_border - 1;
theme.divider_color = theme.window_border_color; theme.divider_color = theme.window_border_color;
theme.button_color = theme.window_background_color;
theme.button_active_color = Rgb32(0x0078a6);
theme.button_hot_color = Rgb32(0x103c4c);
theme.button_selected_color = Rgb32(0x00668D);
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;
@ -215,18 +220,9 @@ void V_EndCommandsWidget(V_CommandsWidget *widget)
UI_Report btn_rep = UI_ReportFromKey(btn_key); UI_Report btn_rep = UI_ReportFromKey(btn_key);
Vec4 btn_color = theme.window_background_color; Vec4 btn_color = theme.window_background_color;
Vec4 btn_border_color = Zi; btn_color = BlendSrgb(btn_color, theme.button_hot_color, btn_rep.hot);
{ btn_color = BlendSrgb(btn_color, theme.button_active_color, btn_rep.active);
Vec4 hovered_color = Rgb32(0x103c4c); Vec4 btn_border_color = BlendSrgb(VEC4(0, 0, 0, 0), theme.button_active_color, btn_rep.hot);
Vec4 pressed_color = hovered_color;
pressed_color.w = 0.2;
f32 btn_hot = btn_rep.hot;
f32 btn_active = btn_rep.active;
f32 btn_hovered = btn_rep.hovered;
btn_color = BlendSrgb(btn_color, hovered_color, btn_hot);
btn_color = BlendSrgb(btn_color, pressed_color, btn_active * btn_hovered);
btn_border_color = BlendSrgb(btn_border_color, Rgb32(0x0078a6), btn_hot);
}
UI_SetNext(Rounding, 0); UI_SetNext(Rounding, 0);
UI_SetNext(Tint, 0); UI_SetNext(Tint, 0);
@ -917,15 +913,16 @@ void V_TickForever(WaveLaneCtx *lane)
++panel->parent->count; ++panel->parent->count;
panel->pref_ratio = 0.5; panel->pref_ratio = 0.5;
panel->is_viewport_panel = 1;
{ // {
V_Window *window = PushStruct(perm, V_Window); // V_Window *window = PushStruct(perm, V_Window);
window->panel = panel; // window->panel = panel;
window->key = UI_TransKey(); // TODO: Don't use transient keys // window->key = UI_TransKey(); // TODO: Don't use transient keys
window->is_viewport_window = 1; // window->is_viewport_window = 1;
DllQueuePushNP(panel->first_window, panel->last_window, window, next_in_panel, prev_in_panel); // DllQueuePushNP(panel->first_window, panel->last_window, window, next_in_panel, prev_in_panel);
++panel->windows_count; // ++panel->windows_count;
} // }
} }
{ {
@ -1023,16 +1020,15 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Push(Tag, panel->key.hash); UI_Push(Tag, panel->key.hash);
panel_dfs->cp = UI_PushCP(panel->key); panel_dfs->cp = UI_PushCP(panel->key);
if (!panel->is_organizing_panel) if (!panel->is_organizing_panel && !panel->is_viewport_panel)
{ {
i64 new_active_window_idx = panel->active_window_idx; i64 new_active_window_idx = panel->active_window_idx;
// UI_SetNext(Width, UI_SHRINK(0, 1));
// UI_SetNext(Width, UI_GROW(1, 0));
// UI_SetNext(Height, UI_GROW(1, 0));
UI_PushCP(UI_BuildColumn()); UI_PushCP(UI_BuildColumn());
{ {
UI_Push(Tint, VEC4(1, 1, 1, 0.95));
i64 active_window_idx = ClampI64(panel->active_window_idx, 0, MaxI64(panel->windows_count - 1, 0)); i64 active_window_idx = ClampI64(panel->active_window_idx, 0, MaxI64(panel->windows_count - 1, 0));
//- Build window tabs //- Build tab row
f32 tab_spacing = 10; f32 tab_spacing = 10;
V_Window *active_window = 0; V_Window *active_window = 0;
{ {
@ -1040,37 +1036,34 @@ void V_TickForever(WaveLaneCtx *lane)
UI_SetNext(Width, UI_GROW(1, 0)); UI_SetNext(Width, UI_GROW(1, 0));
UI_SetNext(Height, UI_SHRINK(0, 1)); UI_SetNext(Height, UI_SHRINK(0, 1));
UI_PushCP(UI_BuildRow()); UI_PushCP(UI_BuildRow());
//- Build window tabs
{
for (V_Window *window = panel->first_window; window; window = window->next_in_panel) for (V_Window *window = panel->first_window; window; window = window->next_in_panel)
{ {
if (!window->is_viewport_window) UI_Push(Tag, window->key.hash);
{ {
UI_Report rep = UI_ReportFromKey(window->key); UI_Report tab_rep = UI_ReportFromKey(window->key);
if (rep.m1.downs > 0) if (tab_rep.m1.downs > 0)
{ {
new_active_window_idx = window_idx; new_active_window_idx = window_idx;
} }
Vec4 border_color = VEC4(0.5, 0.5, 0.5, 1);
if (window == panel->first_window) if (window == panel->first_window)
{ {
UI_BuildSpacer(UI_PIX(tab_spacing, 0), Axis_X); UI_BuildSpacer(UI_PIX(tab_spacing, 0), Axis_X);
} }
Vec4 bg_color = theme.window_background_color;
Vec4 border_color = theme.window_border_color;
if (window_idx == active_window_idx) if (window_idx == active_window_idx)
{ {
active_window = window; active_window = window;
border_color = VEC4(0.9, 0.5, 0.5, 1); border_color = theme.button_active_color;
} }
Vec4 hovered_color = VEC4(0.5, 0.5, 0.5, 1); bg_color = BlendSrgb(bg_color, theme.button_hot_color, tab_rep.hot);
Vec4 pressed_color = hovered_color; bg_color = BlendSrgb(bg_color, theme.button_active_color, tab_rep.active);
pressed_color.w = 0.2; border_color = BlendSrgb(border_color, theme.button_active_color, tab_rep.hot);
Vec4 bg_color = theme.window_background_color;
bg_color.x = 0.4;
bg_color = BlendSrgb(bg_color, hovered_color, rep.hot);
bg_color = BlendSrgb(bg_color, pressed_color, rep.active * rep.hovered);
String tab_name = Zi; String tab_name = Zi;
if (window->is_tile_window) if (window->is_tile_window)
@ -1085,28 +1078,87 @@ void V_TickForever(WaveLaneCtx *lane)
UI_SetNext(BackgroundColor, bg_color); UI_SetNext(BackgroundColor, bg_color);
UI_SetNext(BorderColor, border_color); UI_SetNext(BorderColor, border_color);
UI_SetNext(Border, 1); UI_SetNext(Border, 1);
UI_SetNext(Width, UI_SHRINK(3, 0)); UI_SetNext(Width, UI_SHRINK(0, 0));
UI_SetNext(Height, UI_SHRINK(1, 0)); UI_SetNext(Height, UI_SHRINK(0, 0));
UI_SetNext(ChildAlignment, UI_Alignment_Center); UI_SetNext(ChildAlignment, UI_Alignment_Left);
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable); UI_SetNext(Flags, UI_BoxFlag_Interactable);
UI_SetNext(Text, tab_name); UI_SetNext(Text, tab_name);
UI_PushCP(UI_BuildRowEx(window->key)); UI_PushCP(UI_BuildRowEx(window->key));
{ {
// Build tab title
{
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Flags, UI_BoxFlag_DrawText);
UI_SetNext(Text, tab_name);
UI_SetNext(Width, UI_SHRINK(6, 0));
UI_SetNext(Height, UI_SHRINK(2, 0));
UI_BuildRow();
}
// Build tab close button
{
UI_Key close_key = UI_KeyF("close");
UI_Report close_rep = UI_ReportFromKey(close_key);
Vec4 close_color = Zi;
close_color = BlendSrgb(close_color, theme.button_hot_color, close_rep.hot);
close_color = BlendSrgb(close_color, theme.button_active_color, close_rep.active);
Vec4 close_border_color = BlendSrgb(VEC4(0, 0, 0, 0), theme.button_active_color, close_rep.hot);
UI_SetNext(BackgroundColor, close_color);
UI_SetNext(BorderColor, close_border_color);
UI_SetNext(Border, 2);
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_SetNext(Text, Lit("x"));
UI_SetNext(Width, UI_SHRINK(6, 0));
UI_SetNext(Height, UI_SHRINK(2, 0));
UI_BuildRowEx(close_key);
}
} }
UI_PopCP(UI_TopCP()); UI_PopCP(UI_TopCP());
UI_BuildSpacer(UI_PIX(tab_spacing, 0), Axis_X);
} }
UI_Pop(Tag);
UI_BuildSpacer(UI_PIX(tab_spacing, 0), Axis_X);
window_idx += 1; window_idx += 1;
} }
}
//- Build new-tab button
{
UI_Key key = UI_KeyF("new tab");
UI_Report rep = UI_ReportFromKey(key);
Vec4 bg_color = Zi;
bg_color = BlendSrgb(bg_color, theme.button_hot_color, rep.hot);
bg_color = BlendSrgb(bg_color, theme.button_active_color, rep.active);
bg_color.w *= 0.5;
Vec4 border_color = BlendSrgb(VEC4(0, 0, 0, 0), theme.button_active_color, rep.hot);
UI_SetNext(BackgroundColor, bg_color);
UI_SetNext(BorderColor, border_color);
UI_SetNext(Border, 2);
UI_SetNext(Width, UI_SHRINK(10, 0));
UI_SetNext(Height, UI_SHRINK(2, 0));
UI_SetNext(ChildAlignment, UI_Alignment_Center);
// UI_SetNext(FontSize, theme.font_size * 1.5);
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_SetNext(Text, Lit("+"));
UI_PushCP(UI_BuildRowEx(key));
{
}
UI_PopCP(UI_TopCP());
}
UI_PopCP(UI_TopCP()); UI_PopCP(UI_TopCP());
} }
//- Build active window //- Build active window
if (active_window && !active_window->is_viewport_window) if (active_window)
{ {
Vec4 window_bg_color = theme.window_background_color;
Vec4 window_border_color = theme.window_border_color;
V_Window *window = active_window; V_Window *window = active_window;
UI_SetNext(BackgroundColor, VEC4(0, 0, 0, 0.5)); UI_SetNext(BackgroundColor, window_bg_color);
UI_SetNext(BorderColor, VEC4(0.5, 0.5, 0.5, 1)); UI_SetNext(BorderColor, window_border_color);
UI_SetNext(Border, 1); UI_SetNext(Border, 1);
UI_SetNext(Width, UI_GROW(1, 0)); UI_SetNext(Width, UI_GROW(1, 0));
UI_SetNext(Height, UI_GROW(1, 0)); UI_SetNext(Height, UI_GROW(1, 0));
@ -1127,19 +1179,31 @@ void V_TickForever(WaveLaneCtx *lane)
frame->equipped_tile = tile_kind; frame->equipped_tile = tile_kind;
} }
Vec4 hovered_color = VEC4(0.5, 0.7, 0, 0.25); Vec4 bg_color = Zi;
Vec4 bg_color = hovered_color; bg_color = BlendSrgb(bg_color, theme.button_hot_color, rep.hot);
bg_color.w *= MaxF32(rep.hot, rep.active); bg_color = BlendSrgb(bg_color, theme.button_active_color, rep.active);
Vec4 border_color = VEC4(1, 1, 0, 0.5); // Vec4 border_color = Zi;
border_color.w *= tile_kind == frame->equipped_tile; // if (tile_kind == frame->equipped_tile)
// {
// border_color = theme.button_active_color;
// border_color.w *= 0.5;
// }
// border_color = BlendSrgb(border_color, theme.button_active_color, rep.hot);
b32 is_selected = tile_kind == frame->equipped_tile;
Vec4 border_color = Zi;
border_color = BlendSrgb(border_color, theme.button_selected_color, rep.selected);
border_color = BlendSrgb(border_color, theme.button_active_color, rep.hot);
UI_SetNext(Rounding, UI_RPIX(5));
UI_SetNext(BackgroundColor, bg_color); UI_SetNext(BackgroundColor, bg_color);
UI_SetNext(BorderColor, border_color); UI_SetNext(BorderColor, border_color);
UI_SetNext(Border, 1); UI_SetNext(Border, 1);
UI_SetNext(Width, UI_GROW(1, 0)); UI_SetNext(Width, UI_GROW(1, 0));
UI_SetNext(Height, UI_SHRINK(0, 0)); UI_SetNext(Height, UI_SHRINK(0, 0));
UI_SetNext(Flags, UI_BoxFlag_Interactable); UI_SetNext(Flags, UI_BoxFlag_Interactable | (UI_BoxFlag_Selected * is_selected));
UI_PushCP(UI_BuildRowEx(key)); UI_PushCP(UI_BuildRowEx(key));
{ {
UI_SetNext(ChildAlignment, UI_Alignment_Center); UI_SetNext(ChildAlignment, UI_Alignment_Center);

View File

@ -31,6 +31,11 @@ Struct(V_WidgetTheme)
f32 window_padding; f32 window_padding;
f32 window_width; f32 window_width;
Vec4 button_color;
Vec4 button_hot_color;
Vec4 button_active_color;
Vec4 button_selected_color;
f32 text_padding_x; f32 text_padding_x;
f32 text_padding_y; f32 text_padding_y;
}; };
@ -52,10 +57,9 @@ Struct(V_Hotkey)
Enum(V_CmdKind) Enum(V_CmdKind)
{ {
#define X(name, ...) V_CmdKind_##name, #define X(name, ...) V_CmdKind_##name,
V_CmdsTableXMacro(X) V_CmdsTableXMacro(X)
#undef X #undef X
V_CmdKind_COUNT, V_CmdKind_COUNT,
}; };
@ -167,6 +171,7 @@ Struct(V_Panel)
Axis axis; Axis axis;
b32 is_organizing_panel; b32 is_organizing_panel;
b32 is_viewport_panel;
i64 active_window_idx; i64 active_window_idx;
i64 windows_count; i64 windows_count;
@ -183,7 +188,6 @@ Struct(V_Window)
UI_Key key; UI_Key key;
b32 is_tile_window; b32 is_tile_window;
b32 is_viewport_window;
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -785,13 +785,15 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color)
f32 target_hovered = report->is_hovered; f32 target_hovered = report->is_hovered;
f32 target_hot = report->is_hot; f32 target_hot = report->is_hot;
f32 target_active = box == active_box; f32 target_active = box == active_box;
f32 hot_blend_rate = target_hot == 1 ? 1 : (20 * dt); f32 target_selected = !!(box->desc.flags & UI_BoxFlag_Selected);
f32 active_blend_rate = target_active == 1 ? 1 : (20 * dt); f32 hot_blend_rate = target_hot == 1 ? 1 : (15 * dt);
f32 hovered_blend_rate = target_hovered == 1 ? 1 : (20 * dt); f32 active_blend_rate = target_active == 1 ? 1 : (15 * dt);
f32 hovered_blend_rate = target_hovered == 1 ? 1 : (15 * dt);
f32 selected_blend_rate = target_selected == 1 ? 1 : (15 * dt);
report->hot = LerpF32(report->hot, target_hot, hot_blend_rate); report->hot = LerpF32(report->hot, target_hot, hot_blend_rate);
report->active = LerpF32(report->active, target_active, active_blend_rate); report->active = LerpF32(report->active, target_active, active_blend_rate);
report->hovered = LerpF32(report->hovered, target_hovered, hovered_blend_rate); report->hovered = LerpF32(report->hovered, target_hovered, hovered_blend_rate);
report->selected = LerpF32(report->selected, target_selected, selected_blend_rate);
report->screen_rect = box->rect; report->screen_rect = box->rect;
} }
@ -1313,10 +1315,10 @@ void UI_EndFrame(UI_Frame *frame)
} }
// Submit position // Submit position
Vec2 floored_final_pos = FloorVec2(final_pos); Vec2 rounded_final_pos = RoundVec2(final_pos);
Vec2 ceiled_dims = CeilVec2(dims_vec); Vec2 rounded_dims = RoundVec2(dims_vec);
box->rect.p0 = FloorVec2(floored_final_pos); box->rect.p0 = FloorVec2(rounded_final_pos);
box->rect.p1 = AddVec2(floored_final_pos, ceiled_dims); box->rect.p1 = AddVec2(rounded_final_pos, rounded_dims);
} }
// Rounding // Rounding

View File

@ -85,6 +85,7 @@ Enum(UI_BoxFlag)
UI_BoxFlag_NoTextTruncation = (1 << 2), UI_BoxFlag_NoTextTruncation = (1 << 2),
UI_BoxFlag_Floating = (1 << 3), UI_BoxFlag_Floating = (1 << 3),
UI_BoxFlag_NoFloatingClamp = (1 << 4), UI_BoxFlag_NoFloatingClamp = (1 << 4),
UI_BoxFlag_Selected = (1 << 5),
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -121,11 +122,11 @@ Enum(UI_BoxFlag)
Enum(UI_StyleKind) Enum(UI_StyleKind)
{ {
#define X(name, type) UI_StyleKind_##name, #define X(name, type) UI_StyleKind_##name,
UI_StyleKind_None, UI_StyleKind_None,
UI_StyleKindsXMacro(X) UI_StyleKindsXMacro(X)
UI_StyleKind_COUNT, UI_StyleKind_COUNT,
#undef X #undef X
}; };
Struct(UI_Style) Struct(UI_Style)
@ -188,6 +189,7 @@ Struct(UI_Report)
f32 hovered; f32 hovered;
f32 hot; f32 hot;
f32 active; f32 active;
f32 selected;
// Mouse button info // Mouse button info
Vec2 last_down_mouse_offset; Vec2 last_down_mouse_offset;