Merge branch 'stabilization/2110' of https://github.com/aws-lumberyard-dev/o3de into scripting/4060

monroegm-disable-blank-issue-2
lsemp3d 4 years ago
commit 6c25e08d3f

@ -31,7 +31,7 @@ def Terrain_SupportsPhysics():
Test Steps: Test Steps:
1) Load the base level 1) Load the base level
2) Create 2 test entities, one parent at 512.0, 512.0, 50.0 and one child at the default position and add the required components 2) Create 2 test entities, one parent at 512.0, 512.0, 50.0 and one child at the default position and add the required components
2a) Create a ball at 600.0, 600.0, 46.0 - This position is bot too high over the heighfield so will collide in a reasonable time 2a) Create a ball at 600.0, 600.0, 46.0 - This position is not too high over the heightfield so will collide in a reasonable time
3) Start the Tracer to catch any errors and warnings 3) Start the Tracer to catch any errors and warnings
4) Change the Axis Aligned Box Shape dimensions 4) Change the Axis Aligned Box Shape dimensions
5) Set the Vegetation Shape reference to TestEntity1 5) Set the Vegetation Shape reference to TestEntity1
@ -80,7 +80,7 @@ def Terrain_SupportsPhysics():
height_provider_entity = hydra.Entity("TestEntity2") height_provider_entity = hydra.Entity("TestEntity2")
height_provider_entity.create_entity(azmath.Vector3(0.0, 0.0, 0.0), entity2_components_to_add,terrain_spawner_entity.id) height_provider_entity.create_entity(azmath.Vector3(0.0, 0.0, 0.0), entity2_components_to_add,terrain_spawner_entity.id)
Report.result(Tests.create_height_provider_entity, height_provider_entity.id.IsValid()) Report.result(Tests.create_height_provider_entity, height_provider_entity.id.IsValid())
# 2a) Create a ball at 600.0, 600.0, 46.0 - This position is bot too high over the heighfield so will collide in a reasonable time # 2a) Create a ball at 600.0, 600.0, 46.0 - This position is not too high over the heightfield so will collide in a reasonable time
ball = hydra.Entity("Ball") ball = hydra.Entity("Ball")
ball.create_entity(azmath.Vector3(600.0, 600.0, 46.0), ball_components_to_add) ball.create_entity(azmath.Vector3(600.0, 600.0, 46.0), ball_components_to_add)
Report.result(Tests.create_test_ball, ball.id.IsValid()) Report.result(Tests.create_test_ball, ball.id.IsValid())
@ -107,9 +107,9 @@ def Terrain_SupportsPhysics():
Report.result(Tests.frequency_changed, math.isclose(Frequency, FrequencyVal, abs_tol = 0.00001)) Report.result(Tests.frequency_changed, math.isclose(Frequency, FrequencyVal, abs_tol = 0.00001))
# 7) Set the Gradient List to TestEntity2 # 7) Set the Gradient List to TestEntity2
pte = hydra.get_property_tree(terrain_spawner_entity.components[2]) propertyTree = hydra.get_property_tree(terrain_spawner_entity.components[2])
pte.add_container_item("Configuration|Gradient Entities", 0, height_provider_entity.id) propertyTree.add_container_item("Configuration|Gradient Entities", 0, height_provider_entity.id)
checkID = pte.get_container_item("Configuration|Gradient Entities", 0) checkID = propertyTree.get_container_item("Configuration|Gradient Entities", 0)
Report.result(Tests.entity_added, checkID.GetValue() == height_provider_entity.id) Report.result(Tests.entity_added, checkID.GetValue() == height_provider_entity.id)
# 8) Set the PhysX Collider to Sphere mode # 8) Set the PhysX Collider to Sphere mode

@ -13,15 +13,15 @@ import os
import sys import sys
from ly_test_tools import LAUNCHERS from ly_test_tools import LAUNCHERS
from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSingleTest from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSharedTest
@pytest.mark.SUITE_main @pytest.mark.SUITE_main
@pytest.mark.parametrize("launcher_platform", ['windows_editor']) @pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"]) @pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(EditorTestSuite): class TestAutomation(EditorTestSuite):
class test_AxisAlignedBoxShape_ConfigurationWorks(EditorSingleTest): class test_AxisAlignedBoxShape_ConfigurationWorks(EditorSharedTest):
from .EditorScripts import TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges as test_module from .EditorScripts import TerrainPhysicsCollider_ChangesSizeWithAxisAlignedBoxShapeChanges as test_module
class test_Terrain_SupportsPhysics(EditorSingleTest): class test_Terrain_SupportsPhysics(EditorSharedTest):
from .EditorScripts import Terrain_SupportsPhysics as test_module from .EditorScripts import Terrain_SupportsPhysics as test_module

@ -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()) if (GetIEditor()->IsInGameMode())
{ {
@ -246,9 +246,6 @@ void Q2DViewport::OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& p
setFocus(); setFocus();
} }
// Check Edit Tool.
MouseCallback(eMouseRDown, point, modifiers);
SetCurrentCursor(STD_CURSOR_MOVE, QString()); SetCurrentCursor(STD_CURSOR_MOVE, QString());
// Save the mouse down position // 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 // Save the mouse down position
m_RMouseDownPos = point; 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); SetViewMode(NothingMode);
ReleaseMouse(); ReleaseMouse();

@ -2307,10 +2307,10 @@ void* EditorViewportWidget::GetSystemCursorConstraintWindow() const
return systemCursorConstrained ? renderOverlayHWND() : nullptr; 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, viewportId, point);
QtViewport::BuildDragDropContext(context, scaledPoint);
} }
void EditorViewportWidget::RestoreViewportAfterGameMode() void EditorViewportWidget::RestoreViewportAfterGameMode()

@ -273,7 +273,8 @@ private:
bool CheckRespondToInput() const; 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 SetAsActiveViewport();
void PushDisableRendering(); void PushDisableRendering();

@ -10,7 +10,6 @@
#include <AzCore/Component/ComponentApplicationBus.h> #include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/Entity.h> #include <AzCore/Component/Entity.h>
#include <AzCore/Component/TransformBus.h> #include <AzCore/Component/TransformBus.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/Debug/Profiler.h> #include <AzCore/Debug/Profiler.h>
#include <AzCore/Math/Transform.h> #include <AzCore/Math/Transform.h>
#include <AzCore/RTTI/AttributeReader.h> #include <AzCore/RTTI/AttributeReader.h>
@ -57,6 +56,7 @@
#include <AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx> #include <AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx>
#include <AzToolsFramework/UI/Layer/NameConflictWarning.hxx> #include <AzToolsFramework/UI/Layer/NameConflictWarning.hxx>
#include <AzToolsFramework/ViewportSelection/EditorHelpers.h> #include <AzToolsFramework/ViewportSelection/EditorHelpers.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <MathConversion.h> #include <MathConversion.h>
#include <Atom/RPI.Public/ViewportContext.h> #include <Atom/RPI.Public/ViewportContext.h>
@ -1394,13 +1394,13 @@ void SandboxIntegrationManager::ContextMenu_NewEntity()
{ {
AZ::Vector3 worldPosition = AZ::Vector3::CreateZero(); 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 // If we don't have a viewport active to aid in placement, the object
// will be created at the origin. // will be created at the origin.
if (view) if (CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport())
{ {
const QPoint viewPoint(static_cast<int>(m_contextMenuViewPoint.GetX()), static_cast<int>(m_contextMenuViewPoint.GetY())); worldPosition = AzToolsFramework::FindClosestPickIntersection(
worldPosition = view->GetHitLocation(viewPoint); view->GetViewportId(), AzFramework::ScreenPointFromVector2(m_contextMenuViewPoint), AzToolsFramework::EditorPickRayLength,
GetDefaultEntityPlacementDistance());
} }
CreateNewEntityAtPosition(worldPosition); CreateNewEntityAtPosition(worldPosition);

@ -14,14 +14,19 @@
// Qt // Qt
#include <QPainter> #include <QPainter>
// AzCore
#include <AzCore/Console/IConsole.h>
// AzQtComponents // AzQtComponents
#include <AzQtComponents/DragAndDrop/ViewportDragAndDrop.h> #include <AzQtComponents/DragAndDrop/ViewportDragAndDrop.h>
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h> #include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h> #include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h> #include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
// Editor // Editor
#include "Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h"
#include "ViewManager.h" #include "ViewManager.h"
#include "Include/ITransformManipulator.h" #include "Include/ITransformManipulator.h"
#include "Include/HitContext.h" #include "Include/HitContext.h"
@ -32,22 +37,35 @@
#include "GameEngine.h" #include "GameEngine.h"
#include "Settings.h" #include "Settings.h"
#ifdef LoadCursor #ifdef LoadCursor
#undef LoadCursor #undef LoadCursor
#endif #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 // 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 = AzToolsFramework::FindClosestPickIntersection(
context.m_hitLocation = GetHitLocation(pt); viewportId, AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(point), AzToolsFramework::EditorPickRayLength,
GetDefaultEntityPlacementDistance());
} }
void QtViewport::dragEnterEvent(QDragEnterEvent* event) void QtViewport::dragEnterEvent(QDragEnterEvent* event)
{ {
if (!GetIEditor()->GetGameEngine()->IsLevelLoaded()) if (!GetIEditor()->GetGameEngine()->IsLevelLoaded())
@ -66,7 +84,7 @@ void QtViewport::dragEnterEvent(QDragEnterEvent* event)
// new bus-based way of doing it (install a listener!) // new bus-based way of doing it (install a listener!)
using namespace AzQtComponents; using namespace AzQtComponents;
ViewportDragContext context; ViewportDragContext context;
BuildDragDropContext(context, event->pos()); BuildDragDropContext(context, GetViewportId(), event->pos());
DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragEnter, event, context); 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!) // new bus-based way of doing it (install a listener!)
using namespace AzQtComponents; using namespace AzQtComponents;
ViewportDragContext context; ViewportDragContext context;
BuildDragDropContext(context, event->pos()); BuildDragDropContext(context, GetViewportId(), event->pos());
DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::DragMove, event, context); 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!) // new bus-based way of doing it (install a listener!)
ViewportDragContext context; ViewportDragContext context;
BuildDragDropContext(context, event->pos()); BuildDragDropContext(context, GetViewportId(), event->pos());
DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::Drop, event, context); DragAndDropEventsBus::Event(DragAndDropContexts::EditorViewport, &DragAndDropEvents::Drop, event, context);
} }
} }
@ -340,13 +358,6 @@ void QtViewport::resizeEvent(QResizeEvent* event)
Update(); Update();
} }
//////////////////////////////////////////////////////////////////////////
void QtViewport::leaveEvent(QEvent* event)
{
QWidget::leaveEvent(event);
MouseCallback(eMouseLeave, QPoint(), Qt::KeyboardModifiers(), Qt::MouseButtons());
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void QtViewport::paintEvent([[maybe_unused]] QPaintEvent* event) void QtViewport::paintEvent([[maybe_unused]] QPaintEvent* event)
{ {
@ -581,63 +592,7 @@ void QtViewport::keyReleaseEvent(QKeyEvent* event)
OnKeyUp(nativeKey, 1, event->nativeModifiers()); 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() void QtViewport::OnSetCursor()
@ -696,44 +651,6 @@ void QtViewport::OnDragSelectRectangle(const QRect& rect, bool bNormalizeRect)
GetIEditor()->SetStatusText(szNewStatusText); 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) void QtViewport::SetCurrentCursor(const QCursor& hCursor, const QString& cursorString)
{ {
@ -1119,29 +1036,6 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo)
return false; 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) void QtViewport::SetZoomFactor(float fZoomFactor)
{ {
@ -1315,84 +1209,6 @@ bool QtViewport::GetAdvancedSelectModeFlag()
return m_bAdvancedSelectMode; 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) void QtViewport::ProcessRenderLisneters(DisplayContext& rstDisplayContext)
{ {

@ -6,13 +6,12 @@
* *
*/ */
// Description : interface for the CViewport class. // Description : interface for the CViewport class.
#pragma once #pragma once
#if !defined(Q_MOC_RUN) #if !defined(Q_MOC_RUN)
#include <AzFramework/Viewport/ViewportId.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h> #include <AzToolsFramework/Viewport/ViewportTypes.h>
#include <AzToolsFramework/ViewportUi/ViewportUiManager.h> #include <AzToolsFramework/ViewportUi/ViewportUiManager.h>
#include <Cry_Color.h> #include <Cry_Color.h>
@ -88,6 +87,9 @@ enum EStdCursor
STD_CURSOR_LAST, 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 AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
class SANDBOX_API CViewport class SANDBOX_API CViewport
: public IDisplayViewport : public IDisplayViewport
@ -201,7 +203,6 @@ public:
//! Performs hit testing of 2d point in view to find which object hit. //! Performs hit testing of 2d point in view to find which object hit.
virtual bool HitTest(const QPoint& point, HitContext& hitInfo) = 0; virtual bool HitTest(const QPoint& point, HitContext& hitInfo) = 0;
virtual AZ::Vector3 GetHitLocation(const QPoint& point) = 0;
virtual void MakeConstructionPlane(int axis) = 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. //! Performs hit testing of 2d point in view to find which object hit.
bool HitTest(const QPoint& point, HitContext& hitInfo) override; bool HitTest(const QPoint& point, HitContext& hitInfo) override;
AZ::Vector3 GetHitLocation(const QPoint& point) override;
//! Do 2D hit testing of line in world space. //! 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. // 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); void setRenderOverlayVisible(bool);
bool isRenderOverlayVisible() const; 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 ProcessRenderLisneters(DisplayContext& rstDisplayContext);
void mousePressEvent(QMouseEvent* event) override; void mousePressEvent(QMouseEvent* event) override;
@ -535,29 +532,29 @@ protected:
void keyPressEvent(QKeyEvent* event) override; void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override;
void resizeEvent(QResizeEvent* event) override; void resizeEvent(QResizeEvent* event) override;
void leaveEvent(QEvent* event) override;
void paintEvent(QPaintEvent* event) override; void paintEvent(QPaintEvent* event) override;
virtual void OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint& point); virtual void OnMouseMove(Qt::KeyboardModifiers, Qt::MouseButtons, const QPoint&) {}
virtual void OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta, const QPoint& pt); virtual void OnMouseWheel(Qt::KeyboardModifiers, short zDelta, const QPoint&);
virtual void OnLButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); virtual void OnLButtonDown(Qt::KeyboardModifiers, const QPoint&) {}
virtual void OnLButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); virtual void OnLButtonUp(Qt::KeyboardModifiers, const QPoint&) {}
virtual void OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); virtual void OnRButtonDown(Qt::KeyboardModifiers, const QPoint&) {}
virtual void OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); virtual void OnRButtonUp(Qt::KeyboardModifiers, const QPoint&) {}
virtual void OnMButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point); virtual void OnMButtonDblClk(Qt::KeyboardModifiers, const QPoint&) {}
virtual void OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); virtual void OnMButtonDown(Qt::KeyboardModifiers, const QPoint&) {}
virtual void OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); virtual void OnMButtonUp(Qt::KeyboardModifiers, const QPoint&) {}
virtual void OnLButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point); virtual void OnLButtonDblClk(Qt::KeyboardModifiers, const QPoint&) {}
virtual void OnRButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point); virtual void OnRButtonDblClk(Qt::KeyboardModifiers, const QPoint&) {}
virtual void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); virtual void OnKeyDown([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) {}
virtual void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); virtual void OnKeyUp([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) {}
#if defined(AZ_PLATFORM_WINDOWS) #if defined(AZ_PLATFORM_WINDOWS)
void OnRawInput(UINT wParam, HRAWINPUT lParam); void OnRawInput(UINT wParam, HRAWINPUT lParam);
#endif #endif
void OnSetCursor(); 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 dragEnterEvent(QDragEnterEvent* event) override;
void dragMoveEvent(QDragMoveEvent* event) override; void dragMoveEvent(QDragMoveEvent* event) override;
void dragLeaveEvent(QDragLeaveEvent* event) override; void dragLeaveEvent(QDragLeaveEvent* event) override;

@ -528,7 +528,7 @@ namespace AzToolsFramework
} }
} }
void PropertyAssetCtrl::UpdateErrorButton(const AZStd::string& errorLog) void PropertyAssetCtrl::UpdateErrorButton()
{ {
if (m_errorButton) if (m_errorButton)
{ {
@ -543,12 +543,17 @@ namespace AzToolsFramework
m_errorButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_errorButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
m_errorButton->setFixedSize(QSize(16, 16)); m_errorButton->setFixedSize(QSize(16, 16));
m_errorButton->setMouseTracking(true); m_errorButton->setMouseTracking(true);
m_errorButton->setIcon(QIcon("Icons/PropertyEditor/error_icon.png")); m_errorButton->setIcon(QIcon(":/PropertyEditor/Resources/error_icon.png"));
m_errorButton->setToolTip("Show Errors"); m_errorButton->setToolTip("Show Errors");
// Insert the error button after the asset label // Insert the error button after the asset label
qobject_cast<QHBoxLayout*>(layout())->insertWidget(1, m_errorButton); qobject_cast<QHBoxLayout*>(layout())->insertWidget(1, m_errorButton);
} }
}
void PropertyAssetCtrl::UpdateErrorButtonWithLog(const AZStd::string& errorLog)
{
UpdateErrorButton();
// Connect pressed to opening the error dialog // Connect pressed to opening the error dialog
// Must capture this for call to QObject::connect // Must capture this for call to QObject::connect
@ -588,6 +593,21 @@ namespace AzToolsFramework
}); });
} }
void PropertyAssetCtrl::UpdateErrorButtonWithMessage(const AZStd::string& message)
{
UpdateErrorButton();
connect(m_errorButton, &QPushButton::clicked, this, [this, message]() {
QMessageBox::critical(nullptr, "Error", message.c_str());
// Without this, the error button would maintain focus after clicking, which left the red error icon in a blue-highlighted state
if (parentWidget())
{
parentWidget()->setFocus();
}
});
}
void PropertyAssetCtrl::ClearAssetInternal() void PropertyAssetCtrl::ClearAssetInternal()
{ {
SetCurrentAssetHint(AZStd::string()); SetCurrentAssetHint(AZStd::string());
@ -960,7 +980,6 @@ namespace AzToolsFramework
else else
{ {
const AZ::Data::AssetId assetID = GetCurrentAssetID(); const AZ::Data::AssetId assetID = GetCurrentAssetID();
m_currentAssetHint = "";
AZ::Outcome<AssetSystem::JobInfoContainer> jobOutcome = AZ::Failure(); AZ::Outcome<AssetSystem::JobInfoContainer> jobOutcome = AZ::Failure();
AssetSystemJobRequestBus::BroadcastResult(jobOutcome, &AssetSystemJobRequestBus::Events::GetAssetJobsInfoByAssetID, assetID, false, false); AssetSystemJobRequestBus::BroadcastResult(jobOutcome, &AssetSystemJobRequestBus::Events::GetAssetJobsInfoByAssetID, assetID, false, false);
@ -1018,7 +1037,7 @@ namespace AzToolsFramework
// In case of failure, render failure icon // In case of failure, render failure icon
case AssetSystem::JobStatus::Failed: case AssetSystem::JobStatus::Failed:
{ {
UpdateErrorButton(errorLog); UpdateErrorButtonWithLog(errorLog);
} }
break; break;
@ -1043,6 +1062,10 @@ namespace AzToolsFramework
m_currentAssetHint = assetPath; m_currentAssetHint = assetPath;
} }
} }
else
{
UpdateErrorButtonWithMessage(AZStd::string::format("Asset is missing.\n\nID: %s\nHint:%s", assetID.ToString<AZStd::string>().c_str(), GetCurrentAssetHint().c_str()));
}
} }
// Get the asset file name // Get the asset file name

@ -168,7 +168,9 @@ namespace AzToolsFramework
bool IsCorrectMimeData(const QMimeData* pData, AZ::Data::AssetId* pAssetId = nullptr, AZ::Data::AssetType* pAssetType = nullptr) const; bool IsCorrectMimeData(const QMimeData* pData, AZ::Data::AssetId* pAssetId = nullptr, AZ::Data::AssetType* pAssetType = nullptr) const;
void ClearErrorButton(); void ClearErrorButton();
void UpdateErrorButton(const AZStd::string& errorLog); void UpdateErrorButton();
void UpdateErrorButtonWithLog(const AZStd::string& errorLog);
void UpdateErrorButtonWithMessage(const AZStd::string& message);
virtual const AZStd::string GetFolderSelection() const { return AZStd::string(); } virtual const AZStd::string GetFolderSelection() const { return AZStd::string(); }
virtual void SetFolderSelection(const AZStd::string& /* folderPath */) {} virtual void SetFolderSelection(const AZStd::string& /* folderPath */) {}
virtual void ClearAssetInternal(); virtual void ClearAssetInternal();

@ -6,6 +6,7 @@
* *
*/ */
#include <AzFramework/Render/IntersectorInterface.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h> #include <AzToolsFramework/Viewport/ViewportMessages.h>
namespace AzToolsFramework namespace AzToolsFramework
@ -62,4 +63,33 @@ namespace AzToolsFramework
return circleBoundWidth; 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 } // namespace AzToolsFramework

@ -334,6 +334,12 @@ namespace AzToolsFramework
return entityContextId; 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. //! 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). //! @note Function only cares about up or down events, all other events are mapped to Nil (ignored).
AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction( AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(

@ -18,9 +18,6 @@
namespace AzToolsFramework 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) AZ::Vector3 CalculateCenterOffset(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot)
{ {
if (Centered(pivot)) if (Centered(pivot))

@ -26,6 +26,9 @@ namespace AzFramework
namespace AzToolsFramework 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 //! Is the pivot at the center of the object (middle of extents) or at the
//! exported authored object root position. //! exported authored object root position.
inline bool Centered(const EditorTransformComponentSelectionRequests::Pivot pivot) inline bool Centered(const EditorTransformComponentSelectionRequests::Pivot pivot)

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:28c3cfd8958813b4b539738bfff589731da0aeec5b3376558f377da2ebe973ff oid sha256:7028c8db4f935f23aa4396668278a67691d92fe345cc9d417a9f47bd9a4af32b
size 5455 size 8130

@ -0,0 +1,91 @@
<ObjectStream version="3">
<Class name="TextureSettings" version="2" type="{980132FF-C450-425D-8AE0-BD96A8486177}">
<Class name="AZ::Uuid" field="PresetID" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="Name" field="Preset" value="ReferenceImage" type="{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}"/>
<Class name="unsigned int" field="SizeReduceLevel" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="bool" field="EngineReduce" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="EnableMipmap" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="MaintainAlphaCoverage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="AZStd::vector" field="MipMapAlphaAdjustments" type="{3349AACD-BE04-50BC-9478-528BF2ACFD55}">
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="MipMapGenEval" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="ImageProcessingAtom::MipGenType" field="MipMapGenType" value="1" type="{8524F650-1417-44DA-BBB0-C707A7A1A709}"/>
<Class name="AZStd::map" field="PlatformSpecificOverrides" type="{74E4843B-0924-583D-8C6E-A37B09BD51FE}">
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="android" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="ios" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="linux" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="mac" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#2·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="pc" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
</Class>
<Class name="AZStd::string" field="OverridingPlatform" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</ObjectStream>

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:8a0935be7347d695ed1716d030b5bae68153a88239b0ff15f67f900ac90be442 oid sha256:a7d94b9c0a77741736b93d8ed4d2b22bc9ae4cf649f3d8b3f10cbaf595a3ed31
size 5038 size 8336

@ -0,0 +1,148 @@
<ObjectStream version="3">
<Class name="TextureSettings" version="2" type="{980132FF-C450-425D-8AE0-BD96A8486177}">
<Class name="AZ::Uuid" field="PresetID" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="Name" field="Preset" value="ReferenceImage" type="{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}"/>
<Class name="unsigned int" field="SizeReduceLevel" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="bool" field="EngineReduce" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="EnableMipmap" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="MaintainAlphaCoverage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="AZStd::vector" field="MipMapAlphaAdjustments" type="{3349AACD-BE04-50BC-9478-528BF2ACFD55}">
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="MipMapGenEval" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="ImageProcessingAtom::MipGenType" field="MipMapGenType" value="1" type="{8524F650-1417-44DA-BBB0-C707A7A1A709}"/>
<Class name="AZStd::map" field="PlatformSpecificOverrides" type="{74E4843B-0924-583D-8C6E-A37B09BD51FE}">
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="android" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#4·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#2·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#3·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="ios" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#4·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#2·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#3·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="linux" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#4·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#2·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#3·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="mac" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#4·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#2·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#3·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="pc" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
</Class>
<Class name="AZStd::string" field="OverridingPlatform" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</ObjectStream>

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:bb243cd6d6414b4e95eab919fa94193b57825902b8d09f40ce3f334d829e74e2 oid sha256:3bbd45e3ef81850da81d1cc01775930a53c424e64e287b00990af3e7e6a682ba
size 6286 size 9701

@ -0,0 +1,148 @@
<ObjectStream version="3">
<Class name="TextureSettings" version="2" type="{980132FF-C450-425D-8AE0-BD96A8486177}">
<Class name="AZ::Uuid" field="PresetID" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="Name" field="Preset" value="ReferenceImage" type="{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}"/>
<Class name="unsigned int" field="SizeReduceLevel" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="bool" field="EngineReduce" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="EnableMipmap" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="MaintainAlphaCoverage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="AZStd::vector" field="MipMapAlphaAdjustments" type="{3349AACD-BE04-50BC-9478-528BF2ACFD55}">
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="MipMapGenEval" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="ImageProcessingAtom::MipGenType" field="MipMapGenType" value="1" type="{8524F650-1417-44DA-BBB0-C707A7A1A709}"/>
<Class name="AZStd::map" field="PlatformSpecificOverrides" type="{74E4843B-0924-583D-8C6E-A37B09BD51FE}">
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="android" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#4·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#2·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#3·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="ios" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#4·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#2·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#3·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="linux" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#4·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#2·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#3·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="mac" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#4·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#2·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#3·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="pc" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
</Class>
<Class name="AZStd::string" field="OverridingPlatform" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</ObjectStream>

@ -12,6 +12,7 @@
#include <AzCore/JSON/document.h> #include <AzCore/JSON/document.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h> #include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
namespace AZ namespace AZ
{ {
@ -21,21 +22,24 @@ namespace AZ
{ {
// Declarations... // Declarations...
Outcome<Data::AssetId> MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId); // Note that these functions default to TraceLevel::Error to preserve legacy behavior of these APIs. It would be nice to make the default match
// RPI.Reflect/Asset/AssetUtils.h which is TraceLevel::Warning, but we are close to a release so it isn't worth the risk at this time.
Outcome<Data::AssetId> MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId); Outcome<Data::AssetId> MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId, TraceLevel reporting = TraceLevel::Error);
Outcome<Data::AssetId> MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId, TraceLevel reporting = TraceLevel::Error);
template<typename AssetDataT> template<typename AssetDataT>
Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZStd::string& sourcePath, uint32_t productSubId = 0); Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZStd::string& sourcePath, uint32_t productSubId = 0, TraceLevel reporting = TraceLevel::Error);
template<typename AssetDataT> template<typename AssetDataT>
Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId = 0); Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId = 0, TraceLevel reporting = TraceLevel::Error);
template<typename AssetDataT> template<typename AssetDataT>
Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZ::Data::AssetId& assetId, const char* sourcePathForDebug); Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZ::Data::AssetId& assetId, const char* sourcePathForDebug, TraceLevel reporting = TraceLevel::Error);
template<typename AssetDataT> template<typename AssetDataT>
Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZ::Data::AssetId& assetId); Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZ::Data::AssetId& assetId, TraceLevel reporting = TraceLevel::Error);
//! Attempts to resolve the full path to a product asset given its ID //! Attempts to resolve the full path to a product asset given its ID
AZStd::string GetProductPathByAssetId(const AZ::Data::AssetId& assetId); AZStd::string GetProductPathByAssetId(const AZ::Data::AssetId& assetId);
@ -65,12 +69,12 @@ namespace AZ
// Definitions... // Definitions...
template<typename AssetDataT> template<typename AssetDataT>
Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZStd::string& sourcePath, uint32_t productSubId) Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZStd::string& sourcePath, uint32_t productSubId, TraceLevel reporting)
{ {
auto assetId = MakeAssetId(sourcePath, productSubId); auto assetId = MakeAssetId(sourcePath, productSubId, reporting);
if (assetId.IsSuccess()) if (assetId.IsSuccess())
{ {
return LoadAsset<AssetDataT>(assetId.GetValue(), sourcePath.c_str()); return LoadAsset<AssetDataT>(assetId.GetValue(), sourcePath.c_str(), reporting);
} }
else else
{ {
@ -79,20 +83,20 @@ namespace AZ
} }
template<typename AssetDataT> template<typename AssetDataT>
Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId) Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId, TraceLevel reporting)
{ {
AZStd::string resolvedPath = ResolvePathReference(originatingSourcePath, referencedSourceFilePath); AZStd::string resolvedPath = ResolvePathReference(originatingSourcePath, referencedSourceFilePath);
return LoadAsset<AssetDataT>(resolvedPath, productSubId); return LoadAsset<AssetDataT>(resolvedPath, productSubId, reporting);
} }
template<typename AssetDataT> template<typename AssetDataT>
Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZ::Data::AssetId& assetId) Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZ::Data::AssetId& assetId, TraceLevel reporting)
{ {
return LoadAsset<AssetDataT>(assetId, nullptr); return LoadAsset<AssetDataT>(assetId, nullptr, reporting);
} }
template<typename AssetDataT> template<typename AssetDataT>
Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZ::Data::AssetId& assetId, [[maybe_unused]] const char* sourcePathForDebug) Outcome<AZ::Data::Asset<AssetDataT>> LoadAsset(const AZ::Data::AssetId& assetId, [[maybe_unused]] const char* sourcePathForDebug, TraceLevel reporting)
{ {
if (nullptr == AZ::IO::FileIOBase::GetInstance()->GetAlias("@products@")) if (nullptr == AZ::IO::FileIOBase::GetInstance()->GetAlias("@products@"))
{ {
@ -111,11 +115,11 @@ namespace AZ
} }
else else
{ {
AZ_Error("AssetUtils", false, "Could not load %s [Source='%s' Cache='%s' AssetID=%s] ", AssetUtilsInternal::ReportIssue(reporting, AZStd::string::format("Could not load %s [Source='%s' Cache='%s' AssetID=%s] ",
AzTypeInfo<AssetDataT>::Name(), AzTypeInfo<AssetDataT>::Name(),
sourcePathForDebug ? sourcePathForDebug : "<unknown>", sourcePathForDebug ? sourcePathForDebug : "<unknown>",
asset.GetHint().empty() ? "<unknown>" : asset.GetHint().c_str(), asset.GetHint().empty() ? "<unknown>" : asset.GetHint().c_str(),
assetId.ToString<AZStd::string>().c_str()); assetId.ToString<AZStd::string>().c_str()).c_str());
return AZ::Failure(); return AZ::Failure();
} }

@ -28,7 +28,18 @@ namespace AZ
namespace MaterialUtils namespace MaterialUtils
{ {
Outcome<Data::Asset<ImageAsset>> GetImageAssetReference(AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath); enum class GetImageAssetResult
{
Empty, //! No image was actually requested, the path was empty
Found, //! The requested asset was found
Missing //! The requested asset was not found, and a placeholder asset was used instead
};
//! Finds an ImageAsset referenced by a material file (or a placeholder)
//! @param imageAsset the resulting ImageAsset
//! @param materialSourceFilePath the full path to a material source file that is referenfing an image file
//! @param imageFilePath the path to an image source file, which could be relative to the asset root or relative to the material file
GetImageAssetResult GetImageAssetReference(Data::Asset<ImageAsset>& imageAsset, AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath);
//! Resolve an enum to a uint32_t given its name and definition array (in MaterialPropertyDescriptor). //! Resolve an enum to a uint32_t given its name and definition array (in MaterialPropertyDescriptor).
//! @param propertyDescriptor it contains the definition of all enum names in an array. //! @param propertyDescriptor it contains the definition of all enum names in an array.

@ -29,6 +29,14 @@ namespace AZ
Count Count
}; };
namespace DefaultImageAssetPaths
{
static constexpr char DefaultFallback[] = "textures/defaults/defaultfallback.png.streamingimage";
static constexpr char Processing[] = "textures/defaults/processing.png.streamingimage";
static constexpr char ProcessingFailed[] = "textures/defaults/processingfailed.png.streamingimage";
static constexpr char Missing[] = "textures/defaults/missing.png.streamingimage";
}
class ImageSystemInterface class ImageSystemInterface
{ {
public: public:

@ -64,10 +64,20 @@ namespace AZ
BusDisconnect(); BusDisconnect();
} }
bool MaterialBuilder::ReportMaterialAssetWarningsAsErrors() const
{
bool warningsAsErrors = false;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
settingsRegistry->Get(warningsAsErrors, "/O3DE/Atom/RPI/MaterialBuilder/WarningsAsErrors");
}
return warningsAsErrors;
}
//! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path. //! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path.
//! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found. //! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found.
//! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back //! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back
//! to the AssetBuilderSDK::CreateJobsResponse. If isOrderedOnceForMaterialTypes is true and the dependency is a materialtype file, the job dependency type //! to the AssetBuilderSDK::CreateJobsResponse. If isOrderedOnceForMaterialTypes is true and the dependency is a .materialtype file, the job dependency type
//! will be set to JobDependencyType::OrderOnce. //! will be set to JobDependencyType::OrderOnce.
void AddPossibleDependencies(AZStd::string_view currentFilePath, void AddPossibleDependencies(AZStd::string_view currentFilePath,
AZStd::string_view referencedParentPath, AZStd::string_view referencedParentPath,
@ -278,7 +288,7 @@ namespace AZ
return materialTypeAssetOutcome.GetValue(); return materialTypeAssetOutcome.GetValue();
} }
AZ::Data::Asset<MaterialAsset> CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json) AZ::Data::Asset<MaterialAsset> MaterialBuilder::CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json) const
{ {
auto material = LoadSourceData<MaterialSourceData>(json, materialSourceFilePath); auto material = LoadSourceData<MaterialSourceData>(json, materialSourceFilePath);
@ -292,7 +302,7 @@ namespace AZ
return {}; return {};
} }
auto materialAssetOutcome = material.GetValue().CreateMaterialAsset(Uuid::CreateRandom(), materialSourceFilePath, true); auto materialAssetOutcome = material.GetValue().CreateMaterialAsset(Uuid::CreateRandom(), materialSourceFilePath, ReportMaterialAssetWarningsAsErrors());
if (!materialAssetOutcome.IsSuccess()) if (!materialAssetOutcome.IsSuccess())
{ {
return {}; return {};

@ -9,6 +9,8 @@
#pragma once #pragma once
#include <AssetBuilderSDK/AssetBuilderBusses.h> #include <AssetBuilderSDK/AssetBuilderBusses.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AzCore/JSON/document.h>
namespace AZ namespace AZ
{ {
@ -37,6 +39,9 @@ namespace AZ
private: private:
AZ::Data::Asset<MaterialAsset> CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json) const;
bool ReportMaterialAssetWarningsAsErrors() const;
bool m_isShuttingDown = false; bool m_isShuttingDown = false;
}; };

@ -10,6 +10,7 @@
#include <AzFramework/StringFunc/StringFunc.h> #include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzCore/IO/IOUtils.h> #include <AzCore/IO/IOUtils.h>
#include <AzCore/IO/Path/Path.h>
namespace AZ namespace AZ
{ {
@ -46,6 +47,12 @@ namespace AZ
AZStd::string ResolvePathReference(const AZStd::string& originatingSourceFilePath, const AZStd::string& referencedSourceFilePath) AZStd::string ResolvePathReference(const AZStd::string& originatingSourceFilePath, const AZStd::string& referencedSourceFilePath)
{ {
// The IsAbsolute part prevents "second join parameter is an absolute path" warnings in StringFunc::Path::Join below
if (referencedSourceFilePath.empty() || AZ::IO::PathView{referencedSourceFilePath}.IsAbsolute())
{
return referencedSourceFilePath;
}
AZStd::string normalizedReferencedPath = referencedSourceFilePath; AZStd::string normalizedReferencedPath = referencedSourceFilePath;
AzFramework::StringFunc::Path::Normalize(normalizedReferencedPath); AzFramework::StringFunc::Path::Normalize(normalizedReferencedPath);
@ -113,7 +120,7 @@ namespace AZ
return results; return results;
} }
Outcome<Data::AssetId> MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId) Outcome<Data::AssetId> MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId, TraceLevel reporting)
{ {
bool assetFound = false; bool assetFound = false;
AZ::Data::AssetInfo sourceInfo; AZ::Data::AssetInfo sourceInfo;
@ -122,7 +129,7 @@ namespace AZ
if (!assetFound) if (!assetFound)
{ {
AZ_Error("AssetUtils", false, "Could not find asset [%s]", sourcePath.c_str()); AssetUtilsInternal::ReportIssue(reporting, AZStd::string::format("Could not find asset [%s]", sourcePath.c_str()).c_str());
return AZ::Failure(); return AZ::Failure();
} }
else else
@ -131,10 +138,10 @@ namespace AZ
} }
} }
Outcome<Data::AssetId> MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId) Outcome<Data::AssetId> MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId, TraceLevel reporting)
{ {
AZStd::string resolvedPath = ResolvePathReference(originatingSourcePath, referencedSourceFilePath); AZStd::string resolvedPath = ResolvePathReference(originatingSourcePath, referencedSourceFilePath);
return MakeAssetId(resolvedPath, productSubId); return MakeAssetId(resolvedPath, productSubId, reporting);
} }
} // namespace AssetUtils } // namespace AssetUtils
} // namespace RPI } // namespace RPI

@ -303,7 +303,7 @@ namespace AZ
MaterialPropertyId propertyId{ group.first, property.first }; MaterialPropertyId propertyId{ group.first, property.first };
if (!property.second.m_value.IsValid()) if (!property.second.m_value.IsValid())
{ {
AZ_Warning("Material source data", false, "Source data for material property value is invalid."); materialAssetCreator.ReportWarning("Source data for material property value is invalid.");
} }
else else
{ {
@ -317,22 +317,20 @@ namespace AZ
{ {
case MaterialPropertyDataType::Image: case MaterialPropertyDataType::Image:
{ {
Outcome<Data::Asset<ImageAsset>> imageAssetResult = MaterialUtils::GetImageAssetReference( Data::Asset<ImageAsset> imageAsset;
materialSourceFilePath, property.second.m_value.GetValue<AZStd::string>());
if (imageAssetResult.IsSuccess()) MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference(
{ imageAsset, materialSourceFilePath, property.second.m_value.GetValue<AZStd::string>());
auto& imageAsset = imageAssetResult.GetValue();
// Load referenced images when load material if (result == MaterialUtils::GetImageAssetResult::Missing)
imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad);
materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset);
}
else
{ {
materialAssetCreator.ReportError( materialAssetCreator.ReportWarning(
"Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(),
property.second.m_value.GetValue<AZStd::string>().data()); property.second.m_value.GetValue<AZStd::string>().data());
} }
imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad);
materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset);
} }
break; break;
case MaterialPropertyDataType::Enum: case MaterialPropertyDataType::Enum:

@ -451,20 +451,21 @@ namespace AZ
{ {
case MaterialPropertyDataType::Image: case MaterialPropertyDataType::Image:
{ {
auto imageAssetResult = MaterialUtils::GetImageAssetReference( Data::Asset<ImageAsset> imageAsset;
materialTypeSourceFilePath, property.m_value.GetValue<AZStd::string>());
if (imageAssetResult) MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference(
{ imageAsset, materialTypeSourceFilePath, property.m_value.GetValue<AZStd::string>());
auto imageAsset = imageAssetResult.GetValue();
materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset); if (result == MaterialUtils::GetImageAssetResult::Missing)
}
else
{ {
materialTypeAssetCreator.ReportError( materialTypeAssetCreator.ReportError(
"Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(), "Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(),
property.m_value.GetValue<AZStd::string>().data()); property.m_value.GetValue<AZStd::string>().data());
} }
else
{
materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset);
}
} }
break; break;
case MaterialPropertyDataType::Enum: case MaterialPropertyDataType::Enum:

@ -28,25 +28,36 @@ namespace AZ
{ {
namespace MaterialUtils namespace MaterialUtils
{ {
Outcome<Data::Asset<ImageAsset>> GetImageAssetReference(AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath) GetImageAssetResult GetImageAssetReference(Data::Asset<ImageAsset>& imageAsset, AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath)
{ {
imageAsset = {};
if (imageFilePath.empty()) if (imageFilePath.empty())
{ {
// The image value was present but specified an empty string, meaning the texture asset should be explicitly cleared. // The image value was present but specified an empty string, meaning the texture asset should be explicitly cleared.
return AZ::Success(Data::Asset<ImageAsset>()); return GetImageAssetResult::Empty;
} }
else else
{ {
Outcome<Data::AssetId> imageAssetId = AssetUtils::MakeAssetId(materialSourceFilePath, imageFilePath, StreamingImageAsset::GetImageAssetSubId()); // We use TraceLevel::None because fallback textures are available and we'll return GetImageAssetResult::Missing below in that case.
// Callers of GetImageAssetReference will be responsible for logging warnings or errors as needed.
Outcome<Data::AssetId> imageAssetId = AssetUtils::MakeAssetId(materialSourceFilePath, imageFilePath, StreamingImageAsset::GetImageAssetSubId(), AssetUtils::TraceLevel::None);
if (!imageAssetId.IsSuccess()) if (!imageAssetId.IsSuccess())
{ {
return AZ::Failure(); // When the AssetId cannot be found, we don't want to outright fail, because the runtime has mechanisms for displaying fallback textures which gives the
} // user a better recovery workflow. On the other hand we can't just provide an empty/invalid Asset<ImageAsset> because that would be interpreted as simply
else // no value was present and result in using no texture, and this would amount to a silent failure.
{ // So we use a randomly generated (well except for the "BADA55E7" bit ;) UUID which the runtime and tools will interpret as a missing asset and represent
Data::Asset<ImageAsset> unloadedImageAssetReference(imageAssetId.GetValue(), azrtti_typeid<StreamingImageAsset>(), imageFilePath); // it as such.
return AZ::Success(unloadedImageAssetReference); static const Uuid InvalidAssetPlaceholderId = "{BADA55E7-1A1D-4940-B655-9D08679BD62F}";
imageAsset = Data::Asset<ImageAsset>{InvalidAssetPlaceholderId, azrtti_typeid<StreamingImageAsset>(), imageFilePath};
return GetImageAssetResult::Missing;
} }
imageAsset = Data::Asset<ImageAsset>{imageAssetId.GetValue(), azrtti_typeid<StreamingImageAsset>(), imageFilePath};
return GetImageAssetResult::Found;
} }
} }

@ -7,6 +7,7 @@
*/ */
#include <Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h> #include <Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h>
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
#include <AzCore/Settings/SettingsRegistry.h> #include <AzCore/Settings/SettingsRegistry.h>
#include <AzFramework/Asset/AssetSystemBus.h> #include <AzFramework/Asset/AssetSystemBus.h>
@ -52,7 +53,7 @@ namespace AZ
missingAssetStatus, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, asset.GetId().m_guid); missingAssetStatus, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, asset.GetId().m_guid);
// Determine which fallback image to use // Determine which fallback image to use
const char* relativePath = "textures/defaults/defaultfallback.png.streamingimage"; const char* relativePath = DefaultImageAssetPaths::DefaultFallback;
bool useDebugFallbackImages = true; bool useDebugFallbackImages = true;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
@ -66,15 +67,15 @@ namespace AZ
{ {
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Queued: case AzFramework::AssetSystem::AssetStatus::AssetStatus_Queued:
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiling: case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiling:
relativePath = "textures/defaults/processing.png.streamingimage"; relativePath = DefaultImageAssetPaths::Processing;
break; break;
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Failed: case AzFramework::AssetSystem::AssetStatus::AssetStatus_Failed:
relativePath = "textures/defaults/processingfailed.png.streamingimage"; relativePath = DefaultImageAssetPaths::ProcessingFailed;
break; break;
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Missing: case AzFramework::AssetSystem::AssetStatus::AssetStatus_Missing:
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Unknown: case AzFramework::AssetSystem::AssetStatus::AssetStatus_Unknown:
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiled: case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiled:
relativePath = "textures/defaults/missing.png.streamingimage"; relativePath = DefaultImageAssetPaths::Missing;
break; break;
} }
} }

@ -118,12 +118,16 @@ namespace AZ
else if (value.is<Data::Asset<Data::AssetData>>()) else if (value.is<Data::Asset<Data::AssetData>>())
{ {
result.m_value = Data::Asset<RPI::ImageAsset>( result.m_value = Data::Asset<RPI::ImageAsset>(
AZStd::any_cast<Data::Asset<Data::AssetData>>(value).GetId(), azrtti_typeid<RPI::StreamingImageAsset>()); AZStd::any_cast<Data::Asset<Data::AssetData>>(value).GetId(),
azrtti_typeid<RPI::StreamingImageAsset>(),
AZStd::any_cast<Data::Asset<Data::AssetData>>(value).GetHint());
} }
else if (value.is<Data::Asset<StreamingImageAsset>>()) else if (value.is<Data::Asset<StreamingImageAsset>>())
{ {
result.m_value = Data::Asset<RPI::ImageAsset>( result.m_value = Data::Asset<RPI::ImageAsset>(
AZStd::any_cast<Data::Asset<StreamingImageAsset>>(value).GetId(), azrtti_typeid<RPI::StreamingImageAsset>()); AZStd::any_cast<Data::Asset<StreamingImageAsset>>(value).GetId(),
azrtti_typeid<RPI::StreamingImageAsset>(),
AZStd::any_cast<Data::Asset<StreamingImageAsset>>(value).GetHint());
} }
else if (value.is<Data::Asset<ImageAsset>>()) else if (value.is<Data::Asset<ImageAsset>>())
{ {

@ -625,23 +625,6 @@ namespace UnitTest
// We use local functions to easily start a new MaterialAssetCreator for each test case because // We use local functions to easily start a new MaterialAssetCreator for each test case because
// the AssetCreator would just skip subsequent operations after the first failure is detected. // the AssetCreator would just skip subsequent operations after the first failure is detected.
auto expectError = [](AZStd::function<void(MaterialSourceData& materialSourceData)> setOneBadInput, [[maybe_unused]] uint32_t expectedAsserts = 2)
{
MaterialSourceData sourceData;
sourceData.m_materialType = "@exefolder@/Temp/test.materialtype";
AddPropertyGroup(sourceData, "general");
setOneBadInput(sourceData);
AZ_TEST_START_ASSERTTEST;
auto materialAssetOutcome = sourceData.CreateMaterialAsset(Uuid::CreateRandom(), "", false);
AZ_TEST_STOP_ASSERTTEST(expectedAsserts); // Usually one for the initial error, and one for when End() is called
EXPECT_FALSE(materialAssetOutcome.IsSuccess());
};
auto expectWarning = [](AZStd::function<void(MaterialSourceData& materialSourceData)> setOneBadInput, [[maybe_unused]] uint32_t expectedAsserts = 1) auto expectWarning = [](AZStd::function<void(MaterialSourceData& materialSourceData)> setOneBadInput, [[maybe_unused]] uint32_t expectedAsserts = 1)
{ {
MaterialSourceData sourceData; MaterialSourceData sourceData;
@ -692,10 +675,10 @@ namespace UnitTest
}); });
// Missing image reference // Missing image reference
expectError([](MaterialSourceData& materialSourceData) expectWarning([](MaterialSourceData& materialSourceData)
{ {
AddProperty(materialSourceData, "general", "MyImage", AZStd::string("doesNotExist.streamingimage")); AddProperty(materialSourceData, "general", "MyImage", AZStd::string("doesNotExist.streamingimage"));
}, 3); // Expect a 3rd error because AssetUtils reports its own assertion failure });
} }

@ -888,4 +888,43 @@ namespace UnitTest
EXPECT_EQ(indexFromOldName, indexFromNewName); EXPECT_EQ(indexFromOldName, indexFromNewName);
} }
template<typename T>
void CheckPropertyValueRoundTrip(const T& value)
{
AZ::RPI::MaterialPropertyValue materialPropertyValue{value};
AZStd::any anyValue{value};
AZ::RPI::MaterialPropertyValue materialPropertyValueFromAny = MaterialPropertyValue::FromAny(anyValue);
AZ::RPI::MaterialPropertyValue materialPropertyValueFromRoundTrip = MaterialPropertyValue::FromAny(MaterialPropertyValue::ToAny(materialPropertyValue));
EXPECT_EQ(materialPropertyValue, materialPropertyValueFromAny);
EXPECT_EQ(materialPropertyValue, materialPropertyValueFromRoundTrip);
if (materialPropertyValue.Is<Data::Asset<ImageAsset>>())
{
EXPECT_EQ(materialPropertyValue.GetValue<Data::Asset<ImageAsset>>().GetHint(), materialPropertyValueFromAny.GetValue<Data::Asset<ImageAsset>>().GetHint());
EXPECT_EQ(materialPropertyValue.GetValue<Data::Asset<ImageAsset>>().GetHint(), materialPropertyValueFromRoundTrip.GetValue<Data::Asset<ImageAsset>>().GetHint());
}
}
TEST_F(MaterialTests, TestMaterialPropertyValueAsAny)
{
CheckPropertyValueRoundTrip(true);
CheckPropertyValueRoundTrip(false);
CheckPropertyValueRoundTrip(7);
CheckPropertyValueRoundTrip(8u);
CheckPropertyValueRoundTrip(9.0f);
CheckPropertyValueRoundTrip(AZ::Vector2(1.0f, 2.0f));
CheckPropertyValueRoundTrip(AZ::Vector3(1.0f, 2.0f, 3.0f));
CheckPropertyValueRoundTrip(AZ::Vector4(1.0f, 2.0f, 3.0f, 4.0f));
CheckPropertyValueRoundTrip(AZ::Color(1.0f, 2.0f, 3.0f, 4.0f));
CheckPropertyValueRoundTrip(Data::Asset<Data::AssetData>{});
CheckPropertyValueRoundTrip(Data::Asset<ImageAsset>{});
CheckPropertyValueRoundTrip(Data::Asset<StreamingImageAsset>{});
CheckPropertyValueRoundTrip(Data::Asset<Data::AssetData>{Uuid::CreateRandom(), azrtti_typeid<AZ::RPI::StreamingImageAsset>(), "TestAssetPath.png"});
CheckPropertyValueRoundTrip(Data::Asset<ImageAsset>{Uuid::CreateRandom(), azrtti_typeid<AZ::RPI::StreamingImageAsset>(), "TestAssetPath.png"});
CheckPropertyValueRoundTrip(Data::Asset<StreamingImageAsset>{Uuid::CreateRandom(), azrtti_typeid<AZ::RPI::StreamingImageAsset>(), "TestAssetPath.png"});
CheckPropertyValueRoundTrip(m_testImageAsset);
CheckPropertyValueRoundTrip(Data::Instance<Image>{m_testImage});
CheckPropertyValueRoundTrip(AZStd::string{"hello"});
}
} }

@ -26,6 +26,21 @@ namespace AtomToolsFramework
//! Get the combined output of all messages //! Get the combined output of all messages
AZStd::string GetDump() const; AZStd::string GetDump() const;
//! Return the number of OnAssert calls
size_t GetAssertCount() const;
//! Return the number of OnException calls
size_t GetExceptionCount() const;
//! Return the number of OnError calls, and includes OnAssert and OnException if @includeHigher is true
size_t GetErrorCount(bool includeHigher = false) const;
//! Return the number of OnWarning calls, and includes higher categories if @includeHigher is true
size_t GetWarningCount(bool includeHigher = false) const;
//! Return the number of OnPrintf calls, and includes higher categories if @includeHigher is true
size_t GetPrintfCount(bool includeHigher = false) const;
private: private:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// AZ::Debug::TraceMessageBus::Handler overrides... // AZ::Debug::TraceMessageBus::Handler overrides...
@ -38,5 +53,11 @@ namespace AtomToolsFramework
size_t m_maxMessageCount = std::numeric_limits<size_t>::max(); size_t m_maxMessageCount = std::numeric_limits<size_t>::max();
AZStd::list<AZStd::string> m_messages; AZStd::list<AZStd::string> m_messages;
size_t m_assertCount = 0;
size_t m_exceptionCount = 0;
size_t m_errorCount = 0;
size_t m_warningCount = 0;
size_t m_printfCount = 0;
}; };
} // namespace AtomToolsFramework } // namespace AtomToolsFramework

@ -49,6 +49,7 @@ namespace AtomToolsFramework
//! @param propertyValue the value being converted before saving //! @param propertyValue the value being converted before saving
bool ConvertToExportFormat( bool ConvertToExportFormat(
const AZStd::string& exportPath, const AZStd::string& exportPath,
[[maybe_unused]] const AZ::Name& propertyId,
const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition,
AZ::RPI::MaterialPropertyValue& propertyValue); AZ::RPI::MaterialPropertyValue& propertyValue);

@ -10,6 +10,7 @@
#include <Atom/RPI.Public/Base.h> #include <Atom/RPI.Public/Base.h>
#include <Atom/RPI.Public/View.h> #include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <AzFramework/Viewport/CameraState.h> #include <AzFramework/Viewport/CameraState.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h> #include <AzToolsFramework/Viewport/ViewportMessages.h>
@ -17,7 +18,9 @@ namespace AtomToolsFramework
{ {
//! A concrete implementation of the ViewportInteractionRequestBus. //! A concrete implementation of the ViewportInteractionRequestBus.
//! Primarily concerned with picking (screen to world and world to screen transformations). //! Primarily concerned with picking (screen to world and world to screen transformations).
class ViewportInteractionImpl : public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler class ViewportInteractionImpl
: public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler
, private AZ::RPI::ViewportContextIdNotificationBus::Handler
{ {
public: public:
explicit ViewportInteractionImpl(AZ::RPI::ViewPtr viewPtr); explicit ViewportInteractionImpl(AZ::RPI::ViewPtr viewPtr);
@ -37,6 +40,9 @@ namespace AtomToolsFramework
AZStd::function<float()> m_deviceScalingFactorFn; //! Callback to determine the device scaling factor. AZStd::function<float()> m_deviceScalingFactorFn; //! Callback to determine the device scaling factor.
private: private:
// ViewportContextIdNotificationBus overrides ...
void OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view) override;
AZ::RPI::ViewPtr m_viewPtr; AZ::RPI::ViewPtr m_viewPtr;
}; };
} // namespace AtomToolsFramework } // namespace AtomToolsFramework

@ -31,6 +31,7 @@ namespace AtomToolsFramework
bool TraceRecorder::OnAssert(const char* message) bool TraceRecorder::OnAssert(const char* message)
{ {
++m_assertCount;
if (m_messages.size() < m_maxMessageCount) if (m_messages.size() < m_maxMessageCount)
{ {
m_messages.push_back(AZStd::string::format("Assert: %s", message)); m_messages.push_back(AZStd::string::format("Assert: %s", message));
@ -40,6 +41,7 @@ namespace AtomToolsFramework
bool TraceRecorder::OnException(const char* message) bool TraceRecorder::OnException(const char* message)
{ {
++m_exceptionCount;
if (m_messages.size() < m_maxMessageCount) if (m_messages.size() < m_maxMessageCount)
{ {
m_messages.push_back(AZStd::string::format("Exception: %s", message)); m_messages.push_back(AZStd::string::format("Exception: %s", message));
@ -49,6 +51,7 @@ namespace AtomToolsFramework
bool TraceRecorder::OnError(const char* /*window*/, const char* message) bool TraceRecorder::OnError(const char* /*window*/, const char* message)
{ {
++m_errorCount;
if (m_messages.size() < m_maxMessageCount) if (m_messages.size() < m_maxMessageCount)
{ {
m_messages.push_back(AZStd::string::format("Error: %s", message)); m_messages.push_back(AZStd::string::format("Error: %s", message));
@ -58,6 +61,7 @@ namespace AtomToolsFramework
bool TraceRecorder::OnWarning(const char* /*window*/, const char* message) bool TraceRecorder::OnWarning(const char* /*window*/, const char* message)
{ {
++m_warningCount;
if (m_messages.size() < m_maxMessageCount) if (m_messages.size() < m_maxMessageCount)
{ {
m_messages.push_back(AZStd::string::format("Warning: %s", message)); m_messages.push_back(AZStd::string::format("Warning: %s", message));
@ -67,6 +71,7 @@ namespace AtomToolsFramework
bool TraceRecorder::OnPrintf(const char* /*window*/, const char* message) bool TraceRecorder::OnPrintf(const char* /*window*/, const char* message)
{ {
++m_printfCount;
if (m_messages.size() < m_maxMessageCount) if (m_messages.size() < m_maxMessageCount)
{ {
m_messages.push_back(AZStd::string::format("%s", message)); m_messages.push_back(AZStd::string::format("%s", message));
@ -74,4 +79,50 @@ namespace AtomToolsFramework
return false; return false;
} }
size_t TraceRecorder::GetAssertCount() const
{
return m_assertCount;
}
size_t TraceRecorder::GetExceptionCount() const
{
return m_exceptionCount;
}
size_t TraceRecorder::GetErrorCount(bool includeHigher) const
{
if (includeHigher)
{
return m_errorCount + GetAssertCount() + GetExceptionCount();
}
else
{
return m_errorCount;
}
}
size_t TraceRecorder::GetWarningCount(bool includeHigher) const
{
if (includeHigher)
{
return m_warningCount + GetErrorCount(true);
}
else
{
return m_warningCount;
}
}
size_t TraceRecorder::GetPrintfCount(bool includeHigher) const
{
if (includeHigher)
{
return m_printfCount + GetWarningCount(true);
}
else
{
return m_printfCount;
}
}
} // namespace AtomToolsFramework } // namespace AtomToolsFramework

@ -495,8 +495,6 @@ namespace AtomToolsFramework
return AZ::Uuid::CreateNull(); return AZ::Uuid::CreateNull();
} }
traceRecorder.GetDump().clear();
bool openResult = false; bool openResult = false;
AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, requestedPath); AtomToolsDocumentRequestBus::EventResult(openResult, documentId, &AtomToolsDocumentRequestBus::Events::Open, requestedPath);
if (!openResult) if (!openResult)
@ -507,6 +505,12 @@ namespace AtomToolsFramework
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId); AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::DestroyDocument, documentId);
return AZ::Uuid::CreateNull(); return AZ::Uuid::CreateNull();
} }
else if (traceRecorder.GetWarningCount(true) > 0)
{
QMessageBox::warning(
QApplication::activeWindow(), QString("Document opened with warnings"),
QString("Warnings encountered: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str()));
}
return documentId; return documentId;
} }

@ -167,6 +167,7 @@ namespace AtomToolsFramework
bool ConvertToExportFormat( bool ConvertToExportFormat(
const AZStd::string& exportPath, const AZStd::string& exportPath,
[[maybe_unused]] const AZ::Name& propertyId,
const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition, const AZ::RPI::MaterialTypeSourceData::PropertyDefinition& propertyDefinition,
AZ::RPI::MaterialPropertyValue& propertyValue) AZ::RPI::MaterialPropertyValue& propertyValue)
{ {
@ -175,7 +176,7 @@ namespace AtomToolsFramework
const uint32_t index = propertyValue.GetValue<uint32_t>(); const uint32_t index = propertyValue.GetValue<uint32_t>();
if (index >= propertyDefinition.m_enumValues.size()) if (index >= propertyDefinition.m_enumValues.size())
{ {
AZ_Error("AtomToolsFramework", false, "Invalid value for material enum property: '%s'.", propertyDefinition.m_name.c_str()); AZ_Error("AtomToolsFramework", false, "Invalid value for material enum property: '%s'.", propertyId.GetCStr());
return false; return false;
} }
@ -186,18 +187,33 @@ namespace AtomToolsFramework
// Image asset references must be converted from asset IDs to a relative source file path // Image asset references must be converted from asset IDs to a relative source file path
if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Image) if (propertyDefinition.m_dataType == AZ::RPI::MaterialPropertyDataType::Image)
{ {
AZStd::string imagePath;
AZ::Data::AssetId imageAssetId;
if (propertyValue.Is<AZ::Data::Asset<AZ::RPI::ImageAsset>>()) if (propertyValue.Is<AZ::Data::Asset<AZ::RPI::ImageAsset>>())
{ {
const auto& imageAsset = propertyValue.GetValue<AZ::Data::Asset<AZ::RPI::ImageAsset>>(); const auto& imageAsset = propertyValue.GetValue<AZ::Data::Asset<AZ::RPI::ImageAsset>>();
const auto& imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAsset.GetId()); imageAssetId = imageAsset.GetId();
propertyValue = GetExteralReferencePath(exportPath, imagePath);
return true;
} }
if (propertyValue.Is<AZ::Data::Instance<AZ::RPI::Image>>()) if (propertyValue.Is<AZ::Data::Instance<AZ::RPI::Image>>())
{ {
const auto& image = propertyValue.GetValue<AZ::Data::Instance<AZ::RPI::Image>>(); const auto& image = propertyValue.GetValue<AZ::Data::Instance<AZ::RPI::Image>>();
const auto& imagePath = image ? AZ::RPI::AssetUtils::GetSourcePathByAssetId(image->GetAssetId()) : ""; if (image)
{
imageAssetId = image->GetAssetId();
}
}
imagePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(imageAssetId);
if (imageAssetId.IsValid() && imagePath.empty())
{
AZ_Error("AtomToolsFramework", false, "Image asset could not be found for property: '%s'.", propertyId.GetCStr());
return false;
}
else
{
propertyValue = GetExteralReferencePath(exportPath, imagePath); propertyValue = GetExteralReferencePath(exportPath, imagePath);
return true; return true;
} }

@ -19,10 +19,12 @@ namespace AtomToolsFramework
void ViewportInteractionImpl::Connect(const AzFramework::ViewportId viewportId) void ViewportInteractionImpl::Connect(const AzFramework::ViewportId viewportId)
{ {
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(viewportId); AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(viewportId);
AZ::RPI::ViewportContextIdNotificationBus::Handler::BusConnect(viewportId);
} }
void ViewportInteractionImpl::Disconnect() void ViewportInteractionImpl::Disconnect()
{ {
AZ::RPI::ViewportContextIdNotificationBus::Handler::BusDisconnect();
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect();
} }
@ -58,4 +60,9 @@ namespace AtomToolsFramework
{ {
return m_deviceScalingFactorFn(); return m_deviceScalingFactorFn();
} }
void ViewportInteractionImpl::OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view)
{
m_viewPtr = AZStd::move(view);
}
} // namespace AtomToolsFramework } // namespace AtomToolsFramework

@ -7,12 +7,14 @@
*/ */
#include <Atom/RPI.Public/View.h> #include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <AtomToolsFramework/Viewport/RenderViewportWidget.h> #include <AtomToolsFramework/Viewport/RenderViewportWidget.h>
#include <AzCore/Math/IntersectSegment.h> #include <AzCore/Math/IntersectSegment.h>
#include <AzCore/Math/MatrixUtils.h> #include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Name/NameDictionary.h> #include <AzCore/Name/NameDictionary.h>
#include <AzCore/UnitTest/TestTypes.h> #include <AzCore/UnitTest/TestTypes.h>
#include <AzFramework/Viewport/ScreenGeometry.h> #include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzFramework/Viewport/ViewportScreen.h>
#include <AzTest/AzTest.h> #include <AzTest/AzTest.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h> #include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
#include <Tests/Utils/Printers.h> #include <Tests/Utils/Printers.h>
@ -169,4 +171,39 @@ namespace UnitTest
EXPECT_EQ(intersection, AZ::Intersect::SphereIsectTypes::ISECT_RAY_SPHERE_ISECT); EXPECT_EQ(intersection, AZ::Intersect::SphereIsectTypes::ISECT_RAY_SPHERE_ISECT);
} }
TEST_F(ViewportInteractionImplFixture, ViewportInteractionRequestsReturnsNewViewWhenItIsChanged)
{
// Given
const auto primaryViewTransform = AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation(
AZ::Matrix3x3::CreateRotationZ(AZ::DegToRad(90.0f)) * AZ::Matrix3x3::CreateRotationX(AZ::DegToRad(-45.0f)),
AZ::Vector3(-10.0f, -15.0f, 20.0f));
m_view->SetCameraTransform(primaryViewTransform);
AZ::RPI::ViewPtr secondaryView = AZ::RPI::View::CreateView(AZ::Name("SecondaryView"), AZ::RPI::View::UsageCamera);
const auto secondaryViewTransform = AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation(
AZ::Matrix3x3::CreateRotationZ(AZ::DegToRad(-90.0f)) * AZ::Matrix3x3::CreateRotationX(AZ::DegToRad(30.0f)),
AZ::Vector3(-50.0f, -25.0f, 10.0f));
secondaryView->SetCameraTransform(secondaryViewTransform);
// When
AZ::RPI::ViewportContextIdNotificationBus::Event(
TestViewportId, &AZ::RPI::ViewportContextIdNotificationBus::Events::OnViewportDefaultViewChanged, secondaryView);
// retrieve updated camera transform
AzFramework::CameraState cameraState;
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult(
cameraState, TestViewportId, &AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::GetCameraState);
const auto cameraMatrix = AzFramework::CameraTransform(cameraState);
const auto cameraTransform = AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation(
AZ::Matrix3x3::CreateFromMatrix4x4(cameraMatrix), cameraMatrix.GetTranslation());
// Then
// camera transform matches that of the secondary view
EXPECT_THAT(cameraTransform, IsClose(secondaryViewTransform));
}
} // namespace UnitTest } // namespace UnitTest

@ -12,6 +12,7 @@
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h> #include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h> #include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <Atom/RPI.Public/Material/Material.h> #include <Atom/RPI.Public/Material/Material.h>
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
#include <Atom/RPI.Reflect/Image/Image.h> #include <Atom/RPI.Reflect/Image/Image.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h> #include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
#include <Atom/RPI.Reflect/Material/MaterialFunctor.h> #include <Atom/RPI.Reflect/Material/MaterialFunctor.h>
@ -594,7 +595,7 @@ namespace MaterialEditor
MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(it->second.GetValue()); MaterialPropertyValue propertyValue = AtomToolsFramework::ConvertToRuntimeType(it->second.GetValue());
if (propertyValue.IsValid()) if (propertyValue.IsValid())
{ {
if (!AtomToolsFramework::ConvertToExportFormat(exportPath, propertyDefinition, propertyValue)) if (!AtomToolsFramework::ConvertToExportFormat(exportPath, propertyId.GetFullName(), propertyDefinition, propertyValue))
{ {
AZ_Error("MaterialDocument", false, "Material document property could not be converted: '%s' in '%s'.", propertyId.GetFullName().GetCStr(), m_absolutePath.c_str()); AZ_Error("MaterialDocument", false, "Material document property could not be converted: '%s' in '%s'.", propertyId.GetFullName().GetCStr(), m_absolutePath.c_str());
result = false; result = false;
@ -709,6 +710,8 @@ namespace MaterialEditor
return false; return false;
} }
const bool elevateWarnings = false;
// In order to support automation, general usability, and 'save as' functionality, the user must not have to wait // In order to support automation, general usability, and 'save as' functionality, the user must not have to wait
// for their JSON file to be cooked by the asset processor before opening or editing it. // for their JSON file to be cooked by the asset processor before opening or editing it.
// We need to reduce or remove dependency on the asset processor. In order to get around the bottleneck for now, // We need to reduce or remove dependency on the asset processor. In order to get around the bottleneck for now,
@ -716,7 +719,7 @@ namespace MaterialEditor
// Long term, the material document should not be concerned with assets at all. The viewport window should be the // Long term, the material document should not be concerned with assets at all. The viewport window should be the
// only thing concerned with assets or instances. // only thing concerned with assets or instances.
auto materialAssetResult = auto materialAssetResult =
m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, true, true, &m_sourceDependencies); m_materialSourceData.CreateMaterialAssetFromSourceData(Uuid::CreateRandom(), m_absolutePath, elevateWarnings, true, &m_sourceDependencies);
if (!materialAssetResult) if (!materialAssetResult)
{ {
AZ_Error("MaterialDocument", false, "Material asset could not be created from source data: '%s'.", m_absolutePath.c_str()); AZ_Error("MaterialDocument", false, "Material asset could not be created from source data: '%s'.", m_absolutePath.c_str());

@ -1353,9 +1353,8 @@ namespace AZ::AtomBridge
// if 2d draw need to project pos to screen first // if 2d draw need to project pos to screen first
AzFramework::TextDrawParameters params; AzFramework::TextDrawParameters params;
AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext();
const auto dpiScaleFactor = viewportContext->GetDpiScalingFactor();
params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works
params.m_position = AZ::Vector3(x * dpiScaleFactor, y * dpiScaleFactor, 1.0f); params.m_position = AZ::Vector3(x, y, 1.0f);
params.m_color = m_rendState.m_color; params.m_color = m_rendState.m_color;
params.m_scale = AZ::Vector2(size); params.m_scale = AZ::Vector2(size);
params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment

@ -134,7 +134,7 @@ namespace AZ
propertyValue = AZ::RPI::MaterialPropertyValue::FromAny(propertyOverrideItr->second); propertyValue = AZ::RPI::MaterialPropertyValue::FromAny(propertyOverrideItr->second);
} }
if (!AtomToolsFramework::ConvertToExportFormat(path, propertyDefinition, propertyValue)) if (!AtomToolsFramework::ConvertToExportFormat(path, propertyId.GetFullName(), propertyDefinition, propertyValue))
{ {
AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to export: %s", path.c_str()); AZ_Error("AZ::Render::EditorMaterialComponentUtil", false, "Failed to export: %s", path.c_str());
result = false; result = false;

@ -11,6 +11,7 @@
#include <Editor/EditorJointConfiguration.h> #include <Editor/EditorJointConfiguration.h>
#include <Source/EditorColliderComponent.h> #include <Source/EditorColliderComponent.h>
#include <Source/EditorRigidBodyComponent.h> #include <Source/EditorRigidBodyComponent.h>
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
namespace namespace
{ {
@ -213,7 +214,7 @@ namespace PhysX
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{ {
serializeContext->Class<EditorJointConfig>() serializeContext->Class<EditorJointConfig>()
->Version(4, &EditorJointConfig::VersionConverter) ->Version(5, &EditorJointConfig::VersionConverter)
->Field("Local Position", &EditorJointConfig::m_localPosition) ->Field("Local Position", &EditorJointConfig::m_localPosition)
->Field("Local Rotation", &EditorJointConfig::m_localRotation) ->Field("Local Rotation", &EditorJointConfig::m_localRotation)
->Field("Parent Entity", &EditorJointConfig::m_leadEntity) ->Field("Parent Entity", &EditorJointConfig::m_leadEntity)
@ -228,6 +229,12 @@ namespace PhysX
if (auto* editContext = serializeContext->GetEditContext()) if (auto* editContext = serializeContext->GetEditContext())
{ {
editContext->Enum<EditorJointConfig::DisplaySetupState>("Joint Display Setup State", "Options for displaying joint setup.")
->Value("Never", EditorJointConfig::DisplaySetupState::Never)
->Value("Selected", EditorJointConfig::DisplaySetupState::Selected)
->Value("Always", EditorJointConfig::DisplaySetupState::Always)
;
editContext->Class<PhysX::EditorJointConfig>( editContext->Class<PhysX::EditorJointConfig>(
"PhysX Joint Configuration", "") "PhysX Joint Configuration", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
@ -244,8 +251,11 @@ namespace PhysX
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorJointConfig::ValidateLeadEntityId) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorJointConfig::ValidateLeadEntityId)
->DataElement(0, &PhysX::EditorJointConfig::m_selfCollide, "Lead-Follower Collide" ->DataElement(0, &PhysX::EditorJointConfig::m_selfCollide, "Lead-Follower Collide"
, "When active, the lead and follower pair will collide with each other.") , "When active, the lead and follower pair will collide with each other.")
->DataElement(0, &PhysX::EditorJointConfig::m_displayJointSetup, "Display Setup in Viewport" ->DataElement(
, "Display joint setup in the viewport.") AZ::Edit::UIHandlers::ComboBox, &PhysX::EditorJointConfig::m_displayJointSetup, "Display Setup in Viewport"
, "Never = Not shown."
"Select = Show setup display when entity is selected."
"Always = Always show setup display.")
->Attribute(AZ::Edit::Attributes::ReadOnly, &EditorJointConfig::IsInComponentMode) ->Attribute(AZ::Edit::Attributes::ReadOnly, &EditorJointConfig::IsInComponentMode)
->DataElement(0, &PhysX::EditorJointConfig::m_selectLeadOnSnap, "Select Lead on Snap" ->DataElement(0, &PhysX::EditorJointConfig::m_selectLeadOnSnap, "Select Lead on Snap"
, "Select lead entity on snap to position in component mode.") , "Select lead entity on snap to position in component mode.")
@ -306,6 +316,23 @@ namespace PhysX
m_followerEntity); m_followerEntity);
} }
bool EditorJointConfig::ShowSetupDisplay() const
{
switch(m_displayJointSetup)
{
case DisplaySetupState::Always:
return true;
case DisplaySetupState::Selected:
{
bool showSetup = false;
AzToolsFramework::EditorEntityInfoRequestBus::EventResult(
showSetup, m_followerEntity, &AzToolsFramework::EditorEntityInfoRequests::IsSelected);
return showSetup;
}
}
return false;
}
bool EditorJointConfig::IsInComponentMode() const bool EditorJointConfig::IsInComponentMode() const
{ {
return m_inComponentMode; return m_inComponentMode;
@ -343,6 +370,31 @@ namespace PhysX
} }
} }
// convert m_displayJointSetup from a bool to the enum with the option Never,Selected,Always show joint setup helpers.
if (classElement.GetVersion() <= 4)
{
// get the current bool setting and remove it.
bool oldSetting = false;
const int displayJointSetupIndex = classElement.FindElement(AZ_CRC_CE("Display Debug"));
if (displayJointSetupIndex >= 0)
{
AZ::SerializeContext::DataElementNode& elementNode = classElement.GetSubElement(displayJointSetupIndex);
elementNode.GetData<bool>(oldSetting);
classElement.RemoveElement(displayJointSetupIndex);
}
//if the old setting was on set it to 'Selected'. otherwise 'Never'
if (oldSetting)
{
classElement.AddElementWithData(context, "Display Debug", EditorJointConfig::DisplaySetupState::Selected);
}
else
{
classElement.AddElementWithData(context, "Display Debug", EditorJointConfig::DisplaySetupState::Never);
}
}
return result; return result;
} }

@ -100,12 +100,21 @@ namespace PhysX
AZ_TYPE_INFO(EditorJointConfig, "{8A966D65-CA97-4786-A13C-ACAA519D97EA}"); AZ_TYPE_INFO(EditorJointConfig, "{8A966D65-CA97-4786-A13C-ACAA519D97EA}");
static void Reflect(AZ::ReflectContext* context); static void Reflect(AZ::ReflectContext* context);
enum class DisplaySetupState : AZ::u8
{
Never = 0,
Selected,
Always
};
void SetLeadEntityId(AZ::EntityId leadEntityId); void SetLeadEntityId(AZ::EntityId leadEntityId);
JointGenericProperties ToGenericProperties() const; JointGenericProperties ToGenericProperties() const;
JointComponentConfiguration ToGameTimeConfig() const; JointComponentConfiguration ToGameTimeConfig() const;
bool ShowSetupDisplay() const;
bool m_breakable = false; bool m_breakable = false;
bool m_displayJointSetup = false; DisplaySetupState m_displayJointSetup = DisplaySetupState::Selected;
bool m_inComponentMode = false; bool m_inComponentMode = false;
bool m_selectLeadOnSnap = true; bool m_selectLeadOnSnap = true;
bool m_selfCollide = false; bool m_selfCollide = false;
@ -129,3 +138,8 @@ namespace PhysX
}; };
} // namespace PhysX } // namespace PhysX
namespace AZ
{
AZ_TYPE_INFO_SPECIALIZE(PhysX::EditorJointConfig::DisplaySetupState, "{17EBE6BD-289A-4326-8A24-DCE3B7FEC51E}");
} // namespace AZ

@ -215,7 +215,7 @@ namespace PhysX
{ {
EditorJointComponent::DisplayEntityViewport(viewportInfo, debugDisplay); EditorJointComponent::DisplayEntityViewport(viewportInfo, debugDisplay);
if (!m_config.m_displayJointSetup && if (!m_config.ShowSetupDisplay() &&
!m_config.m_inComponentMode) !m_config.m_inComponentMode)
{ {
return; return;

@ -211,7 +211,7 @@ namespace PhysX
{ {
EditorJointComponent::DisplayEntityViewport(viewportInfo, debugDisplay); EditorJointComponent::DisplayEntityViewport(viewportInfo, debugDisplay);
if (!m_config.m_displayJointSetup && if (!m_config.ShowSetupDisplay() &&
!m_config.m_inComponentMode) !m_config.m_inComponentMode)
{ {
return; return;

Loading…
Cancel
Save