diff --git a/Source/Engine/Engine/Screen.cpp b/Source/Engine/Engine/Screen.cpp index c9efb9e05..40bc0341b 100644 --- a/Source/Engine/Engine/Screen.cpp +++ b/Source/Engine/Engine/Screen.cpp @@ -116,6 +116,19 @@ CursorLockMode Screen::GetCursorLock() void Screen::SetCursorLock(CursorLockMode mode) { +#if USE_EDITOR + const auto win = Editor::Managed->GetGameWindow(); +#else + const auto win = Engine::MainWindow; +#endif + if (win && mode == CursorLockMode::Clipped) + { + win->StartClippingCursor(win->GetClientBounds()); + } + else if (win && CursorLock == CursorLockMode::Clipped) + { + win->EndClippingCursor(); + } CursorLock = mode; } diff --git a/Source/Engine/Input/Enums.h b/Source/Engine/Input/Enums.h index 9600cd2b8..6dc4b78b1 100644 --- a/Source/Engine/Input/Enums.h +++ b/Source/Engine/Input/Enums.h @@ -21,6 +21,11 @@ API_ENUM() enum class CursorLockMode /// Cursor position is locked to the center of the game window. /// Locked = 1, + + /// + /// Cursor position is confined to the bounds of the game window. + /// + Clipped = 2, }; /// diff --git a/Source/Engine/Platform/Base/WindowBase.cpp b/Source/Engine/Platform/Base/WindowBase.cpp index 6394c6d60..b884db38a 100644 --- a/Source/Engine/Platform/Base/WindowBase.cpp +++ b/Source/Engine/Platform/Base/WindowBase.cpp @@ -104,6 +104,7 @@ WindowBase::WindowBase(const CreateWindowSettings& settings) , _trackingMouseOffset(Float2::Zero) , _isUsingMouseOffset(false) , _isTrackingMouse(false) + , _isClippingCursor(false) , RenderTask(nullptr) { // Update window location based on start location diff --git a/Source/Engine/Platform/Base/WindowBase.h b/Source/Engine/Platform/Base/WindowBase.h index 638a7e84a..25b72bc4e 100644 --- a/Source/Engine/Platform/Base/WindowBase.h +++ b/Source/Engine/Platform/Base/WindowBase.h @@ -288,6 +288,7 @@ protected: bool _isUsingMouseOffset; Rectangle _mouseOffsetScreenSize; bool _isTrackingMouse; + bool _isClippingCursor; explicit WindowBase(const CreateWindowSettings& settings); virtual ~WindowBase(); @@ -694,6 +695,29 @@ public: { } + /// + /// Starts the cursor clipping. + /// + /// The bounds that the cursor will be confined to. + API_FUNCTION() virtual void StartClippingCursor(const Rectangle& bounds) + { + } + + /// + /// Gets the value indicating whenever the cursor is being clipped. + /// + API_PROPERTY() bool IsCursorClipping() const + { + return _isClippingCursor; + } + + /// + /// Ends the cursor clipping. + /// + API_FUNCTION() virtual void EndClippingCursor() + { + } + /// /// Gets the mouse cursor. /// diff --git a/Source/Engine/Platform/Windows/WindowsWindow.cpp b/Source/Engine/Platform/Windows/WindowsWindow.cpp index 724c86049..ce2affa44 100644 --- a/Source/Engine/Platform/Windows/WindowsWindow.cpp +++ b/Source/Engine/Platform/Windows/WindowsWindow.cpp @@ -564,6 +564,34 @@ void WindowsWindow::EndTrackingMouse() } } +void WindowsWindow::StartClippingCursor(const Rectangle& bounds) +{ + ASSERT(HasHWND()); + + if (!_isClippingCursor) + { + _isClippingCursor = true; + } + + const RECT lpRect = { + bounds.GetUpperLeft().X, + bounds.GetUpperLeft().Y, + bounds.GetBottomRight().X, + bounds.GetBottomRight().Y + }; + ClipCursor(&lpRect); +} + +void WindowsWindow::EndClippingCursor() +{ + if (_isClippingCursor) + { + _isClippingCursor = false; + + ClipCursor(NULL); + } +} + void WindowsWindow::SetCursor(CursorType type) { // Base diff --git a/Source/Engine/Platform/Windows/WindowsWindow.h b/Source/Engine/Platform/Windows/WindowsWindow.h index 82f1f9909..73ad56f39 100644 --- a/Source/Engine/Platform/Windows/WindowsWindow.h +++ b/Source/Engine/Platform/Windows/WindowsWindow.h @@ -120,6 +120,8 @@ public: DragDropEffect DoDragDrop(const StringView& data) override; void StartTrackingMouse(bool useMouseScreenOffset) override; void EndTrackingMouse() override; + void StartClippingCursor(const Rectangle& bounds) override; + void EndClippingCursor() override; void SetCursor(CursorType type) override; #if USE_EDITOR