From bf4f52e146b09a3171c98926e29d0101be868dc8 Mon Sep 17 00:00:00 2001 From: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> Date: Thu, 18 Nov 2021 10:58:18 +0000 Subject: [PATCH] Updates and fixes to viewport placement (#5712) * updates to use more modern viewport intersection logic Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * updates to editor viewport ray intersection for object placement Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * make ed_defaultEntityPlacementDistance visible to Viewport.cpp Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * fix link error for AZ_CVAR variable Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> * updates following review feedback Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com> --- Code/Editor/2DViewport.cpp | 24 +- Code/Editor/EditorViewportWidget.cpp | 6 +- Code/Editor/EditorViewportWidget.h | 3 +- .../SandboxIntegration.cpp | 10 +- Code/Editor/Viewport.cpp | 236 ++---------------- Code/Editor/Viewport.h | 43 ++-- .../Viewport/ViewportMessages.cpp | 30 +++ .../Viewport/ViewportMessages.h | 6 + .../ViewportSelection/EditorSelectionUtil.cpp | 3 - .../ViewportSelection/EditorSelectionUtil.h | 3 + 10 files changed, 98 insertions(+), 266 deletions(-) diff --git a/Code/Editor/2DViewport.cpp b/Code/Editor/2DViewport.cpp index ba433c869f..4d0609907f 100644 --- a/Code/Editor/2DViewport.cpp +++ b/Code/Editor/2DViewport.cpp @@ -234,7 +234,7 @@ void Q2DViewport::UpdateContent(int flags) } ////////////////////////////////////////////////////////////////////////// -void Q2DViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) +void Q2DViewport::OnRButtonDown([[maybe_unused]] Qt::KeyboardModifiers modifiers, const QPoint& point) { if (GetIEditor()->IsInGameMode()) { @@ -246,9 +246,6 @@ void Q2DViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& p setFocus(); } - // Check Edit Tool. - MouseCallback(eMouseRDown, point, modifiers); - SetCurrentCursor(STD_CURSOR_MOVE, QString()); // Save the mouse down position @@ -273,17 +270,8 @@ void Q2DViewport::OnRButtonUp([[maybe_unused]] Qt::KeyboardModifiers modifiers, } ////////////////////////////////////////////////////////////////////////// -void Q2DViewport::OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) +void Q2DViewport::OnMButtonDown([[maybe_unused]] Qt::KeyboardModifiers modifiers, const QPoint& point) { - //////////////////////////////////////////////////////////////////////// - // User pressed the middle mouse button - //////////////////////////////////////////////////////////////////////// - // Check Edit Tool. - if (MouseCallback(eMouseMDown, point, modifiers)) - { - return; - } - // Save the mouse down position m_RMouseDownPos = point; @@ -300,14 +288,8 @@ void Q2DViewport::OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& p } ////////////////////////////////////////////////////////////////////////// -void Q2DViewport::OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) +void Q2DViewport::OnMButtonUp([[maybe_unused]] Qt::KeyboardModifiers modifiers, [[maybe_unused]] const QPoint& point) { - // Check Edit Tool. - if (MouseCallback(eMouseMUp, point, modifiers)) - { - return; - } - SetViewMode(NothingMode); ReleaseMouse(); diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 86a91a25bb..8f94afd514 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -2307,10 +2307,10 @@ void* EditorViewportWidget::GetSystemCursorConstraintWindow() const return systemCursorConstrained ? renderOverlayHWND() : nullptr; } -void EditorViewportWidget::BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) +void EditorViewportWidget::BuildDragDropContext( + AzQtComponents::ViewportDragContext& context, const AzFramework::ViewportId viewportId, const QPoint& point) { - const auto scaledPoint = WidgetToViewport(pt); - QtViewport::BuildDragDropContext(context, scaledPoint); + QtViewport::BuildDragDropContext(context, viewportId, point); } void EditorViewportWidget::RestoreViewportAfterGameMode() diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index d20f3fe939..7d8daba8c5 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -273,7 +273,8 @@ private: bool CheckRespondToInput() const; - void BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) override; + void BuildDragDropContext( + AzQtComponents::ViewportDragContext& context, AzFramework::ViewportId viewportId, const QPoint& point) override; void SetAsActiveViewport(); void PushDisableRendering(); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 4aae4191a0..64bd943d63 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -57,6 +56,7 @@ #include #include #include +#include #include #include @@ -1394,13 +1394,13 @@ void SandboxIntegrationManager::ContextMenu_NewEntity() { AZ::Vector3 worldPosition = AZ::Vector3::CreateZero(); - CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport(); // If we don't have a viewport active to aid in placement, the object // will be created at the origin. - if (view) + if (CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport()) { - const QPoint viewPoint(static_cast(m_contextMenuViewPoint.GetX()), static_cast(m_contextMenuViewPoint.GetY())); - worldPosition = view->GetHitLocation(viewPoint); + worldPosition = AzToolsFramework::FindClosestPickIntersection( + view->GetViewportId(), AzFramework::ScreenPointFromVector2(m_contextMenuViewPoint), AzToolsFramework::EditorPickRayLength, + GetDefaultEntityPlacementDistance()); } CreateNewEntityAtPosition(worldPosition); diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index c8f2e268d9..77be6e260e 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -14,14 +14,19 @@ // Qt #include +// AzCore +#include + // AzQtComponents #include #include #include #include +#include // Editor +#include "Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h" #include "ViewManager.h" #include "Include/ITransformManipulator.h" #include "Include/HitContext.h" @@ -32,22 +37,35 @@ #include "GameEngine.h" #include "Settings.h" - #ifdef LoadCursor #undef LoadCursor #endif +AZ_CVAR( + float, + ed_defaultEntityPlacementDistance, + 10.0f, + nullptr, + AZ::ConsoleFunctorFlags::Null, + "The default distance to place an entity from the camera if no intersection is found"); + +float GetDefaultEntityPlacementDistance() +{ + return ed_defaultEntityPlacementDistance; +} + ////////////////////////////////////////////////////////////////////// // Viewport drag and drop support ////////////////////////////////////////////////////////////////////// -void QtViewport::BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) +void QtViewport::BuildDragDropContext( + AzQtComponents::ViewportDragContext& context, const AzFramework::ViewportId viewportId, const QPoint& point) { - context.m_hitLocation = AZ::Vector3::CreateZero(); - context.m_hitLocation = GetHitLocation(pt); + context.m_hitLocation = AzToolsFramework::FindClosestPickIntersection( + viewportId, AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(point), AzToolsFramework::EditorPickRayLength, + GetDefaultEntityPlacementDistance()); } - void QtViewport::dragEnterEvent(QDragEnterEvent* event) { if (!GetIEditor()->GetGameEngine()->IsLevelLoaded()) @@ -66,7 +84,7 @@ void QtViewport::dragEnterEvent(QDragEnterEvent* event) // new bus-based way of doing it (install a listener!) using namespace AzQtComponents; ViewportDragContext context; - BuildDragDropContext(context, event->pos()); + BuildDragDropContext(context, GetViewportId(), event->pos()); DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragEnter, event, context); } } @@ -89,7 +107,7 @@ void QtViewport::dragMoveEvent(QDragMoveEvent* event) // new bus-based way of doing it (install a listener!) using namespace AzQtComponents; ViewportDragContext context; - BuildDragDropContext(context, event->pos()); + BuildDragDropContext(context, GetViewportId(), event->pos()); DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragMove, event, context); } } @@ -112,7 +130,7 @@ void QtViewport::dropEvent(QDropEvent* event) { // new bus-based way of doing it (install a listener!) ViewportDragContext context; - BuildDragDropContext(context, event->pos()); + BuildDragDropContext(context, GetViewportId(), event->pos()); DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::Drop, event, context); } } @@ -340,13 +358,6 @@ void QtViewport::resizeEvent(QResizeEvent* event) Update(); } -////////////////////////////////////////////////////////////////////////// -void QtViewport::leaveEvent(QEvent* event) -{ - QWidget::leaveEvent(event); - MouseCallback(eMouseLeave, QPoint(), Qt::KeyboardModifiers(), Qt::MouseButtons()); -} - ////////////////////////////////////////////////////////////////////////// void QtViewport::paintEvent([[maybe_unused]] QPaintEvent* event) { @@ -581,63 +592,7 @@ void QtViewport::keyReleaseEvent(QKeyEvent* event) OnKeyUp(nativeKey, 1, event->nativeModifiers()); } -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnLButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - // Save the mouse down position - m_cMouseDownPos = point; - - if (MouseCallback(eMouseLDown, point, modifiers)) - { - return; - } -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnLButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - // Check Edit Tool. - MouseCallback(eMouseLUp, point, modifiers); -} -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - MouseCallback(eMouseRDown, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - MouseCallback(eMouseRUp, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - // Check Edit Tool. - MouseCallback(eMouseMDown, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - // Move the viewer to the mouse location. - // Check Edit Tool. - MouseCallback(eMouseMUp, point, modifiers); -} -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnMButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - MouseCallback(eMouseMDblClick, point, modifiers); -} - - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint& point) -{ - MouseCallback(eMouseMove, point, modifiers, buttons); -} ////////////////////////////////////////////////////////////////////////// void QtViewport::OnSetCursor() @@ -696,44 +651,6 @@ void QtViewport::OnDragSelectRectangle(const QRect& rect, bool bNormalizeRect) GetIEditor()->SetStatusText(szNewStatusText); } -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnLButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - if (GetIEditor()->IsInGameMode()) - { - // Ignore double clicks while in game. - return; - } - - MouseCallback(eMouseLDblClick, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnRButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point) -{ - MouseCallback(eMouseRDblClick, point, modifiers); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnKeyDown([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) -{ - if (GetIEditor()->IsInGameMode()) - { - // Ignore key downs while in game. - return; - } -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::OnKeyUp([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) -{ - if (GetIEditor()->IsInGameMode()) - { - // Ignore key downs while in game. - return; - } -} - ////////////////////////////////////////////////////////////////////////// void QtViewport::SetCurrentCursor(const QCursor& hCursor, const QString& cursorString) { @@ -1119,29 +1036,6 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo) return false; } -AZ::Vector3 QtViewport::GetHitLocation(const QPoint& point) -{ - Vec3 pos = Vec3(ZERO); - HitContext hit; - if (HitTest(point, hit)) - { - pos = hit.raySrc + hit.rayDir * hit.dist; - pos = SnapToGrid(pos); - } - else - { - bool hitTerrain; - pos = ViewToWorld(point, &hitTerrain); - if (hitTerrain) - { - pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y); - } - pos = SnapToGrid(pos); - } - - return AZ::Vector3(pos.x, pos.y, pos.z); -} - ////////////////////////////////////////////////////////////////////////// void QtViewport::SetZoomFactor(float fZoomFactor) { @@ -1315,84 +1209,6 @@ bool QtViewport::GetAdvancedSelectModeFlag() return m_bAdvancedSelectMode; } -////////////////////////////////////////////////////////////////////////// -bool QtViewport::MouseCallback(EMouseEvent event, const QPoint& point, Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons) -{ - AZ_PROFILE_FUNCTION(Editor); - - // Ignore any mouse events in game mode. - if (GetIEditor()->IsInGameMode()) - { - return true; - } - - // We must ignore mouse events when we are in the middle of an assert. - // Reason: If we have an assert called from an engine module under the editor, if we call this function, - // it may call the engine again and cause a deadlock. - // Concrete example: CryPhysics called from Trackview causing an assert, and moving the cursor over the viewport - // would cause the editor to freeze as it calls CryPhysics again for a raycast while it didn't release the lock. - if (gEnv->pSystem->IsAssertDialogVisible()) - { - return true; - } - - ////////////////////////////////////////////////////////////////////////// - // Hit test gizmo objects. - ////////////////////////////////////////////////////////////////////////// - bool bAltClick = (modifiers & Qt::AltModifier); - bool bCtrlClick = (modifiers & Qt::ControlModifier); - bool bShiftClick = (modifiers & Qt::ShiftModifier); - - int flags = (bCtrlClick ? MK_CONTROL : 0) | - (bShiftClick ? MK_SHIFT : 0) | - ((buttons& Qt::LeftButton) ? MK_LBUTTON : 0) | - ((buttons& Qt::MiddleButton) ? MK_MBUTTON : 0) | - ((buttons& Qt::RightButton) ? MK_RBUTTON : 0); - - switch (event) - { - case eMouseMove: - - if (m_nLastUpdateFrame == m_nLastMouseMoveFrame) - { - // If mouse move event generated in the same frame, ignore it. - return false; - } - m_nLastMouseMoveFrame = m_nLastUpdateFrame; - - // Skip the marker position update if anything is selected, since it is only used - // by the info bar which doesn't show the marker when there is an active selection. - // This helps a performance issue when calling ViewToWorld (which calls RayWorldIntersection) - // on every mouse movement becomes very expensive in scenes with large amounts of entities. - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (!(buttons & Qt::RightButton) /* && m_nLastUpdateFrame != m_nLastMouseMoveFrame*/ && (selection && selection->IsEmpty())) - { - //m_nLastMouseMoveFrame = m_nLastUpdateFrame; - Vec3 pos = ViewToWorld(point); - GetIEditor()->SetMarkerPosition(pos); - } - break; - } - - QPoint tempPoint(point.x(), point.y()); - - ////////////////////////////////////////////////////////////////////////// - // Handle viewport manipulators. - ////////////////////////////////////////////////////////////////////////// - if (!bAltClick) - { - ITransformManipulator* pManipulator = GetIEditor()->GetTransformManipulator(); - if (pManipulator) - { - if (pManipulator->MouseCallback(this, event, tempPoint, flags)) - { - return true; - } - } - } - - return false; -} ////////////////////////////////////////////////////////////////////////// void QtViewport::ProcessRenderLisneters(DisplayContext& rstDisplayContext) { diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index 7f8ccc4c4f..bf44b914aa 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -6,13 +6,12 @@ * */ - // Description : interface for the CViewport class. - #pragma once #if !defined(Q_MOC_RUN) +#include #include #include #include @@ -88,6 +87,9 @@ enum EStdCursor STD_CURSOR_LAST, }; +//! The default distance an entity is placed from the camera if there is no intersection +SANDBOX_API float GetDefaultEntityPlacementDistance(); + AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING class SANDBOX_API CViewport : public IDisplayViewport @@ -201,7 +203,6 @@ public: //! Performs hit testing of 2d point in view to find which object hit. virtual bool HitTest(const QPoint& point, HitContext& hitInfo) = 0; - virtual AZ::Vector3 GetHitLocation(const QPoint& point) = 0; virtual void MakeConstructionPlane(int axis) = 0; @@ -432,7 +433,6 @@ public: //! Performs hit testing of 2d point in view to find which object hit. bool HitTest(const QPoint& point, HitContext& hitInfo) override; - AZ::Vector3 GetHitLocation(const QPoint& point) override; //! Do 2D hit testing of line in world space. // pToCameraDistance is an optional output parameter in which distance from the camera to the line is returned. @@ -522,9 +522,6 @@ protected: void setRenderOverlayVisible(bool); bool isRenderOverlayVisible() const; - // called to process mouse callback inside the viewport. - virtual bool MouseCallback(EMouseEvent event, const QPoint& point, Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons = Qt::NoButton); - void ProcessRenderLisneters(DisplayContext& rstDisplayContext); void mousePressEvent(QMouseEvent* event) override; @@ -535,29 +532,29 @@ protected: void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; void resizeEvent(QResizeEvent* event) override; - void leaveEvent(QEvent* event) override; - void paintEvent(QPaintEvent* event) override; - virtual void OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint& point); - virtual void OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta, const QPoint& pt); - virtual void OnLButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnLButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnMButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnLButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnRButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point); - virtual void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); - virtual void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); + virtual void OnMouseMove(Qt::KeyboardModifiers, Qt::MouseButtons, const QPoint&) {} + virtual void OnMouseWheel(Qt::KeyboardModifiers, short zDelta, const QPoint&); + virtual void OnLButtonDown(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnLButtonUp(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnRButtonDown(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnRButtonUp(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnMButtonDblClk(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnMButtonDown(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnMButtonUp(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnLButtonDblClk(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnRButtonDblClk(Qt::KeyboardModifiers, const QPoint&) {} + virtual void OnKeyDown([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) {} + virtual void OnKeyUp([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) {} #if defined(AZ_PLATFORM_WINDOWS) void OnRawInput(UINT wParam, HRAWINPUT lParam); #endif void OnSetCursor(); - virtual void BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt); + virtual void BuildDragDropContext( + AzQtComponents::ViewportDragContext& context, AzFramework::ViewportId viewportId, const QPoint& point); + void dragEnterEvent(QDragEnterEvent* event) override; void dragMoveEvent(QDragMoveEvent* event) override; void dragLeaveEvent(QDragLeaveEvent* event) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp index e3b45aca2b..8f8bd3e3f9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.cpp @@ -6,6 +6,7 @@ * */ +#include #include namespace AzToolsFramework @@ -62,4 +63,33 @@ namespace AzToolsFramework return circleBoundWidth; } + + AZ::Vector3 FindClosestPickIntersection( + AzFramework::ViewportId viewportId, const AzFramework::ScreenPoint& screenPoint, const float rayLength, const float defaultDistance) + { + using AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus; + AzToolsFramework::ViewportInteraction::ProjectedViewportRay viewportRay{}; + ViewportInteractionRequestBus::EventResult( + viewportRay, viewportId, &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPoint); + + AzFramework::RenderGeometry::RayRequest ray; + ray.m_startWorldPosition = viewportRay.origin; + ray.m_endWorldPosition = viewportRay.origin + viewportRay.direction * rayLength; + ray.m_onlyVisible = true; + + AzFramework::RenderGeometry::RayResult renderGeometryIntersectionResult; + AzFramework::RenderGeometry::IntersectorBus::EventResult( + renderGeometryIntersectionResult, AzToolsFramework::GetEntityContextId(), + &AzFramework::RenderGeometry::IntersectorBus::Events::RayIntersect, ray); + + // attempt a ray intersection with any visible mesh and return the intersection position if successful + if (renderGeometryIntersectionResult) + { + return renderGeometryIntersectionResult.m_worldPosition; + } + else + { + return viewportRay.origin + viewportRay.direction * defaultDistance; + } + } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index 84a8daa83e..aa97eb361e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -334,6 +334,12 @@ namespace AzToolsFramework return entityContextId; } + //! Performs an intersection test against meshes in the scene, if there is a hit (the ray intersects + //! a mesh), that position is returned, otherwise a point projected defaultDistance from the + //! origin of the ray will be returned. + AZ::Vector3 FindClosestPickIntersection( + AzFramework::ViewportId viewportId, const AzFramework::ScreenPoint& screenPoint, float rayLength, float defaultDistance); + //! Maps a mouse interaction event to a ClickDetector event. //! @note Function only cares about up or down events, all other events are mapped to Nil (ignored). AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp index a5ef66e7a3..0a7bed6b18 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp @@ -18,9 +18,6 @@ namespace AzToolsFramework { - // default ray length for picking in the viewport - static const float EditorPickRayLength = 1000.0f; - AZ::Vector3 CalculateCenterOffset(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot) { if (Centered(pivot)) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h index d58549b329..5c9f47fdd3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h @@ -26,6 +26,9 @@ namespace AzFramework namespace AzToolsFramework { + //! Default ray length for picking in the viewport. + inline constexpr float EditorPickRayLength = 1000.0f; + //! Is the pivot at the center of the object (middle of extents) or at the //! exported authored object root position. inline bool Centered(const EditorTransformComponentSelectionRequests::Pivot pivot)