UI debug break

This commit is contained in:
jacob 2026-03-30 01:16:24 -05:00
parent 629d03a24e
commit ee3ffdb02a
8 changed files with 165 additions and 55 deletions

View File

@ -154,12 +154,13 @@
#if IsRtcEnabled #if IsRtcEnabled
#define Assert(cond) ((cond) ? 1 : (IsRunningInDebugger() ? (*(volatile i32 *)0 = 0) : Panic(Lit(__FILE__ ":" Stringize(__LINE__) ":0: assertion failed: "Stringize(cond)"")))) #define Assert(cond) ((cond) ? 1 : (IsRunningInDebugger() ? (*(volatile i32 *)0 = 0) : Panic(Lit(__FILE__ ":" Stringize(__LINE__) ":0: assertion failed: "Stringize(cond)""))))
#if IsCompilerMsvc #if IsCompilerMsvc
#define DEBUGBREAK __debugbreak() #define DEBUGBREAK do { if (IsRunningInDebugger()) __debugbreak(); } while (0)
#else #else
#define DEBUGBREAK __builtin_debugtrap() #define DEBUGBREAK do { if (IsRunningInDebugger()) __builtin_debugtrap(); } while (0)
#endif #endif
#define DEBUGBREAKABLE { volatile i32 __DEBUGBREAKABLE_VAR = 0; __DEBUGBREAKABLE_VAR; } (void)0 #define DEBUGBREAKABLE { volatile i32 __DEBUGBREAKABLE_VAR = 0; __DEBUGBREAKABLE_VAR; } (void)0
#else #else
#define DEBUGBREAK
#define Assert(cond) (void)(0) #define Assert(cond) (void)(0)
#endif #endif

View File

@ -108,7 +108,12 @@ String StringFromButton(Button button)
return name; return name;
} }
b32 IsMouseButton(Button button) b32 IsMouseClickButton(Button button)
{
return button >= Button_M1 && button <= Button_M3;
}
b32 IsAnyMouseButton(Button button)
{ {
return button >= Button_M1 && button <= Button_MWheelDown; return button >= Button_M1 && button <= Button_MWheelDown;
} }

View File

@ -160,4 +160,5 @@ Struct(ControllerEventsArray)
//~ Button helpers //~ Button helpers
String StringFromButton(Button button); String StringFromButton(Button button);
b32 IsMouseButton(Button button); b32 IsMouseClickButton(Button button);
b32 IsAnyMouseButton(Button button);

View File

@ -292,6 +292,10 @@ void V_ApplyTextboxDeltas(V_TextboxState *tb, V_TextboxDeltaList deltas)
{ {
tb->end = 0; tb->end = 0;
} }
else if (!(delta.flags & V_TextboxDeltaFlag_NavSelect) && tb->end != tb->start)
{
tb->end = MinI64(tb->end, tb->start);
}
else if (delta.flags & V_TextboxDeltaFlag_NavWord) else if (delta.flags & V_TextboxDeltaFlag_NavWord)
{ {
if (tb->end > 0 && tb->text32[tb->end - 1] == ' ') if (tb->end > 0 && tb->text32[tb->end - 1] == ' ')
@ -318,6 +322,10 @@ void V_ApplyTextboxDeltas(V_TextboxState *tb, V_TextboxDeltaList deltas)
{ {
tb->end = I64Max; tb->end = I64Max;
} }
else if (!(delta.flags & V_TextboxDeltaFlag_NavSelect) && tb->end != tb->start)
{
tb->end = MaxI64(tb->end, tb->start);
}
else if (delta.flags & V_TextboxDeltaFlag_NavWord) else if (delta.flags & V_TextboxDeltaFlag_NavWord)
{ {
if (tb->end < tb->len && tb->text32[tb->end] == ' ') if (tb->end < tb->len && tb->text32[tb->end] == ' ')
@ -889,6 +897,7 @@ void V_TickForever(WaveLaneCtx *lane)
G_ResetArena(cl, gpu_frame_arena); G_ResetArena(cl, gpu_frame_arena);
// Persist state // Persist state
CopyBytes(frame->real_held_buttons, prev_frame->real_held_buttons, sizeof(frame->real_held_buttons));
CopyBytes(frame->held_buttons, prev_frame->held_buttons, sizeof(frame->held_buttons)); CopyBytes(frame->held_buttons, prev_frame->held_buttons, sizeof(frame->held_buttons));
frame->palette = prev_frame->palette; frame->palette = prev_frame->palette;
frame->is_editing = prev_frame->is_editing; frame->is_editing = prev_frame->is_editing;
@ -1114,22 +1123,42 @@ void V_TickForever(WaveLaneCtx *lane)
frame->has_keyboard_focus = 0; frame->has_keyboard_focus = 0;
} }
//- Reset held buttons //- Clear held buttons
for (Button btn = 0; btn < countof(frame->held_buttons); ++btn) b32 is_typing = !UI_IsKeyNil(prev_frame->text_input_focus);
for (Button btn = 0; btn < countof(frame->real_held_buttons); ++btn)
{ {
if (btn == Button_M1 || btn == Button_M2 || btn == Button_M3) b32 clear = 0;
{ {
if (!frame->has_mouse_focus) if (IsMouseClickButton(btn) && !frame->has_mouse_focus)
{ {
frame->held_buttons[btn] = 0; clear = 1;
}
if (!IsAnyMouseButton(btn) && !frame->has_keyboard_focus)
{
clear = 1;
} }
} }
else if (clear)
{ {
if (!frame->has_keyboard_focus) frame->real_held_buttons[btn] = 0;
}
}
for (Button btn = 0; btn < countof(frame->held_buttons); ++btn)
{
b32 clear = 0;
{
if (IsMouseClickButton(btn) && !frame->has_mouse_focus)
{ {
frame->held_buttons[btn] = 0; clear = 1;
} }
if (!IsAnyMouseButton(btn) && (!frame->has_keyboard_focus || is_typing))
{
clear = 1;
}
}
if (clear)
{
frame->held_buttons[btn] = 0;
} }
} }
@ -1164,9 +1193,9 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
V_Hotkey hotkey = Zi; V_Hotkey hotkey = Zi;
hotkey.button = cev->button; hotkey.button = cev->button;
hotkey.ctrl = frame->held_buttons[Button_Ctrl]; hotkey.ctrl = frame->real_held_buttons[Button_Ctrl];
hotkey.shift = frame->held_buttons[Button_Shift]; hotkey.shift = frame->real_held_buttons[Button_Shift];
hotkey.alt = frame->held_buttons[Button_Alt]; hotkey.alt = frame->real_held_buttons[Button_Alt];
{ {
u64 hotkey_hash = HashString(StringFromStruct(&hotkey)); u64 hotkey_hash = HashString(StringFromStruct(&hotkey));
V_ShortcutBin *bin = &shortcut_bins[hotkey_hash % shortcut_bins_count]; V_ShortcutBin *bin = &shortcut_bins[hotkey_hash % shortcut_bins_count];
@ -1203,7 +1232,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
delta.flags |= V_TextboxDeltaFlag_NavRight | V_TextboxDeltaFlag_NavLine; delta.flags |= V_TextboxDeltaFlag_NavRight | V_TextboxDeltaFlag_NavLine;
} }
if (down && cev->button == Button_A && frame->held_buttons[Button_Ctrl]) if (down && cev->button == Button_A && frame->real_held_buttons[Button_Ctrl])
{ {
delta.flags |= V_TextboxDeltaFlag_NavSelect | V_TextboxDeltaFlag_NavDirect; delta.flags |= V_TextboxDeltaFlag_NavSelect | V_TextboxDeltaFlag_NavDirect;
delta.direct_start = 0; delta.direct_start = 0;
@ -1219,26 +1248,26 @@ void V_TickForever(WaveLaneCtx *lane)
delta.text = Lit(""); delta.text = Lit("");
delta.flags |= V_TextboxDeltaFlag_OnlyNavIfSelectionEmpty | V_TextboxDeltaFlag_NavSelect | V_TextboxDeltaFlag_NavRight | V_TextboxDeltaFlag_UpdateText; delta.flags |= V_TextboxDeltaFlag_OnlyNavIfSelectionEmpty | V_TextboxDeltaFlag_NavSelect | V_TextboxDeltaFlag_NavRight | V_TextboxDeltaFlag_UpdateText;
} }
if (down && cev->button == Button_C && frame->held_buttons[Button_Ctrl]) if (down && cev->button == Button_C && frame->real_held_buttons[Button_Ctrl])
{ {
delta.flags |= V_TextboxDeltaFlag_CopySelectionToClipboard; delta.flags |= V_TextboxDeltaFlag_CopySelectionToClipboard;
} }
else if (down && cev->button == Button_V && frame->held_buttons[Button_Ctrl]) else if (down && cev->button == Button_V && frame->real_held_buttons[Button_Ctrl])
{ {
delta.flags |= V_TextboxDeltaFlag_InheritTextFromClipboard | V_TextboxDeltaFlag_UpdateText; delta.flags |= V_TextboxDeltaFlag_InheritTextFromClipboard | V_TextboxDeltaFlag_UpdateText;
} }
else if (text.len > 0 && !MatchString(text, Lit("\n")) && !MatchString(text, Lit("\t")) && !MatchString(text, Lit("\r"))) else if (text.len > 0 && !frame->real_held_buttons[Button_Alt] && !MatchString(text, Lit("\n")) && !MatchString(text, Lit("\t")) && !MatchString(text, Lit("\r")))
{ {
delta.flags |= V_TextboxDeltaFlag_UpdateText; delta.flags |= V_TextboxDeltaFlag_UpdateText;
delta.text = text; delta.text = text;
} }
if (delta.flags) if (delta.flags)
{ {
if (frame->held_buttons[Button_Shift]) if (frame->real_held_buttons[Button_Shift])
{ {
delta.flags |= V_TextboxDeltaFlag_NavSelect; delta.flags |= V_TextboxDeltaFlag_NavSelect;
} }
if (frame->held_buttons[Button_Ctrl]) if (frame->real_held_buttons[Button_Ctrl])
{ {
delta.flags |= V_TextboxDeltaFlag_NavWord; delta.flags |= V_TextboxDeltaFlag_NavWord;
} }
@ -1252,7 +1281,11 @@ void V_TickForever(WaveLaneCtx *lane)
} }
} }
} }
frame->held_buttons[hotkey.button] = down; frame->real_held_buttons[hotkey.button] = down;
if (IsMouseClickButton(hotkey.button) || !is_typing)
{
frame->held_buttons[hotkey.button] = down;
}
} }
} }
@ -4379,7 +4412,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Push(Tag, HashF("developer command palette")); UI_Push(Tag, HashF("developer command palette"));
UI_Size total_width = UI_FNT(40, 1); UI_Size total_width = UI_FNT(40, 1);
UI_Size total_height = UI_FNT(40, 1); UI_Size total_height = UI_FNT(30, 1);
UI_Size header_height = UI_FNT(1.3, 1); UI_Size header_height = UI_FNT(1.3, 1);
UI_Size window_padding = UI_FNT(0.5, 1); UI_Size window_padding = UI_FNT(0.5, 1);
UI_Size icon_col_width = UI_FNT(1.75, 1); UI_Size icon_col_width = UI_FNT(1.75, 1);
@ -4393,7 +4426,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Key thumb_key = UI_KeyF("scrollbar thumb"); UI_Key thumb_key = UI_KeyF("scrollbar thumb");
UI_Key scrollbar_up_key = UI_KeyF("scrollbar up"); UI_Key scrollbar_up_key = UI_KeyF("scrollbar up");
UI_Key scrollbar_down_key = UI_KeyF("scrollbar down"); UI_Key scrollbar_down_key = UI_KeyF("scrollbar down");
UI_Key scrollbar_container_key = UI_KeyF("scrollbar container"); UI_Key track_key = UI_KeyF("scrollbar track");
UI_BoxReports scrollbar_reps = UI_ReportsFromKey(scrollbar_key); UI_BoxReports scrollbar_reps = UI_ReportsFromKey(scrollbar_key);
UI_BoxReports thumb_reps = UI_ReportsFromKey(thumb_key); UI_BoxReports thumb_reps = UI_ReportsFromKey(thumb_key);
@ -4401,7 +4434,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_BoxReports lister_reps = UI_ReportsFromKey(lister_key); UI_BoxReports lister_reps = UI_ReportsFromKey(lister_key);
UI_BoxReports scrollbar_up_reps = UI_ReportsFromKey(scrollbar_up_key); UI_BoxReports scrollbar_up_reps = UI_ReportsFromKey(scrollbar_up_key);
UI_BoxReports scrollbar_down_reps = UI_ReportsFromKey(scrollbar_down_key); UI_BoxReports scrollbar_down_reps = UI_ReportsFromKey(scrollbar_down_key);
UI_BoxReports scrollbar_container_reps = UI_ReportsFromKey(scrollbar_container_key); UI_BoxReports track_reps = UI_ReportsFromKey(track_key);
f32 lister_start = lister_reps.draw.screen_rect.p0.y; f32 lister_start = lister_reps.draw.screen_rect.p0.y;
f32 lister_end = lister_reps.draw.screen_rect.p1.y; f32 lister_end = lister_reps.draw.screen_rect.p1.y;
@ -4411,9 +4444,9 @@ void V_TickForever(WaveLaneCtx *lane)
f32 scissor_end = scissor_reps.draw.screen_rect.p1.y; f32 scissor_end = scissor_reps.draw.screen_rect.p1.y;
f32 scissor_height = MaxF32(scissor_end - scissor_start, 1); f32 scissor_height = MaxF32(scissor_end - scissor_start, 1);
f32 scrollbar_container_start = scrollbar_container_reps.draw.screen_rect.p0.y; f32 track_start = track_reps.draw.screen_rect.p0.y;
f32 scrollbar_container_end = scrollbar_container_reps.draw.screen_rect.p1.y; f32 track_end = track_reps.draw.screen_rect.p1.y;
f32 scrollbar_container_height = MaxF32(scrollbar_container_end - scrollbar_container_start, 1); f32 track_height = MaxF32(track_end - track_start, 1);
f32 thumb_start = thumb_reps.draw.screen_rect.p0.y; f32 thumb_start = thumb_reps.draw.screen_rect.p0.y;
f32 thumb_end = thumb_reps.draw.screen_rect.p1.y; f32 thumb_end = thumb_reps.draw.screen_rect.p1.y;
@ -4424,15 +4457,20 @@ void V_TickForever(WaveLaneCtx *lane)
if (thumb_reps.draw.m1.downs) if (thumb_reps.draw.m1.downs)
{ {
palette->drag_lister = lister_reps.draw.screen_rect; palette->drag_lister = lister_reps.draw.screen_rect;
palette->drag_container = scrollbar_container_reps.draw.screen_rect; palette->drag_scissor = scissor_reps.draw.screen_rect;
palette->drag_track = track_reps.draw.screen_rect;
palette->drag_thumb = thumb_reps.draw.screen_rect;
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.m1.held) if (thumb_reps.draw.m1.held)
{ {
f32 delta_ratio = (frame->screen_cursor.y - palette->drag_cursor.y) / (palette->drag_container.p1.y - palette->drag_container.p0.y); f32 drag_track_height = palette->drag_track.p1.y - palette->drag_track.p0.y;
palette->scroll = palette->drag_scroll + delta_ratio * (palette->drag_lister.p1.y - palette->drag_lister.p0.y); f32 drag_thumb_height = palette->drag_thumb.p1.y - palette->drag_thumb.p0.y;
f32 drag_scroll_height = (palette->drag_lister.p1.y - palette->drag_lister.p0.y) - (palette->drag_scissor.p1.y - palette->drag_scissor.p0.y);
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 = ClampF32(palette->scroll, 0, scroll_height); palette->scroll = ClampF32(palette->scroll, 0, scroll_height);
} }
@ -4440,10 +4478,10 @@ void V_TickForever(WaveLaneCtx *lane)
f32 scroll_ratio = palette->scroll / scroll_height; f32 scroll_ratio = palette->scroll / scroll_height;
f32 lister_offset = scroll_ratio * scroll_height; f32 lister_offset = scroll_ratio * scroll_height;
f32 new_thumb_size_ratio = scissor_height / lister_height; f32 new_thumb_height = track_height * (scissor_height / lister_height);
f32 new_thumb_start = scroll_ratio * scrollbar_container_height - scroll_ratio * thumb_height; f32 new_thumb_start = scroll_ratio * track_height - scroll_ratio * thumb_height;
b32 scrollbar_visible = new_thumb_size_ratio < 1; b32 scrollbar_visible = new_thumb_height < track_height;
@ -4552,7 +4590,7 @@ void V_TickForever(WaveLaneCtx *lane)
//- Build searchbox //- Build searchbox
b32 is_searching = 0; b32 is_searching = 0;
String search_text = Zi; String search_pattern = Zi;
{ {
UI_Size search_height = UI_PIX(item_size_px * 1.25, 1); UI_Size search_height = UI_PIX(item_size_px * 1.25, 1);
@ -4587,7 +4625,7 @@ void V_TickForever(WaveLaneCtx *lane)
UI_BoxReport search_report = UI_ReportsFromKey(search_box).draw; 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->keyboard_focus_box); b32 has_focus = UI_MatchKey(search_box, prev_frame->text_input_focus);
// FIXME: Remove this // FIXME: Remove this
has_focus = 1; has_focus = 1;
@ -4599,6 +4637,11 @@ void V_TickForever(WaveLaneCtx *lane)
V.text_input_ns = frame->time_ns; V.text_input_ns = frame->time_ns;
} }
if (!palette->is_showing)
{
has_focus = 0;
}
if (search_report.is_hot) if (search_report.is_hot)
{ {
WND_SetCursor(window_frame, WND_CursorKind_Text); WND_SetCursor(window_frame, WND_CursorKind_Text);
@ -4606,7 +4649,7 @@ void V_TickForever(WaveLaneCtx *lane)
if (has_focus) if (has_focus)
{ {
frame->keyboard_focus_box = search_box; frame->text_input_focus = search_box;
if (text_input_deltas.first) if (text_input_deltas.first)
{ {
V.text_input_ns = frame->time_ns; V.text_input_ns = frame->time_ns;
@ -4641,7 +4684,8 @@ void V_TickForever(WaveLaneCtx *lane)
search_text = V_StringFromTextbox(frame->arena, search_state); String search_text = V_StringFromTextbox(frame->arena, search_state);
search_pattern = LowerString(frame->arena, search_text);
is_searching = search_text.len != 0; is_searching = search_text.len != 0;
@ -4875,6 +4919,25 @@ void V_TickForever(WaveLaneCtx *lane)
} }
} }
//////////////////////////////
//- Prune non-matching items
if (is_searching)
{
for (PaletteItem *item = first_item; item;)
{
PaletteItem *next = item->next;
{
b32 prune = !StringContains(LowerString(frame->arena, item->display_name), search_pattern);
if (prune)
{
DllQueueRemove(first_item, last_item, item);
}
}
item = next;
}
}
////////////////////////////// //////////////////////////////
//- Build items //- Build items
@ -5239,7 +5302,8 @@ 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, scrollbar_up_reps.draw.active);
bd_col = LerpSrgb(bd_col, theme.col.button_active, scrollbar_up_reps.draw.hot); bd_col = LerpSrgb(bd_col, theme.col.button_hot, scrollbar_up_reps.draw.hot);
bd_col = LerpSrgb(bd_col, theme.col.button_active, scrollbar_up_reps.draw.active);
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);
@ -5254,8 +5318,8 @@ void V_TickForever(WaveLaneCtx *lane)
//- Scrollbar thumb //- Scrollbar thumb
{ {
// UI_SetNext( UI_SetNext(Height, UI_GROW(1, 0));
UI_PushCP(UI_BuildBoxEx(scrollbar_container_key)); UI_PushCP(UI_BuildBoxEx(track_key));
{ {
Vec4 bg = theme.col.button_hot; Vec4 bg = theme.col.button_hot;
Vec4 bd = bg; Vec4 bd = bg;
@ -5264,14 +5328,15 @@ void V_TickForever(WaveLaneCtx *lane)
UI_SetNext(BackgroundColor, bg); UI_SetNext(BackgroundColor, bg);
UI_SetNext(Width, UI_GROW(1, 0)); UI_SetNext(Width, UI_GROW(1, 0));
UI_SetNext(Height, UI_GROW(new_thumb_size_ratio, 1)); UI_SetNext(Height, UI_PIX(new_thumb_height, 1));
UI_SetNext(BorderSize, 1); UI_SetNext(BorderSize, 1);
UI_SetNext(BorderColor, bd); UI_SetNext(BorderColor, bd);
UI_SetNext(Rounding, UI_RGROW(1 * theme.rounding)); UI_SetNext(Rounding, UI_RGROW(1 * theme.rounding));
UI_SetNext(FloatingPos, VEC2(0, new_thumb_start)); UI_SetNext(FloatingPos, VEC2(0, new_thumb_start));
UI_SetNext(Anchor, UI_Region_Center); UI_SetNext(Anchor, UI_Region_Center);
UI_SetNext(Anchor, UI_Region_Top); UI_SetNext(Anchor, UI_Region_Top);
UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_Floating); // UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_Floating);
UI_SetNext(Flags, UI_BoxFlag_CaptureMouse | UI_BoxFlag_Floating | UI_BoxFlag_NoFloatingClampY);
UI_SetNext(Anchor, UI_Region_Top); UI_SetNext(Anchor, UI_Region_Top);
UI_BuildBoxEx(thumb_key); UI_BuildBoxEx(thumb_key);
} }
@ -5283,7 +5348,8 @@ 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, scrollbar_down_reps.draw.active);
bd_col = LerpSrgb(bd_col, theme.col.button_active, scrollbar_down_reps.draw.hot); bd_col = LerpSrgb(bd_col, theme.col.button_hot, scrollbar_down_reps.draw.hot);
bd_col = LerpSrgb(bd_col, theme.col.button_active, scrollbar_down_reps.draw.active);
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);
@ -5604,10 +5670,6 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Build debug info UI //- Build debug info UI

View File

@ -224,7 +224,9 @@ Struct(V_Palette)
// f32 drag_scrollbar_container_end; // f32 drag_scrollbar_container_end;
Rng2 drag_lister; Rng2 drag_lister;
Rng2 drag_container; Rng2 drag_scissor;
Rng2 drag_track;
Rng2 drag_thumb;
Vec2 drag_cursor; Vec2 drag_cursor;
f32 drag_scroll; f32 drag_scroll;
@ -342,10 +344,11 @@ Struct(V_Frame)
f64 blend_sim_tick; f64 blend_sim_tick;
f64 blend_predict_tick; f64 blend_predict_tick;
Button held_buttons[Button_COUNT]; Button held_buttons[Button_COUNT]; // User input state captured for gameplay
Button real_held_buttons[Button_COUNT]; // Actual state of user input regardless of keyboard / mouse focus
V_Palette palette; V_Palette palette;
UI_Key keyboard_focus_box; UI_Key text_input_focus;
String window_restore; String window_restore;

View File

@ -484,6 +484,7 @@ UI_Key UI_BuildBoxEx(UI_Key semantic_key)
n->cmd.box.is_transient = is_transient; n->cmd.box.is_transient = is_transient;
n->cmd.box.parent = UI_Top(Parent); n->cmd.box.parent = UI_Top(Parent);
n->cmd.box.flags = (UI_Top(Flags) | UI_Top(OrFlags)) & ~UI_Top(OmitFlags); n->cmd.box.flags = (UI_Top(Flags) | UI_Top(OrFlags)) & ~UI_Top(OmitFlags);
n->cmd.box.debug_break_flags = UI_Top(DebugBreakFlags);
n->cmd.box.pref_semantic_dims[Axis_X] = UI_Top(Width); n->cmd.box.pref_semantic_dims[Axis_X] = UI_Top(Width);
n->cmd.box.pref_semantic_dims[Axis_Y] = UI_Top(Height); n->cmd.box.pref_semantic_dims[Axis_Y] = UI_Top(Height);
n->cmd.box.scale = UI_Top(Scale); n->cmd.box.scale = UI_Top(Scale);
@ -668,7 +669,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
is_cursor_in_box = non_corner_edge_dist >= 0 && corner_edge_dist >= 0; is_cursor_in_box = non_corner_edge_dist >= 0 && corner_edge_dist >= 0;
} }
report->is_hovered = is_cursor_in_box; report->is_hovered = is_cursor_in_box;
if (top_hovered_box == 0 && box->desc.flags & UI_BoxFlag_CaptureMouse && is_cursor_in_box) if (top_hovered_box == 0 && (box->desc.flags & UI_BoxFlag_CaptureMouse) && is_cursor_in_box)
{ {
top_hovered_box = box; top_hovered_box = box;
} }
@ -1109,6 +1110,8 @@ 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);
box->pre_index = pre_index; box->pre_index = pre_index;
boxes_pre[pre_index] = box; boxes_pre[pre_index] = box;
pre_index += 1; pre_index += 1;
@ -1143,6 +1146,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_IndependentSolve);
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
{ {
UI_Size size = box->desc.pref_semantic_dims[axis]; UI_Size size = box->desc.pref_semantic_dims[axis];
@ -1177,6 +1181,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis);
if (box->parent) if (box->parent)
{ {
Axis axis = box->parent->desc.child_layout_axis; Axis axis = box->parent->desc.child_layout_axis;
@ -1211,6 +1216,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
for (u64 post_index = 0; post_index < boxes_count; ++post_index) for (u64 post_index = 0; post_index < boxes_count; ++post_index)
{ {
UI_Box *box = boxes_post[post_index]; UI_Box *box = boxes_post[post_index];
UI_DebugBreak(box, UI_DebugBreakFlag_DownwardsDependentSolve);
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
{ {
UI_Size size = box->desc.pref_semantic_dims[axis]; UI_Size size = box->desc.pref_semantic_dims[axis];
@ -1241,6 +1247,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis);
if (box->parent) if (box->parent)
{ {
Axis axis = !box->parent->desc.child_layout_axis; Axis axis = !box->parent->desc.child_layout_axis;
@ -1256,6 +1263,7 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_SolveViolations);
for (Axis axis = 0; axis < Axis_COUNTXY; ++axis) for (Axis axis = 0; axis < Axis_COUNTXY; ++axis)
{ {
f32 box_size = box->solved_dims.v[axis]; f32 box_size = box->solved_dims.v[axis];
@ -1338,6 +1346,8 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_FinalSolve);
UI_Box *parent = box->parent; UI_Box *parent = box->parent;
// TODO: Distinguish between baseline alignment & visual alignment // TODO: Distinguish between baseline alignment & visual alignment
@ -1356,8 +1366,8 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
f32 scaled_size = 0; f32 scaled_size = 0;
if (box->solved_scale.v[axis] == 1) if (box->solved_scale.v[axis] == 1)
{ {
// scaled_size = RoundF32(unscaled_size); scaled_size = RoundF32(unscaled_size);
scaled_size = unscaled_size; // scaled_size = unscaled_size;
} }
else else
{ {
@ -1561,6 +1571,8 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index) for (u64 pre_index = 0; pre_index < boxes_count; ++pre_index)
{ {
UI_Box *box = boxes_pre[pre_index]; UI_Box *box = boxes_pre[pre_index];
UI_DebugBreak(box, UI_DebugBreakFlag_BuildGpuData);
GC_Run raw_run_unscaled = box->glyph_run; GC_Run raw_run_unscaled = box->glyph_run;
GC_Run raw_run = UI_ScaleRun(frame->arena, raw_run_unscaled, box->solved_scale); GC_Run raw_run = UI_ScaleRun(frame->arena, raw_run_unscaled, box->solved_scale);

View File

@ -95,6 +95,24 @@ Enum(UI_BoxFlag)
UI_BoxFlag_Scissor = (1 << 6), UI_BoxFlag_Scissor = (1 << 6),
}; };
////////////////////////////////////////////////////////////
//~ Debug breakpoint flags
Enum(UI_DebugBreakFlag)
{
UI_DebugBreakFlag_None = 0,
UI_DebugBreakFlag_Prep = (1 << 0),
UI_DebugBreakFlag_IndependentSolve = (1 << 1),
UI_DebugBreakFlag_UpwardsDependentSolveLayoutAxis = (1 << 2),
UI_DebugBreakFlag_DownwardsDependentSolve = (1 << 3),
UI_DebugBreakFlag_UpwardsDependentSolveNonLayoutAxis = (1 << 4),
UI_DebugBreakFlag_SolveViolations = (1 << 5),
UI_DebugBreakFlag_FinalSolve = (1 << 6),
UI_DebugBreakFlag_BuildGpuData = (1 << 7),
UI_DebugBreakFlag_All = 0xFFFFFFFF
};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Style types //~ Style types
@ -102,6 +120,7 @@ Enum(UI_BoxFlag)
X(OmitFlags, UI_BoxFlag) \ X(OmitFlags, UI_BoxFlag) \
X(OrFlags, UI_BoxFlag) \ X(OrFlags, UI_BoxFlag) \
X(Flags, UI_BoxFlag) \ X(Flags, UI_BoxFlag) \
X(DebugBreakFlags, UI_DebugBreakFlag) \
X(Parent, UI_Key) \ X(Parent, UI_Key) \
X(Tag, u64) \ X(Tag, u64) \
X(ChildLayoutAxis, Axis) \ X(ChildLayoutAxis, Axis) \
@ -236,6 +255,7 @@ Enum(UI_CmdKind)
Struct(UI_BoxDesc) Struct(UI_BoxDesc)
{ {
UI_BoxFlag flags; UI_BoxFlag flags;
UI_DebugBreakFlag debug_break_flags;
UI_Key key; UI_Key key;
UI_Key parent; UI_Key parent;
@ -518,6 +538,12 @@ UI_Key UI_BuildBoxEx(UI_Key semantic_key);
void UI_SetRawTexture(UI_Key key, G_TextureRef tex, Rng2 uv); void UI_SetRawTexture(UI_Key key, G_TextureRef tex, Rng2 uv);
#if IsRtcEnabled
#define UI_DebugBreak(box, target_flags) do { if (box->desc.debug_break_flags & target_flags) { DEBUGBREAK; } } while (0)
#else
#define UI_DebugBreak(...)
#endif
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Report //~ Report

View File

@ -102,7 +102,7 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input)
//- Scissor //- Scissor
// FIXME: Inclusive // FIXME: Inclusive
if (p.x < rect.scissor.p0.x || p.x > rect.scissor.p1.x || p.y < rect.scissor.p0.y || p.y > rect.scissor.p1.y) if (p.x < rect.scissor.p0.x || p.x >= rect.scissor.p1.x || p.y < rect.scissor.p0.y || p.y >= rect.scissor.p1.y)
{ {
result = 0; result = 0;
} }