// 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)
{
@@ -1407,6 +1223,69 @@ void QtViewport::ProcessRenderLisneters(DisplayContext& rstDisplayContext)
}
//////////////////////////////////////////////////////////////////////////
#if defined(AZ_PLATFORM_WINDOWS)
+// Note: Both CreateAnglesYPR and CreateOrientationYPR were copied verbatim from Cry_Camera.h which has been removed.
+//
+// Description
+//
+// x-YAW
+// y-PITCH (negative=looking down / positive=looking up)
+// z-ROLL
+//
+// Note: If we are looking along the z-axis, its not possible to specify the x and z-angle
+inline Ang3 CreateAnglesYPR(const Matrix33& m)
+{
+ assert(m.IsOrthonormal());
+ float l = Vec3(m.m01, m.m11, 0.0f).GetLength();
+ if (l > 0.0001)
+ {
+ return Ang3(atan2f(-m.m01 / l, m.m11 / l), atan2f(m.m21, l), atan2f(-m.m20 / l, m.m22 / l));
+ }
+ else
+ {
+ return Ang3(0, atan2f(m.m21, l), 0);
+ }
+}
+
+// Description
+// This function builds a 3x3 orientation matrix using YPR-angles
+// Rotation order for the orientation-matrix is Z-X-Y. (Zaxis=YAW / Xaxis=PITCH / Yaxis=ROLL)
+//
+//
+// COORDINATE-SYSTEM
+//
+// z-axis
+// ^
+// |
+// | y-axis
+// | /
+// | /
+// |/
+// +---------------> x-axis
+//
+//
+// Example:
+// Matrix33 orientation=CreateOrientationYPR( Ang3(1,2,3) );
+inline Matrix33 CreateOrientationYPR(const Ang3& ypr)
+{
+ f32 sz, cz;
+ sincos_tpl(ypr.x, &sz, &cz); //Zaxis = YAW
+ f32 sx, cx;
+ sincos_tpl(ypr.y, &sx, &cx); //Xaxis = PITCH
+ f32 sy, cy;
+ sincos_tpl(ypr.z, &sy, &cy); //Yaxis = ROLL
+ Matrix33 c;
+ c.m00 = cy * cz - sy * sz * sx;
+ c.m01 = -sz * cx;
+ c.m02 = sy * cz + cy * sz * sx;
+ c.m10 = cy * sz + sy * sx * cz;
+ c.m11 = cz * cx;
+ c.m12 = sy * sz - cy * sx * cz;
+ c.m20 = -sy * cx;
+ c.m21 = sx;
+ c.m22 = cy * cx;
+ return c;
+}
+
void QtViewport::OnRawInput([[maybe_unused]] UINT wParam, HRAWINPUT lParam)
{
static C3DConnexionDriver* p3DConnexionDriver = 0;
@@ -1450,12 +1329,12 @@ void QtViewport::OnRawInput([[maybe_unused]] UINT wParam, HRAWINPUT lParam)
t *= sys_scale3DMouseTranslation->GetFVal();
float as = 0.001f * gSettings.cameraMoveSpeed;
- Ang3 ypr = CCamera::CreateAnglesYPR(Matrix33(viewTM));
+ Ang3 ypr = CreateAnglesYPR(Matrix33(viewTM));
ypr.x += -all6DOFs[5] * as * fScaleYPR;
ypr.y = AZStd::clamp(ypr.y + all6DOFs[3] * as * fScaleYPR, -1.5f, 1.5f); // to keep rotation in reasonable range
ypr.z = 0; // to have camera always upward
- viewTM = Matrix34(CCamera::CreateOrientationYPR(ypr), viewTM.GetTranslation());
+ viewTM = Matrix34(CreateOrientationYPR(ypr), viewTM.GetTranslation());
viewTM = viewTM * Matrix34::CreateTranslationMat(t);
SetViewTM(viewTM);
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/Editor/ViewportManipulatorController.cpp b/Code/Editor/ViewportManipulatorController.cpp
index 1766945541..e46328eb65 100644
--- a/Code/Editor/ViewportManipulatorController.cpp
+++ b/Code/Editor/ViewportManipulatorController.cpp
@@ -8,13 +8,15 @@
#include "ViewportManipulatorController.h"
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include
-#include
-#include
-#include
-#include
-#include
+#include
#include
@@ -87,8 +89,14 @@ namespace SandboxEditor
}
using InteractionBus = AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
- using namespace AzToolsFramework::ViewportInteraction;
using AzFramework::InputChannel;
+ using AzToolsFramework::ViewportInteraction::KeyboardModifier;
+ using AzToolsFramework::ViewportInteraction::MouseButton;
+ using AzToolsFramework::ViewportInteraction::MouseEvent;
+ using AzToolsFramework::ViewportInteraction::MouseInteraction;
+ using AzToolsFramework::ViewportInteraction::MouseInteractionEvent;
+ using AzToolsFramework::ViewportInteraction::ProjectedViewportRay;
+ using AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus;
bool interactionHandled = false;
float wheelDelta = 0.0f;
@@ -117,16 +125,13 @@ namespace SandboxEditor
aznumeric_cast(position->m_normalizedPosition.GetX() * windowSize.m_width),
aznumeric_cast(position->m_normalizedPosition.GetY() * windowSize.m_height));
- m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPoint;
- AZStd::optional ray;
+ ProjectedViewportRay ray{};
ViewportInteractionRequestBus::EventResult(
ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPoint);
- if (ray.has_value())
- {
- m_mouseInteraction.m_mousePick.m_rayOrigin = ray.value().origin;
- m_mouseInteraction.m_mousePick.m_rayDirection = ray.value().direction;
- }
+ m_mouseInteraction.m_mousePick.m_rayOrigin = ray.origin;
+ m_mouseInteraction.m_mousePick.m_rayDirection = ray.direction;
+ m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPoint;
}
eventType = MouseEvent::Move;
@@ -152,7 +157,7 @@ namespace SandboxEditor
// Only insert the double click timing once we're done processing events, to avoid a false IsDoubleClick positive
if (finishedProcessingEvents)
{
- m_pendingDoubleClicks[mouseButton] = m_curTime;
+ m_pendingDoubleClicks[mouseButton] = { m_currentTime, m_mouseInteraction.m_mousePick.m_screenCoordinates };
}
eventType = MouseEvent::Down;
}
@@ -160,8 +165,8 @@ namespace SandboxEditor
else if (state == InputChannel::State::Ended)
{
// If we've actually logged a mouse down event, forward a mouse up event.
- // This prevents corner cases like the context menu thinking it should be opened even though no one clicked in this viewport,
- // due to RenderViewportWidget ensuring all controllers get InputChannel::State::Ended events.
+ // This prevents corner cases like the context menu thinking it should be opened even though no one clicked in this
+ // viewport, due to RenderViewportWidget ensuring all controllers get InputChannel::State::Ended events.
if (m_mouseInteraction.m_mouseButtons.m_mouseButtons & mouseButtonValue)
{
// Erase the button from our state if we're done processing events.
@@ -246,17 +251,22 @@ namespace SandboxEditor
void ViewportManipulatorControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{
- m_curTime = event.m_time;
+ m_currentTime = event.m_time;
}
bool ViewportManipulatorControllerInstance::IsDoubleClick(AzToolsFramework::ViewportInteraction::MouseButton button) const
{
- auto clickIt = m_pendingDoubleClicks.find(button);
- if (clickIt == m_pendingDoubleClicks.end())
+ if (auto clickIt = m_pendingDoubleClicks.find(button); clickIt != m_pendingDoubleClicks.end())
{
- return false;
+ const double doubleClickThresholdMilliseconds = qApp->doubleClickInterval();
+ const bool insideTimeThreshold =
+ (m_currentTime.GetMilliseconds() - clickIt->second.m_time.GetMilliseconds()) < doubleClickThresholdMilliseconds;
+ const bool insideDistanceThreshold =
+ AzFramework::ScreenVectorLength(clickIt->second.m_position - m_mouseInteraction.m_mousePick.m_screenCoordinates) <
+ AzFramework::DefaultMouseMoveDeadZone;
+ return insideTimeThreshold && insideDistanceThreshold;
}
- const double doubleClickThresholdMilliseconds = qApp->doubleClickInterval();
- return (m_curTime.GetMilliseconds() - clickIt->second.GetMilliseconds()) < doubleClickThresholdMilliseconds;
+
+ return false;
}
-} //namespace SandboxEditor
+} // namespace SandboxEditor
diff --git a/Code/Editor/ViewportManipulatorController.h b/Code/Editor/ViewportManipulatorController.h
index d551eb3647..b9c359a544 100644
--- a/Code/Editor/ViewportManipulatorController.h
+++ b/Code/Editor/ViewportManipulatorController.h
@@ -39,8 +39,16 @@ namespace SandboxEditor
static bool IsMouseMove(const AzFramework::InputChannel& inputChannel);
static AzToolsFramework::ViewportInteraction::KeyboardModifier GetKeyboardModifier(const AzFramework::InputChannel& inputChannel);
+ //! Represents the time and location of a click.
+ struct ClickEvent
+ {
+ AZ::ScriptTimePoint m_time;
+ AzFramework::ScreenPoint m_position;
+ };
+
AzToolsFramework::ViewportInteraction::MouseInteraction m_mouseInteraction;
- AZStd::unordered_map m_pendingDoubleClicks;
- AZ::ScriptTimePoint m_curTime;
+ AZStd::unordered_map m_pendingDoubleClicks;
+
+ AZ::ScriptTimePoint m_currentTime;
};
} // namespace SandboxEditor
diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp
index 75d16e9a40..49459fad0f 100644
--- a/Code/Editor/ViewportTitleDlg.cpp
+++ b/Code/Editor/ViewportTitleDlg.cpp
@@ -138,14 +138,11 @@ CViewportTitleDlg::CViewportTitleDlg(QWidget* pParent)
connect(this, &CViewportTitleDlg::ActionTriggered, MainWindow::instance()->GetActionManager(), &ActionManager::ActionTriggered);
- AZ::VR::VREventBus::Handler::BusConnect();
-
OnInitDialog();
}
CViewportTitleDlg::~CViewportTitleDlg()
{
- AZ::VR::VREventBus::Handler::BusDisconnect();
GetISystem()->GetISystemEventDispatcher()->RemoveListener(this);
GetIEditor()->UnregisterNotifyListener(this);
@@ -236,10 +233,6 @@ void CViewportTitleDlg::SetupOverflowMenu()
connect(m_audioMuteAction, &QAction::triggered, this, &CViewportTitleDlg::OnBnClickedMuteAudio);
overFlowMenu->addAction(m_audioMuteAction);
- m_enableVRAction = new QAction("Enable VR Preview", overFlowMenu);
- connect(m_enableVRAction, &QAction::triggered, this, &CViewportTitleDlg::OnBnClickedEnableVR);
- overFlowMenu->addAction(m_enableVRAction);
-
overFlowMenu->addSeparator();
m_enableGridSnappingAction = new QAction("Enable Grid Snapping", overFlowMenu);
@@ -305,16 +298,6 @@ void CViewportTitleDlg::OnInitDialog()
connect(displayInfoHelper, &CViewportTitleDlgDisplayInfoHelper::ViewportInfoStatusUpdated, this, &CViewportTitleDlg::UpdateDisplayInfo);
UpdateDisplayInfo();
- // This is here just in case this class hasn't been created before
- // a VR headset was initialized
- m_enableVRAction->setEnabled(false);
- if (AZ::VR::HMDDeviceRequestBus::GetTotalNumOfEventHandlers() != 0)
- {
- m_enableVRAction->setEnabled(true);
- }
-
- AZ::VR::VREventBus::Handler::BusConnect();
-
QFontMetrics metrics({});
int width = static_cast(metrics.boundingRect("-9999.99").width() * m_fieldWidthMultiplier);
@@ -931,23 +914,6 @@ void CViewportTitleDlg::UpdateMuteActionText()
}
}
-void CViewportTitleDlg::OnHMDInitialized()
-{
- m_enableVRAction->setEnabled(true);
-}
-
-void CViewportTitleDlg::OnHMDShutdown()
-{
- m_enableVRAction->setEnabled(false);
-}
-
-void CViewportTitleDlg::OnBnClickedEnableVR()
-{
- gSettings.bEnableGameModeVR = !gSettings.bEnableGameModeVR;
-
- m_enableVRAction->setText(gSettings.bEnableGameModeVR ? tr("Disable VR Preview") : tr("Enable VR Preview"));
-}
-
inline double Round(double fVal, double fStep)
{
if (fStep > 0.f)
diff --git a/Code/Editor/ViewportTitleDlg.h b/Code/Editor/ViewportTitleDlg.h
index 6996fe7750..a3e19837b4 100644
--- a/Code/Editor/ViewportTitleDlg.h
+++ b/Code/Editor/ViewportTitleDlg.h
@@ -22,7 +22,6 @@
#include
#include
-#include
#endif
// CViewportTitleDlg dialog
@@ -44,7 +43,6 @@ class CViewportTitleDlg
: public QWidget
, public IEditorNotifyListener
, public ISystemEventListener
- , public AZ::VR::VREventBus::Handler
{
Q_OBJECT
public:
@@ -85,13 +83,6 @@ protected:
void OnToggleHelpers();
void UpdateDisplayInfo();
- //////////////////////////////////////////////////////////////////////////
- /// VR Event Bus Implementation
- //////////////////////////////////////////////////////////////////////////
- void OnHMDInitialized() override;
- void OnHMDShutdown() override;
- //////////////////////////////////////////////////////////////////////////
-
void SetupCameraDropdownMenu();
void SetupResolutionDropdownMenu();
void SetupViewportInformationMenu();
@@ -140,7 +131,6 @@ protected:
void OnBnClickedGotoPosition();
void OnBnClickedMuteAudio();
- void OnBnClickedEnableVR();
void UpdateMuteActionText();
@@ -168,7 +158,6 @@ protected:
QAction* m_fullInformationAction = nullptr;
QAction* m_compactInformationAction = nullptr;
QAction* m_audioMuteAction = nullptr;
- QAction* m_enableVRAction = nullptr;
QAction* m_enableGridSnappingAction = nullptr;
QAction* m_enableAngleSnappingAction = nullptr;
QComboBox* m_cameraSpeed = nullptr;
diff --git a/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp b/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp
index 17f576b5ee..89dfcaffd1 100644
--- a/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp
+++ b/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp
@@ -25,8 +25,6 @@
#include
-// AzFramework
-#include
// AzToolsFramework
#include
@@ -173,9 +171,6 @@ void WelcomeScreenDialog::SetRecentFileList(RecentFileList* pList)
m_pRecentList = pList;
- const char* engineRoot;
- EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
-
auto projectPath = AZ::Utils::GetProjectPath();
QString gamePath{projectPath.c_str()};
Path::ConvertSlashToBackSlash(gamePath);
diff --git a/Code/Framework/AtomCore/Tests/Main.cpp b/Code/Framework/AtomCore/Tests/Main.cpp
index 29ef408551..eb4c6bc835 100644
--- a/Code/Framework/AtomCore/Tests/Main.cpp
+++ b/Code/Framework/AtomCore/Tests/Main.cpp
@@ -7,7 +7,6 @@
*/
-#include
#include
#include
#include
diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetCommon.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetCommon.cpp
index fdc3053b5c..bf3ad20768 100644
--- a/Code/Framework/AzCore/AzCore/Asset/AssetCommon.cpp
+++ b/Code/Framework/AzCore/AzCore/Asset/AssetCommon.cpp
@@ -14,453 +14,450 @@
#include
#include
-namespace AZ
+namespace AZ::Data
{
- namespace Data
+ AssetFilterInfo::AssetFilterInfo(const AssetId& id, const AssetType& assetType, AssetLoadBehavior loadBehavior)
+ : m_assetId(id)
+ , m_assetType(assetType)
+ , m_loadBehavior(loadBehavior)
{
- AssetFilterInfo::AssetFilterInfo(const AssetId& id, const AssetType& assetType, AssetLoadBehavior loadBehavior)
- : m_assetId(id)
- , m_assetType(assetType)
- , m_loadBehavior(loadBehavior)
+ }
+
+ AssetFilterInfo::AssetFilterInfo(const Asset& asset)
+ : m_assetId(asset.GetId())
+ , m_assetType(asset.GetType())
+ , m_loadBehavior(asset.GetAutoLoadBehavior())
+ {
+ }
+
+
+ AssetId AssetId::CreateString(AZStd::string_view input)
+ {
+ size_t separatorIdx = input.find(':');
+ if (separatorIdx == AZStd::string_view::npos)
{
+ return AssetId();
}
- AssetFilterInfo::AssetFilterInfo(const Asset& asset)
- : m_assetId(asset.GetId())
- , m_assetType(asset.GetType())
- , m_loadBehavior(asset.GetAutoLoadBehavior())
+ AssetId assetId;
+ assetId.m_guid = Uuid::CreateString(input.data(), separatorIdx);
+ if (assetId.m_guid.IsNull())
{
+ return AssetId();
}
+ assetId.m_subId = strtoul(&input[separatorIdx + 1], nullptr, 16);
- AssetId AssetId::CreateString(AZStd::string_view input)
+ return assetId;
+ }
+
+ void AssetId::Reflect(AZ::ReflectContext* context)
+ {
+ if (SerializeContext* serializeContext = azrtti_cast(context))
{
- size_t separatorIdx = input.find(':');
- if (separatorIdx == AZStd::string_view::npos)
- {
- return AssetId();
- }
-
- AssetId assetId;
- assetId.m_guid = Uuid::CreateString(input.data(), separatorIdx);
- if (assetId.m_guid.IsNull())
- {
- return AssetId();
- }
-
- assetId.m_subId = strtoul(&input[separatorIdx + 1], nullptr, 16);
-
- return assetId;
+ serializeContext->Class()
+ ->Version(1)
+ ->Field("guid", &Data::AssetId::m_guid)
+ ->Field("subId", &Data::AssetId::m_subId)
+ ;
}
- void AssetId::Reflect(AZ::ReflectContext* context)
+ if (BehaviorContext* behaviorContext = azrtti_cast(context))
{
- if (SerializeContext* serializeContext = azrtti_cast(context))
- {
- serializeContext->Class()
- ->Version(1)
- ->Field("guid", &Data::AssetId::m_guid)
- ->Field("subId", &Data::AssetId::m_subId)
- ;
- }
+ behaviorContext->Class()
+ ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
+ ->Attribute(AZ::Script::Attributes::Category, "Asset")
+ ->Attribute(AZ::Script::Attributes::Module, "asset")
+ ->Constructor()
+ ->Constructor()
+ ->Method("CreateString", &Data::AssetId::CreateString)
+ ->Method("IsValid", &Data::AssetId::IsValid)
+ ->Attribute(AZ::Script::Attributes::Alias, "is_valid")
+ ->Method("ToString", [](const Data::AssetId* self) { return self->ToString(); })
+ ->Attribute(AZ::Script::Attributes::Alias, "to_string")
+ ->Method("IsEqual", [](const Data::AssetId& self, const Data::AssetId& other) { return self == other; })
+ ->Attribute(AZ::Script::Attributes::Alias, "is_equal")
+ ->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
+ ;
- if (BehaviorContext* behaviorContext = azrtti_cast(context))
- {
- behaviorContext->Class()
- ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
- ->Attribute(AZ::Script::Attributes::Category, "Asset")
- ->Attribute(AZ::Script::Attributes::Module, "asset")
- ->Constructor()
- ->Constructor()
- ->Method("CreateString", &Data::AssetId::CreateString)
- ->Method("IsValid", &Data::AssetId::IsValid)
- ->Attribute(AZ::Script::Attributes::Alias, "is_valid")
- ->Method("ToString", [](const Data::AssetId* self) { return self->ToString(); })
- ->Attribute(AZ::Script::Attributes::Alias, "to_string")
- ->Method("IsEqual", [](const Data::AssetId& self, const Data::AssetId& other) { return self == other; })
- ->Attribute(AZ::Script::Attributes::Alias, "is_equal")
- ->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Equal)
- ;
+ behaviorContext->Class()
+ ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
+ ->Attribute(AZ::Script::Attributes::Category, "Asset")
+ ->Attribute(AZ::Script::Attributes::Module, "asset")
+ ->Property("assetId", BehaviorValueGetter(&Data::AssetInfo::m_assetId), nullptr)
+ ->Property("assetType", BehaviorValueGetter(&Data::AssetInfo::m_assetType), nullptr)
+ ->Property("sizeBytes", BehaviorValueGetter(&Data::AssetInfo::m_sizeBytes), nullptr)
+ ->Property("relativePath", BehaviorValueGetter(&Data::AssetInfo::m_relativePath), nullptr)
+ ;
+ }
+ }
- behaviorContext->Class()
- ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
- ->Attribute(AZ::Script::Attributes::Category, "Asset")
- ->Attribute(AZ::Script::Attributes::Module, "asset")
- ->Property("assetId", BehaviorValueGetter(&Data::AssetInfo::m_assetId), nullptr)
- ->Property("assetType", BehaviorValueGetter(&Data::AssetInfo::m_assetType), nullptr)
- ->Property("sizeBytes", BehaviorValueGetter(&Data::AssetInfo::m_sizeBytes), nullptr)
- ->Property("relativePath", BehaviorValueGetter(&Data::AssetInfo::m_relativePath), nullptr)
- ;
- }
+ namespace AssetInternal
+ {
+ Asset FindOrCreateAsset(const AssetId& id, const AssetType& type, AssetLoadBehavior assetReferenceLoadBehavior)
+ {
+ return AssetManager::Instance().FindOrCreateAsset(id, type, assetReferenceLoadBehavior);
}
- namespace AssetInternal
+ Asset GetAsset(const AssetId& id, const AssetType& type, AssetLoadBehavior assetReferenceLoadBehavior,
+ const AssetLoadParameters& loadParams)
{
- Asset FindOrCreateAsset(const AssetId& id, const AssetType& type, AssetLoadBehavior assetReferenceLoadBehavior)
- {
- return AssetManager::Instance().FindOrCreateAsset(id, type, assetReferenceLoadBehavior);
- }
-
- Asset GetAsset(const AssetId& id, const AssetType& type, AssetLoadBehavior assetReferenceLoadBehavior,
- const AssetLoadParameters& loadParams)
- {
- return AssetManager::Instance().GetAsset(id, type, assetReferenceLoadBehavior, loadParams);
- }
-
- AssetData::AssetStatus BlockUntilLoadComplete(const Asset& asset)
- {
- return AssetManager::Instance().BlockUntilLoadComplete(asset);
- }
-
- void UpdateAssetInfo(AssetId& id, AZStd::string& assetHint)
- {
- // it is possible that the assetID given is legacy / old and we have a new assetId we can use instead for it.
- // in that case, upgrade the AssetID to the new one, so that future saves are in the new format.
- // this function should only be invoked if the feature is turned on in the asset manager as it can be (slightly) expensive
-
- if ((!AssetManager::IsReady()) || (!AssetManager::Instance().GetAssetInfoUpgradingEnabled()))
- {
- return;
- }
-
- AZ::Data::AssetInfo assetInfo;
- AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, id);
- if (assetInfo.m_assetId.IsValid())
- {
- id = assetInfo.m_assetId;
- if (!assetInfo.m_relativePath.empty())
- {
- assetHint = assetInfo.m_relativePath;
- }
- }
- }
-
- bool ReloadAsset(AssetData* assetData, AssetLoadBehavior assetReferenceLoadBehavior)
- {
- AssetManager::Instance().ReloadAsset(assetData->GetId(), assetReferenceLoadBehavior);
- return true;
- }
-
- bool SaveAsset(AssetData* assetData, AssetLoadBehavior assetReferenceLoadBehavior)
- {
- AssetManager::Instance().SaveAsset({ assetData, assetReferenceLoadBehavior });
- return true;
- }
-
- Asset GetAssetData(const AssetId& id, AssetLoadBehavior assetReferenceLoadBehavior)
- {
- if (AssetManager::IsReady())
- {
- AZStd::lock_guard assetLock(AssetManager::Instance().m_assetMutex);
- auto it = AssetManager::Instance().m_assets.find(id);
- if (it != AssetManager::Instance().m_assets.end())
- {
- return { it->second, assetReferenceLoadBehavior };
- }
- }
- return {};
- }
-
- AssetId ResolveAssetId(const AssetId& id)
- {
- AZ::Data::AssetInfo assetInfo;
- AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, id);
- if (assetInfo.m_assetId.IsValid())
- {
- return assetInfo.m_assetId;
- }
- else
- {
- return id;
- }
-
- }
+ return AssetManager::Instance().GetAsset(id, type, assetReferenceLoadBehavior, loadParams);
}
- AssetData::~AssetData()
+ AssetData::AssetStatus BlockUntilLoadComplete(const Asset& asset)
{
- UnregisterWithHandler();
+ return AssetManager::Instance().BlockUntilLoadComplete(asset);
}
- void AssetData::Reflect(AZ::ReflectContext* context)
+ void UpdateAssetInfo(AssetId& id, AZStd::string& assetHint)
{
- if (SerializeContext* serializeContext = azrtti_cast(context))
+ // it is possible that the assetID given is legacy / old and we have a new assetId we can use instead for it.
+ // in that case, upgrade the AssetID to the new one, so that future saves are in the new format.
+ // this function should only be invoked if the feature is turned on in the asset manager as it can be (slightly) expensive
+
+ if ((!AssetManager::IsReady()) || (!AssetManager::Instance().GetAssetInfoUpgradingEnabled()))
{
- serializeContext->Class()
- ->Version(1)
- ;
- }
-
- if (BehaviorContext* behaviorContext = azrtti_cast(context))
- {
- behaviorContext->Class("AssetData")
- ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
- ->Attribute(AZ::Script::Attributes::Category, "Asset")
- ->Attribute(AZ::Script::Attributes::Module, "asset")
- ->Method("IsReady", &AssetData::IsReady)
- ->Attribute(AZ::Script::Attributes::Alias, "is_ready")
- ->Method("IsError", &AssetData::IsError)
- ->Attribute(AZ::Script::Attributes::Alias, "is_error")
- ->Method("IsLoading", &AssetData::IsLoading)
- ->Attribute(AZ::Script::Attributes::Alias, "is_loading")
- ->Method("GetId", &AssetData::GetId)
- ->Attribute(AZ::Script::Attributes::Alias, "get_id")
- ->Method("GetUseCount", &AssetData::GetUseCount)
- ->Attribute(AZ::Script::Attributes::Alias, "get_use_count")
- ;
- }
- }
-
- void AssetData::Acquire()
- {
- AZ_Assert(m_useCount >= 0, "AssetData has been deleted");
-
- AcquireWeak();
- ++m_useCount;
- }
-
- void AssetData::Release()
- {
- AZ_Assert(m_useCount > 0, "Usecount is already 0!");
-
- if (m_useCount.fetch_sub(1) == 1)
- {
- if (AssetManager::IsReady())
- {
- AssetManager::Instance().OnAssetUnused(this);
- }
- else
- {
- AZ_Assert(false, "Attempting to release asset after AssetManager has been destroyed!");
- }
- }
-
- ReleaseWeak();
- }
-
- void AssetData::AcquireWeak()
- {
- AZ_Assert(m_useCount >= 0, "AssetData has been deleted");
- ++m_weakUseCount;
- }
-
- void AssetData::ReleaseWeak()
- {
- AZ_Assert(m_weakUseCount > 0, "WeakUseCount is already 0");
-
- AssetId assetId = m_assetId;
- int creationToken = m_creationToken;
- AssetType assetType = GetType();
- bool removeFromHash = IsRegisterReadonlyAndShareable();
- // default creation token implies that the asset was not created by the asset manager and therefore it cannot be in the asset map.
- removeFromHash = creationToken == s_defaultCreationToken ? false : removeFromHash;
-
- if (m_weakUseCount.fetch_sub(1) == 1)
- {
- if (AssetManager::IsReady())
- {
- AssetManager::Instance().ReleaseAsset(this, assetId, assetType, removeFromHash, creationToken);
- }
- else
- {
- AZ_Assert(false, "Attempting to release asset after AssetManager has been destroyed!");
- }
- }
- }
-
- bool AssetData::IsLoading(bool includeQueued) const
- {
- auto curStatus = GetStatus();
- return(curStatus == AssetStatus::Loading || curStatus == AssetStatus::LoadedPreReady || curStatus==AssetStatus::StreamReady ||
- (includeQueued && curStatus == AssetStatus::Queued));
- }
-
- void AssetData::RegisterWithHandler(AssetHandler* handler)
- {
- if (!handler)
- {
- AZ_Error("AssetData", false, "No handler to register with");
return;
}
- m_registeredHandler = handler;
- }
- void AssetData::UnregisterWithHandler()
- {
- if (m_registeredHandler)
+ AZ::Data::AssetInfo assetInfo;
+ AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, id);
+ if (assetInfo.m_assetId.IsValid())
{
- m_registeredHandler = nullptr;
- }
- }
-
- bool AssetData::GetFlag(const AssetDataFlags& checkFlag) const
- {
- return m_flags[aznumeric_cast(checkFlag)];
- }
-
- void AssetData::SetFlag(const AssetDataFlags& checkFlag, bool setValue)
- {
- m_flags.set(aznumeric_cast(checkFlag), setValue);
- }
-
- bool AssetData::GetRequeue() const
- {
- return GetFlag(AssetDataFlags::Requeue);
- }
- void AssetData::SetRequeue(bool requeue)
- {
- SetFlag(AssetDataFlags::Requeue, requeue);
- }
-
- void AssetBusCallbacks::SetCallbacks(const AssetReadyCB& readyCB, const AssetMovedCB& movedCB, const AssetReloadedCB& reloadedCB,
- const AssetSavedCB& savedCB, const AssetUnloadedCB& unloadedCB, const AssetErrorCB& errorCB, const AssetCanceledCB& cancelCB)
- {
- m_onAssetReadyCB = readyCB;
- m_onAssetMovedCB = movedCB;
- m_onAssetReloadedCB = reloadedCB;
- m_onAssetSavedCB = savedCB;
- m_onAssetUnloadedCB = unloadedCB;
- m_onAssetErrorCB = errorCB;
- m_onAssetCanceledCB = cancelCB;
- }
-
- void AssetBusCallbacks::ClearCallbacks()
- {
- SetCallbacks(AssetBusCallbacks::AssetReadyCB(),
- AssetBusCallbacks::AssetMovedCB(),
- AssetBusCallbacks::AssetReloadedCB(),
- AssetBusCallbacks::AssetSavedCB(),
- AssetBusCallbacks::AssetUnloadedCB(),
- AssetBusCallbacks::AssetErrorCB(),
- AssetBusCallbacks::AssetCanceledCB());
- }
-
-
- void AssetBusCallbacks::SetOnAssetReadyCallback(const AssetReadyCB& readyCB)
- {
- m_onAssetReadyCB = readyCB;
- }
-
- void AssetBusCallbacks::SetOnAssetMovedCallback(const AssetMovedCB& movedCB)
- {
- m_onAssetMovedCB = movedCB;
- }
-
- void AssetBusCallbacks::SetOnAssetReloadedCallback(const AssetReloadedCB& reloadedCB)
- {
- m_onAssetReloadedCB = reloadedCB;
- }
-
- void AssetBusCallbacks::SetOnAssetSavedCallback(const AssetSavedCB& savedCB)
- {
- m_onAssetSavedCB = savedCB;
- }
-
- void AssetBusCallbacks::SetOnAssetUnloadedCallback(const AssetUnloadedCB& unloadedCB)
- {
- m_onAssetUnloadedCB = unloadedCB;
- }
-
- void AssetBusCallbacks::SetOnAssetErrorCallback(const AssetErrorCB& errorCB)
- {
- m_onAssetErrorCB = errorCB;
- }
-
- void AssetBusCallbacks::SetOnAssetCanceledCallback(const AssetCanceledCB& cancelCB)
- {
- m_onAssetCanceledCB = cancelCB;
- }
-
- void AssetBusCallbacks::OnAssetReady(Asset asset)
- {
- if (m_onAssetReadyCB)
- {
- m_onAssetReadyCB(asset, *this);
- }
- }
-
- void AssetBusCallbacks::OnAssetMoved(Asset asset, void* oldDataPointer)
- {
- if (m_onAssetMovedCB)
- {
- m_onAssetMovedCB(asset, oldDataPointer, *this);
- }
- }
-
- void AssetBusCallbacks::OnAssetReloaded(Asset asset)
- {
- if (m_onAssetReloadedCB)
- {
- m_onAssetReloadedCB(asset, *this);
- }
- }
-
- void AssetBusCallbacks::OnAssetSaved(Asset asset, bool isSuccessful)
- {
- if (m_onAssetSavedCB)
- {
- m_onAssetSavedCB(asset, isSuccessful, *this);
- }
- }
-
- void AssetBusCallbacks::OnAssetUnloaded(const AssetId assetId, const AssetType assetType)
- {
- if (m_onAssetUnloadedCB)
- {
- m_onAssetUnloadedCB(assetId, assetType, *this);
- }
- }
-
- void AssetBusCallbacks::OnAssetError(Asset asset)
- {
- if (m_onAssetErrorCB)
- {
- m_onAssetErrorCB(asset, *this);
- }
- }
-
- void AssetBusCallbacks::OnAssetCanceled(const AssetId assetId)
- {
- if (m_onAssetCanceledCB)
- {
- m_onAssetCanceledCB(assetId, *this);
- }
- }
-
- /*static*/ bool AssetFilterNoAssetLoading([[maybe_unused]] const AssetFilterInfo& filterInfo)
- {
- return false;
- }
- namespace ProductDependencyInfo
- {
- AZ::Data::AssetLoadBehavior LoadBehaviorFromFlags(const ProductDependencyFlags& dependencyFlags)
- {
- AZ::u8 loadBehaviorValue = 0;
- for (AZ::u8 thisFlag = aznumeric_cast(ProductDependencyFlagBits::LoadBehaviorLow);
- thisFlag <= aznumeric_cast(ProductDependencyFlagBits::LoadBehaviorHigh); ++thisFlag)
+ id = assetInfo.m_assetId;
+ if (!assetInfo.m_relativePath.empty())
{
- if (dependencyFlags[thisFlag])
- {
- loadBehaviorValue |= (1 << thisFlag);
- }
+ assetHint = assetInfo.m_relativePath;
}
- return static_cast(loadBehaviorValue);
- }
-
- ProductDependencyFlags CreateFlags(AZ::Data::AssetLoadBehavior autoLoadBehavior)
- {
- AZ::Data::ProductDependencyInfo::ProductDependencyFlags returnFlags;
- AZ::u8 loadBehavior = aznumeric_caster(autoLoadBehavior);
- for (AZ::u8 thisFlag = aznumeric_cast(ProductDependencyFlagBits::LoadBehaviorLow);
- thisFlag <= aznumeric_cast(ProductDependencyFlagBits::LoadBehaviorHigh); ++thisFlag)
- {
- if (loadBehavior & (1 << thisFlag))
- {
- returnFlags[thisFlag] = true;
- }
- }
- return returnFlags;
}
}
- } // namespace Data
-} // namespace AZ
+
+ bool ReloadAsset(AssetData* assetData, AssetLoadBehavior assetReferenceLoadBehavior)
+ {
+ AssetManager::Instance().ReloadAsset(assetData->GetId(), assetReferenceLoadBehavior);
+ return true;
+ }
+
+ bool SaveAsset(AssetData* assetData, AssetLoadBehavior assetReferenceLoadBehavior)
+ {
+ AssetManager::Instance().SaveAsset({ assetData, assetReferenceLoadBehavior });
+ return true;
+ }
+
+ Asset GetAssetData(const AssetId& id, AssetLoadBehavior assetReferenceLoadBehavior)
+ {
+ if (AssetManager::IsReady())
+ {
+ AZStd::lock_guard assetLock(AssetManager::Instance().m_assetMutex);
+ auto it = AssetManager::Instance().m_assets.find(id);
+ if (it != AssetManager::Instance().m_assets.end())
+ {
+ return { it->second, assetReferenceLoadBehavior };
+ }
+ }
+ return {};
+ }
+
+ AssetId ResolveAssetId(const AssetId& id)
+ {
+ AZ::Data::AssetInfo assetInfo;
+ AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, id);
+ if (assetInfo.m_assetId.IsValid())
+ {
+ return assetInfo.m_assetId;
+ }
+ else
+ {
+ return id;
+ }
+
+ }
+ }
+
+ AssetData::~AssetData()
+ {
+ UnregisterWithHandler();
+ }
+
+ void AssetData::Reflect(AZ::ReflectContext* context)
+ {
+ if (SerializeContext* serializeContext = azrtti_cast(context))
+ {
+ serializeContext->Class()
+ ->Version(1)
+ ;
+ }
+
+ if (BehaviorContext* behaviorContext = azrtti_cast(context))
+ {
+ behaviorContext->Class("AssetData")
+ ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
+ ->Attribute(AZ::Script::Attributes::Category, "Asset")
+ ->Attribute(AZ::Script::Attributes::Module, "asset")
+ ->Method("IsReady", &AssetData::IsReady)
+ ->Attribute(AZ::Script::Attributes::Alias, "is_ready")
+ ->Method("IsError", &AssetData::IsError)
+ ->Attribute(AZ::Script::Attributes::Alias, "is_error")
+ ->Method("IsLoading", &AssetData::IsLoading)
+ ->Attribute(AZ::Script::Attributes::Alias, "is_loading")
+ ->Method("GetId", &AssetData::GetId)
+ ->Attribute(AZ::Script::Attributes::Alias, "get_id")
+ ->Method("GetUseCount", &AssetData::GetUseCount)
+ ->Attribute(AZ::Script::Attributes::Alias, "get_use_count")
+ ;
+ }
+ }
+
+ void AssetData::Acquire()
+ {
+ AZ_Assert(m_useCount >= 0, "AssetData has been deleted");
+
+ AcquireWeak();
+ ++m_useCount;
+ }
+
+ void AssetData::Release()
+ {
+ AZ_Assert(m_useCount > 0, "Usecount is already 0!");
+
+ if (m_useCount.fetch_sub(1) == 1)
+ {
+ if (AssetManager::IsReady())
+ {
+ AssetManager::Instance().OnAssetUnused(this);
+ }
+ else
+ {
+ AZ_Assert(false, "Attempting to release asset after AssetManager has been destroyed!");
+ }
+ }
+
+ ReleaseWeak();
+ }
+
+ void AssetData::AcquireWeak()
+ {
+ AZ_Assert(m_useCount >= 0, "AssetData has been deleted");
+ ++m_weakUseCount;
+ }
+
+ void AssetData::ReleaseWeak()
+ {
+ AZ_Assert(m_weakUseCount > 0, "WeakUseCount is already 0");
+
+ AssetId assetId = m_assetId;
+ int creationToken = m_creationToken;
+ AssetType assetType = GetType();
+ bool removeFromHash = IsRegisterReadonlyAndShareable();
+ // default creation token implies that the asset was not created by the asset manager and therefore it cannot be in the asset map.
+ removeFromHash = creationToken == s_defaultCreationToken ? false : removeFromHash;
+
+ if (m_weakUseCount.fetch_sub(1) == 1)
+ {
+ if (AssetManager::IsReady())
+ {
+ AssetManager::Instance().ReleaseAsset(this, assetId, assetType, removeFromHash, creationToken);
+ }
+ else
+ {
+ AZ_Assert(false, "Attempting to release asset after AssetManager has been destroyed!");
+ }
+ }
+ }
+
+ bool AssetData::IsLoading(bool includeQueued) const
+ {
+ auto curStatus = GetStatus();
+ return(curStatus == AssetStatus::Loading || curStatus == AssetStatus::LoadedPreReady || curStatus==AssetStatus::StreamReady ||
+ (includeQueued && curStatus == AssetStatus::Queued));
+ }
+
+ void AssetData::RegisterWithHandler(AssetHandler* handler)
+ {
+ if (!handler)
+ {
+ AZ_Error("AssetData", false, "No handler to register with");
+ return;
+ }
+ m_registeredHandler = handler;
+ }
+
+ void AssetData::UnregisterWithHandler()
+ {
+ if (m_registeredHandler)
+ {
+ m_registeredHandler = nullptr;
+ }
+ }
+
+ bool AssetData::GetFlag(const AssetDataFlags& checkFlag) const
+ {
+ return m_flags[aznumeric_cast(checkFlag)];
+ }
+
+ void AssetData::SetFlag(const AssetDataFlags& checkFlag, bool setValue)
+ {
+ m_flags.set(aznumeric_cast(checkFlag), setValue);
+ }
+
+ bool AssetData::GetRequeue() const
+ {
+ return GetFlag(AssetDataFlags::Requeue);
+ }
+ void AssetData::SetRequeue(bool requeue)
+ {
+ SetFlag(AssetDataFlags::Requeue, requeue);
+ }
+
+ void AssetBusCallbacks::SetCallbacks(const AssetReadyCB& readyCB, const AssetMovedCB& movedCB, const AssetReloadedCB& reloadedCB,
+ const AssetSavedCB& savedCB, const AssetUnloadedCB& unloadedCB, const AssetErrorCB& errorCB, const AssetCanceledCB& cancelCB)
+ {
+ m_onAssetReadyCB = readyCB;
+ m_onAssetMovedCB = movedCB;
+ m_onAssetReloadedCB = reloadedCB;
+ m_onAssetSavedCB = savedCB;
+ m_onAssetUnloadedCB = unloadedCB;
+ m_onAssetErrorCB = errorCB;
+ m_onAssetCanceledCB = cancelCB;
+ }
+
+ void AssetBusCallbacks::ClearCallbacks()
+ {
+ SetCallbacks(AssetBusCallbacks::AssetReadyCB(),
+ AssetBusCallbacks::AssetMovedCB(),
+ AssetBusCallbacks::AssetReloadedCB(),
+ AssetBusCallbacks::AssetSavedCB(),
+ AssetBusCallbacks::AssetUnloadedCB(),
+ AssetBusCallbacks::AssetErrorCB(),
+ AssetBusCallbacks::AssetCanceledCB());
+ }
+
+
+ void AssetBusCallbacks::SetOnAssetReadyCallback(const AssetReadyCB& readyCB)
+ {
+ m_onAssetReadyCB = readyCB;
+ }
+
+ void AssetBusCallbacks::SetOnAssetMovedCallback(const AssetMovedCB& movedCB)
+ {
+ m_onAssetMovedCB = movedCB;
+ }
+
+ void AssetBusCallbacks::SetOnAssetReloadedCallback(const AssetReloadedCB& reloadedCB)
+ {
+ m_onAssetReloadedCB = reloadedCB;
+ }
+
+ void AssetBusCallbacks::SetOnAssetSavedCallback(const AssetSavedCB& savedCB)
+ {
+ m_onAssetSavedCB = savedCB;
+ }
+
+ void AssetBusCallbacks::SetOnAssetUnloadedCallback(const AssetUnloadedCB& unloadedCB)
+ {
+ m_onAssetUnloadedCB = unloadedCB;
+ }
+
+ void AssetBusCallbacks::SetOnAssetErrorCallback(const AssetErrorCB& errorCB)
+ {
+ m_onAssetErrorCB = errorCB;
+ }
+
+ void AssetBusCallbacks::SetOnAssetCanceledCallback(const AssetCanceledCB& cancelCB)
+ {
+ m_onAssetCanceledCB = cancelCB;
+ }
+
+ void AssetBusCallbacks::OnAssetReady(Asset asset)
+ {
+ if (m_onAssetReadyCB)
+ {
+ m_onAssetReadyCB(asset, *this);
+ }
+ }
+
+ void AssetBusCallbacks::OnAssetMoved(Asset asset, void* oldDataPointer)
+ {
+ if (m_onAssetMovedCB)
+ {
+ m_onAssetMovedCB(asset, oldDataPointer, *this);
+ }
+ }
+
+ void AssetBusCallbacks::OnAssetReloaded(Asset asset)
+ {
+ if (m_onAssetReloadedCB)
+ {
+ m_onAssetReloadedCB(asset, *this);
+ }
+ }
+
+ void AssetBusCallbacks::OnAssetSaved(Asset asset, bool isSuccessful)
+ {
+ if (m_onAssetSavedCB)
+ {
+ m_onAssetSavedCB(asset, isSuccessful, *this);
+ }
+ }
+
+ void AssetBusCallbacks::OnAssetUnloaded(const AssetId assetId, const AssetType assetType)
+ {
+ if (m_onAssetUnloadedCB)
+ {
+ m_onAssetUnloadedCB(assetId, assetType, *this);
+ }
+ }
+
+ void AssetBusCallbacks::OnAssetError(Asset asset)
+ {
+ if (m_onAssetErrorCB)
+ {
+ m_onAssetErrorCB(asset, *this);
+ }
+ }
+
+ void AssetBusCallbacks::OnAssetCanceled(const AssetId assetId)
+ {
+ if (m_onAssetCanceledCB)
+ {
+ m_onAssetCanceledCB(assetId, *this);
+ }
+ }
+
+ /*static*/ bool AssetFilterNoAssetLoading([[maybe_unused]] const AssetFilterInfo& filterInfo)
+ {
+ return false;
+ }
+ namespace ProductDependencyInfo
+ {
+ AZ::Data::AssetLoadBehavior LoadBehaviorFromFlags(const ProductDependencyFlags& dependencyFlags)
+ {
+ AZ::u8 loadBehaviorValue = 0;
+ for (AZ::u8 thisFlag = aznumeric_cast(ProductDependencyFlagBits::LoadBehaviorLow);
+ thisFlag <= aznumeric_cast(ProductDependencyFlagBits::LoadBehaviorHigh); ++thisFlag)
+ {
+ if (dependencyFlags[thisFlag])
+ {
+ loadBehaviorValue |= (1 << thisFlag);
+ }
+ }
+ return static_cast(loadBehaviorValue);
+ }
+
+ ProductDependencyFlags CreateFlags(AZ::Data::AssetLoadBehavior autoLoadBehavior)
+ {
+ AZ::Data::ProductDependencyInfo::ProductDependencyFlags returnFlags;
+ AZ::u8 loadBehavior = aznumeric_caster(autoLoadBehavior);
+ for (AZ::u8 thisFlag = aznumeric_cast(ProductDependencyFlagBits::LoadBehaviorLow);
+ thisFlag <= aznumeric_cast(ProductDependencyFlagBits::LoadBehaviorHigh); ++thisFlag)
+ {
+ if (loadBehavior & (1 << thisFlag))
+ {
+ returnFlags[thisFlag] = true;
+ }
+ }
+ return returnFlags;
+ }
+ }
+} // namespace AZ::Data
diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetCommon.h b/Code/Framework/AzCore/AzCore/Asset/AssetCommon.h
index 0c8e5209ca..c45bb21c6d 100644
--- a/Code/Framework/AzCore/AzCore/Asset/AssetCommon.h
+++ b/Code/Framework/AzCore/AzCore/Asset/AssetCommon.h
@@ -556,16 +556,24 @@ namespace AZ
Asset assetData(AssetInternal::GetAssetData(actualId, AZ::Data::AssetLoadBehavior::Default));
if (assetData)
{
- auto curStatus = assetData->GetStatus();
+ auto isReady = assetData->GetStatus() == AssetData::AssetStatus::Ready;
bool isError = assetData->IsError();
- connectLock.unlock();
- if (curStatus == AssetData::AssetStatus::Ready)
+
+ if (isReady || isError)
{
- handler->OnAssetReady(assetData);
- }
- else if (isError)
- {
- handler->OnAssetError(assetData);
+ connectLock.unlock();
+
+ if (isReady)
+ {
+ handler->OnAssetReady(assetData);
+ }
+ else if (isError)
+ {
+ handler->OnAssetError(assetData);
+ }
+
+ // Lock the mutex again since some destructors will be modifying the context afterwards
+ connectLock.lock();
}
}
}
diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp
index ce15c7bc4e..bab161fc0a 100644
--- a/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp
+++ b/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp
@@ -11,466 +11,469 @@
#include
#include
-namespace AZ
+namespace AZ::Data
{
- namespace Data
+ AssetContainer::AssetContainer(Asset rootAsset, const AssetLoadParameters& loadParams)
{
- AssetContainer::AssetContainer(Asset rootAsset, const AssetLoadParameters& loadParams)
- {
- m_rootAsset = AssetInternal::WeakAsset(rootAsset);
- m_containerAssetId = m_rootAsset.GetId();
+ m_rootAsset = AssetInternal::WeakAsset(rootAsset);
+ m_containerAssetId = m_rootAsset.GetId();
- AddDependentAssets(rootAsset, loadParams);
+ AddDependentAssets(rootAsset, loadParams);
+ }
+
+ AssetContainer::~AssetContainer()
+ {
+ // Validate that if the AssetManager is performing normal processing duties, the AssetContainer is only destroyed once all
+ // dependent asset loads have completed.
+ if (AssetManager::IsReady() && !AssetManager::Instance().ShouldCancelAllActiveJobs())
+ {
+ AZ_Assert(m_waitingCount == 0, "Container destroyed while dependent assets are still loading. The dependent assets may "
+ "end up in a perpetual loading state if there is no top-level container signalling the completion of the full load.");
}
- AssetContainer::~AssetContainer()
- {
- // Validate that if the AssetManager is performing normal processing duties, the AssetContainer is only destroyed once all
- // dependent asset loads have completed.
- if (AssetManager::IsReady() && !AssetManager::Instance().ShouldCancelAllActiveJobs())
- {
- AZ_Assert(m_waitingCount == 0, "Container destroyed while dependent assets are still loading. The dependent assets may "
- "end up in a perpetual loading state if there is no top-level container signalling the completion of the full load.");
- }
+ AssetBus::MultiHandler::BusDisconnect();
+ AssetLoadBus::MultiHandler::BusDisconnect();
+ }
- AssetBus::MultiHandler::BusDisconnect();
- AssetLoadBus::MultiHandler::BusDisconnect();
+ AZStd::vector>> AssetContainer::CreateAndQueueDependentAssets(
+ const AZStd::vector& dependencyInfoList, const AssetLoadParameters& loadParamsCopyWithNoLoadingFilter)
+ {
+ AZStd::vector>> dependencyAssets;
+
+ for (auto& thisInfo : dependencyInfoList)
+ {
+ auto dependentAsset = AssetManager::Instance().FindOrCreateAsset(
+ thisInfo.m_assetId, thisInfo.m_assetType, AZ::Data::AssetLoadBehavior::Default);
+
+ if (!dependentAsset || !dependentAsset.GetId().IsValid())
+ {
+ AZ_Warning("AssetContainer", false, "Dependency Asset %s (%s) was not found\n",
+ thisInfo.m_assetId.ToString().c_str(), thisInfo.m_relativePath.c_str());
+ RemoveWaitingAsset(thisInfo.m_assetId);
+ continue;
+ }
+ dependencyAssets.emplace_back(thisInfo, AZStd::move(dependentAsset));
}
- void AssetContainer::AddDependentAssets(Asset rootAsset, const AssetLoadParameters& loadParams)
+ // Queue the loading of all of the dependent assets before loading the root asset.
+ for (auto& [dependentAssetInfo, dependentAsset] : dependencyAssets)
{
- AssetId rootAssetId = rootAsset.GetId();
- AssetType rootAssetType = rootAsset.GetType();
+ // Queue each asset to load.
+ auto queuedDependentAsset = AssetManager::Instance().GetAssetInternal(
+ dependentAsset.GetId(), dependentAsset.GetType(),
+ AZ::Data::AssetLoadBehavior::Default, loadParamsCopyWithNoLoadingFilter,
+ dependentAssetInfo, HasPreloads(dependentAsset.GetId()));
- // Every asset we're going to be waiting on a load for - the root and all valid dependencies
- AZStd::vector waitingList;
- waitingList.push_back(rootAssetId);
+ // Verify that the returned asset reference matches the one that we found or created and queued to load.
+ AZ_Assert(dependentAsset == queuedDependentAsset, "GetAssetInternal returned an unexpected asset reference for Asset %s",
+ dependentAsset.GetId().ToString().c_str());
+ }
- // Every asset dependency that we're aware of, whether or not it gets filtered out by the asset filter callback.
- // This will be used at the point that asset references get serialized in to see whether or not we've received any
- // unexpected assets that didn't appear in our asset catalog dependency list that need to be loaded anyways.
- AZStd::vector handledAssetDependencyList;
+ return dependencyAssets;
+ }
- // Cached AssetInfo to save another lookup inside Assetmanager
- AZStd::vector