summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/cinput.cpp38
-rw-r--r--src/gui.cpp71
-rw-r--r--src/hl2h.cpp3
-rw-r--r--src/hl2h.h3
-rw-r--r--src/menu.cpp9
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
86using InputCreateMoveFn = void (*)(void *, int, float, bool); 86using InputCreateMoveFn = void (*)(void *, int, float, bool);
87static InputCreateMoveFn oInputCreateMove = nullptr; 87static InputCreateMoveFn oInputCreateMove = nullptr;
88using InputExtraMouseFn = void (*)(void *, float, bool);
89static 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.
94static 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
101void 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
89static void hkdInputCreateMove(void *self, int seq, float frametime, 110static 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
1281static unsigned int (*real_get_rel_mouse)(int *, int *) = nullptr;
1282static int (*real_poll_event)(void *) = nullptr;
1283
1284extern "C" __attribute__((visibility("default"))) unsigned int
1285SDL_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
1298extern "C" __attribute__((visibility("default"))) int
1299SDL_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;
diff --git a/src/hl2h.h b/src/hl2h.h
index 8a81439..d5a9dc3 100644
--- a/src/hl2h.h
+++ b/src/hl2h.h
@@ -129,7 +129,7 @@ struct CUserCmd {
129// engine constants 129// engine constants
130// --------------------------------------------------------------------------- 130// ---------------------------------------------------------------------------
131 131
132enum { IN_ATTACK = 1 << 0, IN_JUMP = 1 << 1, IN_DUCK = 1 << 2, IN_USE = 1 << 5, IN_ATTACK2 = 1 << 11 }; 132enum { IN_ATTACK = 1 << 0, IN_JUMP = 1 << 1, IN_DUCK = 1 << 2, IN_USE = 1 << 5, IN_ATTACK2 = 1 << 11, IN_SPEED = 1 << 17 };
133enum { FL_ONGROUND = 1 << 0, FL_DUCKING = 1 << 1, FL_INWATER = 1 << 9 }; 133enum { FL_ONGROUND = 1 << 0, FL_DUCKING = 1 << 1, FL_INWATER = 1 << 9 };
134enum { MOVETYPE_WALK = 2, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 }; 134enum { MOVETYPE_WALK = 2, MOVETYPE_NOCLIP = 8, MOVETYPE_LADDER = 9 };
135 135
@@ -180,6 +180,7 @@ enum EspOption {
180// --------------------------------------------------------------------------- 180// ---------------------------------------------------------------------------
181void note_modified(const CUserCmd *cmd, int flags, const float *vel); 181void note_modified(const CUserCmd *cmd, int flags, const float *vel);
182CUserCmd *get_usercmd(int seq); 182CUserCmd *get_usercmd(int seq);
183void input_clear_mouse_states();
183void fix_verified_crc(int seq, uint32_t crc); 184void fix_verified_crc(int seq, uint32_t crc);
184uint32_t usercmd_checksum(const CUserCmd *c); 185uint32_t usercmd_checksum(const CUserCmd *c);
185bool find_input_global(); 186bool 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)
470static constexpr int SCAN_INSERT = 73; 470static constexpr int SCAN_INSERT = 73; // reserved for the GUI
471static constexpr int SCAN_TEXT_MENU = 58; // F1 preview key for the old tree
471static constexpr int SCAN_UP = 82; // these are SDL scancodes 472static constexpr int SCAN_UP = 82; // these are SDL scancodes
472static constexpr int SCAN_DOWN = 81; 473static constexpr int SCAN_DOWN = 81;
473static constexpr int SCAN_LEFT = 80; 474static 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 }