From 90a674724a1a72a3b8d77cac0e37d52255c61a69 Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 31 Dec 2025 23:21:18 -0600 Subject: [PATCH] correct slider cursor offset --- src/base/base_math.c | 14 ++ src/base/base_math.h | 5 + src/base/base_string.c | 2 +- src/platform/platform_win32/platform_win32.c | 2 +- src/pp/pp_vis/pp_vis_core.c | 183 ++++++++++--------- src/pp/pp_vis/pp_vis_core.h | 1 + src/ui/ui_core.c | 114 ++++++------ src/ui/ui_core.h | 25 +-- src/ui/ui_extras.c | 2 + 9 files changed, 193 insertions(+), 155 deletions(-) diff --git a/src/base/base_math.c b/src/base/base_math.c index 5e46367a..5a244c54 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -548,6 +548,20 @@ Vec2I32 DivVec2I32Vec2I32(Vec2I32 a, Vec2I32 b) //////////////////////////////////////////////////////////// //~ Vec4 +//- Mul + +Vec4 MulVec4(Vec4 v, f32 s) +{ + return VEC4(v.x * s, v.y * s, v.z * s, v.w * s); +} + +Vec4 MulVec4Vec4(Vec4 a, Vec4 b) +{ + return VEC4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); +} + +//- Conversion + Vec4 Vec4FromU32(u32 v) { Vec4 result = Zi; diff --git a/src/base/base_math.h b/src/base/base_math.h index b020a11c..f93cbc12 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -371,6 +371,11 @@ Vec2I32 SubVec2I32(Vec2I32 a, Vec2I32 b); //////////////////////////////////////////////////////////// //~ Vec4 +//- Mul +Vec4 MulVec4(Vec4 v, f32 s); +Vec4 MulVec4Vec4(Vec4 a, Vec4 b); + +//- Conversion Vec4 Vec4FromU32(u32 v); u32 U32FromVec4(Vec4 v); diff --git a/src/base/base_string.c b/src/base/base_string.c index a0cc86f5..d635e5b5 100644 --- a/src/base/base_string.c +++ b/src/base/base_string.c @@ -299,7 +299,7 @@ f64 FloatFromString(String str) if (ok) { - result = (f64)whole_part + ((f64)frac_part / PowU64(10, str.len - (frac_start_idx + 1))); + result = ((f64)whole_part + ((f64)frac_part / PowU64(10, str.len - (frac_start_idx + 1)))) * sign; } else { diff --git a/src/platform/platform_win32/platform_win32.c b/src/platform/platform_win32/platform_win32.c index 6f2e48e1..325e09ad 100644 --- a/src/platform/platform_win32/platform_win32.c +++ b/src/platform/platform_win32/platform_win32.c @@ -901,7 +901,7 @@ void P_MessageBox(P_MessageBoxKind kind, String message) } break; } - LogDebugF("Showing message box kind %F with text \"%F\"", FmtSint(kind), FmtString(message)); + LogInfoF("Showing message box kind %F with text \"%F\"", FmtSint(kind), FmtString(message)); MessageBoxExW(0, message_wstr, title, mbox_type, 0); EndScratch(scratch); diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index c5209671..c0b8f25f 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -94,6 +94,7 @@ V_WidgetTheme V_GetWidgetTheme(void) // theme.rounding = 1; theme.rounding = TweakFloat(Lit("Rounding"), 1, 0, 1); + theme.text_color = Rgb32(0xffdddee0); theme.text_padding_x = 5; theme.text_padding_y = 5; @@ -120,6 +121,7 @@ void V_PushWidgetThemeStyles(V_WidgetTheme theme) { UI_Push(Font, theme.font); UI_Push(FontSize, theme.font_size); + UI_Push(TextColor, theme.text_color); } //////////////////////////////////////////////////////////// @@ -343,7 +345,7 @@ void V_TickForever(WaveLaneCtx *lane) V_PushWidgetThemeStyles(theme); UI_Key vis_box = UI_KeyF("vis box"); - UI_Report vis_box_rep = UI_ReportFromKey(vis_box); + UI_BoxReports vis_box_reps = UI_ReportsFromKey(vis_box); { UI_Push(ChildLayoutAxis, Axis_Y); UI_Push(Width, UI_GROW(1, 0)); @@ -353,7 +355,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 - frame->ui_dims = RoundVec2(DimsFromRng2(vis_box_rep.screen_rect)); + frame->ui_dims = RoundVec2(DimsFromRng2(vis_box_reps.draw.screen_rect)); frame->ui_dims.x = MaxF32(frame->ui_dims.x, 64); frame->ui_dims.y = MaxF32(frame->ui_dims.y, 64); frame->draw_dims = frame->ui_dims; @@ -784,7 +786,7 @@ void V_TickForever(WaveLaneCtx *lane) { panel_dfs->visited = 1; - UI_Report panel_rep = UI_ReportFromKey(panel->key); + UI_BoxReport panel_rep = UI_ReportsFromKey(panel->key).draw; f32 panel_size = 0; if (panel->axis == Axis_X) { @@ -811,10 +813,10 @@ void V_TickForever(WaveLaneCtx *lane) // Apply resize if (resize_panel) { - UI_Report child_rep = UI_ReportFromKey(resize_panel->key); - UI_Report divider_rep = UI_ReportFromKey(resize_panel->divider_key); + UI_BoxReport child_rep = UI_ReportsFromKey(resize_panel->key).draw; + UI_BoxReports divider_reps = UI_ReportsFromKey(resize_panel->divider_key); - f32 drag_offset = ui_frame->last_mouse_down_cursor_pos.v[panel->axis] - divider_rep.last_mouse_down_screen_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; child_pref_size += frame->ui_cursor.v[panel->axis]; @@ -880,7 +882,7 @@ void V_TickForever(WaveLaneCtx *lane) V_Window *close_window = 0; { UI_Key tab_row_key = UI_KeyF("tab row"); - UI_Report tab_row_rep = UI_ReportFromKey(tab_row_key); + UI_BoxReport tab_row_rep = UI_ReportsFromKey(tab_row_key).draw; UI_SetNext(Width, UI_GROW(1, 0)); UI_SetNext(Height, UI_SHRINK(0, 1)); @@ -930,7 +932,7 @@ void V_TickForever(WaveLaneCtx *lane) DrawableTab *right = first_drawable_tab; for (DrawableTab *sibling = first_drawable_tab; sibling; sibling = sibling->next) { - UI_Report sibling_rep = UI_ReportFromKey(sibling->key); + UI_BoxReport sibling_rep = UI_ReportsFromKey(sibling->key).draw; f32 zone = CenterFromRng2(sibling_rep.screen_rect).x; if (frame->ui_cursor.x <= zone) { @@ -965,7 +967,7 @@ void V_TickForever(WaveLaneCtx *lane) for (DrawableTab *tab = first_drawable_tab; tab; tab = tab->next) { UI_Push(Tag, tab->key.hash); - UI_Report tab_rep = UI_ReportFromKey(tab->key); + UI_BoxReport tab_rep = UI_ReportsFromKey(tab->key).draw; if (tab == first_drawable_tab) { @@ -991,7 +993,7 @@ void V_TickForever(WaveLaneCtx *lane) f32 drag_threshold = 20; if (tab_rep.m1.held) { - Vec2 drag_start = ui_frame->last_mouse_down_cursor_pos; + Vec2 drag_start = ui_frame->drag_cursor_pos; if (Vec2Len(SubVec2(frame->ui_cursor, drag_start)) > drag_threshold) { V.dragging_window = window; @@ -1013,14 +1015,9 @@ void V_TickForever(WaveLaneCtx *lane) border_color = theme.button_active_color; } - bg_color = LerpSrgb(bg_color, theme.button_hot_color, tab_rep.hot * (1.0 - tab_rep.selected)); + bg_color = LerpSrgb(bg_color, theme.button_hot_color, tab_rep.hot); bg_color = LerpSrgb(bg_color, theme.button_active_color, tab_rep.active * is_dragging); - border_color = LerpSrgb(border_color, theme.button_active_color, tab_rep.selected); - - // if (is_dragging) - // { - // bg_color = Color_Blue; - // } + border_color = LerpSrgb(border_color, theme.button_active_color, tab_rep.misc); String tab_name = Zi; if (window->is_tile_window) @@ -1038,7 +1035,8 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(Width, UI_SHRINK(0, 0)); UI_SetNext(Height, UI_SHRINK(0, 0)); UI_SetNext(ChildAlignment, UI_Region_Left); - UI_SetNext(Flags, UI_BoxFlag_Interactable | (UI_BoxFlag_Selected * (active_window == window))); + UI_SetNext(Misc, window == active_window); + UI_SetNext(Flags, UI_BoxFlag_Interactable); UI_SetNext(Text, tab_name); UI_PushCP(UI_BuildRowEx(tab->key)); { @@ -1055,7 +1053,7 @@ void V_TickForever(WaveLaneCtx *lane) // Build tab close button { UI_Key close_key = UI_KeyF("close"); - UI_Report close_rep = UI_ReportFromKey(close_key); + UI_BoxReport close_rep = UI_ReportsFromKey(close_key).draw; Vec4 close_color = Zi; close_color = LerpSrgb(close_color, theme.button_hot_color, close_rep.hot); @@ -1089,7 +1087,7 @@ void V_TickForever(WaveLaneCtx *lane) case DrawableTabKind_Ghost: { - UI_Report rep = UI_ReportFromKey(tab->key); + UI_BoxReport rep = UI_ReportsFromKey(tab->key).draw; Vec4 bg_color = Zi; bg_color = LerpSrgb(bg_color, theme.button_hot_color, rep.exists); @@ -1120,7 +1118,7 @@ void V_TickForever(WaveLaneCtx *lane) case DrawableTabKind_NewTab: { UI_Key key = UI_KeyF("new tab"); - UI_Report rep = UI_ReportFromKey(key); + UI_BoxReport rep = UI_ReportsFromKey(key).draw; Vec4 bg_color = Zi; bg_color = LerpSrgb(bg_color, theme.button_hot_color, rep.hot); @@ -1172,7 +1170,7 @@ void V_TickForever(WaveLaneCtx *lane) { String name = S_NameFromTileKind(tile_kind); UI_Key key = UI_KeyF("Tile %F", FmtString(name)); - UI_Report rep = UI_ReportFromKey(key); + UI_BoxReport rep = UI_ReportsFromKey(key).draw; if (rep.m1.downs) { @@ -1186,7 +1184,7 @@ void V_TickForever(WaveLaneCtx *lane) b32 is_selected = tile_kind == frame->equipped_tile; Vec4 border_color = Zi; - border_color = LerpSrgb(border_color, theme.button_selected_color, rep.selected); + border_color = LerpSrgb(border_color, theme.button_selected_color, rep.misc); border_color = LerpSrgb(border_color, theme.button_active_color, rep.hot); UI_SetNext(BackgroundColor, bg_color); @@ -1194,7 +1192,8 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(Border, 1); UI_SetNext(Width, UI_GROW(1, 0)); UI_SetNext(Height, UI_SHRINK(0, 0)); - UI_SetNext(Flags, UI_BoxFlag_Interactable | (UI_BoxFlag_Selected * is_selected)); + UI_SetNext(Misc, is_selected); + UI_SetNext(Flags, UI_BoxFlag_Interactable); UI_PushCP(UI_BuildRowEx(key)); { UI_SetNext(ChildAlignment, UI_Region_Center); @@ -1226,7 +1225,7 @@ void V_TickForever(WaveLaneCtx *lane) if (panel->next != 0) { panel->divider_key = UI_KeyF("Divider"); - UI_Report rep = UI_ReportFromKey(panel->divider_key); + UI_BoxReport rep = UI_ReportsFromKey(panel->divider_key).draw; Vec4 active_color = theme.button_active_color; Vec4 hot_color = LerpSrgb(theme.button_hot_color, theme.button_active_color, 0.25); @@ -1307,20 +1306,20 @@ void V_TickForever(WaveLaneCtx *lane) { UI_Push(Tag, palette->key.hash); UI_Key titlebar_key = UI_KeyF("title bar"); - UI_Report titlebar_rep = UI_ReportFromKey(titlebar_key); - UI_Report palette_rep = UI_ReportFromKey(palette->key); + UI_BoxReports titlebar_reps = UI_ReportsFromKey(titlebar_key); + UI_BoxReports palette_reps = UI_ReportsFromKey(palette->key); Vec4 window_background_color = theme.window_background_color; Vec4 window_border_color = theme.window_border_color; Vec4 titlebar_color = Zi; Vec4 titlebar_border_color = Zi; Vec4 divider_color = theme.divider_color; - if (titlebar_rep.m1.held) + if (titlebar_reps.draw.m1.held) { - Vec2 drag_offset = SubVec2(ui_frame->last_mouse_down_cursor_pos, palette_rep.last_mouse_down_screen_anchor); + Vec2 drag_offset = SubVec2(ui_frame->drag_cursor_pos, palette_reps.drag.screen_anchor); palette->pos = SubVec2(frame->ui_cursor, drag_offset); } - window_border_color = LerpSrgb(window_border_color, Rgb32(0x0078a6), titlebar_rep.hot); + window_border_color = LerpSrgb(window_border_color, Rgb32(0x0078a6), titlebar_reps.draw.hot); f32 scale = LerpF32(0.85, 1, palette->show); UI_Push(Tint, VEC4(1, 1, 1, palette->show)); @@ -1464,7 +1463,7 @@ void V_TickForever(WaveLaneCtx *lane) // Divider UI_BuildDivider(UI_PIX(1, 1), divider_color, Axis_Y); - UI_Report item_rep = UI_ReportFromKey(item->key); + UI_BoxReport item_rep = UI_ReportsFromKey(item->key).draw; if (item_rep.m1.presses) { if (item->flags & PaletteItemFlag_IsCmd) @@ -1483,6 +1482,9 @@ void V_TickForever(WaveLaneCtx *lane) item_border_color = LerpSrgb(item_border_color, theme.button_active_color, item_rep.hot); } + UI_Size item_height = UI_FNT(1.5, 1); + UI_Size tweak_height = UI_FNT(1.25, 1); + UI_SetNext(BorderColor, 0); UI_SetNext(Rounding, UI_RPIX(0)); UI_PushCP(UI_BuildRow()); @@ -1491,7 +1493,7 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(BackgroundColor, item_color); UI_SetNext(Rounding, UI_RPIX(5)); UI_SetNext(Width, UI_GROW(1, 0)); - UI_SetNext(Height, UI_FNT(1.5, 1)); + UI_SetNext(Height, item_height); UI_SetNext(ChildAlignment, UI_Region_Left); UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable); UI_PushCP(UI_BuildRowEx(item->key)); @@ -1525,7 +1527,7 @@ void V_TickForever(WaveLaneCtx *lane) { UI_BuildSpacer(UI_PIX(spacing * 0.5, 1), Axis_X); UI_Key reset_key = UI_KeyF("reset"); - UI_Report reset_rep = UI_ReportFromKey(reset_key); + UI_BoxReport reset_rep = UI_ReportsFromKey(reset_key).draw; if (reset_rep.m1.presses > 0) { @@ -1551,13 +1553,15 @@ void V_TickForever(WaveLaneCtx *lane) UI_PopCP(UI_TopCP()); } + TweakFloat(Lit("Test"), 0, -50, 50); + switch (tweak_desc.kind) { // Boolean tweak case TweakKind_Bool: { UI_Key cb_key = UI_KeyF("tweak checkbox"); - UI_Report cb_rep = UI_ReportFromKey(cb_key); + UI_BoxReport cb_rep = UI_ReportsFromKey(cb_key).draw; b32 tweak_bool = BoolFromString(new_tweak_str); if (cb_rep.m1.downs) @@ -1593,11 +1597,13 @@ void V_TickForever(WaveLaneCtx *lane) UI_Key slider_key = UI_KeyF("tweak slider"); UI_Key marker_key = UI_KeyF("tweak slider marker"); - UI_Report slider_rep = UI_ReportFromKey(slider_key); - UI_Report marker_rep = UI_ReportFromKey(marker_key); + UI_BoxReports slider_reps = UI_ReportsFromKey(slider_key); + UI_BoxReports marker_reps = UI_ReportsFromKey(marker_key); - Vec2 slider_pos = slider_rep.screen_rect.p0; - Vec2 slider_dims = DimsFromRng2(slider_rep.screen_rect); + 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); f64 range_min = tweak_desc.range.min; f64 range_max = tweak_desc.range.max; @@ -1606,76 +1612,83 @@ void V_TickForever(WaveLaneCtx *lane) range_max = range_min + 1; } - if (TweakFloat(Lit("Test"), 0.5, 0, 1)) - { - } - f64 tweak_float = FloatFromString(new_tweak_str); - { - Axis slider_axis = Axis_X; - if (slider_rep.m1.held) + if (slider_reps.draw.m1.held) { + f64 initial_marker_width = DimsFromRng2(marker_reps.drag.screen_rect).x; + f64 initial_slider_pos = slider_reps.drag.screen_rect.p0.x; + f64 initial_slider_width = DimsFromRng2(slider_reps.drag.screen_rect).x - initial_marker_width; + f64 initial_cursor = ui_frame->drag_cursor_pos.x; + f64 initial_ratio = slider_reps.drag.misc; - Vec2 initial_start = slider_rep.last_mouse_down_screen_rect.p0; - Vec2 initial_end = slider_rep.last_mouse_down_screen_rect.p1; - Vec2 initial_dims = SubVec2(initial_end, initial_start); + f64 virtual_slider_start = initial_cursor - (initial_slider_width * initial_ratio); + f64 virtual_slider_end = virtual_slider_start + initial_slider_width; - Vec2 initial_marker_offset = SubVec2(marker_rep.last_mouse_down_screen_anchor, initial_start); - Vec2 initial_cursor = ui_frame->last_mouse_down_cursor_pos; + f64 virtual_cursor = ClampF32(frame->ui_cursor.x, virtual_slider_start, virtual_slider_end); + f64 virtual_cursor_ratio = (virtual_cursor - virtual_slider_start) / (virtual_slider_end - virtual_slider_start); - Vec2 virtual_start = SubVec2(initial_cursor, initial_marker_offset); - Vec2 virtual_end = AddVec2(virtual_start, initial_dims); - Vec2 virtual_cursor_offset = SubVec2(frame->ui_cursor, virtual_start); - Vec2 virtual_cursor_ratio = DivVec2Vec2(virtual_cursor_offset, initial_dims); - virtual_cursor_ratio = ClampVec2(virtual_cursor_ratio, RNG2(VEC2(0, 0), VEC2(1, 1))); + tweak_float = LerpF64(range_min, range_max, virtual_cursor_ratio); + tweak_float = ClampF64(tweak_float, range_min, range_max); - f32 precision = 3; // FIXME: Remove this - tweak_float = LerpF64(range_min, range_max, virtual_cursor_ratio.v[slider_axis]); + f64 precision = 6; // FIXME: Remove this new_tweak_str = StringFromFloat(frame->arena, tweak_float, precision); } - if (slider_rep.is_hot) + if (slider_reps.draw.is_hot) { - WND_PushCmd( - window_frame, - .kind = WND_CmdKind_SetCursor, - slider_axis == Axis_X ? WND_CursorKind_HorizontalResize : WND_CursorKind_VerticalResize - ); + WND_PushCmd(window_frame, .kind = WND_CmdKind_SetCursor, WND_CursorKind_HorizontalResize); } } + f32 ratio = 0; + ratio = (tweak_float - range_min) / (range_max - range_min); + ratio = ClampF32(ratio, 0, 1); UI_BuildSpacer(UI_PIX(spacing, 1), Axis_X); - // Tweak slider - Vec4 slider_bg_color = Zi; + Vec4 slider_bg_color = theme.window_background_color; Vec4 slider_border_color = theme.window_border_color; - slider_border_color = LerpSrgb(slider_border_color, theme.button_active_color, slider_rep.hot); + Vec4 slider_progress_color = theme.color_positive; + Vec4 marker_bg_color = slider_bg_color; + slider_border_color = LerpSrgb(slider_border_color, theme.button_active_color, slider_reps.draw.hot); + marker_bg_color = LerpSrgb(marker_bg_color, theme.text_color, slider_reps.draw.hot); UI_SetNext(BackgroundColor, slider_bg_color); UI_SetNext(BorderColor, slider_border_color); UI_SetNext(Rounding, UI_RGROW(theme.rounding)); - UI_SetNext(Border, 2); + UI_SetNext(Border, 1); UI_SetNext(Width, UI_FNT(10, 1)); - UI_SetNext(Height, UI_FNT(1.25, 1)); + UI_SetNext(Height, tweak_height); UI_SetNext(Flags, UI_BoxFlag_Interactable); + UI_SetNext(Misc, ratio); UI_PushCP(UI_BuildRowEx(slider_key)); { - // FIXME: Marker pos should account for marker width - f32 ratio = 0; - ratio = (tweak_float - range_min) / (range_max - range_min); - ratio = ClampF32(ratio, 0, 1); - f32 marker_pos = ratio * slider_dims.x; + f32 marker_pos = ratio * (slider_dims.x - marker_dims.x); - UI_SetNext(BackgroundColor, slider_bg_color); - UI_SetNext(BorderColor, slider_border_color); - UI_SetNext(Rounding, UI_RGROW(theme.rounding)); - UI_SetNext(Border, 2); - UI_SetNext(Width, UI_FNT(1.25, 1)); - UI_SetNext(Height, UI_FNT(1.25, 1)); - UI_SetNext(Anchor, UI_Region_Center); - UI_SetNext(FloatingPos, VEC2(marker_pos, 0)); - UI_SetNext(Flags, UI_BoxFlag_Floating); - UI_BuildBoxEx(marker_key); + // Slider progress + { + UI_SetNext(BackgroundColor, slider_progress_color); + // UI_SetNext(Rounding, UI_RGROW(theme.rounding)); + UI_SetNext(Rounding, 0); + UI_SetNext(BorderColor, 0); + UI_SetNext(Border, 1); + UI_SetNext(Width, UI_PIX(marker_pos + half_marker_dims.x, 0)); + UI_SetNext(Height, tweak_height); + UI_BuildBox(); + } + + // Slider marker + { + UI_SetNext(BackgroundColor, marker_bg_color); + UI_SetNext(BorderColor, slider_border_color); + UI_SetNext(Rounding, UI_RGROW(theme.rounding)); + UI_SetNext(Border, 1); + UI_SetNext(Width, tweak_height); + UI_SetNext(Height, tweak_height); + // UI_SetNext(Anchor, UI_Region_Center); + UI_SetNext(FloatingPos, VEC2(marker_pos, 0)); + UI_SetNext(Flags, UI_BoxFlag_Floating); + UI_BuildBoxEx(marker_key); + } } UI_PopCP(UI_TopCP()); } break; @@ -1691,7 +1704,7 @@ void V_TickForever(WaveLaneCtx *lane) for (u64 i = 0; i < countof(item->hotkeys); ++i) { UI_Key hotkey_key = UI_KeyF("hotkey%F", FmtUint(i)); - UI_Report hotkey_rep = UI_ReportFromKey(hotkey_key); + UI_BoxReport hotkey_rep = UI_ReportsFromKey(hotkey_key).draw; Vec4 hotkey_color = Zi; Vec4 hotkey_border_color = Zi; @@ -1759,7 +1772,7 @@ void V_TickForever(WaveLaneCtx *lane) if (frame->show_console) { UI_Key dbg_box = UI_KeyF("Debug box"); - UI_Report dbg_rep = UI_ReportFromKey(dbg_box); + UI_BoxReport dbg_rep = UI_ReportsFromKey(dbg_box).draw; Vec2 dbg_dims = DimsFromRng2(dbg_rep.screen_rect); f32 padding = 20; diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index 0689bd96..d08c57ec 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -46,6 +46,7 @@ Struct(V_WidgetTheme) Vec4 color_positive; Vec4 color_negative; + Vec4 text_color; f32 text_padding_x; f32 text_padding_y; }; diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index e2d759c4..2aaef3b4 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -341,23 +341,18 @@ void UI_PushDefaults(void) switch (kind) { default: break; - case UI_StyleKind_Parent: { desc.style.Parent = UI_RootKey; } break; - case UI_StyleKind_Width: { desc.style.Width = UI_GROW(1, 0); } break; - case UI_StyleKind_Height: { desc.style.Height = UI_GROW(1, 0); } - case UI_StyleKind_Scale: { desc.style.Scale = VEC2(1, 1); } break; - case UI_StyleKind_Font: { desc.style.Font = UI_GetDefaultFont(); } break; - - u8 prefetch[127] = Zi; - for (u64 idx = 0; idx < countof(prefetch); ++idx) - { - prefetch[idx] = idx; - } + case UI_StyleKind_Parent: { desc.style.Parent = UI_RootKey; } break; + case UI_StyleKind_Width: { desc.style.Width = UI_GROW(1, 0); } break; + case UI_StyleKind_Height: { desc.style.Height = UI_GROW(1, 0); } + case UI_StyleKind_Scale: { desc.style.Scale = VEC2(1, 1); } break; + case UI_StyleKind_Font: { desc.style.Font = UI_GetDefaultFont(); } break; case UI_StyleKind_FontSize: { desc.style.FontSize = 16.0f; } break; case UI_StyleKind_Tint: { desc.style.Tint = Color_White; } break; + case UI_StyleKind_TextColor: { desc.style.TextColor = Color_White; } break; case UI_StyleKind_Tag: { desc.style.Tag = HashFnv64(Fnv64Basis, Lit("root")); } break; case UI_StyleKind_DebugColor: { desc.style.DebugColor = Rgba(1, 0, 1, 0.5); } break; - case UI_StyleKind_InvisibleDebugColor: { desc.style.InvisibleDebugColor = Rgba(0, 1, 1, 0.25); } break; - case UI_StyleKind_BackgroundTextureSliceUv: { desc.style.BackgroundTextureSliceUv = RNG2(VEC2(0, 0), VEC2(1, 1)); } break; + case UI_StyleKind_InvisibleDebugColor: { desc.style.InvisibleDebugColor = Rgba(0, 1, 1, 0.25); } break; + case UI_StyleKind_BackgroundTextureSliceUv: { desc.style.BackgroundTextureSliceUv = RNG2(VEC2(0, 0), VEC2(1, 1)); } break; }; UI_PushStyle(desc); } @@ -518,11 +513,12 @@ UI_Key UI_BuildBoxEx(UI_Key semantic_key) n->cmd.box.border = UI_Top(Border); n->cmd.box.font = UI_Top(Font); n->cmd.box.font_size = UI_Top(FontSize); - n->cmd.box.rounding = UI_Top(Rounding); + n->cmd.box.text_color = UI_Top(TextColor); n->cmd.box.text = UI_Top(Text); n->cmd.box.anchor = UI_Top(Anchor); n->cmd.box.floating_pos = UI_Top(FloatingPos); + n->cmd.box.misc = UI_Top(Misc); } ++frame->cmds_count; SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, n); @@ -546,14 +542,14 @@ void UI_SetRawTexture(UI_Key key, G_Texture2DRef tex, Rng2 uv) //////////////////////////////////////////////////////////// //~ Report -UI_Report UI_ReportFromKey(UI_Key key) +UI_BoxReports UI_ReportsFromKey(UI_Key key) { - UI_Report result = Zi; + UI_BoxReports result = Zi; UI_Box *box = UI_BoxFromKey(key); if (box) { - result = box->report; + result = box->reports; } return result; @@ -636,7 +632,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) //- Process controller events frame->cursor_pos = last_frame->cursor_pos; - frame->last_mouse_down_cursor_pos = last_frame->last_mouse_down_cursor_pos; + frame->drag_cursor_pos = last_frame->drag_cursor_pos; if (last_frame->boxes_pre != 0) { @@ -660,6 +656,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) for (u64 pre_index = UI.boxes_count; pre_index-- > 0;) { UI_Box *box = last_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. @@ -686,20 +683,20 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) } is_cursor_in_box = non_corner_edge_dist >= 0 && corner_edge_dist >= 0; } - box->report.is_hovered = is_cursor_in_box; + report->is_hovered = is_cursor_in_box; if (top_hovered_box == 0 && box->desc.flags & UI_BoxFlag_Interactable && is_cursor_in_box) { top_hovered_box = box; } - box->report.m1.ups = 0; - box->report.m1.downs = 0; - box->report.m1.presses = 0; - box->report.m2.ups = 0; - box->report.m2.downs = 0; - box->report.m2.presses = 0; - box->report.m3.ups = 0; - box->report.m3.downs = 0; - box->report.m3.presses = 0; + report->m1.ups = 0; + report->m1.downs = 0; + report->m1.presses = 0; + report->m2.ups = 0; + report->m2.downs = 0; + report->m2.presses = 0; + report->m3.ups = 0; + report->m3.downs = 0; + report->m3.presses = 0; } // Update state from controller events @@ -720,18 +717,18 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) { if (cev.button == Button_M1) { - ++top_hovered_box->report.m1.downs; - top_hovered_box->report.m1.held = 1; + ++top_hovered_box->reports.draw.m1.downs; + top_hovered_box->reports.draw.m1.held = 1; } else if (cev.button == Button_M2) { - ++top_hovered_box->report.m2.downs; - top_hovered_box->report.m2.held = 1; + ++top_hovered_box->reports.draw.m2.downs; + top_hovered_box->reports.draw.m2.held = 1; } else if (cev.button == Button_M3) { - ++top_hovered_box->report.m3.downs; - top_hovered_box->report.m3.held = 1; + ++top_hovered_box->reports.draw.m3.downs; + top_hovered_box->reports.draw.m3.held = 1; } active_box = top_hovered_box; } @@ -748,12 +745,12 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) { if (active_box == top_hovered_box) { - ++active_box->report.m1.presses; + ++active_box->reports.draw.m1.presses; } - ++active_box->report.m1.ups; - if (active_box->report.m1.held) + ++active_box->reports.draw.m1.ups; + if (active_box->reports.draw.m1.held) { - active_box->report.m1.held = 0; + active_box->reports.draw.m1.held = 0; active_box = 0; } } @@ -761,12 +758,12 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) { if (active_box == top_hovered_box) { - ++active_box->report.m2.presses; + ++active_box->reports.draw.m2.presses; } - ++active_box->report.m2.ups; - if (active_box->report.m2.held) + ++active_box->reports.draw.m2.ups; + if (active_box->reports.draw.m2.held) { - active_box->report.m2.held = 0; + active_box->reports.draw.m2.held = 0; active_box = 0; } } @@ -774,12 +771,12 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) { if (active_box == top_hovered_box) { - ++active_box->report.m3.presses; + ++active_box->reports.draw.m3.presses; } - ++active_box->report.m3.ups; - if (active_box->report.m3.held) + ++active_box->reports.draw.m3.ups; + if (active_box->reports.draw.m3.held) { - active_box->report.m3.held = 0; + active_box->reports.draw.m3.held = 0; active_box = 0; } } @@ -804,40 +801,40 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags, Vec4 swapchain_color) for (u64 pre_index = 0; pre_index < UI.boxes_count; ++pre_index) { UI_Box *box = last_frame->boxes_pre[pre_index]; - UI_Report *report = &box->report; + UI_BoxReport *report = &box->reports.draw; report->is_hot = box == hot_box; - report->is_selected = !!(box->desc.flags & UI_BoxFlag_Selected); f32 target_exists = box->last_build_tick >= (frame->tick - 1); f32 target_hovered = report->is_hovered; f32 target_hot = report->is_hot; f32 target_active = box == active_box; - f32 target_selected = report->is_selected; + f64 target_misc = box->desc.misc; + // TODO: Configurable per-box blend rates f32 exists_blend_rate = (30 * frame->dt); f32 hot_blend_rate = target_hot == 1 ? 1 : (15 * frame->dt); f32 active_blend_rate = target_active == 1 ? 1 : (15 * frame->dt); f32 hovered_blend_rate = target_hovered == 1 ? 1 : (15 * frame->dt); - f32 selected_blend_rate = (30 * frame->dt); + f64 misc_blend_rate = (30 * frame->dt); report->exists = LerpF32(report->exists, target_exists, exists_blend_rate); report->hot = LerpF32(report->hot, target_hot, hot_blend_rate); report->active = LerpF32(report->active, target_active, active_blend_rate); report->hovered = LerpF32(report->hovered, target_hovered, hovered_blend_rate); - report->selected = LerpF32(report->selected, target_selected, selected_blend_rate); + // report->misc = LerpF32(report->misc, target_misc, misc_blend_rate); + report->misc = target_misc; + report->screen_rect = box->screen_rect; report->screen_anchor = box->screen_anchor; - if (mouse_downs > 0) { - report->last_mouse_down_screen_rect = box->screen_rect; - report->last_mouse_down_screen_anchor = box->screen_anchor; + box->reports.drag = *report; } } if (mouse_downs > 0) { - frame->last_mouse_down_cursor_pos = frame->cursor_pos; + frame->drag_cursor_pos = frame->cursor_pos; } frame->top_hovered_box = top_hovered_box ? top_hovered_box->key : UI_NilKey; @@ -1540,6 +1537,7 @@ void UI_EndFrame(UI_Frame *frame) if (is_visible || AnyBit(frame->frame_flags, UI_FrameFlag_Debug)) { Vec4 debug_lin = is_visible ? LinearFromSrgb(box->desc.debug_color) : LinearFromSrgb(box->desc.invisible_debug_color); + Vec4 tint_lin = LinearFromSrgb(box->desc.tint); // Box rect { @@ -1548,7 +1546,7 @@ void UI_EndFrame(UI_Frame *frame) rect->background_lin = LinearFromSrgb(box->desc.background_color); rect->border_lin = LinearFromSrgb(box->desc.border_color); rect->debug_lin = debug_lin; - rect->tint_lin = LinearFromSrgb(box->desc.tint); + rect->tint_lin = tint_lin; rect->border = box->desc.border; rect->tl_rounding = box->rounding_tl; rect->tr_rounding = box->rounding_tr; @@ -1661,6 +1659,8 @@ void UI_EndFrame(UI_Frame *frame) baseline = CeilVec2(baseline); // Push text rects + Vec4 text_color_lin = LinearFromSrgb(box->desc.text_color); + text_color_lin = MulVec4Vec4(text_color_lin, tint_lin); for (u64 rect_idx = 0; rect_idx < final_rects_count; ++rect_idx) { GC_RunRect rr = final_rects[rect_idx]; @@ -1669,7 +1669,7 @@ void UI_EndFrame(UI_Frame *frame) { UI_DRect *rect = PushStruct(frame->rects_arena, UI_DRect); rect->debug_lin = debug_lin; - rect->tint_lin = LinearFromSrgb(box->desc.tint); + rect->tint_lin = text_color_lin; rect->tex = rr.tex; rect->tex_slice_uv = rr.tex_slice_uv; rect->bounds = rr.bounds; diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index b2311601..1dc6d8e8 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -91,7 +91,6 @@ Enum(UI_BoxFlag) UI_BoxFlag_NoTextTruncation = (1 << 2), UI_BoxFlag_Floating = (1 << 3), UI_BoxFlag_NoFloatingClamp = (1 << 4), - UI_BoxFlag_Selected = (1 << 5), }; //////////////////////////////////////////////////////////// @@ -119,9 +118,11 @@ Enum(UI_BoxFlag) X(Rounding, UI_Round) \ X(Font, GC_FontKey) \ X(FontSize, f32) \ + X(TextColor, Vec4) \ X(Text, String) \ X(BackgroundTexture, G_Texture2DRef) \ X(BackgroundTextureSliceUv, Rng2) \ + X(Misc, f64) \ /* --------------------------------------------- */ \ /* --------------- Virtual styles -------------- */ \ /* --------------------------------------------- */ \ @@ -191,29 +192,29 @@ Struct(UI_MouseReport) i32 presses; // Mouse button events while box is active and hovered }; -Struct(UI_Report) +Struct(UI_BoxReport) { b32 is_hovered; b32 is_hot; - b32 is_selected; f32 exists; f32 hovered; f32 hot; f32 active; - f32 selected; + f64 misc; UI_MouseReport m1; UI_MouseReport m2; UI_MouseReport m3; - // Where was this box rendered in screen coordinates Rng2 screen_rect; Vec2 screen_anchor; +}; - // Where was this box rendered during the last mouse press - Rng2 last_mouse_down_screen_rect; - Vec2 last_mouse_down_screen_anchor; +Struct(UI_BoxReports) +{ + UI_BoxReport draw; // Box data used for last render + UI_BoxReport drag; // Box data during last mouse button down event }; //////////////////////////////////////////////////////////// @@ -244,6 +245,7 @@ Struct(UI_BoxDesc) Vec4 tint; f32 border; Vec2 scale; + Vec4 text_color; String text; GC_FontKey font; f32 font_size; @@ -251,6 +253,7 @@ Struct(UI_BoxDesc) UI_Region child_alignment; UI_Region anchor; Vec2 floating_pos; + f64 misc; }; Struct(UI_Cmd) @@ -284,7 +287,7 @@ Struct(UI_Box) //- Persistent data UI_Box *next_in_bin; UI_Box *prev_in_bin; - UI_Report report; + UI_BoxReports reports; i64 last_build_tick; i64 old_gen; @@ -380,7 +383,7 @@ Struct(UI_Frame) // Control Vec2 cursor_pos; - Vec2 last_mouse_down_cursor_pos; + Vec2 drag_cursor_pos; UI_Key top_hovered_box; UI_Key hot_box; UI_Key active_box; @@ -518,7 +521,7 @@ void UI_SetRawTexture(UI_Key key, G_Texture2DRef tex, Rng2 uv); //////////////////////////////////////////////////////////// //~ Report -UI_Report UI_ReportFromKey(UI_Key key); +UI_BoxReports UI_ReportsFromKey(UI_Key key); //////////////////////////////////////////////////////////// //~ Begin frame diff --git a/src/ui/ui_extras.c b/src/ui/ui_extras.c index b78e4508..72dc9efa 100644 --- a/src/ui/ui_extras.c +++ b/src/ui/ui_extras.c @@ -8,6 +8,7 @@ UI_Key UI_BuildLabel(String text) f32 font_size = UI_Top(FontSize); Vec2 scale = UI_Top(Scale); Vec4 tint = UI_Top(Tint); + Vec4 text_color = UI_Top(TextColor); UI_Region alignment = UI_Top(ChildAlignment); UI_Key key = Zi; @@ -19,6 +20,7 @@ UI_Key UI_BuildLabel(String text) UI_Push(Tint, tint); UI_Push(Font, font); UI_Push(FontSize, font_size); + UI_Push(TextColor, text_color); UI_Push(Width, UI_SHRINK(0, 1)); UI_Push(Height, UI_SHRINK(0, 1)); UI_Push(Text, text);