From 246f63a61f2fd391ff716efe16e4d8a26d2ceb79 Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 30 Mar 2026 20:54:55 -0500 Subject: [PATCH] propagate child UI captures upwards in tree --- src/base/base_controller.h | 3 +- src/pp/pp_sim/pp_sim_core.c | 1 + src/pp/pp_vis/pp_vis_core.c | 774 ++++++++++++++++++++++++++++++++---- src/pp/pp_vis/pp_vis_core.h | 23 +- src/ui/ui_core.c | 144 ++++--- src/ui/ui_core.h | 58 +-- src/ui/ui_extras.h | 3 - 7 files changed, 844 insertions(+), 162 deletions(-) diff --git a/src/base/base_controller.h b/src/base/base_controller.h index f4c27d82..f9bfb2fb 100644 --- a/src/base/base_controller.h +++ b/src/base/base_controller.h @@ -132,6 +132,7 @@ Enum(ControllerEventKind) Struct(ControllerEvent) { ControllerEventKind kind; + i32 captures; // ControllerEventKind_ButtonDown // ControllerEventKind_ButtonUp @@ -162,4 +163,4 @@ Struct(ControllerEventsArray) String StringFromButton(Button button); b32 IsClickButton(Button button); b32 IsWheelButton(Button button); -b32 IsouseButton(Button button); +b32 IsMouseButton(Button button); diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 1073135d..7eb1150c 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -924,6 +924,7 @@ void S_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Publish Sim -> User data + ProfZoneDF("Publish Sim -> User") { LockTicketMutex(&P.s2v_tm); { diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index df42b14a..efd5864c 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -1208,9 +1208,14 @@ void V_TickForever(WaveLaneCtx *lane) String text = cev->kind == ControllerEventKind_Text ? STRING(cev->text_chars_count, cev->text_chars) : STRING(0, 0); b32 ignore = 0; + if (cev->captures > 0 && !frame->has_mouse_focus) + { + ignore = 1; + } + if (down) { - if (cev->button == Button_M1 || cev->button == Button_M2 || cev->button == Button_M3) + if (cev->button == Button_M1 || cev->button == Button_M2 || cev->button == Button_M3) { if (!frame->has_mouse_focus) { @@ -3895,7 +3900,7 @@ void V_TickForever(WaveLaneCtx *lane) { V_Window *window = tab->window; { - if (tab_rep.m1.downs > 0) + if (tab_rep.buttons[Button_M1].downs > 0) { new_active_window_idx = tab->window_idx; } @@ -3903,7 +3908,7 @@ void V_TickForever(WaveLaneCtx *lane) if (V.dragging_window == 0) { f32 drag_threshold = 20; - if (tab_rep.m1.held) + if (tab_rep.buttons[Button_M1].held) { Vec2 drag_start = ui_frame->drag_cursor_pos; if (Vec2Len(SubVec2(frame->screen_cursor, drag_start)) > drag_threshold) @@ -3914,7 +3919,7 @@ void V_TickForever(WaveLaneCtx *lane) } b32 is_dragging = window == V.dragging_window; - if (is_dragging && tab_rep.m1.ups > 0) + if (is_dragging && tab_rep.buttons[Button_M1].ups > 0) { V.dragging_window = 0; } @@ -3999,7 +4004,7 @@ void V_TickForever(WaveLaneCtx *lane) } UI_PopCp(UI_TopCp()); - if (close_rep.m1.presses) + if (close_rep.buttons[Button_M1].presses) { prune_windows[prune_windows_count] = window; prune_windows_count += 1; @@ -4108,7 +4113,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_Key key = UI_KeyF("Tile %F", FmtString(tile_name)); UI_BoxReport rep = UI_ReportsFromKey(key).draw; - if (rep.m1.downs) + if (rep.buttons[Button_M1].downs) { frame->edit_mode = V_EditMode_Tile; frame->equipped_tile = tile_kind; @@ -4182,7 +4187,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_Key key = UI_KeyF("Prefab %F", FmtString(prefab_name)); UI_BoxReport rep = UI_ReportsFromKey(key).draw; - if (rep.m1.downs) + if (rep.buttons[Button_M1].downs) { frame->edit_mode = V_EditMode_Prefab; frame->equipped_prefab = prefab_kind; @@ -4281,7 +4286,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(AxisSize, UI_PIX(divider_size, 1), .axis = !panel->axis); UI_BuildBoxEx(panel->divider_key); - if (rep.is_hot || rep.m1.held) + if (rep.is_hot || rep.buttons[Button_M1].held) { if (panel->axis == Axis_X) { @@ -4293,7 +4298,7 @@ void V_TickForever(WaveLaneCtx *lane) } } - if (rep.m1.held) + if (rep.buttons[Button_M1].held) { panel->resizing = 1; } @@ -4364,6 +4369,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_Size item_col_width = UI_FNT(30, 1); // UI_Size col2_width = UI_FNT(10, 1); UI_Size scrollbar_width = UI_FNT(1, 1); + f32 item_size_px = UI_FNT(1.5, 1).v; UI_Key scissor_key = UI_KeyF("scissor"); UI_Key lister_key = UI_KeyF("lister"); @@ -4397,9 +4403,11 @@ void V_TickForever(WaveLaneCtx *lane) f32 thumb_end = thumb_reps.draw.screen_rect.p1.y; f32 thumb_height = MaxF32(thumb_end - thumb_start, 1); + f32 wheel_scroll_amount = item_size_px * 2; f32 scroll_height = MaxF32(lister_height - scissor_height, 1); { - if (thumb_reps.draw.m1.downs) + i32 wheels = lister_reps.draw.buttons[Button_WheelDown].downs - lister_reps.draw.buttons[Button_WheelUp].downs; + if (thumb_reps.draw.buttons[Button_M1].downs) { palette->drag_lister = lister_reps.draw.screen_rect; palette->drag_scissor = scissor_reps.draw.screen_rect; @@ -4409,7 +4417,7 @@ void V_TickForever(WaveLaneCtx *lane) palette->drag_scroll = palette->scroll; } - if (thumb_reps.draw.m1.held) + if (thumb_reps.draw.buttons[Button_M1].held) { f32 drag_track_height = palette->drag_track.p1.y - palette->drag_track.p0.y; f32 drag_thumb_height = palette->drag_thumb.p1.y - palette->drag_thumb.p0.y; @@ -4417,6 +4425,7 @@ void V_TickForever(WaveLaneCtx *lane) f32 delta_ratio = (frame->screen_cursor.y - palette->drag_cursor.y) / (drag_track_height - drag_thumb_height); palette->scroll = palette->drag_scroll + delta_ratio * drag_scroll_height; } + palette->scroll += wheels * wheel_scroll_amount; palette->scroll = ClampF32(palette->scroll, 0, scroll_height); } @@ -4439,7 +4448,6 @@ void V_TickForever(WaveLaneCtx *lane) if (palette->is_showing || palette->show > 0.001) { - f32 item_size_px = UI_FNT(1.5, 1).v; f32 tweak_size_px = UI_FNT(1.25, 1).v; palette->key = UI_KeyF("command palette"); @@ -4455,7 +4463,7 @@ void V_TickForever(WaveLaneCtx *lane) Vec4 titlebar_color = Zi; Vec4 titlebar_border_color = Zi; Vec4 divider_color = theme.col.divider; - if (titlebar_reps.draw.m1.held) + if (titlebar_reps.draw.buttons[Button_M1].held) { Vec2 drag_offset = SubVec2(ui_frame->drag_cursor_pos, palette_reps.drag.screen_anchor); palette->pos = SubVec2(frame->screen_cursor, drag_offset); @@ -4575,8 +4583,8 @@ void V_TickForever(WaveLaneCtx *lane) // FIXME: Remove this has_focus = 1; - // if (search_report.m1.downs) - if (search_report.m1.downs) + // if (search_report.buttons[Button_M1].downs) + if (search_report.buttons[Button_M1].downs) { has_focus = 1; V.text_input_ns = frame->time_ns; @@ -4788,7 +4796,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(Width, UI_GROW(1, 0)); UI_SetNext(Height, UI_SHRINK(0, 1)); UI_SetNext(FloatingPos, VEC2(0, -lister_offset)); - UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClampY); + UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClampY | UI_BoxFlag_CaptureMouse | UI_BoxFlag_CaptureThroughChildren); UI_PushCp(UI_BuildRowEx(lister_key)); { UI_SetNext(Tint, 0); @@ -4895,7 +4903,7 @@ void V_TickForever(WaveLaneCtx *lane) } UI_BoxReport item_rep = UI_ReportsFromKey(item->key).draw; - if (item_rep.m1.presses) + if (item_rep.buttons[Button_M1].presses) { if (item->flags & PaletteItemFlag_IsCmd) { @@ -4963,7 +4971,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_Key reset_key = UI_KeyF("reset"); UI_BoxReport reset_rep = UI_ReportsFromKey(reset_key).draw; - if (reset_rep.m1.downs > 0) + if (reset_rep.buttons[Button_M1].downs > 0) { new_tweak_str = tweak_var.initial; } @@ -5029,7 +5037,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_BoxReport cb_rep = UI_ReportsFromKey(cb_key).draw; b32 tweak_bool = CR_BoolFromString(new_tweak_str); - if (cb_rep.m1.downs) + if (cb_rep.buttons[Button_M1].downs) { tweak_bool = !tweak_bool; new_tweak_str = StringFromBool(frame->arena, tweak_bool); @@ -5064,7 +5072,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_BoxReports marker_reps = UI_ReportsFromKey(marker_key); b32 is_hot = slider_reps.draw.is_hot || marker_reps.draw.is_hot; - b32 is_active = slider_reps.draw.m1.held || marker_reps.draw.m1.held; + b32 is_active = slider_reps.draw.buttons[Button_M1].held || marker_reps.draw.buttons[Button_M1].held; f32 hot = MaxF32(slider_reps.draw.hot, marker_reps.draw.hot); Vec2 slider_pos = slider_reps.draw.screen_rect.p0; @@ -5347,11 +5355,11 @@ void V_TickForever(WaveLaneCtx *lane) // // ratio = (tweak_float - range_min) / (range_max - range_min); // // ratio = ClampF32(ratio, 0, 1); - // if (thumb_reps.draw.m1.downs) + // if (thumb_reps.draw.buttons[Button_M1].downs) // { // palette->scroll_begin = palette->scroll; // } - // if (thumb_reps.draw.m1.held) + // if (thumb_reps.draw.buttons[Button_M1].held) // { // palette->scroll = palette->scroll_begin + (frame->screen_cursor.y - ui_frame->drag_cursor_pos.y); // } @@ -5417,11 +5425,6 @@ void V_TickForever(WaveLaneCtx *lane) - - - - - ////////////////////////////// //- Build profiler @@ -5430,11 +5433,30 @@ void V_TickForever(WaveLaneCtx *lane) V_Profiler *profiler = &frame->profiler; + profiler->ns_per_px = MaxI64(profiler->ns_per_px, 1); UI_Key profiler_graph_box = UI_KeyF("graph"); + UI_PushDF(OmitFlags, UI_BoxFlag_CaptureMouse * !!(frame->is_looking)) if (TweakBool("Show profiler", 1)) { profiler->is_showing = 1; + + + + // FIXME: Remove this + + i64 highest_current_sample_ns = NsFromSeconds(10); + + + + + + + if (frame->tick == 1) + { + profiler->ns_per_px = NsFromSeconds(0.010); + } + UI_BoxReports profiler_graph_reports = UI_ReportsFromKey(profiler_graph_box); profiler->graph_dims = DimsFromRng2(profiler_graph_reports.draw.screen_rect); @@ -5500,20 +5522,115 @@ void V_TickForever(WaveLaneCtx *lane) UI_Size profiler_height = UI_FNT(40, 1); UI_Size header_height = UI_FNT(2, 1); UI_Size window_padding = UI_FNT(0.5, 1); - UI_Size graph_height = UI_GROW(0.25, 0); + // UI_Size graph_height = UI_GROW(0.25, 0); + UI_Size graph_height = UI_FNT(2, 1); UI_Size main_height = UI_GROW(1, 0); UI_Size zone_height = UI_FNT(0.75, 0); + UI_Size track_height = UI_FNT(4, 0); - UI_BoxReport main_rep = UI_ReportsFromKey(main_box).draw; + UI_BoxReports main_reps = UI_ReportsFromKey(main_box); - Vec2 last_main_dims = DimsFromRng2(main_rep.screen_rect); - last_main_dims.x = MaxF32(last_main_dims.x, 1); - last_main_dims.y = MaxF32(last_main_dims.y, 1); - i64 view_start_ns = NsFromSeconds(0); - i64 view_end_ns = NsFromSeconds(10); + // Vec2 old_main_dims = DimsFromRng2(main_reps.draw.screen_rect); + // old_main_dims.x = MaxF32(old_main_dims.x, 1); + // old_main_dims.y = MaxF32(old_main_dims.y, 1); - f64 ns_per_px = MaxF64((view_end_ns - view_start_ns) / last_main_dims.x, 1); + + + // if (profiler->view_start_ns == 0 && profiler->view_end_ns == 0) + // { + // profiler->view_start_ns = NsFromSeconds(0); + // profiler->view_end_ns = NsFromSeconds(10); + // } + + + // f32 old_cursor_offset_px = frame->screen_cursor.x - main_reps.draw.screen_rect.p0.x; + // i64 old_cursor_offset_ns = (old_cursor_offset_px / old_main_dims.x) * (profiler->view_end_ns - profiler->view_start_ns); + // i64 old_cursor_ns = profiler->view_start_ns + old_cursor_offset_ns; + + f32 cursor_px = frame->screen_cursor.x - main_reps.draw.screen_rect.p0.x; + i64 cursor_ns = (cursor_px * profiler->ns_per_px) + profiler->view_ns; + f32 view_offset_px = profiler->view_ns / profiler->ns_per_px; + + + + + + + + + + + // FIXME: Remove this + f32 prof_zoom_rate = 1.5; + + + + i32 zooms = main_reps.draw.buttons[Button_WheelDown].presses - main_reps.draw.buttons[Button_WheelUp].presses; + f32 zoom_factor = PowF32(prof_zoom_rate, zooms); + + profiler->ns_per_px *= zoom_factor; + + // profiler->view_ns -= (cursor_ns - profiler->view_ns) / zoom_factor; + profiler->view_ns = cursor_ns - (cursor_ns - profiler->view_ns) * zoom_factor; + + + + + + + + + + // if (profiler->is_dragging && !prev_frame->profiler.is_dragging) + // { + // profiler->drag_view_ns = profiler->view_ns; + // profiler->drag_cursor_px = cursor_px; + // } + + // if (profiler->is_dragging) + // { + // profiler->view_ns = profiler->drag_view_ns - ((cursor_px - profiler->drag_cursor_px) * profiler->ns_per_px); + // } + + + + + // FIXME: Recalc cursor after zoom + + + + + if (main_reps.draw.buttons[Button_M3].downs) + { + profiler->drag_view_ns = profiler->view_ns; + profiler->drag_cursor_px = cursor_px; + } + + if (main_reps.draw.buttons[Button_M3].held) + { + profiler->view_ns = profiler->drag_view_ns - ((cursor_px - profiler->drag_cursor_px) * profiler->ns_per_px); + } + + + + + + + + + // FIXME: Remove this + b32 do_break = frame->real_held_buttons[Button_B] && !prev_frame->real_held_buttons[Button_B]; + + + + + + + + + + // f64 ns_per_px = MaxF64((profiler->view_end_ns - profiler->view_start_ns) / old_main_dims.x, 1); Vec4 profiler_color = theme.col.window_bg; profiler_color.a = 1; @@ -5524,6 +5641,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(BackgroundColor, profiler_color); UI_SetNext(Rounding, UI_RPIX(10 * theme.rounding)); UI_SetNext(Height, profiler_height); + UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); UI_PushDF(Width, UI_GROW(1, 0)) UI_PushDF(Parent, UI_BuildColumnEx(profiler_box)) UI_PushDF(Parent, UI_BuildRow()) @@ -5537,7 +5655,7 @@ void V_TickForever(WaveLaneCtx *lane) // UI_SetNext(BorderSize, 1); UI_SetNext(ChildAlignment, UI_Region_Center); UI_PushDF(Height, header_height) - UI_PushDF(Parent, UI_BuildBoxF("profiler header")) + UI_PushDF(Parent, UI_BuildBoxEx(UI_KeyF("profiler header"))) { UI_PushDF(TextColor, theme.col.hint) UI_BuildLabelF("Profiler"); @@ -5553,13 +5671,50 @@ void V_TickForever(WaveLaneCtx *lane) UI_BuildDivider(UI_PIX(1, 1), theme.col.divider, Axis_Y); //- Main + if (do_break) + { + UI_SetNext(DebugBreakFlags, UI_DebugBreakFlag_BuildReport); + UI_SetNext(Text, Lit("MAIN")); + } UI_SetNext(Height, main_height); - UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); - UI_PushDF(Parent, UI_BuildRowEx(main_box)) + UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_CaptureThroughChildren); + UI_PushDF(Parent, UI_BuildColumnEx(main_box)) { + + // FIXME: Remove this + // Struct(V_ZoneDesc) + // { + // Vec4 color; + // i64 start_ns; + // i64 end_ns; + // }; + + // u64 zones_count = 64; + // V_ZoneDesc *zones = PushStructs(frame->arena, V_ZoneDesc, zones_count); + // for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) + // { + // V_ZoneDesc *zone = &zones[zone_idx]; + + // // zone->color = VEC4(0.5, 0.2, 0.2, 0.5); + // // zone->color.r += 0.5 * Norm24(MixU64(zone_idx)); + + // u64 seed0 = MixU64(zone_idx + 1); + // u64 seed1 = MixU64(seed0); + // u64 seed2 = MixU64(seed1); + // u64 seed3 = MixU64(seed2); + + // zone->color = VEC4(Norm24(seed0), Norm24(seed1), Norm24(seed2), 1); + // zone->color.r += (1.0 - zone->color.r) * 0.25; + + // zone->start_ns = NsFromSeconds(zone_idx * 2); + // zone->end_ns = NsFromSeconds(zone_idx * 2 + 1); + // }; + + + Struct(V_ZoneDesc) { Vec4 color; @@ -5567,49 +5722,179 @@ void V_TickForever(WaveLaneCtx *lane) i64 end_ns; }; - u64 zones_count = 64; - V_ZoneDesc *zones = PushStructs(frame->arena, V_ZoneDesc, zones_count); - for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) + u32 tracks_count = Atomic32Fetch(&Prof.tracks_count); + for (u64 track_idx = 0; track_idx < tracks_count; ++track_idx) { - V_ZoneDesc *zone = &zones[zone_idx]; - zone->color = VEC4(0.5, 0.2, 0.2, 0.5); - zone->start_ns = NsFromSeconds(zone_idx * 2); - zone->end_ns = NsFromSeconds(zone_idx * 2 + 1); - }; - - //- Zones - for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) - { - V_ZoneDesc *zone = &zones[zone_idx]; - - UI_Key zone_box = UI_KeyF("Zone %F", FmtUint(zone_idx)); - // UI_BoxReport zone_rep = UI_ReportFromKey(zone_box).draw; - - Vec4 zone_color = zone->color; - - // Vec4 zone_color_bd = Zi; - // zone_color_bd - - i64 zone_len_ns = zone->end_ns - zone->start_ns; - f32 zone_len_px = zone_len_ns / ns_per_px; - // i6 - - f32 zone_offset_px = (zone->start_ns - view_start_ns) / ns_per_px; - Vec2 zone_pos = VEC2(zone_offset_px, 0); - UI_Size zone_width = UI_PIX(zone_len_px, 1); - - // UI_Report - - - UI_SetNext(Width, zone_width); - UI_SetNext(Height, zone_height); - UI_SetNext(BackgroundColor, zone_color); - UI_SetNext(FloatingPos, zone_pos); - UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClampX | UI_BoxFlag_NoFloatingClampY); - UI_PushDF(Parent, UI_BuildBoxEx(zone_box)) + UI_Key track_box = UI_KeyF("track %F", FmtUint(track_idx)); + UI_SetNext(Height, track_height); + // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); + UI_PushDF(Tag, track_box.v) + UI_PushDF(Parent, UI_BuildRowEx(track_box)) { + ProfTrack *track = Prof.tracks[track_idx]; + + // u64 zones_count = 64; + // V_ZoneDesc *zones = PushStructs(frame->arena, V_ZoneDesc, zones_count); + // for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) + // { + // V_ZoneDesc *zone = &zones[zone_idx]; + + // // zone->color = VEC4(0.5, 0.2, 0.2, 0.5); + // // zone->color.r += 0.5 * Norm24(MixU64(zone_idx)); + + // u64 seed0 = MixU64(zone_idx + 1); + // u64 seed1 = MixU64(seed0); + // u64 seed2 = MixU64(seed1); + // u64 seed3 = MixU64(seed2); + + // zone->color = VEC4(Norm24(seed0), Norm24(seed1), Norm24(seed2), 1); + // zone->color.r += (1.0 - zone->color.r) * 0.25; + + // zone->start_ns = NsFromSeconds(zone_idx * 2); + // zone->end_ns = NsFromSeconds(zone_idx * 2 + 1); + // }; + + + + + + // // Binary search to find samples range + // // FIXME: Atomic + // ProfSample *samples = track->samples; + // u64 samples_start_seq = track->top_sample_seq - MinU64(track->top_sample_seq, ProfTrackSamplesCap); + // u64 samples_end_seq = track->new_sample_seq; + // { + // // i64 search_seq = samples_start_seq + (samples_end_seq - samples_start_seq) / 2; + // i64 search_start_seq = samples_start_seq; + // i64 search_end_seq = samples_end_seq; + // while (search_end_seq > search_start_seq) + // { + // if (samples[search_start_seq % ProfTrackSamplesCap]. + // } + // samples_start_seq = search_start_seq; + // } + + + + + + + + // FIXME: Atomic + ProfSample *samples = track->samples; + u64 samples_start_seq = track->top_sample_seq - MinU64(track->top_sample_seq, ProfTrackSamplesCap); + u64 samples_end_seq = track->top_sample_seq; + + + + + + + + + + + + u64 zones_count = samples_end_seq - samples_start_seq; + + zones_count = MinU64(zones_count, 100); + + V_ZoneDesc *zones = PushStructs(frame->arena, V_ZoneDesc, zones_count); + for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) + { + V_ZoneDesc *zone = &zones[zone_idx]; + + ProfSample *sample = &samples[samples_start_seq % ProfTrackSamplesCap]; + + // zone->color = VEC4(0.5, 0.2, 0.2, 0.5); + // zone->color.r += 0.5 * Norm24(MixU64(zone_idx)); + + u64 seed0 = MixU64(zone_idx + 1); + u64 seed1 = MixU64(seed0); + u64 seed2 = MixU64(seed1); + u64 seed3 = MixU64(seed2); + + zone->color = VEC4(Norm24(seed0), Norm24(seed1), Norm24(seed2), 1); + zone->color.r += (1.0 - zone->color.r) * 0.25; + + zone->start_ns = NsFromSeconds(zone_idx * 2); + zone->end_ns = NsFromSeconds(zone_idx * 2 + 1); + + // zone->start_ns = NsFromProfStamp(sample->stamp); + // zone->end_ns = zone->start_ns + NsFromSeconds(0.100); + }; + + + + + + + + + //- Zones + for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) + { + V_ZoneDesc *zone = &zones[zone_idx]; + + UI_Key zone_box = UI_KeyF("Zone %F", FmtUint(zone_idx)); + UI_BoxReport zone_rep = UI_ReportsFromKey(zone_box).draw; + + Vec4 zone_color = zone->color; + + // Vec4 zone_color_bd = Zi; + // zone_color_bd + + i64 zone_len_ns = zone->end_ns - zone->start_ns; + f32 zone_len_px = zone_len_ns / profiler->ns_per_px; + // i6 + + f32 zone_offset_px = (zone->start_ns - profiler->view_ns) / profiler->ns_per_px; + Vec2 zone_pos = VEC2(zone_offset_px, 0); + UI_Size zone_width = UI_PIX(zone_len_px, 1); + + + if (do_break && zone_rep.is_hovered) + { + UI_SetNext(DebugBreakFlags, UI_DebugBreakFlag_BuildReport); + UI_SetNext(Text, StringF(frame->arena, "ZONE %F", FmtUint(zone_idx))); + } + + + + UI_SetNext(Width, zone_width); + UI_SetNext(Height, zone_height); + UI_SetNext(BackgroundColor, zone_color); + UI_SetNext(FloatingPos, zone_pos); + UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClampX | UI_BoxFlag_NoFloatingClampY | UI_BoxFlag_CaptureMouse); + UI_PushDF(Parent, UI_BuildBoxEx(zone_box)) + { + } + } } } + + + + + + + + + + //- Timeline cursor + { + // Vec2 timeline_cursor_pos = VEC2(old_cursor_offset_px, 0); + Vec2 timeline_cursor_pos = VEC2((cursor_ns - profiler->view_ns) / profiler->ns_per_px, 0); + Vec4 timeline_cursor_color = theme.col.window_bd; + timeline_cursor_color.a = main_reps.draw.hot; + + UI_SetNext(Width, UI_FNT(0.15, 1)); + UI_SetNext(Height, UI_GROW(1, 0)); + UI_SetNext(BackgroundColor, timeline_cursor_color); + UI_SetNext(FloatingPos, timeline_cursor_pos); + UI_SetNext(Flags, UI_BoxFlag_Floating); + UI_BuildBox(); + } } } @@ -5618,6 +5903,341 @@ void V_TickForever(WaveLaneCtx *lane) } } + + + + + + + + + + + + + + + + + + + + + + // ////////////////////////////// + // //- Build profiler + + + // // FIXME: Finalize + + + // V_Profiler *profiler = &frame->profiler; + // UI_Key profiler_graph_box = UI_KeyF("graph"); + // UI_PushDF(OmitFlags, UI_BoxFlag_CaptureMouse * !!(frame->is_looking)) + // if (TweakBool("Show profiler", 1)) + // { + // profiler->is_showing = 1; + + // UI_BoxReports profiler_graph_reports = UI_ReportsFromKey(profiler_graph_box); + // profiler->graph_dims = DimsFromRng2(profiler_graph_reports.draw.screen_rect); + + // //- Init test samples + // // // FIXME: Remove this + // // Struct(SampleState) + // // { + // // i64 ready_samples_count; + // // Arena *samples_arena; + // // }; + // // Struct(Sample) + // // { + // // u64 zone_id; + // // u64 thread_id; + // // i64 start_ns; + // // i64 end_ns; + // // }; + // // PERSIST i64 sample_states_count = 1; + // // PERSIST SampleState *sample_states = 0; + // // if (!sample_states) + // // { + // // sample_states = PushStructs(perm, SampleState, sample_states_count); + // // for (i64 sample_state_idx = 0; sample_state_idx < sample_states_count; ++sample_state_idx) + // // { + // // SampleState *ss = &sample_states[sample_state_idx]; + // // ss->samples_arena = AcquireArena(Gibi(64)); + + + + + + + // // ss->ready_samples_count = 128; + // // for (i64 sample_idx = 0; sample_idx < ss->ready_samples_count; ++sample_idx) + // // { + // // Sample *sample = PushStruct(ss->samples_arena, Sample); + // // sample->zone_id = (u64)"Hello there"; + // // sample->thread_id = 0; + // // sample->start_ns = NsFromSeconds(sample_idx); + // // sample->end_ns = NsFromSeconds(sample_idx + 1); + // // } + // // } + // // } + + + // // FIXME: Remove this + // { + // V_ProfilerFrame *pf = &V.profiler_frames[V.profiler_frame_seq % V_ProfilerFramesCap]; + // V.profiler_frame_seq += 1; + // } + + + + + + // //- Build profiler + // UI_Key profiler_box = UI_KeyF("profiler"); + // UI_PushDF(Tag, profiler_box.v) + // UI_PushDF(Parent, profiler_box) + // { + // UI_Key main_box = UI_KeyF("main"); + + // UI_Size profiler_height = UI_FNT(40, 1); + // UI_Size header_height = UI_FNT(2, 1); + // UI_Size window_padding = UI_FNT(0.5, 1); + // // UI_Size graph_height = UI_GROW(0.25, 0); + // UI_Size graph_height = UI_FNT(2, 1); + // UI_Size main_height = UI_GROW(1, 0); + // UI_Size zone_height = UI_FNT(0.75, 0); + + // UI_BoxReports main_reps = UI_ReportsFromKey(main_box); + + + // Vec2 old_main_dims = DimsFromRng2(main_reps.draw.screen_rect); + // old_main_dims.x = MaxF32(old_main_dims.x, 1); + // old_main_dims.y = MaxF32(old_main_dims.y, 1); + + + + // if (profiler->view_start_ns == 0 && profiler->view_end_ns == 0) + // { + // profiler->view_start_ns = NsFromSeconds(0); + // profiler->view_end_ns = NsFromSeconds(10); + // } + + + // f32 old_cursor_offset_px = frame->screen_cursor.x - main_reps.draw.screen_rect.p0.x; + // i64 old_cursor_offset_ns = (old_cursor_offset_px / old_main_dims.x) * (profiler->view_end_ns - profiler->view_start_ns); + // i64 old_cursor_ns = profiler->view_start_ns + old_cursor_offset_ns; + + + + + + + // // FIXME: Remove this + // f32 prof_zoom_rate = 2; + // // profiler->view_start_ns += NsFromSeconds(1) * main_reps.draw.buttons[Button_WheelUp].presses * prof_zoom_rate; + // // profiler->view_start_ns -= NsFromSeconds(1) * main_reps.draw.buttons[Button_WheelDown].presses * prof_zoom_rate; + + // // profiler->view_start_ns -= main_reps.draw.buttons[Button_WheelUp].presses * ns_to_left * prof_zoom_rate; + // // profiler->view_end_ns += main_reps.draw.buttons[Button_WheelDown].presses * ns_to_right * prof_zoom_rate; + + // // profiler->view_start_ns -= main_reps.draw.buttons[Button_WheelDown].presses * ns_to_left * prof_zoom_rate; + // // profiler->view_end_ns += main_reps.draw.buttons[Button_WheelDown].presses * ns_to_right * prof_zoom_rate; + + // if (main_reps.draw.buttons[Button_WheelUp].presses) + // { + // DEBUGBREAKABLE; + // } + + // // profiler->view_start_ns += main_reps.draw.buttons[Button_WheelUp].presses * ns_to_left / prof_zoom_rate; + // // profiler->view_end_ns -= main_reps.draw.buttons[Button_WheelUp].presses * ns_to_right / prof_zoom_rate; + + // for (i32 zoom_idx = 0; zoom_idx < main_reps.draw.buttons[Button_WheelUp].presses; ++zoom_idx) + // { + // i64 ns_to_left = old_cursor_ns - profiler->view_start_ns; + // i64 ns_to_right = profiler->view_end_ns - old_cursor_ns; + // profiler->view_start_ns += (old_cursor_ns - profiler->view_start_ns) / prof_zoom_rate; + // profiler->view_end_ns -= (profiler->view_end_ns - old_cursor_ns) / prof_zoom_rate; + // } + // for (i32 zoom_idx = 0; zoom_idx < main_reps.draw.buttons[Button_WheelDown].presses; ++zoom_idx) + // { + // i64 ns_to_left = old_cursor_ns - profiler->view_start_ns; + // i64 ns_to_right = profiler->view_end_ns - old_cursor_ns; + // profiler->view_start_ns -= (old_cursor_ns - profiler->view_start_ns) * prof_zoom_rate; + // profiler->view_end_ns += (profiler->view_end_ns - old_cursor_ns) * prof_zoom_rate; + // } + + // if (main_reps.draw.buttons[Button_M3].downs) + // { + // profiler->drag_view_start_ns = profiler->view_start_ns; + // profiler->drag_cursor_ns = old_cursor_ns; + // } + + // if (main_reps.draw.buttons[Button_M3].held) + // { + // // i64 ns_delta = prev_frame->profiler. + // i64 ns_delta = old_cursor_ns - profiler->drag_cursor_ns; + + // // i64 dims_ns = profiler->view_end_ns - profiler->view_start_ns; + + // // profiler->view_start_ns = profiler->drag_view_start_ns - ns_delta; + // // profiler->view_end_ns = profiler->view_start_ns + dims_ns; + + // i64 dims_ns = profiler->view_end_ns - profiler->view_start_ns; + // profiler->view_start_ns = profiler->drag_view_start_ns - ns_delta; + // profiler->view_end_ns = profiler->view_start_ns + dims_ns; + // } + + + + + + + + + + + + // f64 ns_per_px = MaxF64((profiler->view_end_ns - profiler->view_start_ns) / old_main_dims.x, 1); + + // Vec4 profiler_color = theme.col.window_bg; + // profiler_color.a = 1; + + // UI_SetNext(Parent, vis_ui_box); + // UI_SetNext(BorderColor, theme.col.window_bd); + // UI_SetNext(BorderSize, 2); + // UI_SetNext(BackgroundColor, profiler_color); + // UI_SetNext(Rounding, UI_RPIX(10 * theme.rounding)); + // UI_SetNext(Height, profiler_height); + // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); + // UI_PushDF(Width, UI_GROW(1, 0)) + // UI_PushDF(Parent, UI_BuildColumnEx(profiler_box)) + // UI_PushDF(Parent, UI_BuildRow()) + // { + // UI_BuildSpacer(window_padding, Axis_X); + // UI_PushDF(Parent, UI_BuildColumn()) + // { + // //- Header + // // UI_PushDF(BackgroundColor, Color_Red) + // // UI_SetNext(BorderColor, Color_Red); + // // UI_SetNext(BorderSize, 1); + // UI_SetNext(ChildAlignment, UI_Region_Center); + // UI_PushDF(Height, header_height) + // UI_PushDF(Parent, UI_BuildBoxF("profiler header")) + // { + // UI_PushDF(TextColor, theme.col.hint) + // UI_BuildLabelF("Profiler"); + // } + // UI_BuildDivider(UI_PIX(1, 1), theme.col.divider, Axis_Y); + + // //- Graph + // // UI_SetNext(BackgroundColor, Color_Cyan); + // UI_SetNext(Height, graph_height); + // UI_PushDF(Parent, UI_BuildBoxEx(profiler_graph_box)) + // { + // } + // UI_BuildDivider(UI_PIX(1, 1), theme.col.divider, Axis_Y); + + // //- Main + // UI_SetNext(Height, main_height); + // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); + // UI_PushDF(Parent, UI_BuildRowEx(main_box)) + // { + + // // FIXME: Remove this + + // Struct(V_ZoneDesc) + // { + // Vec4 color; + // i64 start_ns; + // i64 end_ns; + // }; + + // u64 zones_count = 64; + // V_ZoneDesc *zones = PushStructs(frame->arena, V_ZoneDesc, zones_count); + // for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) + // { + // V_ZoneDesc *zone = &zones[zone_idx]; + + // // zone->color = VEC4(0.5, 0.2, 0.2, 0.5); + // // zone->color.r += 0.5 * Norm24(MixU64(zone_idx)); + + // u64 seed0 = MixU64(zone_idx + 1); + // u64 seed1 = MixU64(seed0); + // u64 seed2 = MixU64(seed1); + // u64 seed3 = MixU64(seed2); + + // zone->color = VEC4(Norm24(seed0), Norm24(seed1), Norm24(seed2), 1); + // zone->color.r += (1.0 - zone->color.r) * 0.25; + + // zone->start_ns = NsFromSeconds(zone_idx * 2); + // zone->end_ns = NsFromSeconds(zone_idx * 2 + 1); + // }; + + // //- Zones + // for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) + // { + // V_ZoneDesc *zone = &zones[zone_idx]; + + // UI_Key zone_box = UI_KeyF("Zone %F", FmtUint(zone_idx)); + // // UI_BoxReport zone_rep = UI_ReportFromKey(zone_box).draw; + + // Vec4 zone_color = zone->color; + + // // Vec4 zone_color_bd = Zi; + // // zone_color_bd + + // i64 zone_len_ns = zone->end_ns - zone->start_ns; + // f32 zone_len_px = zone_len_ns / ns_per_px; + // // i6 + + // f32 zone_offset_px = (zone->start_ns - profiler->view_start_ns) / ns_per_px; + // Vec2 zone_pos = VEC2(zone_offset_px, 0); + // UI_Size zone_width = UI_PIX(zone_len_px, 1); + + // // UI_Report + + + // UI_SetNext(Width, zone_width); + // UI_SetNext(Height, zone_height); + // UI_SetNext(BackgroundColor, zone_color); + // UI_SetNext(FloatingPos, zone_pos); + // UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClampX | UI_BoxFlag_NoFloatingClampY); + // UI_PushDF(Parent, UI_BuildBoxEx(zone_box)) + // { + // } + // } + + // //- Timeline cursor + // { + // // Vec2 timeline_cursor_pos = VEC2(old_cursor_offset_px, 0); + // Vec2 timeline_cursor_pos = VEC2((old_cursor_ns - profiler->view_start_ns) / ns_per_px, 0); + // Vec4 timeline_cursor_color = theme.col.window_bd; + // timeline_cursor_color.a = main_reps.draw.hot; + + // UI_SetNext(Width, UI_FNT(0.15, 1)); + // UI_SetNext(Height, UI_GROW(1, 0)); + // UI_SetNext(BackgroundColor, timeline_cursor_color); + // UI_SetNext(FloatingPos, timeline_cursor_pos); + // UI_SetNext(Flags, UI_BoxFlag_Floating); + // UI_BuildBox(); + // } + // } + + // } + // UI_BuildSpacer(window_padding, Axis_X); + // } + // } + // } + + + + + + + + + ////////////////////////////// //- Build notifications diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index fac2cb91..6f9d2fac 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -40,6 +40,8 @@ #define ProfTrackSamplesCap Kibi(256) #define MaxRegisteredProfTracks Kibi(32) +#define NsFromProfStamp(stamp) (stamp & ~((u64)1 << 63)) + @@ -68,9 +70,8 @@ Struct(ProfCtx) Struct(ProfThreadLocalCtx) { - b32 initialized; u32 track_idx; - ProfTrack thread_track; + ProfTrack *thread_track; }; extern ProfCtx Prof; @@ -79,9 +80,14 @@ extern ThreadLocal ProfThreadLocalCtx Prof_tl; Inline void PushProfZoneEx(b32 end_zone) { - ProfTrack *track = &Prof_tl.thread_track; - if (!Prof_tl.initialized) + ProfTrack *track = Prof_tl.thread_track; + if (!track) { + Arena *perm = PermArena(); + { + track = PushStruct(perm, ProfTrack); + Prof_tl.thread_track = track; + } LockTicketMutex(&Prof.register_track_tm); { Prof_tl.track_idx = Atomic32Fetch(&Prof.tracks_count); @@ -89,7 +95,6 @@ Inline void PushProfZoneEx(b32 end_zone) Atomic32FetchAdd(&Prof.tracks_count, 1); } UnlockTicketMutex(&Prof.register_track_tm); - Prof_tl.initialized = 1; } u64 sample_seq = track->top_sample_seq; @@ -387,6 +392,14 @@ Struct(V_Profiler) { Vec2 graph_dims; b32 is_showing; + + // TODO: Per track data + + f32 drag_view_ns; + f32 drag_cursor_px; + + i64 ns_per_px; + i64 view_ns; }; //////////////////////////////////////////////////////////// diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 85855109..834646e3 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -629,14 +629,15 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags) //- Update cursor pos for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index) { - ControllerEvent cev = controller_events.events[cev_index]; - if (cev.kind == ControllerEventKind_CursorMove) + ControllerEvent *cev = &controller_events.events[cev_index]; + if (cev->kind == ControllerEventKind_CursorMove) { - frame->cursor_pos = Vec2FromVec(cev.cursor_pos); + frame->cursor_pos = Vec2FromVec(cev->cursor_pos); } } //- Init box reports + // TODO: Iterate in post order and early out for (u64 pre_index = UI.boxes_count; pre_index-- > 0;) { UI_Box *box = prev_frame->boxes_pre[pre_index]; @@ -673,110 +674,122 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags) { top_hovered_box = box; } - report->m1.ups = 0; - report->m1.downs = 0; - report->m1.presses = 0; - report->m2.ups = 0; - report->m2.downs = 0; - report->m2.presses = 0; - report->m3.ups = 0; - report->m3.downs = 0; - report->m3.presses = 0; + for (u64 button_idx = 0; button_idx < countof(report->buttons); ++button_idx) + { + UI_ButtonReport *br = &report->buttons[button_idx]; + b32 old_held = br->held; + { + ZeroStruct(br); + } + br->held = old_held; + } + box->reports.old_tree_capture = box->reports.tree_capture; + box->reports.tree_capture = UI_NilKey; + report->is_hot = 0; } //- Update state from controller events i32 mouse_downs = 0; for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index) { - ControllerEvent cev = controller_events.events[cev_index]; - switch (cev.kind) + ControllerEvent *cev = &controller_events.events[cev_index]; + switch (cev->kind) { default: break; case ControllerEventKind_ButtonDown: { - if (IsClickButton(cev.button) || IsWheelButton(cev.button)) + if (IsClickButton(cev->button) || IsWheelButton(cev->button)) { mouse_downs += 1; if (top_hovered_box && active_box == 0) { - if (cev.button == Button_M1) + if (cev->button == Button_M1) { - ++top_hovered_box->reports.draw.m1.downs; - top_hovered_box->reports.draw.m1.held = 1; + ++top_hovered_box->reports.draw.buttons[Button_M1].downs; + top_hovered_box->reports.draw.buttons[Button_M1].held = 1; active_box = top_hovered_box; } - else if (cev.button == Button_M2) + else if (cev->button == Button_M2) { - ++top_hovered_box->reports.draw.m2.downs; - top_hovered_box->reports.draw.m2.held = 1; + ++top_hovered_box->reports.draw.buttons[Button_M2].downs; + top_hovered_box->reports.draw.buttons[Button_M2].held = 1; active_box = top_hovered_box; } - else if (cev.button == Button_M3) + else if (cev->button == Button_M3) { - ++top_hovered_box->reports.draw.m3.downs; - top_hovered_box->reports.draw.m3.held = 1; + ++top_hovered_box->reports.draw.buttons[Button_M3].downs; + top_hovered_box->reports.draw.buttons[Button_M3].held = 1; active_box = top_hovered_box; } - else if (cev.button == Button_WheelUp) + else if (cev->button == Button_WheelUp) { - ++top_hovered_box->reports.draw.wheel_up; + ++top_hovered_box->reports.draw.buttons[Button_WheelUp].downs; + ++top_hovered_box->reports.draw.buttons[Button_WheelUp].ups; + ++top_hovered_box->reports.draw.buttons[Button_WheelUp].presses; } - else if (cev.button == Button_WheelUp) + else if (cev->button == Button_WheelDown) { - ++top_hovered_box->reports.draw.wheel_down; + ++top_hovered_box->reports.draw.buttons[Button_WheelDown].downs; + ++top_hovered_box->reports.draw.buttons[Button_WheelDown].ups; + ++top_hovered_box->reports.draw.buttons[Button_WheelDown].presses; } + cev->captures += 1; } } } break; case ControllerEventKind_ButtonUp: { - if (IsClickButton(cev.button)) + if (IsClickButton(cev->button)) { if (active_box) { - if (cev.button == Button_M1) + if (cev->button == Button_M1) { if (active_box == top_hovered_box) { - ++active_box->reports.draw.m1.presses; + ++active_box->reports.draw.buttons[Button_M1].presses; } - ++active_box->reports.draw.m1.ups; - if (active_box->reports.draw.m1.held) + ++active_box->reports.draw.buttons[Button_M1].ups; + if (active_box->reports.draw.buttons[Button_M1].held) { - active_box->reports.draw.m1.held = 0; + active_box->reports.draw.buttons[Button_M1].held = 0; active_box = 0; } } - else if (cev.button == Button_M2) + else if (cev->button == Button_M2) { if (active_box == top_hovered_box) { - ++active_box->reports.draw.m2.presses; + ++active_box->reports.draw.buttons[Button_M2].presses; } - ++active_box->reports.draw.m2.ups; - if (active_box->reports.draw.m2.held) + ++active_box->reports.draw.buttons[Button_M2].ups; + if (active_box->reports.draw.buttons[Button_M2].held) { - active_box->reports.draw.m2.held = 0; + active_box->reports.draw.buttons[Button_M2].held = 0; active_box = 0; } } - else if (cev.button == Button_M3) + else if (cev->button == Button_M3) { if (active_box == top_hovered_box) { - ++active_box->reports.draw.m3.presses; + ++active_box->reports.draw.buttons[Button_M3].presses; } - ++active_box->reports.draw.m3.ups; - if (active_box->reports.draw.m3.held) + ++active_box->reports.draw.buttons[Button_M3].ups; + if (active_box->reports.draw.buttons[Button_M3].held) { - active_box->reports.draw.m3.held = 0; + active_box->reports.draw.buttons[Button_M3].held = 0; active_box = 0; } } } } + else if (IsWheelButton(cev->button) && top_hovered_box) + { + cev->captures += 1; + } } break; case ControllerEventKind_Quit: @@ -792,15 +805,39 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags) hot_box = top_hovered_box; } + if (hot_box) + { + // hot_box->reports.tree_capture = hot_box->key; + } + //- Update box reports { 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 = 0; pre_index < UI.boxes_count; ++pre_index) + for (u64 pre_index = UI.boxes_count; pre_index-- > 0;) { UI_Box *box = prev_frame->boxes_pre[pre_index]; UI_BoxReport *report = &box->reports.draw; - report->is_hot = box == hot_box; + UI_DebugBreak(box, UI_DebugBreakFlag_BuildReport); + + if (box == hot_box) + { + report->is_hot = 1; + box->reports.tree_capture = box->key; + } + + if (!UI_MatchKey(box->reports.tree_capture, box->reports.old_tree_capture)) + { + for (u64 button_idx = 0; button_idx < countof(report->buttons); ++button_idx) + { + UI_ButtonReport *button = &report->buttons[button_idx]; + if (button->held) + { + button->held = 0; + button->ups += 1; + } + } + } f32 target_exists = (box->last_build_tick >= (frame->tick - 1)) ? upper_target : lower_target; f32 target_hovered = report->is_hovered ? Inf : lower_target; @@ -828,6 +865,17 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags) { box->reports.drag = *report; } + + // Propagate upwards captures to tree + if (box->parent && !UI_IsKeyNil(box->reports.tree_capture)) + { + box->parent->reports.tree_capture = box->reports.tree_capture; + UI_Box *captured_child = UI_BoxFromKey(box->reports.tree_capture); + if (box->parent->desc.flags & UI_BoxFlag_CaptureThroughChildren) + { + box->parent->reports.draw = captured_child->reports.draw; + } + } } } @@ -1120,7 +1168,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) UI_Box *box = ir.box; if (ir.pre) { - UI_DebugBreak(box, UI_DebugBreakFlag_Prep); + UI_DebugBreak(box, UI_DebugBreakFlag_PrepLayout); box->pre_index = pre_index; boxes_pre[pre_index] = box; @@ -1507,7 +1555,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) // Solve scissor { box->solved_scissor = Rng2Inf; - if (box->desc.flags & UI_BoxFlag_Scissor) + if (box->desc.flags & UI_BoxFlag_Scissor || !parent) { box->solved_scissor = box->screen_rect; } diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 76c36797..bf17718f 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -88,11 +88,12 @@ Enum(UI_BoxFlag) UI_BoxFlag_None = 0, UI_BoxFlag_DrawText = (1 << 0), UI_BoxFlag_CaptureMouse = (1 << 1), - UI_BoxFlag_NoTextTruncation = (1 << 2), - UI_BoxFlag_Floating = (1 << 3), - UI_BoxFlag_NoFloatingClampX = (1 << 4), - UI_BoxFlag_NoFloatingClampY = (1 << 5), - UI_BoxFlag_Scissor = (1 << 6), + UI_BoxFlag_CaptureThroughChildren = (1 << 2), + UI_BoxFlag_NoTextTruncation = (1 << 3), + UI_BoxFlag_Floating = (1 << 4), + UI_BoxFlag_NoFloatingClampX = (1 << 5), + UI_BoxFlag_NoFloatingClampY = (1 << 6), + UI_BoxFlag_Scissor = (1 << 7), }; //////////////////////////////////////////////////////////// @@ -101,14 +102,15 @@ Enum(UI_BoxFlag) Enum(UI_DebugBreakFlag) { UI_DebugBreakFlag_None = 0, - UI_DebugBreakFlag_Prep = (1 << 0), - UI_DebugBreakFlag_IndependentSolve = (1 << 1), - UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis = (1 << 2), - UI_DebugBreakFlag_DownwardsDependentSolve = (1 << 3), - UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis = (1 << 4), - UI_DebugBreakFlag_SolveViolations = (1 << 5), - UI_DebugBreakFlag_FinalSolve = (1 << 6), - UI_DebugBreakFlag_BuildGpuData = (1 << 7), + UI_DebugBreakFlag_BuildReport = (1 << 0), + UI_DebugBreakFlag_PrepLayout = (1 << 1), + UI_DebugBreakFlag_IndependentSolve = (1 << 2), + UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis = (1 << 3), + UI_DebugBreakFlag_DownwardsDependentSolve = (1 << 4), + UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis = (1 << 5), + UI_DebugBreakFlag_SolveViolations = (1 << 6), + UI_DebugBreakFlag_FinalSolve = (1 << 7), + UI_DebugBreakFlag_BuildGpuData = (1 << 8), UI_DebugBreakFlag_All = 0xFFFFFFFF }; @@ -209,39 +211,39 @@ Struct(UI_Stack) //////////////////////////////////////////////////////////// //~ Report types -Struct(UI_MouseReport) +Struct(UI_ButtonReport) { - b32 held; + b32 held; // Persistent i32 downs; // Mouse button down events over box causing activation i32 ups; // Mouse button up events while box is active i32 presses; // Mouse button events while box is active and hovered }; -Struct(UI_BoxReport) +Struct(UI_CapturesReport) { b32 is_hovered; b32 is_hot; + UI_ButtonReport buttons[Button_COUNT]; +}; +Struct(UI_BoxReport) +{ + Embed(UI_CapturesReport, captures); + Rng2 screen_rect; + Vec2 screen_anchor; f32 exists; f32 hovered; f32 hot; f32 active; f64 misc; - - UI_MouseReport m1; - UI_MouseReport m2; - UI_MouseReport m3; - i32 wheel_up; - i32 wheel_down; - - Rng2 screen_rect; - Vec2 screen_anchor; }; Struct(UI_BoxReports) { - UI_BoxReport draw; // Box data used for last render - UI_BoxReport drag; // Box data during last mouse button down event + UI_BoxReport draw; // Box data used for last render + UI_BoxReport drag; // Box data during last mouse button down event + UI_Key tree_capture; // Key of captured child (if any) + UI_Key old_tree_capture; }; //////////////////////////////////////////////////////////// @@ -414,6 +416,7 @@ Struct(UI_Frame) // Control Vec2 cursor_pos; Vec2 drag_cursor_pos; + UI_Key top_hovered_box; UI_Key hot_box; UI_Key active_box; @@ -539,7 +542,6 @@ UI_Checkpoint UI_TopCp(void); UI_Key UI_BuildBoxEx(UI_Key semantic_key); #define UI_BuildBox() UI_BuildBoxEx(UI_NilKey) -#define UI_BuildBoxF(...) UI_BuildBoxEx(UI_KeyF(__VA_ARGS__)) void UI_SetRawTexture(UI_Key key, G_TextureRef tex, Rng2 uv); diff --git a/src/ui/ui_extras.h b/src/ui/ui_extras.h index 71d3b57c..a75b52d7 100644 --- a/src/ui/ui_extras.h +++ b/src/ui/ui_extras.h @@ -31,6 +31,3 @@ UI_Key UI_BuildColumnEx(UI_Key key); #define UI_BuildRow() UI_BuildRowEx(UI_NilKey) #define UI_BuildColumn() UI_BuildColumnEx(UI_NilKey) - -#define UI_BuildRowF(...) UI_BuildRowEx(UI_KeyF(__VA_ARGS__)) -#define UI_BuildColumnF(...) UI_BuildColumnEx(UI_KeyF(__VA_ARGS__))