From f17bdc9d764ab3ed694863619d411d23f3c84ceb Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 5 Apr 2026 22:22:52 -0500 Subject: [PATCH] in-world death text --- src/base/base_math.c | 74 +++- src/base/base_math.h | 13 +- src/pp/pp.c | 27 +- src/pp/pp.h | 6 +- src/pp/pp_terms.h | 1 - src/pp/pp_vis/pp_vis_core.c | 851 +++++++++++++++++++----------------- src/pp/pp_vis/pp_vis_core.h | 17 +- src/ui/ui_core.c | 131 +++--- src/ui/ui_core.h | 9 +- 9 files changed, 635 insertions(+), 494 deletions(-) diff --git a/src/base/base_math.c b/src/base/base_math.c index f8ff5689..0f396ab7 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -342,26 +342,6 @@ Vec4 SrgbFromLinear(Vec4 lin) return result; } -Vec4 SrgbFromHsv(f32 h, f32 s, f32 v) -{ - h = ModF32(h, 360.0f); - if (h < 0) - { - h += 360.0f; - } - f32 c = v * s; - f32 x = c * (1.0f - AbsF32(ModF32(h / 60.0f, 2.0f) - 1.0f)); - f32 m = v - c; - Vec4 result = VEC4(0, 0, 0, 1); - if (h < 60.0f) { result.r = c; result.g = x; result.b = 0; } - else if (h < 120.0f) { result.r = x; result.g = c; result.b = 0; } - else if (h < 180.0f) { result.r = 0; result.g = c; result.b = x; } - else if (h < 240.0f) { result.r = 0; result.g = x; result.b = c; } - else if (h < 300.0f) { result.r = x; result.g = 0; result.b = c; } - else { result.r = c; result.g = 0; result.b = x; } - return result; -} - Vec4 PremulFromLinear(Vec4 lin) { Vec4 result = Zi; @@ -389,6 +369,60 @@ Vec4 LerpSrgb(Vec4 a, Vec4 b, f32 t) return result; } +Vec4 SrgbFromHsv(Hsv hsv) +{ + f32 h = ModF32(hsv.h, 360); + f32 s = hsv.s; + f32 v = hsv.v; + if (h < 0) + { + h += 360; + } + f32 c = v * s; + f32 x = c * (1 - AbsF32(ModF32(h / 60, 2) - 1)); + f32 m = v - c; + Vec4 result = VEC4(0, 0, 0, 1); + if (h < 60) { result.r = c; result.g = x; result.b = 0; } + else if (h < 120) { result.r = x; result.g = c; result.b = 0; } + else if (h < 180) { result.r = 0; result.g = c; result.b = x; } + else if (h < 240) { result.r = 0; result.g = x; result.b = c; } + else if (h < 300) { result.r = x; result.g = 0; result.b = c; } + else { result.r = c; result.g = 0; result.b = x; } + return result; +} + +Hsv HsvFromSrgb(Vec4 srgb) +{ + f32 r = srgb.r; + f32 g = srgb.g; + f32 b = srgb.b; + f32 max = MaxF32(r, MaxF32(g, b)); + f32 min = MinF32(r, MinF32(g, b)); + f32 delta = max - min; + Hsv result = Zi; + { + result.v = max; + if (max <= 0) { + result.s = 0; + } else { + result.s = delta / max; + } + if (delta <= 0) { + result.h = 0; + } else if (max == r) { + result.h = 60 * ModF32((g - b) / delta, 6); + } else if (max == g) { + result.h = 60 * (((b - r) / delta) + 2); + } else { + result.h = 60 * (((r - g) / delta) + 4); + } + if (result.h < 0) { + result.h += 360; + } + } + return result; +} + //////////////////////////////////////////////////////////// //~ Vec2 diff --git a/src/base/base_math.h b/src/base/base_math.h index aa99b0eb..10ebcc59 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -194,6 +194,15 @@ Union(Mat4x4) f32 e[4][4]; }; +//////////////////////////////////////////////////////////// +//~ Color types + +#define HSV(h, s, v) ((Hsv) { (h), (s), (v) }) +Struct(Hsv) +{ + f32 h, s, v; +}; + //////////////////////////////////////////////////////////// //~ Min / max @@ -339,13 +348,15 @@ f32 LinearFromSrgbF32(f32 srgb); Vec4 LinearFromSrgb(Vec4 srgb); Vec4 SrgbFromLinear(Vec4 lin); -Vec4 SrgbFromHsv(f32 h, f32 s, f32 v); Vec4 PremulFromLinear(Vec4 lin); Vec4 PremulFromSrgb(Vec4 srgb); Vec4 LerpSrgb(Vec4 a, Vec4 b, f32 t); +Vec4 SrgbFromHsv(Hsv hsv); +Hsv HsvFromSrgb(Vec4 srgb); + //////////////////////////////////////////////////////////// //~ Vec2 diff --git a/src/pp/pp.c b/src/pp/pp.c index fdcb0206..8bfafbe4 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -260,6 +260,16 @@ P_Shape P_WorldShapeFromEnt(P_Ent *ent) //////////////////////////////////////////////////////////// //~ Status helpers +b32 P_IsEntRolling(P_Frame *frame, P_Ent *ent) +{ + b32 result = ( + ent->last_roll_ns > 0 && + (frame->time_ns - ent->last_roll_ns) > 0 && + (frame->time_ns - ent->last_roll_ns) < P_RollTimeNs + ); + return result; +} + P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent) { P_Anim result = Zi; @@ -368,14 +378,17 @@ P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent) return result; } -b32 P_IsEntRolling(P_Frame *frame, P_Ent *ent) +Vec4 P_ColorFromEnt(P_Ent *ent) { - b32 result = ( - ent->last_roll_ns > 0 && - (frame->time_ns - ent->last_roll_ns) > 0 && - (frame->time_ns - ent->last_roll_ns) < P_RollTimeNs - ); - return result; + String ent_str = P_StringFromEnt(ent); + u64 color_seed = MixU64s(P_EntityColorBasis, HashString(ent_str)); + f32 hue_offset = TweakFloat("Entity color hue offset", 135, 0, 360); + f32 h = (Norm16(color_seed >> 2) * 1) * 360 + hue_offset; + f32 s = TweakFloat("Entity color saturation", 0.7, 0, 1); + f32 v = TweakFloat("Entity color brightness", 1, 0, 1); + // f32 s = TweakFloat("Entity color saturation", 0.3, 0, 1); + // f32 v = TweakFloat("Entity color brightness", 0.6, 0, 1); + return SrgbFromHsv(HSV(h, s, v)); } //////////////////////////////////////////////////////////// diff --git a/src/pp/pp.h b/src/pp/pp.h index 76b51b03..932a30bd 100644 --- a/src/pp/pp.h +++ b/src/pp/pp.h @@ -12,6 +12,7 @@ #define P_BulletTrailBasis 0x27c011f891c571feull #define P_DeathBasis 0x2e3c75a3286d872aull #define P_KillfeedBasis 0xd1f84bd6f7c3cf1eull +#define P_EntityColorBasis 0x3d2ddd9778146eccull Struct(P_EntKey) { @@ -190,8 +191,6 @@ Struct(P_NetworkedEntState) b32 is_player; P_EntKey guy; - f32 ping; - u64 kills; u64 deaths; @@ -715,8 +714,9 @@ P_Shape P_WorldShapeFromEnt(P_Ent *ent); //////////////////////////////////////////////////////////// //~ Status helpers -P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent); b32 P_IsEntRolling(P_Frame *frame, P_Ent *ent); +P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent); +Vec4 P_ColorFromEnt(P_Ent *ent); //////////////////////////////////////////////////////////// //~ Collision diff --git a/src/pp/pp_terms.h b/src/pp/pp_terms.h index 8d3ec0af..fbfff33d 100644 --- a/src/pp/pp_terms.h +++ b/src/pp/pp_terms.h @@ -12,7 +12,6 @@ PERSIST Readonly String P_KillTerms[] = { CompLit("terminated"), CompLit("demoted"), CompLit("restructured"), - CompLit("shredded"), CompLit("decommissioned"), CompLit("finalized"), CompLit("offboarded"), diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 8ea67e3d..ca6c91ba 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -680,7 +680,7 @@ void V_PushWidgetThemeStyles(V_WidgetTheme theme) //////////////////////////////////////////////////////////// //~ Notification helpers -void V_PushNotif(String msg) +V_Notif *V_PushNotif(String msg) { Arena *perm = PermArena(); V_Notif *notif = PushStruct(perm, V_Notif); @@ -693,6 +693,7 @@ void V_PushNotif(String msg) } SllQueuePushFront(V.first_notif, V.last_notif, notif); LogInfoF("[Notif] %F", FmtString(notif->msg)); + return notif; } //////////////////////////////////////////////////////////// @@ -2497,6 +2498,7 @@ void V_TickForever(WaveLaneCtx *lane) } //- Observe + ent->initial_observation_time_ns = obs->initial_observation_time_ns; ent->last_observation_time_ns = frame->time_ns; ent->is_first_observation = obs->initial_observation_time_ns == frame->time_ns; } @@ -2940,19 +2942,16 @@ void V_TickForever(WaveLaneCtx *lane) Vec4 legs_mask_color_lin = Zi; if (ent->is_guy) { - f32 body_hue_offset = TweakFloat("Guy body hue offset", 135, 0, 360); - f32 body_s = TweakFloat("Guy body saturation", 0.7, 0, 1); - f32 body_v = TweakFloat("Guy body brightness", 1, 0, 1); f32 legs_hue_offset = TweakFloat("Guy legs hue offset", 180, 0, 360); f32 legs_s = TweakFloat("Guy legs saturation", 1, 0, 1); f32 legs_v = TweakFloat("Guy legs brightness", 1, 0, 1); { P_Ent *player = P_EntFromKey(local_frame, ent->source); - u64 color_seed = HashString(P_StringFromEnt(player)); - f32 body_hue = (Norm16(color_seed >> 2) * 1) * 360 + body_hue_offset; + Vec4 body_color = P_ColorFromEnt(player); + f32 body_hue = HsvFromSrgb(body_color).h; f32 legs_hue = ModF32(body_hue + legs_hue_offset, 360); - body_mask_color_lin = LinearFromSrgb(SrgbFromHsv(body_hue, body_s, body_v)); - legs_mask_color_lin = LinearFromSrgb(SrgbFromHsv(legs_hue, legs_s, legs_v)); + body_mask_color_lin = body_color; + legs_mask_color_lin = LinearFromSrgb(SrgbFromHsv(HSV(legs_hue, legs_s, legs_v))); } } @@ -3043,20 +3042,16 @@ void V_TickForever(WaveLaneCtx *lane) for (P_Ent *event = P_FirstEnt(local_frame); !P_IsEntNil(event); event = P_NextEnt(event)) { - if (event->is_first_observation) + f64 seconds_since_observation = SecondsFromNs(frame->time_ns - event->initial_observation_time_ns); + u64 angle_offset_basis = 0xf55070bae6e1d70c; + f32 rand_angle = (Norm24(MixU64s(event->key.v, angle_offset_basis)) * 2 - 1); + + ////////////////////////////// + //- Trail + + if (event->is_trail) { - f64 seconds_since_observation = SecondsFromNs(frame->time_ns - event->initial_observation_time_ns); - u64 angle_offset_basis = 0xf55070bae6e1d70c; - f32 rand_angle = (Norm24(MixU64s(event->key.v, angle_offset_basis)) * 2 - 1); - - ////////////////////////////// - //- Trail - - - // TODO: Remove this - - - if (event->is_trail) + if (event->is_first_observation) { Vec2 p0 = event->trail_p0; Vec2 p1 = event->trail_p1; @@ -3416,15 +3411,14 @@ void V_TickForever(WaveLaneCtx *lane) } } + } + ////////////////////////////// + //- Hit - - - - ////////////////////////////// - //- Hit - - if (event->is_hit) + if (event->is_hit) + { + if (event->is_first_observation) { P_MaterialKind material = event->hit_material; @@ -3556,39 +3550,25 @@ void V_TickForever(WaveLaneCtx *lane) // V_DrawPoint(victim_raycast.p, Color_Green); // V_DrawLine(victim_raycast.p, AddVec2(victim_raycast.p, MulVec2(victim_raycast.normal, 0.5)), Color_White); } + } + ////////////////////////////// + //- Death + if (event->is_death) + { + Vec2 death_pos = event->death_pos; + u64 killfeed_term_seed = MixU64s(event->key.v, P_KillfeedBasis); + String killfeed_term = UpperString(frame->arena, P_KillTerms[killfeed_term_seed % countof(P_KillTerms)]); - - ////////////////////////////// - //- Death - - if (event->is_death) + if (event->is_first_observation) { - Vec2 death_pos = event->death_pos; - - //- Killfeed + //- Killfeed notification { - P_Ent *victim = P_EntFromKey(local_frame, event->death_victim); - P_Ent *killer = P_EntFromKey(local_frame, event->death_killer); - String victim_name = P_StringFromEnt(victim); - String killer_name = P_StringFromEnt(killer); - - if (victim_name.len > 0) - { - u64 killfeed_term_seed = MixU64s(event->key.v, P_KillfeedBasis); - String killfeed_term = UpperString(frame->arena, P_KillTerms[killfeed_term_seed % countof(P_KillTerms)]); - String msg = Zi; - if (killer_name.len > 0) - { - msg = StringF(frame->arena, "%F %F %F", FmtString(killer_name), FmtString(killfeed_term), FmtString(victim_name)); - } - else - { - msg = StringF(frame->arena, "%F was %F", FmtString(killfeed_term), FmtString(victim_name)); - } - V_PushNotif(msg); - } + V_Notif *notif = V_PushNotif(killfeed_term); + notif->flags |= V_NotifFlag_Kill; + notif->killer = event->death_killer; + notif->victim = event->death_victim; } //- Death particles @@ -3623,6 +3603,55 @@ void V_TickForever(WaveLaneCtx *lane) V_PushParticles(emitter); } } + + // P_Ent *victim = P_EntFromKey(local_frame, event->death_victim); + // P_Ent *killer = P_EntFromKey(local_frame, event->death_killer); + // String victim_name = P_StringFromEnt(victim); + // String killer_name = P_StringFromEnt(killer); + + + f32 event_seconds = SecondsFromNs(frame->time_ns - event->initial_observation_time_ns); + f32 duration_seconds = 0.5; + f32 progress = SaturateF32(event_seconds / duration_seconds); + f32 opacity = 1.0 - progress; + + u64 text_dir_basis = 0x2f2b82acccbcf025ull; + u64 text_dir_seed = MixU64s(event->key.v, text_dir_basis); + f32 move_dir_spread = Tau / 4; + f32 move_meters = 1; + + // Vec4 text_color = LinearFromSrgb(VEC4(0.75, 0.2, 0.2, 1)); + Vec4 text_color = Color_White; + Vec2 move_dir = VEC2(0, -1); + + Vec2 text_world_pos = AddVec2(death_pos, MulVec2(move_dir, progress)); + text_world_pos.y -= 0.25; + Vec2 text_screen_pos = MulAffineVec2(frame->af.world_to_screen, text_world_pos); + + UI_PushDF(Parent, vis_screen_overlay_box) + UI_PushDF(FontSize, 32) + UI_PushDF(Opacity, opacity) + UI_PushDF(Flags, UI_BoxFlag_Floating | UI_BoxFlag_DrawText | UI_BoxFlag_DontClampFloatingX | UI_BoxFlag_DontClampFloatingY) + UI_PushDF(Font, theme.player_name_font) + { + + String text = killfeed_term; + + // Name box + UI_SetNext(FloatingPos, text_screen_pos); + UI_PushDF(TextColor, text_color) + UI_PushDF(Parent, UI_BuildBox()) + UI_PushDF(Text, text) + { + // Drop-shadow + UI_SetNext(TextColor, Color_Black); + UI_SetNext(FloatingPos, VEC2(2, 2)); + UI_BuildBox(); + + // Name text + UI_BuildBox(); + } + } } } @@ -4038,12 +4067,80 @@ void V_TickForever(WaveLaneCtx *lane) + + // UI_PushDF(Parent, vis_root_box) + // b32 show_panels = 1; + // if (!show_panels) + // { + // UI_SetNext(Flags, UI_BoxFlag_Floating); + // UI_SetNext(Parent, vis_screen_box); + // UI_BuildBoxEx(vis_panels_box); + // UI_SetNext(Parent, vis_panels_box); + // UI_BuildColumnEx(vis_screen_panel_box); + // UI_BuildBoxEx(vis_panels_box); + // } + + // { + // b32 lock_screen_to_panel = TweakBool("Lock screen to panel", 0); + // if (lock_screen_to_panel) + // { + // UI_SetNext(Parent, vis_screen_panel_box); + // } + // else + // { + // UI_SetNext(Parent, vis_root_box); + // } + // UI_BuildBoxEx(vis_screen_box); + // } + + // if (!show_panels) + // { + // UI_SetNext(Parent, vis_root_box); + // UI_BuildBoxEx(vis_screen_box); + // } + + // FIXME: Limit dims based on sample buffer capacity // b32 should_draw_profiler_graph = frame->profiler.is_showing && frame->profiler.graph_dims.x > 0 && frame->profiler.graph_dims.y > 0; // frame->profiler_graph_dims = frame->profiler.graph_dims; // frame->profiler_frame_seq = V.profiler_frame_seq; + + + + + + + + b32 show_panels = frame->is_editing; + // UI_PushDF(Parent, vis_root_box) + // if (!show_panels) + // { + // // UI_SetNext(Flags, UI_BoxFlag_Floating); + // // UI_SetNext(Parent, vis_root_box); + // // UI_BuildColumnEx(vis_screen_panel_box); + // UI_SetNext(Flags, UI_BoxFlag_Floating); + // UI_SetNext(Parent, vis_root_box); + // UI_BuildColumnEx(vis_panels_box); + // } + + { + UI_SetNext(Parent, vis_root_box); + UI_BuildBoxEx(vis_screen_box); + + UI_SetNext(Parent, vis_screen_box); + UI_BuildBoxEx(vis_panels_box); + + UI_SetNext(Parent, vis_panels_box); + UI_BuildBoxEx(vis_screen_panel_box); + + } + + + + + UI_Key profiler_graph_box = UI_KeyF("graph"); b32 should_draw_profiler_graph = 0; V.profiler_graph_dims = DimsFromRng2(UI_Rect(profiler_graph_box)); @@ -4053,7 +4150,7 @@ void V_TickForever(WaveLaneCtx *lane) - if (V.root_panel) + if (V.root_panel && show_panels) { Struct(BfsPanel) { BfsPanel *next; V_Panel *panel; }; BfsPanel *first_bfs_panel = PushStruct(frame->arena, BfsPanel); @@ -4780,7 +4877,7 @@ void V_TickForever(WaveLaneCtx *lane) f32 h = (Norm16(color_seed >> 0) * 1) * 360; f32 s = TweakFloat("Profiler zone saturation", 0.50, 0, 1); f32 v = TweakFloat("Profiler zone brightness", 1.00, 0, 1); - Vec4 zone_color = SrgbFromHsv(h, s, v); + Vec4 zone_color = SrgbFromHsv(HSV(h, s, v)); // b32 should_collapse_zone = visual_zone_len_px <= zone_collapse_threshold_px; // b32 should_collapse_zone = 0; @@ -4865,8 +4962,8 @@ void V_TickForever(WaveLaneCtx *lane) main_color_unsampled.g *= 0.85; main_color_unsampled.b *= 0.85; - Vec4 collapsed_line_color = SrgbFromHsv(64, 1, 0.5); - Vec4 collapsed_text_color = SrgbFromHsv(64, 1, 0.75); + Vec4 collapsed_line_color = SrgbFromHsv(HSV(64, 1, 0.5)); + Vec4 collapsed_text_color = SrgbFromHsv(HSV(64, 1, 0.75)); // main_color_sampled.g += 0.05; @@ -5559,18 +5656,18 @@ void V_TickForever(WaveLaneCtx *lane) V.root_panel = panel; } - // //- Left panel - // { - // V_Panel *panel = left_panel; - // panel->parent = V.root_panel; - // panel->axis = Axis_X; - // DllQueuePush(panel->parent->first, panel->parent->last, panel); - // panel->box = UI_RandKey(); - // panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v)); - // panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v)); - // panel->pct = 0.10; - // panel->is_organizational = 1; - // } + //- Left panel + { + V_Panel *panel = left_panel; + panel->parent = V.root_panel; + panel->axis = Axis_X; + DllQueuePush(panel->parent->first, panel->parent->last, panel); + panel->box = UI_RandKey(); + panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v)); + panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v)); + panel->pct = 0.10; + panel->is_organizational = 1; + } //- Right panel { @@ -5586,32 +5683,32 @@ void V_TickForever(WaveLaneCtx *lane) } } - // //- Test spawn panel - // { - // V_Panel *panel = PushStruct(perm, V_Panel); - // panel->parent = left_panel; - // panel->axis = Axis_X; - // DllQueuePush(panel->parent->first, panel->parent->last, panel); - // panel->box = UI_RandKey(); - // panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v)); - // panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v)); - // panel->flags |= V_PanelFlag_Spawn; - // panel->pct = 0.25; - // } - - //- Test profiler panel + //- Test spawn panel { V_Panel *panel = PushStruct(perm, V_Panel); - panel->parent = right_panel; + panel->parent = left_panel; panel->axis = Axis_X; DllQueuePush(panel->parent->first, panel->parent->last, panel); panel->box = UI_RandKey(); panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v)); panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v)); - panel->flags |= V_PanelFlag_Profiler; - panel->pct = 0.5; + panel->flags |= V_PanelFlag_Spawn; + panel->pct = 0.25; } + // //- Test profiler panel + // { + // V_Panel *panel = PushStruct(perm, V_Panel); + // panel->parent = right_panel; + // panel->axis = Axis_X; + // DllQueuePush(panel->parent->first, panel->parent->last, panel); + // panel->box = UI_RandKey(); + // panel->contents_box = UI_KeyF("panel contents box %F", FmtUint(panel->box.v)); + // panel->resizer_box = UI_KeyF("panel resizer box %F", FmtUint(panel->box.v)); + // panel->flags |= V_PanelFlag_Profiler; + // panel->pct = 0.5; + // } + //- Vis screen panel { V_Panel *panel = PushStruct(perm, V_Panel); @@ -5648,298 +5745,260 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Build vis panel contents + if (show_panels) UI_PushDF(Tag, HashF("vis panels")) { - // FIXME: Remove this + UI_SetNext(Flags, UI_BoxFlag_Floating); + UI_SetNext(Parent, vis_root_box); + UI_SetNext(ChildLayoutAxis, V.root_panel->axis); + UI_BuildBoxEx(vis_panels_box); - ////////////////////////////// - //- Init test panels - - - - - - - - - - - - - // UI_PushDF(Parent, vis_root_box) - // if (!show_panels) - // { - // UI_SetNext(Flags, UI_BoxFlag_Floating); - // UI_SetNext(Parent, vis_root_box); - // UI_BuildColumnEx(vis_screen_panel_box); - // } + Struct(PanelBfs) { PanelBfs *next; V_Panel *panel; }; + PanelBfs *first_panel_bfs = PushStruct(frame->arena, PanelBfs); + PanelBfs *last_panel_bfs = first_panel_bfs; + first_panel_bfs->panel = V.root_panel; + for (PanelBfs *bfs_parent = first_panel_bfs; bfs_parent; bfs_parent = first_panel_bfs) { - b32 lock_screen_to_panel = TweakBool("Lock screen to panel", 0); - if (lock_screen_to_panel) + SllQueuePop(first_panel_bfs, last_panel_bfs); + V_Panel *parent_panel = bfs_parent->panel; + + Axis parent_axis = parent_panel->axis; + Rng2 parent_rect = UI_Rect(parent_panel->contents_box); + Vec2 parent_dims = DimsFromRng2(parent_rect); + f32 parent_contents_size_px = MaxF32(DimsFromRng2(UI_Rect(parent_panel->contents_box)).v[parent_axis], 1); + + UI_PushDF(Tag, parent_panel->contents_box.v) + UI_PushDF(Parent, parent_panel->contents_box) { - UI_SetNext(Parent, vis_screen_panel_box); - } - else - { - UI_SetNext(Parent, vis_root_box); - } - UI_BuildBoxEx(vis_screen_box); - } + f32 minimum_panel_pct = 0.05; - { - UI_SetNext(Flags, UI_BoxFlag_Floating); - UI_SetNext(Parent, vis_root_box); - UI_SetNext(ChildLayoutAxis, V.root_panel->axis); - UI_BuildBoxEx(vis_panels_box); - Struct(PanelBfs) { PanelBfs *next; V_Panel *panel; }; - PanelBfs *first_panel_bfs = PushStruct(frame->arena, PanelBfs); - PanelBfs *last_panel_bfs = first_panel_bfs; - first_panel_bfs->panel = V.root_panel; + // FIXME: Ignored panels should be skipped during sibling iteration as well - for (PanelBfs *bfs_parent = first_panel_bfs; bfs_parent; bfs_parent = first_panel_bfs) - { - SllQueuePop(first_panel_bfs, last_panel_bfs); - V_Panel *parent_panel = bfs_parent->panel; - Axis parent_axis = parent_panel->axis; - Rng2 parent_rect = UI_Rect(parent_panel->contents_box); - Vec2 parent_dims = DimsFromRng2(parent_rect); - f32 parent_contents_size_px = MaxF32(DimsFromRng2(UI_Rect(parent_panel->contents_box)).v[parent_axis], 1); - UI_PushDF(Tag, parent_panel->contents_box.v) - UI_PushDF(Parent, parent_panel->contents_box) + //- Resize panels + for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) { - f32 minimum_panel_pct = 0.05; - - - // FIXME: Ignored panels should be skipped during sibling iteration as well - - - - //- Resize panels - for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) + if (UI_Downs(panel->resizer_box, Button_M1)) { - if (UI_Downs(panel->resizer_box, Button_M1)) - { - // FIXME: Don't need to store this state per-panel - panel->drag_resize_pct = panel->pct; - panel->drag_resize_pct_per_px = 1.0 / parent_contents_size_px; - } - if (UI_Held(panel->resizer_box, Button_M1)) - { - f32 drag_delta_px = UI_CursorPos().v[parent_axis] - UI_DragCursorPos().v[parent_axis]; - f32 drag_delta_pct = drag_delta_px * panel->drag_resize_pct_per_px; + // FIXME: Don't need to store this state per-panel + panel->drag_resize_pct = panel->pct; + panel->drag_resize_pct_per_px = 1.0 / parent_contents_size_px; + } + if (UI_Held(panel->resizer_box, Button_M1)) + { + f32 drag_delta_px = UI_CursorPos().v[parent_axis] - UI_DragCursorPos().v[parent_axis]; + f32 drag_delta_pct = drag_delta_px * panel->drag_resize_pct_per_px; - f32 old_pct = panel->pct; - f32 new_pct = MaxF32(panel->drag_resize_pct + drag_delta_pct, minimum_panel_pct); - f32 new_sibling_pct = 0; - if (panel->next) - { - f32 old_sibling_pct = panel->next->pct; - f32 desired_new_sibling_pct = panel->next->pct - (new_pct - old_pct); - new_sibling_pct = MaxF32(desired_new_sibling_pct, minimum_panel_pct); - new_pct -= (new_sibling_pct - desired_new_sibling_pct); - } - - if (panel->next) - { - panel->next->pct = new_sibling_pct; - } - panel->pct = new_pct; - } - if (UI_HotAbsolute(panel->resizer_box)) + f32 old_pct = panel->pct; + f32 new_pct = MaxF32(panel->drag_resize_pct + drag_delta_pct, minimum_panel_pct); + f32 new_sibling_pct = 0; + if (panel->next) { - if (parent_axis == Axis_X) - { - WND_SetCursor(window_frame, WND_CursorKind_HorizontalResize); - } - else - { - WND_SetCursor(window_frame, WND_CursorKind_VerticalResize); - } + f32 old_sibling_pct = panel->next->pct; + f32 desired_new_sibling_pct = panel->next->pct - (new_pct - old_pct); + new_sibling_pct = MaxF32(desired_new_sibling_pct, minimum_panel_pct); + new_pct -= (new_sibling_pct - desired_new_sibling_pct); + } + + if (panel->next) + { + panel->next->pct = new_sibling_pct; + } + panel->pct = new_pct; + } + if (UI_HotAbsolute(panel->resizer_box)) + { + if (parent_axis == Axis_X) + { + WND_SetCursor(window_frame, WND_CursorKind_HorizontalResize); + } + else + { + WND_SetCursor(window_frame, WND_CursorKind_VerticalResize); } } + } - //- Adjust panel pcts to add to 1 - { - f32 pct_accum = 0; - f32 children_count = 0; - for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) - { - children_count += 1; - pct_accum += panel->pct; - } - f32 violation = 1.0 - pct_accum; - for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) - { - panel->pct = panel->pct + violation / children_count; - panel->pct = MaxF32(panel->pct, minimum_panel_pct); - } - } - - - - // //- Adjust panel pcts to add to 1 - // f32 children_pct_scale = 1; - // { - // f32 pct_accum = 0; - // for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) - // { - // if (!V_ShouldIgnorePanel(panel)) - // { - // pct_accum += panel->pct; - // } - // } - // children_pct_scale = 1.0 / MinF32(pct_accum, 1); - // } - - - - // // //- Determine scale needed for sum of pcts to reach 1 - // // f32 children_pct_scale = 1; - // // { - // // f32 pct_accum = 0; - // // for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) - // // { - // // if (!V_ShouldIgnorePanel(panel)) - // // { - // // pct_accum += panel->pct; - // // } - // // } - // // children_pct_scale = 1.0 / MaxF32(pct_accum, 0.0001); - // // } - - - - - - - - //- Build panel boxes + //- Adjust panel pcts to add to 1 + { + f32 pct_accum = 0; + f32 children_count = 0; for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) { - PanelBfs *bfs_panel = PushStruct(frame->arena, PanelBfs); - bfs_panel->panel = panel; - SllQueuePush(first_panel_bfs, last_panel_bfs, bfs_panel); + children_count += 1; + pct_accum += panel->pct; + } + f32 violation = 1.0 - pct_accum; + for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) + { + panel->pct = panel->pct + violation / children_count; + panel->pct = MaxF32(panel->pct, minimum_panel_pct); + } + } - UI_Key panel_box = panel->box; - UI_Key contents_box = panel->contents_box; - UI_Key resizer_box = panel->resizer_box; - UI_Size resizer_size = UI_Px(3, 1); - Vec4 panel_bg = panel->bg; - panel_bg.a *= panel->opacity; + // //- Adjust panel pcts to add to 1 + // f32 children_pct_scale = 1; + // { + // f32 pct_accum = 0; + // for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) + // { + // if (!V_ShouldIgnorePanel(panel)) + // { + // pct_accum += panel->pct; + // } + // } + // children_pct_scale = 1.0 / MinF32(pct_accum, 1); + // } - Vec4 panel_bd = panel->bd; - Vec4 resizer_color = theme.col.divider; - resizer_color.a *= theme.col.panel_resizer_opacity; - panel_bd.a *= theme.col.panel_border_opacity; - // f32 panel_pct = panel->pct; + // // //- Determine scale needed for sum of pcts to reach 1 + // // f32 children_pct_scale = 1; + // // { + // // f32 pct_accum = 0; + // // for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) + // // { + // // if (!V_ShouldIgnorePanel(panel)) + // // { + // // pct_accum += panel->pct; + // // } + // // } + // // children_pct_scale = 1.0 / MaxF32(pct_accum, 0.0001); + // // } - // UI_SetNext(AxisSize, UI_Grow(panel_pct, 1), .axis = parent_axis); - // UI_SetNext(AxisSize, UI_Grow(panel_pct, 0), .axis = parent_axis); - UI_SetNext(AxisSize, UI_Grow(panel->pct, 0), .axis = parent_axis); - // UI_SetNext(AxisSize, UI_Grow(panel->solved_pct * children_pct_scale, 1), .axis = parent_axis); - // UI_SetNext(AxisSize, UI_Px(panel_pct * parent_contents_size_px, 0), .axis = parent_axis); - UI_SetNext(AxisSize, UI_Grow(1, 0), .axis = !parent_axis); - UI_SetNext(ChildLayoutAxis, parent_axis); - UI_PushDF(Tag, panel_box.v) - UI_PushDF(Parent, UI_BuildBoxEx(panel_box)) + + + + + + + //- Build panel boxes + for (V_Panel *panel = parent_panel->first; panel; panel = panel->next) + { + PanelBfs *bfs_panel = PushStruct(frame->arena, PanelBfs); + bfs_panel->panel = panel; + SllQueuePush(first_panel_bfs, last_panel_bfs, bfs_panel); + + UI_Key panel_box = panel->box; + UI_Key contents_box = panel->contents_box; + UI_Key resizer_box = panel->resizer_box; + + UI_Size resizer_size = UI_Px(3, 1); + + Vec4 panel_bg = panel->bg; + panel_bg.a *= panel->opacity; + + Vec4 panel_bd = panel->bd; + + Vec4 resizer_color = theme.col.divider; + resizer_color.a *= theme.col.panel_resizer_opacity; + panel_bd.a *= theme.col.panel_border_opacity; + + // f32 panel_pct = panel->pct; + + // UI_SetNext(AxisSize, UI_Grow(panel_pct, 1), .axis = parent_axis); + // UI_SetNext(AxisSize, UI_Grow(panel_pct, 0), .axis = parent_axis); + UI_SetNext(AxisSize, UI_Grow(panel->pct, 0), .axis = parent_axis); + // UI_SetNext(AxisSize, UI_Grow(panel->solved_pct * children_pct_scale, 1), .axis = parent_axis); + // UI_SetNext(AxisSize, UI_Px(panel_pct * parent_contents_size_px, 0), .axis = parent_axis); + UI_SetNext(AxisSize, UI_Grow(1, 0), .axis = !parent_axis); + UI_SetNext(ChildLayoutAxis, parent_axis); + UI_PushDF(Tag, panel_box.v) + UI_PushDF(Parent, UI_BuildBoxEx(panel_box)) + { + // panel_bd.a = 0; + // resizer_color.a = 0; + + b32 is_screen_panel_box = panel->flags & V_PanelFlag_Screen; + if (is_screen_panel_box || panel->is_organizational) { - // panel_bd.a = 0; - // resizer_color.a = 0; - - b32 is_screen_panel_box = panel->flags & V_PanelFlag_Screen; - if (is_screen_panel_box || panel->is_organizational) - { - panel_bg.a = 0; - panel_bd.a = 0; - resizer_color.a = 0; - } - if (panel->is_organizational) - { - panel_bg.a = 0; - } - - //- Left null-resizer box - // if (!panel->prev && !V_ShouldIgnorePanel(panel->prev)) - // { - // UI_SetNext(AxisSize, resizer_size, .axis = parent_axis); - // UI_SetNext(BackgroundColor, resizer_color); - // UI_BuildBox(); - // } - - //- Panel contents box - { - // UI_SetNext(AxisSize, UI_Grow(panel_pct, 1), .axis = parent_axis); - // UI_SetNext(AxisSize, UI_Grow(1, 0), .axis = !parent_axis); - UI_SetNext(ChildLayoutAxis, panel->axis); - // UI_SetNext(Width, UI_Px(500, 1)); - // UI_SetNext(Height, UI_Px(200, 1)); - UI_SetNext(BackgroundColor, panel_bg); - UI_SetNext(BorderColor, panel_bd); - UI_SetNext(BorderSize, 2); - // UI_SetNext(Rounding, UI_Rpx(10 * theme.rounding)); - UI_SetNext(Flags, UI_BoxFlag_Scissor | (UI_BoxFlag_CaptureMouse * (!is_screen_panel_box && !panel->is_organizational))); - UI_PushDF(Parent, UI_BuildBoxEx(contents_box)) - { - } - } - - - - //- Resizer box - b32 can_resize = panel->next != 0; - if (can_resize) - { - UI_SetNext(AxisSize, resizer_size, .axis = parent_axis); - UI_SetNext(BackgroundColor, resizer_color); - UI_SetNext(Flags, UI_BoxFlag_CaptureMouse * !!can_resize); - UI_BuildBoxEx(resizer_box); - } - - - // //- Overlay box - // { - // // UI_SetNext(AxisSize, resizer_size, .axis = parent_axis); - // // UI_SetNext(AxisSize, UI_Px(100, 1), .axis = parent_axis); - // // UI_SetNext(AxisSize, UI_Px(100, 1), .axis = !parent_axis); - // // UI_SetNext(AxisSize, UI_Grow(1, 1), .axis = !parent_axis); - // // UI_SetNext(AxisSize, UI_Grow(1, 1), .axis = !parent_axis); - // // UI_SetNext(BackgroundColor, Color_Cyan); - // // UI_SetNext(Anchor, UI_Region_Center); - // UI_SetNext(ChildLayoutAxis, parent_axis); - // UI_SetNext(Flags, UI_BoxFlag_Floating); - // UI_SetNext(Parent, contents_box); - // // FIXME: Don't use contents box - // UI_PushDF(Parent, UI_BuildBoxEx(UI_KeyF("overlay box"))) - // { - // UI_SetNext(AxisSize, UI_Grow(1, 0), .axis = parent_axis); - // UI_BuildBox(); - - // //- Resizer box - // if (panel->next) - // { - // UI_SetNext(AxisSize, resizer_size, .axis = parent_axis); - // // UI_SetNext(AxisSize, UI_Px(100, 1), .axis = parent_axis); - // // UI_SetNext(AxisSize, UI_Px(100, 1), .axis = !parent_axis); - // // UI_SetNext(AxisSize, UI_Grow(1, 1), .axis = !parent_axis); - // // UI_SetNext(BackgroundColor, theme.col.divider); - // UI_SetNext(Anchor, UI_Region_Center); - // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); - // UI_BuildBoxEx(resizer_box); - // } - // } - // } + panel_bg.a = 0; + panel_bd.a = 0; + resizer_color.a = 0; } + if (panel->is_organizational) + { + panel_bg.a = 0; + } + + //- Left null-resizer box + // if (!panel->prev && !V_ShouldIgnorePanel(panel->prev)) + // { + // UI_SetNext(AxisSize, resizer_size, .axis = parent_axis); + // UI_SetNext(BackgroundColor, resizer_color); + // UI_BuildBox(); + // } + + //- Panel contents box + { + // UI_SetNext(AxisSize, UI_Grow(panel_pct, 1), .axis = parent_axis); + // UI_SetNext(AxisSize, UI_Grow(1, 0), .axis = !parent_axis); + UI_SetNext(ChildLayoutAxis, panel->axis); + // UI_SetNext(Width, UI_Px(500, 1)); + // UI_SetNext(Height, UI_Px(200, 1)); + UI_SetNext(BackgroundColor, panel_bg); + UI_SetNext(BorderColor, panel_bd); + UI_SetNext(BorderSize, 2); + // UI_SetNext(Rounding, UI_Rpx(10 * theme.rounding)); + UI_SetNext(Flags, UI_BoxFlag_Scissor | (UI_BoxFlag_CaptureMouse * (!is_screen_panel_box && !panel->is_organizational))); + UI_PushDF(Parent, UI_BuildBoxEx(contents_box)) + { + } + } + + + + //- Resizer box + b32 can_resize = panel->next != 0; + if (can_resize) + { + UI_SetNext(AxisSize, resizer_size, .axis = parent_axis); + UI_SetNext(BackgroundColor, resizer_color); + UI_SetNext(Flags, UI_BoxFlag_CaptureMouse * !!can_resize); + UI_BuildBoxEx(resizer_box); + } + + + // //- Overlay box + // { + // // UI_SetNext(AxisSize, resizer_size, .axis = parent_axis); + // // UI_SetNext(AxisSize, UI_Px(100, 1), .axis = parent_axis); + // // UI_SetNext(AxisSize, UI_Px(100, 1), .axis = !parent_axis); + // // UI_SetNext(AxisSize, UI_Grow(1, 1), .axis = !parent_axis); + // // UI_SetNext(AxisSize, UI_Grow(1, 1), .axis = !parent_axis); + // // UI_SetNext(BackgroundColor, Color_Cyan); + // // UI_SetNext(Anchor, UI_Region_Center); + // UI_SetNext(ChildLayoutAxis, parent_axis); + // UI_SetNext(Flags, UI_BoxFlag_Floating); + // UI_SetNext(Parent, contents_box); + // // FIXME: Don't use contents box + // UI_PushDF(Parent, UI_BuildBoxEx(UI_KeyF("overlay box"))) + // { + // UI_SetNext(AxisSize, UI_Grow(1, 0), .axis = parent_axis); + // UI_BuildBox(); + + // //- Resizer box + // if (panel->next) + // { + // UI_SetNext(AxisSize, resizer_size, .axis = parent_axis); + // // UI_SetNext(AxisSize, UI_Px(100, 1), .axis = parent_axis); + // // UI_SetNext(AxisSize, UI_Px(100, 1), .axis = !parent_axis); + // // UI_SetNext(AxisSize, UI_Grow(1, 1), .axis = !parent_axis); + // // UI_SetNext(BackgroundColor, theme.col.divider); + // UI_SetNext(Anchor, UI_Region_Center); + // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); + // UI_BuildBoxEx(resizer_box); + // } + // } + // } } } } @@ -7491,7 +7550,7 @@ void V_TickForever(WaveLaneCtx *lane) f32 h = TweakFloat("Text selection hue", 200, 0, 360); f32 s = TweakFloat("Text selection saturation", 1, 0, 1); f32 v = TweakFloat("Text selection brightness", 0.6, 0, 1); - Vec4 selection_color = SrgbFromHsv(h, s, v); + Vec4 selection_color = SrgbFromHsv(HSV(h, s, v)); // Vec4 selection_color = theme.col.button_active; // selection_color.a = 1; @@ -8260,7 +8319,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(BackgroundColor, bg); UI_SetNext(Rounding, 0); // UI_SetNext(Flags, UI_BoxFlag_Floating); - UI_PushCp(UI_BuildColumnEx(notifs_key)); + UI_PushDF(Parent, UI_BuildColumnEx(notifs_key)) { UI_Push(ChildAlignment, UI_Region_Left); UI_Push(Font, theme.chat_font); @@ -8276,41 +8335,77 @@ void V_TickForever(WaveLaneCtx *lane) opacity = PowF64(((f64)remaining_ns / (f64)duration_ns), fade_curve); } + b32 is_kill_msg = AnyBit(notif->flags, V_NotifFlag_Kill); + UI_SetNext(Tint, 0); UI_SetNext(Width, UI_Shrink(0, 0)); UI_SetNext(Height, UI_Shrink(0, 0)); - UI_PushCp(UI_BuildRow()); + UI_PushDF(Tint, VEC4(1, 1, 1, opacity)) + UI_PushDF(Width, UI_Shrink(0, 0)) + UI_PushDF(Height, UI_Shrink(0, 0)) + UI_PushDF(Parent, UI_BuildRow()) + if (is_kill_msg) { - UI_Push(Tint, VEC4(1, 1, 1, opacity)); - UI_Push(Width, UI_Shrink(0, 0)); - UI_Push(Height, UI_Shrink(0, 0)); + P_Ent *killer = P_EntFromKey(local_frame, notif->killer); + P_Ent *victim = P_EntFromKey(local_frame, notif->victim); + String killer_name = P_StringFromEnt(killer); + String victim_name = P_StringFromEnt(victim); + Vec4 killer_color = P_ColorFromEnt(killer); + Vec4 victim_color = P_ColorFromEnt(victim); + //- Killer name { - String msg = StringF( + UI_SetNext(TextColor, killer_color); + UI_SetNext(Text, StringF(frame->arena, "%F", FmtString(killer_name))); + UI_SetNext(Flags, UI_BoxFlag_DrawText); + UI_BuildRow(); + } + //- Msg text + { + String msg = StringF(frame->arena, " %F ", FmtString(notif->msg)); + UI_SetNext(Text, msg); + UI_SetNext(Font, theme.player_name_font); + UI_SetNext(FontSize, 16); + UI_SetNext(Flags, UI_BoxFlag_DrawText); + UI_BuildRow(); + } + //- Victim name + { + UI_SetNext(TextColor, victim_color); + UI_SetNext(Text, StringF(frame->arena, "%F", FmtString(victim_name))); + UI_SetNext(Flags, UI_BoxFlag_DrawText); + UI_BuildRow(); + } + } + else + { + //- Time + { + String time_msg = StringF( frame->arena, "[%F:%F:%F] ", FmtUint(notif->datetime.hour % 12, .z = 2), FmtUint(notif->datetime.minute, .z = 2), FmtUint(notif->datetime.second, .z = 2) ); - Vec4 col = UI_Top(TextColor); + Vec4 seq_color = UI_Top(TextColor); if (notif->seq % 2 == 0) { - col.x = 0.55; - col.y = 0.52; - col.z = 0.49; + seq_color.x = 0.55; + seq_color.y = 0.52; + seq_color.z = 0.49; } else { - col.x = 0.49; - col.y = 0.52; - col.z = 0.55; + seq_color.x = 0.49; + seq_color.y = 0.52; + seq_color.z = 0.55; } - - UI_SetNext(TextColor, col); - UI_SetNext(Text, msg); + UI_SetNext(TextColor, seq_color); + UI_SetNext(Text, time_msg); UI_SetNext(Flags, UI_BoxFlag_DrawText); UI_BuildRow(); } + //- Msg text { String msg = notif->msg; UI_SetNext(Text, msg); @@ -8318,7 +8413,6 @@ void V_TickForever(WaveLaneCtx *lane) UI_BuildRow(); } } - UI_PopCp(UI_TopCp()); if (notif_idx != 0) { @@ -8326,8 +8420,6 @@ void V_TickForever(WaveLaneCtx *lane) } } } - - UI_PopCp(UI_TopCp()); } } @@ -8645,13 +8737,11 @@ void V_TickForever(WaveLaneCtx *lane) // UI_Size name_sz = UI_Grow(0.75, 0); // UI_Size kills_sz = UI_Grow(0.25, 0); // UI_Size deaths_sz = UI_Grow(0.25, 0); - // UI_Size ping_sz = UI_Grow(0.25, 0); // UI_Size spacing_sz = UI_Fnt(1, 0); UI_Size name_sz = UI_Fnt(10, 0); UI_Size kills_sz = UI_Fnt(10, 0); UI_Size deaths_sz = UI_Fnt(10, 0); - UI_Size ping_sz = UI_Fnt(5, 0); UI_Size spacing_sz = UI_Fnt(1, 0); Enum(BoardRowFlag) @@ -8664,7 +8754,6 @@ void V_TickForever(WaveLaneCtx *lane) BoardRow *next; BoardRowFlag flags; String name; - f32 ping; f32 kills; f32 deaths; }; @@ -8690,7 +8779,6 @@ void V_TickForever(WaveLaneCtx *lane) board_rows_count += 1; String name = P_StringFromEnt(player); row->name = name; - row->ping = player->ping; row->kills = player->kills; row->deaths = player->deaths; } @@ -8790,22 +8878,6 @@ void V_TickForever(WaveLaneCtx *lane) } } UI_PopCp(UI_TopCp()); - UI_BuildDivider(UI_Px(1, 1), theme.col.divider, Axis_X); - - UI_BuildSpacer(spacing_sz, Axis_X); - UI_SetNext(Width, ping_sz); - UI_PushCp(UI_BuildColumn()); // Ping column - { - if (is_header) - { - UI_BuildLabelF("Ping"); - } - else - { - UI_BuildLabelF("%F", FmtFloat(board_row->ping, .p = 2)); - } - } - UI_PopCp(UI_TopCp()); } UI_PopCp(UI_TopCp()); @@ -8884,7 +8956,6 @@ void V_TickForever(WaveLaneCtx *lane) // Name text UI_BuildBox(); } - } } } diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index f3f1ce02..c7358b67 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -156,13 +156,25 @@ Global Readonly V_CmdDesc V_cmd_descs[V_CmdKind_COUNT] = { //////////////////////////////////////////////////////////// //~ Notification types +Enum(V_NotifFlag) +{ + V_NotifFlag_None, + V_NotifFlag_Kill = (1 << 0), +}; + Struct(V_Notif) { V_Notif *next; + + V_NotifFlag flags; + String msg; + + P_EntKey killer; + P_EntKey victim; + DateTime datetime; i64 time_ns; i64 seq; - String msg; }; //////////////////////////////////////////////////////////// @@ -245,7 +257,6 @@ Struct(V_Palette) //////////////////////////////////////////////////////////// //~ Profiler types -// #define V_CollapsedZoneBasis 0x4a06f782d21f18af #define V_MinChunkCapacity 1 Struct(V_Zone) @@ -545,7 +556,7 @@ void V_PushWidgetThemeStyles(V_WidgetTheme theme); //////////////////////////////////////////////////////////// //~ Notification helpers -void V_PushNotif(String msg); +V_Notif *V_PushNotif(String msg); //////////////////////////////////////////////////////////// //~ Vis tick diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 3ee5984d..2c500a9d 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -621,6 +621,10 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags) if (prev_frame->boxes_pre != 0) { ControllerEventsArray controller_events = frame->window_frame.controller_events; + u64 boxes_pre_count = prev_frame->boxes_pre_count; + u64 boxes_post_count = prev_frame->boxes_post_count; + UI_Box **boxes_pre = prev_frame->boxes_pre; + UI_Box **boxes_post = prev_frame->boxes_post; //- Locate boxes UI_Box *prev_top_active_box = UI_BoxFromKey(prev_frame->top_active_box); @@ -639,9 +643,9 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags) } //- Locate hovered box - for (u64 pre_index = UI.boxes_count; pre_index-- > 0;) + for (u64 pre_idx = boxes_pre_count; pre_idx-- > 0;) { - UI_Box *box = prev_frame->boxes_pre[pre_index]; + UI_Box *box = boxes_pre[pre_idx]; UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_CheckCursorHover); //- Reset state { @@ -830,9 +834,9 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags) { f32 lower_target = TweakFloat("UI lower blend target", -0.05, -1, 0); f32 upper_target = TweakFloat("UI upper blend target", 1.05, 1, 10); - for (u64 pre_index = UI.boxes_count; pre_index-- > 0;) + for (u64 pre_idx = boxes_pre_count; pre_idx-- > 0;) { - UI_Box *box = prev_frame->boxes_pre[pre_index]; + UI_Box *box = boxes_pre[pre_idx]; UI_Box *parent = box->parent; UI_Feedback *feedback = &box->feedback; UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_BuildFeedback); @@ -1438,64 +1442,66 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) } ////////////////////////////// - //- Layout + //- Layout prepass - u64 boxes_count = UI.boxes_count; - UI_Box **boxes_pre = PushStructsNoZero(frame->arena, UI_Box *, boxes_count); - UI_Box **boxes_post = PushStructsNoZero(frame->arena, UI_Box *, boxes_count); - frame->boxes_pre = boxes_pre; - frame->boxes_post = boxes_post; - ProfZoneDF("Layout UI") + //- Prepare layout data + ProfZoneDF("Layout prepass") { - //- Prepare layout data - ProfZoneDF("Layout prepass") + frame->boxes_pre_count = 0; + frame->boxes_post_count = 0; + frame->boxes_pre = PushStructsNoZero(frame->arena, UI_Box *, UI.boxes_count); + frame->boxes_post = PushStructsNoZero(frame->arena, UI_Box *, UI.boxes_count); + for (UI_BoxIterResult ir = UI_FirstBox(scratch.arena, &box_iter, UI_RootKey); ir.box; ir = UI_NextBox(scratch.arena, &box_iter)) { - u64 pre_index = 0; - u64 post_index = 0; - for (UI_BoxIterResult ir = UI_FirstBox(scratch.arena, &box_iter, UI_RootKey); ir.box; ir = UI_NextBox(scratch.arena, &box_iter)) + UI_Box *box = ir.box; + if (ir.pre) { - UI_Box *box = ir.box; - if (ir.pre) + UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_PrepLayout); + + box->pre_idx = frame->boxes_pre_count; + frame->boxes_pre[box->pre_idx] = box; + frame->boxes_pre_count += 1; + + // Reset layout data + box->cursor = 0; + box->final_children_size_accum = VEC2(0, 0); + box->solved_dims = VEC2(0, 0); + + // Solve scale { - UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_PrepLayout); - - box->pre_index = pre_index; - boxes_pre[pre_index] = box; - pre_index += 1; - - // Reset layout data - box->cursor = 0; - box->final_children_size_accum = VEC2(0, 0); - box->solved_dims = VEC2(0, 0); - - // Solve scale & opacity + UI_Box *parent = box->parent; + box->solved_scale = box->desc.scale; + if (parent) { - UI_Box *parent = box->parent; - box->solved_opacity = box->desc.opacity; - box->solved_scale = box->desc.scale; - if (parent) - { - box->solved_opacity = parent->solved_opacity * box->solved_opacity; - box->solved_scale = MulVec2Vec2(parent->solved_scale, box->solved_scale); - } + box->solved_scale = MulVec2Vec2(parent->solved_scale, box->solved_scale); } } - else - { - box->post_index = post_index; - boxes_post[post_index] = box; - post_index += 1; - } } - Assert(pre_index == boxes_count); - Assert(post_index == boxes_count); + else + { + box->post_idx = frame->boxes_post_count; + frame->boxes_post[box->post_idx] = box; + frame->boxes_post_count += 1; + } } + Assert(frame->boxes_pre_count == UI.boxes_count); + Assert(frame->boxes_post_count == UI.boxes_count); + } + u64 boxes_pre_count = frame->boxes_pre_count; + u64 boxes_post_count = frame->boxes_post_count; + UI_Box **boxes_pre = frame->boxes_pre; + UI_Box **boxes_post = frame->boxes_post; + ////////////////////////////// + //- Layout + + ProfZoneDF("Layout UI") + { //- Solve independent sizes ProfZoneDF("Solve independent sizes") - for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) + for (u64 pre_idx = 0; pre_idx < boxes_pre_count; ++pre_idx) { - UI_Box *box = boxes_pre[pre_index]; + UI_Box *box = boxes_pre[pre_idx]; UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_IndependentSolve); for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) { @@ -1550,9 +1556,9 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) //- Solve upwards-dependent sizes along layout axis ProfZoneDF("Solve upwards-dependent sizes (along layout-axis)") - for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) + for (u64 pre_idx = 0; pre_idx < boxes_pre_count; ++pre_idx) { - UI_Box *box = boxes_pre[pre_index]; + UI_Box *box = boxes_pre[pre_idx]; UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis); if (box->parent) { @@ -1588,9 +1594,9 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) //- Solve downwards-dependent sizes ProfZoneDF("Solve downwards-dependent sizes") - for (u64 post_index = 0; post_index < boxes_count; ++post_index) + for (u64 post_idx = 0; post_idx < boxes_post_count; ++post_idx) { - UI_Box *box = boxes_post[post_index]; + UI_Box *box = boxes_post[post_idx]; UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_DownwardsDependentSolve); for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) { @@ -1621,9 +1627,9 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) //- Solve upwards-dependent sizes along non-layout axis ProfZoneDF("Solve upwards-dependent sizes (along non-layout-axis)") - for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) + for (u64 pre_idx = 0; pre_idx < boxes_pre_count; ++pre_idx) { - UI_Box *box = boxes_pre[pre_index]; + UI_Box *box = boxes_pre[pre_idx]; UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis); if (box->parent) { @@ -1638,9 +1644,9 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) //- Solve violations ProfZoneDF("Solve violations") - for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) + for (u64 pre_idx = 0; pre_idx < boxes_pre_count; ++pre_idx) { - UI_Box *box = boxes_pre[pre_index]; + UI_Box *box = boxes_pre[pre_idx]; UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_SolveViolations); for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) { @@ -1722,9 +1728,9 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) //- Solve final positions ProfZoneDF("Solve final screen positions") - for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) + for (u64 pre_idx = 0; pre_idx < boxes_pre_count; ++pre_idx) { - UI_Box *box = boxes_pre[pre_index]; + UI_Box *box = boxes_pre[pre_idx]; UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_FinalSolve); UI_Box *parent = box->parent; @@ -1962,17 +1968,16 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) //- Build render data // Build GPU rect data - ProfZoneDF("Build GPU rects") - for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) + for (u64 pre_idx = 0; pre_idx < boxes_pre_count; ++pre_idx) { - UI_Box *box = boxes_pre[pre_index]; + UI_Box *box = boxes_pre[pre_idx]; UI_ExecuteDebugBreak(box, UI_DebugBreakFlag_BuildGpuData); GC_Run raw_run_unscaled = box->glyph_run; GC_Run raw_run = UI_ScaleRun(frame->arena, raw_run_unscaled, box->solved_scale); Vec4 final_tint_lin = LinearFromSrgb(box->desc.tint); - final_tint_lin.a *= box->solved_opacity; + final_tint_lin.a *= box->desc.opacity; Vec4 final_border_color_lin = LinearFromSrgb(box->desc.border_color); @@ -2011,7 +2016,6 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) UI_AxisRegion y_alignment = child_alignment.v[Axis_Y]; // Box rect - ProfZoneDF("GPU box rect") { UI_GpuRect *rect = PushStruct(frame->rects_arena, UI_GpuRect); rect->bounds = box->screen_rect; @@ -2044,7 +2048,6 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) // Text rects if (should_upload_text || AnyBit(frame->frame_flags, UI_FrameFlag_Debug)) - ProfZoneDF("GPU text rects") { f32 max_baseline_length = CeilF32(DimsFromRng2(box->screen_rect).x); b32 should_truncate = FloorF32(raw_run.baseline_length) > max_baseline_length && !AnyBit(box->desc.flags, UI_BoxFlag_DontTruncateText); diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 328164e8..7e99718b 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -374,12 +374,9 @@ Struct(UI_Box) GC_Run glyph_run; SPR_Sprite sprite; - //- Pre-layout data - u64 pre_index; - u64 post_index; - //- Layout data - f32 solved_opacity; + u64 pre_idx; + u64 post_idx; Vec2 solved_scale; Rng2 solved_scissor; Vec2 final_children_size_accum; @@ -476,6 +473,8 @@ Struct(UI_Frame) UI_StyleNode *first_free_style_node; // Layout + u64 boxes_pre_count; + u64 boxes_post_count; UI_Box **boxes_pre; UI_Box **boxes_post; };