diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-27 18:21:13 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-27 18:21:13 +0100 |
| commit | 304441c71997ee61e618146f4d4302c6d2b952ad (patch) | |
| tree | e7a00d279b257f88e7a590da59023533cae6ae80 /src/gui.cpp | |
| parent | GUI: allow movement while open; freeze look and block bind capture (diff) | |
| download | hl2h-304441c71997ee61e618146f4d4302c6d2b952ad.tar.gz hl2h-304441c71997ee61e618146f4d4302c6d2b952ad.zip | |
GUI: Insert-only close, freeze mouse look at the source
Feedback pass:
- Insert now toggles the GUI; the old text tree moved to F1.
- Remove the title-bar X. Insert is the only close path; Esc only cancels
bind capture.
- Discard accumulated mouse deltas in CInput::CreateMove before the game can
apply them (CInput::ClearStates), so the camera no longer moves for a frame
and snaps back. Also skip ExtraMouseSample and zero relative mouse state
while the GUI is open.
- Strip attack/use/impulse/weapon selection from the command while open;
keep jump, duck and walk. Skip combat command edits (spread seed) too.
- Widen System page buttons so "Reload config" and "Reset defaults" fit.
- Update CONTEXT/ADR for the Insert-only close behavior.
Diffstat (limited to '')
| -rw-r--r-- | src/gui.cpp | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/src/gui.cpp b/src/gui.cpp index 923cd4d..eb9062e 100644 --- a/src/gui.cpp +++ b/src/gui.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // gui.cpp — custom immediate-mode GUI shell (temporary F2 preview) | 1 | // gui.cpp — custom immediate-mode GUI shell (temporary Insert preview) |
| 2 | // | 2 | // |
| 3 | // This is the first vertical slice: the visual shell, categories, cards, | 3 | // This is the first vertical slice: the visual shell, categories, cards, |
| 4 | // dummy controls, cursor handling and input freeze. It does not read or write | 4 | // dummy controls, cursor handling and input freeze. It does not read or write |
| @@ -575,6 +575,7 @@ static void close_gui() { | |||
| 575 | g_dragging = false; | 575 | g_dragging = false; |
| 576 | g_scroll_drag = false; | 576 | g_scroll_drag = false; |
| 577 | g_slider_drag = -1; | 577 | g_slider_drag = -1; |
| 578 | input_clear_mouse_states(); | ||
| 578 | if (g_sdl_ready) { | 579 | if (g_sdl_ready) { |
| 579 | if (sd_set_relative) | 580 | if (sd_set_relative) |
| 580 | sd_set_relative(g_prev_relative ? 1 : 0); | 581 | sd_set_relative(g_prev_relative ? 1 : 0); |
| @@ -611,6 +612,7 @@ static void open_gui() { | |||
| 611 | if (sd_show_cursor) | 612 | if (sd_show_cursor) |
| 612 | sd_show_cursor(1); | 613 | sd_show_cursor(1); |
| 613 | } | 614 | } |
| 615 | input_clear_mouse_states(); | ||
| 614 | g_open = true; | 616 | g_open = true; |
| 615 | g_capture_card = -1; | 617 | g_capture_card = -1; |
| 616 | g_wheel.exchange(0); | 618 | g_wheel.exchange(0); |
| @@ -659,7 +661,7 @@ static void handle_capture(const unsigned char *keys) { | |||
| 659 | for (int k = 0; k < 512; k++) { | 661 | for (int k = 0; k < 512; k++) { |
| 660 | if (!keys[k] || g_prev_keys[k]) | 662 | if (!keys[k] || g_prev_keys[k]) |
| 661 | continue; | 663 | continue; |
| 662 | if (k == 73 || k == 59) // Insert reserved; F2 closes the preview | 664 | if (k == 73) // Insert is reserved for opening/closing the GUI |
| 663 | continue; | 665 | continue; |
| 664 | g_cards[g_capture_card].bind = k; | 666 | g_cards[g_capture_card].bind = k; |
| 665 | g_capture_card = -1; | 667 | g_capture_card = -1; |
| @@ -674,12 +676,7 @@ static void handle_mouse_click() { | |||
| 674 | 676 | ||
| 675 | // title bar: drag or close | 677 | // title bar: drag or close |
| 676 | Rect title{g_win_x, g_win_y, g_win_w, S(38.0f)}; | 678 | Rect title{g_win_x, g_win_y, g_win_w, S(38.0f)}; |
| 677 | Rect close{g_win_x + g_win_w - S(38.0f), g_win_y, S(38.0f), S(38.0f)}; | ||
| 678 | if (title.has(mx, my)) { | 679 | if (title.has(mx, my)) { |
| 679 | if (close.has(mx, my)) { | ||
| 680 | close_gui(); | ||
| 681 | return; | ||
| 682 | } | ||
| 683 | g_dragging = true; | 680 | g_dragging = true; |
| 684 | g_drag_dx = mx - g_win_x; | 681 | g_drag_dx = mx - g_win_x; |
| 685 | g_drag_dy = my - g_win_y; | 682 | g_drag_dy = my - g_win_y; |
| @@ -787,7 +784,7 @@ static void handle_mouse_click() { | |||
| 787 | return; | 784 | return; |
| 788 | } | 785 | } |
| 789 | if (ct.kind == CK_BUTTON) { | 786 | if (ct.kind == CK_BUTTON) { |
| 790 | Rect b{cr.x + cr.w - S(130.0f), by + S(3.0f), S(114.0f), | 787 | Rect b{cr.x + cr.w - S(176.0f), by + S(3.0f), S(160.0f), |
| 791 | S(26.0f)}; | 788 | S(26.0f)}; |
| 792 | if (b.has(mx, my)) { | 789 | if (b.has(mx, my)) { |
| 793 | logf("gui: dummy action %s", ct.label ? ct.label : "?"); | 790 | logf("gui: dummy action %s", ct.label ? ct.label : "?"); |
| @@ -858,8 +855,8 @@ void gui_handle_input() { | |||
| 858 | if (nk > 512) nk = 512; | 855 | if (nk > 512) nk = 512; |
| 859 | update_mouse(); | 856 | update_mouse(); |
| 860 | 857 | ||
| 861 | bool f2 = (nk > 59) && keys[59]; | 858 | bool toggle_key = (nk > 73) && keys[73]; |
| 862 | bool f2_edge = f2 && !g_prev_keys[59]; | 859 | bool toggle_edge = toggle_key && !g_prev_keys[73]; |
| 863 | bool esc = (nk > 41) && keys[41]; | 860 | bool esc = (nk > 41) && keys[41]; |
| 864 | bool esc_edge = esc && !g_prev_keys[41]; | 861 | bool esc_edge = esc && !g_prev_keys[41]; |
| 865 | bool left = (nk > 80) && keys[80]; | 862 | bool left = (nk > 80) && keys[80]; |
| @@ -867,7 +864,7 @@ void gui_handle_input() { | |||
| 867 | bool left_edge = left && !g_prev_keys[80]; | 864 | bool left_edge = left && !g_prev_keys[80]; |
| 868 | bool right_edge = right && !g_prev_keys[79]; | 865 | bool right_edge = right && !g_prev_keys[79]; |
| 869 | 866 | ||
| 870 | if (f2_edge) { | 867 | if (toggle_edge) { |
| 871 | if (g_open) | 868 | if (g_open) |
| 872 | close_gui(); | 869 | close_gui(); |
| 873 | else | 870 | else |
| @@ -887,6 +884,11 @@ void gui_handle_input() { | |||
| 887 | sd_set_relative(0); | 884 | sd_set_relative(0); |
| 888 | if (sd_show_cursor) | 885 | if (sd_show_cursor) |
| 889 | sd_show_cursor(1); | 886 | sd_show_cursor(1); |
| 887 | if (g_iface.engine) { | ||
| 888 | QAngle f = g_frozen; | ||
| 889 | using SetViewFn = void (*)(void *, QAngle *); | ||
| 890 | vfunc<SetViewFn>(g_iface.engine, 20)(g_iface.engine, &f); | ||
| 891 | } | ||
| 890 | 892 | ||
| 891 | handle_capture(keys); | 893 | handle_capture(keys); |
| 892 | 894 | ||
| @@ -1063,7 +1065,7 @@ static void draw_card(const Rect &clip, int index, int y) { | |||
| 1063 | text_in(clip, cr.x + S(16.0f), by + S(1.0f), ct.label, g_font_body, | 1065 | text_in(clip, cr.x + S(16.0f), by + S(1.0f), ct.label, g_font_body, |
| 1064 | g_body_h, cr.w - S(24.0f), C_DIM); | 1066 | g_body_h, cr.w - S(24.0f), C_DIM); |
| 1065 | } else if (ct.kind == CK_BUTTON) { | 1067 | } else if (ct.kind == CK_BUTTON) { |
| 1066 | Rect b{cr.x + cr.w - S(130.0f), by + S(3.0f), S(114.0f), S(26.0f)}; | 1068 | Rect b{cr.x + cr.w - S(176.0f), by + S(3.0f), S(160.0f), S(26.0f)}; |
| 1067 | fill(b, Col{45, 50, 60, 255}, &clip); | 1069 | fill(b, Col{45, 50, 60, 255}, &clip); |
| 1068 | outline(b, C_BORDER, &clip); | 1070 | outline(b, C_BORDER, &clip); |
| 1069 | text_in(clip, b.x + S(10.0f), b.y + S(4.0f), ct.label, g_font_body, | 1071 | text_in(clip, b.x + S(10.0f), b.y + S(4.0f), ct.label, g_font_body, |
| @@ -1126,12 +1128,6 @@ void gui_draw() { | |||
| 1126 | g_title_h, win.w - S(80.0f), C_TEXT); | 1128 | g_title_h, win.w - S(80.0f), C_TEXT); |
| 1127 | text_in(win, win.x + S(110.0f), win.y + S(10.0f), "GUI shell preview", | 1129 | text_in(win, win.x + S(110.0f), win.y + S(10.0f), "GUI shell preview", |
| 1128 | g_font_body, g_body_h, win.w - S(180.0f), C_DIM); | 1130 | g_font_body, g_body_h, win.w - S(180.0f), C_DIM); |
| 1129 | Rect close{win.x + win.w - S(38.0f), win.y, S(38.0f), S(38.0f)}; | ||
| 1130 | fill(close, Col{45, 48, 56, 255}); | ||
| 1131 | line(close.x + S(13.0f), close.y + S(12.0f), close.x + S(25.0f), | ||
| 1132 | close.y + S(25.0f), C_DIM); | ||
| 1133 | line(close.x + S(25.0f), close.y + S(12.0f), close.x + S(13.0f), | ||
| 1134 | close.y + S(25.0f), C_DIM); | ||
| 1135 | 1131 | ||
| 1136 | Rect side{win.x, win.y + S(38.0f), S(190.0f), | 1132 | Rect side{win.x, win.y + S(38.0f), S(190.0f), |
| 1137 | win.h - S(38.0f) - S(30.0f)}; | 1133 | win.h - S(38.0f) - S(30.0f)}; |
| @@ -1185,7 +1181,7 @@ void gui_draw() { | |||
| 1185 | "config: ~/.config/hl2hake/config", g_font_body, g_body_h, | 1181 | "config: ~/.config/hl2hake/config", g_font_body, g_body_h, |
| 1186 | foot.w - S(220.0f), C_DIM); | 1182 | foot.w - S(220.0f), C_DIM); |
| 1187 | text_in(foot, foot.x + foot.w - S(200.0f), foot.y + S(6.0f), | 1183 | text_in(foot, foot.x + foot.w - S(200.0f), foot.y + S(6.0f), |
| 1188 | g_capture_card >= 0 ? "press a key / Esc" : "F2 close | Insert text", | 1184 | g_capture_card >= 0 ? "press a key / Esc" : "INS close | F1 text menu", |
| 1189 | g_font_body, g_body_h, S(190.0f), C_DIM); | 1185 | g_font_body, g_body_h, S(190.0f), C_DIM); |
| 1190 | 1186 | ||
| 1191 | draw_tooltip(); | 1187 | draw_tooltip(); |
| @@ -1281,3 +1277,40 @@ SDL_WarpMouseGlobal(int x, int y) { | |||
| 1281 | if (real_warp_global) | 1277 | if (real_warp_global) |
| 1282 | real_warp_global(x, y); | 1278 | real_warp_global(x, y); |
| 1283 | } | 1279 | } |
| 1280 | |||
| 1281 | static unsigned int (*real_get_rel_mouse)(int *, int *) = nullptr; | ||
| 1282 | static int (*real_poll_event)(void *) = nullptr; | ||
| 1283 | |||
| 1284 | extern "C" __attribute__((visibility("default"))) unsigned int | ||
| 1285 | SDL_GetRelativeMouseState(int *x, int *y) { | ||
| 1286 | if (!real_get_rel_mouse) | ||
| 1287 | real_get_rel_mouse = | ||
| 1288 | (unsigned int (*)(int *, int *))dlsym(RTLD_NEXT, | ||
| 1289 | "SDL_GetRelativeMouseState"); | ||
| 1290 | unsigned int mask = real_get_rel_mouse ? real_get_rel_mouse(x, y) : 0; | ||
| 1291 | if (g_open) { | ||
| 1292 | if (x) *x = 0; | ||
| 1293 | if (y) *y = 0; | ||
| 1294 | } | ||
| 1295 | return mask; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | extern "C" __attribute__((visibility("default"))) int | ||
| 1299 | SDL_PollEvent(void *event) { | ||
| 1300 | if (!real_poll_event) | ||
| 1301 | real_poll_event = (int (*)(void *))dlsym(RTLD_NEXT, "SDL_PollEvent"); | ||
| 1302 | if (!real_poll_event) | ||
| 1303 | return 0; | ||
| 1304 | for (;;) { | ||
| 1305 | int r = real_poll_event(event); | ||
| 1306 | if (!r) | ||
| 1307 | return 0; | ||
| 1308 | if (!g_open || !event) | ||
| 1309 | return r; | ||
| 1310 | unsigned int type = *(unsigned int *)event; | ||
| 1311 | if (type != 0x400) // SDL_MOUSEMOTION | ||
| 1312 | return r; | ||
| 1313 | // Drop motion while the GUI is open: the game must not accumulate look | ||
| 1314 | // deltas. The GUI uses absolute SDL_GetMouseState polling. | ||
| 1315 | } | ||
| 1316 | } | ||
