Fix issue with mouse input for viewport camera (#3210)
* fix for drift accumulating in the viewport camera Signed-off-by: hultonha <hultonha@amazon.co.uk> * fix typo and update how events are stored Signed-off-by: hultonha <hultonha@amazon.co.uk> * respond to PR feedback and fix linux and windows build issues Signed-off-by: hultonha <hultonha@amazon.co.uk> * fix failing unit tests in camera input Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
+17
-21
@@ -285,7 +285,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::ProcessPendingMouseEvents()
|
||||
void QtEventToAzInputMapper::ProcessPendingMouseEvents(const QPoint& cursorDelta)
|
||||
{
|
||||
auto systemCursorChannel =
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::SystemCursorPosition);
|
||||
@@ -297,14 +297,8 @@ namespace AzToolsFramework
|
||||
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::Z);
|
||||
|
||||
systemCursorChannel->ProcessRawInputEvent(m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetLength());
|
||||
// Generate movement events based on the pixel delta divided by the DPI scaling factor, to calculate a rough approximation
|
||||
// of cursor movement velocity.
|
||||
movementXChannel->ProcessRawInputEvent(
|
||||
m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetX() * aznumeric_cast<float>(m_sourceWidget->width()) /
|
||||
m_sourceWidget->devicePixelRatioF());
|
||||
movementYChannel->ProcessRawInputEvent(
|
||||
m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta.GetY() * aznumeric_cast<float>(m_sourceWidget->height()) /
|
||||
m_sourceWidget->devicePixelRatioF());
|
||||
movementXChannel->ProcessRawInputEvent(cursorDelta.x());
|
||||
movementYChannel->ProcessRawInputEvent(cursorDelta.y());
|
||||
mouseWheelChannel->ProcessRawInputEvent(0.0f);
|
||||
|
||||
NotifyUpdateChannelIfNotIdle(systemCursorChannel, nullptr);
|
||||
@@ -337,41 +331,43 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Vector2 QtEventToAzInputMapper::WidgetPositionToNormalizedPosition(QPoint position)
|
||||
AZ::Vector2 QtEventToAzInputMapper::WidgetPositionToNormalizedPosition(const QPoint& position)
|
||||
{
|
||||
const float normalizedX = aznumeric_cast<float>(position.x()) / aznumeric_cast<float>(m_sourceWidget->width());
|
||||
const float normalizedY = aznumeric_cast<float>(position.y()) / aznumeric_cast<float>(m_sourceWidget->height());
|
||||
return AZ::Vector2{normalizedX, normalizedY};
|
||||
return AZ::Vector2{ normalizedX, normalizedY };
|
||||
}
|
||||
|
||||
QPoint QtEventToAzInputMapper::NormalizedPositionToWidgetPosition(AZ::Vector2 normalizedPosition)
|
||||
QPoint QtEventToAzInputMapper::NormalizedPositionToWidgetPosition(const AZ::Vector2& normalizedPosition)
|
||||
{
|
||||
const int denormalizedX = aznumeric_cast<int>(normalizedPosition.GetX() * m_sourceWidget->width());
|
||||
const int denormalizedY = aznumeric_cast<int>(normalizedPosition.GetY() * m_sourceWidget->height());
|
||||
return QPoint{denormalizedX, denormalizedY};
|
||||
return QPoint{ denormalizedX, denormalizedY };
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::HandleMouseMoveEvent(QMouseEvent* mouseEvent)
|
||||
{
|
||||
AZ::Vector2 lastCursorPosition = m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition;
|
||||
const QPoint cursorPosition = mouseEvent->pos();
|
||||
const QPoint cursorDelta = cursorPosition - m_previousCursorPosition;
|
||||
|
||||
const QPoint mousePos = mouseEvent->pos();
|
||||
const AZ::Vector2 normalizedPosition = WidgetPositionToNormalizedPosition(mousePos);
|
||||
m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta = normalizedPosition - m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition;
|
||||
m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition = normalizedPosition;
|
||||
ProcessPendingMouseEvents();
|
||||
m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition = WidgetPositionToNormalizedPosition(cursorPosition);
|
||||
m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta = WidgetPositionToNormalizedPosition(cursorDelta);
|
||||
|
||||
ProcessPendingMouseEvents(cursorDelta);
|
||||
|
||||
if (m_capturingCursor)
|
||||
{
|
||||
// Reset our cursor position to the previous point.
|
||||
QPoint targetScreenPosition = m_sourceWidget->mapToGlobal(NormalizedPositionToWidgetPosition(lastCursorPosition));
|
||||
const QPoint targetScreenPosition = m_sourceWidget->mapToGlobal(m_previousCursorPosition);
|
||||
AzQtComponents::SetCursorPos(targetScreenPosition);
|
||||
|
||||
// Even though we just set the cursor position, there are edge cases such as remote desktop that will leave
|
||||
// the cursor position unchanged. For safety, we re-cache our last cursor position for delta generation.
|
||||
QPoint actualWidgetPosition = m_sourceWidget->mapFromGlobal(QCursor::pos());
|
||||
const QPoint actualWidgetPosition = m_sourceWidget->mapFromGlobal(QCursor::pos());
|
||||
m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition = WidgetPositionToNormalizedPosition(actualWidgetPosition);
|
||||
}
|
||||
|
||||
m_previousCursorPosition = cursorPosition;
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::HandleKeyEvent(QKeyEvent* keyEvent)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <QEvent>
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
#endif //! defined(Q_MOC_RUN)
|
||||
|
||||
class QWidget;
|
||||
@@ -111,12 +112,12 @@ namespace AzToolsFramework
|
||||
void NotifyUpdateChannelIfNotIdle(const AzFramework::InputChannel* channel, QEvent* event);
|
||||
|
||||
// Processes any pending mouse movement events, this allows mouse movement channels to close themselves.
|
||||
void ProcessPendingMouseEvents();
|
||||
void ProcessPendingMouseEvents(const QPoint& cursorDelta);
|
||||
|
||||
// Converts a point in logical source widget space [0..m_sourceWidget->size()] to normalized [0..1] space.
|
||||
AZ::Vector2 WidgetPositionToNormalizedPosition(QPoint position);
|
||||
AZ::Vector2 WidgetPositionToNormalizedPosition(const QPoint& position);
|
||||
// Converts a point in normalized [0..1] space to logical source widget space [0..m_sourceWidget->size()].
|
||||
QPoint NormalizedPositionToWidgetPosition(AZ::Vector2 normalizedPosition);
|
||||
QPoint NormalizedPositionToWidgetPosition(const AZ::Vector2& normalizedPosition);
|
||||
|
||||
// Handle mouse click events.
|
||||
void HandleMouseButtonEvent(QMouseEvent* mouseEvent);
|
||||
@@ -148,6 +149,8 @@ namespace AzToolsFramework
|
||||
AZStd::unordered_set<Qt::Key> m_highPriorityKeys;
|
||||
// A lookup table for AZ input channel ID -> physical input channel on our mouse or keyboard device.
|
||||
AZStd::unordered_map<AzFramework::InputChannelId, AzFramework::InputChannel*> m_channels;
|
||||
// Where the position of the mouse cursor was at the last cursor event.
|
||||
QPoint m_previousCursorPosition;
|
||||
// The source widget to map events from, used to calculate the relative mouse position within the widget bounds.
|
||||
QWidget* m_sourceWidget;
|
||||
// Flags whether or not Qt events should currently be processed.
|
||||
|
||||
+7
-16
@@ -188,7 +188,7 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
using namespace AzToolsFramework::ViewportInteraction;
|
||||
using AzToolsFramework::ViewportInteraction::MouseEvent;
|
||||
const auto& mouseInteraction = mouseInteractionEvent.m_mouseInteraction;
|
||||
// store the current interaction for use in DrawManipulators
|
||||
m_currentInteraction = mouseInteraction;
|
||||
@@ -196,28 +196,19 @@ namespace AzToolsFramework
|
||||
switch (mouseInteractionEvent.m_mouseEvent)
|
||||
{
|
||||
case MouseEvent::Down:
|
||||
{
|
||||
return m_manipulatorManager->ConsumeViewportMousePress(mouseInteraction);
|
||||
}
|
||||
return m_manipulatorManager->ConsumeViewportMousePress(mouseInteraction);
|
||||
case MouseEvent::DoubleClick:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case MouseEvent::Move:
|
||||
{
|
||||
AzToolsFramework::ManipulatorManager::ConsumeMouseMoveResult mouseMoveResult =
|
||||
AzToolsFramework::ManipulatorManager::ConsumeMouseMoveResult::None;
|
||||
mouseMoveResult = m_manipulatorManager->ConsumeViewportMouseMove(mouseInteraction);
|
||||
const AzToolsFramework::ManipulatorManager::ConsumeMouseMoveResult mouseMoveResult =
|
||||
m_manipulatorManager->ConsumeViewportMouseMove(mouseInteraction);
|
||||
return mouseMoveResult == AzToolsFramework::ManipulatorManager::ConsumeMouseMoveResult::Interacting;
|
||||
}
|
||||
case MouseEvent::Up:
|
||||
{
|
||||
return m_manipulatorManager->ConsumeViewportMouseRelease(mouseInteraction);
|
||||
}
|
||||
return m_manipulatorManager->ConsumeViewportMouseRelease(mouseInteraction);
|
||||
case MouseEvent::Wheel:
|
||||
{
|
||||
return m_manipulatorManager->ConsumeViewportMouseWheel(mouseInteraction);
|
||||
}
|
||||
return m_manipulatorManager->ConsumeViewportMouseWheel(mouseInteraction);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user