Fix mouse resetting issues after ending relative mode

This commit is contained in:
2025-01-19 21:56:40 +02:00
parent 0aefdf4411
commit d64654ed68
2 changed files with 41 additions and 14 deletions

View File

@@ -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 <SDL3/SDL_events.h>
@@ -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:
/// <summary>
@@ -370,14 +377,24 @@ public:
/// </summary>
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<SDLWindow*>(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<SDLWindow*>(window)->GetSDLWindow();
auto windowHandle = static_cast<SDLWindow*>(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);
}
}
};

View File

@@ -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");