diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp index 18acccf049..d146dc91da 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp @@ -256,6 +256,14 @@ namespace AzToolsFramework // If our focus changes, go ahead and reset all input devices. HandleFocusChange(event); + if (eventType == QEvent::FocusOut) + { + if (m_capturingCursor) + { + qApp->restoreOverrideCursor(); + } + } + // If we focus in on the source widget and the mouse is contained in its // bounds, refresh the cached cursor position to ensure it is up to date (this // ensures cursor positions are refreshed correctly with context menu focus changes) @@ -264,6 +272,11 @@ namespace AzToolsFramework const auto globalCursorPosition = QCursor::pos(); if (m_sourceWidget->geometry().contains(globalCursorPosition)) { + if (m_capturingCursor) + { + qApp->setOverrideCursor(Qt::ForbiddenCursor); + } + HandleMouseMoveEvent(globalCursorPosition); } } @@ -452,4 +465,22 @@ namespace AzToolsFramework } } } + + void QtEventToAzInputMapper::PushCursor(/*enum*/) + { + if (!m_overrideCursor) + { + qApp->setOverrideCursor(Qt::ForbiddenCursor); + m_overrideCursor = true; + } + } + + void QtEventToAzInputMapper::PopCursor() + { + if (m_overrideCursor) + { + qApp->restoreOverrideCursor(); + m_overrideCursor = false; + } + } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h index 5add24ad84..8127738dd3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h @@ -55,6 +55,9 @@ namespace AzToolsFramework //! like a dolly or rotation, where mouse movement is important but cursor location is not. void SetCursorCaptureEnabled(bool enabled); + void PushCursor(/*enum*/); + void PopCursor(); + // QObject overrides... bool eventFilter(QObject* object, QEvent* event) override; @@ -164,6 +167,8 @@ namespace AzToolsFramework bool m_enabled = true; // Flags whether or not the cursor is being constrained to the source widget (for invisible mouse movement). bool m_capturingCursor = false; + // + bool m_overrideCursor = true; // Our viewport-specific AZ devices. We control their internal input channel states. AZStd::unique_ptr m_mouseDevice; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index 9d2f7e9b90..93ca8706eb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -310,6 +310,10 @@ namespace AzToolsFramework virtual void EndCursorCapture() = 0; //! Is the mouse over the viewport. virtual bool IsMouseOver() const = 0; + //! + virtual void PushOverrideCursor(/*enum*/) {} // make virtual + //! + virtual void PopOverrideCursor() {} // make virtual protected: ~ViewportMouseCursorRequests() = default; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp index bb718d0dc9..912e1ccff5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp @@ -189,9 +189,15 @@ namespace AzToolsFramework // Verify if the entity Id corresponds to an entity that is focused; if not, halt selection. if (!IsSelectableAccordingToFocusMode(entityIdUnderCursor)) { + ViewportInteraction::ViewportMouseCursorRequestBus::Event( + viewportId, &ViewportInteraction::ViewportMouseCursorRequestBus::Events::PushOverrideCursor); + return AZ::EntityId(); } + ViewportInteraction::ViewportMouseCursorRequestBus::Event( + viewportId, &ViewportInteraction::ViewportMouseCursorRequestBus::Events::PopOverrideCursor); + // Container Entity support - if the entity that is being selected is part of a closed container, // change the selection to the container instead. if (ContainerEntityInterface* containerEntityInterface = AZ::Interface::Get()) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h index b407aa2b4c..eebe445f7b 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -102,6 +102,8 @@ namespace AtomToolsFramework void BeginCursorCapture() override; void EndCursorCapture() override; bool IsMouseOver() const override; + void PushOverrideCursor(/*enum*/) override; + void PopOverrideCursor() override; // AzFramework::WindowRequestBus::Handler overrides ... void SetWindowTitle(const AZStd::string& title) override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 83926ecc79..df639c8026 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -367,6 +367,16 @@ namespace AtomToolsFramework m_inputChannelMapper->SetCursorCaptureEnabled(false); } + void RenderViewportWidget::PushOverrideCursor(/*enum*/) + { + m_inputChannelMapper->PushCursor(); + } + + void RenderViewportWidget::PopOverrideCursor() + { + m_inputChannelMapper->PopCursor(); + } + void RenderViewportWidget::SetWindowTitle(const AZStd::string& title) { setWindowTitle(QString::fromUtf8(title.c_str()));