propagate child UI captures upwards in tree

This commit is contained in:
jacob 2026-03-30 20:54:55 -05:00
parent 10acb10782
commit 246f63a61f
7 changed files with 844 additions and 162 deletions

View File

@ -132,6 +132,7 @@ Enum(ControllerEventKind)
Struct(ControllerEvent) Struct(ControllerEvent)
{ {
ControllerEventKind kind; ControllerEventKind kind;
i32 captures;
// ControllerEventKind_ButtonDown // ControllerEventKind_ButtonDown
// ControllerEventKind_ButtonUp // ControllerEventKind_ButtonUp
@ -162,4 +163,4 @@ Struct(ControllerEventsArray)
String StringFromButton(Button button); String StringFromButton(Button button);
b32 IsClickButton(Button button); b32 IsClickButton(Button button);
b32 IsWheelButton(Button button); b32 IsWheelButton(Button button);
b32 IsouseButton(Button button); b32 IsMouseButton(Button button);

View File

@ -924,6 +924,7 @@ void S_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Publish Sim -> User data //- Publish Sim -> User data
ProfZoneDF("Publish Sim -> User")
{ {
LockTicketMutex(&P.s2v_tm); LockTicketMutex(&P.s2v_tm);
{ {

View File

@ -1208,6 +1208,11 @@ void V_TickForever(WaveLaneCtx *lane)
String text = cev->kind == ControllerEventKind_Text ? STRING(cev->text_chars_count, cev->text_chars) : STRING(0, 0); String text = cev->kind == ControllerEventKind_Text ? STRING(cev->text_chars_count, cev->text_chars) : STRING(0, 0);
b32 ignore = 0; b32 ignore = 0;
if (cev->captures > 0 && !frame->has_mouse_focus)
{
ignore = 1;
}
if (down) 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)
@ -3895,7 +3900,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
V_Window *window = tab->window; 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; new_active_window_idx = tab->window_idx;
} }
@ -3903,7 +3908,7 @@ void V_TickForever(WaveLaneCtx *lane)
if (V.dragging_window == 0) if (V.dragging_window == 0)
{ {
f32 drag_threshold = 20; f32 drag_threshold = 20;
if (tab_rep.m1.held) if (tab_rep.buttons[Button_M1].held)
{ {
Vec2 drag_start = ui_frame->drag_cursor_pos; Vec2 drag_start = ui_frame->drag_cursor_pos;
if (Vec2Len(SubVec2(frame->screen_cursor, drag_start)) > drag_threshold) 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; 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; V.dragging_window = 0;
} }
@ -3999,7 +4004,7 @@ void V_TickForever(WaveLaneCtx *lane)
} }
UI_PopCp(UI_TopCp()); UI_PopCp(UI_TopCp());
if (close_rep.m1.presses) if (close_rep.buttons[Button_M1].presses)
{ {
prune_windows[prune_windows_count] = window; prune_windows[prune_windows_count] = window;
prune_windows_count += 1; prune_windows_count += 1;
@ -4108,7 +4113,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Key key = UI_KeyF("Tile %F", FmtString(tile_name)); UI_Key key = UI_KeyF("Tile %F", FmtString(tile_name));
UI_BoxReport rep = UI_ReportsFromKey(key).draw; UI_BoxReport rep = UI_ReportsFromKey(key).draw;
if (rep.m1.downs) if (rep.buttons[Button_M1].downs)
{ {
frame->edit_mode = V_EditMode_Tile; frame->edit_mode = V_EditMode_Tile;
frame->equipped_tile = tile_kind; 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_Key key = UI_KeyF("Prefab %F", FmtString(prefab_name));
UI_BoxReport rep = UI_ReportsFromKey(key).draw; UI_BoxReport rep = UI_ReportsFromKey(key).draw;
if (rep.m1.downs) if (rep.buttons[Button_M1].downs)
{ {
frame->edit_mode = V_EditMode_Prefab; frame->edit_mode = V_EditMode_Prefab;
frame->equipped_prefab = prefab_kind; 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_SetNext(AxisSize, UI_PIX(divider_size, 1), .axis = !panel->axis);
UI_BuildBoxEx(panel->divider_key); 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) 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; panel->resizing = 1;
} }
@ -4364,6 +4369,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Size item_col_width = UI_FNT(30, 1); UI_Size item_col_width = UI_FNT(30, 1);
// UI_Size col2_width = UI_FNT(10, 1); // UI_Size col2_width = UI_FNT(10, 1);
UI_Size scrollbar_width = UI_FNT(1, 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 scissor_key = UI_KeyF("scissor");
UI_Key lister_key = UI_KeyF("lister"); 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_end = thumb_reps.draw.screen_rect.p1.y;
f32 thumb_height = MaxF32(thumb_end - thumb_start, 1); 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); 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_lister = lister_reps.draw.screen_rect;
palette->drag_scissor = scissor_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; 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_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; 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); 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 = palette->drag_scroll + delta_ratio * drag_scroll_height;
} }
palette->scroll += wheels * wheel_scroll_amount;
palette->scroll = ClampF32(palette->scroll, 0, scroll_height); 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) 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; f32 tweak_size_px = UI_FNT(1.25, 1).v;
palette->key = UI_KeyF("command palette"); palette->key = UI_KeyF("command palette");
@ -4455,7 +4463,7 @@ void V_TickForever(WaveLaneCtx *lane)
Vec4 titlebar_color = Zi; Vec4 titlebar_color = Zi;
Vec4 titlebar_border_color = Zi; Vec4 titlebar_border_color = Zi;
Vec4 divider_color = theme.col.divider; 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); Vec2 drag_offset = SubVec2(ui_frame->drag_cursor_pos, palette_reps.drag.screen_anchor);
palette->pos = SubVec2(frame->screen_cursor, drag_offset); palette->pos = SubVec2(frame->screen_cursor, drag_offset);
@ -4575,8 +4583,8 @@ void V_TickForever(WaveLaneCtx *lane)
// FIXME: Remove this // FIXME: Remove this
has_focus = 1; has_focus = 1;
// if (search_report.m1.downs) // if (search_report.buttons[Button_M1].downs)
if (search_report.m1.downs) if (search_report.buttons[Button_M1].downs)
{ {
has_focus = 1; has_focus = 1;
V.text_input_ns = frame->time_ns; 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(Width, UI_GROW(1, 0));
UI_SetNext(Height, UI_SHRINK(0, 1)); UI_SetNext(Height, UI_SHRINK(0, 1));
UI_SetNext(FloatingPos, VEC2(0, -lister_offset)); 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_PushCp(UI_BuildRowEx(lister_key));
{ {
UI_SetNext(Tint, 0); UI_SetNext(Tint, 0);
@ -4895,7 +4903,7 @@ void V_TickForever(WaveLaneCtx *lane)
} }
UI_BoxReport item_rep = UI_ReportsFromKey(item->key).draw; 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) if (item->flags & PaletteItemFlag_IsCmd)
{ {
@ -4963,7 +4971,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Key reset_key = UI_KeyF("reset"); UI_Key reset_key = UI_KeyF("reset");
UI_BoxReport reset_rep = UI_ReportsFromKey(reset_key).draw; 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; new_tweak_str = tweak_var.initial;
} }
@ -5029,7 +5037,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_BoxReport cb_rep = UI_ReportsFromKey(cb_key).draw; UI_BoxReport cb_rep = UI_ReportsFromKey(cb_key).draw;
b32 tweak_bool = CR_BoolFromString(new_tweak_str); b32 tweak_bool = CR_BoolFromString(new_tweak_str);
if (cb_rep.m1.downs) if (cb_rep.buttons[Button_M1].downs)
{ {
tweak_bool = !tweak_bool; tweak_bool = !tweak_bool;
new_tweak_str = StringFromBool(frame->arena, 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); UI_BoxReports marker_reps = UI_ReportsFromKey(marker_key);
b32 is_hot = slider_reps.draw.is_hot || marker_reps.draw.is_hot; 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); f32 hot = MaxF32(slider_reps.draw.hot, marker_reps.draw.hot);
Vec2 slider_pos = slider_reps.draw.screen_rect.p0; 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 = (tweak_float - range_min) / (range_max - range_min);
// // ratio = ClampF32(ratio, 0, 1); // // ratio = ClampF32(ratio, 0, 1);
// if (thumb_reps.draw.m1.downs) // if (thumb_reps.draw.buttons[Button_M1].downs)
// { // {
// palette->scroll_begin = palette->scroll; // 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); // 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 //- Build profiler
@ -5430,11 +5433,30 @@ void V_TickForever(WaveLaneCtx *lane)
V_Profiler *profiler = &frame->profiler; V_Profiler *profiler = &frame->profiler;
profiler->ns_per_px = MaxI64(profiler->ns_per_px, 1);
UI_Key profiler_graph_box = UI_KeyF("graph"); UI_Key profiler_graph_box = UI_KeyF("graph");
UI_PushDF(OmitFlags, UI_BoxFlag_CaptureMouse * !!(frame->is_looking))
if (TweakBool("Show profiler", 1)) if (TweakBool("Show profiler", 1))
{ {
profiler->is_showing = 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); UI_BoxReports profiler_graph_reports = UI_ReportsFromKey(profiler_graph_box);
profiler->graph_dims = DimsFromRng2(profiler_graph_reports.draw.screen_rect); 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 profiler_height = UI_FNT(40, 1);
UI_Size header_height = UI_FNT(2, 1); UI_Size header_height = UI_FNT(2, 1);
UI_Size window_padding = UI_FNT(0.5, 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 main_height = UI_GROW(1, 0);
UI_Size zone_height = UI_FNT(0.75, 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); // Vec2 old_main_dims = DimsFromRng2(main_reps.draw.screen_rect);
i64 view_end_ns = NsFromSeconds(10); // 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; Vec4 profiler_color = theme.col.window_bg;
profiler_color.a = 1; profiler_color.a = 1;
@ -5524,6 +5641,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_SetNext(BackgroundColor, profiler_color); UI_SetNext(BackgroundColor, profiler_color);
UI_SetNext(Rounding, UI_RPIX(10 * theme.rounding)); UI_SetNext(Rounding, UI_RPIX(10 * theme.rounding));
UI_SetNext(Height, profiler_height); UI_SetNext(Height, profiler_height);
UI_SetNext(Flags, UI_BoxFlag_CaptureMouse);
UI_PushDF(Width, UI_GROW(1, 0)) UI_PushDF(Width, UI_GROW(1, 0))
UI_PushDF(Parent, UI_BuildColumnEx(profiler_box)) UI_PushDF(Parent, UI_BuildColumnEx(profiler_box))
UI_PushDF(Parent, UI_BuildRow()) UI_PushDF(Parent, UI_BuildRow())
@ -5537,7 +5655,7 @@ void V_TickForever(WaveLaneCtx *lane)
// UI_SetNext(BorderSize, 1); // UI_SetNext(BorderSize, 1);
UI_SetNext(ChildAlignment, UI_Region_Center); UI_SetNext(ChildAlignment, UI_Region_Center);
UI_PushDF(Height, header_height) 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_PushDF(TextColor, theme.col.hint)
UI_BuildLabelF("Profiler"); UI_BuildLabelF("Profiler");
@ -5553,13 +5671,50 @@ void V_TickForever(WaveLaneCtx *lane)
UI_BuildDivider(UI_PIX(1, 1), theme.col.divider, Axis_Y); UI_BuildDivider(UI_PIX(1, 1), theme.col.divider, Axis_Y);
//- Main //- Main
if (do_break)
{
UI_SetNext(DebugBreakFlags, UI_DebugBreakFlag_BuildReport);
UI_SetNext(Text, Lit("MAIN"));
}
UI_SetNext(Height, main_height); UI_SetNext(Height, main_height);
UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_CaptureThroughChildren);
UI_PushDF(Parent, UI_BuildRowEx(main_box)) UI_PushDF(Parent, UI_BuildColumnEx(main_box))
{ {
// FIXME: Remove this // 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) Struct(V_ZoneDesc)
{ {
Vec4 color; Vec4 color;
@ -5567,23 +5722,122 @@ void V_TickForever(WaveLaneCtx *lane)
i64 end_ns; i64 end_ns;
}; };
u64 zones_count = 64; u32 tracks_count = Atomic32Fetch(&Prof.tracks_count);
for (u64 track_idx = 0; track_idx < tracks_count; ++track_idx)
{
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); V_ZoneDesc *zones = PushStructs(frame->arena, V_ZoneDesc, zones_count);
for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx)
{ {
V_ZoneDesc *zone = &zones[zone_idx]; V_ZoneDesc *zone = &zones[zone_idx];
zone->color = VEC4(0.5, 0.2, 0.2, 0.5);
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->start_ns = NsFromSeconds(zone_idx * 2);
zone->end_ns = NsFromSeconds(zone_idx * 2 + 1); zone->end_ns = NsFromSeconds(zone_idx * 2 + 1);
// zone->start_ns = NsFromProfStamp(sample->stamp);
// zone->end_ns = zone->start_ns + NsFromSeconds(0.100);
}; };
//- Zones //- Zones
for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx) for (u64 zone_idx = 0; zone_idx < zones_count; ++zone_idx)
{ {
V_ZoneDesc *zone = &zones[zone_idx]; V_ZoneDesc *zone = &zones[zone_idx];
UI_Key zone_box = UI_KeyF("Zone %F", FmtUint(zone_idx)); UI_Key zone_box = UI_KeyF("Zone %F", FmtUint(zone_idx));
// UI_BoxReport zone_rep = UI_ReportFromKey(zone_box).draw; UI_BoxReport zone_rep = UI_ReportsFromKey(zone_box).draw;
Vec4 zone_color = zone->color; Vec4 zone_color = zone->color;
@ -5591,26 +5845,57 @@ void V_TickForever(WaveLaneCtx *lane)
// zone_color_bd // zone_color_bd
i64 zone_len_ns = zone->end_ns - zone->start_ns; i64 zone_len_ns = zone->end_ns - zone->start_ns;
f32 zone_len_px = zone_len_ns / ns_per_px; f32 zone_len_px = zone_len_ns / profiler->ns_per_px;
// i6 // i6
f32 zone_offset_px = (zone->start_ns - view_start_ns) / ns_per_px; f32 zone_offset_px = (zone->start_ns - profiler->view_ns) / profiler->ns_per_px;
Vec2 zone_pos = VEC2(zone_offset_px, 0); Vec2 zone_pos = VEC2(zone_offset_px, 0);
UI_Size zone_width = UI_PIX(zone_len_px, 1); UI_Size zone_width = UI_PIX(zone_len_px, 1);
// UI_Report
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(Width, zone_width);
UI_SetNext(Height, zone_height); UI_SetNext(Height, zone_height);
UI_SetNext(BackgroundColor, zone_color); UI_SetNext(BackgroundColor, zone_color);
UI_SetNext(FloatingPos, zone_pos); UI_SetNext(FloatingPos, zone_pos);
UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClampX | UI_BoxFlag_NoFloatingClampY); UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClampX | UI_BoxFlag_NoFloatingClampY | UI_BoxFlag_CaptureMouse);
UI_PushDF(Parent, UI_BuildBoxEx(zone_box)) 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();
}
}
} }
UI_BuildSpacer(window_padding, Axis_X); UI_BuildSpacer(window_padding, Axis_X);
@ -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 //- Build notifications

View File

@ -40,6 +40,8 @@
#define ProfTrackSamplesCap Kibi(256) #define ProfTrackSamplesCap Kibi(256)
#define MaxRegisteredProfTracks Kibi(32) #define MaxRegisteredProfTracks Kibi(32)
#define NsFromProfStamp(stamp) (stamp & ~((u64)1 << 63))
@ -68,9 +70,8 @@ Struct(ProfCtx)
Struct(ProfThreadLocalCtx) Struct(ProfThreadLocalCtx)
{ {
b32 initialized;
u32 track_idx; u32 track_idx;
ProfTrack thread_track; ProfTrack *thread_track;
}; };
extern ProfCtx Prof; extern ProfCtx Prof;
@ -79,9 +80,14 @@ extern ThreadLocal ProfThreadLocalCtx Prof_tl;
Inline void PushProfZoneEx(b32 end_zone) Inline void PushProfZoneEx(b32 end_zone)
{ {
ProfTrack *track = &Prof_tl.thread_track; ProfTrack *track = Prof_tl.thread_track;
if (!Prof_tl.initialized) if (!track)
{ {
Arena *perm = PermArena();
{
track = PushStruct(perm, ProfTrack);
Prof_tl.thread_track = track;
}
LockTicketMutex(&Prof.register_track_tm); LockTicketMutex(&Prof.register_track_tm);
{ {
Prof_tl.track_idx = Atomic32Fetch(&Prof.tracks_count); Prof_tl.track_idx = Atomic32Fetch(&Prof.tracks_count);
@ -89,7 +95,6 @@ Inline void PushProfZoneEx(b32 end_zone)
Atomic32FetchAdd(&Prof.tracks_count, 1); Atomic32FetchAdd(&Prof.tracks_count, 1);
} }
UnlockTicketMutex(&Prof.register_track_tm); UnlockTicketMutex(&Prof.register_track_tm);
Prof_tl.initialized = 1;
} }
u64 sample_seq = track->top_sample_seq; u64 sample_seq = track->top_sample_seq;
@ -387,6 +392,14 @@ Struct(V_Profiler)
{ {
Vec2 graph_dims; Vec2 graph_dims;
b32 is_showing; b32 is_showing;
// TODO: Per track data
f32 drag_view_ns;
f32 drag_cursor_px;
i64 ns_per_px;
i64 view_ns;
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -629,14 +629,15 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
//- Update cursor pos //- Update cursor pos
for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index) for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index)
{ {
ControllerEvent cev = controller_events.events[cev_index]; ControllerEvent *cev = &controller_events.events[cev_index];
if (cev.kind == ControllerEventKind_CursorMove) if (cev->kind == ControllerEventKind_CursorMove)
{ {
frame->cursor_pos = Vec2FromVec(cev.cursor_pos); frame->cursor_pos = Vec2FromVec(cev->cursor_pos);
} }
} }
//- Init box reports //- Init box reports
// TODO: Iterate in post order and early out
for (u64 pre_index = UI.boxes_count; pre_index-- > 0;) for (u64 pre_index = UI.boxes_count; pre_index-- > 0;)
{ {
UI_Box *box = prev_frame->boxes_pre[pre_index]; 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; top_hovered_box = box;
} }
report->m1.ups = 0; for (u64 button_idx = 0; button_idx < countof(report->buttons); ++button_idx)
report->m1.downs = 0; {
report->m1.presses = 0; UI_ButtonReport *br = &report->buttons[button_idx];
report->m2.ups = 0; b32 old_held = br->held;
report->m2.downs = 0; {
report->m2.presses = 0; ZeroStruct(br);
report->m3.ups = 0; }
report->m3.downs = 0; br->held = old_held;
report->m3.presses = 0; }
box->reports.old_tree_capture = box->reports.tree_capture;
box->reports.tree_capture = UI_NilKey;
report->is_hot = 0;
} }
//- Update state from controller events //- Update state from controller events
i32 mouse_downs = 0; i32 mouse_downs = 0;
for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index) for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index)
{ {
ControllerEvent cev = controller_events.events[cev_index]; ControllerEvent *cev = &controller_events.events[cev_index];
switch (cev.kind) switch (cev->kind)
{ {
default: break; default: break;
case ControllerEventKind_ButtonDown: case ControllerEventKind_ButtonDown:
{ {
if (IsClickButton(cev.button) || IsWheelButton(cev.button)) if (IsClickButton(cev->button) || IsWheelButton(cev->button))
{ {
mouse_downs += 1; mouse_downs += 1;
if (top_hovered_box && active_box == 0) 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.buttons[Button_M1].downs;
top_hovered_box->reports.draw.m1.held = 1; top_hovered_box->reports.draw.buttons[Button_M1].held = 1;
active_box = top_hovered_box; 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.buttons[Button_M2].downs;
top_hovered_box->reports.draw.m2.held = 1; top_hovered_box->reports.draw.buttons[Button_M2].held = 1;
active_box = top_hovered_box; 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.buttons[Button_M3].downs;
top_hovered_box->reports.draw.m3.held = 1; top_hovered_box->reports.draw.buttons[Button_M3].held = 1;
active_box = top_hovered_box; 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; } break;
case ControllerEventKind_ButtonUp: case ControllerEventKind_ButtonUp:
{ {
if (IsClickButton(cev.button)) if (IsClickButton(cev->button))
{ {
if (active_box) if (active_box)
{ {
if (cev.button == Button_M1) if (cev->button == Button_M1)
{ {
if (active_box == top_hovered_box) 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; ++active_box->reports.draw.buttons[Button_M1].ups;
if (active_box->reports.draw.m1.held) 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; active_box = 0;
} }
} }
else if (cev.button == Button_M2) else if (cev->button == Button_M2)
{ {
if (active_box == top_hovered_box) 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; ++active_box->reports.draw.buttons[Button_M2].ups;
if (active_box->reports.draw.m2.held) 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; active_box = 0;
} }
} }
else if (cev.button == Button_M3) else if (cev->button == Button_M3)
{ {
if (active_box == top_hovered_box) 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; ++active_box->reports.draw.buttons[Button_M3].ups;
if (active_box->reports.draw.m3.held) 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; active_box = 0;
} }
} }
} }
} }
else if (IsWheelButton(cev->button) && top_hovered_box)
{
cev->captures += 1;
}
} break; } break;
case ControllerEventKind_Quit: case ControllerEventKind_Quit:
@ -792,15 +805,39 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
hot_box = top_hovered_box; hot_box = top_hovered_box;
} }
if (hot_box)
{
// hot_box->reports.tree_capture = hot_box->key;
}
//- Update box reports //- Update box reports
{ {
f32 lower_target = TweakFloat("UI lower blend target", -0.05, -1, 0); f32 lower_target = TweakFloat("UI lower blend target", -0.05, -1, 0);
f32 upper_target = TweakFloat("UI upper blend target", 1.05, 1, 10); 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_Box *box = prev_frame->boxes_pre[pre_index];
UI_BoxReport *report = &box->reports.draw; 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_exists = (box->last_build_tick >= (frame->tick - 1)) ? upper_target : lower_target;
f32 target_hovered = report->is_hovered ? Inf : 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; 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; UI_Box *box = ir.box;
if (ir.pre) if (ir.pre)
{ {
UI_DebugBreak(box, UI_DebugBreakFlag_Prep); UI_DebugBreak(box, UI_DebugBreakFlag_PrepLayout);
box->pre_index = pre_index; box->pre_index = pre_index;
boxes_pre[pre_index] = box; boxes_pre[pre_index] = box;
@ -1507,7 +1555,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
// Solve scissor // Solve scissor
{ {
box->solved_scissor = Rng2Inf; 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; box->solved_scissor = box->screen_rect;
} }

View File

@ -88,11 +88,12 @@ Enum(UI_BoxFlag)
UI_BoxFlag_None = 0, UI_BoxFlag_None = 0,
UI_BoxFlag_DrawText = (1 << 0), UI_BoxFlag_DrawText = (1 << 0),
UI_BoxFlag_CaptureMouse = (1 << 1), UI_BoxFlag_CaptureMouse = (1 << 1),
UI_BoxFlag_NoTextTruncation = (1 << 2), UI_BoxFlag_CaptureThroughChildren = (1 << 2),
UI_BoxFlag_Floating = (1 << 3), UI_BoxFlag_NoTextTruncation = (1 << 3),
UI_BoxFlag_NoFloatingClampX = (1 << 4), UI_BoxFlag_Floating = (1 << 4),
UI_BoxFlag_NoFloatingClampY = (1 << 5), UI_BoxFlag_NoFloatingClampX = (1 << 5),
UI_BoxFlag_Scissor = (1 << 6), UI_BoxFlag_NoFloatingClampY = (1 << 6),
UI_BoxFlag_Scissor = (1 << 7),
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -101,14 +102,15 @@ Enum(UI_BoxFlag)
Enum(UI_DebugBreakFlag) Enum(UI_DebugBreakFlag)
{ {
UI_DebugBreakFlag_None = 0, UI_DebugBreakFlag_None = 0,
UI_DebugBreakFlag_Prep = (1 << 0), UI_DebugBreakFlag_BuildReport = (1 << 0),
UI_DebugBreakFlag_IndependentSolve = (1 << 1), UI_DebugBreakFlag_PrepLayout = (1 << 1),
UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis = (1 << 2), UI_DebugBreakFlag_IndependentSolve = (1 << 2),
UI_DebugBreakFlag_DownwardsDependentSolve = (1 << 3), UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis = (1 << 3),
UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis = (1 << 4), UI_DebugBreakFlag_DownwardsDependentSolve = (1 << 4),
UI_DebugBreakFlag_SolveViolations = (1 << 5), UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis = (1 << 5),
UI_DebugBreakFlag_FinalSolve = (1 << 6), UI_DebugBreakFlag_SolveViolations = (1 << 6),
UI_DebugBreakFlag_BuildGpuData = (1 << 7), UI_DebugBreakFlag_FinalSolve = (1 << 7),
UI_DebugBreakFlag_BuildGpuData = (1 << 8),
UI_DebugBreakFlag_All = 0xFFFFFFFF UI_DebugBreakFlag_All = 0xFFFFFFFF
}; };
@ -209,39 +211,39 @@ Struct(UI_Stack)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Report types //~ Report types
Struct(UI_MouseReport) Struct(UI_ButtonReport)
{ {
b32 held; b32 held; // Persistent
i32 downs; // Mouse button down events over box causing activation i32 downs; // Mouse button down events over box causing activation
i32 ups; // Mouse button up events while box is active i32 ups; // Mouse button up events while box is active
i32 presses; // Mouse button events while box is active and hovered i32 presses; // Mouse button events while box is active and hovered
}; };
Struct(UI_BoxReport) Struct(UI_CapturesReport)
{ {
b32 is_hovered; b32 is_hovered;
b32 is_hot; b32 is_hot;
UI_ButtonReport buttons[Button_COUNT];
};
Struct(UI_BoxReport)
{
Embed(UI_CapturesReport, captures);
Rng2 screen_rect;
Vec2 screen_anchor;
f32 exists; f32 exists;
f32 hovered; f32 hovered;
f32 hot; f32 hot;
f32 active; f32 active;
f64 misc; 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) Struct(UI_BoxReports)
{ {
UI_BoxReport draw; // Box data used for last render UI_BoxReport draw; // Box data used for last render
UI_BoxReport drag; // Box data during last mouse button down event 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 // Control
Vec2 cursor_pos; Vec2 cursor_pos;
Vec2 drag_cursor_pos; Vec2 drag_cursor_pos;
UI_Key top_hovered_box; UI_Key top_hovered_box;
UI_Key hot_box; UI_Key hot_box;
UI_Key active_box; UI_Key active_box;
@ -539,7 +542,6 @@ UI_Checkpoint UI_TopCp(void);
UI_Key UI_BuildBoxEx(UI_Key semantic_key); UI_Key UI_BuildBoxEx(UI_Key semantic_key);
#define UI_BuildBox() UI_BuildBoxEx(UI_NilKey) #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); void UI_SetRawTexture(UI_Key key, G_TextureRef tex, Rng2 uv);

View File

@ -31,6 +31,3 @@ UI_Key UI_BuildColumnEx(UI_Key key);
#define UI_BuildRow() UI_BuildRowEx(UI_NilKey) #define UI_BuildRow() UI_BuildRowEx(UI_NilKey)
#define UI_BuildColumn() UI_BuildColumnEx(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__))