diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cinput.cpp | 38 | ||||
| -rw-r--r-- | src/gui.cpp | 71 | ||||
| -rw-r--r-- | src/hl2h.cpp | 3 | ||||
| -rw-r--r-- | src/hl2h.h | 3 | ||||
| -rw-r--r-- | src/menu.cpp | 9 |
5 files changed, 98 insertions, 26 deletions
diff --git a/src/cinput.cpp b/src/cinput.cpp index a75cc4f..ad7face 100644 --- a/src/cinput.cpp +++ b/src/cinput.cpp | |||
| @@ -85,12 +85,42 @@ void fix_verified_crc(int seq, uint32_t crc) { | |||
| 85 | 85 | ||
| 86 | using InputCreateMoveFn = void (*)(void *, int, float, bool); | 86 | using InputCreateMoveFn = void (*)(void *, int, float, bool); |
| 87 | static InputCreateMoveFn oInputCreateMove = nullptr; | 87 | static InputCreateMoveFn oInputCreateMove = nullptr; |
| 88 | using InputExtraMouseFn = void (*)(void *, float, bool); | ||
| 89 | static InputExtraMouseFn oInputExtraMouseSample = nullptr; | ||
| 90 | |||
| 91 | // ExtraMouseSample runs AdjustAngles at render-frame rate, between movement | ||
| 92 | // commands. While the GUI is open it must not touch the view; movement still | ||
| 93 | // comes through CreateMove. | ||
| 94 | static void hkdInputExtraMouseSample(void *self, float frametime, bool active) { | ||
| 95 | if (gui_is_open()) | ||
| 96 | return; | ||
| 97 | if (oInputExtraMouseSample) | ||
| 98 | oInputExtraMouseSample(self, frametime, active); | ||
| 99 | } | ||
| 100 | |||
| 101 | void input_clear_mouse_states() { | ||
| 102 | if (!g_input) | ||
| 103 | return; | ||
| 104 | // CInput::ClearStates (IInput slot 20): zeros both the software mouse | ||
| 105 | // accumulator and the engine raw-input accumulator. | ||
| 106 | using Fn = void (*)(void *); | ||
| 107 | vfunc<Fn>((void *)g_input, 20)((void *)g_input); | ||
| 108 | } | ||
| 88 | 109 | ||
| 89 | static void hkdInputCreateMove(void *self, int seq, float frametime, | 110 | static void hkdInputCreateMove(void *self, int seq, float frametime, |
| 90 | bool active) { | 111 | bool active) { |
| 112 | // Mouse deltas are accumulated between ticks. With the custom GUI open we | ||
| 113 | // must discard them before CInput::CreateMove applies mouse look, otherwise | ||
| 114 | // the view moves for one frame and snaps back when do_move freezes it. | ||
| 115 | if (gui_is_open()) | ||
| 116 | input_clear_mouse_states(); | ||
| 91 | if (oInputCreateMove) | 117 | if (oInputCreateMove) |
| 92 | oInputCreateMove(self, seq, frametime, active); | 118 | oInputCreateMove(self, seq, frametime, active); |
| 93 | 119 | ||
| 120 | // No combat features may modify the command while the GUI is open. | ||
| 121 | if (gui_is_open()) | ||
| 122 | return; | ||
| 123 | |||
| 94 | CUserCmd *cmd = get_usercmd(seq); | 124 | CUserCmd *cmd = get_usercmd(seq); |
| 95 | if (!cmd) | 125 | if (!cmd) |
| 96 | return; | 126 | return; |
| @@ -125,8 +155,14 @@ static bool install_input_hook() { | |||
| 125 | memcpy(nvt, vt, N * sizeof(void *)); | 155 | memcpy(nvt, vt, N * sizeof(void *)); |
| 126 | oInputCreateMove = (InputCreateMoveFn)vt[3]; | 156 | oInputCreateMove = (InputCreateMoveFn)vt[3]; |
| 127 | nvt[3] = (void *)&hkdInputCreateMove; | 157 | nvt[3] = (void *)&hkdInputCreateMove; |
| 158 | if (N > 4) { | ||
| 159 | oInputExtraMouseSample = (InputExtraMouseFn)vt[4]; | ||
| 160 | nvt[4] = (void *)&hkdInputExtraMouseSample; | ||
| 161 | } | ||
| 128 | VTABLE((void *)g_input) = nvt; | 162 | VTABLE((void *)g_input) = nvt; |
| 129 | logf("CInput CreateMove hooked: slot 3 orig=%p", (void *)oInputCreateMove); | 163 | logf("CInput CreateMove hooked: slot 3 orig=%p; ExtraMouseSample slot 4 " |
| 164 | "orig=%p", | ||
| 165 | (void *)oInputCreateMove, (void *)oInputExtraMouseSample); | ||
| 130 | return true; | 166 | return true; |
| 131 | } | 167 | } |
| 132 | 168 | ||
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 | } | ||
diff --git a/src/hl2h.cpp b/src/hl2h.cpp index a0e6b53..1460577 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp | |||
| @@ -561,7 +561,8 @@ static void do_move(int seq, float frametime) { | |||
| 561 | cmd->buttons = 0; | 561 | cmd->buttons = 0; |
| 562 | } else { | 562 | } else { |
| 563 | // Movement is allowed while the GUI is open, but not look/attack/use. | 563 | // Movement is allowed while the GUI is open, but not look/attack/use. |
| 564 | cmd->buttons &= (IN_JUMP | IN_DUCK); | 564 | // Keep locomotion buttons (jump, duck, walk) only. |
| 565 | cmd->buttons &= (IN_JUMP | IN_DUCK | IN_SPEED); | ||
| 565 | } | 566 | } |
| 566 | cmd->impulse = 0; | 567 | cmd->impulse = 0; |
| 567 | cmd->weaponselect = 0; | 568 | cmd->weaponselect = 0; |
| @@ -129,7 +129,7 @@ struct CUserCmd { | |||
| 129 | // engine constants | 129 | // engine constants |
| 130 | // --------------------------------------------------------------------------- | 130 | // --------------------------------------------------------------------------- |
| 131 | 131 | ||
| 132 | enum { IN_ATTACK = 1 << 0, IN_JUMP = 1 << 1, IN_DUCK = 1 << 2, IN_USE = 1 << 5, IN_ATTACK2 = 1 << 11 }; | 132 | enum { IN_ATTACK = 1 << 0, IN_JUMP = 1 << 1, IN_DUCK = 1 << 2, IN_USE = 1 << 5, IN_ATTACK2 = 1 << 11, IN_SPEED = 1 << 17 }; |
| 133 | enum { FL_ONGROUND = 1 << 0, FL_DUCKING = 1 << 1, FL_INWATER = 1 << 9 }; | 133 | enum { FL_ONGROUND = 1 << 0, FL_DUCKING = 1 << 1, FL_INWATER = 1 << 9 }; |
| 134 | enum { MOVETYPE_WALK = 2, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 }; | 134 | enum { MOVETYPE_WALK = 2, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 }; |
| 135 | 135 | ||
| @@ -180,6 +180,7 @@ enum EspOption { | |||
| 180 | // --------------------------------------------------------------------------- | 180 | // --------------------------------------------------------------------------- |
| 181 | void note_modified(const CUserCmd *cmd, int flags, const float *vel); | 181 | void note_modified(const CUserCmd *cmd, int flags, const float *vel); |
| 182 | CUserCmd *get_usercmd(int seq); | 182 | CUserCmd *get_usercmd(int seq); |
| 183 | void input_clear_mouse_states(); | ||
| 183 | void fix_verified_crc(int seq, uint32_t crc); | 184 | void fix_verified_crc(int seq, uint32_t crc); |
| 184 | uint32_t usercmd_checksum(const CUserCmd *c); | 185 | uint32_t usercmd_checksum(const CUserCmd *c); |
| 185 | bool find_input_global(); | 186 | bool find_input_global(); |
diff --git a/src/menu.cpp b/src/menu.cpp index 56fe6fa..a0cf323 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -467,7 +467,8 @@ static void config_load() { | |||
| 467 | // --------------------------------------------------------------------------- | 467 | // --------------------------------------------------------------------------- |
| 468 | 468 | ||
| 469 | // SDL scancodes for navigation keys (matches the game's scancode set) | 469 | // SDL scancodes for navigation keys (matches the game's scancode set) |
| 470 | static constexpr int SCAN_INSERT = 73; | 470 | static constexpr int SCAN_INSERT = 73; // reserved for the GUI |
| 471 | static constexpr int SCAN_TEXT_MENU = 58; // F1 preview key for the old tree | ||
| 471 | static constexpr int SCAN_UP = 82; // these are SDL scancodes | 472 | static constexpr int SCAN_UP = 82; // these are SDL scancodes |
| 472 | static constexpr int SCAN_DOWN = 81; | 473 | static constexpr int SCAN_DOWN = 81; |
| 473 | static constexpr int SCAN_LEFT = 80; | 474 | static constexpr int SCAN_LEFT = 80; |
| @@ -637,7 +638,7 @@ static void menu_handle_input() { | |||
| 637 | // SDL state can be sampled several times per rendered frame (both ISurface | 638 | // SDL state can be sampled several times per rendered frame (both ISurface |
| 638 | // hooks call outer_draw). Use a physical-key latch instead of the one-poll | 639 | // hooks call outer_draw). Use a physical-key latch instead of the one-poll |
| 639 | // edge so one press cannot open and close the menu in the same frame. | 640 | // edge so one press cannot open and close the menu in the same frame. |
| 640 | bool insert_down = key_held(SCAN_INSERT); | 641 | bool insert_down = key_held(SCAN_TEXT_MENU); |
| 641 | bool insert_edge = insert_down && !g_insert_latch; | 642 | bool insert_edge = insert_down && !g_insert_latch; |
| 642 | if (insert_down) | 643 | if (insert_down) |
| 643 | g_insert_latch = true; | 644 | g_insert_latch = true; |
| @@ -662,8 +663,8 @@ static void menu_handle_input() { | |||
| 662 | for (int i = 0; i < MOUSE_BASE + 5; i++) { | 663 | for (int i = 0; i < MOUSE_BASE + 5; i++) { |
| 663 | if (!g_key_down[i]) | 664 | if (!g_key_down[i]) |
| 664 | continue; | 665 | continue; |
| 665 | if (i == SCAN_INSERT || i == SCAN_UP || i == SCAN_DOWN || | 666 | if (i == SCAN_INSERT || i == SCAN_TEXT_MENU || i == SCAN_UP || |
| 666 | i == SCAN_LEFT || i == SCAN_RIGHT) { | 667 | i == SCAN_DOWN || i == SCAN_LEFT || i == SCAN_RIGHT) { |
| 667 | g_bind_mode = false; | 668 | g_bind_mode = false; |
| 668 | return; // cancel bind select | 669 | return; // cancel bind select |
| 669 | } | 670 | } |
