From d64654ed688c6672bd7f5cbebb315202f5f34ae4 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 19 Jan 2025 21:56:40 +0200 Subject: [PATCH] Fix mouse resetting issues after ending relative mode --- Source/Engine/Platform/SDL/SDLInput.cpp | 53 ++++++++++++++++------ Source/Engine/Platform/SDL/SDLPlatform.cpp | 2 +- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/Source/Engine/Platform/SDL/SDLInput.cpp b/Source/Engine/Platform/SDL/SDLInput.cpp index d4fd45bfc..a7f796d5e 100644 --- a/Source/Engine/Platform/SDL/SDLInput.cpp +++ b/Source/Engine/Platform/SDL/SDLInput.cpp @@ -11,6 +11,11 @@ #include "Engine/Input/Mouse.h" #include "Engine/Input/Keyboard.h" #include "Engine/Input/Gamepad.h" +#include "Engine/Engine/Screen.h" +#if USE_EDITOR +#include "Editor/Editor.h" +#include "Editor/Managed/ManagedEditor.h" +#endif #include @@ -352,7 +357,9 @@ public: class SDLMouse : public Mouse { private: - Float2 oldPosition; + Float2 oldPosition = Float2::Zero; + Window* relativeModeWindow = nullptr; + const SDL_Rect* oldScreenRect = nullptr; public: /// @@ -370,14 +377,24 @@ public: /// Float2 GetOldMousePosition() const { - return oldPosition; + ASSERT(relativeModeWindow != nullptr); + return relativeModeWindow->ClientToScreen(oldPosition); } // [Mouse] - void SetMousePosition(const Float2& newPosition) final override + void SetMousePosition(const Float2& screenPosition) final override { - SDL_WarpMouseGlobal(newPosition.X, newPosition.Y); - OnMouseMoved(newPosition); +#if USE_EDITOR + auto window = Editor::Managed->GetGameWindow(); + if (window == nullptr) + window = Engine::MainWindow; +#else + auto window = Engine::MainWindow; +#endif + Float2 position = window->ScreenToClient(screenPosition); + SDL_WarpMouseInWindow(static_cast(window)->_window, position.X, position.Y); + + OnMouseMoved(position); } void SetRelativeMode(bool relativeMode, Window* window) final override @@ -385,19 +402,29 @@ public: if (relativeMode == _relativeMode) return; - auto sdlWindow = static_cast(window)->GetSDLWindow(); + auto windowHandle = static_cast(window)->_window; if (relativeMode) + { + oldScreenRect = SDL_GetWindowMouseRect(windowHandle); + relativeModeWindow = window; SDL_GetMouseState(&oldPosition.X, &oldPosition.Y); + if (!SDL_CursorVisible()) + { + // Trap the cursor in current location + SDL_Rect clipRect = { (int)oldPosition.X, (int)oldPosition.Y, 1, 1 }; + SDL_SetWindowMouseRect(windowHandle, &clipRect); + } + } + else + { + SDL_SetWindowMouseRect(windowHandle, oldScreenRect); + oldScreenRect = nullptr; + relativeModeWindow = nullptr; + } Mouse::SetRelativeMode(relativeMode, window); - if (!SDL_SetWindowRelativeMouseMode(sdlWindow, relativeMode)) + if (!SDL_SetWindowRelativeMouseMode(windowHandle, relativeMode)) LOG(Error, "Failed to set mouse relative mode: {0}", String(SDL_GetError())); - - if (!relativeMode) - { - SDL_WarpMouseInWindow(sdlWindow, oldPosition.X, oldPosition.Y); - OnMouseMoved(oldPosition); - } } }; diff --git a/Source/Engine/Platform/SDL/SDLPlatform.cpp b/Source/Engine/Platform/SDL/SDLPlatform.cpp index be384701d..814a6f134 100644 --- a/Source/Engine/Platform/SDL/SDLPlatform.cpp +++ b/Source/Engine/Platform/SDL/SDLPlatform.cpp @@ -71,7 +71,7 @@ bool SDLPlatform::Init() SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, "0"); SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, "1"); // Needed for tracking mode - SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "1"); // Is this needed? + SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "0"); // //SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); // Disables raw mouse input SDL_SetHint(SDL_HINT_WINDOWS_RAW_KEYBOARD, "1");