diff options
Diffstat (limited to '')
| -rw-r--r-- | CONTEXT.md | 16 | ||||
| -rw-r--r-- | docs/adr/0001-custom-isurface-gui.md | 5 | ||||
| -rw-r--r-- | src/gui.cpp | 96 | ||||
| -rw-r--r-- | src/hl2h.cpp | 38 | ||||
| -rw-r--r-- | src/hl2h.h | 1 |
5 files changed, 133 insertions, 23 deletions
| @@ -148,20 +148,24 @@ Binds use SDL scancodes; mouse buttons are pseudo-scancodes 600..604. | |||
| 148 | - **Category**: sidebar group. Movement, Combat, Visuals, Weapons, System. | 148 | - **Category**: sidebar group. Movement, Combat, Visuals, Weapons, System. |
| 149 | - **Card**: per-feature panel. Header always shows Active + Bind; body is a | 149 | - **Card**: per-feature panel. Header always shows Active + Bind; body is a |
| 150 | collapsible set of settings. | 150 | collapsible set of settings. |
| 151 | - **Freeze**: while the GUI is open, the usercmd movement/buttons/impulses/view | 151 | - **Freeze**: while the GUI is open, look/attack/use/impulse/weapon selection |
| 152 | are held and combat features are skipped; the game keeps simulating and | 152 | are blocked and combat features are skipped, but normal WASD/jump/duck |
| 153 | ESP/FOV circle/speed graph keep drawing. No invulnerability. | 153 | movement is allowed. Bind capture blocks all game input until it ends. The |
| 154 | game keeps simulating and ESP/FOV circle/speed graph keep drawing. No | ||
| 155 | invulnerability. | ||
| 154 | - **Native cursor**: on open, leave SDL relative-mouse mode and show the OS | 156 | - **Native cursor**: on open, leave SDL relative-mouse mode and show the OS |
| 155 | cursor; restore on close. Absolute mouse coordinates are used. | 157 | cursor; restore on close. Absolute mouse coordinates are used. |
| 156 | - **Bind capture**: click Bind, press a key/button; Esc or clicking elsewhere | 158 | - **Bind capture**: click Bind, press a key/button; Esc cancels capture but |
| 157 | cancels; Clear sets None; Insert is reserved for the GUI. | 159 | does not close the GUI; clicking elsewhere cancels; Clear sets None; Insert |
| 160 | is reserved for the GUI. | ||
| 158 | - **UI scale**: `clamp(min(screen_w/1920, screen_h/1080), 0.75, 1.5)`; base | 161 | - **UI scale**: `clamp(min(screen_w/1920, screen_h/1080), 0.75, 1.5)`; base |
| 159 | window 960x620, body/title fonts 15/20 px at scale 1. | 162 | window 960x620, body/title fonts 15/20 px at scale 1. |
| 160 | - Every feature gets Active + Bind; bind None means always-on. | 163 | - Every feature gets Active + Bind; bind None means always-on. |
| 161 | - System page: config path/build info, Reload config, and a two-click Reset | 164 | - System page: config path/build info, Reload config, and a two-click Reset |
| 162 | that restores feature settings/binds but keeps GUI layout. | 165 | that restores feature settings/binds but keeps GUI layout. |
| 163 | - Window: fixed-size, draggable by title bar, clamped to screen, position, | 166 | - Window: fixed-size, draggable by title bar, clamped to screen, position, |
| 164 | category and expanded cards persisted under `[gui]`. | 167 | category and expanded cards persisted under `[gui]`. Esc does not close the |
| 168 | GUI; the toggle key or title-bar X does. | ||
| 165 | 169 | ||
| 166 | 170 | ||
| 167 | ## Bones / ESP | 171 | ## Bones / ESP |
diff --git a/docs/adr/0001-custom-isurface-gui.md b/docs/adr/0001-custom-isurface-gui.md index 9da3c0c..9595ca8 100644 --- a/docs/adr/0001-custom-isurface-gui.md +++ b/docs/adr/0001-custom-isurface-gui.md | |||
| @@ -38,8 +38,9 @@ path. | |||
| 38 | - Left sidebar categories (Movement, Combat, Visuals, Weapons, System) and a | 38 | - Left sidebar categories (Movement, Combat, Visuals, Weapons, System) and a |
| 39 | content pane of feature cards with collapsible settings. | 39 | content pane of feature cards with collapsible settings. |
| 40 | - Native OS cursor by releasing SDL relative-mouse mode while the GUI is open. | 40 | - Native OS cursor by releasing SDL relative-mouse mode while the GUI is open. |
| 41 | - While open, freeze usercmd input/view and skip combat features; keep the | 41 | - While open, freeze look/attack/use and skip combat features, but allow |
| 42 | game simulating and keep ESP/FOV circle/speed graph drawing. | 42 | normal movement; bind capture blocks all game input. Keep the game |
| 43 | simulating and keep ESP/FOV circle/speed graph drawing. | ||
| 43 | - Replace the text menu with the GUI. No permanent fallback menu; git history | 44 | - Replace the text menu with the GUI. No permanent fallback menu; git history |
| 44 | retains the old implementation. | 45 | retains the old implementation. |
| 45 | 46 | ||
diff --git a/src/gui.cpp b/src/gui.cpp index 74dd537..923cd4d 100644 --- a/src/gui.cpp +++ b/src/gui.cpp | |||
| @@ -879,12 +879,8 @@ void gui_handle_input() { | |||
| 879 | return; | 879 | return; |
| 880 | } | 880 | } |
| 881 | 881 | ||
| 882 | if (esc_edge) { | 882 | if (esc_edge && g_capture_card >= 0) |
| 883 | if (g_capture_card >= 0) | 883 | g_capture_card = -1; |
| 884 | g_capture_card = -1; | ||
| 885 | else | ||
| 886 | close_gui(); | ||
| 887 | } | ||
| 888 | 884 | ||
| 889 | // Keep the native cursor free even if the game re-grabs it. | 885 | // Keep the native cursor free even if the game re-grabs it. |
| 890 | if (sd_set_relative) | 886 | if (sd_set_relative) |
| @@ -1196,4 +1192,92 @@ void gui_draw() { | |||
| 1196 | } | 1192 | } |
| 1197 | 1193 | ||
| 1198 | bool gui_is_open() { return g_open; } | 1194 | bool gui_is_open() { return g_open; } |
| 1195 | bool gui_bind_capture_active() { return g_open && g_capture_card >= 0; } | ||
| 1199 | QAngle gui_frozen_view() { return g_frozen; } | 1196 | QAngle gui_frozen_view() { return g_frozen; } |
| 1197 | |||
| 1198 | // --------------------------------------------------------------------------- | ||
| 1199 | // SDL cursor interposition | ||
| 1200 | // --------------------------------------------------------------------------- | ||
| 1201 | // The game re-asserts relative mouse mode / hides the cursor every frame. While | ||
| 1202 | // the GUI is open, force the opposite so the native cursor stays usable. | ||
| 1203 | |||
| 1204 | static int (*real_show_cursor)(int) = nullptr; | ||
| 1205 | static int (*real_set_relative)(int) = nullptr; | ||
| 1206 | static void (*real_warp_mouse)(void *, int, int) = nullptr; | ||
| 1207 | static void (*real_set_grab)(void *, int) = nullptr; | ||
| 1208 | |||
| 1209 | extern "C" __attribute__((visibility("default"))) int SDL_ShowCursor(int toggle) { | ||
| 1210 | if (!real_show_cursor) | ||
| 1211 | real_show_cursor = (int (*)(int))dlsym(RTLD_NEXT, "SDL_ShowCursor"); | ||
| 1212 | if (g_open && toggle != -1) { | ||
| 1213 | if (real_show_cursor) | ||
| 1214 | real_show_cursor(1); | ||
| 1215 | return 1; | ||
| 1216 | } | ||
| 1217 | return real_show_cursor ? real_show_cursor(toggle) : 0; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | extern "C" __attribute__((visibility("default"))) int | ||
| 1221 | SDL_SetRelativeMouseMode(int enabled) { | ||
| 1222 | if (!real_set_relative) | ||
| 1223 | real_set_relative = | ||
| 1224 | (int (*)(int))dlsym(RTLD_NEXT, "SDL_SetRelativeMouseMode"); | ||
| 1225 | if (g_open) { | ||
| 1226 | if (real_set_relative) | ||
| 1227 | real_set_relative(0); | ||
| 1228 | return 0; | ||
| 1229 | } | ||
| 1230 | return real_set_relative ? real_set_relative(enabled) : 0; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | extern "C" __attribute__((visibility("default"))) void | ||
| 1234 | SDL_WarpMouseInWindow(void *window, int x, int y) { | ||
| 1235 | if (!real_warp_mouse) | ||
| 1236 | real_warp_mouse = | ||
| 1237 | (void (*)(void *, int, int))dlsym(RTLD_NEXT, "SDL_WarpMouseInWindow"); | ||
| 1238 | if (g_open) | ||
| 1239 | return; | ||
| 1240 | if (real_warp_mouse) | ||
| 1241 | real_warp_mouse(window, x, y); | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | extern "C" __attribute__((visibility("default"))) void | ||
| 1245 | SDL_SetWindowGrab(void *window, int grabbed) { | ||
| 1246 | if (!real_set_grab) | ||
| 1247 | real_set_grab = | ||
| 1248 | (void (*)(void *, int))dlsym(RTLD_NEXT, "SDL_SetWindowGrab"); | ||
| 1249 | if (g_open) { | ||
| 1250 | if (real_set_grab) | ||
| 1251 | real_set_grab(window, 0); | ||
| 1252 | return; | ||
| 1253 | } | ||
| 1254 | if (real_set_grab) | ||
| 1255 | real_set_grab(window, grabbed); | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | static void (*real_set_mouse_grab)(void *, int) = nullptr; | ||
| 1259 | static void (*real_warp_global)(int, int) = nullptr; | ||
| 1260 | |||
| 1261 | extern "C" __attribute__((visibility("default"))) void | ||
| 1262 | SDL_SetWindowMouseGrab(void *window, int grabbed) { | ||
| 1263 | if (!real_set_mouse_grab) | ||
| 1264 | real_set_mouse_grab = | ||
| 1265 | (void (*)(void *, int))dlsym(RTLD_NEXT, "SDL_SetWindowMouseGrab"); | ||
| 1266 | if (g_open) { | ||
| 1267 | if (real_set_mouse_grab) | ||
| 1268 | real_set_mouse_grab(window, 0); | ||
| 1269 | return; | ||
| 1270 | } | ||
| 1271 | if (real_set_mouse_grab) | ||
| 1272 | real_set_mouse_grab(window, grabbed); | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | extern "C" __attribute__((visibility("default"))) void | ||
| 1276 | SDL_WarpMouseGlobal(int x, int y) { | ||
| 1277 | if (!real_warp_global) | ||
| 1278 | real_warp_global = (void (*)(int, int))dlsym(RTLD_NEXT, "SDL_WarpMouseGlobal"); | ||
| 1279 | if (g_open) | ||
| 1280 | return; | ||
| 1281 | if (real_warp_global) | ||
| 1282 | real_warp_global(x, y); | ||
| 1283 | } | ||
diff --git a/src/hl2h.cpp b/src/hl2h.cpp index c0c27af..a0e6b53 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp | |||
| @@ -546,10 +546,23 @@ static void do_move(int seq, float frametime) { | |||
| 546 | cmd->viewangles[0] = f.x; | 546 | cmd->viewangles[0] = f.x; |
| 547 | cmd->viewangles[1] = f.y; | 547 | cmd->viewangles[1] = f.y; |
| 548 | cmd->viewangles[2] = f.z; | 548 | cmd->viewangles[2] = f.z; |
| 549 | cmd->forwardmove = 0.0f; | 549 | // Freeze the rendered view explicitly: CInput may not push the modified |
| 550 | cmd->sidemove = 0.0f; | 550 | // command view back to the engine if the client mode returns false. |
| 551 | cmd->upmove = 0.0f; | 551 | if (g_iface.engine) { |
| 552 | cmd->buttons = 0; | 552 | QAngle set = f; |
| 553 | using SetViewFn = void (*)(void *, QAngle *); | ||
| 554 | vfunc<SetViewFn>(g_iface.engine, 20)(g_iface.engine, &set); | ||
| 555 | } | ||
| 556 | if (gui_bind_capture_active()) { | ||
| 557 | // Bind capture must not move/act in the game while keys are sampled. | ||
| 558 | cmd->forwardmove = 0.0f; | ||
| 559 | cmd->sidemove = 0.0f; | ||
| 560 | cmd->upmove = 0.0f; | ||
| 561 | cmd->buttons = 0; | ||
| 562 | } else { | ||
| 563 | // Movement is allowed while the GUI is open, but not look/attack/use. | ||
| 564 | cmd->buttons &= (IN_JUMP | IN_DUCK); | ||
| 565 | } | ||
| 553 | cmd->impulse = 0; | 566 | cmd->impulse = 0; |
| 554 | cmd->weaponselect = 0; | 567 | cmd->weaponselect = 0; |
| 555 | cmd->weaponsubtype = 0; | 568 | cmd->weaponsubtype = 0; |
| @@ -670,12 +683,19 @@ void set_silent_restore(const QAngle &angles) { | |||
| 670 | static void hkdFrameStageNotify(void *self, int stage) { | 683 | static void hkdFrameStageNotify(void *self, int stage) { |
| 671 | if (oFrameStageNotify) | 684 | if (oFrameStageNotify) |
| 672 | oFrameStageNotify(self, stage); | 685 | oFrameStageNotify(self, stage); |
| 673 | if (stage == 5 && g_silent_restore_pending) { | 686 | if (stage == 5) { |
| 674 | g_silent_restore_pending = false; | 687 | if (g_silent_restore_pending) { |
| 675 | if (g_iface.engine) { | 688 | g_silent_restore_pending = false; |
| 676 | QAngle a = g_silent_restore_angles; | 689 | if (g_iface.engine) { |
| 690 | QAngle a = g_silent_restore_angles; | ||
| 691 | using SetViewFn = void (*)(void *, QAngle *); | ||
| 692 | vfunc<SetViewFn>(g_iface.engine, 20)(g_iface.engine, &a); | ||
| 693 | } | ||
| 694 | } | ||
| 695 | if (gui_is_open() && g_iface.engine) { | ||
| 696 | QAngle f = gui_frozen_view(); | ||
| 677 | using SetViewFn = void (*)(void *, QAngle *); | 697 | using SetViewFn = void (*)(void *, QAngle *); |
| 678 | vfunc<SetViewFn>(g_iface.engine, 20)(g_iface.engine, &a); | 698 | vfunc<SetViewFn>(g_iface.engine, 20)(g_iface.engine, &f); |
| 679 | } | 699 | } |
| 680 | } | 700 | } |
| 681 | } | 701 | } |
| @@ -234,6 +234,7 @@ void menu_force_close(); | |||
| 234 | void gui_handle_input(); | 234 | void gui_handle_input(); |
| 235 | void gui_draw(); | 235 | void gui_draw(); |
| 236 | bool gui_is_open(); | 236 | bool gui_is_open(); |
| 237 | bool gui_bind_capture_active(); | ||
| 237 | QAngle gui_frozen_view(); | 238 | QAngle gui_frozen_view(); |
| 238 | // ISurface pointer (defined in menu.cpp, used for drawing tests) | 239 | // ISurface pointer (defined in menu.cpp, used for drawing tests) |
| 239 | struct ISurface; | 240 | struct ISurface; |
