ui feedback api

This commit is contained in:
jacob 2026-03-30 22:03:34 -05:00
parent d4bfdfcd4c
commit b2a9b3091d
3 changed files with 601 additions and 488 deletions

View File

@ -1082,7 +1082,6 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Push(Height, UI_GROW(1, 0)); UI_Push(Height, UI_GROW(1, 0));
UI_Key vis_game_box = UI_KeyF("vis game box"); UI_Key vis_game_box = UI_KeyF("vis game box");
UI_Key vis_ui_box = UI_KeyF("vis ui box"); UI_Key vis_ui_box = UI_KeyF("vis ui box");
UI_BoxReports vis_game_box_reps = UI_ReportsFromKey(vis_game_box);
{ {
UI_SetNext(Flags, UI_BoxFlag_CaptureMouse); UI_SetNext(Flags, UI_BoxFlag_CaptureMouse);
UI_BuildColumnEx(vis_game_box); UI_BuildColumnEx(vis_game_box);
@ -1092,7 +1091,7 @@ void V_TickForever(WaveLaneCtx *lane)
} }
// TODO: Don't rely on ui report for draw size since it introduces one frame of delay when resizing // TODO: Don't rely on ui report for draw size since it introduces one frame of delay when resizing
frame->screen_dims = RoundVec2(DimsFromRng2(vis_game_box_reps.draw.screen_rect)); frame->screen_dims = RoundVec2(DimsFromRng2(UI_Rect(vis_game_box)));
frame->screen_dims.x = MaxF32(frame->screen_dims.x, 64); frame->screen_dims.x = MaxF32(frame->screen_dims.x, 64);
frame->screen_dims.y = MaxF32(frame->screen_dims.y, 64); frame->screen_dims.y = MaxF32(frame->screen_dims.y, 64);
@ -3694,15 +3693,14 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
panel_dfs->visited = 1; panel_dfs->visited = 1;
UI_BoxReport panel_rep = UI_ReportsFromKey(panel->key).draw;
f32 panel_size = 0; f32 panel_size = 0;
if (panel->axis == Axis_X) if (panel->axis == Axis_X)
{ {
panel_size = DimsFromRng2(panel_rep.screen_rect).x; panel_size = DimsFromRng2(UI_Rect(panel->key)).x;
} }
else else
{ {
panel_size = DimsFromRng2(panel_rep.screen_rect).y; panel_size = DimsFromRng2(UI_Rect(panel->key)).y;
} }
// Push children to dfs stack // Push children to dfs stack
@ -3724,14 +3722,13 @@ void V_TickForever(WaveLaneCtx *lane)
// Apply resize // Apply resize
if (resize_panel) if (resize_panel)
{ {
UI_BoxReport child_rep = UI_ReportsFromKey(resize_panel->key).draw; Vec2 drag_pos = UI_DragCursorPos();
UI_BoxReports divider_reps = UI_ReportsFromKey(resize_panel->divider_key); Vec2 drag_anchor = UI_DragAnchor(resize_panel->divider_key);
f32 drag_offset = drag_pos.v[panel->axis] - drag_anchor.v[panel->axis];
f32 drag_offset = ui_frame->drag_cursor_pos.v[panel->axis] - divider_reps.drag.screen_anchor.v[panel->axis];
f32 child_pref_size = 0; f32 child_pref_size = 0;
child_pref_size += frame->screen_cursor.v[panel->axis]; child_pref_size += frame->screen_cursor.v[panel->axis];
child_pref_size -= child_rep.screen_anchor.v[panel->axis]; child_pref_size -= drag_anchor.v[panel->axis];
// child_pref_size -= divider_rep.last_cursor_down_anchor_offset.v[panel->axis]; // child_pref_size -= divider_rep.last_cursor_down_anchor_offset.v[panel->axis];
child_pref_size -= drag_offset; child_pref_size -= drag_offset;
@ -3787,7 +3784,7 @@ void V_TickForever(WaveLaneCtx *lane)
i64 new_active_window_idx = panel->active_window_idx; i64 new_active_window_idx = panel->active_window_idx;
UI_PushCp(UI_BuildColumn()); UI_PushCp(UI_BuildColumn());
{ {
UI_Push(Tint, VEC4(1, 1, 1, 0.90 * panel_rep.exists)); UI_Push(Tint, VEC4(1, 1, 1, 0.90 * UI_Exists(panel->key)));
i64 active_window_idx = ClampI64(panel->active_window_idx, 0, MaxI64(panel->windows_count - 1, 0)); i64 active_window_idx = ClampI64(panel->active_window_idx, 0, MaxI64(panel->windows_count - 1, 0));
@ -3799,7 +3796,6 @@ void V_TickForever(WaveLaneCtx *lane)
V_Window *close_window = 0; V_Window *close_window = 0;
{ {
UI_Key tab_row_key = UI_KeyF("tab row"); UI_Key tab_row_key = UI_KeyF("tab row");
UI_BoxReport tab_row_rep = UI_ReportsFromKey(tab_row_key).draw;
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));
@ -3843,14 +3839,13 @@ void V_TickForever(WaveLaneCtx *lane)
} }
// Insert ghost tab // Insert ghost tab
if (V.dragging_window && panel_rep.is_hovered) if (V.dragging_window && UI_Hovered(panel->key))
{ {
DrawableTab *left = 0; DrawableTab *left = 0;
DrawableTab *right = first_drawable_tab; DrawableTab *right = first_drawable_tab;
for (DrawableTab *sibling = first_drawable_tab; sibling; sibling = sibling->next) for (DrawableTab *sibling = first_drawable_tab; sibling; sibling = sibling->next)
{ {
UI_BoxReport sibling_rep = UI_ReportsFromKey(sibling->key).draw; f32 zone = CenterFromRng2(UI_Rect(sibling->key)).x;
f32 zone = CenterFromRng2(sibling_rep.screen_rect).x;
if (frame->screen_cursor.x <= zone) if (frame->screen_cursor.x <= zone)
{ {
break; break;
@ -3884,8 +3879,6 @@ void V_TickForever(WaveLaneCtx *lane)
for (DrawableTab *tab = first_drawable_tab; tab; tab = tab->next) for (DrawableTab *tab = first_drawable_tab; tab; tab = tab->next)
{ {
UI_Push(Tag, tab->key.v); UI_Push(Tag, tab->key.v);
UI_BoxReport tab_rep = UI_ReportsFromKey(tab->key).draw;
if (tab == first_drawable_tab) if (tab == first_drawable_tab)
{ {
UI_BuildSpacer(UI_PIX(tab_spacing, 0), Axis_X); UI_BuildSpacer(UI_PIX(tab_spacing, 0), Axis_X);
@ -3900,7 +3893,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
V_Window *window = tab->window; V_Window *window = tab->window;
{ {
if (tab_rep.buttons[Button_M1].downs > 0) if (UI_Downs(tab->key, Button_M1) > 0)
{ {
new_active_window_idx = tab->window_idx; new_active_window_idx = tab->window_idx;
} }
@ -3908,7 +3901,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.buttons[Button_M1].held) if (UI_Held(tab->key, Button_M1))
{ {
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)
@ -3919,7 +3912,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.buttons[Button_M1].ups > 0) if (is_dragging && UI_Ups(tab->key, Button_M1) > 0)
{ {
V.dragging_window = 0; V.dragging_window = 0;
} }
@ -3932,9 +3925,9 @@ void V_TickForever(WaveLaneCtx *lane)
border_color = theme.col.button_active; border_color = theme.col.button_active;
} }
bg_color = LerpSrgb(bg_color, theme.col.button_hot, tab_rep.hot); bg_color = LerpSrgb(bg_color, theme.col.button_hot, UI_Hot(tab->key));
bg_color = LerpSrgb(bg_color, theme.col.button_active, tab_rep.active * is_dragging); bg_color = LerpSrgb(bg_color, theme.col.button_active, UI_Active(tab->key) * is_dragging);
border_color = LerpSrgb(border_color, theme.col.button_active, tab_rep.misc); border_color = LerpSrgb(border_color, theme.col.button_active, UI_Misc(tab->key));
String tab_name = Zi; String tab_name = Zi;
if (window->is_tile_window) if (window->is_tile_window)
@ -3977,12 +3970,11 @@ void V_TickForever(WaveLaneCtx *lane)
// Build tab close button // Build tab close button
{ {
UI_Key close_key = UI_KeyF("close"); UI_Key close_key = UI_KeyF("close");
UI_BoxReport close_rep = UI_ReportsFromKey(close_key).draw;
Vec4 close_color = Zi; Vec4 close_color = Zi;
close_color = LerpSrgb(close_color, theme.col.button_hot, close_rep.hot); close_color = LerpSrgb(close_color, theme.col.button_hot, UI_Hot(close_key));
close_color = LerpSrgb(close_color, theme.col.button_active, close_rep.active); close_color = LerpSrgb(close_color, theme.col.button_active, UI_Active(close_key));
Vec4 close_border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.col.button_active, close_rep.hot); Vec4 close_border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.col.button_active, UI_Hot(close_key));
UI_SetNext(BackgroundColor, close_color); UI_SetNext(BackgroundColor, close_color);
UI_SetNext(BorderColor, close_border_color); UI_SetNext(BorderColor, close_border_color);
@ -4004,7 +3996,7 @@ void V_TickForever(WaveLaneCtx *lane)
} }
UI_PopCp(UI_TopCp()); UI_PopCp(UI_TopCp());
if (close_rep.buttons[Button_M1].presses) if (UI_Presses(close_key, Button_M1))
{ {
prune_windows[prune_windows_count] = window; prune_windows[prune_windows_count] = window;
prune_windows_count += 1; prune_windows_count += 1;
@ -4021,17 +4013,15 @@ void V_TickForever(WaveLaneCtx *lane)
case DrawableTabKind_Ghost: case DrawableTabKind_Ghost:
{ {
UI_BoxReport rep = UI_ReportsFromKey(tab->key).draw;
Vec4 bg_color = Zi; Vec4 bg_color = Zi;
bg_color = LerpSrgb(bg_color, theme.col.button_hot, rep.exists); bg_color = LerpSrgb(bg_color, theme.col.button_hot, UI_Exists(tab->key));
bg_color.w *= 0.5; bg_color.w *= 0.5;
Vec4 border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.col.button_active, rep.exists); Vec4 border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.col.button_active, UI_Exists(tab->key));
// UI_SetNext(Anchor, UI_Region_Center); // UI_SetNext(Anchor, UI_Region_Center);
UI_SetNext(Anchor, UI_Region_TopRight); UI_SetNext(Anchor, UI_Region_TopRight);
UI_SetNext(Scale, VEC2(rep.exists, 1)); UI_SetNext(Scale, VEC2(UI_Exists(tab->key), 1));
UI_SetNext(BackgroundColor, bg_color); UI_SetNext(BackgroundColor, bg_color);
UI_SetNext(BorderColor, border_color); UI_SetNext(BorderColor, border_color);
UI_SetNext(BorderSize, 2); UI_SetNext(BorderSize, 2);
@ -4052,13 +4042,12 @@ void V_TickForever(WaveLaneCtx *lane)
case DrawableTabKind_NewTab: case DrawableTabKind_NewTab:
{ {
UI_Key key = UI_KeyF("new tab"); UI_Key key = UI_KeyF("new tab");
UI_BoxReport rep = UI_ReportsFromKey(key).draw;
Vec4 bg_color = Zi; Vec4 bg_color = Zi;
bg_color = LerpSrgb(bg_color, theme.col.button_hot, rep.hot); bg_color = LerpSrgb(bg_color, theme.col.button_hot, UI_Hot(key));
bg_color = LerpSrgb(bg_color, theme.col.button_active, rep.active); bg_color = LerpSrgb(bg_color, theme.col.button_active, UI_Active(key));
bg_color.w *= 0.5; bg_color.w *= 0.5;
Vec4 border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.col.button_active, rep.hot); Vec4 border_color = LerpSrgb(VEC4(0, 0, 0, 0), theme.col.button_active, UI_Hot(key));
UI_SetNext(BackgroundColor, bg_color); UI_SetNext(BackgroundColor, bg_color);
UI_SetNext(BorderColor, border_color); UI_SetNext(BorderColor, border_color);
@ -4111,17 +4100,16 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
String tile_name = P_NameFromTileKind(tile_kind); String tile_name = P_NameFromTileKind(tile_kind);
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;
if (rep.buttons[Button_M1].downs) if (UI_Downs(key, Button_M1))
{ {
frame->edit_mode = V_EditMode_Tile; frame->edit_mode = V_EditMode_Tile;
frame->equipped_tile = tile_kind; frame->equipped_tile = tile_kind;
} }
Vec4 bg_color = Zi; Vec4 bg_color = Zi;
bg_color = LerpSrgb(bg_color, theme.col.button_hot, rep.hot); bg_color = LerpSrgb(bg_color, theme.col.button_hot, UI_Hot(key));
bg_color = LerpSrgb(bg_color, theme.col.button_active, rep.active); bg_color = LerpSrgb(bg_color, theme.col.button_active, UI_Active(key));
b32 is_selected = ( b32 is_selected = (
frame->edit_mode == V_EditMode_Tile && frame->edit_mode == V_EditMode_Tile &&
@ -4129,8 +4117,8 @@ void V_TickForever(WaveLaneCtx *lane)
); );
Vec4 border_color = Zi; Vec4 border_color = Zi;
border_color = LerpSrgb(border_color, theme.col.button_selected, rep.misc); border_color = LerpSrgb(border_color, theme.col.button_selected, UI_Misc(key));
border_color = LerpSrgb(border_color, theme.col.button_active, rep.hot); border_color = LerpSrgb(border_color, theme.col.button_active, UI_Hot(key));
UI_SetNext(BackgroundColor, bg_color); UI_SetNext(BackgroundColor, bg_color);
UI_SetNext(BorderColor, border_color); UI_SetNext(BorderColor, border_color);
@ -4185,17 +4173,16 @@ void V_TickForever(WaveLaneCtx *lane)
if (!AnyBit(prefab_flags, P_PrefabFlag_HideFromEditor)) if (!AnyBit(prefab_flags, P_PrefabFlag_HideFromEditor))
{ {
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;
if (rep.buttons[Button_M1].downs) if (UI_Downs(key, Button_M1))
{ {
frame->edit_mode = V_EditMode_Prefab; frame->edit_mode = V_EditMode_Prefab;
frame->equipped_prefab = prefab_kind; frame->equipped_prefab = prefab_kind;
} }
Vec4 bg_color = Zi; Vec4 bg_color = Zi;
bg_color = LerpSrgb(bg_color, theme.col.button_hot, rep.hot); bg_color = LerpSrgb(bg_color, theme.col.button_hot, UI_Hot(key));
bg_color = LerpSrgb(bg_color, theme.col.button_active, rep.active); bg_color = LerpSrgb(bg_color, theme.col.button_active, UI_Active(key));
b32 is_selected = ( b32 is_selected = (
frame->edit_mode == V_EditMode_Prefab && frame->edit_mode == V_EditMode_Prefab &&
@ -4203,8 +4190,8 @@ void V_TickForever(WaveLaneCtx *lane)
); );
Vec4 border_color = Zi; Vec4 border_color = Zi;
border_color = LerpSrgb(border_color, theme.col.button_selected, rep.misc); border_color = LerpSrgb(border_color, theme.col.button_selected, UI_Misc(key));
border_color = LerpSrgb(border_color, theme.col.button_active, rep.hot); border_color = LerpSrgb(border_color, theme.col.button_active, UI_Hot(key));
UI_SetNext(BackgroundColor, bg_color); UI_SetNext(BackgroundColor, bg_color);
UI_SetNext(BorderColor, border_color); UI_SetNext(BorderColor, border_color);
@ -4266,14 +4253,13 @@ void V_TickForever(WaveLaneCtx *lane)
if (panel->next != 0) if (panel->next != 0)
{ {
panel->divider_key = UI_KeyF("Divider"); panel->divider_key = UI_KeyF("Divider");
UI_BoxReport rep = UI_ReportsFromKey(panel->divider_key).draw;
Vec4 active_color = theme.col.button_active; Vec4 active_color = theme.col.button_active;
Vec4 hot_color = LerpSrgb(theme.col.button_hot, theme.col.button_active, 0.25); Vec4 hot_color = LerpSrgb(theme.col.button_hot, theme.col.button_active, 0.25);
Vec4 bg_color = Zi; Vec4 bg_color = Zi;
bg_color = LerpSrgb(bg_color, hot_color, rep.hot); bg_color = LerpSrgb(bg_color, hot_color, UI_Hot(panel->divider_key));
bg_color = LerpSrgb(bg_color, active_color, rep.active); bg_color = LerpSrgb(bg_color, active_color, UI_Active(panel->divider_key));
Vec4 border_color = Zi; Vec4 border_color = Zi;
f32 visible_size = 2.0; f32 visible_size = 2.0;
@ -4286,7 +4272,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.buttons[Button_M1].held) if (UI_TargetHot(panel->divider_key) || UI_Held(panel->divider_key, Button_M1))
{ {
if (panel->axis == Axis_X) if (panel->axis == Axis_X)
{ {
@ -4298,7 +4284,7 @@ void V_TickForever(WaveLaneCtx *lane)
} }
} }
if (rep.buttons[Button_M1].held) if (UI_Held(panel->divider_key, Button_M1))
{ {
panel->resizing = 1; panel->resizing = 1;
} }
@ -4379,45 +4365,37 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Key scrollbar_down_key = UI_KeyF("scrollbar down"); UI_Key scrollbar_down_key = UI_KeyF("scrollbar down");
UI_Key track_key = UI_KeyF("scrollbar track"); UI_Key track_key = UI_KeyF("scrollbar track");
UI_BoxReports scrollbar_reps = UI_ReportsFromKey(scrollbar_key); f32 lister_start = UI_Rect(lister_key).p0.y;
UI_BoxReports thumb_reps = UI_ReportsFromKey(thumb_key); f32 lister_end = UI_Rect(lister_key).p1.y;
UI_BoxReports scissor_reps = UI_ReportsFromKey(scissor_key);
UI_BoxReports lister_reps = UI_ReportsFromKey(lister_key);
UI_BoxReports scrollbar_up_reps = UI_ReportsFromKey(scrollbar_up_key);
UI_BoxReports scrollbar_down_reps = UI_ReportsFromKey(scrollbar_down_key);
UI_BoxReports track_reps = UI_ReportsFromKey(track_key);
f32 lister_start = lister_reps.draw.screen_rect.p0.y;
f32 lister_end = lister_reps.draw.screen_rect.p1.y;
f32 lister_height = MaxF32(lister_end - lister_start, 1); f32 lister_height = MaxF32(lister_end - lister_start, 1);
f32 scissor_start = scissor_reps.draw.screen_rect.p0.y; f32 scissor_start = UI_Rect(scissor_key).p0.y;
f32 scissor_end = scissor_reps.draw.screen_rect.p1.y; f32 scissor_end = UI_Rect(scissor_key).p1.y;
f32 scissor_height = MaxF32(scissor_end - scissor_start, 1); f32 scissor_height = MaxF32(scissor_end - scissor_start, 1);
f32 track_start = track_reps.draw.screen_rect.p0.y; f32 track_start = UI_Rect(track_key).p0.y;
f32 track_end = track_reps.draw.screen_rect.p1.y; f32 track_end = UI_Rect(track_key).p1.y;
f32 track_height = MaxF32(track_end - track_start, 1); f32 track_height = MaxF32(track_end - track_start, 1);
f32 thumb_start = thumb_reps.draw.screen_rect.p0.y; f32 thumb_start = UI_Rect(thumb_key).p0.y;
f32 thumb_end = thumb_reps.draw.screen_rect.p1.y; f32 thumb_end = UI_Rect(thumb_key).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 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);
{ {
i32 wheels = lister_reps.draw.buttons[Button_WheelDown].downs - lister_reps.draw.buttons[Button_WheelUp].downs; i32 wheels = UI_Downs(lister_key, Button_WheelDown) - UI_Downs(lister_key, Button_WheelUp);
if (thumb_reps.draw.buttons[Button_M1].downs) if (UI_Downs(thumb_key, Button_M1))
{ {
palette->drag_lister = lister_reps.draw.screen_rect; palette->drag_lister = UI_Rect(lister_key);
palette->drag_scissor = scissor_reps.draw.screen_rect; palette->drag_scissor = UI_Rect(scissor_key);
palette->drag_track = track_reps.draw.screen_rect; palette->drag_track = UI_Rect(track_key);
palette->drag_thumb = thumb_reps.draw.screen_rect; palette->drag_thumb = UI_Rect(thumb_key);
palette->drag_cursor = frame->screen_cursor; palette->drag_cursor = frame->screen_cursor;
palette->drag_scroll = palette->scroll; palette->drag_scroll = palette->scroll;
} }
if (thumb_reps.draw.buttons[Button_M1].held) if (UI_Held(thumb_key, Button_M1))
{ {
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;
@ -4455,20 +4433,18 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
UI_Push(Tag, palette->key.v); UI_Push(Tag, palette->key.v);
UI_Key titlebar_key = UI_KeyF("title bar"); UI_Key titlebar_key = UI_KeyF("title bar");
UI_BoxReports titlebar_reps = UI_ReportsFromKey(titlebar_key);
UI_BoxReports palette_reps = UI_ReportsFromKey(palette->key);
Vec4 window_background_color = theme.col.window_bg; Vec4 window_background_color = theme.col.window_bg;
Vec4 window_border_color = theme.col.window_bd; Vec4 window_border_color = theme.col.window_bd;
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.buttons[Button_M1].held) if (UI_Held(titlebar_key, Button_M1))
{ {
Vec2 drag_offset = SubVec2(ui_frame->drag_cursor_pos, palette_reps.drag.screen_anchor); Vec2 drag_offset = SubVec2(ui_frame->drag_cursor_pos, UI_DragAnchor(palette->key));
palette->pos = SubVec2(frame->screen_cursor, drag_offset); palette->pos = SubVec2(frame->screen_cursor, drag_offset);
} }
window_border_color = LerpSrgb(window_border_color, theme.col.button_active, titlebar_reps.draw.hot); window_border_color = LerpSrgb(window_border_color, theme.col.button_active, UI_Hot(titlebar_key));
f32 scale = LerpF32(0.85, 1, palette->show); f32 scale = LerpF32(0.85, 1, palette->show);
UI_Push(Tint, VEC4(1, 1, 1, palette->show)); UI_Push(Tint, VEC4(1, 1, 1, palette->show));
@ -4575,7 +4551,6 @@ void V_TickForever(WaveLaneCtx *lane)
//- Search box //- Search box
{ {
UI_Key search_box = UI_KeyF("search box"); UI_Key search_box = UI_KeyF("search box");
UI_BoxReport search_report = UI_ReportsFromKey(search_box).draw;
V_TextboxState *search_state = &palette->search_state; V_TextboxState *search_state = &palette->search_state;
b32 has_focus = UI_MatchKey(search_box, prev_frame->text_input_focus); b32 has_focus = UI_MatchKey(search_box, prev_frame->text_input_focus);
@ -4583,8 +4558,8 @@ void V_TickForever(WaveLaneCtx *lane)
// FIXME: Remove this // FIXME: Remove this
has_focus = 1; has_focus = 1;
// if (search_report.buttons[Button_M1].downs) // if (UI_Downs(search_box, Button_M1))
if (search_report.buttons[Button_M1].downs) if (UI_Downs(search_box, Button_M1))
{ {
has_focus = 1; has_focus = 1;
V.text_input_ns = frame->time_ns; V.text_input_ns = frame->time_ns;
@ -4595,7 +4570,7 @@ void V_TickForever(WaveLaneCtx *lane)
has_focus = 0; has_focus = 0;
} }
if (search_report.is_hot) if (UI_TargetHot(search_box))
{ {
WND_SetCursor(window_frame, WND_CursorKind_Text); WND_SetCursor(window_frame, WND_CursorKind_Text);
} }
@ -4902,8 +4877,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_BuildDivider(UI_PIX(1, 1), divider_color, Axis_Y); UI_BuildDivider(UI_PIX(1, 1), divider_color, Axis_Y);
} }
UI_BoxReport item_rep = UI_ReportsFromKey(item->key).draw; if (UI_Presses(item->key, Button_M1))
if (item_rep.buttons[Button_M1].presses)
{ {
if (item->flags & PaletteItemFlag_IsCmd) if (item->flags & PaletteItemFlag_IsCmd)
{ {
@ -4918,13 +4892,13 @@ void V_TickForever(WaveLaneCtx *lane)
Vec4 item_border_color = Zi; Vec4 item_border_color = Zi;
if (item->flags & PaletteItemFlag_IsCmd) if (item->flags & PaletteItemFlag_IsCmd)
{ {
item_color = LerpSrgb(item_color, theme.col.button_hot, item_rep.hot); item_color = LerpSrgb(item_color, theme.col.button_hot, UI_Hot(item->key));
item_color = LerpSrgb(item_color, theme.col.button_active, item_rep.active); item_color = LerpSrgb(item_color, theme.col.button_active, UI_Active(item->key));
item_border_color = LerpSrgb(item_border_color, theme.col.button_active, item_rep.hot); item_border_color = LerpSrgb(item_border_color, theme.col.button_active, UI_Hot(item->key));
} }
else else
{ {
item_border_color = LerpSrgb(item_border_color, theme.col.button_active, item_rep.hot); item_border_color = LerpSrgb(item_border_color, theme.col.button_active, UI_Hot(item->key));
} }
UI_SetNext(Tint, 0); UI_SetNext(Tint, 0);
@ -4969,27 +4943,26 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
// UI_BuildSpacer(UI_PIX(spacing * 0.5, 1), Axis_X); // UI_BuildSpacer(UI_PIX(spacing * 0.5, 1), Axis_X);
UI_Key reset_key = UI_KeyF("reset"); UI_Key reset_key = UI_KeyF("reset");
UI_BoxReport reset_rep = UI_ReportsFromKey(reset_key).draw;
if (reset_rep.buttons[Button_M1].downs > 0) if (UI_Downs(reset_key, Button_M1))
{ {
new_tweak_str = tweak_var.initial; new_tweak_str = tweak_var.initial;
} }
if (reset_rep.is_hot) if (UI_TargetHot(reset_key))
{ {
WND_SetCursor(window_frame, WND_CursorKind_Hand); WND_SetCursor(window_frame, WND_CursorKind_Hand);
} }
Vec4 reset_bg = Zi; Vec4 reset_bg = Zi;
// reset_bg = LerpSrgb(reset_bg, theme.col.button_hot, reset_rep.hot); // reset_bg = LerpSrgb(reset_bg, theme.col.button_hot, UI_Hot(reset_key));
// reset_bg = LerpSrgb(reset_bg, theme.col.button_active, reset_rep.active); // reset_bg = LerpSrgb(reset_bg, theme.col.button_active, UI_Active(reset_key));
Vec4 reset_bd = Zi; Vec4 reset_bd = Zi;
// reset_bd = LerpSrgb(reset_bd, theme.col.button_active, reset_rep.hot); // reset_bd = LerpSrgb(reset_bd, theme.col.button_active, UI_Hot(reset_key));
// reset_bd = LerpSrgb(reset_bd, theme.col.text, reset_rep.hot); // reset_bd = LerpSrgb(reset_bd, theme.col.text, UI_Hot(reset_key));
Vec4 reset_text_col = theme.col.hint; Vec4 reset_text_col = theme.col.hint;
reset_text_col = LerpSrgb(reset_text_col, theme.col.text, reset_rep.hot); reset_text_col = LerpSrgb(reset_text_col, theme.col.text, UI_Hot(reset_key));
UI_SetNext(Rounding, UI_RGROW(0.75 * theme.rounding)); UI_SetNext(Rounding, UI_RGROW(0.75 * theme.rounding));
UI_SetNext(ChildAlignment, UI_Region_Bottom); UI_SetNext(ChildAlignment, UI_Region_Bottom);
@ -5034,10 +5007,9 @@ void V_TickForever(WaveLaneCtx *lane)
case TweakKind_Bool: case TweakKind_Bool:
{ {
UI_Key cb_key = UI_KeyF("tweak checkbox"); UI_Key cb_key = UI_KeyF("tweak checkbox");
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.buttons[Button_M1].downs) if (UI_Downs(cb_key, Button_M1))
{ {
tweak_bool = !tweak_bool; tweak_bool = !tweak_bool;
new_tweak_str = StringFromBool(frame->arena, tweak_bool); new_tweak_str = StringFromBool(frame->arena, tweak_bool);
@ -5047,7 +5019,7 @@ void V_TickForever(WaveLaneCtx *lane)
Vec4 cb_bg_color = Zi; Vec4 cb_bg_color = Zi;
Vec4 cb_border_color = theme.col.window_bd; Vec4 cb_border_color = theme.col.window_bd;
cb_bg_color = LerpSrgb(cb_bg_color, theme.col.positive, tweak_bool); cb_bg_color = LerpSrgb(cb_bg_color, theme.col.positive, tweak_bool);
cb_border_color = LerpSrgb(cb_border_color, theme.col.button_active, cb_rep.hot); cb_border_color = LerpSrgb(cb_border_color, theme.col.button_active, UI_Hot(cb_key));
UI_SetNext(BackgroundColor, cb_bg_color); UI_SetNext(BackgroundColor, cb_bg_color);
UI_SetNext(BorderColor, cb_border_color); UI_SetNext(BorderColor, cb_border_color);
@ -5068,16 +5040,13 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Key slider_key = UI_KeyF("tweak slider"); UI_Key slider_key = UI_KeyF("tweak slider");
UI_Key marker_key = UI_KeyF("tweak slider marker"); UI_Key marker_key = UI_KeyF("tweak slider marker");
UI_BoxReports slider_reps = UI_ReportsFromKey(slider_key); b32 is_hot = UI_TargetHot(slider_key) || UI_TargetHot(marker_key);
UI_BoxReports marker_reps = UI_ReportsFromKey(marker_key); b32 is_active = UI_Held(slider_key, Button_M1) || UI_Held(marker_key, Button_M1);
f32 hot = MaxF32(UI_Hot(slider_key), UI_Hot(marker_key));
b32 is_hot = slider_reps.draw.is_hot || marker_reps.draw.is_hot; Vec2 slider_pos = UI_Rect(slider_key).p0;
b32 is_active = slider_reps.draw.buttons[Button_M1].held || marker_reps.draw.buttons[Button_M1].held; Vec2 slider_dims = DimsFromRng2(UI_Rect(slider_key));
f32 hot = MaxF32(slider_reps.draw.hot, marker_reps.draw.hot); Vec2 marker_dims = DimsFromRng2(UI_Rect(marker_key));
Vec2 slider_pos = slider_reps.draw.screen_rect.p0;
Vec2 slider_dims = DimsFromRng2(slider_reps.draw.screen_rect);
Vec2 marker_dims = DimsFromRng2(marker_reps.draw.screen_rect);
Vec2 half_marker_dims = MulVec2(marker_dims, 0.5); Vec2 half_marker_dims = MulVec2(marker_dims, 0.5);
f64 range_min = tweak_var.range.min; f64 range_min = tweak_var.range.min;
@ -5091,11 +5060,11 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
if (is_active) if (is_active)
{ {
f64 initial_slider_pos = slider_reps.drag.screen_rect.p0.x; f64 initial_slider_pos = UI_DragRect(slider_key).p0.x;
f64 initial_marker_width = DimsFromRng2(marker_reps.drag.screen_rect).x; f64 initial_marker_width = DimsFromRng2(UI_DragRect(marker_key)).x;
f64 initial_slider_width = DimsFromRng2(slider_reps.drag.screen_rect).x - initial_marker_width; f64 initial_slider_width = DimsFromRng2(UI_DragRect(slider_key)).x - initial_marker_width;
f64 initial_cursor = ui_frame->drag_cursor_pos.x; f64 initial_cursor = ui_frame->drag_cursor_pos.x;
f64 initial_ratio = slider_reps.drag.misc; f64 initial_ratio = UI_DragMisc(slider_key);
f64 virtual_slider_start = initial_cursor - (initial_slider_width * initial_ratio); f64 virtual_slider_start = initial_cursor - (initial_slider_width * initial_ratio);
f64 virtual_slider_end = virtual_slider_start + initial_slider_width; f64 virtual_slider_end = virtual_slider_start + initial_slider_width;
@ -5178,8 +5147,7 @@ void V_TickForever(WaveLaneCtx *lane)
// Command hotkey buttons // Command hotkey buttons
for (u64 i = 0; i < countof(item->hotkeys); ++i) for (u64 i = 0; i < countof(item->hotkeys); ++i)
{ {
UI_Key hotkey_key = UI_KeyF("hotkey%F", FmtUint(i)); UI_Key hotkey_box = UI_KeyF("hotkey%F", FmtUint(i));
UI_BoxReport hotkey_rep = UI_ReportsFromKey(hotkey_key).draw;
Vec4 hotkey_color = Zi; Vec4 hotkey_color = Zi;
Vec4 hotkey_border_color = Zi; Vec4 hotkey_border_color = Zi;
@ -5187,9 +5155,9 @@ void V_TickForever(WaveLaneCtx *lane)
Vec4 hovered_color = Rgb32(0x103c4c); Vec4 hovered_color = Rgb32(0x103c4c);
Vec4 pressed_color = hovered_color; Vec4 pressed_color = hovered_color;
pressed_color.w = 0.2; pressed_color.w = 0.2;
f32 hotkey_hot = hotkey_rep.hot; f32 hotkey_hot = UI_Hot(hotkey_box);
f32 hotkey_active = hotkey_rep.active; f32 hotkey_active = UI_Active(hotkey_box);
f32 hotkey_hovered = hotkey_rep.hovered; f32 hotkey_hovered = UI_Hovered(hotkey_box);
hotkey_color = LerpSrgb(hotkey_color, hovered_color, hotkey_hot); hotkey_color = LerpSrgb(hotkey_color, hovered_color, hotkey_hot);
hotkey_color = LerpSrgb(hotkey_color, pressed_color, hotkey_active * hotkey_hovered); hotkey_color = LerpSrgb(hotkey_color, pressed_color, hotkey_active * hotkey_hovered);
hotkey_border_color = LerpSrgb(hotkey_border_color, Rgb32(0x0078a6), hotkey_hot); hotkey_border_color = LerpSrgb(hotkey_border_color, Rgb32(0x0078a6), hotkey_hot);
@ -5214,7 +5182,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_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_CaptureMouse); UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_CaptureMouse);
UI_PushCp(UI_BuildRowEx(hotkey_key)); UI_PushCp(UI_BuildRowEx(hotkey_box));
{ {
} }
UI_PopCp(UI_TopCp()); UI_PopCp(UI_TopCp());
@ -5254,9 +5222,9 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
Vec4 col = theme.col.hint; Vec4 col = theme.col.hint;
Vec4 bd_col = Zi; Vec4 bd_col = Zi;
col = LerpSrgb(col, theme.col.button_active, scrollbar_up_reps.draw.active); col = LerpSrgb(col, theme.col.button_active, UI_Active(scrollbar_key));
bd_col = LerpSrgb(bd_col, theme.col.button_hot, scrollbar_up_reps.draw.hot); bd_col = LerpSrgb(bd_col, theme.col.button_hot, UI_Hot(scrollbar_key));
bd_col = LerpSrgb(bd_col, theme.col.button_active, scrollbar_up_reps.draw.active); bd_col = LerpSrgb(bd_col, theme.col.button_active, UI_Active(scrollbar_key));
UI_SetNext(ChildAlignment, UI_Region_Center); UI_SetNext(ChildAlignment, UI_Region_Center);
UI_SetNext(BorderColor, bd_col); UI_SetNext(BorderColor, bd_col);
UI_SetNext(BorderSize, 1); UI_SetNext(BorderSize, 1);
@ -5276,8 +5244,8 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
Vec4 bg = theme.col.button_hot; Vec4 bg = theme.col.button_hot;
Vec4 bd = bg; Vec4 bd = bg;
bg = LerpSrgb(bg, theme.col.button_active, thumb_reps.draw.active); bg = LerpSrgb(bg, theme.col.button_active, UI_Active(thumb_key));
bd = LerpSrgb(bg, theme.col.button_active, thumb_reps.draw.hot); bd = LerpSrgb(bg, theme.col.button_active, UI_Hot(thumb_key));
UI_SetNext(BackgroundColor, bg); UI_SetNext(BackgroundColor, bg);
UI_SetNext(Width, UI_GROW(1, 0)); UI_SetNext(Width, UI_GROW(1, 0));
@ -5300,9 +5268,9 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
Vec4 col = theme.col.hint; Vec4 col = theme.col.hint;
Vec4 bd_col = Zi; Vec4 bd_col = Zi;
col = LerpSrgb(col, theme.col.button_active, scrollbar_down_reps.draw.active); col = LerpSrgb(col, theme.col.button_active, UI_Active(scrollbar_down_key));
bd_col = LerpSrgb(bd_col, theme.col.button_hot, scrollbar_down_reps.draw.hot); bd_col = LerpSrgb(bd_col, theme.col.button_hot, UI_Hot(scrollbar_down_key));
bd_col = LerpSrgb(bd_col, theme.col.button_active, scrollbar_down_reps.draw.active); bd_col = LerpSrgb(bd_col, theme.col.button_active, UI_Active(scrollbar_down_key));
UI_SetNext(ChildAlignment, UI_Region_Center); UI_SetNext(ChildAlignment, UI_Region_Center);
UI_SetNext(BorderColor, bd_col); UI_SetNext(BorderColor, bd_col);
UI_SetNext(BorderSize, 1); UI_SetNext(BorderSize, 1);
@ -5333,9 +5301,9 @@ void V_TickForever(WaveLaneCtx *lane)
// if (scrollbar_visible) // if (scrollbar_visible)
// { // {
// Vec2 scrollbar_pos = scrollbar_reps.draw.screen_rect.p0; // Vec2 scrollbar_pos = scrollbar_reps.UI_Rect().p0;
// Vec2 scrollbar_dims = DimsFromRng2(scrollbar_reps.draw.screen_rect); // Vec2 scrollbar_dims = DimsFromRng2(scrollbar_reps.UI_Rect());
// Vec2 thumb_dims = DimsFromRng2(thumb_reps.draw.screen_rect); // Vec2 thumb_dims = DimsFromRng2(UI_Rect(thumb_key));
// // Vec2 half_thumb_dims = MulVec2(thumb_dims, 0.5); // // Vec2 half_thumb_dims = MulVec2(thumb_dims, 0.5);
@ -5379,7 +5347,7 @@ void V_TickForever(WaveLaneCtx *lane)
// UI_Size thumb_height = UI_FNT(10, 1); // UI_Size thumb_height = UI_FNT(10, 1);
// Vec4 thumb_color = VEC4(0, 0.5, 1, 1); // Vec4 thumb_color = VEC4(0, 0.5, 1, 1);
// thumb_color.a = thumb_reps.draw.hot * 0.5 + 0.5; // thumb_color.a = thumb_reps.UI_Hot() * 0.5 + 0.5;
// UI_SetNext(BackgroundColor, thumb_color); // UI_SetNext(BackgroundColor, thumb_color);
// UI_SetNext(Width, UI_GROW(1, 0)); // UI_SetNext(Width, UI_GROW(1, 0));
@ -5457,8 +5425,7 @@ void V_TickForever(WaveLaneCtx *lane)
profiler->ns_per_px = NsFromSeconds(0.010); profiler->ns_per_px = NsFromSeconds(0.010);
} }
UI_BoxReports profiler_graph_reports = UI_ReportsFromKey(profiler_graph_box); profiler->graph_dims = DimsFromRng2(UI_Rect(profiler_graph_box));
profiler->graph_dims = DimsFromRng2(profiler_graph_reports.draw.screen_rect);
//- Init test samples //- Init test samples
// // FIXME: Remove this // // FIXME: Remove this
@ -5528,10 +5495,7 @@ void V_TickForever(WaveLaneCtx *lane)
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_Size track_height = UI_FNT(4, 0);
UI_BoxReports main_reps = UI_ReportsFromKey(main_box); // Vec2 old_main_dims = DimsFromRng2(UI_Rect(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.x = MaxF32(old_main_dims.x, 1);
// old_main_dims.y = MaxF32(old_main_dims.y, 1); // old_main_dims.y = MaxF32(old_main_dims.y, 1);
@ -5544,11 +5508,11 @@ void V_TickForever(WaveLaneCtx *lane)
// } // }
// f32 old_cursor_offset_px = frame->screen_cursor.x - main_reps.draw.screen_rect.p0.x; // f32 old_cursor_offset_px = frame->screen_cursor.x - UI_Rect(main_box).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_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; // 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; f32 cursor_px = frame->screen_cursor.x - UI_Rect(main_box).p0.x;
i64 cursor_ns = (cursor_px * profiler->ns_per_px) + profiler->view_ns; i64 cursor_ns = (cursor_px * profiler->ns_per_px) + profiler->view_ns;
f32 view_offset_px = profiler->view_ns / profiler->ns_per_px; f32 view_offset_px = profiler->view_ns / profiler->ns_per_px;
@ -5566,7 +5530,7 @@ void V_TickForever(WaveLaneCtx *lane)
i32 zooms = main_reps.draw.buttons[Button_WheelDown].presses - main_reps.draw.buttons[Button_WheelUp].presses; i32 zooms = UI_Presses(main_box, Button_WheelDown) - UI_Presses(main_box, Button_WheelUp);
f32 zoom_factor = PowF32(prof_zoom_rate, zooms); f32 zoom_factor = PowF32(prof_zoom_rate, zooms);
profiler->ns_per_px *= zoom_factor; profiler->ns_per_px *= zoom_factor;
@ -5601,13 +5565,13 @@ void V_TickForever(WaveLaneCtx *lane)
if (main_reps.draw.buttons[Button_M3].downs) if (UI_Downs(main_box, Button_M3))
{ {
profiler->drag_view_ns = profiler->view_ns; profiler->drag_view_ns = profiler->view_ns;
profiler->drag_cursor_px = cursor_px; profiler->drag_cursor_px = cursor_px;
} }
if (main_reps.draw.buttons[Button_M3].held) if (UI_Held(main_box, Button_M3))
{ {
profiler->view_ns = profiler->drag_view_ns - ((cursor_px - profiler->drag_cursor_px) * profiler->ns_per_px); profiler->view_ns = profiler->drag_view_ns - ((cursor_px - profiler->drag_cursor_px) * profiler->ns_per_px);
} }
@ -5837,7 +5801,6 @@ void V_TickForever(WaveLaneCtx *lane)
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_ReportsFromKey(zone_box).draw;
Vec4 zone_color = zone->color; Vec4 zone_color = zone->color;
@ -5853,7 +5816,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Size zone_width = UI_PIX(zone_len_px, 1); UI_Size zone_width = UI_PIX(zone_len_px, 1);
if (do_break && zone_rep.is_hovered) if (do_break && UI_TargetHovered(zone_box))
{ {
UI_SetNext(DebugBreakFlags, UI_DebugBreakFlag_BuildReport); UI_SetNext(DebugBreakFlags, UI_DebugBreakFlag_BuildReport);
UI_SetNext(Text, StringF(frame->arena, "ZONE %F", FmtUint(zone_idx))); UI_SetNext(Text, StringF(frame->arena, "ZONE %F", FmtUint(zone_idx)));
@ -5886,7 +5849,7 @@ void V_TickForever(WaveLaneCtx *lane)
// Vec2 timeline_cursor_pos = VEC2(old_cursor_offset_px, 0); // 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); Vec2 timeline_cursor_pos = VEC2((cursor_ns - profiler->view_ns) / profiler->ns_per_px, 0);
Vec4 timeline_cursor_color = theme.col.window_bd; Vec4 timeline_cursor_color = theme.col.window_bd;
timeline_cursor_color.a = main_reps.draw.hot; timeline_cursor_color.a = UI_Hot(main_box);
UI_SetNext(Width, UI_FNT(0.15, 1)); UI_SetNext(Width, UI_FNT(0.15, 1));
UI_SetNext(Height, UI_GROW(1, 0)); UI_SetNext(Height, UI_GROW(1, 0));
@ -5938,8 +5901,8 @@ void V_TickForever(WaveLaneCtx *lane)
// { // {
// profiler->is_showing = 1; // profiler->is_showing = 1;
// UI_BoxReports profiler_graph_reports = UI_ReportsFromKey(profiler_graph_box); // UI_BoxReports profiler_graph_box = UI_ReportsFromKey(profiler_graph_box);
// profiler->graph_dims = DimsFromRng2(profiler_graph_reports.draw.screen_rect); // profiler->graph_dims = DimsFromRng2(profiler_graph_box.UI_Rect());
// //- Init test samples // //- Init test samples
// // // FIXME: Remove this // // // FIXME: Remove this
@ -6008,10 +5971,10 @@ void V_TickForever(WaveLaneCtx *lane)
// 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_BoxReports main_reps = UI_ReportsFromKey(main_box); // UI_BoxReports main_box = UI_ReportsFromKey(main_box);
// Vec2 old_main_dims = DimsFromRng2(main_reps.draw.screen_rect); // Vec2 old_main_dims = DimsFromRng2(UI_Rect(main_box));
// old_main_dims.x = MaxF32(old_main_dims.x, 1); // old_main_dims.x = MaxF32(old_main_dims.x, 1);
// old_main_dims.y = MaxF32(old_main_dims.y, 1); // old_main_dims.y = MaxF32(old_main_dims.y, 1);
@ -6024,7 +5987,7 @@ void V_TickForever(WaveLaneCtx *lane)
// } // }
// f32 old_cursor_offset_px = frame->screen_cursor.x - main_reps.draw.screen_rect.p0.x; // f32 old_cursor_offset_px = frame->screen_cursor.x - UI_Rect(main_box).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_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; // i64 old_cursor_ns = profiler->view_start_ns + old_cursor_offset_ns;
@ -6035,31 +5998,31 @@ void V_TickForever(WaveLaneCtx *lane)
// // FIXME: Remove this // // FIXME: Remove this
// f32 prof_zoom_rate = 2; // 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_box.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 -= NsFromSeconds(1) * main_box.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_start_ns -= main_box.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_end_ns += main_box.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_start_ns -= main_box.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; // // profiler->view_end_ns += main_box.draw.buttons[Button_WheelDown].presses * ns_to_right * prof_zoom_rate;
// if (main_reps.draw.buttons[Button_WheelUp].presses) // if (main_box.draw.buttons[Button_WheelUp].presses)
// { // {
// DEBUGBREAKABLE; // DEBUGBREAKABLE;
// } // }
// // profiler->view_start_ns += main_reps.draw.buttons[Button_WheelUp].presses * ns_to_left / prof_zoom_rate; // // profiler->view_start_ns += main_box.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; // // profiler->view_end_ns -= main_box.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) // for (i32 zoom_idx = 0; zoom_idx < main_box.draw.buttons[Button_WheelUp].presses; ++zoom_idx)
// { // {
// i64 ns_to_left = old_cursor_ns - profiler->view_start_ns; // i64 ns_to_left = old_cursor_ns - profiler->view_start_ns;
// i64 ns_to_right = profiler->view_end_ns - old_cursor_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_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; // 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) // for (i32 zoom_idx = 0; zoom_idx < main_box.draw.buttons[Button_WheelDown].presses; ++zoom_idx)
// { // {
// i64 ns_to_left = old_cursor_ns - profiler->view_start_ns; // i64 ns_to_left = old_cursor_ns - profiler->view_start_ns;
// i64 ns_to_right = profiler->view_end_ns - old_cursor_ns; // i64 ns_to_right = profiler->view_end_ns - old_cursor_ns;
@ -6067,13 +6030,13 @@ void V_TickForever(WaveLaneCtx *lane)
// profiler->view_end_ns += (profiler->view_end_ns - old_cursor_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) // if (main_box.draw.buttons[Button_M3].downs)
// { // {
// profiler->drag_view_start_ns = profiler->view_start_ns; // profiler->drag_view_start_ns = profiler->view_start_ns;
// profiler->drag_cursor_ns = old_cursor_ns; // profiler->drag_cursor_ns = old_cursor_ns;
// } // }
// if (main_reps.draw.buttons[Button_M3].held) // if (main_box.draw.buttons[Button_M3].held)
// { // {
// // i64 ns_delta = prev_frame->profiler. // // i64 ns_delta = prev_frame->profiler.
// i64 ns_delta = old_cursor_ns - profiler->drag_cursor_ns; // i64 ns_delta = old_cursor_ns - profiler->drag_cursor_ns;
@ -6180,7 +6143,7 @@ void V_TickForever(WaveLaneCtx *lane)
// 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_box = UI_ReportFromKey(zone_box).draw;
// Vec4 zone_color = zone->color; // Vec4 zone_color = zone->color;
@ -6213,7 +6176,7 @@ void V_TickForever(WaveLaneCtx *lane)
// // Vec2 timeline_cursor_pos = VEC2(old_cursor_offset_px, 0); // // 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); // Vec2 timeline_cursor_pos = VEC2((old_cursor_ns - profiler->view_start_ns) / ns_per_px, 0);
// Vec4 timeline_cursor_color = theme.col.window_bd; // Vec4 timeline_cursor_color = theme.col.window_bd;
// timeline_cursor_color.a = main_reps.draw.hot; // timeline_cursor_color.a = UI_Hot(main_box);
// UI_SetNext(Width, UI_FNT(0.15, 1)); // UI_SetNext(Width, UI_FNT(0.15, 1));
// UI_SetNext(Height, UI_GROW(1, 0)); // UI_SetNext(Height, UI_GROW(1, 0));
@ -6269,13 +6232,12 @@ void V_TickForever(WaveLaneCtx *lane)
// Build notification UI // Build notification UI
{ {
UI_Key notifs_key = UI_KeyF("notifs"); UI_Key notifs_key = UI_KeyF("notifs");
UI_BoxReport notifs_rep = UI_ReportsFromKey(notifs_key).draw;
f32 width = 600; f32 width = 600;
Vec2 pos = Zi; Vec2 pos = Zi;
pos.x = 10; pos.x = 10;
// pos.y = frame->screen_dims.y * 0.5 - DimsFromRng2(notifs_rep.screen_rect).y * 0.5; // pos.y = frame->screen_dims.y * 0.5 - DimsFromRng2(UI_Rect(notifs_key.screen_rect)).y * 0.5;
pos.y = 10; pos.y = 10;
// Vec4 bg = VEC4(0, 0, 0, 0.25); // Vec4 bg = VEC4(0, 0, 0, 0.25);
@ -6383,8 +6345,7 @@ void V_TickForever(WaveLaneCtx *lane)
if (frame->show_console) if (frame->show_console)
{ {
UI_Key dbg_box = UI_KeyF("Debug box"); UI_Key dbg_box = UI_KeyF("Debug box");
UI_BoxReport dbg_rep = UI_ReportsFromKey(dbg_box).draw; Vec2 dbg_dims = DimsFromRng2(UI_Rect(dbg_box));
Vec2 dbg_dims = DimsFromRng2(dbg_rep.screen_rect);
f32 padding = 20; f32 padding = 20;
f32 rounding = 15 * theme.rounding; f32 rounding = 15 * theme.rounding;

View File

@ -542,20 +542,6 @@ UI_ButtonState *UI_SignalButton(UI_Key key, Button button)
return &n->cmd.signal.button_state; return &n->cmd.signal.button_state;
} }
////////////////////////////////////////////////////////////
//~ Report
UI_BoxReports UI_ReportsFromKey(UI_Key key)
{
UI_BoxReports result = Zi;
UI_Box *box = UI_BoxFromKey(key);
if (box)
{
result = box->reports;
}
return result;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Begin frame //~ Begin frame
@ -634,315 +620,315 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
frame->frame_flags = frame_flags; frame->frame_flags = frame_flags;
////////////////////////////// //////////////////////////////
//- Process controller events into signals //- Build feedback data
frame->cursor_pos = prev_frame->cursor_pos; frame->cursor_pos = prev_frame->cursor_pos;
frame->drag_cursor_pos = prev_frame->drag_cursor_pos; frame->drag_cursor_pos = prev_frame->drag_cursor_pos;
if (prev_frame->boxes_pre != 0) // if (prev_frame->boxes_pre != 0)
{
ControllerEventsArray controller_events = frame->window_frame.controller_events;
//- Locate boxes
UI_Box *top_hovered_box = 0;
UI_Box *active_box = UI_BoxFromKey(prev_frame->active_box);
//- 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)
{
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];
UI_BoxReport *report = &box->reports.draw;
b32 is_cursor_in_box = 0;
{
// TODO: More efficient test. This logic is just copied from the renderer's SDF function for now.
Rng2 interactable_region = IntersectRng2(box->solved_scissor, box->screen_rect);
Vec2 p0 = interactable_region.p0;
Vec2 p1 = interactable_region.p1;
Vec2 point = frame->cursor_pos;
b32 is_corner = 0;
f32 non_corner_edge_dist = MinF32(MinF32(point.x - p0.x, p1.x - point.x), MinF32(point.y - p0.y, p1.y - point.y));
f32 corner_edge_dist = non_corner_edge_dist;
if (non_corner_edge_dist >= 0)
{
f32 tl_radius = box->rounding_tl;
f32 tr_radius = box->rounding_tr;
f32 br_radius = box->rounding_br;
f32 bl_radius = box->rounding_bl;
Vec2 tl = VEC2(p0.x + tl_radius, p0.y + tl_radius);
Vec2 tr = VEC2(p1.x - tr_radius, p0.y + tr_radius);
Vec2 br = VEC2(p1.x - br_radius, p1.y - br_radius);
Vec2 bl = VEC2(p0.x + bl_radius, p1.y - bl_radius);
if (point.x < tl.x && point.y < tl.y) corner_edge_dist = MinF32(corner_edge_dist, tl_radius - Vec2Len(SubVec2(tl, point)));
if (point.x > tr.x && point.y < tr.y) corner_edge_dist = MinF32(corner_edge_dist, tr_radius - Vec2Len(SubVec2(tr, point)));
if (point.x > br.x && point.y > br.y) corner_edge_dist = MinF32(corner_edge_dist, br_radius - Vec2Len(SubVec2(br, point)));
if (point.x < bl.x && point.y > bl.y) corner_edge_dist = MinF32(corner_edge_dist, bl_radius - Vec2Len(SubVec2(bl, point)));
}
is_cursor_in_box = non_corner_edge_dist >= 0 && corner_edge_dist >= 0;
}
report->is_hovered = is_cursor_in_box;
if (top_hovered_box == 0 && (box->desc.flags & UI_BoxFlag_CaptureMouse) && is_cursor_in_box)
{
top_hovered_box = box;
}
for (u64 button_idx = 0; button_idx < countof(report->buttons); ++button_idx)
{
UI_ButtonState *br = &report->buttons[button_idx];
b32 old_held = br->held;
{
ZeroStruct(br);
}
br->held = old_held;
}
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)
{
default: break;
case ControllerEventKind_ButtonDown:
{
if (IsClickButton(cev->button) || IsWheelButton(cev->button))
{
mouse_downs += 1;
if (top_hovered_box && active_box == 0)
{
if (cev->button == Button_M1)
{
++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)
{
++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)
{
++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)
{
++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_WheelDown)
{
++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 (active_box)
{
if (cev->button == Button_M1)
{
if (active_box == top_hovered_box)
{
++active_box->reports.draw.buttons[Button_M1].presses;
}
++active_box->reports.draw.buttons[Button_M1].ups;
if (active_box->reports.draw.buttons[Button_M1].held)
{
active_box->reports.draw.buttons[Button_M1].held = 0;
active_box = 0;
}
}
else if (cev->button == Button_M2)
{
if (active_box == top_hovered_box)
{
++active_box->reports.draw.buttons[Button_M2].presses;
}
++active_box->reports.draw.buttons[Button_M2].ups;
if (active_box->reports.draw.buttons[Button_M2].held)
{
active_box->reports.draw.buttons[Button_M2].held = 0;
active_box = 0;
}
}
else if (cev->button == Button_M3)
{
if (active_box == top_hovered_box)
{
++active_box->reports.draw.buttons[Button_M3].presses;
}
++active_box->reports.draw.buttons[Button_M3].ups;
if (active_box->reports.draw.buttons[Button_M3].held)
{
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:
{
SignalExit(0);
} break;
}
}
UI_Box *hot_box = active_box;
if (top_hovered_box && !active_box)
{
hot_box = top_hovered_box;
}
if (hot_box)
{
// hot_box->reports.tree_capture = hot_box->key;
}
//- Update reports from signals
for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
{
UI_Cmd cmd = cmd_node->cmd;
if (cmd.kind == UI_CmdKind_Signal)
{
UI_Box *box = UI_BoxFromKey(cmd.signal.key);
if (box)
{
Button button = cmd.signal.button;
UI_ButtonState state = cmd.signal.button_state;
box->reports.draw.buttons[button] = state;
// Propagate button state upwards
for (UI_Box *parent = box->parent; parent; parent = parent->parent)
{
if (parent->desc.flags & UI_BoxFlag_CaptureThroughChildren)
{
parent->reports.draw.buttons[button] = state;
}
}
}
}
}
//- Update box reports from inputs
// { // {
// f32 lower_target = TweakFloat("UI lower blend target", -0.05, -1, 0); // ControllerEventsArray controller_events = frame->window_frame.controller_events;
// f32 upper_target = TweakFloat("UI upper blend target", 1.05, 1, 10);
// //- Locate boxes
// UI_Box *top_hovered_box = 0;
// UI_Box *active_box = UI_BoxFromKey(prev_frame->active_box);
// //- 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)
// {
// 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;) // 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;
// UI_DebugBreak(box, UI_DebugBreakFlag_BuildReport); // b32 is_cursor_in_box = 0;
// if (box == hot_box)
// { // {
// report->is_hot = 1; // // TODO: More efficient test. This logic is just copied from the renderer's SDF function for now.
// box->reports.tree_capture = box->key; // Rng2 interactable_region = IntersectRng2(box->solved_scissor, box->screen_rect);
// Vec2 p0 = interactable_region.p0;
// Vec2 p1 = interactable_region.p1;
// Vec2 point = frame->cursor_pos;
// b32 is_corner = 0;
// f32 non_corner_edge_dist = MinF32(MinF32(point.x - p0.x, p1.x - point.x), MinF32(point.y - p0.y, p1.y - point.y));
// f32 corner_edge_dist = non_corner_edge_dist;
// if (non_corner_edge_dist >= 0)
// {
// f32 tl_radius = box->rounding_tl;
// f32 tr_radius = box->rounding_tr;
// f32 br_radius = box->rounding_br;
// f32 bl_radius = box->rounding_bl;
// Vec2 tl = VEC2(p0.x + tl_radius, p0.y + tl_radius);
// Vec2 tr = VEC2(p1.x - tr_radius, p0.y + tr_radius);
// Vec2 br = VEC2(p1.x - br_radius, p1.y - br_radius);
// Vec2 bl = VEC2(p0.x + bl_radius, p1.y - bl_radius);
// if (point.x < tl.x && point.y < tl.y) corner_edge_dist = MinF32(corner_edge_dist, tl_radius - Vec2Len(SubVec2(tl, point)));
// if (point.x > tr.x && point.y < tr.y) corner_edge_dist = MinF32(corner_edge_dist, tr_radius - Vec2Len(SubVec2(tr, point)));
// if (point.x > br.x && point.y > br.y) corner_edge_dist = MinF32(corner_edge_dist, br_radius - Vec2Len(SubVec2(br, point)));
// if (point.x < bl.x && point.y > bl.y) corner_edge_dist = MinF32(corner_edge_dist, bl_radius - Vec2Len(SubVec2(bl, point)));
// }
// is_cursor_in_box = non_corner_edge_dist >= 0 && corner_edge_dist >= 0;
// }
// report->is_hovered = is_cursor_in_box;
// if (top_hovered_box == 0 && (box->desc.flags & UI_BoxFlag_CaptureMouse) && is_cursor_in_box)
// {
// top_hovered_box = box;
// }
// for (u64 button_idx = 0; button_idx < countof(report->buttons); ++button_idx)
// {
// UI_ButtonState *br = &report->buttons[button_idx];
// b32 old_held = br->held;
// {
// ZeroStruct(br);
// }
// br->held = old_held;
// }
// report->is_hot = 0;
// } // }
// // if (!UI_MatchKey(box->reports.tree_capture, box->reports.old_tree_capture)) // //- 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)
// {
// default: break;
// case ControllerEventKind_ButtonDown:
// {
// if (IsClickButton(cev->button) || IsWheelButton(cev->button))
// {
// mouse_downs += 1;
// if (top_hovered_box && active_box == 0)
// {
// if (cev->button == Button_M1)
// {
// ++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)
// {
// ++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)
// {
// ++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)
// {
// ++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_WheelDown)
// {
// ++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 (active_box)
// {
// if (cev->button == Button_M1)
// {
// if (active_box == top_hovered_box)
// {
// ++active_box->reports.draw.buttons[Button_M1].presses;
// }
// ++active_box->reports.draw.buttons[Button_M1].ups;
// if (active_box->reports.draw.buttons[Button_M1].held)
// {
// active_box->reports.draw.buttons[Button_M1].held = 0;
// active_box = 0;
// }
// }
// else if (cev->button == Button_M2)
// {
// if (active_box == top_hovered_box)
// {
// ++active_box->reports.draw.buttons[Button_M2].presses;
// }
// ++active_box->reports.draw.buttons[Button_M2].ups;
// if (active_box->reports.draw.buttons[Button_M2].held)
// {
// active_box->reports.draw.buttons[Button_M2].held = 0;
// active_box = 0;
// }
// }
// else if (cev->button == Button_M3)
// {
// if (active_box == top_hovered_box)
// {
// ++active_box->reports.draw.buttons[Button_M3].presses;
// }
// ++active_box->reports.draw.buttons[Button_M3].ups;
// if (active_box->reports.draw.buttons[Button_M3].held)
// {
// 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:
// {
// SignalExit(0);
// } break;
// }
// }
// UI_Box *hot_box = active_box;
// if (top_hovered_box && !active_box)
// {
// hot_box = top_hovered_box;
// }
// if (hot_box)
// {
// // hot_box->reports.tree_capture = hot_box->key;
// }
// //- Update reports from signals
// for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
// {
// UI_Cmd cmd = cmd_node->cmd;
// if (cmd.kind == UI_CmdKind_Signal)
// {
// UI_Box *box = UI_BoxFromKey(cmd.signal.key);
// if (box)
// {
// Button button = cmd.signal.button;
// UI_ButtonState state = cmd.signal.button_state;
// box->reports.draw.buttons[button] = state;
// // Propagate button state upwards
// for (UI_Box *parent = box->parent; parent; parent = parent->parent)
// {
// if (parent->desc.flags & UI_BoxFlag_CaptureThroughChildren)
// {
// parent->reports.draw.buttons[button] = state;
// }
// }
// }
// }
// }
// //- Update box reports from inputs
// // { // // {
// // for (u64 button_idx = 0; button_idx < countof(report->buttons); ++button_idx) // // f32 lower_target = TweakFloat("UI lower blend target", -0.05, -1, 0);
// // f32 upper_target = TweakFloat("UI upper blend target", 1.05, 1, 10);
// // for (u64 pre_index = UI.boxes_count; pre_index-- > 0;)
// // { // // {
// // UI_ButtonState *button = &report->buttons[button_idx]; // // UI_Box *box = prev_frame->boxes_pre[pre_index];
// // if (button->held) // // UI_BoxReport *report = &box->reports.draw;
// // UI_DebugBreak(box, UI_DebugBreakFlag_BuildReport);
// // if (box == hot_box)
// // { // // {
// // button->held = 0; // // report->is_hot = 1;
// // button->ups += 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_ButtonState *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;
// // f32 target_hot = report->is_hot ? Inf : lower_target;
// // f32 target_active = box == active_box ? Inf : lower_target;
// // f64 target_misc = box->desc.misc;
// // // TODO: Configurable per-box blend rates
// // f32 exists_blend_rate = (30 * frame->dt);
// // f32 hot_blend_rate = (15 * frame->dt);
// // f32 active_blend_rate = (15 * frame->dt);
// // f32 hovered_blend_rate = (15 * frame->dt);
// // // f64 misc_blend_rate = (30 * frame->dt);
// // f64 misc_blend_rate = 1;
// // report->exists = SaturateF32(LerpF32(report->exists, target_exists, exists_blend_rate));
// // report->hot = SaturateF32(LerpF32(report->hot, target_hot, hot_blend_rate));
// // report->active = SaturateF32(LerpF32(report->active, target_active, active_blend_rate));
// // report->hovered = SaturateF32(LerpF32(report->hovered, target_hovered, hovered_blend_rate));
// // report->misc = SaturateF32(LerpF32(report->misc, target_misc, misc_blend_rate));
// // report->screen_rect = box->screen_rect;
// // report->screen_anchor = box->screen_anchor;
// // if (mouse_downs > 0)
// // {
// // 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.captures = captured_child->reports.draw.captures;
// // }
// // } // // }
// // } // // }
// // } // // }
// 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_hot = report->is_hot ? Inf : lower_target;
// f32 target_active = box == active_box ? Inf : lower_target;
// f64 target_misc = box->desc.misc;
// // TODO: Configurable per-box blend rates
// f32 exists_blend_rate = (30 * frame->dt);
// f32 hot_blend_rate = (15 * frame->dt);
// f32 active_blend_rate = (15 * frame->dt);
// f32 hovered_blend_rate = (15 * frame->dt);
// // f64 misc_blend_rate = (30 * frame->dt);
// f64 misc_blend_rate = 1;
// report->exists = SaturateF32(LerpF32(report->exists, target_exists, exists_blend_rate));
// report->hot = SaturateF32(LerpF32(report->hot, target_hot, hot_blend_rate));
// report->active = SaturateF32(LerpF32(report->active, target_active, active_blend_rate));
// report->hovered = SaturateF32(LerpF32(report->hovered, target_hovered, hovered_blend_rate));
// report->misc = SaturateF32(LerpF32(report->misc, target_misc, misc_blend_rate));
// report->screen_rect = box->screen_rect;
// report->screen_anchor = box->screen_anchor;
// if (mouse_downs > 0) // if (mouse_downs > 0)
// { // {
// box->reports.drag = *report; // frame->drag_cursor_pos = frame->cursor_pos;
// } // }
// // Propagate upwards captures to tree // frame->top_hovered_box = top_hovered_box ? top_hovered_box->key : UI_NilKey;
// if (box->parent && !UI_IsKeyNil(box->reports.tree_capture)) // frame->hot_box = hot_box ? hot_box->key : UI_NilKey;
// { // frame->active_box = active_box ? active_box->key : UI_NilKey;
// 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.captures = captured_child->reports.draw.captures;
// } // }
// }
// }
// }
if (mouse_downs > 0)
{
frame->drag_cursor_pos = frame->cursor_pos;
}
frame->top_hovered_box = top_hovered_box ? top_hovered_box->key : UI_NilKey;
frame->hot_box = hot_box ? hot_box->key : UI_NilKey;
frame->active_box = active_box ? active_box->key : UI_NilKey;
}
////////////////////////////// //////////////////////////////
//- Build root box //- Build root box
@ -1361,9 +1347,139 @@ Arena *UI_FrameArena(void)
return UI_CurrentFrame()->arena; return UI_CurrentFrame()->arena;
} }
////////////////////////////////////////////////////////////
//~ Feedback
//- Input
i32 UI_Downs(UI_Key key, Button button)
{
i32 result = Zi;
return result;
}
b32 UI_Held(UI_Key key, Button button)
{
b32 result = Zi;
return result;
}
b32 UI_Ups(UI_Key key, Button button)
{
b32 result = Zi;
return result;
}
b32 UI_Presses(UI_Key key, Button button)
{
b32 result = Zi;
return result;
}
//- Interaction
f32 UI_Exists(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_TargetExists(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_Hovered(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_TargetHovered(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_Active(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_TargetActive(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_Hot(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_TargetHot(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_Misc(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_DragMisc(UI_Key key)
{
f32 result = Zi;
return result;
}
f32 UI_TargetMisc(UI_Key key)
{
f32 result = Zi;
return result;
}
//- Layout
Vec2 UI_Anchor(UI_Key key)
{
Vec2 result = Zi;
return result;
}
Vec2 UI_DragAnchor(UI_Key key)
{
Vec2 result = Zi;
return result;
}
Rng2 UI_Rect(UI_Key key)
{
Rng2 result = Zi;
return result;
}
Rng2 UI_DragRect(UI_Key key)
{
Rng2 result = Zi;
return result;
}
Vec2 UI_CursorPos(void) Vec2 UI_CursorPos(void)
{ {
return UI_CurrentFrame()->cursor_pos; Vec2 result = Zi;
return result;
}
Vec2 UI_DragCursorPos(void)
{
Vec2 result = Zi;
return result;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -219,33 +219,34 @@ Struct(UI_ButtonState)
i32 presses; // Mouse button events while box is active and hovered i32 presses; // Mouse button events while box is active and hovered
}; };
//////////////////////////////////////////////////////////// Struct(UI_InputState)
//~ Report types
Struct(UI_CapturesReport)
{ {
b32 is_hovered;
b32 is_hot;
UI_ButtonState buttons[Button_COUNT]; UI_ButtonState buttons[Button_COUNT];
}; };
Struct(UI_BoxReport) ////////////////////////////////////////////////////////////
{ //~ Report types
Embed(UI_CapturesReport, captures);
Rng2 screen_rect;
Vec2 screen_anchor;
f32 exists;
f32 hovered;
f32 hot;
f32 active;
f64 misc;
};
Struct(UI_BoxReports) // Struct(UI_BoxReport)
{ // {
UI_BoxReport draw; // Box data used for last render // Rng2 screen_rect;
UI_BoxReport drag; // Box data during last mouse button down event // Vec2 screen_anchor;
};
// b32 is_hovered;
// b32 is_hot;
// f32 exists;
// f32 hovered;
// f32 hot;
// f32 active;
// f64 misc;
// };
// Struct(UI_BoxReports)
// {
// UI_BoxReport draw; // Box data used for last render
// UI_BoxReport drag; // Box data during last mouse button down event
// };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Command types //~ Command types
@ -329,7 +330,6 @@ Struct(UI_Box)
//- Persistent data //- Persistent data
UI_Box *next_in_bin; UI_Box *next_in_bin;
UI_Box *prev_in_bin; UI_Box *prev_in_bin;
UI_BoxReports reports;
i64 last_build_tick; i64 last_build_tick;
i64 old_gen; i64 old_gen;
@ -421,9 +421,11 @@ Struct(UI_Frame)
i64 dt_ns; i64 dt_ns;
f32 dt; f32 dt;
// Control // Input
Vec2 cursor_pos; Vec2 cursor_pos;
Vec2 drag_cursor_pos; Vec2 drag_cursor_pos;
UI_InputState input_state;
UI_InputState drag_input_state;
UI_Key top_hovered_box; UI_Key top_hovered_box;
UI_Key hot_box; UI_Key hot_box;
@ -560,10 +562,6 @@ UI_ButtonState *UI_SignalButton(UI_Key key, Button button);
#define UI_DebugBreak(...) #define UI_DebugBreak(...)
#endif #endif
////////////////////////////////////////////////////////////
//~ Report
UI_BoxReports UI_ReportsFromKey(UI_Key key);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Begin frame //~ Begin frame
@ -576,7 +574,45 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags);
UI_Frame *UI_CurrentFrame(void); UI_Frame *UI_CurrentFrame(void);
UI_Frame *UI_PrevFrame(void); UI_Frame *UI_PrevFrame(void);
Arena *UI_FrameArena(void); Arena *UI_FrameArena(void);
////////////////////////////////////////////////////////////
//~ Feedback
//- Input
i32 UI_Downs(UI_Key key, Button button);
b32 UI_Held(UI_Key key, Button button);
b32 UI_Ups(UI_Key key, Button button);
b32 UI_Presses(UI_Key key, Button button);
//- Interaction
f32 UI_Exists(UI_Key key);
f32 UI_TargetExists(UI_Key key);
f32 UI_Hovered(UI_Key key);
f32 UI_TargetHovered(UI_Key key);
f32 UI_Active(UI_Key key);
f32 UI_TargetActive(UI_Key key);
f32 UI_Hot(UI_Key key);
f32 UI_TargetHot(UI_Key key);
f32 UI_Misc(UI_Key key);
f32 UI_DragMisc(UI_Key key);
f32 UI_TargetMisc(UI_Key key);
//- Layout
Vec2 UI_Anchor(UI_Key key);
Vec2 UI_DragAnchor(UI_Key key);
Rng2 UI_Rect(UI_Key key);
Rng2 UI_DragRect(UI_Key key);
Vec2 UI_CursorPos(void); Vec2 UI_CursorPos(void);
Vec2 UI_DragCursorPos(void);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Layout helpers //~ Layout helpers