Fix cursor locking bounds calculation

This commit is contained in:
2025-04-02 21:37:14 +03:00
parent bebda275a9
commit 68c0ac0ffc
5 changed files with 46 additions and 42 deletions

View File

@@ -123,34 +123,32 @@ void Screen::SetCursorLock(CursorLockMode mode)
#if USE_EDITOR #if USE_EDITOR
const auto win = Editor::Managed->GetGameWindow(true); const auto win = Editor::Managed->GetGameWindow(true);
Rectangle bounds(Editor::Managed->GameViewportToScreen(Float2::Zero), Editor::Managed->GetGameWindowSize()); Rectangle bounds(Editor::Managed->GameViewportToScreen(Float2::Zero), Editor::Managed->GetGameWindowSize());
if (win)
bounds = Rectangle(win->ScreenToClient(bounds.GetTopLeft()), bounds.Size);
#else #else
const auto win = Engine::MainWindow; const auto win = Engine::MainWindow;
Rectangle bounds = win != nullptr ? win->GetClientBounds() : Rectangle(); Rectangle bounds = win != nullptr ? win->GetClientBounds() : Rectangle();
#endif #endif
bool inRelativeMode = Input::Mouse->IsRelative(); if (win)
if (win && mode == CursorLockMode::Clipped)
win->StartClippingCursor(bounds);
else if (win && mode == CursorLockMode::Locked)
{ {
// Use mouse clip region to restrict the cursor in one spot bool inRelativeMode = Input::Mouse->IsRelative();
Rectangle centerBounds; if (mode == CursorLockMode::Clipped)
auto mousePosition = win->GetMousePosition(); win->StartClippingCursor(bounds);
if (bounds.Contains(mousePosition)) else if (mode == CursorLockMode::Locked)
centerBounds = Rectangle(mousePosition, Float2(1, 1)); {
else // Use mouse clip region to restrict the cursor in one spot
centerBounds = Rectangle(bounds.GetCenter(), Float2(1, 1)); win->StartClippingCursor(Rectangle(bounds.GetCenter(), Float2(1, 1)));
win->StartClippingCursor(centerBounds); }
} else if (CursorLock == CursorLockMode::Locked || CursorLock == CursorLockMode::Clipped)
else if (win && (CursorLock == CursorLockMode::Locked || CursorLock == CursorLockMode::Clipped)) win->EndClippingCursor();
win->EndClippingCursor();
CursorLock = mode;
// Enable relative mode when cursor is restricted // Enable relative mode when cursor is restricted
bool focused = win && Engine::HasGameViewportFocus(); if (mode != CursorLockMode::None)
if (win && CursorLock != CursorLockMode::None) Input::Mouse->SetRelativeMode(true, win);
Input::Mouse->SetRelativeMode(true, win); else if (mode == CursorLockMode::None && inRelativeMode)
else if (win && CursorLock == CursorLockMode::None && inRelativeMode) Input::Mouse->SetRelativeMode(false, win);
Input::Mouse->SetRelativeMode(false, win); }
CursorLock = mode;
} }
GameWindowMode Screen::GetGameWindowMode() GameWindowMode Screen::GetGameWindowMode()

View File

@@ -521,6 +521,17 @@ public:
{ {
} }
/// <summary>
/// Gets the mouse position in window coordinates.
/// </summary>
API_PROPERTY() virtual Float2 GetMousePosition() const;
/// <summary>
/// Sets the mouse position in window coordinates.
/// </summary>
/// <param name="position">Mouse position to set on</param>
API_PROPERTY() virtual void SetMousePosition(const Float2& position) const;
/// <summary> /// <summary>
/// Gets the mouse cursor. /// Gets the mouse cursor.
/// </summary> /// </summary>
@@ -717,16 +728,6 @@ public:
API_FUNCTION() bool GetKeyUp(KeyboardKeys key) const; API_FUNCTION() bool GetKeyUp(KeyboardKeys key) const;
public: public:
/// <summary>
/// Gets the mouse position in window coordinates.
/// </summary>
API_PROPERTY() Float2 GetMousePosition() const;
/// <summary>
/// Sets the mouse position in window coordinates.
/// </summary>
/// <param name="position">Mouse position to set on</param>
API_PROPERTY() void SetMousePosition(const Float2& position) const;
/// <summary> /// <summary>
/// Gets the mouse position change during the last frame. /// Gets the mouse position change during the last frame.

View File

@@ -399,6 +399,7 @@ public:
void SetRelativeMode(bool relativeMode, Window* window) final override void SetRelativeMode(bool relativeMode, Window* window) final override
{ {
ASSERT(window != nullptr);
if (relativeMode == _relativeMode) if (relativeMode == _relativeMode)
return; return;

View File

@@ -820,16 +820,8 @@ void SDLWindow::StartClippingCursor(const Rectangle& bounds)
return; return;
#if PLATFORM_LINUX #if PLATFORM_LINUX
{ // The cursor is not fully constrained when positioned outside the clip region
auto oldValue = SDL_GetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION); SetMousePosition(bounds.GetCenter());
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, "1");
// The cursor is not fully constrained when positioned outside of the clip region...
Float2 center = bounds.GetCenter();
SDL_WarpMouseInWindow(_window, center.X, center.Y);
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, oldValue);
}
#endif #endif
_isClippingCursor = true; _isClippingCursor = true;
@@ -847,6 +839,17 @@ void SDLWindow::EndClippingCursor()
SDL_SetWindowMouseRect(_window, nullptr); SDL_SetWindowMouseRect(_window, nullptr);
} }
void SDLWindow::SetMousePosition(const Float2& position) const
{
if (!_settings.AllowInput || !_focused)
return;
SDL_WarpMouseInWindow(_window, position.X, position.Y);
Float2 screenPosition = ClientToScreen(position);
Input::Mouse->OnMouseMoved(screenPosition);
}
void SDLWindow::SetCursor(CursorType type) void SDLWindow::SetCursor(CursorType type)
{ {
CursorType oldCursor = _cursor; CursorType oldCursor = _cursor;

View File

@@ -113,6 +113,7 @@ public:
void EndTrackingMouse() override; void EndTrackingMouse() override;
void StartClippingCursor(const Rectangle& bounds) override; void StartClippingCursor(const Rectangle& bounds) override;
void EndClippingCursor() override; void EndClippingCursor() override;
void SetMousePosition(const Float2& position) const override;
void SetCursor(CursorType type) override; void SetCursor(CursorType type) override;
#if USE_EDITOR && PLATFORM_WINDOWS #if USE_EDITOR && PLATFORM_WINDOWS