From d1fe4593dad2d9159910be1b8bf93ecbe81633f3 Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 29 Dec 2025 19:44:42 -0600 Subject: [PATCH] ui animation scaling adjustments --- src/base/base_math.c | 22 +++++++++++ src/base/base_math.h | 5 +++ src/glyph_cache/glyph_cache.c | 12 +++--- src/pp/pp_vis/pp_vis_core.c | 21 +++++++---- src/ui/ui_core.c | 70 ++++++++++++++--------------------- src/ui/ui_core.h | 5 +++ 6 files changed, 77 insertions(+), 58 deletions(-) diff --git a/src/base/base_math.c b/src/base/base_math.c index c201cda5..359206a6 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -1173,6 +1173,13 @@ u32 U32FromVec4(Vec4 v) //////////////////////////////////////////////////////////// //~ Range +//- Rng1 + +f32 NormRng(Rng r, f32 v) +{ + return (r.max - r.min) / v; +} + //- Rng2 Vec2 DimsFromRng2(Rng2 r) @@ -1192,6 +1199,21 @@ Vec2 CenterFromRng2(Rng2 r) return result; } +Vec2 NormRng2(Rng2 r, Vec2 v) +{ + Vec2 result = Zi; + Vec2 dims = SubVec2(r.p1, r.p0); + if (dims.x != 0) + { + result.x = v.x / dims.x; + } + if (dims.y != 0) + { + result.y = v.y / dims.y; + } + return result; +} + Rng2 UnionRng2(Rng2 a, Rng2 b) { Rng2 result = Zi; diff --git a/src/base/base_math.h b/src/base/base_math.h index b396652d..0ee4db1e 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -390,9 +390,14 @@ u32 U32FromVec4(Vec4 v); //////////////////////////////////////////////////////////// //~ Range +//- Rng1 +f32 NormRng(Rng r, f32 v); +#define Norm(min, max, v) NormRng(RNG((min), (max)), (v)) + //- Rng2 Vec2 DimsFromRng2(Rng2 r); Vec2 CenterFromRng2(Rng2 r); +Vec2 NormRng2(Rng2 r, Vec2 v); Rng2 UnionRng2(Rng2 a, Rng2 b); Rng2 AddRng2Vec2(Rng2 r, Vec2 v); Rng2 MulRng2Vec2(Rng2 a, Vec2 v); diff --git a/src/glyph_cache/glyph_cache.c b/src/glyph_cache/glyph_cache.c index 7e74fab1..dc43867f 100644 --- a/src/glyph_cache/glyph_cache.c +++ b/src/glyph_cache/glyph_cache.c @@ -178,14 +178,13 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size { GC_Glyph *glyph = ready_glyphs[glyph_idx]; GC_RunRect *rect = &result.rects[glyph_idx]; - - f32 advance = RoundF32(glyph->advance * scale); + f32 advance = glyph->advance * scale; Rng2 bounds = Zi; - bounds.p0 = MulVec2(glyph->bounds.p0, scale); - bounds.p1 = MulVec2(glyph->bounds.p1, scale); - bounds.p0 = RoundVec2(bounds.p0); - bounds.p1 = RoundVec2(bounds.p1); + bounds.p0 = glyph->bounds.p0; + bounds.p1 = glyph->bounds.p1; + bounds.p0 = MulVec2(bounds.p0, scale); + bounds.p1 = MulVec2(bounds.p1, scale); rect->tex = glyph->atlas->tex_ref; rect->tex_slice = glyph->tex_slice; @@ -211,7 +210,6 @@ GC_Run GC_RunFromString(Arena *arena, String str, GC_FontKey font, f32 font_size if (ready_glyphs_count > 0) { - // TOOD: Round these too? GC_Glyph *glyph = ready_glyphs[0]; result.font_size = glyph->font_size * scale; result.font_ascent = glyph->font_ascent * scale; diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index b6f54f1a..0ed26197 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -140,6 +140,8 @@ void V_EndCommandsWidget(V_CommandsWidget *widget) 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); @@ -149,13 +151,16 @@ void V_EndCommandsWidget(V_CommandsWidget *widget) Vec4 divider_color = theme.divider_color; if (titlebar_rep.m1.held) { - widget->pos = SubVec2(cursor_pos, titlebar_rep.last_mouse_down_cursor_offset); + widget->pos = AddVec2(SubVec2(cursor_pos, titlebar_rep.last_mouse_down_cursor_offset), widget_half_dims); } - // window_border_color = LerpSrgb(window_border_color, Rgb(0.5, 0.5, 0.5), titlebar_rep.hot); window_border_color = LerpSrgb(window_border_color, Rgb32(0x0078a6), titlebar_rep.hot); - UI_Push(Scale, titlebar_rep.exists); - UI_Push(Tint, VEC4(1, 1, 1, titlebar_rep.exists)); + 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); @@ -164,8 +169,8 @@ void V_EndCommandsWidget(V_CommandsWidget *widget) UI_Push(Width, UI_PIX(theme.window_width, 0)); UI_Push(Height, UI_SHRINK(0, 0)); UI_Push(ChildLayoutAxis, Axis_Y); - UI_Push(FloatingPos, widget->pos); - UI_SetNext(Flags, UI_BoxFlag_Floating); + UI_Push(FloatingPos, SubVec2(widget->pos, widget_half_dims)); + UI_SetNext(Flags, UI_BoxFlag_Floating | (UI_BoxFlag_Selected * frame->show_command_palette)); UI_PushCP(UI_BuildBoxEx(widget->key)); { // Title bar @@ -1079,7 +1084,7 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Build tab row - f32 tab_spacing = 10; + f32 tab_spacing = 5; V_Window *active_window = 0; V_Window *close_window = 0; { @@ -1491,7 +1496,7 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Build command palette - if (frame->show_command_palette) + // if (frame->show_command_palette) { V_BeginCommandsWidget(&frame->commands_widget); { diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 57ae198f..a7faf7b7 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -265,7 +265,8 @@ void UI_PushDefaults(void) 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; - case UI_StyleKind_BackgroundTextureSliceUv: { desc.style.BackgroundTextureSliceUv = RNG2(VEC2(0, 0), VEC2(1, 1)); } break; + case UI_StyleKind_InvisibleDebugColor: { desc.style.InvisibleDebugColor = Rgba(0, 1, 1, 0.25); } break; + case UI_StyleKind_BackgroundTextureSliceUv: { desc.style.BackgroundTextureSliceUv = RNG2(VEC2(0, 0), VEC2(1, 1)); } break; }; UI_PushStyle(desc); } @@ -385,11 +386,6 @@ void UI_PushStyle(UI_StyleDesc desc) { default: break; - case UI_StyleKind_Text: - { - n->style.Text = PushString(frame->arena, desc.style.Text); - } break; - case UI_StyleKind_Tag: { if (n->next != 0) @@ -397,6 +393,11 @@ void UI_PushStyle(UI_StyleDesc desc) n->style.Tag = RandU64FromSeeds(n->next->style.Tag, n->style.Tag); } } break; + + case UI_StyleKind_Text: + { + n->style.Text = PushString(frame->arena, n->style.Text); + } break; } } } @@ -504,7 +505,7 @@ UI_Key UI_BuildBoxEx(UI_Key semantic_key) n->cmd.box.key = key; n->cmd.box.is_transient = is_transient; n->cmd.box.parent = UI_UseTop(Parent); - n->cmd.box.flags = UI_UseTop(Flags); + n->cmd.box.flags = (UI_UseTop(Flags) | UI_UseTop(OrFlags)) & ~UI_UseTop(OmitFlags); n->cmd.box.pref_semantic_dims[Axis_X] = UI_UseTop(Width); n->cmd.box.pref_semantic_dims[Axis_Y] = UI_UseTop(Height); n->cmd.box.scale = UI_UseTop(Scale); @@ -514,6 +515,7 @@ UI_Key UI_BuildBoxEx(UI_Key semantic_key) n->cmd.box.background_color = UI_UseTop(BackgroundColor); n->cmd.box.border_color = UI_UseTop(BorderColor); n->cmd.box.debug_color = UI_UseTop(DebugColor); + n->cmd.box.invisible_debug_color = UI_UseTop(InvisibleDebugColor); n->cmd.box.tint = UI_UseTop(Tint); n->cmd.box.border = UI_UseTop(Border); n->cmd.box.font = UI_UseTop(Font); @@ -809,11 +811,11 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) f32 target_active = box == active_box; f32 target_selected = !!(box->desc.flags & UI_BoxFlag_Selected); - f32 exists_blend_rate = (30 * frame->dt); + f32 exists_blend_rate = (40 * frame->dt); f32 hot_blend_rate = target_hot == 1 ? 1 : (15 * frame->dt); f32 active_blend_rate = target_active == 1 ? 1 : (15 * frame->dt); f32 hovered_blend_rate = target_hovered == 1 ? 1 : (15 * frame->dt); - f32 selected_blend_rate = target_selected == 1 ? 1 : (15 * frame->dt); + f32 selected_blend_rate = (40 * frame->dt); report->exists = LerpF32(report->exists, target_exists, exists_blend_rate); report->hot = LerpF32(report->hot, target_hot, hot_blend_rate); @@ -935,7 +937,6 @@ void UI_EndFrame(UI_Frame *frame) for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next) { UI_Cmd cmd = cmd_node->cmd; - switch (cmd.kind) { case UI_CmdKind_BuildBox: @@ -974,9 +975,7 @@ void UI_EndFrame(UI_Frame *frame) box->glyph_run = GC_RunFromString(frame->arena, box->desc.text, box->desc.font, box->desc.font_size, box->desc.scale); } - box->last_build_tick = frame->tick; - } break; case UI_CmdKind_SetRawTexture: @@ -1088,21 +1087,6 @@ void UI_EndFrame(UI_Frame *frame) Assert(post_index == boxes_count); } - // Scale semantic pixel sizes - for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) - { - UI_Box *box = boxes_pre[pre_index]; - for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) - { - UI_Size *sem_dims = &box->desc.pref_semantic_dims[axis]; - b32 skip = sem_dims->kind != UI_SizeKind_Pixel; - if (!skip) - { - sem_dims->v *= box->desc.scale; - } - } - } - // Compute independent sizes for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) { @@ -1112,7 +1096,7 @@ void UI_EndFrame(UI_Frame *frame) UI_Size sem_dims = box->desc.pref_semantic_dims[axis]; if (sem_dims.kind == UI_SizeKind_Pixel) { - box->solved_dims[axis] = sem_dims.v; + box->solved_dims[axis] = RoundF32(sem_dims.v * box->desc.scale); } else if (sem_dims.kind == UI_SizeKind_Shrink && AnyBit(box->desc.flags, UI_BoxFlag_DrawText)) { @@ -1126,7 +1110,7 @@ void UI_EndFrame(UI_Frame *frame) { text_size = box->glyph_run.font_ascent + box->glyph_run.font_descent; } - box->solved_dims[axis] = text_size + (sem_dims.v * 2); + box->solved_dims[axis] = RoundF32(text_size + (sem_dims.v * 2 * box->desc.scale)); } } } @@ -1153,7 +1137,7 @@ void UI_EndFrame(UI_Frame *frame) found_match = 1; } } - box->solved_dims[axis] = match_size * sem_dims.v; + box->solved_dims[axis] = RoundF32(match_size * sem_dims.v); } } } @@ -1182,7 +1166,7 @@ void UI_EndFrame(UI_Frame *frame) } } } - box->solved_dims[axis] = accum + (sem_dims.v * 2); + box->solved_dims[axis] = CeilF32(accum + (sem_dims.v * 2)); } } } @@ -1197,7 +1181,7 @@ void UI_EndFrame(UI_Frame *frame) UI_Size sem_dims = box->desc.pref_semantic_dims[axis]; if (sem_dims.kind == UI_SizeKind_Grow) { - box->solved_dims[axis] = box->parent->solved_dims[axis] * sem_dims.v; + box->solved_dims[axis] = RoundF32(box->parent->solved_dims[axis] * sem_dims.v); } } } @@ -1257,7 +1241,7 @@ void UI_EndFrame(UI_Frame *frame) } } adjusted_size_accum += new_size; - child->solved_dims[axis] = new_size; + child->solved_dims[axis] = RoundF32(new_size); } } size_accum = adjusted_size_accum; @@ -1274,7 +1258,7 @@ void UI_EndFrame(UI_Frame *frame) { f32 strictness = child->desc.pref_semantic_dims[axis].strictness; f32 flex = size * (1.0 - strictness); - child->solved_dims[axis] = MaxF32(size - flex, box_size); + child->solved_dims[axis] = RoundF32(MaxF32(size - flex, box_size)); } } } @@ -1367,10 +1351,9 @@ void UI_EndFrame(UI_Frame *frame) } // Submit position - Vec2 rounded_final_pos = RoundVec2(final_pos); - Vec2 rounded_dims = RoundVec2(dims_vec); - box->rect.p0 = FloorVec2(rounded_final_pos); - box->rect.p1 = AddVec2(rounded_final_pos, rounded_dims); + Vec2 rounded_final_pos = FloorVec2(final_pos); + box->rect.p0 = rounded_final_pos; + box->rect.p1 = AddVec2(rounded_final_pos, dims_vec); } // Rounding @@ -1437,11 +1420,12 @@ void UI_EndFrame(UI_Frame *frame) { UI_Box *box = boxes_pre[pre_index]; b32 is_visible = 1; - is_visible = is_visible && (box->desc.tint.w != 0); - is_visible = is_visible && (box->rect.p1.x > box->rect.p0.x); - is_visible = is_visible && (box->rect.p1.y > box->rect.p0.y); + is_visible = is_visible && (box->desc.tint.w >= 0.001); + is_visible = is_visible && (box->rect.p1.x - box->rect.p0.x >= 1); + is_visible = is_visible && (box->rect.p1.y - box->rect.p0.y >= 1); if (is_visible || AnyBit(frame->frame_flags, UI_FrameFlag_Debug)) { + Vec4 debug_lin = is_visible ? LinearFromSrgb(box->desc.debug_color) : LinearFromSrgb(box->desc.invisible_debug_color); // Box rect { @@ -1449,7 +1433,7 @@ void UI_EndFrame(UI_Frame *frame) rect->bounds = box->rect; rect->background_lin = LinearFromSrgb(box->desc.background_color); rect->border_lin = LinearFromSrgb(box->desc.border_color); - rect->debug_lin = LinearFromSrgb(box->desc.debug_color); + rect->debug_lin = debug_lin; rect->tint_lin = LinearFromSrgb(box->desc.tint); rect->border = box->desc.border; rect->tl_rounding = box->rounding_tl; @@ -1568,7 +1552,7 @@ void UI_EndFrame(UI_Frame *frame) if (glyph_dims.x != 0 || glyph_dims.y != 0) { UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect); - rect->debug_lin = LinearFromSrgb(box->desc.debug_color); + rect->debug_lin = debug_lin; rect->tint_lin = LinearFromSrgb(box->desc.tint); rect->tex = rr.tex; rect->tex_slice_uv = rr.tex_slice_uv; diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index c80cc599..295362ca 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -92,6 +92,8 @@ Enum(UI_BoxFlag) //~ Style types #define UI_StyleKindsXMacro(X) \ + X(OmitFlags, UI_BoxFlag) \ + X(OrFlags, UI_BoxFlag) \ X(Flags, UI_BoxFlag) \ X(Parent, UI_Key) \ X(Tag, u64) \ @@ -104,6 +106,7 @@ Enum(UI_BoxFlag) X(BackgroundColor, Vec4) \ X(BorderColor, Vec4) \ X(DebugColor, Vec4) \ + X(InvisibleDebugColor, Vec4) \ X(Tint, Vec4) \ X(Border, f32) \ X(FloatingPos, Vec2) \ @@ -117,6 +120,7 @@ Enum(UI_BoxFlag) /* --------------- Virtual styles -------------- */ \ /* --------------------------------------------- */ \ X(BeginVirtualStyles_, i8) \ + /* --------------------------------------------- */ \ X(ChildAlignment, UI_Alignment) \ X(AxisSize, UI_Size) \ /* ------------------------------------------------- */ @@ -227,6 +231,7 @@ Struct(UI_BoxDesc) Vec4 background_color; Vec4 border_color; Vec4 debug_color; + Vec4 invisible_debug_color; Vec4 tint; f32 border; f32 scale;