From f269d92f9085d4d8d83c50ce3359918d65a895e6 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Tue, 27 Apr 2021 11:17:24 -0500 Subject: [PATCH 1/2] [LYN-3122] Fixed the viewport Entity hit test logic. This allows the BuildDragDropContext to detect hit position correctly so that assets dragged into the viewport are placed in the correct position. --- Code/Sandbox/Editor/EditorViewportWidget.h | 5 +- Code/Sandbox/Editor/RenderViewport.h | 5 +- Code/Sandbox/Editor/Viewport.cpp | 59 +++++++++++++++++++++- Code/Sandbox/Editor/Viewport.h | 7 +++ 4 files changed, 67 insertions(+), 9 deletions(-) diff --git a/Code/Sandbox/Editor/EditorViewportWidget.h b/Code/Sandbox/Editor/EditorViewportWidget.h index 1244e61242..b0dd2a286c 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.h +++ b/Code/Sandbox/Editor/EditorViewportWidget.h @@ -234,11 +234,8 @@ public: QPoint ViewportToWidget(const QPoint& point) const; QSize WidgetToViewport(const QSize& size) const; - /// Take raw input and create a final mouse interaction. - /// @attention Do not map **point** from widget to viewport explicitly, - /// this is handled internally by BuildMouseInteraction - just pass directly. AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction( - Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, const QPoint& point); + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, const QPoint& point) override; void SetPlayerPos() { diff --git a/Code/Sandbox/Editor/RenderViewport.h b/Code/Sandbox/Editor/RenderViewport.h index 664ed73abc..2edbd86770 100644 --- a/Code/Sandbox/Editor/RenderViewport.h +++ b/Code/Sandbox/Editor/RenderViewport.h @@ -238,11 +238,8 @@ public: QPoint ViewportToWidget(const QPoint& point) const; QSize WidgetToViewport(const QSize& size) const; - /// Take raw input and create a final mouse interaction. - /// @attention Do not map **point** from widget to viewport explicitly, - /// this is handled internally by BuildMouseInteraction - just pass directly. AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction( - Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, const QPoint& point); + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, const QPoint& point) override; void SetPlayerPos() { diff --git a/Code/Sandbox/Editor/Viewport.cpp b/Code/Sandbox/Editor/Viewport.cpp index 1041a4f086..44480f530d 100644 --- a/Code/Sandbox/Editor/Viewport.cpp +++ b/Code/Sandbox/Editor/Viewport.cpp @@ -21,6 +21,9 @@ // AzQtComponents #include +#include +#include + // Editor #include "ViewManager.h" #include "Include/ITransformManipulator.h" @@ -1091,6 +1094,13 @@ void QtViewport::SetAxisConstrain(int axis) m_activeAxis = axis; }; +AzToolsFramework::ViewportInteraction::MouseInteraction QtViewport::BuildMouseInteraction( + [[maybe_unused]] Qt::MouseButtons buttons, [[maybe_unused]] Qt::KeyboardModifiers modifiers, [[maybe_unused]] const QPoint& point) +{ + // Implemented by sub-class + return AzToolsFramework::ViewportInteraction::MouseInteraction(); +} + ////////////////////////////////////////////////////////////////////////// bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) { @@ -1103,7 +1113,54 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) hitInfo.bUseSelectionHelpers = true; } - return GetIEditor()->GetObjectManager()->HitTest(hitInfo); + const int viewportId = GetViewportId(); + + // TODO: Use the EditorVisibleEntityDataCache instead once we are able to move to EditorViewportWidget + AzToolsFramework::EntityIdList visibleEntityIds; + AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Event( + viewportId, + &AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequests::FindVisibleEntities, + visibleEntityIds); + + // Look through all visible entities to find the closest one to the specified mouse point + AZ::EntityId entityIdUnderCursor; + float closestDistance = std::numeric_limits::max(); + for (auto entityId : visibleEntityIds) + { + using AzFramework::ViewportInfo; + // Check if components provide an aabb + if (const AZ::Aabb aabb = AzToolsFramework::CalculateEditorEntitySelectionBounds(entityId, ViewportInfo{ viewportId }); + aabb.IsValid()) + { + using namespace AzToolsFramework::ViewportInteraction; + + MouseInteraction mouseInteraction = BuildMouseInteraction(QGuiApplication::mouseButtons(), + QGuiApplication::queryKeyboardModifiers(), + point); + + // Coarse grain check + if (AzToolsFramework::AabbIntersectMouseRay(mouseInteraction, aabb)) + { + // If success, pick against specific component + if (AzToolsFramework::PickEntity( + entityId, mouseInteraction, + closestDistance, viewportId)) + { + entityIdUnderCursor = entityId; + } + } + } + } + + // If we hit a valid Entity, then store the distance in the HitContext + // so that the caller can use this for calculations + if (entityIdUnderCursor.IsValid()) + { + hitInfo.dist = closestDistance; + return true; + } + + return false; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Viewport.h b/Code/Sandbox/Editor/Viewport.h index 9979a3bb0a..bd7c749573 100644 --- a/Code/Sandbox/Editor/Viewport.h +++ b/Code/Sandbox/Editor/Viewport.h @@ -17,6 +17,7 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include #include #include "IPostRenderer.h" @@ -405,6 +406,12 @@ public: void SetAxisConstrain(int axis); + /// Take raw input and create a final mouse interaction. + /// @attention Do not map **point** from widget to viewport explicitly, + /// this is handled internally by BuildMouseInteraction - just pass directly. + virtual AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction( + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, const QPoint& point); + ////////////////////////////////////////////////////////////////////////// // Selection. ////////////////////////////////////////////////////////////////////////// From 84e0f6f58d2009e746b8e9832777e6f557f9d383 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Tue, 27 Apr 2021 13:32:30 -0500 Subject: [PATCH 2/2] [LYN-3122] Moved invariant logic outside of for loop and removed TODO comment. --- Code/Sandbox/Editor/Viewport.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Code/Sandbox/Editor/Viewport.cpp b/Code/Sandbox/Editor/Viewport.cpp index 44480f530d..37a9ee5f29 100644 --- a/Code/Sandbox/Editor/Viewport.cpp +++ b/Code/Sandbox/Editor/Viewport.cpp @@ -1115,7 +1115,6 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) const int viewportId = GetViewportId(); - // TODO: Use the EditorVisibleEntityDataCache instead once we are able to move to EditorViewportWidget AzToolsFramework::EntityIdList visibleEntityIds; AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Event( viewportId, @@ -1123,8 +1122,12 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) visibleEntityIds); // Look through all visible entities to find the closest one to the specified mouse point + using namespace AzToolsFramework::ViewportInteraction; AZ::EntityId entityIdUnderCursor; float closestDistance = std::numeric_limits::max(); + MouseInteraction mouseInteraction = BuildMouseInteraction(QGuiApplication::mouseButtons(), + QGuiApplication::queryKeyboardModifiers(), + point); for (auto entityId : visibleEntityIds) { using AzFramework::ViewportInfo; @@ -1132,12 +1135,6 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) if (const AZ::Aabb aabb = AzToolsFramework::CalculateEditorEntitySelectionBounds(entityId, ViewportInfo{ viewportId }); aabb.IsValid()) { - using namespace AzToolsFramework::ViewportInteraction; - - MouseInteraction mouseInteraction = BuildMouseInteraction(QGuiApplication::mouseButtons(), - QGuiApplication::queryKeyboardModifiers(), - point); - // Coarse grain check if (AzToolsFramework::AabbIntersectMouseRay(mouseInteraction, aabb)) {