From 471321938844eb65899a6fb587cda47e8c9f47af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radek=20Krzy=C5=9Bk=C3=B3w?= <46760021+Flower35@users.noreply.github.com> Date: Sun, 30 Jun 2024 21:44:40 +0200 Subject: [PATCH] Moved mouse-state code to a separate file, enabled mouse-look camera-mode for DXGI (#86) --- src/pc/controller/controller_entry_point.c | 7 -- src/pc/controller/controller_mouse.c | 121 +++++++++++++++++++++ src/pc/controller/controller_mouse.h | 21 ++-- src/pc/controller/controller_sdl.h | 4 +- src/pc/controller/controller_sdl1.c | 48 +++----- src/pc/controller/controller_sdl2.c | 43 ++------ src/pc/djui/djui_cursor.c | 3 +- src/pc/djui/djui_hud_utils.c | 9 +- src/pc/gfx/gfx_dxgi.cpp | 2 +- src/pc/gfx/gfx_dxgi.h | 2 +- 10 files changed, 169 insertions(+), 91 deletions(-) create mode 100644 src/pc/controller/controller_mouse.c diff --git a/src/pc/controller/controller_entry_point.c b/src/pc/controller/controller_entry_point.c index 08fb4d43..4fb2da76 100644 --- a/src/pc/controller/controller_entry_point.c +++ b/src/pc/controller/controller_entry_point.c @@ -12,13 +12,6 @@ // moved these from sdl controller implementations -int mouse_x; -int mouse_y; - -int mouse_window_buttons; -int mouse_window_x; -int mouse_window_y; - static struct ControllerAPI *controller_implementations[] = { #if defined(CAPI_SDL2) || defined(CAPI_SDL1) &controller_sdl, diff --git a/src/pc/controller/controller_mouse.c b/src/pc/controller/controller_mouse.c new file mode 100644 index 00000000..b1f21a68 --- /dev/null +++ b/src/pc/controller/controller_mouse.c @@ -0,0 +1,121 @@ +#include "controller_mouse.h" + +#ifdef WAPI_DXGI + #define WIN32_LEAN_AND_MEAN + #include + extern HWND gfx_dxgi_get_h_wnd(void); + static bool mouse_relative_prev_cursor_state; + +#elif defined(CAPI_SDL1) + #include + +#elif defined(CAPI_SDL2) + #include +#endif + +bool mouse_init_ok; + +u32 mouse_buttons; +s32 mouse_x; +s32 mouse_y; + +u32 mouse_window_buttons; +s32 mouse_window_x; +s32 mouse_window_y; + +static bool mouse_relative_enabled; + +void controller_mouse_read_window(void) { + if (!mouse_init_ok) { return; } + +#if defined(WAPI_DXGI) + mouse_window_buttons = + (GetAsyncKeyState(VK_LBUTTON) ? (1 << 0) : 0) | + (GetAsyncKeyState(VK_MBUTTON) ? (1 << 1) : 0) | + (GetAsyncKeyState(VK_RBUTTON) ? (1 << 2) : 0); + + POINT p; + if (GetCursorPos(&p) && ScreenToClient(gfx_dxgi_get_h_wnd(), &p)) { + mouse_window_x = p.x; + mouse_window_y = p.y; + } + +#elif defined(CAPI_SDL1) || defined(CAPI_SDL2) + mouse_window_buttons = SDL_GetMouseState(&mouse_window_x, &mouse_window_y); + +#endif +} + +void controller_mouse_read_relative(void) { + if (!mouse_init_ok) { return; } + +#if defined(WAPI_DXGI) + mouse_buttons = + (GetAsyncKeyState(VK_LBUTTON) ? (1 << 0) : 0) | + (GetAsyncKeyState(VK_MBUTTON) ? (1 << 1) : 0) | + (GetAsyncKeyState(VK_RBUTTON) ? (1 << 2) : 0); + + if (mouse_relative_enabled) { + static POINT p0; + POINT p1; + RECT rect; + if (GetWindowRect(gfx_dxgi_get_h_wnd(), &rect) && GetCursorPos(&p1)) { + mouse_x = p1.x - p0.x; + mouse_y = p1.y - p0.y; + + p0.x = rect.left + (rect.right - rect.left) / 2; + p0.y = rect.top + (rect.bottom - rect.top) / 2; + SetCursorPos(p0.x, p0.y); + } + } else { + mouse_x = 0; + mouse_y = 0; + } + +#elif defined(CAPI_SDL1) || defined(CAPI_SDL2) + mouse_buttons = SDL_GetRelativeMouseState(&mouse_x, &mouse_y); +#endif +} + +void controller_mouse_enter_relative(void) { + if (!mouse_relative_enabled) { + mouse_relative_enabled = true; + + #if defined(WAPI_DXGI) + CURSORINFO ci; + ci.cbSize = sizeof(CURSORINFO); + if (GetCursorInfo(&ci)) { + mouse_relative_prev_cursor_state = (0 != ci.flags); + } else { + mouse_relative_prev_cursor_state = false; + } + + ShowCursor(FALSE); + + #elif defined(CAPI_SDL1) + SDL_WM_GrabInput(SDL_GRAB_ON); + + #elif defined(CAPI_SDL2) + SDL_SetRelativeMouseMode(SDL_TRUE); + + #endif + } +} + +void controller_mouse_leave_relative(void) { + if (mouse_relative_enabled) { + mouse_relative_enabled = false; + + #if defined(WAPI_DXGI) + ShowCursor(mouse_relative_prev_cursor_state); + + #elif defined(CAPI_SDL1) + SDL_WM_GrabInput(SDL_GRAB_OFF); + + #elif defined(CAPI_SDL2) + SDL_SetRelativeMouseMode(SDL_FALSE); + + #endif + } +} + diff --git a/src/pc/controller/controller_mouse.h b/src/pc/controller/controller_mouse.h index 43566330..877f5d30 100644 --- a/src/pc/controller/controller_mouse.h +++ b/src/pc/controller/controller_mouse.h @@ -1,18 +1,23 @@ #ifndef CONTROLLER_MOUSE_H #define CONTROLLER_MOUSE_H -#include "controller_api.h" +#include "controller_sdl.h" +#include -extern int mouse_x; -extern int mouse_y; +extern bool mouse_init_ok; -extern int mouse_window_buttons; -extern int mouse_window_x; -extern int mouse_window_y; +extern u32 mouse_buttons; +extern s32 mouse_x; +extern s32 mouse_y; +extern u32 mouse_window_buttons; +extern s32 mouse_window_x; +extern s32 mouse_window_y; -#define VK_BASE_MOUSE 0x2000 +void controller_mouse_read_window(void); +void controller_mouse_read_relative(void); -extern struct ControllerAPI controller_mouse; +void controller_mouse_enter_relative(void); +void controller_mouse_leave_relative(void); #endif diff --git a/src/pc/controller/controller_sdl.h b/src/pc/controller/controller_sdl.h index ea4ad0fc..bab54edd 100644 --- a/src/pc/controller/controller_sdl.h +++ b/src/pc/controller/controller_sdl.h @@ -5,12 +5,10 @@ #define VK_BASE_SDL_GAMEPAD 0x1000 -// mouse buttons are also in the controller namespace (why), just offset 0x100 +// mouse buttons are also in the controller namespace, just offset 0x100 #define VK_OFS_SDL_MOUSE 0x0100 #define VK_BASE_SDL_MOUSE (VK_BASE_SDL_GAMEPAD + VK_OFS_SDL_MOUSE) extern struct ControllerAPI controller_sdl; -void controller_sdl_read_mouse_window(void); - #endif diff --git a/src/pc/controller/controller_sdl1.c b/src/pc/controller/controller_sdl1.c index 3b579026..abb269fc 100644 --- a/src/pc/controller/controller_sdl1.c +++ b/src/pc/controller/controller_sdl1.c @@ -124,14 +124,16 @@ static void controller_sdl_init(void) { if (i >= num_joy_axes) joy_axis_binds[i] = -1; } - - if (newcam_mouse == 1 && gMenuMode == -1 && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) - SDL_WM_GrabInput(SDL_GRAB_ON); - SDL_GetRelativeMouseState(&mouse_x, &mouse_y); + + if (newcam_mouse == 1 && gMenuMode == -1 && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) { + controller_mouse_enter_relative(); + } + controller_mouse_read_relative(); controller_sdl_bind(); init_ok = true; + mouse_init_ok = true; } static inline void update_button(const int i, const bool new) { @@ -151,12 +153,15 @@ extern s16 gMenuMode; static void controller_sdl_read(OSContPad *pad) { if (!init_ok) return; - if (newcam_mouse == 1 && gMenuMode == -1 && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) - SDL_WM_GrabInput(SDL_GRAB_ON); - else - SDL_WM_GrabInput(SDL_GRAB_OFF); - - u32 mouse = SDL_GetRelativeMouseState(&mouse_x, &mouse_y); + if (newcam_mouse == 1 && gMenuMode == -1 && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) { + controller_mouse_enter_relative(); + } else { + controller_mouse_leave_relative(); + } + + u32 mouse_prev = mouse_buttons; + controller_mouse_read_relative(); + u32 mouse = mouse_buttons; if (!gInteractableOverridePad) { for (u32 i = 0; i < num_mouse_binds; ++i) @@ -165,8 +170,7 @@ static void controller_sdl_read(OSContPad *pad) { } // remember buttons that changed from 0 to 1 - last_mouse = (mouse_buttons ^ mouse) & mouse; - mouse_buttons = mouse; + last_mouse = (mouse_prev ^ mouse) & mouse; if (configDisableGamepads) { return; } if (!sdl_joy) return; @@ -229,25 +233,6 @@ static void controller_sdl_read(OSContPad *pad) { } } -void controller_sdl_read_mouse_window(void) { - if (!init_ok) { return; } - -#if defined(_WIN32) && (defined(RAPI_D3D12) || defined(RAPI_D3D11)) - mouse_window_buttons = 0; - mouse_window_buttons |= (GetAsyncKeyState(VK_LBUTTON) ? (1 << 0) : 0); - mouse_window_buttons |= (GetAsyncKeyState(VK_RBUTTON) ? (1 << 1) : 0); - POINT p; - if (GetCursorPos(&p) && ScreenToClient(GetActiveWindow(), &p)) - { - mouse_window_x = p.x; - mouse_window_y = p.y; - } -#else - mouse_window_buttons = SDL_GetMouseState(&mouse_window_x, &mouse_window_y); -#endif - -} - static void controller_sdl_rumble_play(f32 strength, f32 length) { } static void controller_sdl_rumble_stop(void) { } @@ -279,6 +264,7 @@ static void controller_sdl_shutdown(void) { } init_ok = false; + mouse_init_ok = false; } struct ControllerAPI controller_sdl = { diff --git a/src/pc/controller/controller_sdl2.c b/src/pc/controller/controller_sdl2.c index 6f99e3ec..70145dda 100644 --- a/src/pc/controller/controller_sdl2.c +++ b/src/pc/controller/controller_sdl2.c @@ -48,7 +48,6 @@ static u32 joy_binds[MAX_JOYBINDS][2] = { 0 }; static u32 mouse_binds[MAX_JOYBINDS][2] = { 0 }; static bool joy_buttons[MAX_JOYBUTTONS] = { false }; -static u32 mouse_buttons = 0; static u32 last_mouse = VK_INVALID; static u32 last_joybutton = VK_INVALID; static u32 last_gamepad = 0; @@ -124,13 +123,13 @@ static void controller_sdl_init(void) { free(gcdata); } - if (newcam_mouse == 1) - SDL_SetRelativeMouseMode(SDL_TRUE); - SDL_GetRelativeMouseState(&mouse_x, &mouse_y); + if (newcam_mouse == 1) { controller_mouse_enter_relative(); } + controller_mouse_read_relative(); controller_sdl_bind(); init_ok = true; + mouse_init_ok = true; } static SDL_Haptic *controller_sdl_init_haptics(const int joy) { @@ -169,17 +168,17 @@ static inline void update_button(const int i, const bool new) { extern s16 gMenuMode; static void controller_sdl_read(OSContPad *pad) { - if (!init_ok) { - return; - } + if (!init_ok) { return; } if ((newcam_mouse == 1 || gFirstPersonCamera.enabled || gDjuiHudLockMouse) && gMenuMode == -1 && !gDjuiInMainMenu && !gDjuiChatBoxFocus && !gDjuiConsoleFocus && WAPI.has_focus()) { - SDL_SetRelativeMouseMode(SDL_TRUE); + controller_mouse_enter_relative(); } else { - SDL_SetRelativeMouseMode(SDL_FALSE); + controller_mouse_leave_relative(); } - u32 mouse = SDL_GetRelativeMouseState(&mouse_x, &mouse_y); + u32 mouse_prev = mouse_buttons; + controller_mouse_read_relative(); + u32 mouse = mouse_buttons; if (!gInteractableOverridePad) { for (u32 i = 0; i < num_mouse_binds; ++i) @@ -187,8 +186,7 @@ static void controller_sdl_read(OSContPad *pad) { pad->button |= mouse_binds[i][1]; } // remember buttons that changed from 0 to 1 - last_mouse = (mouse_buttons ^ mouse) & mouse; - mouse_buttons = mouse; + last_mouse = (mouse_prev ^ mouse) & mouse; if (configBackgroundGamepad != sBackgroundGamepad) { sBackgroundGamepad = configBackgroundGamepad; @@ -221,7 +219,7 @@ static void controller_sdl_read(OSContPad *pad) { return; } } - + int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX); int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY); int16_t rightx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTX); @@ -278,24 +276,6 @@ static void controller_sdl_read(OSContPad *pad) { } } -void controller_sdl_read_mouse_window(void) { - if (!init_ok) { return; } - -#if defined(_WIN32) && (defined(RAPI_D3D12) || defined(RAPI_D3D11)) - mouse_window_buttons = 0; - mouse_window_buttons |= (GetAsyncKeyState(VK_LBUTTON) ? (1 << 0) : 0); - mouse_window_buttons |= (GetAsyncKeyState(VK_RBUTTON) ? (1 << 1) : 0); - POINT p; - if (GetCursorPos(&p) && ScreenToClient(GetActiveWindow(), &p)) - { - mouse_window_x = p.x; - mouse_window_y = p.y; - } -#else - mouse_window_buttons = SDL_GetMouseState(&mouse_window_x, &mouse_window_y); -#endif -} - static void controller_sdl_rumble_play(f32 strength, f32 length) { if (sdl_haptic) SDL_HapticRumblePlay(sdl_haptic, strength, (u32)(length * 1000.0f)); @@ -342,6 +322,7 @@ static void controller_sdl_shutdown(void) { haptics_enabled = false; init_ok = false; + mouse_init_ok = false; } struct ControllerAPI controller_sdl = { diff --git a/src/pc/djui/djui_cursor.c b/src/pc/djui/djui_cursor.c index d57ffeb0..e5d6b9f4 100644 --- a/src/pc/djui/djui_cursor.c +++ b/src/pc/djui/djui_cursor.c @@ -1,7 +1,6 @@ #include "djui.h" #include "djui_panel.h" #include "pc/controller/controller_mouse.h" -#include "pc/controller/controller_sdl.h" #include "pc/gfx/gfx_window_manager_api.h" #include "pc/pc_main.h" @@ -118,7 +117,7 @@ void djui_cursor_update(void) { if (sMouseCursor == NULL) { return; } if (!djui_panel_is_active()) { return; } - controller_sdl_read_mouse_window(); + controller_mouse_read_window(); // check if mouse is in control again static bool sFirstUpdate = true; diff --git a/src/pc/djui/djui_hud_utils.c b/src/pc/djui/djui_hud_utils.c index a2aba017..bbf7e948 100644 --- a/src/pc/djui/djui_hud_utils.c +++ b/src/pc/djui/djui_hud_utils.c @@ -3,7 +3,6 @@ #include #include -#include "pc/controller/controller_sdl.h" #include "pc/controller/controller_mouse.h" #include "pc/gfx/gfx_pc.h" #include "pc/gfx/gfx_window_manager_api.h" @@ -235,16 +234,12 @@ u32 djui_hud_get_screen_height(void) { } f32 djui_hud_get_mouse_x(void) { -#ifdef HAVE_SDL2 - controller_sdl_read_mouse_window(); -#endif + controller_mouse_read_window(); return mouse_window_x / djui_gfx_get_scale(); } f32 djui_hud_get_mouse_y(void) { -#ifdef HAVE_SDL2 - controller_sdl_read_mouse_window(); -#endif + controller_mouse_read_window(); return mouse_window_y / djui_gfx_get_scale(); } diff --git a/src/pc/gfx/gfx_dxgi.cpp b/src/pc/gfx/gfx_dxgi.cpp index 468a913f..0488c60d 100644 --- a/src/pc/gfx/gfx_dxgi.cpp +++ b/src/pc/gfx/gfx_dxgi.cpp @@ -708,7 +708,7 @@ static bool gfx_dxgi_has_focus(void) { return GetFocus() == dxgi.h_wnd; } -HWND gfx_dxgi_get_h_wnd(void) { +extern "C" HWND gfx_dxgi_get_h_wnd(void) { return dxgi.h_wnd; } diff --git a/src/pc/gfx/gfx_dxgi.h b/src/pc/gfx/gfx_dxgi.h index 6f42474c..04b9f156 100644 --- a/src/pc/gfx/gfx_dxgi.h +++ b/src/pc/gfx/gfx_dxgi.h @@ -6,7 +6,7 @@ #ifdef DECLARE_GFX_DXGI_FUNCTIONS void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1 *adapter, bool test_only)); Microsoft::WRL::ComPtr gfx_dxgi_create_swap_chain(IUnknown *device); -HWND gfx_dxgi_get_h_wnd(void); +extern "C" HWND gfx_dxgi_get_h_wnd(void); void ThrowIfFailed(HRESULT res); void ThrowIfFailed(HRESULT res, HWND h_wnd, const char *message); #endif