From 5fc4aeaf09c0aa29f5537c248cde5f166014bec1 Mon Sep 17 00:00:00 2001 From: hultonha Date: Mon, 12 Apr 2021 11:03:46 +0100 Subject: [PATCH 01/74] add alias for AZStd::vector before potential change --- Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h | 7 +++++-- Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h | 6 +++--- .../Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp | 4 +++- .../Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp | 4 ++-- .../Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h | 8 ++++---- Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp | 8 ++++---- Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h | 2 +- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h index f47c5c6b0e..5b8d384774 100644 --- a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h +++ b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h @@ -102,6 +102,9 @@ namespace WhiteBox //! Alias for a collection of faces. using Faces = AZStd::vector; + //! Underlying representation of the White Box mesh (serialized halfedge data). + using WhiteBoxMeshStream = AZStd::vector; + //! Represents the vertex handles to be used to form a new face. struct FaceVertHandles { @@ -729,7 +732,7 @@ namespace WhiteBox //! Take an input stream of bytes and create a white box mesh from the deserialized data. //! @return Will return false if any error was encountered during deserialization, true otherwise. //! @note A white box mesh must have been created first. - bool ReadMesh(WhiteBoxMesh& whiteBox, const AZStd::vector& input); + bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input); //! Take an input stream and create a white box mesh from the deserialized data. //! @return Will return false if any error was encountered during deserialization, true otherwise. @@ -738,7 +741,7 @@ namespace WhiteBox //! Take a white box mesh and write it out to a stream of bytes. //! @return Will return false if any error was encountered during serialization, true otherwise. - bool WriteMesh(const WhiteBoxMesh& whiteBox, AZStd::vector& output); + bool WriteMesh(const WhiteBoxMesh& whiteBox, WhiteBoxMeshStream& output); //! Clones the white box mesh object into a new mesh. //! @return Will return null if any error was encountered during serialization, otherwise the cloned mesh. diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h index f5915d033b..d25af2fed2 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAsset.h @@ -51,12 +51,12 @@ namespace WhiteBox return AZStd::move(m_mesh); } - void SetWhiteBoxData(AZStd::vector whiteBoxData) + void SetWhiteBoxData(Api::WhiteBoxMeshStream whiteBoxData) { m_whiteBoxData = AZStd::move(whiteBoxData); } - const AZStd::vector& GetWhiteBoxData() const + const Api::WhiteBoxMeshStream& GetWhiteBoxData() const { return m_whiteBoxData; } @@ -73,7 +73,7 @@ namespace WhiteBox } Api::WhiteBoxMeshPtr m_mesh; - AZStd::vector m_whiteBoxData; //! Data used for creating undo commands. + Api::WhiteBoxMeshStream m_whiteBoxData; //! Data used for creating undo commands. }; } // namespace Pipeline } // namespace WhiteBox diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp index a64c552bb6..72a754f05f 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp @@ -112,7 +112,9 @@ namespace WhiteBox const auto size = stream->GetLength(); - AZStd::vector whiteBoxData(size); + Api::WhiteBoxMeshStream whiteBoxData; + whiteBoxData.reserve(size); + stream->Read(size, whiteBoxData.data()); auto whiteBoxMesh = WhiteBox::Api::CreateWhiteBoxMesh(); diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp index ef11b8d47d..19cbc802dd 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.cpp @@ -29,12 +29,12 @@ namespace WhiteBox m_asset = asset; } - void WhiteBoxMeshAssetUndoCommand::SetUndoState(const AZStd::vector& undoState) + void WhiteBoxMeshAssetUndoCommand::SetUndoState(const Api::WhiteBoxMeshStream& undoState) { m_undoState = undoState; } - void WhiteBoxMeshAssetUndoCommand::SetRedoState(const AZStd::vector& redoState) + void WhiteBoxMeshAssetUndoCommand::SetRedoState(const Api::WhiteBoxMeshStream& redoState) { m_redoState = redoState; } diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h index eb657c5a85..3f6258c1b4 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetUndoCommand.h @@ -34,8 +34,8 @@ namespace WhiteBox ~WhiteBoxMeshAssetUndoCommand() override = default; void SetAsset(AZ::Data::Asset asset); - void SetUndoState(const AZStd::vector& undoState); - void SetRedoState(const AZStd::vector& redoState); + void SetUndoState(const Api::WhiteBoxMeshStream& undoState); + void SetRedoState(const Api::WhiteBoxMeshStream& redoState); // AzToolsFramework::UndoSystem::URSequencePoint ... void Undo() override; @@ -44,7 +44,7 @@ namespace WhiteBox protected: AZ::Data::Asset m_asset; - AZStd::vector m_undoState; - AZStd::vector m_redoState; + Api::WhiteBoxMeshStream m_undoState; + Api::WhiteBoxMeshStream m_redoState; }; } // namespace WhiteBox diff --git a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp index 49e713810e..fbab501e8f 100644 --- a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp +++ b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp @@ -3379,7 +3379,7 @@ namespace WhiteBox CalculatePlanarUVs(whiteBox); } - bool WriteMesh(const WhiteBoxMesh& whiteBox, AZStd::vector& output) + bool WriteMesh(const WhiteBoxMesh& whiteBox, WhiteBoxMeshStream& output) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); @@ -3403,7 +3403,7 @@ namespace WhiteBox return false; } - bool ReadMesh(WhiteBoxMesh& whiteBox, const AZStd::vector& input) + bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); @@ -3437,7 +3437,7 @@ namespace WhiteBox { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); - AZStd::vector clonedData; + WhiteBoxMeshStream clonedData; if (!WriteMesh(whiteBox, clonedData)) { return nullptr; @@ -3461,7 +3461,7 @@ namespace WhiteBox bool SaveToWbm(const WhiteBoxMesh& whiteBox, AZ::IO::GenericStream& stream) { - AZStd::vector buffer; + WhiteBoxMeshStream buffer; const bool success = WhiteBox::Api::WriteMesh(whiteBox, buffer); const auto bytesWritten = stream.Write(buffer.size(), buffer.data()); diff --git a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h index 5d7ac3b303..02b50a9407 100644 --- a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h +++ b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.h @@ -124,7 +124,7 @@ namespace WhiteBox AZStd::optional> m_renderMesh; //!< The render mesh to use for the White Box mesh data. AZ::Transform m_worldFromLocal = AZ::Transform::CreateIdentity(); //!< Cached world transform of Entity. - AZStd::vector m_whiteBoxData; //!< Serialized White Box mesh data. + Api::WhiteBoxMeshStream m_whiteBoxData; //!< Serialized White Box mesh data. //! Holds a reference to an optional WhiteBoxMeshAsset and manages the lifecycle of adding/removing an asset. EditorWhiteBoxMeshAsset* m_editorMeshAsset = nullptr; AZStd::optional m_worldAabb; //!< Cached world aabb (used for selection/view determination). From 8ee92978f4e96a91b3ef1350d009b2ddaa45bbca Mon Sep 17 00:00:00 2001 From: greerdv Date: Mon, 12 Apr 2021 13:07:40 +0100 Subject: [PATCH 02/74] setting max value for scale --- .../AzCore/AzCore/Component/NonUniformScaleBus.h | 3 --- Code/Framework/AzCore/AzCore/Math/Transform.h | 7 +++++++ .../AzFramework/Components/NonUniformScaleComponent.cpp | 5 +++-- .../ToolsComponents/EditorNonUniformScaleComponent.cpp | 9 ++++++--- .../ToolsComponents/TransformComponent.cpp | 1 - .../ToolsComponents/TransformScalePropertyHandler.cpp | 5 +++-- .../EditorTransformComponentSelection.cpp | 2 +- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Component/NonUniformScaleBus.h b/Code/Framework/AzCore/AzCore/Component/NonUniformScaleBus.h index af2fe20a50..9b52fc1794 100644 --- a/Code/Framework/AzCore/AzCore/Component/NonUniformScaleBus.h +++ b/Code/Framework/AzCore/AzCore/Component/NonUniformScaleBus.h @@ -19,9 +19,6 @@ namespace AZ { class Vector3; - //! Do not allow the scale to be zero to avoid problems with inverting scale. - static constexpr float MinNonUniformScale = 1e-3f; - using NonUniformScaleChangedEvent = AZ::Event; //! Requests for working with non-uniform scale. diff --git a/Code/Framework/AzCore/AzCore/Math/Transform.h b/Code/Framework/AzCore/AzCore/Math/Transform.h index 6c96a9a6a6..eb1a12a912 100644 --- a/Code/Framework/AzCore/AzCore/Math/Transform.h +++ b/Code/Framework/AzCore/AzCore/Math/Transform.h @@ -38,6 +38,13 @@ namespace AZ bool CompareValueData(const void* lhs, const void* rhs) override; }; + //! Limits for transform scale values. + //! The scale should not be zero to avoid problems with inverting. + //! @{ + static constexpr float MinTransformScale = 1e-2f; + static constexpr float MaxTransformScale = 1e9f; + //! @} + //! The basic transformation class, represented using a quaternion rotation, vector scale and vector translation. //! By design, cannot represent skew transformations. class Transform diff --git a/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.cpp b/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.cpp index 630dbb0322..095d986fa1 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -81,13 +82,13 @@ namespace AzFramework void NonUniformScaleComponent::SetScale(const AZ::Vector3& scale) { - if (scale.GetMinElement() >= AZ::MinNonUniformScale) + if (scale.GetMinElement() >= AZ::MinTransformScale && scale.GetMaxElement() <= AZ::MaxTransformScale) { m_scale = scale; } else { - AZ::Vector3 clampedScale = scale.GetMax(AZ::Vector3(AZ::MinNonUniformScale)); + AZ::Vector3 clampedScale = scale.GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale)); AZ_Warning("Non-uniform Scale Component", false, "SetScale value was clamped from %s to %s for entity %s", AZ::ToString(scale).c_str(), AZ::ToString(clampedScale).c_str(), GetEntity()->GetName().c_str()); m_scale = clampedScale; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp index 7c4d72dbbf..5e928a382a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace AzToolsFramework @@ -44,7 +45,9 @@ namespace AzToolsFramework ->DataElement( AZ::Edit::UIHandlers::Default, &EditorNonUniformScaleComponent::m_scale, "Non-uniform Scale", "Non-uniform scale for this entity only (does not propagate through hierarchy)") - ->Attribute(AZ::Edit::Attributes::Min, AZ::MinNonUniformScale) + ->Attribute(AZ::Edit::Attributes::Min, AZ::MinTransformScale) + ->Attribute(AZ::Edit::Attributes::Max, AZ::MaxTransformScale) + ->Attribute(AZ::Edit::Attributes::Step, 0.1f) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorNonUniformScaleComponent::OnScaleChanged) ; } @@ -106,13 +109,13 @@ namespace AzToolsFramework void EditorNonUniformScaleComponent::SetScale(const AZ::Vector3& scale) { - if (scale.GetMinElement() >= AZ::MinNonUniformScale) + if (scale.GetMinElement() >= AZ::MinTransformScale && scale.GetMaxElement() <= AZ::MaxTransformScale) { m_scale = scale; } else { - AZ::Vector3 clampedScale = scale.GetMax(AZ::Vector3(AZ::MinNonUniformScale)); + AZ::Vector3 clampedScale = scale.GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale)); AZ_Warning("Editor Non-uniform Scale Component", false, "SetScale value was clamped from %s to %s for entity %s", AZ::ToString(scale).c_str(), AZ::ToString(clampedScale).c_str(), GetEntity()->GetName().c_str()); m_scale = clampedScale; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp index 2ceb97adfd..7ce11e5957 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp @@ -1276,7 +1276,6 @@ namespace AzToolsFramework Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::NotPushableOnSliceRoot)-> DataElement(TransformScaleHandler, &EditorTransform::m_scale, "Scale", "Local Scale")-> Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Min, 0.01f)-> Attribute(AZ::Edit::Attributes::ReadOnly, &EditorTransform::m_locked) ; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp index 0105d9bbad..94d0113bcf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformScalePropertyHandler.cpp @@ -12,6 +12,7 @@ #include "AzToolsFramework_precompiled.h" #include +#include #include namespace AzToolsFramework @@ -36,8 +37,8 @@ namespace AzToolsFramework AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestWrite, newCtrl); }); - newCtrl->setMinimum(0.01f); - newCtrl->setMaximum(std::numeric_limits::max()); + newCtrl->setMinimum(AZ::MinTransformScale); + newCtrl->setMaximum(AZ::MaxTransformScale); return newCtrl; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 27222e9aac..83632708d9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -1603,7 +1603,7 @@ namespace AzToolsFramework const AZ::Vector3 uniformScale = AZ::Vector3(action.m_start.m_sign * sumVectorElements(action.LocalScaleOffset())); const AZ::Vector3 scale = (AZ::Vector3::CreateOne() + - (uniformScale / initialScale)).GetMax(AZ::Vector3(0.01f)); + (uniformScale / initialScale)).GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale)); const AZ::Transform scaleTransform = AZ::Transform::CreateScale(scale); if (action.m_modifiers.Alt()) From a99786fe5919d977d9bc762aef9e4c92a5853d6b Mon Sep 17 00:00:00 2001 From: greerdv Date: Tue, 13 Apr 2021 09:00:33 +0100 Subject: [PATCH 03/74] fixing bug with visibility aabb for non-uniformly scaled polygon prism at activation --- Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp b/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp index 28056c6e60..89c5028e93 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/PolygonPrismShape.cpp @@ -217,6 +217,7 @@ namespace LmbrCentral AZ::TransformBus::EventResult(m_currentTransform, entityId, &AZ::TransformBus::Events::GetWorldTM); m_currentNonUniformScale = AZ::Vector3::CreateOne(); AZ::NonUniformScaleRequestBus::EventResult(m_currentNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale); + m_polygonPrism->SetNonUniformScale(m_currentNonUniformScale); m_intersectionDataCache.InvalidateCache(InvalidateShapeCacheReason::ShapeChange); AZ::TransformNotificationBus::Handler::BusConnect(entityId); From 87a3dfc968d6b8debf53d58bb4c5a429ffb2adc4 Mon Sep 17 00:00:00 2001 From: greerdv Date: Tue, 13 Apr 2021 09:04:13 +0100 Subject: [PATCH 04/74] fixing bug in editor bodies for rigid bodies with non-uniformly scaled asset colliders with position offsets --- Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp index eff1997473..d5ce38d389 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp @@ -36,7 +36,7 @@ namespace PhysX const bool hasNonUniformScaleComponent = (AZ::NonUniformScaleRequestBus::FindFirstHandler(entity->GetId()) != nullptr); - const AZStd::vector colliders = entity->FindComponents(); + const AZStd::vector colliders = entity->FindComponents(); for (const EditorColliderComponent* collider : colliders) { const EditorProxyShapeConfig& shapeConfigurationProxy = collider->GetShapeConfiguration(); @@ -45,12 +45,14 @@ namespace PhysX continue; } - const Physics::ColliderConfiguration colliderConfiguration = collider->GetColliderConfigurationScaled(); + const Physics::ColliderConfiguration colliderConfigurationScaled = collider->GetColliderConfigurationScaled(); + const Physics::ColliderConfiguration colliderConfigurationUnscaled = collider->GetColliderConfiguration(); + if (shapeConfigurationProxy.IsAssetConfig()) { AZStd::vector> shapes; Utils::GetShapesFromAsset(shapeConfigurationProxy.m_physicsAsset.m_configuration, - colliderConfiguration, hasNonUniformScaleComponent, shapeConfigurationProxy.m_subdivisionLevel, shapes); + colliderConfigurationUnscaled, hasNonUniformScaleComponent, shapeConfigurationProxy.m_subdivisionLevel, shapes); for (const auto& shape : shapes) { @@ -64,7 +66,7 @@ namespace PhysX if (!hasNonUniformScaleComponent) { AZStd::shared_ptr shape = AZ::Interface::Get()->CreateShape( - colliderConfiguration, shapeConfiguration); + colliderConfigurationScaled, shapeConfiguration); AZ_Assert(shape, "CreateEditorWorldRigidBody: Shape must not be null!"); if (shape) { @@ -73,7 +75,6 @@ namespace PhysX } else { - const Physics::ColliderConfiguration colliderConfigurationUnscaled = collider->GetColliderConfiguration(); auto convexConfig = Utils::CreateConvexFromPrimitive(colliderConfigurationUnscaled, shapeConfiguration, shapeConfigurationProxy.m_subdivisionLevel, shapeConfiguration.m_scale); auto colliderConfigurationNoOffset = colliderConfigurationUnscaled; @@ -377,7 +378,7 @@ namespace PhysX configuration.m_kinematic = m_config.m_kinematic; configuration.m_colliderAndShapeData = Internal::GetCollisionShapes(GetEntity()); - if (auto* sceneInterface = AZ::Interface::Get()) + if (auto* sceneInterface = AZ::Interface::Get()) { m_rigidBodyHandle = sceneInterface->AddSimulatedBody(m_editorSceneHandle, &configuration); m_editorBody = azdynamic_cast(sceneInterface->GetSimulatedBodyFromHandle(m_editorSceneHandle, m_rigidBodyHandle)); From 90e52d69bc465519707c89d22c0568882fcc6637 Mon Sep 17 00:00:00 2001 From: greerdv Date: Tue, 13 Apr 2021 10:50:07 +0100 Subject: [PATCH 05/74] fixing bug with subdivision level for runtime asset colliders and adding caching for collider aabbs --- .../Physics/ShapeConfiguration.cpp | 1 + .../AzFramework/Physics/ShapeConfiguration.h | 1 + .../Code/Source/BaseColliderComponent.cpp | 7 +++---- .../Code/Source/EditorColliderComponent.cpp | 20 ++++++++++++++----- .../Code/Source/EditorColliderComponent.h | 2 ++ 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp index 44c24758f3..f01e42a443 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp +++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp @@ -142,6 +142,7 @@ namespace Physics ->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset) ->Field("AssetScale", &PhysicsAssetShapeConfiguration::m_assetScale) ->Field("UseMaterialsFromAsset", &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset) + ->Field("SubdivisionLevel", &PhysicsAssetShapeConfiguration::m_subdivisionLevel) ; if (auto editContext = serializeContext->GetEditContext()) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h index 8afe6851b7..b3d04a10c9 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.h @@ -141,6 +141,7 @@ namespace Physics AZ::Data::Asset m_asset{ AZ::Data::AssetLoadBehavior::PreLoad }; AZ::Vector3 m_assetScale = AZ::Vector3::CreateOne(); bool m_useMaterialsFromAsset = true; + AZ::u8 m_subdivisionLevel = 4; ///< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling. }; class NativeShapeConfiguration : public ShapeConfiguration diff --git a/Gems/PhysX/Code/Source/BaseColliderComponent.cpp b/Gems/PhysX/Code/Source/BaseColliderComponent.cpp index f4bc86ef93..c67cc105d8 100644 --- a/Gems/PhysX/Code/Source/BaseColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/BaseColliderComponent.cpp @@ -330,10 +330,9 @@ namespace PhysX } const bool hasNonUniformScale = (AZ::NonUniformScaleRequestBus::FindFirstHandler(GetEntityId()) != nullptr); - // the value for the subdivision level doesn't matter in the runtime, because any approximation of primitives will already have - // happened in the editor, so can pass an arbitrary value here - AZ::u8 subdivisionLevel = 0; - Utils::GetShapesFromAsset(physicsAssetConfiguration, componentColliderConfiguration, hasNonUniformScale, subdivisionLevel, m_shapes); + AZ::u8 subdivisionLevel = physicsAssetConfiguration.m_subdivisionLevel; + Utils::GetShapesFromAsset(physicsAssetConfiguration, componentColliderConfiguration, hasNonUniformScale, + physicsAssetConfiguration.m_subdivisionLevel, m_shapes); return true; } diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index 974ce23810..8c31746931 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -513,6 +513,8 @@ namespace PhysX break; case Physics::ShapeType::PhysicsAsset: colliderComponent = gameEntity->CreateComponent(); + + m_shapeConfiguration.m_physicsAsset.m_configuration.m_subdivisionLevel = m_shapeConfiguration.m_subdivisionLevel; colliderComponent->SetShapeConfigurationList({ AZStd::make_pair(sharedColliderConfig, AZStd::make_shared(m_shapeConfiguration.m_physicsAsset.m_configuration)) }); @@ -560,6 +562,8 @@ namespace PhysX void EditorColliderComponent::CreateStaticEditorCollider() { + m_cachedAabbDirty = true; + // Don't create static rigid body in the editor if current entity components // don't allow creation of runtime static rigid body component if (!StaticRigidBodyUtils::CanCreateRuntimeComponent(*GetEntity())) @@ -1014,11 +1018,17 @@ namespace PhysX // PhysX::ColliderShapeBus AZ::Aabb EditorColliderComponent::GetColliderShapeAabb() { - return PhysX::Utils::GetColliderAabb(GetWorldTM() - , m_hasNonUniformScale - , m_shapeConfiguration.m_subdivisionLevel - , m_shapeConfiguration.GetCurrent() - , m_configuration); + if (m_cachedAabbDirty) + { + m_cachedAabb = PhysX::Utils::GetColliderAabb(GetWorldTM() + , m_hasNonUniformScale + , m_shapeConfiguration.m_subdivisionLevel + , m_shapeConfiguration.GetCurrent() + , m_configuration); + m_cachedAabbDirty = false; + } + + return m_cachedAabb; } void EditorColliderComponent::UpdateShapeConfigurationScale() diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.h b/Gems/PhysX/Code/Source/EditorColliderComponent.h index 65c7a9c67f..f179525802 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.h +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.h @@ -261,6 +261,8 @@ namespace PhysX bool m_hasNonUniformScale = false; //!< Whether there is a non-uniform scale component on this entity. AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne(); //!< Caches the current non-uniform scale. mutable AZStd::optional m_scaledPrimitive; //!< Approximation for non-uniformly scaled primitive. + AZ::Aabb m_cachedAabb = AZ::Aabb::CreateNull(); //!< Cache the Aabb to avoid recalculating it. + bool m_cachedAabbDirty = true; //!< Track whether the cached Aabb needs to be recomputed. AZ::ComponentDescriptor::StringWarningArray m_componentWarnings; }; From 8846e159e09694d16af388dec6b6abb7c412d1c6 Mon Sep 17 00:00:00 2001 From: hultonha Date: Tue, 13 Apr 2021 11:54:22 +0100 Subject: [PATCH 06/74] Add new ByteStream serializer to support storing binary data in json (for now) --- .../Json/ByteStreamSerializer.cpp | 99 +++++++++++++++++++ .../Serialization/Json/ByteStreamSerializer.h | 38 +++++++ .../Json/JsonSystemComponent.cpp | 3 + .../AzCore/AzCore/azcore_files.cmake | 2 + 4 files changed, 142 insertions(+) create mode 100644 Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp create mode 100644 Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.h diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp new file mode 100644 index 0000000000..59c2d1b7e0 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp @@ -0,0 +1,99 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include "ByteStreamSerializer.h" + +#include +#include +#include + +namespace AZ +{ + namespace ByteSerializerInternal + { + static JsonSerializationResult::Result Load(void* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context) + { + using JsonSerializationResult::Outcomes; + using JsonSerializationResult::Tasks; + + AZ_Assert(outputValue, "Expected a valid pointer to load from json value."); + + switch (inputValue.GetType()) + { + case rapidjson::kStringType: { + JsonByteStream* valAsByteStream = reinterpret_cast(outputValue); + JsonByteStream buffer; + buffer.resize(inputValue.GetStringLength()); + AZStd::copy(inputValue.GetString(), inputValue.GetString() + inputValue.GetStringLength(), buffer.begin()); + *valAsByteStream = AZStd::move(buffer); + return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream."); + } + case rapidjson::kArrayType: + case rapidjson::kObjectType: + case rapidjson::kNullType: + case rapidjson::kFalseType: + case rapidjson::kTrueType: + case rapidjson::kNumberType: + return context.Report( + Tasks::ReadField, Outcomes::Unsupported, + "Unsupported type. ByteStream values cannot be read from arrays, objects, nulls, booleans or numbers."); + default: + return context.Report(Tasks::ReadField, Outcomes::Unknown, "Unknown json type encountered for ByteStream value."); + } + } + + static JsonSerializationResult::Result StoreWithDefault( + rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, JsonSerializerContext& context) + { + using JsonSerializationResult::Outcomes; + using JsonSerializationResult::Tasks; + + const JsonByteStream& valAsByteStream = *reinterpret_cast(inputValue); + if (context.ShouldKeepDefaults() || !defaultValue || + (valAsByteStream != *reinterpret_cast(defaultValue))) + { + outputValue.SetString( + reinterpret_cast(valAsByteStream.data()), aznumeric_caster(valAsByteStream.size()), + context.GetJsonAllocator()); + return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored."); + } + + return context.Report(Tasks::WriteValue, Outcomes::DefaultsUsed, "Default ByteStream used."); + } + } // namespace ByteSerializerInternal + + AZ_CLASS_ALLOCATOR_IMPL(JsonByteStreamSerializer, SystemAllocator, 0); + + JsonSerializationResult::Result JsonByteStreamSerializer::Load( + void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonDeserializerContext& context) + { + AZ_Assert( + azrtti_typeid() == outputValueTypeId, + "Unable to deserialize AZStd::vector> to json because the provided type is %s", + outputValueTypeId.ToString().c_str()); + + return ByteSerializerInternal::Load(outputValue, inputValue, context); + } + + JsonSerializationResult::Result JsonByteStreamSerializer::Store( + rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId, + JsonSerializerContext& context) + { + AZ_Assert( + azrtti_typeid() == valueTypeId, + "Unable to serialize AZStd::vector to json because the provided type is %s", + valueTypeId.ToString().c_str()); + + return ByteSerializerInternal::StoreWithDefault(outputValue, inputValue, defaultValue, context); + } +} // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.h new file mode 100644 index 0000000000..4f01e28319 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.h @@ -0,0 +1,38 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#pragma once + +#include +#include + +namespace AZ +{ + using JsonByteStream = AZStd::vector; //!< Alias for AZStd::vector. + + //! Serialize a stream of bytes (usually binary data) as a json string value. + //! @note Related to GenericClassByteStream (part of SerializeGenericTypeInfo> - see AZStdContainers.inl for more + //! details). + class JsonByteStreamSerializer : public BaseJsonSerializer + { + public: + AZ_RTTI(JsonByteStreamSerializer, "{30F0EA5A-CD13-4BA7-BAE1-D50D851CAC45}", BaseJsonSerializer); + AZ_CLASS_ALLOCATOR_DECL; + + JsonSerializationResult::Result Load( + void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue, + JsonDeserializerContext& context) override; + JsonSerializationResult::Result Store( + rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, + JsonSerializerContext& context) override; + }; +} // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp index e33466d8dc..e5a1f5e6bb 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,8 @@ namespace AZ jsonContext->Serializer()->HandlesType(); jsonContext->Serializer()->HandlesType(); + jsonContext->Serializer()->HandlesType>(); + jsonContext->Serializer() ->HandlesType() ->HandlesType() diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index 97b86f2432..e100b240c2 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -505,6 +505,8 @@ set(FILES Serialization/Json/BasicContainerSerializer.cpp Serialization/Json/BoolSerializer.h Serialization/Json/BoolSerializer.cpp + Serialization/Json/ByteStreamSerializer.h + Serialization/Json/ByteStreamSerializer.cpp Serialization/Json/CastingHelpers.h Serialization/Json/DoubleSerializer.h Serialization/Json/DoubleSerializer.cpp From 063b8a6d5476bdba1077703c6825d6c437c335a1 Mon Sep 17 00:00:00 2001 From: hultonha Date: Tue, 13 Apr 2021 12:16:55 +0100 Subject: [PATCH 07/74] update some reinterpret_cast calls to static_cast --- .../AzCore/Serialization/Json/ByteStreamSerializer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp index 59c2d1b7e0..2da71ba68a 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp @@ -30,7 +30,7 @@ namespace AZ switch (inputValue.GetType()) { case rapidjson::kStringType: { - JsonByteStream* valAsByteStream = reinterpret_cast(outputValue); + JsonByteStream* valAsByteStream = static_cast(outputValue); JsonByteStream buffer; buffer.resize(inputValue.GetStringLength()); AZStd::copy(inputValue.GetString(), inputValue.GetString() + inputValue.GetStringLength(), buffer.begin()); @@ -57,9 +57,9 @@ namespace AZ using JsonSerializationResult::Outcomes; using JsonSerializationResult::Tasks; - const JsonByteStream& valAsByteStream = *reinterpret_cast(inputValue); + const JsonByteStream& valAsByteStream = *static_cast(inputValue); if (context.ShouldKeepDefaults() || !defaultValue || - (valAsByteStream != *reinterpret_cast(defaultValue))) + (valAsByteStream != *static_cast(defaultValue))) { outputValue.SetString( reinterpret_cast(valAsByteStream.data()), aznumeric_caster(valAsByteStream.size()), From 5050de260472c4db69e440008111824f64a0d565 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Tue, 13 Apr 2021 15:05:05 -0700 Subject: [PATCH 08/74] Adding "Open Material Editor" action to Material Component slot context menu --- .../Code/Source/Material/EditorMaterialComponentSlot.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 1a41594b5a..5c22a0974e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -172,6 +172,10 @@ namespace AZ { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, sourcePath); } + else + { + EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); + } } void EditorMaterialComponentSlot::Clear() @@ -273,6 +277,8 @@ namespace AZ QAction* action = nullptr; + menu.addAction("Open Material Editor", [this]() { OpenMaterialEditor(); }); + action = menu.addAction("Clear", [this]() { Clear(); }); action->setEnabled(m_materialAsset.GetId().IsValid() || !m_propertyOverrides.empty() || !m_matModUvOverrides.empty()); From ca3df5d6c8f89edb1cfa4c1d8e3ca5a463af6e26 Mon Sep 17 00:00:00 2001 From: karlberg Date: Tue, 13 Apr 2021 20:24:08 -0700 Subject: [PATCH 09/74] Various bug fixes to get entity replication working --- .../AzCore/AzCore/Component/TransformBus.h | 2 +- .../DataStructures/FixedSizeBitset.h | 3 + .../DataStructures/FixedSizeVectorBitset.inl | 12 +-- .../Serialization/AzContainerSerializers.h | 10 +-- Gems/Multiplayer/Code/Include/IMultiplayer.h | 16 ++++ .../Source/AutoGen/AutoComponent_Header.jinja | 31 ++++---- .../Source/AutoGen/AutoComponent_Source.jinja | 66 +++++++++------- .../LocalPredictionPlayerInputComponent.cpp | 1 - .../Components/MultiplayerComponent.cpp | 8 +- .../Source/Components/MultiplayerComponent.h | 8 +- .../Components/MultiplayerController.cpp | 5 ++ .../Source/Components/MultiplayerController.h | 4 + .../Components/NetworkTransformComponent.cpp | 78 ++++++++++++++++++- .../Components/NetworkTransformComponent.h | 32 ++++++-- .../ClientToServerConnectionData.cpp | 59 ++++++++++++++ .../ClientToServerConnectionData.h | 47 +++++++++++ .../ClientToServerConnectionData.inl | 19 +++++ .../Source/ConnectionData/IConnectionData.h | 1 + .../Source/MultiplayerSystemComponent.cpp | 52 ++++++++----- .../Code/Source/MultiplayerSystemComponent.h | 2 +- .../EntityReplicationManager.cpp | 37 +++++---- .../EntityReplicationManager.h | 3 +- .../EntityReplication/EntityReplicator.cpp | 6 +- .../NetworkEntity/NetworkEntityManager.cpp | 21 +++-- .../Source/NetworkTime/RewindableObject.inl | 11 +-- .../NullReplicationWindow.cpp | 47 +++++++++++ .../NullReplicationWindow.h | 38 +++++++++ .../ServerToClientReplicationWindow.cpp | 6 +- Gems/Multiplayer/Code/multiplayer_files.cmake | 5 ++ 29 files changed, 494 insertions(+), 136 deletions(-) create mode 100644 Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp create mode 100644 Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h create mode 100644 Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl create mode 100644 Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.cpp create mode 100644 Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h diff --git a/Code/Framework/AzCore/AzCore/Component/TransformBus.h b/Code/Framework/AzCore/AzCore/Component/TransformBus.h index b0e617f220..2003b949e2 100644 --- a/Code/Framework/AzCore/AzCore/Component/TransformBus.h +++ b/Code/Framework/AzCore/AzCore/Component/TransformBus.h @@ -26,7 +26,7 @@ namespace AZ { class Transform; - using TransformChangedEvent = Event; + using TransformChangedEvent = Event; using ParentChangedEvent = Event; diff --git a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h index 21e12cd305..a91f42b3a0 100644 --- a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h +++ b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h @@ -114,6 +114,9 @@ namespace AzNetworking void ClearUnusedBits(); ContainerType m_container; + + template + friend class FixedSizeVectorBitset; }; } diff --git a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeVectorBitset.inl b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeVectorBitset.inl index a8aceb4dd5..038e68d1d0 100644 --- a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeVectorBitset.inl +++ b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeVectorBitset.inl @@ -192,19 +192,11 @@ namespace AzNetworking template inline void FixedSizeVectorBitset::ClearUnusedBits() { - constexpr ElementType AllOnes = static_cast(~0); - const ElementType LastUsedBits = (GetSize() % BitsetType::ElementTypeBits); -#pragma warning(push) -#pragma warning(disable : 4293) // shift count negative or too big, undefined behaviour -#pragma warning(disable : 6326) // constant constant comparison - const ElementType ShiftAmount = (LastUsedBits == 0) ? 0 : BitsetType::ElementTypeBits - LastUsedBits; - const ElementType ClearBitMask = AllOnes >> ShiftAmount; -#pragma warning(pop) uint32_t usedElementSize = (GetSize() + BitsetType::ElementTypeBits - 1) / BitsetType::ElementTypeBits; - for (uint32_t i = usedElementSize + 1; i < CAPACITY; ++i) + for (uint32_t i = usedElementSize + 1; i < BitsetType::ElementCount; ++i) { m_bitset.GetContainer()[i] = 0; } - m_bitset.GetContainer()[m_bitset.GetContainer().size() - 1] &= ClearBitMask; + m_bitset.ClearUnusedBits(); } } diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/AzContainerSerializers.h b/Code/Framework/AzNetworking/AzNetworking/Serialization/AzContainerSerializers.h index 70dc7847d2..a43a09165c 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/AzContainerSerializers.h +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/AzContainerSerializers.h @@ -270,7 +270,7 @@ namespace AzNetworking value.StoreToFloat3(values); serializer.Serialize(values[0], "xValue"); serializer.Serialize(values[1], "yValue"); - serializer.Serialize(values[1], "zValue"); + serializer.Serialize(values[2], "zValue"); value = AZ::Vector3::CreateFromFloat3(values); return serializer.IsValid(); } @@ -285,8 +285,8 @@ namespace AzNetworking value.StoreToFloat4(values); serializer.Serialize(values[0], "xValue"); serializer.Serialize(values[1], "yValue"); - serializer.Serialize(values[1], "zValue"); - serializer.Serialize(values[1], "wValue"); + serializer.Serialize(values[2], "zValue"); + serializer.Serialize(values[3], "wValue"); value = AZ::Vector4::CreateFromFloat4(values); return serializer.IsValid(); } @@ -301,8 +301,8 @@ namespace AzNetworking value.StoreToFloat4(values); serializer.Serialize(values[0], "xValue"); serializer.Serialize(values[1], "yValue"); - serializer.Serialize(values[1], "zValue"); - serializer.Serialize(values[1], "wValue"); + serializer.Serialize(values[2], "zValue"); + serializer.Serialize(values[3], "wValue"); value = AZ::Quaternion::CreateFromFloat4(values); return serializer.IsValid(); } diff --git a/Gems/Multiplayer/Code/Include/IMultiplayer.h b/Gems/Multiplayer/Code/Include/IMultiplayer.h index fd2b0e6cce..94744dbb54 100644 --- a/Gems/Multiplayer/Code/Include/IMultiplayer.h +++ b/Gems/Multiplayer/Code/Include/IMultiplayer.h @@ -95,4 +95,20 @@ namespace Multiplayer private: MultiplayerStats m_stats; }; + + inline const char* GetEnumString(MultiplayerAgentType value) + { + switch (value) + { + case MultiplayerAgentType::Uninitialized: + return "Uninitialized"; + case MultiplayerAgentType::Client: + return "Client"; + case MultiplayerAgentType::ClientServer: + return "ClientServer"; + case MultiplayerAgentType::DedicatedServer: + return "DedicatedServer"; + } + return "INVALID"; + } } diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja index 33509a61c7..f5774b07c0 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja @@ -33,22 +33,20 @@ const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const; #} {% macro DeclareNetworkPropertySetter(Property) %} {% set PropertyName = UpperFirst(Property.attrib['Name']) %} -{% if Property.attrib['IsPredictable'] | booleanTrue %} -{% if Property.attrib['Container'] == 'Array' %} -void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value); -{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index); -{% elif Property.attrib['Container'] == 'Vector' %} -void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value); -{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index); -bool {{ PropertyName }}PushBack(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value); -bool {{ PropertyName }}PopBack(const Multiplayer::NetworkInput&); -void {{ PropertyName }}Clear(const Multiplayer::NetworkInput&); -{% elif Property.attrib['Container'] == 'Object' %} -void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value); -{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&); -{% else %} -void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value); -{% endif %} +{% if Property.attrib['Container'] == 'Array' %} +void Set{{ PropertyName }}(int32_t index, const {{ Property.attrib['Type'] }}& value); +{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(int32_t index); +{% elif Property.attrib['Container'] == 'Vector' %} +void Set{{ PropertyName }}(int32_t index, const {{ Property.attrib['Type'] }}& value); +{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(int32_t index); +bool {{ PropertyName }}PushBack(const {{ Property.attrib['Type'] }}& value); +bool {{ PropertyName }}PopBack(); +void {{ PropertyName }}Clear(); +{% elif Property.attrib['Container'] == 'Object' %} +void Set{{ PropertyName }}(const {{ Property.attrib['Type'] }}& value); +{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(); +{% else %} +void Set{{ PropertyName }}(const {{ Property.attrib['Type'] }}& value); {% endif %} {% endmacro %} {# @@ -417,6 +415,7 @@ namespace {{ Component.attrib['Namespace'] }} static const Multiplayer::NetComponentId s_componentId = static_cast({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }}); static void Reflect(AZ::ReflectContext* context); + static void ReflectToEditContext(AZ::ReflectContext* context); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index 5dc470fcd1..aee15bc190 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -73,18 +73,17 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}AddEvent(AZ::Even {# #} -{% macro DefineNetworkPropertyPredictableSet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) %} -{% if Property.attrib['IsPredictable'] | booleanTrue %} -{% if Property.attrib['Container'] == 'Array' %} -void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, int32_t index, const {{ Property.attrib['Type'] }}& value) +{% macro DefineNetworkPropertySet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) %} +{% if Property.attrib['Container'] == 'Array' %} +void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index, const {{ Property.attrib['Type'] }}& value) { if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index] != value) { - Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand, index) = value; + Modify{{ UpperFirst(Property.attrib['Name']) }}(index) = value; } } -{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, int32_t index) +{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(int32_t index) { int32_t bitIndex = index + static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }}); GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true); @@ -92,16 +91,16 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index]; } -{% elif Property.attrib['Container'] == 'Vector' %} -void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, int32_t index, const {{ Property.attrib['Type'] }}& value) +{% elif Property.attrib['Container'] == 'Vector' %} +void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index, const {{ Property.attrib['Type'] }}& value) { if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index] != value) { - Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand, index) = value; + Modify{{ UpperFirst(Property.attrib['Name']) }}(index) = value; } } -{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, int32_t index) +{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(int32_t index) { int32_t bitIndex = index + static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }}); GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true); @@ -109,7 +108,7 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}[index]; } -bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const Multiplayer::NetworkInput& inputCommand, const {{ Property.attrib['Type'] }} &value) +bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const {{ Property.attrib['Type'] }} &value) { int32_t indexToSet = GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.GetSize(); GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.PushBack(value); @@ -134,24 +133,24 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}Clear(const Multi GetParent().MarkDirty(); } -{% elif Property.attrib['Container'] == 'Object' %} -void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput& inputCommand, const {{ Property.attrib['Type'] }}& value) +{% elif Property.attrib['Container'] == 'Object' %} +void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Property.attrib['Type'] }}& value) { if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }} != value) { - Modify{{ UpperFirst(Property.attrib['Name']) }}(inputCommand) = value; + Modify{{ UpperFirst(Property.attrib['Name']) }}() = value; } } -{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&) +{{ Property.attrib['Type'] }}& {{ ClassName }}::Modify{{ UpperFirst(Property.attrib['Name']) }}() { GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}), true); GetParent().MarkDirty(); return GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}{% if Property.attrib['IsRewindable']|booleanTrue %}.Modify(){% endif %}; } -{% else %} -void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value) +{% else %} +void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Property.attrib['Type'] }}& value) { if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }} != value) { @@ -161,7 +160,6 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const Multipl } } -{% endif %} {% endif %} {% endmacro %} {# @@ -273,7 +271,7 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Prop {% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %} {% if Property.attrib['IsPublic'] | booleanTrue != IsProtected %} {{ DefineNetworkPropertyGet(ClassName, Property, "GetParent().") }} -{{ DefineNetworkPropertyPredictableSet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) }} +{{ DefineNetworkPropertySet(Component, ReplicateFrom, ReplicateTo, ClassName, Property) }} {% endif %} {% endcall %} {% endmacro %} @@ -478,6 +476,7 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re {%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%} {% endcall %} {% if networkPropertyCount.value > 0 %} + MultiplayerStats& stats = AZ::Interface::Get()->GetStats(); // We modify the record if we are writing an update so that we don't notify for a change that really didn't change the value (just a duplicated send from the server) [[maybe_unused]] bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject; {% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %} @@ -509,7 +508,8 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re static_cast({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}), m_{{ LowerFirst(Property.attrib['Name']) }}, "{{ Property.attrib['Name'] }}", - GetNetComponentId() + GetNetComponentId(), + stats ); {% endif %} {% endcall %} @@ -1111,23 +1111,29 @@ namespace {{ Component.attrib['Namespace'] }} {{ DefineNetworkPropertyReflection(Component, 'Authority', 'Client', ComponentBaseName)|indent(16) -}} {{ DefineNetworkPropertyReflection(Component, 'Authority', 'Autonomous', ComponentBaseName)|indent(16) -}} {{ DefineNetworkPropertyReflection(Component, 'Autonomous', 'Authority', ComponentBaseName)|indent(16) }} - {{ DefineArchetypePropertyReflection(Component, ComponentBaseName)|indent(16) }} - ; + {{ DefineArchetypePropertyReflection(Component, ComponentBaseName)|indent(16) }}; + } + ReflectToEditContext(context); + } + void {{ ComponentBaseName }}::{{ ComponentBaseName }}::ReflectToEditContext(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { AZ::EditContext* editContext = serializeContext->GetEditContext(); if (editContext) { - editContext->Class<{{ ComponentBaseName }}>("{{ ComponentName }}", "{{ Component.attrib['Description'] }}") + editContext->Class<{{ ComponentName }}>("{{ ComponentName }}", "{{ Component.attrib['Description'] }}") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) - {{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Authority', ComponentBaseName)|indent(20) -}} -{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Server', ComponentBaseName)|indent(20) -}} -{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Client', ComponentBaseName)|indent(20) -}} -{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Autonomous', ComponentBaseName)|indent(20) -}} -{{ DefineNetworkPropertyEditReflection(Component, 'Autonomous', 'Authority', ComponentBaseName)|indent(20) }} - {{ DefineArchetypePropertyEditReflection(Component, ComponentBaseName)|indent(20) }} - ; + {{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Authority', ComponentName)|indent(20) -}} +{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Server', ComponentName)|indent(20) -}} +{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Client', ComponentName)|indent(20) -}} +{{ DefineNetworkPropertyEditReflection(Component, 'Authority', 'Autonomous', ComponentName)|indent(20) -}} +{{ DefineNetworkPropertyEditReflection(Component, 'Autonomous', 'Authority', ComponentName)|indent(20) }} + {{ DefineArchetypePropertyEditReflection(Component, ComponentName)|indent(20) }}; } } } diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 0f96fd45e1..6ff27ebe6c 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -24,7 +24,6 @@ namespace Multiplayer serializeContext->Class() ->Version(1); } - LocalPredictionPlayerInputComponentBase::Reflect(context); } diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp index 8dc8c6d303..fcdad87416 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.cpp @@ -43,8 +43,12 @@ namespace Multiplayer NetEntityId MultiplayerComponent::GetNetEntityId() const { - const NetBindComponent* netBindComponent = GetNetBindComponent(); - return netBindComponent ? netBindComponent->GetNetEntityId() : InvalidNetEntityId; + return m_netBindComponent ? m_netBindComponent->GetNetEntityId() : InvalidNetEntityId; + } + + NetEntityRole MultiplayerComponent::GetNetEntityRole() const + { + return m_netBindComponent ? m_netBindComponent->GetNetEntityRole() : NetEntityRole::InvalidRole; } ConstNetworkEntityHandle MultiplayerComponent::GetEntityHandle() const diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.h b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.h index 46823f4c92..9efc13ed4b 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.h +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerComponent.h @@ -62,6 +62,7 @@ namespace Multiplayer //! @} NetEntityId GetNetEntityId() const; + NetEntityRole GetNetEntityRole() const; ConstNetworkEntityHandle GetEntityHandle() const; NetworkEntityHandle GetEntityHandle(); void MarkDirty(); @@ -109,7 +110,8 @@ namespace Multiplayer int32_t bitIndex, TYPE& value, const char* name, - [[maybe_unused]] NetComponentId componentId + [[maybe_unused]] NetComponentId componentId, + MultiplayerStats& stats ) { if (bitset.GetBit(bitIndex)) @@ -119,6 +121,7 @@ namespace Multiplayer serializer.Serialize(value, name); if (modifyRecord && !serializer.GetTrackedChangesFlag()) { + // If the serializer didn't change any values, then lower the flag so we don't unnecessarily notify bitset.SetBit(bitIndex, false); } const uint32_t postUpdateSize = serializer.GetSize(); @@ -126,8 +129,7 @@ namespace Multiplayer const uint32_t updateSize = (postUpdateSize - prevUpdateSize); if (updateSize > 0) { - MultiplayerStats& stats = AZ::Interface::Get()->GetStats(); - if (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) + if (modifyRecord) { stats.m_propertyUpdatesRecv++; stats.m_propertyUpdatesRecvBytes += updateSize; diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp index 97746c3f6c..737ecc10cc 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.cpp @@ -27,6 +27,11 @@ namespace Multiplayer return m_owner.GetNetEntityId(); } + NetEntityRole MultiplayerController::GetNetEntityRole() const + { + return GetNetBindComponent()->GetNetEntityRole(); + } + AZ::Entity* MultiplayerController::GetEntity() const { return m_owner.GetEntity(); diff --git a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.h b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.h index 3495893812..9e3c7d68ab 100644 --- a/Gems/Multiplayer/Code/Source/Components/MultiplayerController.h +++ b/Gems/Multiplayer/Code/Source/Components/MultiplayerController.h @@ -47,6 +47,10 @@ namespace Multiplayer //! @return the networkId for the entity that owns this controller NetEntityId GetNetEntityId() const; + //! Returns the networkRole for the entity that owns this controller. + //! @return the networkRole for the entity that owns this controller + NetEntityRole GetNetEntityRole() const; + //! Returns the raw AZ::Entity pointer for the entity that owns this controller. //! @return the raw AZ::Entity pointer for the entity that owns this controller AZ::Entity* GetEntity() const; diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index 2e6ae60558..607e2813ec 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include namespace Multiplayer { @@ -24,7 +26,81 @@ namespace Multiplayer serializeContext->Class() ->Version(1); } - NetworkTransformComponentBase::Reflect(context); } + + NetworkTransformComponent::NetworkTransformComponent() + : m_rotationEventHandler([this](const AZ::Quaternion& rotation) { OnRotationChangedEvent(rotation); }) + , m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); }) + , m_scaleEventHandler([this](const AZ::Vector3& scale) { OnScaleChangedEvent(scale); }) + { + ; + } + + void NetworkTransformComponent::OnInit() + { + ; + } + + void NetworkTransformComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + RotationAddEvent(m_rotationEventHandler); + TranslationAddEvent(m_translationEventHandler); + ScaleAddEvent(m_scaleEventHandler); + } + + void NetworkTransformComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + ; + } + + void NetworkTransformComponent::OnRotationChangedEvent(const AZ::Quaternion& rotation) + { + AZ::Transform worldTm = GetTransformComponent()->GetWorldTM(); + worldTm.SetRotation(rotation); + GetTransformComponent()->SetWorldTM(worldTm); + } + + void NetworkTransformComponent::OnTranslationChangedEvent(const AZ::Vector3& translation) + { + AZ::Transform worldTm = GetTransformComponent()->GetWorldTM(); + worldTm.SetTranslation(translation); + GetTransformComponent()->SetWorldTM(worldTm); + } + + void NetworkTransformComponent::OnScaleChangedEvent(const AZ::Vector3& scale) + { + AZ::Transform worldTm = GetTransformComponent()->GetWorldTM(); + worldTm.SetScale(scale); + GetTransformComponent()->SetWorldTM(worldTm); + } + + + NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent) + : NetworkTransformComponentControllerBase(parent) + , m_transformChangedHandler([this](const AZ::Transform&, const AZ::Transform& worldTm) { OnTransformChangedEvent(worldTm); }) + { + ; + } + + void NetworkTransformComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + GetParent().GetTransformComponent()->BindTransformChangedEventHandler(m_transformChangedHandler); + OnTransformChangedEvent(GetParent().GetTransformComponent()->GetWorldTM()); + } + + void NetworkTransformComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + ; + } + + void NetworkTransformComponentController::OnTransformChangedEvent(const AZ::Transform& worldTm) + { + if (GetNetEntityRole() == NetEntityRole::Authority) + { + SetRotation(worldTm.GetRotation()); + SetTranslation(worldTm.GetTranslation()); + SetScale(worldTm.GetScale()); + } + } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h index 4719f11a7a..2ae3ab4bb9 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h @@ -13,6 +13,7 @@ #pragma once #include +#include namespace Multiplayer { @@ -22,20 +23,37 @@ namespace Multiplayer public: AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkTransformComponent, s_networkTransformComponentConcreteUuid, Multiplayer::NetworkTransformComponentBase); - static void Reflect([[maybe_unused]] AZ::ReflectContext* context); + static void Reflect(AZ::ReflectContext* context); - void OnInit() override {} - void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} - void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} + NetworkTransformComponent(); + + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + + private: + void OnRotationChangedEvent(const AZ::Quaternion& rotation); + void OnTranslationChangedEvent(const AZ::Vector3& translation); + void OnScaleChangedEvent(const AZ::Vector3& scale); + + AZ::Event::Handler m_rotationEventHandler; + AZ::Event::Handler m_translationEventHandler; + AZ::Event::Handler m_scaleEventHandler; }; class NetworkTransformComponentController : public NetworkTransformComponentControllerBase { public: - NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) {} + NetworkTransformComponentController(NetworkTransformComponent& parent); + + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + + private: + void OnTransformChangedEvent(const AZ::Transform& worldTm); - void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} - void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {} + AZ::TransformChangedEvent::Handler m_transformChangedHandler; + AZ::ScheduledEvent m_transformChangeEvent; }; } diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp new file mode 100644 index 0000000000..1388c1f5d2 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.cpp @@ -0,0 +1,59 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +namespace Multiplayer +{ + static constexpr uint32_t Uint32Max = AZStd::numeric_limits::max(); + + // This can be used to help mitigate client side performance when large numbers of entities are created off the network + AZ_CVAR(uint32_t, cl_ClientMaxRemoteEntitiesPendingCreationCount, Uint32Max, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Maximum number of entities that we have sent to the client, but have not had a confirmation back from the client"); + AZ_CVAR(AZ::TimeMs, cl_ClientEntityReplicatorPendingRemovalTimeMs, AZ::TimeMs{ 10000 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "How long should wait prior to removing an entity for the client through a change in the replication window, entity deletes are still immediate"); + + ClientToServerConnectionData::ClientToServerConnectionData + ( + AzNetworking::IConnection* connection, + AzNetworking::IConnectionListener& connectionListener + ) + : m_connection(connection) + , m_entityReplicationManager(*connection, connectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer) + { + m_entityReplicationManager.SetMaxRemoteEntitiesPendingCreationCount(cl_ClientMaxRemoteEntitiesPendingCreationCount); + m_entityReplicationManager.SetEntityPendingRemovalMs(cl_ClientEntityReplicatorPendingRemovalTimeMs); + } + + ClientToServerConnectionData::~ClientToServerConnectionData() + { + m_entityReplicationManager.Clear(false); + } + + ConnectionDataType ClientToServerConnectionData::GetConnectionDataType() const + { + return ConnectionDataType::ClientToServer; + } + + AzNetworking::IConnection* ClientToServerConnectionData::GetConnection() const + { + return m_connection; + } + + EntityReplicationManager& ClientToServerConnectionData::GetReplicationManager() + { + return m_entityReplicationManager; + } + + void ClientToServerConnectionData::Update([[maybe_unused]] AZ::TimeMs serverGameTimeMs) + { + m_entityReplicationManager.ActivatePendingEntities(); + } +} diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h new file mode 100644 index 0000000000..b63ffee9a3 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.h @@ -0,0 +1,47 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +namespace Multiplayer +{ + class ClientToServerConnectionData final + : public IConnectionData + { + public: + ClientToServerConnectionData + ( + AzNetworking::IConnection* connection, + AzNetworking::IConnectionListener& connectionListener + ); + ~ClientToServerConnectionData() override; + + //! IConnectionData interface + //! @{ + ConnectionDataType GetConnectionDataType() const override; + AzNetworking::IConnection* GetConnection() const override; + EntityReplicationManager& GetReplicationManager() override; + void Update(AZ::TimeMs serverGameTimeMs) override; + //! @} + + bool CanSendUpdates(); + + private: + EntityReplicationManager m_entityReplicationManager; + AzNetworking::IConnection* m_connection = nullptr; + bool m_canSendUpdates = true; + }; +} + +#include diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl new file mode 100644 index 0000000000..1ee5711341 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ConnectionData/ClientToServerConnectionData.inl @@ -0,0 +1,19 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +namespace Multiplayer +{ + inline bool ClientToServerConnectionData::CanSendUpdates() + { + return m_canSendUpdates; + } +} diff --git a/Gems/Multiplayer/Code/Source/ConnectionData/IConnectionData.h b/Gems/Multiplayer/Code/Source/ConnectionData/IConnectionData.h index ba2541ec7b..ebff75fd9b 100644 --- a/Gems/Multiplayer/Code/Source/ConnectionData/IConnectionData.h +++ b/Gems/Multiplayer/Code/Source/ConnectionData/IConnectionData.h @@ -19,6 +19,7 @@ namespace Multiplayer { enum class ConnectionDataType { + ClientToServer, ServerToClient, ServerToServer }; diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index a622814088..70323d7de3 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -13,7 +13,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -66,6 +68,7 @@ namespace Multiplayer AZ_CVAR(AZ::CVarFixedString, sv_gamerules, "norules", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "GameRules server works with"); AZ_CVAR(ProtocolType, sv_protocol, ProtocolType::Udp, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "This flag controls whether we use TCP or UDP for game networking"); AZ_CVAR(bool, sv_isDedicated, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether the host command creates an independent or client hosted server"); + AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Max Ms to use to activate entities coming from the network, 0 means instantiate everything"); void MultiplayerSystemComponent::Reflect(AZ::ReflectContext* context) { @@ -126,23 +129,26 @@ namespace Multiplayer // Handle deferred local rpc messages that were generated during the updates m_networkEntityManager.DispatchLocalDeferredRpcMessages(); m_networkEntityManager.NotifyEntitiesChanged(); + // Let the network system know the frame is done and we can collect dirty bits m_networkEntityManager.NotifyEntitiesDirtied(); - MultiplayerStats& stats = GetStats(); - stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount(); - - auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection) + // Send out the game state update to all connections { - if (connection.GetUserData() != nullptr) + auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection) { - IConnectionData* connectionData = reinterpret_cast(connection.GetUserData()); - connectionData->Update(serverGameTimeMs); - } - }; + if (connection.GetUserData() != nullptr) + { + IConnectionData* connectionData = reinterpret_cast(connection.GetUserData()); + connectionData->Update(serverGameTimeMs); + } + }; - // Send out the game state update to all connections - m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates); + m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates); + } + + MultiplayerStats& stats = GetStats(); + stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount(); MultiplayerPackets::SyncConsole packet; AZ::ThreadSafeDeque::DequeType cvarUpdates; @@ -245,12 +251,8 @@ namespace Multiplayer AZ::CVarFixedString commandString = "sv_map " + packet.GetMap(); AZ::Interface::Get()->PerformCommand(commandString.c_str()); - // This is a bit tricky, so it warrants extra commenting - // The cry level loader has a 'map' command used to invoke the level load system - // We don't want any explicit cry dependencies, so instead we rely on the - // az console binding inside SystemInit to echo any unhandled commands to - // the cry console by stripping off the prefix 'sv_' - AZ::Interface::Get()->PerformCommand(commandString.c_str() + 3); + AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap(); + AZ::Interface::Get()->PerformCommand(loadLevelString.c_str()); return true; } @@ -410,6 +412,16 @@ namespace Multiplayer AZStd::unique_ptr window = AZStd::make_unique(controlledEntity, connection); reinterpret_cast(connection->GetUserData())->GetReplicationManager().SetReplicationWindow(AZStd::move(window)); } + else + { + if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so + { + connection->SetUserData(new ClientToServerConnectionData(connection, *this)); + } + + AZStd::unique_ptr window = AZStd::make_unique(); + reinterpret_cast(connection->GetUserData())->GetReplicationManager().SetEntityActivationTimeSliceMs(cl_defaultNetworkEntityActivationTimeSliceMs); + } } bool MultiplayerSystemComponent::OnPacketReceived(AzNetworking::IConnection* connection, const IPacketHeader& packetHeader, ISerializer& serializer) @@ -463,6 +475,7 @@ namespace Multiplayer } } m_agentType = multiplayerType; + AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType)); } void MultiplayerSystemComponent::AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) @@ -535,14 +548,15 @@ namespace Multiplayer void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) { Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer; + AZ::Interface::Get()->InitializeMultiplayer(serverType); INetworkInterface* networkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); networkInterface->Listen(sv_port); - AZ::Interface::Get()->InitializeMultiplayer(serverType); } AZ_CONSOLEFREEFUNC(host, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection as a host for other clients to connect to"); void connect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) { + AZ::Interface::Get()->InitializeMultiplayer(MultiplayerAgentType::Client); INetworkInterface* networkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); if (arguments.size() < 1) @@ -567,12 +581,12 @@ namespace Multiplayer int32_t portNumber = atol(portStr); const IpAddress ipAddress(addressStr, aznumeric_cast(portNumber), networkInterface->GetType()); networkInterface->Connect(ipAddress); - AZ::Interface::Get()->InitializeMultiplayer(MultiplayerAgentType::Client); } AZ_CONSOLEFREEFUNC(connect, AZ::ConsoleFunctorFlags::DontReplicate, "Opens a multiplayer connection to a remote host"); void disconnect([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) { + AZ::Interface::Get()->InitializeMultiplayer(MultiplayerAgentType::Uninitialized); INetworkInterface* networkInterface = AZ::Interface::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName)); auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); }; networkInterface->GetConnectionSet().VisitConnections(visitor); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index f249124fb0..1e10f9841e 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include namespace AzNetworking { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index e58b7fde9d..8c076f759d 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -126,9 +127,9 @@ namespace Multiplayer MultiplayerPackets::EntityUpdates entityUpdatePacket; entityUpdatePacket.SetHostTimeMs(serverGameTimeMs); // Serialize everything - for (auto it = toSendList.begin(); it != toSendList.end();) + while (!toSendList.empty()) { - EntityReplicator* replicator = *it; + EntityReplicator* replicator = toSendList.front(); NetworkEntityUpdateMessage updateMessage(replicator->GenerateUpdatePacket()); const uint32_t nextMessageSize = updateMessage.GetEstimatedSerializeSize(); @@ -144,15 +145,15 @@ namespace Multiplayer pendingPacketSize += nextMessageSize; entityUpdatePacket.ModifyEntityMessages().push_back(updateMessage); - replicatorUpdatedList.push_back(*it); - it = toSendList.erase(it); + replicatorUpdatedList.push_back(replicator); + toSendList.pop_front(); if (largeEntityDetected) { AZLOG_WARN("\n\n*******************************"); AZLOG_WARN ( - "Serializing Extremely Large Entity (%u) - MaxPayload: %d NeededSize %d", + "Serializing extremely large entity (%u) - MaxPayload: %d NeededSize %d", aznumeric_cast(replicator->GetEntityHandle().GetNetEntityId()), maxPayloadSize, nextMessageSize @@ -173,16 +174,16 @@ namespace Multiplayer EntityReplicationManager::EntityReplicatorList EntityReplicationManager::GenerateEntityUpdateList() { + if (m_replicationWindow == nullptr) + { + return EntityReplicatorList(); + } + // Generate a list of all our entities that need updates - EntityReplicatorList autonomousReplicators; - autonomousReplicators.reserve(m_replicatorsPendingSend.size()); - EntityReplicatorList proxyReplicators; - proxyReplicators.reserve(m_replicatorsPendingSend.size()); + EntityReplicatorList toSendList; uint32_t elementsAdded = 0; - for (auto iter = m_replicatorsPendingSend.begin(); - iter != m_replicatorsPendingSend.end() - && elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount();) + for (auto iter = m_replicatorsPendingSend.begin(); iter != m_replicatorsPendingSend.end() && elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount(); ) { EntityReplicator* replicator = GetEntityReplicator(*iter); bool clearPendingSend = true; @@ -218,13 +219,13 @@ namespace Multiplayer if (replicator->GetRemoteNetworkRole() == NetEntityRole::Autonomous) { - autonomousReplicators.push_back(replicator); + toSendList.push_back(replicator); } else { if (elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount()) { - proxyReplicators.push_back(replicator); + toSendList.push_back(replicator); } } } @@ -243,9 +244,6 @@ namespace Multiplayer } } - EntityReplicatorList toSendList; - toSendList.swap(autonomousReplicators); - toSendList.insert(toSendList.end(), proxyReplicators.begin(), proxyReplicators.end()); return toSendList; } @@ -543,6 +541,7 @@ namespace Multiplayer // Create an entity if we don't have one if (createEntity) { + // @pereslav //replicatorEntity = GetNetworkEntityManager()->CreateSingleEntityImmediateInternal(prefabEntityId, EntitySpawnType::Replicate, AutoActivate::DoNotActivate, netEntityId, localNetworkRole, AZ::Transform::Identity()); AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab");// %s", prefabEntityId.GetString()); if (replicatorEntity == nullptr) @@ -765,7 +764,7 @@ namespace Multiplayer return HandleEntityDeleteMessage(entityReplicator, packetHeader, updateMessage); } - AzNetworking::NetworkOutputSerializer outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize()); + AzNetworking::TrackChangedSerializer outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize()); PrefabEntityId prefabEntityId; if (updateMessage.GetHasValidPrefabId()) @@ -1125,7 +1124,7 @@ namespace Multiplayer { if (message.GetPropertyUpdateData().GetSize() > 0) { - AzNetworking::NetworkOutputSerializer outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize()); + AzNetworking::TrackChangedSerializer outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize()); if (!HandlePropertyChangeMessage ( replicator, diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h index 1385a33208..a6470e6c34 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,7 @@ namespace Multiplayer using RpcMessages = AZStd::list; bool DispatchOrphanedRpc(NetworkEntityRpcMessage& message, EntityReplicator* entityReplicator); - using EntityReplicatorList = AZStd::vector; + using EntityReplicatorList = AZStd::deque; EntityReplicatorList GenerateEntityUpdateList(); void SendEntityUpdatesPacketHelper(AZ::TimeMs serverGameTimeMs, EntityReplicatorList& toSendList, uint32_t maxPayloadSize, AzNetworking::IConnection& connection); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index b0d0328ba8..0edb5db250 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -283,7 +283,7 @@ namespace Multiplayer AZ_Assert(netBindComponent, "No Multiplayer::NetBindComponent"); bool isAuthority = (GetBoundLocalNetworkRole() == NetEntityRole::Authority) - && (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole()); + && (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole()); bool isClient = GetRemoteNetworkRole() == NetEntityRole::Client; bool isAutonomous = GetBoundLocalNetworkRole() == NetEntityRole::Autonomous; if (isAuthority || isClient || isAutonomous) @@ -311,9 +311,9 @@ namespace Multiplayer { bool ret(false); bool isServer = (GetBoundLocalNetworkRole() == NetEntityRole::Server) - && (GetRemoteNetworkRole() == NetEntityRole::Authority); + && (GetRemoteNetworkRole() == NetEntityRole::Authority); bool isClient = (GetBoundLocalNetworkRole() == NetEntityRole::Client) - || (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous); + || (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous); if (isServer || isClient) { ret = true; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 46d1617760..23be4fb4fb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,12 @@ namespace Multiplayer , m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); }) { AZ::Interface::Register(this); + if (AZ::Interface::Get() != nullptr) + { + // Null guard needed for unit tests + AZ::Interface::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler); + AZ::Interface::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler); + } } NetworkEntityManager::~NetworkEntityManager() @@ -43,13 +50,6 @@ namespace Multiplayer void NetworkEntityManager::Initialize(HostId hostId, AZStd::unique_ptr entityDomain) { - if (AZ::Interface::Get() != nullptr) - { - // Null guard needed for unit tests - AZ::Interface::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler); - AZ::Interface::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler); - } - m_hostId = hostId; m_entityDomain = AZStd::move(entityDomain); m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true); @@ -282,8 +282,13 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { + // @pereslav + // Note that this is a total hack.. we should not be listening to this event on a client + // Entities should instead be spawned by the prefabEntityId inside EntityReplicationManager::HandlePropertyChangeMessage() + const bool isClient = AZ::Interface::Get()->GetAgentType() == MultiplayerAgentType::Client; + const NetEntityRole netEntityRole = isClient ? NetEntityRole::Client: NetEntityRole::Authority; const NetEntityId netEntityId = m_nextEntityId++; - netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority); + netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, netEntityRole); } } diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/RewindableObject.inl b/Gems/Multiplayer/Code/Source/NetworkTime/RewindableObject.inl index d5936e6718..69752210bb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/RewindableObject.inl +++ b/Gems/Multiplayer/Code/Source/NetworkTime/RewindableObject.inl @@ -73,7 +73,7 @@ namespace Multiplayer template inline BASE_TYPE& RewindableObject::Modify() { - ApplicationFrameId frameTime = GetCurrentTimeForProperty(); + const ApplicationFrameId frameTime = GetCurrentTimeForProperty(); if (frameTime < m_headTime) { AZ_Assert(false, "Trying to mutate a rewindable in the past"); @@ -82,7 +82,7 @@ namespace Multiplayer { SetValueForTime(GetValueForTime(frameTime), frameTime); } - const BASE_TYPE& returnValue = GetValueForTime(GetCurrentTimeForProperty()); + const BASE_TYPE& returnValue = GetValueForTime(frameTime); return const_cast(returnValue); } @@ -103,10 +103,11 @@ namespace Multiplayer template inline bool RewindableObject::Serialize(AzNetworking::ISerializer& serializer) { - BASE_TYPE current = GetValueForTime(GetCurrentTimeForProperty()); - if (serializer.Serialize(current, "Element") && (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject)) + const ApplicationFrameId frameTime = GetCurrentTimeForProperty(); + BASE_TYPE value = GetValueForTime(frameTime); + if (serializer.Serialize(value, "Element") && (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject)) { - SetValueForTime(current, GetCurrentTimeForProperty()); + SetValueForTime(value, frameTime); } return serializer.IsValid(); } diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.cpp b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.cpp new file mode 100644 index 0000000000..698376dccf --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.cpp @@ -0,0 +1,47 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include "NullReplicationWindow.h" + +namespace Multiplayer +{ + bool NullReplicationWindow::ReplicationSetUpdateReady() + { + return true; + } + + const ReplicationSet& NullReplicationWindow::GetReplicationSet() const + { + return m_emptySet; + } + + uint32_t NullReplicationWindow::GetMaxEntityReplicatorSendCount() const + { + return 0; + } + + bool NullReplicationWindow::IsInWindow([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle, NetEntityRole& outNetworkRole) const + { + outNetworkRole = NetEntityRole::InvalidRole; + return false; + } + + void NullReplicationWindow::UpdateWindow() + { + ; + } + + void NullReplicationWindow::DebugDraw() const + { + // Nothing to draw + } +} diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h new file mode 100644 index 0000000000..76562a34e2 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/NullReplicationWindow.h @@ -0,0 +1,38 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +namespace Multiplayer +{ + class NullReplicationWindow + : public IReplicationWindow + { + public: + NullReplicationWindow() = default; + + //! IReplicationWindow interface + //! @{ + bool ReplicationSetUpdateReady() override; + const ReplicationSet& GetReplicationSet() const override; + uint32_t GetMaxEntityReplicatorSendCount() const override; + bool IsInWindow(const ConstNetworkEntityHandle& entityPtr, NetEntityRole& outNetworkRole) const override; + void UpdateWindow() override; + void DebugDraw() const override; + //! @} + + private: + ReplicationSet m_emptySet; + }; +} diff --git a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp index cfb1286496..d0726f1341 100644 --- a/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp +++ b/Gems/Multiplayer/Code/Source/ReplicationWindows/ServerToClientReplicationWindow.cpp @@ -202,8 +202,7 @@ namespace Multiplayer void ServerToClientReplicationWindow::OnEntityActivated(const AZ::EntityId& entityId) { - AZ::Entity* entity = nullptr; - EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, entityId); + AZ::Entity* entity = AZ::Interface::Get()->FindEntity(entityId); ConstNetworkEntityHandle entityHandle(entity, GetNetworkEntityTracker()); NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent(); @@ -234,8 +233,7 @@ namespace Multiplayer void ServerToClientReplicationWindow::OnEntityDeactivated(const AZ::EntityId& entityId) { - AZ::Entity* entity = nullptr; - EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, entityId); + AZ::Entity* entity = AZ::Interface::Get()->FindEntity(entityId); ConstNetworkEntityHandle entityHandle(entity, GetNetworkEntityTracker()); NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent(); diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index eea9379df9..275625b8b4 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -34,6 +34,9 @@ set(FILES Source/Components/NetBindComponent.h Source/Components/NetworkTransformComponent.cpp Source/Components/NetworkTransformComponent.h + Source/ConnectionData/ClientToServerConnectionData.cpp + Source/ConnectionData/ClientToServerConnectionData.h + Source/ConnectionData/ClientToServerConnectionData.inl Source/ConnectionData/IConnectionData.h Source/ConnectionData/ServerToClientConnectionData.cpp Source/ConnectionData/ServerToClientConnectionData.h @@ -81,6 +84,8 @@ set(FILES Source/NetworkTime/NetworkTime.h Source/NetworkTime/RewindableObject.h Source/NetworkTime/RewindableObject.inl + Source/ReplicationWindows/NullReplicationWindow.cpp + Source/ReplicationWindows/NullReplicationWindow.h Source/ReplicationWindows/IReplicationWindow.h Source/ReplicationWindows/ServerToClientReplicationWindow.cpp Source/ReplicationWindows/ServerToClientReplicationWindow.h From 2655aaa633e8f132e4a3a66db7f6b3acbd5b50c3 Mon Sep 17 00:00:00 2001 From: hultonha Date: Wed, 14 Apr 2021 11:30:40 +0100 Subject: [PATCH 10/74] update ByteStreamSerializer to use Base64 encoding --- .../Json/ByteStreamSerializer.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp index 2da71ba68a..09adaf38cb 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace AZ { @@ -31,11 +32,13 @@ namespace AZ { case rapidjson::kStringType: { JsonByteStream* valAsByteStream = static_cast(outputValue); - JsonByteStream buffer; - buffer.resize(inputValue.GetStringLength()); - AZStd::copy(inputValue.GetString(), inputValue.GetString() + inputValue.GetStringLength(), buffer.begin()); - *valAsByteStream = AZStd::move(buffer); - return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream."); + JsonByteStream buffer(inputValue.GetStringLength()); + if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength())) + { + *valAsByteStream = AZStd::move(buffer); + return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream."); + } + return context.Report(Tasks::ReadField, Outcomes::Invalid, "Decode of Base64 encoded ByteStream failed."); } case rapidjson::kArrayType: case rapidjson::kObjectType: @@ -58,12 +61,10 @@ namespace AZ using JsonSerializationResult::Tasks; const JsonByteStream& valAsByteStream = *static_cast(inputValue); - if (context.ShouldKeepDefaults() || !defaultValue || - (valAsByteStream != *static_cast(defaultValue))) + if (context.ShouldKeepDefaults() || !defaultValue || (valAsByteStream != *static_cast(defaultValue))) { - outputValue.SetString( - reinterpret_cast(valAsByteStream.data()), aznumeric_caster(valAsByteStream.size()), - context.GetJsonAllocator()); + const auto base64ByteStream = AZ::StringFunc::Base64::Encode(valAsByteStream.data(), valAsByteStream.size()); + outputValue.SetString(base64ByteStream.c_str(), base64ByteStream.size(), context.GetJsonAllocator()); return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored."); } From e1e746066da9e064500815e3a06fd26b88b60d4a Mon Sep 17 00:00:00 2001 From: hultonha Date: Wed, 14 Apr 2021 12:04:23 +0100 Subject: [PATCH 11/74] add some preliminary tests for ByteStreamSerializer --- .../Json/ByteStreamSerializerTests.cpp | 59 +++++++++++++++++++ .../AzCore/Tests/azcoretests_files.cmake | 1 + 2 files changed, 60 insertions(+) create mode 100644 Code/Framework/AzCore/Tests/Serialization/Json/ByteStreamSerializerTests.cpp diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/ByteStreamSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/ByteStreamSerializerTests.cpp new file mode 100644 index 0000000000..110466d1a0 --- /dev/null +++ b/Code/Framework/AzCore/Tests/Serialization/Json/ByteStreamSerializerTests.cpp @@ -0,0 +1,59 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include +#include + +namespace JsonSerializationTests +{ + class ByteStreamSerializerTestDescription : public JsonSerializerConformityTestDescriptor + { + public: + AZStd::shared_ptr CreateSerializer() override + { + return AZStd::make_shared(); + } + + AZStd::shared_ptr CreateDefaultInstance() override + { + return AZStd::make_shared(); + } + + AZStd::shared_ptr CreateFullySetInstance() override + { + // create a JsonByteStream (AZStd::vector) with ten 'a's + return AZStd::make_shared(10, 'a'); + } + + AZStd::string_view GetJsonForFullySetInstance() override + { + // Base64 encoded version of 'aaaaaaaaaa' (see CreateFullySetInstance) + return R"("YWFhYWFhYWFhYQ==")"; + } + + void ConfigureFeatures(JsonSerializerConformityTestDescriptorFeatures& features) override + { + features.EnableJsonType(rapidjson::kStringType); + features.m_supportsPartialInitialization = false; + features.m_supportsInjection = false; + } + + bool AreEqual(const AZ::JsonByteStream& lhs, const AZ::JsonByteStream& rhs) override + { + return lhs == rhs; + } + }; + + using ByteStreamConformityTestTypes = ::testing::Types; + INSTANTIATE_TYPED_TEST_CASE_P(JsonByteStreamSerialzier, JsonSerializerConformityTests, ByteStreamConformityTestTypes); +} // namespace JsonSerializationTests diff --git a/Code/Framework/AzCore/Tests/azcoretests_files.cmake b/Code/Framework/AzCore/Tests/azcoretests_files.cmake index c51cf46a37..2129761bfe 100644 --- a/Code/Framework/AzCore/Tests/azcoretests_files.cmake +++ b/Code/Framework/AzCore/Tests/azcoretests_files.cmake @@ -98,6 +98,7 @@ set(FILES Serialization/Json/BaseJsonSerializerTests.cpp Serialization/Json/BasicContainerSerializerTests.cpp Serialization/Json/BoolSerializerTests.cpp + Serialization/Json/ByteStreamSerializerTests.cpp Serialization/Json/ColorSerializerTests.cpp Serialization/Json/DoubleSerializerTests.cpp Serialization/Json/IntSerializerTests.cpp From 28ccb5d381ae24cbba011047f507b0f8d12cf4ae Mon Sep 17 00:00:00 2001 From: mnaumov Date: Wed, 14 Apr 2021 12:17:45 -0700 Subject: [PATCH 12/74] Fixing camera panning and zooming --- ...MaterialEditorViewportInputControllerBus.h | 3 +++ .../Viewport/InputController/Behavior.cpp | 24 +++++++++++++++++++ .../MaterialEditorViewportInputController.cpp | 13 ++++++++++ .../MaterialEditorViewportInputController.h | 3 +++ .../InputController/PanCameraBehavior.cpp | 4 +--- 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/InputController/MaterialEditorViewportInputControllerBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/InputController/MaterialEditorViewportInputControllerBus.h index 04250c4efd..2acdc79286 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/InputController/MaterialEditorViewportInputControllerBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/InputController/MaterialEditorViewportInputControllerBus.h @@ -53,6 +53,9 @@ namespace MaterialEditor //! Modify camera's field of view //! @param value field of view in degrees virtual void SetFieldOfView(float value) = 0; + + //! Check if camera is looking directly at a model + virtual bool IsCameraCentered() const = 0; }; using MaterialEditorViewportInputControllerRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/Behavior.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/Behavior.cpp index 8355b390ef..159d3339be 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/Behavior.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/Behavior.cpp @@ -76,11 +76,35 @@ namespace MaterialEditor void Behavior::TickInternal([[maybe_unused]] float x, [[maybe_unused]] float y, float z) { m_distanceToTarget = m_distanceToTarget - z; + + bool isCameraCentered = false; + MaterialEditorViewportInputControllerRequestBus::BroadcastResult( + isCameraCentered, + &MaterialEditorViewportInputControllerRequestBus::Handler::IsCameraCentered); + + // if camera is looking at the model (locked to the model) we don't want to zoom past the model's center + if (isCameraCentered) + { + m_distanceToTarget = AZ::GetMax(m_distanceToTarget, 0.0f); + } + AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::Vector3 position = m_targetPosition - transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(m_distanceToTarget)); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTranslation, position); + + // if camera is not locked to the model, move its focal point so we can free look + if (!isCameraCentered) + { + m_targetPosition += transform.GetRotation().TransformVector(AZ::Vector3::CreateAxisY(z)); + MaterialEditorViewportInputControllerRequestBus::Broadcast( + &MaterialEditorViewportInputControllerRequestBus::Handler::SetTargetPosition, + m_targetPosition); + MaterialEditorViewportInputControllerRequestBus::BroadcastResult( + m_distanceToTarget, + &MaterialEditorViewportInputControllerRequestBus::Handler::GetDistanceToTarget); + } } float Behavior::GetSensitivityX() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp index e180a5d979..83ec5a41c5 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.cpp @@ -96,6 +96,7 @@ namespace MaterialEditor void MaterialEditorViewportInputController::SetTargetPosition(const AZ::Vector3& targetPosition) { m_targetPosition = targetPosition; + m_isCameraCentered = false; } float MaterialEditorViewportInputController::GetDistanceToTarget() const @@ -246,6 +247,7 @@ namespace MaterialEditor cameraPosition = cameraRotation.TransformVector(cameraPosition); AZ::Transform cameraTransform = AZ::Transform::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalTM, cameraTransform); + m_isCameraCentered = true; // reset model AZ::Transform modelTransform = AZ::Transform::CreateIdentity(); @@ -258,6 +260,12 @@ namespace MaterialEditor AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor(); skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix); + + if (m_behavior) + { + m_behavior->End(); + m_behavior->Start(); + } } void MaterialEditorViewportInputController::SetFieldOfView(float value) @@ -265,6 +273,11 @@ namespace MaterialEditor Camera::CameraRequestBus::Event(m_cameraEntityId, &Camera::CameraRequestBus::Events::SetFovDegrees, value); } + bool MaterialEditorViewportInputController::IsCameraCentered() const + { + return m_isCameraCentered; + } + void MaterialEditorViewportInputController::CalculateExtents() { AZ::TransformBus::EventResult(m_modelCenter, m_targetEntityId, &AZ::TransformBus::Events::GetLocalTranslation); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.h index aa3dd836d6..ee40b5c259 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/MaterialEditorViewportInputController.h @@ -45,6 +45,7 @@ namespace MaterialEditor void GetExtents(float& distanceMin, float& distanceMax) const override; void Reset() override; void SetFieldOfView(float value) override; + bool IsCameraCentered() const override; // AzFramework::ViewportControllerInstance interface overrides... bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; @@ -95,6 +96,8 @@ namespace MaterialEditor float m_distanceMin = 1.0f; //! Maximum distance from camera to target float m_distanceMax = 10.0f; + //! True if camera is centered on a model + bool m_isCameraCentered = true; static constexpr float MaxDistanceMultiplier = 2.5f; static constexpr float StartingDistanceMultiplier = 2.0f; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/PanCameraBehavior.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/PanCameraBehavior.cpp index 087591e6ea..e36a335129 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/PanCameraBehavior.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/InputController/PanCameraBehavior.cpp @@ -34,10 +34,8 @@ namespace MaterialEditor targetPosition); } - void PanCameraBehavior::TickInternal(float x, float y, float z) + void PanCameraBehavior::TickInternal(float x, float y, [[maybe_unused]] float z) { - Behavior::TickInternal(x, y, z); - AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(transform, m_cameraEntityId, &AZ::TransformBus::Events::GetLocalTM); AZ::Quaternion rotation = transform.GetRotation(); From f7aabebb375e9bd0e4e3b1dff4661ea3827aa1ca Mon Sep 17 00:00:00 2001 From: nvsickle Date: Wed, 14 Apr 2021 16:56:23 -0700 Subject: [PATCH 13/74] Fix context menu popping up when it shouldn't --- Code/Sandbox/Editor/LegacyViewportCameraController.cpp | 9 +++++++++ Code/Sandbox/Editor/LegacyViewportCameraController.h | 1 + 2 files changed, 10 insertions(+) diff --git a/Code/Sandbox/Editor/LegacyViewportCameraController.cpp b/Code/Sandbox/Editor/LegacyViewportCameraController.cpp index 44b722d222..7a33dff377 100644 --- a/Code/Sandbox/Editor/LegacyViewportCameraController.cpp +++ b/Code/Sandbox/Editor/LegacyViewportCameraController.cpp @@ -96,6 +96,11 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove( speedScale *= gSettings.cameraFastMoveSpeed; } + if (m_inMoveMode || m_inOrbitMode || m_inRotateMode || m_inZoomMode) + { + m_totalMouseMoveDelta += (QPoint(currentMousePos.m_x, currentMousePos.m_y)-QPoint(previousMousePos.m_x, previousMousePos.m_y)).manhattanLength(); + } + if ((m_inRotateMode && m_inMoveMode) || m_inZoomMode) { Matrix34 m = AZTransformToLYTransform(viewportContext->GetCameraTransform()); @@ -343,11 +348,15 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra } shouldCaptureCursor = true; + // Record how much the cursor has been moved to see if we should own the mouse up event. + m_totalMouseMoveDelta = 0; } else if (state == InputChannel::State::Ended) { m_inZoomMode = false; m_inRotateMode = false; + // If we've moved the cursor more than a couple pixels, we should eat this mouse up event to prevent the context menu controller from seeing it. + shouldConsumeEvent = m_totalMouseMoveDelta > 2; shouldCaptureCursor = false; } } diff --git a/Code/Sandbox/Editor/LegacyViewportCameraController.h b/Code/Sandbox/Editor/LegacyViewportCameraController.h index 3f211f49b7..b4a36f44a5 100644 --- a/Code/Sandbox/Editor/LegacyViewportCameraController.h +++ b/Code/Sandbox/Editor/LegacyViewportCameraController.h @@ -58,6 +58,7 @@ namespace SandboxEditor bool m_inMoveMode = false; bool m_inOrbitMode = false; bool m_inZoomMode = false; + int m_totalMouseMoveDelta = 0; float m_orbitDistance = 10.f; float m_moveSpeed = 1.f; AZ::Vector3 m_orbitTarget = {}; From a23a2fba65bef0248bf16eb03a90046d5e65d594 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Wed, 14 Apr 2021 17:47:37 -0700 Subject: [PATCH 14/74] PR feedback --- .../Code/Source/Material/EditorMaterialComponentSlot.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 5c22a0974e..871bb7f83f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -172,10 +172,6 @@ namespace AZ { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, sourcePath); } - else - { - EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); - } } void EditorMaterialComponentSlot::Clear() @@ -277,7 +273,7 @@ namespace AZ QAction* action = nullptr; - menu.addAction("Open Material Editor", [this]() { OpenMaterialEditor(); }); + menu.addAction("Open Material Editor", [this]() { EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, ""); }); action = menu.addAction("Clear", [this]() { Clear(); }); action->setEnabled(m_materialAsset.GetId().IsValid() || !m_propertyOverrides.empty() || !m_matModUvOverrides.empty()); From 45faa26ffd6ebb2d99d6c0dc2d226eb4a47501a6 Mon Sep 17 00:00:00 2001 From: karlberg Date: Wed, 14 Apr 2021 17:50:04 -0700 Subject: [PATCH 15/74] Some initial updates for eventual support of locally predicted input processing --- .../AutoGen/AutoComponentTypes_Header.jinja | 7 +++++ ...tionPlayerInputComponent.AutoComponent.xml | 4 +-- .../LocalPredictionPlayerInputComponent.cpp | 2 +- .../LocalPredictionPlayerInputComponent.h | 2 +- .../Components/NetworkTransformComponent.h | 1 - .../Code/Source/NetworkInput/NetworkInput.cpp | 26 ++++++++++++++----- .../Code/Source/NetworkInput/NetworkInput.h | 17 +++++++----- .../NetworkInput/NetworkInputVector.cpp | 4 +-- .../Source/NetworkInput/NetworkInputVector.h | 6 ++--- 9 files changed, 47 insertions(+), 22 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja index 22365e685c..090bd4f0e0 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Header.jinja @@ -1,6 +1,7 @@ #pragma once #include +#include namespace AZ { @@ -17,7 +18,13 @@ namespace {{ Namespace }} {% set ComponentName = Component.attrib['Name'] %} {{ ComponentName }}, {% endfor %} + Count }; + static_assert(ComponentTypes::Count < static_cast(Multiplayer::InvalidNetComponentId), "ComponentId overflow"); + //! For reflecting multiplayer components into the serialize, edit, and behaviour contexts. void CreateComponentDescriptors(AZStd::list& descriptors); + + //! For creating multiplayer component network inputs. + void CreateComponentNetworkInput(); } diff --git a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml index faeaf8d0cc..d38ebbb1b8 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml @@ -16,7 +16,7 @@ - + @@ -25,7 +25,7 @@ - + diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 6ff27ebe6c..24986148c4 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -47,7 +47,7 @@ namespace Multiplayer void LocalPredictionPlayerInputComponentController::HandleSendClientInputCorrection ( - [[maybe_unused]] const Multiplayer::NetworkInputId& inputId, + [[maybe_unused]] const Multiplayer::ClientInputId& inputId, [[maybe_unused]] const AzNetworking::PacketEncodingBuffer& correction ) { diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h index d7029ed0a1..b332315799 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.h @@ -42,6 +42,6 @@ namespace Multiplayer void HandleSendClientInput(const Multiplayer::NetworkInputVector& inputArray, const uint32_t& stateHash, const AzNetworking::PacketEncodingBuffer& clientState) override; void HandleSendMigrateClientInput(const Multiplayer::MigrateNetworkInputVector& inputArray) override; - void HandleSendClientInputCorrection(const Multiplayer::NetworkInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction) override; + void HandleSendClientInputCorrection(const Multiplayer::ClientInputId& inputId, const AzNetworking::PacketEncodingBuffer& correction) override; }; } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h index 2ae3ab4bb9..2a3b5fb3cc 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.h @@ -54,6 +54,5 @@ namespace Multiplayer void OnTransformChangedEvent(const AZ::Transform& worldTm); AZ::TransformChangedEvent::Handler m_transformChangedHandler; - AZ::ScheduledEvent m_transformChangeEvent; }; } diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp index 5991e0391d..a02bc4209d 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.cpp @@ -33,22 +33,36 @@ namespace Multiplayer return *this; } - void NetworkInput::SetNetworkInputId(NetworkInputId inputId) + void NetworkInput::SetClientInputId(ClientInputId inputId) { m_inputId = inputId; } - NetworkInputId NetworkInput::GetNetworkInputId() const + ClientInputId NetworkInput::GetClientInputId() const { return m_inputId; } - - NetworkInputId& NetworkInput::ModifyNetworkInputId() + ClientInputId& NetworkInput::ModifyClientInputId() { return m_inputId; } + void NetworkInput::SetServerTimeMs(AZ::TimeMs serverTimeMs) + { + m_serverTimeMs = serverTimeMs; + } + + AZ::TimeMs NetworkInput::GetServerTimeMs() const + { + return m_serverTimeMs; + } + + AZ::TimeMs& NetworkInput::ModifyServerTimeMs() + { + return m_serverTimeMs; + } + void NetworkInput::AttachNetBindComponent(NetBindComponent* netBindComponent) { m_wasAttached = true; @@ -62,7 +76,6 @@ namespace Multiplayer bool NetworkInput::Serialize(AzNetworking::ISerializer& serializer) { - //static_assert(UINT8_MAX >= Multiplayer::ComponentTypes::c_Count, "Expected fewer than 255 components, this code needs to be updated"); if (!serializer.Serialize(m_inputId, "InputId")) { return false; @@ -135,8 +148,9 @@ namespace Multiplayer void NetworkInput::CopyInternal(const NetworkInput& rhs) { m_inputId = rhs.m_inputId; + m_serverTimeMs = rhs.m_serverTimeMs; m_componentInputs.resize(rhs.m_componentInputs.size()); - for (int i = 0; i < rhs.m_componentInputs.size(); ++i) + for (int32_t i = 0; i < rhs.m_componentInputs.size(); ++i) { if (m_componentInputs[i] == nullptr || m_componentInputs[i]->GetComponentId() != rhs.m_componentInputs[i]->GetComponentId()) { diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.h b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.h index 9d0cb6849d..43768c4196 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.h +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInput.h @@ -21,7 +21,7 @@ namespace Multiplayer // Forwards class NetBindComponent; - AZ_TYPE_SAFE_INTEGRAL(NetworkInputId, uint16_t); + AZ_TYPE_SAFE_INTEGRAL(ClientInputId, uint16_t); //! @class NetworkInput //! @brief A single networked client input command. @@ -38,9 +38,13 @@ namespace Multiplayer NetworkInput(const NetworkInput&); NetworkInput& operator= (const NetworkInput&); - void SetNetworkInputId(NetworkInputId inputId); - NetworkInputId GetNetworkInputId() const; - NetworkInputId& ModifyNetworkInputId(); + void SetClientInputId(ClientInputId inputId); + ClientInputId GetClientInputId() const; + ClientInputId& ModifyClientInputId(); + + void SetServerTimeMs(AZ::TimeMs serverTimeMs); + AZ::TimeMs GetServerTimeMs() const; + AZ::TimeMs& ModifyServerTimeMs(); void AttachNetBindComponent(NetBindComponent* netBindComponent); @@ -67,10 +71,11 @@ namespace Multiplayer void CopyInternal(const NetworkInput& rhs); MultiplayerComponentInputVector m_componentInputs; - NetworkInputId m_inputId = NetworkInputId{ 0 }; + ClientInputId m_inputId = ClientInputId{ 0 }; + AZ::TimeMs m_serverTimeMs = AZ::TimeMs{ 0 }; ConstNetworkEntityHandle m_owner; bool m_wasAttached = false; }; } -AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::NetworkInputId); +AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::ClientInputId); diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.cpp b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.cpp index 6f35bdc5fa..466a112e12 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.cpp @@ -48,12 +48,12 @@ namespace Multiplayer return m_inputs[index].m_networkInput; } - void NetworkInputVector::SetPreviousInputId(NetworkInputId previousInputId) + void NetworkInputVector::SetPreviousInputId(ClientInputId previousInputId) { m_previousInputId = previousInputId; } - NetworkInputId NetworkInputVector::GetPreviousInputId() const + ClientInputId NetworkInputVector::GetPreviousInputId() const { return m_previousInputId; } diff --git a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.h b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.h index 63332aa9c2..be41495577 100644 --- a/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.h +++ b/Gems/Multiplayer/Code/Source/NetworkInput/NetworkInputVector.h @@ -32,8 +32,8 @@ namespace Multiplayer NetworkInput& operator[](uint32_t index); const NetworkInput& operator[](uint32_t index) const; - void SetPreviousInputId(NetworkInputId previousInputId); - NetworkInputId GetPreviousInputId() const; + void SetPreviousInputId(ClientInputId previousInputId); + ClientInputId GetPreviousInputId() const; bool Serialize(AzNetworking::ISerializer& serializer); @@ -48,7 +48,7 @@ namespace Multiplayer ConstNetworkEntityHandle m_owner; AZStd::fixed_vector m_inputs; - NetworkInputId m_previousInputId; + ClientInputId m_previousInputId; }; //! @class MigrateNetworkInputVector From 2410d299c1ba6de8392751f0c9f6b0e7b72e8b03 Mon Sep 17 00:00:00 2001 From: srikappa Date: Wed, 14 Apr 2021 17:51:15 -0700 Subject: [PATCH 16/74] Make creation of new prefabs use a relative path to the project --- .../Prefab/PrefabPublicHandler.cpp | 2 +- .../Prefab/PrefabPublicHandler.h | 2 +- .../Prefab/PrefabPublicInterface.h | 2 +- .../UI/Prefab/PrefabIntegrationManager.cpp | 16 ++++++++++++++-- .../UI/Prefab/PrefabIntegrationManager.h | 4 ++++ 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 417a524e77..26191c97af 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -58,7 +58,7 @@ namespace AzToolsFramework m_prefabUndoCache.Destroy(); } - PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZStd::string_view filePath) + PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) { // Retrieve entityList from entityIds EntityList inputEntityList; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h index 46a7f946ba..80f28d7edb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h @@ -42,7 +42,7 @@ namespace AzToolsFramework void UnregisterPrefabPublicHandlerInterface(); // PrefabPublicInterface... - PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZStd::string_view filePath) override; + PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) override; PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, AZ::Vector3 position) override; PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override; PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h index 81a5258d91..4e59729ab2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h @@ -49,7 +49,7 @@ namespace AzToolsFramework * @param filePath The path for the new prefab file. * @return An outcome object; on failure, it comes with an error message detailing the cause of the error. */ - virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZStd::string_view filePath) = 0; + virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) = 0; /** * Instantiate a prefab from a prefab file. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 1e71b545b5..6ce3fdc755 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -39,9 +40,12 @@ namespace AzToolsFramework { namespace Prefab { + EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr; PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr; PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr; + PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr; + const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab"; void PrefabUserSettings::Reflect(AZ::ReflectContext* context) @@ -79,6 +83,13 @@ namespace AzToolsFramework return; } + s_prefabLoaderInterface = AZ::Interface::Get(); + if (s_prefabLoaderInterface == nullptr) + { + AZ_Assert(false, "Prefab - could not get PrefabLoaderInterface on PrefabIntegrationManager construction."); + return; + } + EditorContextMenuBus::Handler::BusConnect(); PrefabInstanceContainerNotificationBus::Handler::BusConnect(); AZ::Interface::Register(this); @@ -320,14 +331,15 @@ namespace AzToolsFramework GenerateSuggestedFilenameFromEntities(prefabRootEntities, suggestedName); - if (!QueryUserForPrefabSaveLocation(suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath)) + if (!QueryUserForPrefabSaveLocation( + suggestedName, targetDirectory, AZ_CRC("PrefabUserSettings"), activeWindow, prefabName, prefabFilePath)) { // User canceled prefab creation, or error prevented continuation. return; } } - auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, prefabFilePath); + auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, s_prefabLoaderInterface->GetRelativePathToProject(prefabFilePath.data())); if (!createPrefabOutcome.IsSuccess()) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h index 66a047df28..c9b846aa5b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -29,6 +29,9 @@ namespace AzToolsFramework { namespace Prefab { + + class PrefabLoaderInterface; + //! Structure for saving/retrieving user settings related to prefab workflows. class PrefabUserSettings : public AZ::UserSettings @@ -129,6 +132,7 @@ namespace AzToolsFramework static EditorEntityUiInterface* s_editorEntityUiInterface; static PrefabPublicInterface* s_prefabPublicInterface; static PrefabEditInterface* s_prefabEditInterface; + static PrefabLoaderInterface* s_prefabLoaderInterface; }; } } From 243af5f697155ff8489d0a310ceaae1bd84eb90b Mon Sep 17 00:00:00 2001 From: pruiksma Date: Wed, 14 Apr 2021 23:13:31 -0500 Subject: [PATCH 17/74] ATOM-15240 Fixing thumbnails attempting to use a feature processor that no longer exists. Adding simple point and simple spot feature processors to the thumbnail scene descriptor. --- .../Rendering/ThumbnailRendererSteps/InitializeStep.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp index 238cbb3a3c..2a447ce3ec 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp @@ -54,8 +54,9 @@ namespace AZ RPI::SceneDescriptor sceneDesc; sceneDesc.m_featureProcessorNames.push_back("AZ::Render::TransformServiceFeatureProcessor"); sceneDesc.m_featureProcessorNames.push_back("AZ::Render::MeshFeatureProcessor"); + sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimplePointLightFeatureProcessor"); + sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SimpleSpotLightFeatureProcessor"); sceneDesc.m_featureProcessorNames.push_back("AZ::Render::PointLightFeatureProcessor"); - sceneDesc.m_featureProcessorNames.push_back("AZ::Render::SpotLightFeatureProcessor"); // There is currently a bug where having multiple DirectionalLightFeatureProcessors active can result in shadow flickering [ATOM-13568] // as well as continually rebuilding MeshDrawPackets [ATOM-13633]. Lets just disable the directional light FP for now. // Possibly re-enable with [GFX TODO][ATOM-13639] From fa7f61cf0d7bc89f14447e160b7cb70c604e0b07 Mon Sep 17 00:00:00 2001 From: qingtao Date: Wed, 14 Apr 2021 22:48:46 -0700 Subject: [PATCH 18/74] ATOM-13791 Editor: ImGui profiling tools doesn't work correctly due to disabled RenderPipelines - Added pause/resume button to ImGui Profiler to pause/resume profiling - Added showing pass execution timeline - Change TimestampResult to include both begin tick and duration tick. Update some function names of TimestampResult. - Update some functions names in Pass. - Stop showing accumulated time for ParentPass. - Fixed a crash issue with ImGuiManager which doesn't have default font. --- .gitignore | 1 + .../ProfilingCaptureSystemComponent.cpp | 4 +- .../Atom/RPI.Public/GpuQuery/GpuQueryTypes.h | 17 +- .../Include/Atom/RPI.Public/Pass/ParentPass.h | 1 - .../Code/Include/Atom/RPI.Public/Pass/Pass.h | 8 +- .../RPI.Public/GpuQuery/GpuQueryTypes.cpp | 40 ++- .../Source/RPI.Public/Pass/ParentPass.cpp | 15 +- .../RPI/Code/Source/RPI.Public/Pass/Pass.cpp | 18 +- .../Source/RPI.Public/Pass/RenderPass.cpp | 2 +- .../Viewport/PerformanceMonitorComponent.cpp | 4 +- .../Include/Atom/Utils/ImGuiGpuProfiler.h | 33 ++- .../Include/Atom/Utils/ImGuiGpuProfiler.inl | 262 ++++++++++++++---- Gems/ImGui/Code/Source/ImGuiManager.cpp | 4 + 13 files changed, 288 insertions(+), 121 deletions(-) diff --git a/.gitignore b/.gitignore index 24af068c53..eb24d72701 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ _savebackup/ #Output folder for test results when running Automated Tests TestResults/** *.swatches +/imgui.ini diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index 38c30d67a6..9cc98a15ec 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -186,7 +186,7 @@ namespace AZ { for (const RPI::Pass* pass : passes) { - m_timestampEntries.push_back({ pass->GetName(), pass->GetTimestampResult().GetTimestampInNanoseconds() }); + m_timestampEntries.push_back({pass->GetName(), pass->GetLatestTimestampResult().GetDurationInNanoseconds()}); } } @@ -223,7 +223,7 @@ namespace AZ { for (const RPI::Pass* pass : passes) { - m_pipelineStatisticsEntries.push_back({ pass->GetName(), pass->GetPipelineStatisticsResult() }); + m_pipelineStatisticsEntries.push_back({pass->GetName(), pass->GetLatestPipelineStatisticsResult()}); } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/GpuQuery/GpuQueryTypes.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/GpuQuery/GpuQueryTypes.h index 80a72aaf55..ae86557170 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/GpuQuery/GpuQueryTypes.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/GpuQuery/GpuQueryTypes.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include @@ -43,15 +44,19 @@ namespace AZ { public: TimestampResult() = default; - TimestampResult(uint64_t timestampInTicks); - TimestampResult(uint64_t timestampQueryResultLow, uint64_t timestampQueryResultHigh); - TimestampResult(AZStd::array_view&& timestampResultArray); + TimestampResult(uint64_t beginTick, uint64_t endTick, RHI::HardwareQueueClass hardwareQueueClass); - uint64_t GetTimestampInNanoseconds() const; - uint64_t GetTimestampInTicks() const; + uint64_t GetDurationInNanoseconds() const; + uint64_t GetDurationInTicks() const; + uint64_t GetTimestampBeginInTicks() const; + + void Add(const TimestampResult& extent); private: - uint64_t m_timestampInTicks = 0u; + // the timestamp of begin and duration in ticks. + uint64_t m_begin = 0; + uint64_t m_duration = 0; + RHI::HardwareQueueClass m_hardwareQueueClass = RHI::HardwareQueueClass::Graphics; }; //! The structure that is used to read back the results form the PipelineStatistics queries diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h index 9317158437..b4f63a7099 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h @@ -122,7 +122,6 @@ namespace AZ private: // RPI::Pass overrides... - TimestampResult GetTimestampResultInternal() const override; PipelineStatisticsResult GetPipelineStatisticsResultInternal() const override; // --- Hierarchy related functions --- diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h index ae249a5f45..b0d6bd4117 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Pass.h @@ -211,11 +211,11 @@ namespace AZ //! Prints the pass virtual void DebugPrint() const; - //! Return the Timestamp result of this pass - TimestampResult GetTimestampResult() const; + //! Return the latest Timestamp result of this pass + TimestampResult GetLatestTimestampResult() const; - //! Return the PipelineStatistic result of this pass - PipelineStatisticsResult GetPipelineStatisticsResult() const; + //! Return the latest PipelineStatistic result of this pass + PipelineStatisticsResult GetLatestPipelineStatisticsResult() const; //! Enables/Disables Timestamp queries for this pass virtual void SetTimestampQueryEnabled(bool enable); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQueryTypes.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQueryTypes.cpp index a1b2ece4dc..715964651f 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQueryTypes.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQueryTypes.cpp @@ -21,41 +21,39 @@ namespace AZ namespace RPI { // --- TimestampResult --- - - TimestampResult::TimestampResult(uint64_t timestampInTicks) + TimestampResult::TimestampResult(uint64_t beginTick, uint64_t endTick, RHI::HardwareQueueClass hardwareQueueClass) { - m_timestampInTicks = timestampInTicks; + AZ_Assert(endTick >= beginTick, "TimestampResult: bad inputs"); + m_begin = beginTick; + m_duration = endTick - beginTick; + m_hardwareQueueClass = hardwareQueueClass; } - TimestampResult::TimestampResult(uint64_t timestampQueryResultLow, uint64_t timestampQueryResultHigh) + uint64_t TimestampResult::GetDurationInNanoseconds() const { - const uint64_t low = AZStd::min(timestampQueryResultLow, timestampQueryResultHigh); - const uint64_t high = AZStd::max(timestampQueryResultLow, timestampQueryResultHigh); + const RHI::Ptr device = RHI::GetRHIDevice(); + const AZStd::chrono::microseconds timeInMicroseconds = device->GpuTimestampToMicroseconds(m_duration, m_hardwareQueueClass); + const auto timeInNanoseconds = AZStd::chrono::nanoseconds(timeInMicroseconds); - m_timestampInTicks = high - low; + return static_cast(timeInNanoseconds.count()); } - TimestampResult::TimestampResult(AZStd::array_view&& timestampResultArray) + uint64_t TimestampResult::GetDurationInTicks() const { - // Loop through all the child passes, and accumulate all the timestampTicks - for (const TimestampResult& timestampResult : timestampResultArray) - { - m_timestampInTicks += timestampResult.m_timestampInTicks; - } + return m_duration; } - uint64_t TimestampResult::GetTimestampInNanoseconds() const + uint64_t TimestampResult::GetTimestampBeginInTicks() const { - const RHI::Ptr device = RHI::GetRHIDevice(); - const AZStd::chrono::microseconds timeInMicroseconds = device->GpuTimestampToMicroseconds(m_timestampInTicks, RHI::HardwareQueueClass::Graphics); - const auto timeInNanoseconds = AZStd::chrono::nanoseconds(timeInMicroseconds); - - return static_cast(timeInNanoseconds.count()); + return m_begin; } - uint64_t TimestampResult::GetTimestampInTicks() const + void TimestampResult::Add(const TimestampResult& extent) { - return m_timestampInTicks; + uint64_t end1 = m_begin + m_duration; + uint64_t end2 = extent.m_begin + extent.m_duration; + m_begin = m_begin < extent.m_begin ? m_begin : extent.m_begin; + m_duration = (end1 > end2 ? end1 : end2) - m_begin; } // --- PipelineStatisticsResult --- diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp index 6314ae376e..106ef82bf1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp @@ -393,19 +393,6 @@ namespace AZ } } - TimestampResult ParentPass::GetTimestampResultInternal() const - { - AZStd::vector timestampResultArray; - timestampResultArray.reserve(m_children.size()); - - // Calculate the Timestamp result by summing all of its child's TimestampResults - for (const Ptr& childPass : m_children) - { - timestampResultArray.emplace_back(childPass->GetTimestampResult()); - } - return TimestampResult(timestampResultArray); - } - PipelineStatisticsResult ParentPass::GetPipelineStatisticsResultInternal() const { AZStd::vector pipelineStatisticsResultArray; @@ -414,7 +401,7 @@ namespace AZ // Calculate the PipelineStatistics result by summing all of its child's PipelineStatistics for (const Ptr& childPass : m_children) { - pipelineStatisticsResultArray.emplace_back(childPass->GetPipelineStatisticsResult()); + pipelineStatisticsResultArray.emplace_back(childPass->GetLatestPipelineStatisticsResult()); } return PipelineStatisticsResult(pipelineStatisticsResultArray); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp index 5ecf293efe..9401d1a9e0 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp @@ -1273,24 +1273,14 @@ namespace AZ } } - TimestampResult Pass::GetTimestampResult() const + TimestampResult Pass::GetLatestTimestampResult() const { - if (IsEnabled() && IsTimestampQueryEnabled()) - { - return GetTimestampResultInternal(); - } - - return TimestampResult(); + return GetTimestampResultInternal(); } - PipelineStatisticsResult Pass::GetPipelineStatisticsResult() const + PipelineStatisticsResult Pass::GetLatestPipelineStatisticsResult() const { - if (IsEnabled() && IsPipelineStatisticsQueryEnabled()) - { - return GetPipelineStatisticsResultInternal(); - } - - return PipelineStatisticsResult(); + return GetPipelineStatisticsResultInternal(); } TimestampResult Pass::GetTimestampResultInternal() const diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp index 19a4f3d302..1fad385fa6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/RenderPass.cpp @@ -539,7 +539,7 @@ namespace AZ const uint32_t TimestampResultQueryCount = 2u; uint64_t timestampResult[TimestampResultQueryCount] = {0}; query->GetLatestResult(×tampResult, sizeof(uint64_t) * TimestampResultQueryCount); - m_timestampResult = TimestampResult(timestampResult[0], timestampResult[1]); + m_timestampResult = TimestampResult(timestampResult[0], timestampResult[1], RHI::HardwareQueueClass::Graphics); }); ExecuteOnPipelineStatisticsQuery([this](RHI::Ptr query) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp index afe3cc6fb6..513bedb55f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp @@ -109,8 +109,8 @@ namespace MaterialEditor AZ::RHI::Ptr rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass(); if (rootPass) { - AZ::RPI::TimestampResult timestampResult = rootPass->GetTimestampResult(); - double gpuFrameTimeMs = aznumeric_cast(timestampResult.GetTimestampInNanoseconds()) / 1000000; + AZ::RPI::TimestampResult timestampResult = rootPass->GetLatestTimestampResult(); + double gpuFrameTimeMs = aznumeric_cast(timestampResult.GetDurationInNanoseconds()) / 1000000; m_gpuFrameTimeMs.PushSample(gpuFrameTimeMs); } } diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h index 8936f15e55..6520844edd 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h @@ -93,7 +93,9 @@ namespace AZ ImGuiPipelineStatisticsView(); //! Draw the PipelineStatistics window. - void DrawPipelineStatisticsWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& m_timestampEntryDatabase); + void DrawPipelineStatisticsWindow(bool& draw, const PassEntry* rootPassEntry, + AZStd::unordered_map& m_timestampEntryDatabase, + AZ::RHI::Ptr rootPass); //! Total number of columns (Attribute columns + PassName column). static const uint32_t HeaderAttributeCount = PassEntry::PipelineStatisticsAttributeCount + 1u; @@ -139,6 +141,9 @@ namespace AZ // ImGui filter used to filter passes by the user's input. ImGuiTextFilter m_passFilter; + + // Pause and showing the pipeline statistics result when it's paused. + bool m_paused = false; }; class ImGuiTimestampView @@ -180,9 +185,19 @@ namespace AZ Count }; + // Timestamp refresh type . + enum class RefreshType : int32_t + { + Realtime = 0, + OncePerSecond, + Count + }; + public: //! Draw the Timestamp window. - void DrawTimestampWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& m_timestampEntryDatabase); + void DrawTimestampWindow(bool& draw, const PassEntry* rootPassEntry, + AZStd::unordered_map& m_timestampEntryDatabase, + AZ::RHI::Ptr rootPass); private: // Draw option for the hierarchical view of the passes. @@ -223,6 +238,20 @@ namespace AZ // ImGui filter used to filter passes. ImGuiTextFilter m_passFilter; + + // Pause and showing the timestamp result when it's paused. + bool m_paused = false; + + // Hide non-parent passes which has 0 execution time. + bool m_hideZeroPasses = false; + + // Show pass execution timeline + bool m_showTimeline = false; + + // Controls how often the timestamp data is refreshed + RefreshType m_refreshType = RefreshType::OncePerSecond; + AZStd::sys_time_t m_lastUpdateTimeMicroSecond; + }; class ImGuiGpuProfiler diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl index a2b29f3fb7..c00533f740 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl @@ -105,9 +105,9 @@ namespace AZ // [GFX TODO][ATOM-4001] Cache the timestamp and PipelineStatistics results. // Get the query results from the passes. - m_timestampResult = pass->GetTimestampResult(); + m_timestampResult = pass->GetLatestTimestampResult(); - const RPI::PipelineStatisticsResult rps = pass->GetPipelineStatisticsResult(); + const RPI::PipelineStatisticsResult rps = pass->GetLatestPipelineStatisticsResult(); m_pipelineStatistics = { rps.m_vertexCount, rps.m_primitiveCount, rps.m_vertexShaderInvocationCount, rps.m_rasterizedPrimitiveCount, rps.m_renderedPrimitiveCount, rps.m_pixelShaderInvocationCount, rps.m_computeShaderInvocationCount }; @@ -153,7 +153,9 @@ namespace AZ } - inline void ImGuiPipelineStatisticsView::DrawPipelineStatisticsWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& passEntryDatabase) + inline void ImGuiPipelineStatisticsView::DrawPipelineStatisticsWindow(bool& draw, + const PassEntry* rootPassEntry, AZStd::unordered_map& passEntryDatabase, + AZ::RHI::Ptr rootPass) { // Early out if nothing is supposed to be drawn if (!draw) @@ -188,12 +190,6 @@ namespace AZ continue; } - // Filter out disabled passes for the PipelineStatistics window if necessary. - if (!m_showDisabledPasses && !passEntry.IsPipelineStatisticsEnabled()) - { - continue; - } - // Filter out parent passes if necessary. if (!m_showParentPasses && passEntry.m_isParent) { @@ -230,6 +226,13 @@ namespace AZ // Start drawing the PipelineStatistics window. if (ImGui::Begin("PipelineStatistics Window", &draw, ImGuiWindowFlags_NoResize)) { + // Pause/unpause the profiling + if (ImGui::Button(m_paused ? "Resume" : "Pause")) + { + m_paused = !m_paused; + rootPass->SetPipelineStatisticsQueryEnabled(!m_paused); + } + ImGui::Columns(2, "HeaderColumns"); // Draw the statistics of the RootPass. @@ -426,23 +429,16 @@ namespace AZ } AZStd::string label; - if (passEntry->IsPipelineStatisticsEnabled()) + if (rootEntry && m_showAttributeContribution) { - if (rootEntry && m_showAttributeContribution) - { - label = AZStd::string::format("%llu (%u%%)", - static_cast(passEntry->m_pipelineStatistics[attributeIdx]), - static_cast(normalized * 100.0f)); - } - else - { - label = AZStd::string::format("%llu", - static_cast(passEntry->m_pipelineStatistics[attributeIdx])); - } + label = AZStd::string::format("%llu (%u%%)", + static_cast(passEntry->m_pipelineStatistics[attributeIdx]), + static_cast(normalized * 100.0f)); } else { - label = "-"; + label = AZStd::string::format("%llu", + static_cast(passEntry->m_pipelineStatistics[attributeIdx])); } if (rootEntry) @@ -523,7 +519,9 @@ namespace AZ // --- ImGuiTimestampView --- - inline void ImGuiTimestampView::DrawTimestampWindow(bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& timestampEntryDatabase) + inline void ImGuiTimestampView::DrawTimestampWindow( + bool& draw, const PassEntry* rootPassEntry, AZStd::unordered_map& timestampEntryDatabase, + AZ::RHI::Ptr rootPass) { // Early out if nothing is supposed to be drawn if (!draw) @@ -534,10 +532,28 @@ namespace AZ // Clear the references from the previous frame. m_passEntryReferences.clear(); + // pass entry grid based on its timestamp + AZStd::vector sortedPassEntries; + AZStd::vector> sortedPassGrid; + // Set the child of the parent, only if it passes the filter. for (auto& passEntryIt : timestampEntryDatabase) { PassEntry* passEntry = &passEntryIt.second; + + // Collect all pass entries with non-zero durations + if (passEntry->m_timestampResult.GetDurationInTicks() > 0) + { + sortedPassEntries.push_back(passEntry); + } + + // Skip the pass if the pass' timestamp duration is 0 + if (m_hideZeroPasses && (!passEntry->m_isParent) && passEntry->m_timestampResult.GetDurationInTicks() == 0) + { + continue; + } + + // Only add pass if it pass the filter. if (m_passFilter.PassFilter(passEntry->m_name.GetCStr())) { if (passEntry->m_parent && !passEntry->m_linked) @@ -545,19 +561,94 @@ namespace AZ passEntry->m_parent->LinkChild(passEntry); } - AZ_Assert(m_passEntryReferences.size() < TimestampEntryCount, "Too many PassEntry references. Increase the size of the array."); + AZ_Assert( + m_passEntryReferences.size() < TimestampEntryCount, + "Too many PassEntry references. Increase the size of the array."); m_passEntryReferences.push_back(passEntry); } } + // Sort the pass entries based on their starting time and duration + AZStd::sort(sortedPassEntries.begin(), sortedPassEntries.end(), [](const PassEntry* passEntry1, const PassEntry* passEntry2) { + if (passEntry1->m_timestampResult.GetTimestampBeginInTicks() == passEntry2->m_timestampResult.GetTimestampBeginInTicks()) + { + return passEntry1->m_timestampResult.GetDurationInTicks() < passEntry2->m_timestampResult.GetDurationInTicks(); + } + return passEntry1->m_timestampResult.GetTimestampBeginInTicks() < passEntry2->m_timestampResult.GetTimestampBeginInTicks(); + }); + + // calculate the total GPU duration. + RPI::TimestampResult gpuTimestamp; + if (sortedPassEntries.size() > 0) + { + gpuTimestamp = sortedPassEntries.front()->m_timestampResult; + gpuTimestamp.Add(sortedPassEntries.back()->m_timestampResult); + } + + // Add a pass to the pass grid which none of the pass's timestamp range won't overlap each other. + // Search each row until the pass can be added to the end of row without overlap the previous one. + for (auto& passEntry : sortedPassEntries) + { + auto row = sortedPassGrid.begin(); + for (; row != sortedPassGrid.end(); row++) + { + if (row->empty()) + { + break; + } + auto last = (*row).back(); + if (passEntry->m_timestampResult.GetTimestampBeginInTicks() >= + last->m_timestampResult.GetTimestampBeginInTicks() + last->m_timestampResult.GetDurationInTicks()) + { + row->push_back(passEntry); + break; + } + } + if (row == sortedPassGrid.end()) + { + sortedPassGrid.push_back(); + sortedPassGrid.back().push_back(passEntry); + } + } + + // Refresh timestamp query + bool needEnable = false; + if (!m_paused) + { + if (m_refreshType == RefreshType::OncePerSecond) + { + auto now = AZStd::GetTimeNowMicroSecond(); + if (m_lastUpdateTimeMicroSecond == 0 || now - m_lastUpdateTimeMicroSecond > 1000000) + { + needEnable = true; + m_lastUpdateTimeMicroSecond = now; + } + } + else if (m_refreshType == RefreshType::Realtime) + { + needEnable = true; + } + } + + if (rootPass->IsTimestampQueryEnabled() != needEnable) + { + rootPass->SetTimestampQueryEnabled(needEnable); + } + const ImVec2 windowSize(680.0f, 620.0f); ImGui::SetNextWindowSize(windowSize, ImGuiCond_Always); if (ImGui::Begin("Timestamp View", &draw, ImGuiWindowFlags_NoResize)) { // Draw the header. { + // Pause/unpause the profiling + if (ImGui::Button(m_paused? "Resume":"Pause")) + { + m_paused = !m_paused; + } + // Draw the frame time (GPU). - const AZStd::string formattedTimestamp = FormatTimestampLabel(rootPassEntry->m_interpolatedTimestampInNanoseconds); + const AZStd::string formattedTimestamp = FormatTimestampLabel(gpuTimestamp.GetDurationInNanoseconds()); const AZStd::string headerFrameTime = AZStd::string::format("Total frame duration (GPU): %s", formattedTimestamp.c_str()); ImGui::Text(headerFrameTime.c_str()); @@ -566,6 +657,17 @@ namespace AZ ImGui::SameLine(); ImGui::RadioButton("Flat", reinterpret_cast(&m_viewType), static_cast(ProfilerViewType::Flat)); + // Draw the refresh option + ImGui::RadioButton("Realtime", reinterpret_cast(&m_refreshType), static_cast(RefreshType::Realtime)); + ImGui::SameLine(); + ImGui::RadioButton("Once Per Second", reinterpret_cast(&m_refreshType), static_cast(RefreshType::OncePerSecond)); + + // Show/hide non-parent passes which have zero execution time + ImGui::Checkbox("Hide Zero Cost Passes", &m_hideZeroPasses); + + // Show/hide the timeline bar of all the passes which has non-zero execution time + ImGui::Checkbox("Show Timeline", &m_showTimeline); + // Draw advanced options. const ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_None; GpuProfilerImGuiHelper::TreeNode("Advanced options", flags, [this](bool unrolled) @@ -587,6 +689,56 @@ namespace AZ ImGui::Separator(); + // Draw the pass entry grid + if (!sortedPassEntries.empty() && m_showTimeline) + { + const float passBarHeight = 20.f; + const float passBarSpace = 3.f; + float areaWidth = ImGui::GetContentRegionAvail().x - 20.f; + + if (ImGui::BeginChild("Timeline", ImVec2(areaWidth, (passBarHeight + passBarSpace) * sortedPassGrid.size()), false)) + { + // start tick and end tick for the area + uint64_t areaStartTick = sortedPassEntries.front()->m_timestampResult.GetTimestampBeginInTicks(); + uint64_t areaEndTick = sortedPassEntries.back()->m_timestampResult.GetTimestampBeginInTicks() + + sortedPassEntries.back()->m_timestampResult.GetDurationInTicks(); + uint64_t areaDurationInTicks = areaEndTick - areaStartTick; + + float rowStartY = 0.f; + for (auto& row : sortedPassGrid) + { + // row start y + for (auto passEntry : row) + { + // button start and end + float buttonStartX = (passEntry->m_timestampResult.GetTimestampBeginInTicks() - areaStartTick) * areaWidth / + areaDurationInTicks; + float buttonWidth = passEntry->m_timestampResult.GetDurationInTicks() * areaWidth / areaDurationInTicks; + ImGui::SetCursorPosX(buttonStartX); + ImGui::SetCursorPosY(rowStartY); + + // Adds a button and the hover colors. + ImGui::Button(passEntry->m_name.GetCStr(), ImVec2(buttonWidth, passBarHeight)); + + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text("Name: %s", passEntry->m_name.GetCStr()); + ImGui::Text("Path: %s", passEntry->m_path.GetCStr()); + ImGui::Text("Duration in ticks: %u", passEntry->m_timestampResult.GetDurationInTicks()); + ImGui::Text("Duration in microsecond: %.3f us", passEntry->m_timestampResult.GetDurationInNanoseconds()/1000.f); + ImGui::EndTooltip(); + } + } + + rowStartY += passBarHeight + passBarSpace; + } + } + ImGui::EndChild(); + + ImGui::Separator(); + } + // Draw the timestamp view. { static const AZStd::array(TimestampMetricUnit::Count)> MetricUnitText = @@ -713,20 +865,18 @@ namespace AZ const auto drawWorkloadBar = [this](const AZStd::string& entryTime, const PassEntry* entry) { ImGui::NextColumn(); - ImGui::Text(entryTime.c_str()); - ImGui::NextColumn(); - - // Only draw the workload bar when the entry is enabled. - if (entry->IsTimestampEnabled()) + if (entry->m_isParent) { - DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds)); + ImGui::NextColumn(); + ImGui::NextColumn(); } else { - ImGui::ProgressBar(0.0f, ImVec2(-1.0f, 0.0f), "Disabled"); + ImGui::Text(entryTime.c_str()); + ImGui::NextColumn(); + DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds)); + ImGui::NextColumn(); } - - ImGui::NextColumn(); }; static const auto createHoverMarker = [](const char* text) @@ -800,23 +950,17 @@ namespace AZ // Draw the flat view. for (const PassEntry* entry : m_passEntryReferences) { + if (entry->m_isParent) + { + continue; + } const AZStd::string entryTime = FormatTimestampLabel(entry->m_interpolatedTimestampInNanoseconds); ImGui::Text(entry->m_name.GetCStr()); ImGui::NextColumn(); ImGui::Text(entryTime.c_str()); ImGui::NextColumn(); - - // Only draw the workload bar if the entry is enabled. - if (entry->IsTimestampEnabled()) - { - DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds)); - } - else - { - ImGui::ProgressBar(0.0f, ImVec2(-1.0f, 0.0f), "Disabled"); - } - + DrawFrameWorkloadBar(NormalizeFrameWorkload(entry->m_interpolatedTimestampInNanoseconds)); ImGui::NextColumn(); } } @@ -890,23 +1034,33 @@ namespace AZ // Update the PassEntry database. const PassEntry* rootPassEntryRef = CreatePassEntries(rootPass); + bool wasDraw = draw; + GpuProfilerImGuiHelper::Begin("Gpu Profiler", &draw, ImGuiWindowFlags_NoResize, [this, &rootPass]() { - ImGui::Checkbox("Enable TimestampView", &m_drawTimestampView); + if (ImGui::Checkbox("Enable TimestampView", &m_drawTimestampView)) + { + rootPass->SetTimestampQueryEnabled(m_drawTimestampView); + } ImGui::Spacing(); - ImGui::Checkbox("Enable PipelineStatisticsView", &m_drawPipelineStatisticsView); + if(ImGui::Checkbox("Enable PipelineStatisticsView", &m_drawPipelineStatisticsView)) + { + rootPass->SetPipelineStatisticsQueryEnabled(m_drawPipelineStatisticsView); + } }); // Draw the PipelineStatistics window. - m_timestampView.DrawTimestampWindow(m_drawTimestampView, rootPassEntryRef, m_passEntryDatabase); + m_timestampView.DrawTimestampWindow(m_drawTimestampView, rootPassEntryRef, m_passEntryDatabase, rootPass); // Draw the PipelineStatistics window. - m_pipelineStatisticsView.DrawPipelineStatisticsWindow(m_drawPipelineStatisticsView, rootPassEntryRef, m_passEntryDatabase); + m_pipelineStatisticsView.DrawPipelineStatisticsWindow(m_drawPipelineStatisticsView, rootPassEntryRef, m_passEntryDatabase, rootPass); - // [GFX TODO][ATOM-13792] Optimization: ImGui GpuProfiler Pass hierarchy traversal. - // Enable/Disable the Timestamp and PipelineStatistics on the RootPass - rootPass->SetTimestampQueryEnabled(draw && m_drawTimestampView); - rootPass->SetPipelineStatisticsQueryEnabled(draw && m_drawPipelineStatisticsView); + //closing window + if (wasDraw && !draw) + { + rootPass->SetTimestampQueryEnabled(false); + rootPass->SetPipelineStatisticsQueryEnabled(false); + } } inline void ImGuiGpuProfiler::InterpolatePassEntries(AZStd::unordered_map& passEntryDatabase, float weight) const @@ -918,7 +1072,7 @@ namespace AZ { // Interpolate the timestamps. const double interpolated = Lerp(static_cast(oldEntryIt->second.m_interpolatedTimestampInNanoseconds), - static_cast(entry.second.m_timestampResult.GetTimestampInNanoseconds()), + static_cast(entry.second.m_timestampResult.GetDurationInNanoseconds()), static_cast(weight)); entry.second.m_interpolatedTimestampInNanoseconds = static_cast(interpolated); } diff --git a/Gems/ImGui/Code/Source/ImGuiManager.cpp b/Gems/ImGui/Code/Source/ImGuiManager.cpp index 697cc61f86..c446c98175 100644 --- a/Gems/ImGui/Code/Source/ImGuiManager.cpp +++ b/Gems/ImGui/Code/Source/ImGuiManager.cpp @@ -222,6 +222,10 @@ void ImGuiManager::Initialize() io.DisplaySize.x = 1920; io.DisplaySize.y = 1080; + // Create a default font + io.Fonts->AddFontDefault(); + io.Fonts->Build(); + // Broadcast ImGui Ready to Listeners ImGuiUpdateListenerBus::Broadcast(&IImGuiUpdateListener::OnImGuiInitialize); m_currentControllerIndex = -1; From 7c5f7181ebb538d04586b9e088ce740db82c6320 Mon Sep 17 00:00:00 2001 From: hultonha Date: Thu, 15 Apr 2021 10:32:46 +0100 Subject: [PATCH 19/74] updates following review feedback - remove explicit resize and update concrete type to alias --- .../AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp | 4 ++-- .../AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp index 09adaf38cb..6077a66682 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/ByteStreamSerializer.cpp @@ -31,10 +31,10 @@ namespace AZ switch (inputValue.GetType()) { case rapidjson::kStringType: { - JsonByteStream* valAsByteStream = static_cast(outputValue); - JsonByteStream buffer(inputValue.GetStringLength()); + JsonByteStream buffer; if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength())) { + JsonByteStream* valAsByteStream = static_cast(outputValue); *valAsByteStream = AZStd::move(buffer); return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream."); } diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp index e5a1f5e6bb..6e3c8cec60 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.cpp @@ -69,7 +69,7 @@ namespace AZ jsonContext->Serializer()->HandlesType(); jsonContext->Serializer()->HandlesType(); - jsonContext->Serializer()->HandlesType>(); + jsonContext->Serializer()->HandlesType(); jsonContext->Serializer() ->HandlesType() From 11081aeddd95360825eaeafe486ea4feda93b55c Mon Sep 17 00:00:00 2001 From: jjjoness <82226755+jjjoness@users.noreply.github.com> Date: Thu, 15 Apr 2021 11:01:08 +0100 Subject: [PATCH 20/74] Changed logo to O3DE --- Code/Sandbox/Editor/AboutDialog.cpp | 2 +- Code/Sandbox/Editor/AboutDialog.ui | 63 ++++++++++++----------- Code/Sandbox/Editor/StartupLogoDialog.cpp | 2 +- Code/Sandbox/Editor/StartupLogoDialog.qrc | 2 +- Code/Sandbox/Editor/StartupLogoDialog.ui | 8 +-- Code/Sandbox/Editor/lumberyard_logo.svg | 41 --------------- Code/Sandbox/Editor/o3de_logo.svg | 22 ++++++++ 7 files changed, 63 insertions(+), 77 deletions(-) delete mode 100644 Code/Sandbox/Editor/lumberyard_logo.svg create mode 100644 Code/Sandbox/Editor/o3de_logo.svg diff --git a/Code/Sandbox/Editor/AboutDialog.cpp b/Code/Sandbox/Editor/AboutDialog.cpp index e1cd4c7bb0..d9cf722d1f 100644 --- a/Code/Sandbox/Editor/AboutDialog.cpp +++ b/Code/Sandbox/Editor/AboutDialog.cpp @@ -56,7 +56,7 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice, m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); // Draw the Open 3D Engine logo from svg - m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg")); + m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg")); // Prevent re-sizing setFixedSize(m_enforcedWidth, m_enforcedHeight); diff --git a/Code/Sandbox/Editor/AboutDialog.ui b/Code/Sandbox/Editor/AboutDialog.ui index 0eb2881600..67767c0de1 100644 --- a/Code/Sandbox/Editor/AboutDialog.ui +++ b/Code/Sandbox/Editor/AboutDialog.ui @@ -60,35 +60,35 @@ 5 - - - - 4 - - - 12 - - - 9 - - - - - - 250 - 60 - - - - - 250 - 60 - - - - - - + + + + 4 + + + 12 + + + 9 + + + + + + 161 + 49 + + + + + 161 + 49 + + + + + + @@ -251,6 +251,11 @@ + + QSvgWidget + QWidget +
qsvgwidget.h
+
ClickableLabel QLabel diff --git a/Code/Sandbox/Editor/StartupLogoDialog.cpp b/Code/Sandbox/Editor/StartupLogoDialog.cpp index 38cf1bc5f6..c3d584b030 100644 --- a/Code/Sandbox/Editor/StartupLogoDialog.cpp +++ b/Code/Sandbox/Editor/StartupLogoDialog.cpp @@ -49,7 +49,7 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); // Draw the Open 3D Engine logo from svg - m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/lumberyard_logo.svg")); + m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg")); m_ui->m_TransparentConfidential->setObjectName("copyrightNotice"); m_ui->m_TransparentConfidential->setTextFormat(Qt::RichText); diff --git a/Code/Sandbox/Editor/StartupLogoDialog.qrc b/Code/Sandbox/Editor/StartupLogoDialog.qrc index 55c93b427c..29730ef9c7 100644 --- a/Code/Sandbox/Editor/StartupLogoDialog.qrc +++ b/Code/Sandbox/Editor/StartupLogoDialog.qrc @@ -1,6 +1,6 @@ - lumberyard_logo.svg + o3de_logo.svg splashscreen_1_27.png diff --git a/Code/Sandbox/Editor/StartupLogoDialog.ui b/Code/Sandbox/Editor/StartupLogoDialog.ui index f14355de8c..6e01808a84 100644 --- a/Code/Sandbox/Editor/StartupLogoDialog.ui +++ b/Code/Sandbox/Editor/StartupLogoDialog.ui @@ -42,14 +42,14 @@ - 250 - 60 + 161 + 49 - 250 - 60 + 161 + 50 diff --git a/Code/Sandbox/Editor/lumberyard_logo.svg b/Code/Sandbox/Editor/lumberyard_logo.svg deleted file mode 100644 index fe5f2fbdcd..0000000000 --- a/Code/Sandbox/Editor/lumberyard_logo.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - background - - - - Layer 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Code/Sandbox/Editor/o3de_logo.svg b/Code/Sandbox/Editor/o3de_logo.svg new file mode 100644 index 0000000000..ac746c07a5 --- /dev/null +++ b/Code/Sandbox/Editor/o3de_logo.svg @@ -0,0 +1,22 @@ + + + Group 12 + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 20c1454e4b0b626a9bec6c7eb81c400aa6516f58 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Thu, 15 Apr 2021 03:41:20 -0700 Subject: [PATCH 21/74] Added the ShaderRead buffer bind flag to the static and dynamic input assembly pools, and one creation of a static input assembly buffer. --- Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp | 4 ++-- Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp index fd2d029ddb..491f57deec 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/BufferSystem.cpp @@ -100,12 +100,12 @@ namespace AZ bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write; break; case CommonBufferPoolType::StaticInputAssembly: - bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly; + bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::ShaderRead; bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device; bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write; break; case CommonBufferPoolType::DynamicInputAssembly: - bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::DynamicInputAssembly; + bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::DynamicInputAssembly | RHI::BufferBindFlags::ShaderRead; bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host; bufferPoolDesc.m_hostMemoryAccess = RHI::HostMemoryAccess::Write; break; diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h index 0a6cfafee7..bea6de5898 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h @@ -98,7 +98,7 @@ namespace WhiteBox // specify the data format for vertex stream data AZ::RHI::BufferDescriptor bufferDescriptor; - bufferDescriptor.m_bindFlags = AZ::RHI::BufferBindFlags::InputAssembly; + bufferDescriptor.m_bindFlags = AZ::RHI::BufferBindFlags::InputAssembly | AZ::RHI::BufferBindFlags::ShaderRead; bufferDescriptor.m_byteCount = bufferSize; bufferDescriptor.m_alignment = elementSize; From 23cf2d5d68d807e40252affdc00fe362ca6c784b Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Tue, 13 Apr 2021 15:03:21 +0100 Subject: [PATCH 22/74] SystemComponent is now only build in PhysX.Static, instead of most of the Physx projects. --- .../AzFramework/Physics/SystemBus.h | 7 -- Gems/Blast/Code/Tests/Mocks/BlastMocks.h | 3 - .../Code/Tests/Mocks/PhysicsSystem.h | 1 - Gems/PhysX/Code/Editor/EditorWindow.cpp | 3 + Gems/PhysX/Code/Editor/EditorWindow.h | 7 ++ .../Components/EditorSystemComponent.cpp | 20 +++- .../Source/Components/EditorSystemComponent.h | 5 + Gems/PhysX/Code/Source/SystemComponent.cpp | 91 ------------------- Gems/PhysX/Code/Source/SystemComponent.h | 16 ---- .../Code/Tests/CharacterControllerTests.cpp | 50 +++++++++- .../Code/physx_editor_shared_files.cmake | 2 - .../PhysX/Code/physx_editor_tests_files.cmake | 2 - Gems/PhysX/Code/physx_files.cmake | 2 + Gems/PhysX/Code/physx_shared_files.cmake | 2 - Gems/PhysX/Code/physx_tests_files.cmake | 2 - 15 files changed, 82 insertions(+), 131 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h index c303e14636..717f9e023c 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h @@ -142,13 +142,6 @@ namespace Physics virtual AZStd::shared_ptr CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0; - /// Adds an appropriate collider component to the entity based on the provided shape configuration. - /// @param entity Entity where the component should be added to. - /// @param colliderConfiguration Configuration of the collider. - /// @param shapeConfiguration Configuration of the shape of the collider. - /// @param addEditorComponents Tells whether to add the Editor version of the collider component or the Game one. - virtual void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents = false) = 0; - /// Releases the mesh object created by the physics backend. /// @param nativeMeshObject Pointer to the mesh object. virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0; diff --git a/Gems/Blast/Code/Tests/Mocks/BlastMocks.h b/Gems/Blast/Code/Tests/Mocks/BlastMocks.h index 0ac1f6c27e..95a16c311f 100644 --- a/Gems/Blast/Code/Tests/Mocks/BlastMocks.h +++ b/Gems/Blast/Code/Tests/Mocks/BlastMocks.h @@ -213,9 +213,6 @@ namespace Blast CreateShape, AZStd::shared_ptr( const Physics::ColliderConfiguration&, const Physics::ShapeConfiguration&)); - MOCK_METHOD4( - AddColliderComponentToEntity, - void(AZ::Entity*, const Physics::ColliderConfiguration&, const Physics::ShapeConfiguration&, bool)); MOCK_METHOD1(ReleaseNativeMeshObject, void(void*)); MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr(const Physics::MaterialConfiguration&)); MOCK_METHOD0(GetDefaultMaterial, AZStd::shared_ptr()); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h b/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h index 0b20632884..1219e34448 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/PhysicsSystem.h @@ -33,7 +33,6 @@ namespace Physics BusDisconnect(); } MOCK_METHOD2(CreateShape, AZStd::shared_ptr(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration)); - MOCK_METHOD4(AddColliderComponentToEntity, void(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents)); MOCK_METHOD1(ReleaseNativeMeshObject, void(void* nativeMeshObject)); MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr(const Physics::MaterialConfiguration& materialConfiguration)); MOCK_METHOD0(GetDefaultMaterial, AZStd::shared_ptr()); diff --git a/Gems/PhysX/Code/Editor/EditorWindow.cpp b/Gems/PhysX/Code/Editor/EditorWindow.cpp index 41b2991c2a..c8d6715838 100644 --- a/Gems/PhysX/Code/Editor/EditorWindow.cpp +++ b/Gems/PhysX/Code/Editor/EditorWindow.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,8 @@ #include #include #include +#include +#include namespace PhysX { diff --git a/Gems/PhysX/Code/Editor/EditorWindow.h b/Gems/PhysX/Code/Editor/EditorWindow.h index 34f1906d43..86f72f70f2 100644 --- a/Gems/PhysX/Code/Editor/EditorWindow.h +++ b/Gems/PhysX/Code/Editor/EditorWindow.h @@ -19,6 +19,7 @@ namespace AzPhysics { class CollisionConfiguration; + struct SceneConfiguration; } namespace Ui @@ -28,6 +29,12 @@ namespace Ui namespace PhysX { + struct PhysXSystemConfiguration; + namespace Debug + { + struct DebugConfiguration; + } + namespace Editor { /// Window pane wrapper for the PhysX Configuration Widget. diff --git a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp index 2f4b389795..516b958adb 100644 --- a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp +++ b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp @@ -18,13 +18,15 @@ #include #include #include -#include -#include #include #include #include +#include +#include +#include +#include #include namespace PhysX @@ -116,18 +118,20 @@ namespace PhysX { AzPhysics::SceneConfiguration editorWorldConfiguration = physicsSystem->GetDefaultSceneConfiguration(); editorWorldConfiguration.m_sceneName = AzPhysics::EditorPhysicsSceneName; - editorWorldConfiguration.m_sceneName = "EditorScene"; m_editorWorldSceneHandle = physicsSystem->AddScene(editorWorldConfiguration); } PhysX::RegisterConfigStringLineEditHandler(); // Register custom unique string line edit control + PhysX::Editor::RegisterPropertyTypes(); + AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect(); } void EditorSystemComponent::Deactivate() { AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect(); + AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); Physics::EditorWorldBus::Handler::BusDisconnect(); if (auto* physicsSystem = AZ::Interface::Get()) @@ -164,6 +168,16 @@ namespace PhysX } } + void EditorSystemComponent::PopulateEditorGlobalContextMenu([[maybe_unused]] QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags) + { + + } + + void EditorSystemComponent::NotifyRegisterViews() + { + PhysX::Editor::EditorWindow::RegisterViewClass(); + } + AZ::Data::AssetId EditorSystemComponent::GenerateSurfaceTypesLibrary() { AZ::Data::AssetId resultAssetId; diff --git a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.h b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.h index cba542ce84..9ebca05ccd 100644 --- a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.h +++ b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.h @@ -30,6 +30,7 @@ namespace PhysX : public AZ::Component , public Physics::EditorWorldBus::Handler , private AzToolsFramework::EditorEntityContextNotificationBus::Handler + , private AzToolsFramework::EditorEvents::Bus::Handler { public: AZ_COMPONENT(EditorSystemComponent, "{560F08DC-94F5-4D29-9AD4-CDFB3B57C654}"); @@ -60,6 +61,10 @@ namespace PhysX void OnStartPlayInEditorBegin() override; void OnStopPlayInEditor() override; + // AztoolsFramework::EditorEvents::Bus::Handler + void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override; + void NotifyRegisterViews() override; + AZ::Data::AssetId GenerateSurfaceTypesLibrary(); AzPhysics::SceneHandle m_editorWorldSceneHandle = AzPhysics::InvalidSceneHandle; diff --git a/Gems/PhysX/Code/Source/SystemComponent.cpp b/Gems/PhysX/Code/Source/SystemComponent.cpp index 6de54a7593..8210492fe7 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.cpp +++ b/Gems/PhysX/Code/Source/SystemComponent.cpp @@ -15,38 +15,18 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include #include #include -#include -#include #include #include #include #include -#include -#include -#include #include #include #include #include #include -#ifdef PHYSX_EDITOR -#include -#include -#include -#include -#include -#endif - #include #include @@ -233,21 +213,11 @@ namespace PhysX Physics::CollisionRequestBus::Handler::BusConnect(); Physics::CharacterSystemRequestBus::Handler::BusConnect(); -#ifdef PHYSX_EDITOR - PhysX::Editor::RegisterPropertyTypes(); - AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect(); - AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); -#endif - ActivatePhysXSystem(); } void SystemComponent::Deactivate() { -#ifdef PHYSX_EDITOR - AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); - AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect(); -#endif AZ::TickBus::Handler::BusDisconnect(); Physics::CharacterSystemRequestBus::Handler::BusDisconnect(); Physics::CollisionRequestBus::Handler::BusDisconnect(); @@ -272,19 +242,6 @@ namespace PhysX m_assetHandlers.clear(); //this need to be after m_physXSystem->Shutdown(); For it will drop the default material library reference. } -#ifdef PHYSX_EDITOR - - // AztoolsFramework::EditorEvents::Bus::Handler overrides - void SystemComponent::PopulateEditorGlobalContextMenu([[maybe_unused]] QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags) - { - } - - void SystemComponent::NotifyRegisterViews() - { - PhysX::Editor::EditorWindow::RegisterViewClass(); - } -#endif - physx::PxConvexMesh* SystemComponent::CreateConvexMesh(const void* vertices, AZ::u32 vertexNum, AZ::u32 vertexStride) { physx::PxConvexMeshDesc desc; @@ -464,54 +421,6 @@ namespace PhysX } } - void SystemComponent::AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, [[maybe_unused]] bool addEditorComponents) - { - [[maybe_unused]] Physics::ShapeType shapeType = shapeConfiguration.GetShapeType(); - -#ifdef PHYSX_EDITOR - if (addEditorComponents) - { - entity->CreateComponent(colliderConfiguration, shapeConfiguration); - } - else -#else - { - if (shapeType == Physics::ShapeType::Sphere) - { - const Physics::SphereShapeConfiguration& sphereConfiguration = static_cast(shapeConfiguration); - auto sphereColliderComponent = entity->CreateComponent(); - sphereColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( - AZStd::make_shared(colliderConfiguration), - AZStd::make_shared(sphereConfiguration)) }); - } - else if (shapeType == Physics::ShapeType::Box) - { - const Physics::BoxShapeConfiguration& boxConfiguration = static_cast(shapeConfiguration); - auto boxColliderComponent = entity->CreateComponent(); - boxColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( - AZStd::make_shared(colliderConfiguration), - AZStd::make_shared(boxConfiguration)) }); - } - else if (shapeType == Physics::ShapeType::Capsule) - { - const Physics::CapsuleShapeConfiguration& capsuleConfiguration = static_cast(shapeConfiguration); - auto capsuleColliderComponent = entity->CreateComponent(); - capsuleColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( - AZStd::make_shared(colliderConfiguration), - AZStd::make_shared(capsuleConfiguration)) }); - } - } - - AZ_Error("PhysX System", !addEditorComponents, "AddColliderComponentToEntity(): Trying to add an Editor collider component in a stand alone build.", - static_cast(shapeType)); - -#endif - { - AZ_Error("PhysX System", shapeType == Physics::ShapeType::Sphere || shapeType == Physics::ShapeType::Box || shapeType == Physics::ShapeType::Capsule, - "AddColliderComponentToEntity(): Using Shape of type %d is not implemented.", static_cast(shapeType)); - } - } - // Physics::CharacterSystemRequestBus AZStd::unique_ptr SystemComponent::CreateCharacter(const Physics::CharacterConfiguration& characterConfig, const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) diff --git a/Gems/PhysX/Code/Source/SystemComponent.h b/Gems/PhysX/Code/Source/SystemComponent.h index c074a2032d..8c4ac0d836 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.h +++ b/Gems/PhysX/Code/Source/SystemComponent.h @@ -36,9 +36,6 @@ #include #include -#ifdef PHYSX_EDITOR -#include -#endif namespace AzPhysics { struct StaticRigidBodyConfiguration; @@ -61,10 +58,6 @@ namespace PhysX , public Physics::SystemRequestBus::Handler , public PhysX::SystemRequestsBus::Handler , public Physics::CharacterSystemRequestBus::Handler -#ifdef PHYSX_EDITOR - , public AzToolsFramework::EditorEntityContextNotificationBus::Handler - , private AzToolsFramework::EditorEvents::Bus::Handler -#endif , private Physics::CollisionRequestBus::Handler , private AZ::TickBus::Handler { @@ -100,8 +93,6 @@ namespace PhysX bool CookTriangleMeshToMemory(const AZ::Vector3* vertices, AZ::u32 vertexCount, const AZ::u32* indices, AZ::u32 indexCount, AZStd::vector& result) override; - void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration, bool addEditorComponents = false) override; - physx::PxFilterData CreateFilterData(const AzPhysics::CollisionLayer& layer, const AzPhysics::CollisionGroup& group) override; physx::PxCooking* GetCooking() override; @@ -125,13 +116,6 @@ namespace PhysX void Activate() override; void Deactivate() override; -#ifdef PHYSX_EDITOR - - // AztoolsFramework::EditorEvents::Bus::Handler overrides - void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override; - void NotifyRegisterViews() override; -#endif - // Physics::SystemRequestBus::Handler AZStd::shared_ptr CreateShape(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration) override; AZStd::shared_ptr CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) override; diff --git a/Gems/PhysX/Code/Tests/CharacterControllerTests.cpp b/Gems/PhysX/Code/Tests/CharacterControllerTests.cpp index d5b961ada7..218571c01c 100644 --- a/Gems/PhysX/Code/Tests/CharacterControllerTests.cpp +++ b/Gems/PhysX/Code/Tests/CharacterControllerTests.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -31,6 +33,51 @@ namespace PhysX { + namespace Internal + { + void AddColliderComponentToEntity(AZ::Entity* entity, const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& shapeConfiguration) + { + Physics::ShapeType shapeType = shapeConfiguration.GetShapeType(); + + switch (shapeType) + { + case Physics::ShapeType::Sphere: + { + const Physics::SphereShapeConfiguration& sphereConfiguration = static_cast(shapeConfiguration); + auto sphereColliderComponent = entity->CreateComponent(); + sphereColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( + AZStd::make_shared(colliderConfiguration), + AZStd::make_shared(sphereConfiguration)) }); + } + break; + case Physics::ShapeType::Box: + { + const Physics::BoxShapeConfiguration& boxConfiguration = static_cast(shapeConfiguration); + auto boxColliderComponent = entity->CreateComponent(); + boxColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( + AZStd::make_shared(colliderConfiguration), + AZStd::make_shared(boxConfiguration)) }); + } + break; + case Physics::ShapeType::Capsule: + { + const Physics::CapsuleShapeConfiguration& capsuleConfiguration = static_cast(shapeConfiguration); + auto capsuleColliderComponent = entity->CreateComponent(); + capsuleColliderComponent->SetShapeConfigurationList({ AZStd::make_pair( + AZStd::make_shared(colliderConfiguration), + AZStd::make_shared(capsuleConfiguration)) }); + } + break; + default: + { + AZ_Error("PhysX", false, + "AddColliderComponentToEntity(): Using Shape of type %d is not implemented.", static_cast(shapeType)); + } + break; + } + } + } + // transform for a floor centred at x = 0, y = 0, with top at level z = 0 static const AZ::Transform DefaultFloorTransform = AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(-0.5f)); @@ -367,8 +414,7 @@ namespace PhysX auto triggerEntity = AZStd::make_unique("TriggerEntity"); triggerEntity->CreateComponent()->SetWorldTM(AZ::Transform::Identity()); triggerEntity->CreateComponent(PhysX::StaticRigidBodyComponentTypeId); - Physics::SystemRequestBus::Broadcast(&Physics::SystemRequests::AddColliderComponentToEntity, - triggerEntity.get(), triggerConfig, boxConfig, false); + Internal::AddColliderComponentToEntity(triggerEntity.get(), triggerConfig, boxConfig); triggerEntity->Init(); triggerEntity->Activate(); diff --git a/Gems/PhysX/Code/physx_editor_shared_files.cmake b/Gems/PhysX/Code/physx_editor_shared_files.cmake index 2a84c4e380..b743efb6aa 100644 --- a/Gems/PhysX/Code/physx_editor_shared_files.cmake +++ b/Gems/PhysX/Code/physx_editor_shared_files.cmake @@ -11,6 +11,4 @@ set(FILES Source/Module.cpp - Source/SystemComponent.cpp - Source/SystemComponent.h ) diff --git a/Gems/PhysX/Code/physx_editor_tests_files.cmake b/Gems/PhysX/Code/physx_editor_tests_files.cmake index 202e688a76..1e6ccde75f 100644 --- a/Gems/PhysX/Code/physx_editor_tests_files.cmake +++ b/Gems/PhysX/Code/physx_editor_tests_files.cmake @@ -11,8 +11,6 @@ set(FILES Source/Module.cpp - Source/SystemComponent.cpp - Source/SystemComponent.h Tests/PhysXTestCommon.cpp Tests/PhysXTestCommon.h Tests/ColliderScalingTests.cpp diff --git a/Gems/PhysX/Code/physx_files.cmake b/Gems/PhysX/Code/physx_files.cmake index c850479f53..ed2d59b8aa 100644 --- a/Gems/PhysX/Code/physx_files.cmake +++ b/Gems/PhysX/Code/physx_files.cmake @@ -12,6 +12,8 @@ set(FILES Source/PhysX_precompiled.cpp Source/PhysX_precompiled.h + Source/SystemComponent.cpp + Source/SystemComponent.h Include/PhysX/SystemComponentBus.h Include/PhysX/ColliderComponentBus.h Include/PhysX/NativeTypeIdentifiers.h diff --git a/Gems/PhysX/Code/physx_shared_files.cmake b/Gems/PhysX/Code/physx_shared_files.cmake index 9451f44648..1b7c17f5f5 100644 --- a/Gems/PhysX/Code/physx_shared_files.cmake +++ b/Gems/PhysX/Code/physx_shared_files.cmake @@ -11,8 +11,6 @@ set(FILES Source/Module.cpp - Source/SystemComponent.cpp - Source/SystemComponent.h Source/ComponentDescriptors.cpp Source/ComponentDescriptors.h ) diff --git a/Gems/PhysX/Code/physx_tests_files.cmake b/Gems/PhysX/Code/physx_tests_files.cmake index adf0f587d2..406aed64a7 100644 --- a/Gems/PhysX/Code/physx_tests_files.cmake +++ b/Gems/PhysX/Code/physx_tests_files.cmake @@ -10,8 +10,6 @@ # set(FILES - Source/SystemComponent.cpp - Source/SystemComponent.h Source/ComponentDescriptors.cpp Source/ComponentDescriptors.h Tests/PhysXComponentBusTests.cpp From ebebc05cd1709369171fdd87885c5de92a295a51 Mon Sep 17 00:00:00 2001 From: Ulugbek Adilbekov Date: Thu, 15 Apr 2021 16:16:31 +0100 Subject: [PATCH 23/74] Reenable Blast Automated tests (#42) Co-authored-by: Ulugbek Adilbekov --- .../Gem/Code/runtime_dependencies.cmake | 2 +- .../Gem/Code/tool_dependencies.cmake | 1 + .../Gem/PythonTests/Blast/TestSuite_Active.py | 14 +++++----- .../Gem/PythonTests/CMakeLists.txt | 26 +++++++++---------- AutomatedTesting/default.blastconfiguration | 2 +- .../Editor/EditorBlastMeshDataComponent.cpp | 2 +- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/AutomatedTesting/Gem/Code/runtime_dependencies.cmake b/AutomatedTesting/Gem/Code/runtime_dependencies.cmake index d281f64954..c8e66740e4 100644 --- a/AutomatedTesting/Gem/Code/runtime_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/runtime_dependencies.cmake @@ -42,7 +42,6 @@ set(GEM_DEPENDENCIES Gem::SurfaceData Gem::GradientSignal Gem::Vegetation - Gem::Atom_RHI.Private Gem::Atom_RPI.Private Gem::Atom_Feature_Common @@ -54,4 +53,5 @@ set(GEM_DEPENDENCIES Gem::ImguiAtom Gem::Atom_AtomBridge Gem::AtomFont + Gem::Blast ) diff --git a/AutomatedTesting/Gem/Code/tool_dependencies.cmake b/AutomatedTesting/Gem/Code/tool_dependencies.cmake index 22132da686..8c5da63f42 100644 --- a/AutomatedTesting/Gem/Code/tool_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/tool_dependencies.cmake @@ -68,4 +68,5 @@ set(GEM_DEPENDENCIES Gem::ImguiAtom Gem::AtomFont Gem::AtomToolsFramework.Editor + Gem::Blast.Editor ) diff --git a/AutomatedTesting/Gem/PythonTests/Blast/TestSuite_Active.py b/AutomatedTesting/Gem/PythonTests/Blast/TestSuite_Active.py index 947ea8363d..066a55c78c 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/TestSuite_Active.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/TestSuite_Active.py @@ -27,28 +27,28 @@ from base import TestAutomationBase class TestAutomation(TestAutomationBase): def test_ActorSplitsAfterCollision(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterCollision as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterRadialDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterRadialDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterCapsuleDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterCapsuleDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterImpactSpreadDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterImpactSpreadDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterShearDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterShearDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterTriangleDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterTriangleDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) + self._run_test(request, workspace, editor, test_module) def test_ActorSplitsAfterStressDamage(self, request, workspace, editor, launcher_platform): from . import ActorSplitsAfterStressDamage as test_module - self._run_test(request, workspace, editor, test_module, expected_lines=[], unexpected_lines=["Assert"]) \ No newline at end of file + self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index 3bd5f84312..ea9c365978 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -135,20 +135,18 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) endif() ## Blast ## -# Disabled until AutomatedTesting runs with Atom. -# if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) -# ly_add_pytest( -# NAME AutomatedTesting::BlastTests -# TEST_SERIAL TRUE -# PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py -# TIMEOUT 500 -# RUNTIME_DEPENDENCIES -# Legacy::Editor -# Legacy::CryRenderNULL -# AZ::AssetProcessor -# AutomatedTesting.Assets -# ) -# endif() +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_pytest( + NAME AutomatedTesting::BlastTests + TEST_SERIAL TRUE + PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py + TIMEOUT 3600 + RUNTIME_DEPENDENCIES + Legacy::Editor + AZ::AssetProcessor + AutomatedTesting.Assets + ) +endif() ############# diff --git a/AutomatedTesting/default.blastconfiguration b/AutomatedTesting/default.blastconfiguration index 96a23ecbb8..6318a5002f 100644 --- a/AutomatedTesting/default.blastconfiguration +++ b/AutomatedTesting/default.blastconfiguration @@ -1,6 +1,6 @@ - + diff --git a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp index d2aa81900b..51789f68da 100644 --- a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp +++ b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp @@ -179,7 +179,7 @@ namespace Blast void EditorBlastMeshDataComponent::RegisterModel() { - if (m_meshFeatureProcessor && m_meshAssets[0].GetId().IsValid()) + if (m_meshFeatureProcessor && !m_meshAssets.empty() && m_meshAssets[0].GetId().IsValid()) { AZ::Render::MaterialAssignmentMap materials; AZ::Render::MaterialComponentRequestBus::EventResult( From 582b098ed227a26b2f9548fe1990f52b2cd01ef0 Mon Sep 17 00:00:00 2001 From: greerdv Date: Thu, 15 Apr 2021 17:06:56 +0100 Subject: [PATCH 24/74] removing unused local variable --- Gems/PhysX/Code/Source/BaseColliderComponent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/PhysX/Code/Source/BaseColliderComponent.cpp b/Gems/PhysX/Code/Source/BaseColliderComponent.cpp index c67cc105d8..c8581efcb7 100644 --- a/Gems/PhysX/Code/Source/BaseColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/BaseColliderComponent.cpp @@ -330,7 +330,6 @@ namespace PhysX } const bool hasNonUniformScale = (AZ::NonUniformScaleRequestBus::FindFirstHandler(GetEntityId()) != nullptr); - AZ::u8 subdivisionLevel = physicsAssetConfiguration.m_subdivisionLevel; Utils::GetShapesFromAsset(physicsAssetConfiguration, componentColliderConfiguration, hasNonUniformScale, physicsAssetConfiguration.m_subdivisionLevel, m_shapes); From 7ff0c5c33a8c0fefe23c5f4fcb8f08073580db0d Mon Sep 17 00:00:00 2001 From: hultonha Date: Thu, 15 Apr 2021 18:17:02 +0100 Subject: [PATCH 25/74] fix reserve call that should have been resize - add extra handling to output error --- .../Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp | 12 ++++++++++-- .../Code/Source/Asset/EditorWhiteBoxMeshAsset.h | 1 + .../Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp | 2 +- Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp | 5 +++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp b/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp index 69d7c03fce..cd308aef0f 100644 --- a/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.cpp @@ -86,7 +86,7 @@ namespace WhiteBox { success = assetHandler->SaveAssetData(meshAsset, &fileStream); AZ_Printf( - "EditorWhiteBoxComponent", "Save %s. Location: %s", success ? "succeeded" : "failed", + "EditorWhiteBoxMeshAsset", "Save %s. Location: %s", success ? "succeeded" : "failed", absoluteFilePath.c_str()); } } @@ -229,7 +229,15 @@ namespace WhiteBox { if (asset == m_meshAsset) { - AZ_Warning("EditorWhiteBoxComponent", false, "OnAssetError: %s", asset.GetHint().c_str()); + AZ_Warning("EditorWhiteBoxMeshAsset", false, "OnAssetError: %s", asset.GetHint().c_str()); + } + } + + void EditorWhiteBoxMeshAsset::OnAssetReloadError(AZ::Data::Asset asset) + { + if (asset == m_meshAsset) + { + AZ_Warning("EditorWhiteBoxMeshAsset", false, "OnAssetReloadError: %s", asset.GetHint().c_str()); } } diff --git a/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.h b/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.h index 2001808668..caa56dce1a 100644 --- a/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.h +++ b/Gems/WhiteBox/Code/Source/Asset/EditorWhiteBoxMeshAsset.h @@ -82,6 +82,7 @@ namespace WhiteBox void OnAssetReady(AZ::Data::Asset asset) override; void OnAssetReloaded(AZ::Data::Asset asset) override; void OnAssetError(AZ::Data::Asset asset) override; + void OnAssetReloadError(AZ::Data::Asset asset) override; // WhiteBoxMeshAssetNotificationBus ... void OnWhiteBoxMeshAssetModified(AZ::Data::Asset asset) override; diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp index 72a754f05f..7aa12777e0 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp @@ -113,7 +113,7 @@ namespace WhiteBox const auto size = stream->GetLength(); Api::WhiteBoxMeshStream whiteBoxData; - whiteBoxData.reserve(size); + whiteBoxData.resize(size); stream->Read(size, whiteBoxData.data()); diff --git a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp index fbab501e8f..03f2545ae1 100644 --- a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp +++ b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp @@ -3407,6 +3407,11 @@ namespace WhiteBox { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); + if (input.empty()) + { + return false; + } + std::string inputStr; inputStr.reserve(input.size()); AZStd::copy(input.cbegin(), input.cend(), AZStd::back_inserter(inputStr)); From 2baa0db2de534ec97e20cda27b27cb046ea5ff04 Mon Sep 17 00:00:00 2001 From: guthadam Date: Thu, 15 Apr 2021 12:38:07 -0500 Subject: [PATCH 26/74] Standardizing dialog button boxes across material editor and component Making dialogs modal https://jira.agscollab.com/browse/ATOM-15173 https://jira.agscollab.com/browse/ATOM-15174 --- .../CreateMaterialDialog.cpp | 2 + .../PresetBrowserDialog.cpp | 1 + .../EditorMaterialComponentExporter.cpp | 21 +++---- .../EditorMaterialComponentInspector.cpp | 14 +++-- .../EditorMaterialModelUvNameMapInspector.cpp | 58 ++++++++----------- 5 files changed, 44 insertions(+), 52 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp index d3b5432624..20d1b587b5 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp @@ -37,6 +37,8 @@ namespace MaterialEditor //Connect ok and cancel buttons QObject::connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); QObject::connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + setModal(true); } void CreateMaterialDialog::InitMaterialTypeSelection() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.cpp index a00490c0b9..f37a047126 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/PresetBrowserDialogs/PresetBrowserDialog.cpp @@ -35,6 +35,7 @@ namespace MaterialEditor SetupPresetList(); SetupSearchWidget(); SetupDialogButtons(); + setModal(true); } void PresetBrowserDialog::SetupPresetList() diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp index b8d1b1df28..34cc53a326 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp @@ -25,6 +25,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin #include #include #include +#include #include #include #include @@ -215,19 +216,10 @@ namespace AZ tableWidget->sortItems(MaterialSlotColumn); // Create the bottom row of the dialog with action buttons for exporting or canceling the operation - QWidget* buttonRow = new QWidget(&dialog); - buttonRow->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - - QPushButton* confirmButton = new QPushButton("Confirm", buttonRow); - QObject::connect(confirmButton, &QPushButton::clicked, confirmButton, [&dialog] { dialog.accept(); }); - - QPushButton* cancelButton = new QPushButton("Cancel", buttonRow); - QObject::connect(cancelButton, &QPushButton::clicked, cancelButton, [&dialog] { dialog.reject(); }); - - QHBoxLayout* buttonLayout = new QHBoxLayout(buttonRow); - buttonLayout->addStretch(); - buttonLayout->addWidget(confirmButton); - buttonLayout->addWidget(cancelButton); + QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); // Create a heading label for the top of the dialog QLabel* labelWidget = new QLabel("\nSelect the material slots that you want to generate new source materials for. Edit the material file name and location using the file picker.\n", &dialog); @@ -236,8 +228,9 @@ namespace AZ QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog); dialogLayout->addWidget(labelWidget); dialogLayout->addWidget(tableWidget); - dialogLayout->addWidget(buttonRow); + dialogLayout->addWidget(buttonBox); dialog.setLayout(dialogLayout); + dialog.setModal(true); // Forcing the initial dialog size to accomodate typical content. // Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent. diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index d2400f52a3..cbc3222694 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -37,6 +37,7 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include +#include #include #include #include @@ -534,7 +535,7 @@ namespace AZ inspector->Populate(); inspector->SetOverrides(propertyOverrideMap); - // Create the menu bottom row with actions for exporting or canceling the operation + // Create the menu botton QToolButton* menuButton = new QToolButton(&dialog); menuButton->setAutoRaise(true); menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); @@ -546,10 +547,6 @@ namespace AZ action = menu.addAction("Clear Overrides", [&] { inspector->SetOverrides(MaterialPropertyOverrideMap()); }); action = menu.addAction("Revert Changes", [&] { inspector->SetOverrides(propertyOverrideMap); }); - menu.addSeparator(); - action = menu.addAction("Confirm Changes", [&] { dialog.accept(); }); - action = menu.addAction("Cancel Changes", [&] { dialog.reject(); }); - menu.addSeparator(); action = menu.addAction("Save Material", [&] { inspector->SaveMaterial(); }); action = menu.addAction("Save Material To Source", [&] { inspector->SaveMaterialToSource(); }); @@ -563,12 +560,19 @@ namespace AZ menu.exec(QCursor::pos()); }); + QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + QObject::connect(&dialog, &QDialog::rejected, &dialog, [&] { inspector->SetOverrides(propertyOverrideMap); }); QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog); dialogLayout->addWidget(menuButton); dialogLayout->addWidget(inspector); + dialogLayout->addWidget(buttonBox); dialog.setLayout(dialogLayout); + dialog.setModal(true); // Forcing the initial dialog size to accomodate typical content. // Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent. diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp index f562f555f0..d05b618f53 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp @@ -32,8 +32,11 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include -#include +#include #include +#include +#include +#include #include AZ_POP_DISABLE_WARNING @@ -286,42 +289,31 @@ namespace AZ MaterialModelUvNameMapInspector* inspector = new MaterialModelUvNameMapInspector(assetId, matModUvOverrides, modelUvNames, matModUvOverrideMapChangedCallBack, &dialog); inspector->Populate(); - // Create the bottom row of the dialog with action buttons for exporting or canceling the operation - QWidget* buttonRow = new QWidget(&dialog); - buttonRow->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - - QPushButton* revertButton = new QPushButton("Revert", buttonRow); - QObject::connect(revertButton, &QPushButton::clicked, revertButton, [inspector, matModUvOverrides] { - inspector->SetUvNameMap(matModUvOverrides); - }); - - QPushButton* clearButton = new QPushButton("Clear", buttonRow); - QObject::connect(clearButton, &QPushButton::clicked, clearButton, [inspector] { - inspector->SetUvNameMap(RPI::MaterialModelUvOverrideMap()); - }); - - QPushButton* confirmButton = new QPushButton("Confirm", buttonRow); - QObject::connect(confirmButton, &QPushButton::clicked, confirmButton, [&dialog] { - dialog.accept(); - }); - - QPushButton* cancelButton = new QPushButton("Cancel", buttonRow); - QObject::connect(cancelButton, &QPushButton::clicked, cancelButton, [inspector, matModUvOverrides, &dialog] { - inspector->SetUvNameMap(matModUvOverrides); - dialog.reject(); - }); - - QHBoxLayout* buttonLayout = new QHBoxLayout(buttonRow); - buttonLayout->addStretch(); - buttonLayout->addWidget(revertButton); - buttonLayout->addWidget(clearButton); - buttonLayout->addWidget(confirmButton); - buttonLayout->addWidget(cancelButton); + // Create the menu botton + QToolButton* menuButton = new QToolButton(&dialog); + menuButton->setAutoRaise(true); + menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); + menuButton->setVisible(true); + QObject::connect(menuButton, &QToolButton::clicked, &dialog, [&]() { + QAction* action = nullptr; + + QMenu menu(&dialog); + action = menu.addAction("Clear", [&] { inspector->SetUvNameMap(RPI::MaterialModelUvOverrideMap()); }); + action = menu.addAction("Revert", [&] { inspector->SetUvNameMap(matModUvOverrides);; }); + menu.exec(QCursor::pos()); + }); + + QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog); + dialogLayout->addWidget(menuButton); dialogLayout->addWidget(inspector); - dialogLayout->addWidget(buttonRow); + dialogLayout->addWidget(buttonBox); dialog.setLayout(dialogLayout); + dialog.setModal(true); // Forcing the initial dialog size to accomodate typical content. // Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent. From a81ca4490fef9f5120fb16b86d8d5b1ca9287ff2 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 15 Apr 2021 10:42:34 -0700 Subject: [PATCH 27/74] Move EMotionFX's OpenGL dependency to 3rd Party and make sure Mac builds successfully --- Gems/EMotionFX/Code/CMakeLists.txt | 6 ------ .../Editor/Platform/Mac/platform_mac.cmake | 8 +------ cmake/3rdParty/FindOpenGLInterface.cmake | 21 +++++++++++++++++++ .../Platform/Mac/OpenGLInterface_mac.cmake | 16 ++++++++++++++ .../Platform/Mac/cmake_mac_files.cmake | 1 + cmake/3rdParty/cmake_files.cmake | 1 + 6 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 cmake/3rdParty/FindOpenGLInterface.cmake create mode 100644 cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake diff --git a/Gems/EMotionFX/Code/CMakeLists.txt b/Gems/EMotionFX/Code/CMakeLists.txt index d46c67fafb..b90902a948 100644 --- a/Gems/EMotionFX/Code/CMakeLists.txt +++ b/Gems/EMotionFX/Code/CMakeLists.txt @@ -68,12 +68,6 @@ ly_add_target( ) if (PAL_TRAIT_BUILD_HOST_TOOLS) - - find_package(OpenGL QUIET REQUIRED) - # Imported targets (like OpenGL::GL) are scoped to a directory. Add a - # a global scope - add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL) - target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL) ly_add_target( NAME EMotionFX.Editor.Static STATIC diff --git a/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake b/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake index 821e7d1f25..95df062a93 100644 --- a/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake +++ b/Gems/EMotionFX/Code/Editor/Platform/Mac/platform_mac.cmake @@ -13,10 +13,4 @@ # based on the active platform # NOTE: functions in cmake are global, therefore adding functions to this file # is being avoided to prevent overriding functions declared in other targets platfrom -# specific cmake files - -target_compile_definitions(3rdParty::OpenGLInterface - INTERFACE - # MacOS 10.14 deprecates OpenGL. This silences the warnings for now. - GL_SILENCE_DEPRECATION -) \ No newline at end of file +# specific cmake files \ No newline at end of file diff --git a/cmake/3rdParty/FindOpenGLInterface.cmake b/cmake/3rdParty/FindOpenGLInterface.cmake new file mode 100644 index 0000000000..7b537d1378 --- /dev/null +++ b/cmake/3rdParty/FindOpenGLInterface.cmake @@ -0,0 +1,21 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +find_package(OpenGL QUIET REQUIRED) +# Imported targets (like OpenGL::GL) are scoped to a directory. Add a +# a global scope +add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL) +target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL) + +set(pal_file ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/OpenGLInterface_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +if(EXISTS ${pal_file}) + include(${pal_file}) +endif() \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake b/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake new file mode 100644 index 0000000000..c9a52f4b1b --- /dev/null +++ b/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake @@ -0,0 +1,16 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +target_compile_definitions(3rdParty::OpenGLInterface + INTERFACE + # MacOS 10.14 deprecates OpenGL. This silences the warnings for now. + GL_SILENCE_DEPRECATION +) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake index f786f80cf7..0e3cc53262 100644 --- a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake +++ b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake @@ -15,6 +15,7 @@ set(FILES Clang_mac.cmake DirectXShaderCompiler_mac.cmake FbxSdk_mac.cmake + OpenGLInterface_mac.cmake OpenSSL_mac.cmake Wwise_mac.cmake ) diff --git a/cmake/3rdParty/cmake_files.cmake b/cmake/3rdParty/cmake_files.cmake index 3fe15bc0ce..46b612df42 100644 --- a/cmake/3rdParty/cmake_files.cmake +++ b/cmake/3rdParty/cmake_files.cmake @@ -18,6 +18,7 @@ set(FILES Finddyad.cmake FindFbxSdk.cmake Findlibav.cmake + FindOpenGLInterface.cmake FindOpenSSL.cmake FindRadTelemetry.cmake FindVkValidation.cmake From cc7b4fc251ac22e65d5bf86cf3e1c2804cf8f347 Mon Sep 17 00:00:00 2001 From: gallowj Date: Thu, 15 Apr 2021 13:06:27 -0500 Subject: [PATCH 28/74] Updated all materials, did some mesh cleaning adding source file as well. --- .../ArtSource/objects/sponza_cleanup.mb | 3 ++ .../Sponza/Assets/objects/sponza.fbx | 4 +- .../Assets/objects/sponza_mat_arch.material | 15 ++++++ .../objects/sponza_mat_background.material | 22 ++++++++- .../Assets/objects/sponza_mat_bricks.material | 27 +++++++++-- .../objects/sponza_mat_ceiling.material | 48 +++++++++++++++++-- .../Assets/objects/sponza_mat_chain.material | 13 ++++- .../objects/sponza_mat_columna.material | 22 ++++++++- .../objects/sponza_mat_columnb.material | 22 ++++++++- .../objects/sponza_mat_columnc.material | 22 ++++++++- .../objects/sponza_mat_curtainblue.material | 19 ++++++++ .../objects/sponza_mat_curtaingreen.material | 16 +++++++ .../objects/sponza_mat_curtainred.material | 21 ++++++++ .../objects/sponza_mat_details.material | 14 +++++- .../objects/sponza_mat_fabricblue.material | 16 +++++++ .../objects/sponza_mat_fabricgreen.material | 16 +++++++ .../objects/sponza_mat_fabricred.material | 16 +++++++ .../objects/sponza_mat_flagpole.material | 19 +++++++- .../Assets/objects/sponza_mat_floor.material | 22 ++++++++- .../Assets/objects/sponza_mat_leaf.material | 39 ++++++++++++++- .../Assets/objects/sponza_mat_lion.material | 23 ++++++++- .../Assets/objects/sponza_mat_roof.material | 17 +++++-- .../Assets/objects/sponza_mat_vase.material | 19 +++++++- .../objects/sponza_mat_vasehanging.material | 16 ++++++- .../objects/sponza_mat_vaseplant.material | 32 ++++++++++++- .../objects/sponza_mat_vaseround.material | 26 +++++++++- 26 files changed, 498 insertions(+), 31 deletions(-) create mode 100644 Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb diff --git a/Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb b/Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb new file mode 100644 index 0000000000..882496f2b0 --- /dev/null +++ b/Gems/AtomContent/Sponza/ArtSource/objects/sponza_cleanup.mb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d3c18d76f00688d15c54736ef3d8c953df08baf46a796fa71627de18bdb3c0f +size 22804332 diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx b/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx index 80cb76941e..9061666968 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza.fbx @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cbfc4d0a6722726070468da4368df7c76be67e8d067a7e3130fd29cdcdd5c6b -size 7613840 +oid sha256:35a880abc018520d4b30d21a64f7a14fca74d936593320d5afd03ddf25771bf3 +size 9176416 diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material index 8f5edb6968..da72f8a430 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/arch_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/arch_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.885053813457489, + 0.801281750202179, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/arch_1k_metallic.png" }, diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material index 5ba48a758e..5a195fd0b6 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/background_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/background_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/background_1k_normal.jpg", + "roughness": 0.4000000059604645 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.8911573886871338, + 0.7894102334976196, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/background_1k_metallic.png" }, @@ -24,7 +45,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.03099999949336052, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material index c32beebd5c..d2089b5537 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/bricks_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/bricks_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/bricks_1k_normal.jpg", + "roughness": 0.5 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.9703211784362793, + 0.9703211784362793, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/bricks_1k_metallic.png" }, @@ -23,11 +44,9 @@ "factor": 1.0 }, "parallax": { - "algorithm": "POM", - "enable": true, + "algorithm": "ContactRefinement", "factor": 0.03500000014901161, - "pdo": true, - "quality": "High", + "quality": "Medium", "textureMap": "Textures/bricks_1k_height.png" }, "roughness": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material index cbccd8ed88..40e476305d 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material @@ -4,17 +4,55 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/ceiling_1k_ao.png" + }, "baseColor": { + "textureBlendMode": "Lerp", + "textureMap": "Textures/ceiling_1k_basecolor.png" + }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "influenceMap": "Textures/ceiling_1k_ao.png", + "normalMap": "Textures/ceiling_1k_normal.png", + "roughness": 0.30000001192092898 + }, + "emissive": { "color": [ - 0.800000011920929, - 0.800000011920929, - 0.800000011920929, + 0.0, + 0.0, + 0.0, 1.0 - ], - "textureMap": "Textures/ceiling_1k_basecolor.png" + ] + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.7591058015823364, + 0.43776607513427737, + 1.0 + ] + }, + "normal": { + "textureMap": "Textures/ceiling_1k_normal.png" }, "opacity": { "factor": 1.0 + }, + "parallax": { + "algorithm": "ContactRefinement", + "factor": 0.019999999552965165, + "pdo": true, + "quality": "Medium", + "textureMap": "Textures/ceiling_1k_height.png" + }, + "roughness": { + "textureMap": "Textures/ceiling_1k_roughness.png" } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_chain.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_chain.material index cdb28a8a6f..4e39112383 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_chain.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_chain.material @@ -13,6 +13,17 @@ ], "textureMap": "Textures/chain_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.4891279339790344, + 0.7931944727897644, + 1.0, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/chain_alpha.png" }, @@ -21,7 +32,7 @@ }, "opacity": { "alphaSource": "Split", - "factor": 1.0, + "factor": 0.30000001192092898, "mode": "Cutout", "textureMap": "Textures/chain_alpha.png" }, diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material index 1889e33313..6c89c94021 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/columnA_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/columnA_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/columnA_1k_normal.jpg", + "roughness": 0.30000001192092898 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.8964369893074036, + 0.8264744281768799, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/columnA_1k_metallic.png" }, @@ -24,7 +45,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.017000000923871995, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material index 095afc0ab1..0be26ba553 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/columnB_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/columnB_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/columnB_1k_normal.jpg", + "roughness": 0.30000001192092898 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.9015335440635681, + 0.8348516225814819, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/columnB_1k_metallic.png" }, @@ -23,7 +44,6 @@ "factor": 1.0 }, "parallax": { - "enable": true, "factor": 0.020999999716877939, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material index e78cb485cc..2f1512fa4a 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/columnC_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/columnC_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/columnC_1k_normal.jpg", + "roughness": 0.30000001192092898 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.9050736427307129, + 0.9050736427307129, + 1.0, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/columnC_1k_metallic.png" }, @@ -24,7 +45,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.014000000432133675, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material index 62942faa87..e68bc7a41a 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/curtain_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/curtainBlue_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.06195162981748581, + 0.2056153267621994, + 1.0, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/curtain_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/curtain_normal.jpg" }, "opacity": { @@ -24,6 +40,9 @@ }, "roughness": { "textureMap": "Textures/curtain_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material index 3284cfa837..85a5ef9775 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/curtain_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/curtainGreen_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.0, + 1.0, + 0.029526207596063615, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/curtain_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/curtain_normal.jpg" }, "opacity": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material index d07cf6d172..086f34727c 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/curtain_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/curtainRed_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.023315785452723504, + 0.048538949340581897, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/curtain_metallic.png" }, @@ -24,6 +39,12 @@ }, "roughness": { "textureMap": "Textures/curtain_roughness.png" + }, + "uv": { + "center": [ + 16.0, + 0.0 + ] } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material index fc5f5761d8..18bd2a307b 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/details_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,15 @@ ], "textureMap": "Textures/details_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "normalMap": "Textures/details_1k_normal.png", + "roughness": 0.25 + }, + "general": { + "applySpecularAA": true + }, "metallic": { "textureMap": "Textures/details_1k_metallic.png" }, @@ -24,7 +37,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.02500000037252903, "pdo": true, "textureMap": "Textures/details_1k_height.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material index 3a555c0824..fb0490f9a9 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/fabric_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/fabricBlue_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.0, + 0.15049973130226136, + 1.0, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/fabric_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/fabric_normal.jpg" }, "opacity": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material index 6a95d0d275..c6074bf894 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/fabric_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/fabricGreen_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.0, + 1.0, + 0.15378041565418244, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/fabric_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/fabric_normal.jpg" }, "opacity": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material index 2558c86819..4215d8dde5 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/fabric_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,10 +17,22 @@ ], "textureMap": "Textures/fabricRed_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.08197146654129029, + 0.10267795622348786, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/fabric_metallic.png" }, "normal": { + "factor": 0.5, "textureMap": "Textures/fabric_normal.jpg" }, "opacity": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material index c13baae474..cbba302103 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/flagpole_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/flagpole_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.6520485281944275, + 0.7122911214828491, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/flagpole_1k_metallic.png" }, @@ -24,7 +39,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.014000000432133675, "pdo": true, "quality": "High", @@ -32,6 +46,9 @@ }, "roughness": { "textureMap": "Textures/flagpole_1k_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material index cb4affe1cf..2c2abe3931 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/floor_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,23 @@ ], "textureMap": "Textures/floor_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "influenceMap": "Textures/floor_1k_ao.png", + "normalMap": "Textures/floor_1k_normal.png", + "roughness": 0.25 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.9404135346412659, + 0.8688944578170776, + 1.0 + ] + }, "normal": { "textureMap": "Textures/floor_1k_normal.png" }, @@ -21,7 +42,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.012000000104308129, "pdo": true, "textureMap": "Textures/floor_1k_height.png" diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material index bb226d14cb..4508a68f3f 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_leaf.material @@ -13,6 +13,23 @@ ], "textureMap": "Textures/thorn_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.05000000074505806, + "normalMap": "Textures/thorn_normal.jpg", + "roughness": 0.10000000149011612 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.46506446599960329, + 1.0, + 0.3944609761238098, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/thorn_metallic.png" }, @@ -20,7 +37,8 @@ "textureMap": "Textures/thorn_normal.jpg" }, "opacity": { - "factor": 0.5699999928474426, + "doubleSided": true, + "factor": 0.20000000298023225, "mode": "Cutout" }, "parallax": { @@ -28,6 +46,25 @@ }, "roughness": { "textureMap": "Textures/thorn_roughness.png" + }, + "subsurfaceScattering": { + "enableSubsurfaceScattering": true, + "quality": 1.0, + "scatterColor": [ + 0.28143739700317385, + 1.0, + 0.13000686466693879, + 1.0 + ], + "scatterDistance": 1.0, + "thickness": 0.10000000149011612, + "transmissionMode": "ThinObject", + "transmissionTint": [ + 0.07225146889686585, + 0.16981765627861024, + 0.04444953054189682, + 1.0 + ] } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material index 4b47e1b7a1..55f44b2f63 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/lion_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/lion_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.7364919781684876, + 0.3672388792037964, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/lion_1k_metallic.png" }, @@ -23,14 +38,18 @@ "factor": 1.0 }, "parallax": { - "algorithm": "POM", + "algorithm": "ContactRefinement", "enable": true, - "factor": 0.023000000044703485, + "factor": 0.009999999776482582, "pdo": true, + "quality": "Ultra", "textureMap": "Textures/lion_1k_height.png" }, "roughness": { "textureMap": "Textures/lion_1k_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material index 3b245b251f..a64486309d 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/roof_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -11,24 +15,27 @@ 0.800000011920929, 1.0 ], + "textureBlendMode": "Lerp", "textureMap": "Textures/roof_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, "metallic": { - "factor": 0.009999999776482582, "useTexture": false }, "normal": { + "factor": 0.5, + "flipY": true, "textureMap": "Textures/roof_1k_normal.jpg" }, "opacity": { "factor": 1.0 }, "parallax": { - "algorithm": "POM", - "enable": true, + "algorithm": "ContactRefinement", "factor": 0.019999999552965165, - "pdo": true, - "quality": "High", + "quality": "Medium", "textureMap": "Textures/roof_1k_height.png" }, "roughness": { diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material index e471de4ab9..867943642e 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/vase_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/vase_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.8713664412498474, + 0.6021667718887329, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/vase_1k_metallic.png" }, @@ -24,7 +39,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.027000000700354577, "pdo": true, "quality": "High", @@ -32,6 +46,9 @@ }, "roughness": { "textureMap": "Textures/vase_1k_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material index 6bb8a205d1..9e96fb983d 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/vaseHanging_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,17 @@ ], "textureMap": "Textures/vaseHanging_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.765606164932251, + 1.0, + 0.7052567601203919, + 1.0 + ] + }, "metallic": { "textureMap": "Textures/vaseHanging_1k_metallic.png" }, @@ -24,7 +39,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.04600000008940697, "pdo": true, "quality": "High", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseplant.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseplant.material index 0fe458b4ac..c5bfe5c6b4 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseplant.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseplant.material @@ -13,9 +13,39 @@ ], "textureMap": "Textures/vasePlant_1k_basecolor.png" }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 0.6788738965988159, + 1.0, + 0.026138704270124437, + 1.0 + ] + }, "opacity": { - "factor": 0.8399999737739563, + "doubleSided": true, + "factor": 0.28999999165534975, "mode": "Cutout" + }, + "subsurfaceScattering": { + "enableSubsurfaceScattering": true, + "quality": 1.0, + "scatterColor": [ + 0.07421988248825073, + 0.10223544389009476, + 0.0, + 1.0 + ], + "subsurfaceScatterFactor": 0.0, + "transmissionMode": "ThinObject", + "transmissionTint": [ + 0.33716335892677309, + 0.4620737135410309, + 0.0, + 1.0 + ] } } } \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material index d2ef595c0d..ebb4e537f5 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material @@ -4,6 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { + "ambientOcclusion": { + "enable": true, + "textureMap": "Textures/vaseRound_1k_ao.png" + }, "baseColor": { "color": [ 0.800000011920929, @@ -13,6 +17,24 @@ ], "textureMap": "Textures/vaseRound_1k_basecolor.png" }, + "clearCoat": { + "enable": true, + "factor": 0.5, + "influenceMap": "Textures/vaseRound_1k_ao.png", + "normalMap": "Textures/vaseRound_1k_normal.jpg", + "roughness": 0.25 + }, + "general": { + "applySpecularAA": true + }, + "irradiance": { + "color": [ + 1.0, + 0.5939116477966309, + 0.29176774621009829, + 1.0 + ] + }, "normal": { "textureMap": "Textures/vaseRound_1k_normal.jpg" }, @@ -21,7 +43,6 @@ }, "parallax": { "algorithm": "POM", - "enable": true, "factor": 0.019999999552965165, "pdo": true, "quality": "High", @@ -29,6 +50,9 @@ }, "roughness": { "textureMap": "Textures/vaseRound_1k_roughness.png" + }, + "specularF0": { + "enableMultiScatterCompensation": true } } } \ No newline at end of file From a9345646f8bf188841551ce649f89f2b22cdfe78 Mon Sep 17 00:00:00 2001 From: gallowj Date: Thu, 15 Apr 2021 13:08:13 -0500 Subject: [PATCH 29/74] fixing a hardcoded path typo that someone submitted on accident. --- .../DccScriptingInterface/azpy/config_utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py index 483e14a8ec..0b75ea4330 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py @@ -158,10 +158,10 @@ def bootstrap_dccsi_py_libs(dccsi_dirpath=return_stub_dir()): """Builds and adds local site dir libs based on py version""" from azpy.constants import STR_DCCSI_PYTHON_LIB_PATH # a path string constructor - _DCCSI_PYTHON_LIB_PATH = "E:\\P4\\jromnoa_spectra_atom_2\\dev\\Tools\\Python\\3.7.5\\windows\\Lib\\site-packages" - # _DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath, - # sys.version_info[0], - # sys.version_info[1]) + #_DCCSI_PYTHON_LIB_PATH = "E:\\P4\\jromnoa_spectra_atom_2\\dev\\Tools\\Python\\3.7.5\\windows\\Lib\\site-packages" + _DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath, + sys.version_info[0], + sys.version_info[1]) if os.path.exists(_DCCSI_PYTHON_LIB_PATH): _LOGGER.debug('Performed site.addsitedir({})'.format(_DCCSI_PYTHON_LIB_PATH)) From 48e53ac66b55ea8089e57f72589b58d004cb8bf6 Mon Sep 17 00:00:00 2001 From: guthadam Date: Thu, 15 Apr 2021 13:50:29 -0500 Subject: [PATCH 30/74] Correctingtypo --- .../Code/Source/Material/EditorMaterialComponentInspector.cpp | 2 +- .../Source/Material/EditorMaterialModelUvNameMapInspector.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index cbc3222694..38e41a74b4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -535,7 +535,7 @@ namespace AZ inspector->Populate(); inspector->SetOverrides(propertyOverrideMap); - // Create the menu botton + // Create the menu button QToolButton* menuButton = new QToolButton(&dialog); menuButton->setAutoRaise(true); menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp index d05b618f53..1c6e338ee9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialModelUvNameMapInspector.cpp @@ -289,7 +289,7 @@ namespace AZ MaterialModelUvNameMapInspector* inspector = new MaterialModelUvNameMapInspector(assetId, matModUvOverrides, modelUvNames, matModUvOverrideMapChangedCallBack, &dialog); inspector->Populate(); - // Create the menu botton + // Create the menu button QToolButton* menuButton = new QToolButton(&dialog); menuButton->setAutoRaise(true); menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); From dbae71c5119705ced5b358b32ead5cb2b79d6b8c Mon Sep 17 00:00:00 2001 From: spham Date: Thu, 15 Apr 2021 11:57:23 -0700 Subject: [PATCH 31/74] Fixes for android nightly unit tests - Fix broken test launcher caused by change in unit test module registry format - Fix test runner script's ENGINE_ROOT (re-parenting) path caused by move of file to different folder - Adding step to always perform an android sdk update to latest creating and launching android virtual device (AVD) --- cmake/Tools/common.py | 9 ++++++--- .../Android/run_test_on_android_simulator.py | 13 ++++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/cmake/Tools/common.py b/cmake/Tools/common.py index 1f53c37c49..563408f942 100755 --- a/cmake/Tools/common.py +++ b/cmake/Tools/common.py @@ -628,8 +628,8 @@ def get_test_module_registry(build_dir_path): test_module_items = unit_test_json['Amazon'] for _, test_module_item in test_module_items.items(): - module_file = test_module_item['Modules'] - dep_modules.append(module_file) + module_files = test_module_item['Modules'] + dep_modules.extend(module_files) except FileNotFoundError: raise LmbrCmdError(f"Unit test registry not found ('{str(unit_test_module_path)}')") @@ -659,7 +659,10 @@ def get_validated_test_modules(test_modules, build_dir_path): for test_target_check in test_modules: if test_target_check not in all_test_modules: raise LmbrCmdError(f"Invalid test module {test_target_check}") - validated_test_modules.append(test_target_check) + if isinstance(test_target_check, list): + validated_test_modules.extend(test_target_check) + else: + validated_test_modules.append(test_target_check) else: validated_test_modules = all_test_modules diff --git a/scripts/build/Platform/Android/run_test_on_android_simulator.py b/scripts/build/Platform/Android/run_test_on_android_simulator.py index e81db00537..bdbe1c6b44 100644 --- a/scripts/build/Platform/Android/run_test_on_android_simulator.py +++ b/scripts/build/Platform/Android/run_test_on_android_simulator.py @@ -20,7 +20,7 @@ import logging CURRENT_PATH = pathlib.Path(os.path.dirname(__file__)).absolute() -ENGINE_ROOT = CURRENT_PATH.parent.parent.parent.parent.parent.parent +ENGINE_ROOT = CURRENT_PATH.parent.parent.parent.parent class AndroidEmuError(Exception): @@ -194,6 +194,14 @@ class AndroidEmulatorManager(object): return installed_packages, available_packages, available_updates + def update_installed_sdks(self): + """ + Run an SDK Manager update to make sure the SDKs are all up-to-date + """ + logging.info(f"Updating android SDK...") + self.sdk_manager_cmd.run(['--update']) + + def install_system_package_if_necessary(self): """ Make sure that we have the correct system image installed, and install if not @@ -503,6 +511,9 @@ def process_unit_test_on_simulator(base_android_sdk_path, build_path, build_conf manager = AndroidEmulatorManager(base_android_sdk_path=base_android_sdk_path, force_avd_creation=True) + # Make sure that the android SDK is up to date + manager.update_installed_sdks() + # First Install or overwrite the unit test emulator manager.install_unit_test_avd() From 020d7801bb625b8b7211dfb62bc45129b7cf7533 Mon Sep 17 00:00:00 2001 From: Terry Michaels <81711813+tjmichaels@users.noreply.github.com> Date: Thu, 15 Apr 2021 14:28:57 -0500 Subject: [PATCH 32/74] Make sure Recent Files list is correctly enabled/disabled when the list changes (#73) Make sure Recent Files list is correctly enabled/disabled when the recent files list changes --- .../AssetEditor/AssetEditorWidget.cpp | 20 ++++++++++++++++++- .../AssetEditor/AssetEditorWidget.h | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp index 603c7a8023..706d8243e2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp @@ -256,6 +256,8 @@ namespace AzToolsFramework m_userSettings = AZ::UserSettings::CreateFind(k_assetEditorWidgetSettings, AZ::UserSettings::CT_LOCAL); + UpdateRecentFileListState(); + QObject::connect(m_recentFileMenu, &QMenu::aboutToShow, this, &AssetEditorWidget::PopulateRecentMenu); } @@ -952,7 +954,8 @@ namespace AzToolsFramework void AssetEditorWidget::AddRecentPath(const AZStd::string& recentPath) { - m_userSettings->AddRecentPath(recentPath); + m_userSettings->AddRecentPath(recentPath); + UpdateRecentFileListState(); } void AssetEditorWidget::PopulateRecentMenu() @@ -989,6 +992,21 @@ namespace AzToolsFramework m_saveAsAssetAction->setEnabled(true); } + void AssetEditorWidget::UpdateRecentFileListState() + { + if (m_recentFileMenu) + { + if (!m_userSettings || m_userSettings->m_recentPaths.empty()) + { + m_recentFileMenu->setEnabled(false); + } + else + { + m_recentFileMenu->setEnabled(true); + } + } + } + } // namespace AssetEditor } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.h index b27d69dba5..4379fc27ed 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.h @@ -122,6 +122,8 @@ namespace AzToolsFramework void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override; void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override; + void UpdateRecentFileListState(); + private: void DirtyAsset(); From a9516c6498b6b92e8e18b02b638e6d98154806d4 Mon Sep 17 00:00:00 2001 From: gallowj Date: Thu, 15 Apr 2021 15:04:36 -0500 Subject: [PATCH 33/74] updated the ref to dccsi env that changed --- Gems/AtomContent/Sponza/Project_Env.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomContent/Sponza/Project_Env.bat b/Gems/AtomContent/Sponza/Project_Env.bat index ae21e6ebc4..46d4663c34 100644 --- a/Gems/AtomContent/Sponza/Project_Env.bat +++ b/Gems/AtomContent/Sponza/Project_Env.bat @@ -44,7 +44,7 @@ CD /d %LY_PROJECT_PATH%\%DEV_REL_PATH% set LY_DEV=%CD% echo LY_DEV = %LY_DEV% -CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env.bat +CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env_Maya.bat rem :: Constant Vars (Global) rem SET LYPY_GDEBUG=0 From 66517b22e04d250a1e0e6a287800e686d4431e54 Mon Sep 17 00:00:00 2001 From: spham Date: Thu, 15 Apr 2021 13:06:27 -0700 Subject: [PATCH 34/74] Updating how to calculate the ENGINE_ROOT path based on the CURRENT_PATH value --- .../build/Platform/Android/run_test_on_android_simulator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/build/Platform/Android/run_test_on_android_simulator.py b/scripts/build/Platform/Android/run_test_on_android_simulator.py index bdbe1c6b44..1fc2e19636 100644 --- a/scripts/build/Platform/Android/run_test_on_android_simulator.py +++ b/scripts/build/Platform/Android/run_test_on_android_simulator.py @@ -20,7 +20,8 @@ import logging CURRENT_PATH = pathlib.Path(os.path.dirname(__file__)).absolute() -ENGINE_ROOT = CURRENT_PATH.parent.parent.parent.parent +# The engine root is based on the location of this file (/scripts/build/Platform/Android). Walk up to calculate the engine root +ENGINE_ROOT = CURRENT_PATH.parents[3] class AndroidEmuError(Exception): From ef30f49bf9cc6152dc6a2afc82c4625fff3627fd Mon Sep 17 00:00:00 2001 From: qingtao Date: Thu, 15 Apr 2021 13:29:29 -0700 Subject: [PATCH 35/74] Fixed a linux compile issue. --- Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl index c00533f740..eb0e295129 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl @@ -725,7 +725,7 @@ namespace AZ ImGui::BeginTooltip(); ImGui::Text("Name: %s", passEntry->m_name.GetCStr()); ImGui::Text("Path: %s", passEntry->m_path.GetCStr()); - ImGui::Text("Duration in ticks: %u", passEntry->m_timestampResult.GetDurationInTicks()); + ImGui::Text("Duration in ticks: %lu", passEntry->m_timestampResult.GetDurationInTicks()); ImGui::Text("Duration in microsecond: %.3f us", passEntry->m_timestampResult.GetDurationInNanoseconds()/1000.f); ImGui::EndTooltip(); } From abf26eede19f53876e7aa8d511a147cc1c3ac7eb Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 14:00:40 -0700 Subject: [PATCH 36/74] Bump REsourcePoolBuilder as the bufferBindFlags were updated --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 7f617f4c6c..812198668d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 1; + builderDescriptor.m_version = 2; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From 7902eafd7d0c34b618cd1aa83b06aa7c87a49409 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 15 Apr 2021 15:20:55 -0700 Subject: [PATCH 37/74] Add empty pal files for platforms other than Mac --- cmake/3rdParty/FindOpenGLInterface.cmake | 4 +--- .../Platform/Android/OpenGLInterface_android.cmake | 10 ++++++++++ .../Platform/Android/cmake_android_files.cmake | 1 + .../Platform/Linux/OpenGLInterface_linux.cmake | 10 ++++++++++ cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake | 1 + .../Platform/Windows/OpenGLInterface_windows.cmake | 10 ++++++++++ .../Platform/Windows/cmake_windows_files.cmake | 1 + cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake | 10 ++++++++++ cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake | 1 + 9 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake create mode 100644 cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake create mode 100644 cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake create mode 100644 cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake diff --git a/cmake/3rdParty/FindOpenGLInterface.cmake b/cmake/3rdParty/FindOpenGLInterface.cmake index 7b537d1378..99bf19c4d7 100644 --- a/cmake/3rdParty/FindOpenGLInterface.cmake +++ b/cmake/3rdParty/FindOpenGLInterface.cmake @@ -16,6 +16,4 @@ add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL) target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL) set(pal_file ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/OpenGLInterface_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) -if(EXISTS ${pal_file}) - include(${pal_file}) -endif() \ No newline at end of file +include(${pal_file}) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake b/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/cmake/3rdParty/Platform/Android/cmake_android_files.cmake b/cmake/3rdParty/Platform/Android/cmake_android_files.cmake index 07e453f862..93d1f3386b 100644 --- a/cmake/3rdParty/Platform/Android/cmake_android_files.cmake +++ b/cmake/3rdParty/Platform/Android/cmake_android_files.cmake @@ -12,6 +12,7 @@ set(FILES BuiltInPackages_android.cmake civetweb_android.cmake + OpenGLInterface_android.cmake VkValidation_android.cmake Wwise_android.cmake ) diff --git a/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake b/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake index 2b1ba4d0e5..cce929b909 100644 --- a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake +++ b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake @@ -16,6 +16,7 @@ set(FILES Clang_linux.cmake dyad_linux.cmake FbxSdk_linux.cmake + OpenGLInterface_linux.cmake OpenSSL_linux.cmake Wwise_linux.cmake ) diff --git a/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake b/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index 2c7890fcc4..675ae7f695 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -18,6 +18,7 @@ set(FILES dyad_windows.cmake FbxSdk_windows.cmake libav_windows.cmake + OpenGLInterface_windows.cmake OpenSSL_windows.cmake Wwise_windows.cmake ) diff --git a/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake b/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake b/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake index e32a9f75bb..242e1e91b0 100644 --- a/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake +++ b/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake @@ -11,6 +11,7 @@ set(FILES BuiltInPackages_ios.cmake + OpenGLInterface_ios.cmake OpenSSL_ios.cmake RadTelemetry_ios.cmake Wwise_ios.cmake From f76322d13d5916d7e38079050f234faa29036f2e Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 15 Apr 2021 15:59:30 -0700 Subject: [PATCH 38/74] Remove Android/iOS pal files since OpenGL is only needed by host tools. --- .../Platform/Android/OpenGLInterface_android.cmake | 10 ---------- .../Platform/Android/cmake_android_files.cmake | 1 - cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake | 10 ---------- cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake | 1 - 4 files changed, 22 deletions(-) delete mode 100644 cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake delete mode 100644 cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake diff --git a/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake b/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/cmake/3rdParty/Platform/Android/OpenGLInterface_android.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# diff --git a/cmake/3rdParty/Platform/Android/cmake_android_files.cmake b/cmake/3rdParty/Platform/Android/cmake_android_files.cmake index 93d1f3386b..07e453f862 100644 --- a/cmake/3rdParty/Platform/Android/cmake_android_files.cmake +++ b/cmake/3rdParty/Platform/Android/cmake_android_files.cmake @@ -12,7 +12,6 @@ set(FILES BuiltInPackages_android.cmake civetweb_android.cmake - OpenGLInterface_android.cmake VkValidation_android.cmake Wwise_android.cmake ) diff --git a/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake b/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/cmake/3rdParty/Platform/iOS/OpenGLInterface_ios.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# diff --git a/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake b/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake index 242e1e91b0..e32a9f75bb 100644 --- a/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake +++ b/cmake/3rdParty/Platform/iOS/cmake_ios_files.cmake @@ -11,7 +11,6 @@ set(FILES BuiltInPackages_ios.cmake - OpenGLInterface_ios.cmake OpenSSL_ios.cmake RadTelemetry_ios.cmake Wwise_ios.cmake From 61c24084e883a43d1a6f583899d22b5d680c550e Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 16:13:22 -0700 Subject: [PATCH 39/74] Enable Null RHI for AutomatedTesting --- .../Gem/Code/Platform/Windows/runtime_dependencies.cmake | 1 + .../Gem/Code/Platform/Windows/tool_dependencies.cmake | 2 ++ .../Template/Code/Platform/Mac/mac_runtime_dependencies.cmake | 1 + .../Template/Code/Platform/Mac/mac_tool_dependencies.cmake | 1 + .../Code/Platform/Windows/windows_runtime_dependencies.cmake | 1 + .../Code/Platform/Windows/windows_tool_dependencies.cmake | 2 ++ 6 files changed, 8 insertions(+) diff --git a/AutomatedTesting/Gem/Code/Platform/Windows/runtime_dependencies.cmake b/AutomatedTesting/Gem/Code/Platform/Windows/runtime_dependencies.cmake index 617816dcd0..0a1541bcfc 100644 --- a/AutomatedTesting/Gem/Code/Platform/Windows/runtime_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/Platform/Windows/runtime_dependencies.cmake @@ -12,4 +12,5 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Vulkan.Private Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Null.Private ) \ No newline at end of file diff --git a/AutomatedTesting/Gem/Code/Platform/Windows/tool_dependencies.cmake b/AutomatedTesting/Gem/Code/Platform/Windows/tool_dependencies.cmake index d13d0fb180..ddd3bfa6a7 100644 --- a/AutomatedTesting/Gem/Code/Platform/Windows/tool_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/Platform/Windows/tool_dependencies.cmake @@ -15,5 +15,7 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Vulkan.Builders Gem::Atom_RHI_DX12.Private Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Null.Private + Gem::Atom_RHI_Null.Builders Gem::Atom_RHI_Metal.Builders ) \ No newline at end of file diff --git a/Templates/DefaultProject/Template/Code/Platform/Mac/mac_runtime_dependencies.cmake b/Templates/DefaultProject/Template/Code/Platform/Mac/mac_runtime_dependencies.cmake index e49929c6e1..2821493346 100644 --- a/Templates/DefaultProject/Template/Code/Platform/Mac/mac_runtime_dependencies.cmake +++ b/Templates/DefaultProject/Template/Code/Platform/Mac/mac_runtime_dependencies.cmake @@ -11,4 +11,5 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Null.Private ) diff --git a/Templates/DefaultProject/Template/Code/Platform/Mac/mac_tool_dependencies.cmake b/Templates/DefaultProject/Template/Code/Platform/Mac/mac_tool_dependencies.cmake index eea4bb1dce..adf5485ed4 100644 --- a/Templates/DefaultProject/Template/Code/Platform/Mac/mac_tool_dependencies.cmake +++ b/Templates/DefaultProject/Template/Code/Platform/Mac/mac_tool_dependencies.cmake @@ -14,4 +14,5 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Metal.Builders Gem::Atom_RHI_Vulkan.Builders Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Null.Builders ) diff --git a/Templates/DefaultProject/Template/Code/Platform/Windows/windows_runtime_dependencies.cmake b/Templates/DefaultProject/Template/Code/Platform/Windows/windows_runtime_dependencies.cmake index c5e1b4bc2e..514a61aa57 100644 --- a/Templates/DefaultProject/Template/Code/Platform/Windows/windows_runtime_dependencies.cmake +++ b/Templates/DefaultProject/Template/Code/Platform/Windows/windows_runtime_dependencies.cmake @@ -12,4 +12,5 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Vulkan.Private Gem::Atom_RHI_DX12.Private + Gem::Atom_RHI_Null.Private ) diff --git a/Templates/DefaultProject/Template/Code/Platform/Windows/windows_tool_dependencies.cmake b/Templates/DefaultProject/Template/Code/Platform/Windows/windows_tool_dependencies.cmake index 304f97d590..b7f4b82126 100644 --- a/Templates/DefaultProject/Template/Code/Platform/Windows/windows_tool_dependencies.cmake +++ b/Templates/DefaultProject/Template/Code/Platform/Windows/windows_tool_dependencies.cmake @@ -14,4 +14,6 @@ set(GEM_DEPENDENCIES Gem::Atom_RHI_Vulkan.Builders Gem::Atom_RHI_DX12.Private Gem::Atom_RHI_DX12.Builders + Gem::Atom_RHI_Null.Private + Gem::Atom_RHI_Null.Builders ) From 8074e0fb186aea840feaa9ebed561c08eadb7ffe Mon Sep 17 00:00:00 2001 From: karlberg Date: Thu, 15 Apr 2021 17:56:08 -0700 Subject: [PATCH 40/74] Remove formal template parameter name to resolve shadowed variable warning on clang --- .../AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h index a91f42b3a0..3d064b5ecc 100644 --- a/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h +++ b/Code/Framework/AzNetworking/AzNetworking/DataStructures/FixedSizeBitset.h @@ -115,7 +115,7 @@ namespace AzNetworking ContainerType m_container; - template + template friend class FixedSizeVectorBitset; }; } From d3520ddcf13413cbedcbe25634ec03ae38cb997b Mon Sep 17 00:00:00 2001 From: mnaumov Date: Thu, 15 Apr 2021 17:59:09 -0700 Subject: [PATCH 41/74] Adding "copy name" and "copy path" to Material Editor --- .../Source/Window/MaterialBrowserInteractions.cpp | 15 +++++++++++++++ .../Source/Window/MaterialBrowserInteractions.h | 1 + 2 files changed, 16 insertions(+) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp index c4601baff2..b0412c001c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -61,6 +62,8 @@ namespace MaterialEditor m_caller = nullptr; }); + AddGenericContextMenuActions(caller, menu, entry); + if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) { const auto source = azalias_cast(entry); @@ -84,6 +87,18 @@ namespace MaterialEditor } } + void MaterialBrowserInteractions::AddGenericContextMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) + { + menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]() + { + QApplication::clipboard()->setText(entry->GetName().c_str()); + }); + menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]() + { + QApplication::clipboard()->setText(entry->GetFullPath().c_str()); + }); + } + void MaterialBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) { menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h index 07e2be2d59..2806cee6d4 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h @@ -44,6 +44,7 @@ namespace MaterialEditor //! AssetBrowserInteractionNotificationBus::Handler overrides... void AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector& entries) override; + void AddGenericContextMenuActions(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry); void AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry); void AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry); void AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry); From 4edbf7890bfc15890a9b5b6b0f5c205c09568df6 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 15 Apr 2021 19:01:15 -0700 Subject: [PATCH 42/74] Bringing fix that has not been migrated to github yet (fixes Windows release builds) --- AutomatedTesting/Gem/PythonTests/CMakeLists.txt | 1 + Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index ea9c365978..b7a5f85087 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -138,6 +138,7 @@ endif() if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_pytest( NAME AutomatedTesting::BlastTests + TEST_SUITE sandbox TEST_SERIAL TRUE PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py TIMEOUT 3600 diff --git a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h index 29b2bfc4b5..44fa5b09e1 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h +++ b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.h @@ -34,7 +34,6 @@ namespace AZ #if !defined(IMGUI_ENABLED) class DebugConsole {}; #else -#endif // defined(IMGUI_ENABLED) //////////////////////////////////////////////////////////////////////////////////////////////// //! A debug console used to enter debug console commands and display debug log messages. //! @@ -132,4 +131,5 @@ namespace AZ bool m_autoScroll = true; //!< Should we auto-scroll as new entries are added? bool m_forceScroll = false; //!< Do we need to force scroll after input entered? }; +#endif // defined(IMGUI_ENABLED) } // namespace AZ From bff55bd688024e9430e12dca0a6dd1f0250c1ed4 Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 15 Apr 2021 22:27:11 -0500 Subject: [PATCH 43/74] LYN-2726 Updated the Settings Registry Merge Utils logic to determine the project root and engine root to fix issues with running the Editor or AssetProcessor from within the project folder overriding the project_path with the engine root bootstrap.cfg project_path entry The order in which the project path is overridden as follows 1. The /bootstrap.cfg is first merged into the Settings Registry. Any '/Amazon/AzCore/Bootstrap/project_path' would be used if the following steps don't override that key. 2. Followed by general *.setreg/*.setregpatch files being merged into the Settings Registry which can override the '/Amazon/AzCore/Bootstrap/project_path' key 3. Next a project.json file searched upwards from the current executable directory to determine the project path 4. Finally if a command line parameter that overrides the project path is supplied it is used instead --- .../AzCore/Component/ComponentApplication.cpp | 27 +++- .../Settings/SettingsRegistryMergeUtils.cpp | 115 ++++++++++------ .../Settings/SettingsRegistryMergeUtils.h | 17 +++ .../ProjectManager/ProjectManager.cpp | 6 + .../API/ToolsApplicationAPI.h | 10 -- .../Application/ToolsApplication.cpp | 126 ------------------ .../Application/ToolsApplication.h | 6 - .../UI/PropertyEditor/PropertyAssetCtrl.cpp | 6 +- .../Editor/AssetEditor/AssetEditorWindow.cpp | 9 +- Code/Sandbox/Editor/PythonEditorFuncs.cpp | 7 +- Code/Sandbox/Editor/ToolBox.cpp | 7 +- 11 files changed, 134 insertions(+), 202 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index b8d3e12712..de97842cee 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -178,14 +178,16 @@ namespace AZ //! on an update to '/Amazon/AzCore/Bootstrap/project_path' key. struct UpdateProjectSettingsEventHandler { - UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry) + UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry, AZ::CommandLine& commandLine) : m_registry{ registry } + , m_commandLine{ commandLine } { } void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type) { using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; + // #1 Update the project settings when the project path is set const auto projectPathKey = FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path"; AZ::IO::FixedMaxPath newProjectPath; if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectPathKey, path) @@ -194,6 +196,7 @@ namespace AZ UpdateProjectSettingsFromProjectPath(AZ::IO::PathView(newProjectPath)); } + // #2 Update the project specialization when the project name is set const auto projectNameKey = FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) + "/project_name"; FixedValueString newProjectName; if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectNameKey, path) @@ -201,6 +204,12 @@ namespace AZ { UpdateProjectSpecializationFromProjectName(newProjectName); } + + // #3 Update the ComponentApplication CommandLine instance when the command line settings are merged into the Settings Registry + if (path == AZ::SettingsRegistryMergeUtils::CommandLineValueChangedKey) + { + UpdateCommandLine(); + } } //! Add the project name as a specialization underneath the /Amazon/AzCore/Settings/Specializations path @@ -233,10 +242,16 @@ namespace AZ AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry); } + void UpdateCommandLine() + { + AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(m_registry, m_commandLine); + } + private: AZ::IO::FixedMaxPath m_oldProjectPath; AZ::SettingsRegistryInterface::FixedValueString m_oldProjectName; AZ::SettingsRegistryInterface& m_registry; + AZ::CommandLine& m_commandLine; }; void ComponentApplication::Descriptor::AllocatorRemapping::Reflect(ReflectContext* context, ComponentApplication* app) @@ -415,6 +430,12 @@ namespace AZ // Add the Command Line arguments into the SettingsRegistry SettingsRegistryMergeUtils::StoreCommandLineToRegistry(*m_settingsRegistry, m_commandLine); + // Add a notifier to update the project_settings when + // 1. The 'project_path' key changes + // 2. The project specialization when the 'project-name' key changes + // 3. The ComponentApplication command line when the command line is stored to the registry + m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry, m_commandLine }); + // Merge Command Line arguments constexpr bool executeRegDumpCommands = false; SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands); @@ -429,10 +450,6 @@ namespace AZ // for the application root. CalculateAppRoot(); - // Add a notifier to update the /Amazon/AzCore/Settings/Specializations - // when the 'project_path' property changes within the SettingsRegistry - m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry }); - // Merge the bootstrap.cfg file into the Settings Registry as soon as the OSAllocator has been created. SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry); SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(*m_settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {}); diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 392e95bf6e..f84ff354b2 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -132,23 +132,14 @@ namespace AZ::Internal AZ::IO::FixedMaxPath ScanUpRootLocator(AZStd::string_view rootFileToLocate) { - - AZStd::fixed_string executableDir; - if (AZ::Utils::GetExecutableDirectory(executableDir.data(), executableDir.capacity()) == Utils::ExecutablePathResult::Success) - { - // Update the size value of the executable directory fixed string to correctly be the length of the null-terminated string - // stored within it - executableDir.resize_no_construct(AZStd::char_traits::length(executableDir.data())); - } - - AZ::IO::FixedMaxPath engineRootCandidate{ executableDir }; + AZ::IO::FixedMaxPath rootCandidate{ AZ::Utils::GetExecutableDirectory() }; bool rootPathVisited = false; do { - if (AZ::IO::SystemFile::Exists((engineRootCandidate / rootFileToLocate).c_str())) + if (AZ::IO::SystemFile::Exists((rootCandidate / rootFileToLocate).c_str())) { - return engineRootCandidate; + return rootCandidate; } // Note for posix filesystems the parent directory of '/' is '/' and for windows @@ -156,38 +147,69 @@ namespace AZ::Internal // Validate that the parent directory isn't itself, that would imply // that it is the filesystem root path - AZ::IO::PathView parentPath = engineRootCandidate.ParentPath(); - rootPathVisited = (engineRootCandidate == parentPath); + AZ::IO::PathView parentPath = rootCandidate.ParentPath(); + rootPathVisited = (rootCandidate == parentPath); // Recurse upwards one directory - engineRootCandidate = AZStd::move(parentPath); + rootCandidate = AZStd::move(parentPath); } while (!rootPathVisited); return {}; } + void InjectSettingToCommandLineFront(AZ::SettingsRegistryInterface& settingsRegistry, + AZStd::string_view path, AZStd::string_view value) + { + AZ::CommandLine commandLine; + AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(settingsRegistry, commandLine); + AZ::CommandLine::ParamContainer paramContainer; + commandLine.Dump(paramContainer); + + auto projectPathOverride = AZStd::string::format(R"(--regset="%.*s=%.*s")", + aznumeric_cast(path.size()), path.data(), aznumeric_cast(value.size()), value.data()); + paramContainer.emplace(paramContainer.begin(), AZStd::move(projectPathOverride)); + commandLine.Parse(paramContainer); + AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine); + } } // namespace AZ::Internal namespace AZ::SettingsRegistryMergeUtils { + constexpr AZStd::string_view InternalScanUpEngineRootKey{ "/O3DE/Settings/Internal/engine_root_scan_up_path" }; + constexpr AZStd::string_view InternalScanUpProjectRootKey{ "/O3DE/Settings/Internal/project_root_scan_up_path" }; + AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry) { AZ::IO::FixedMaxPath engineRoot; - // This is the 'external' engine root key, as in passed from command-line or .setreg files. auto engineRootKey = SettingsRegistryInterface::FixedValueString::format("%s/engine_path", BootstrapSettingsRootKey); - if (settingsRegistry.Get(engineRoot.Native(), engineRootKey); !engineRoot.empty()) + + // Step 1 Run the scan upwards logic once to find the location of the engine.json if it exist + // Once this step is run the {InternalScanUpEngineRootKey} is set in the Settings Registry + // to have this scan logic only run once InternalScanUpEngineRootKey the supplied registry + if (settingsRegistry.GetType(InternalScanUpEngineRootKey) == SettingsRegistryInterface::Type::NoType) { - return engineRoot; + // We can scan up from exe directory to find engine.json, use that for engine root if it exists. + engineRoot = Internal::ScanUpRootLocator("engine.json"); + // Set the {InternalScanUpEngineRootKey} to make sure this code path isn't called again for this settings registry + settingsRegistry.Set(InternalScanUpEngineRootKey, engineRoot.Native()); + if (!engineRoot.empty()) + { + settingsRegistry.Set(engineRootKey, engineRoot.Native()); + // Inject the engine root into the front of the command line settings + Internal::InjectSettingToCommandLineFront(settingsRegistry, engineRootKey, engineRoot.Native()); + return engineRoot; + } } - // We can scan up from exe directory to find engine.json, use that for engine root if it exists. - if (engineRoot = Internal::ScanUpRootLocator("engine.json"); !engineRoot.empty()) + // Step 2 check if the engine_path key has been supplied + if (settingsRegistry.Get(engineRoot.Native(), engineRootKey); !engineRoot.empty()) { - settingsRegistry.Set(engineRootKey, engineRoot.c_str()); return engineRoot; } + // Step 3 locate the project root and attempt to find the engine root using the registered engine + // for the project in the project.json file AZ::IO::FixedMaxPath projectRoot = FindProjectRoot(settingsRegistry); if (projectRoot.empty()) { @@ -207,16 +229,30 @@ namespace AZ::SettingsRegistryMergeUtils AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry) { AZ::IO::FixedMaxPath projectRoot; - // This is the 'external' project root key, as in passed from command-line or .setreg files. - auto projectRootKey = SettingsRegistryInterface::FixedValueString::format("%s/project_path", BootstrapSettingsRootKey); - if (settingsRegistry.Get(projectRoot.Native(), projectRootKey)) + const auto projectRootKey = SettingsRegistryInterface::FixedValueString::format("%s/project_path", BootstrapSettingsRootKey); + + // Step 1 Run the scan upwards logic once to find the location of the project.json if it exist + // Once this step is run the {InternalScanUpProjectRootKey} is set in the Settings Registry + // to have this scan logic only run once for the supplied registry + // SettingsRegistryInterface::GetType is used to check if a key is set + if (settingsRegistry.GetType(InternalScanUpProjectRootKey) == SettingsRegistryInterface::Type::NoType) { - return projectRoot; + projectRoot = Internal::ScanUpRootLocator("project.json"); + // Set the {InternalScanUpProjectRootKey} to make sure this code path isn't called again for this settings registry + settingsRegistry.Set(InternalScanUpProjectRootKey, projectRoot.Native()); + if (!projectRoot.empty()) + { + settingsRegistry.Set(projectRootKey, projectRoot.c_str()); + // Inject the project root into the front of the command line settings + Internal::InjectSettingToCommandLineFront(settingsRegistry, projectRootKey, projectRoot.Native()); + return projectRoot; + } } - if (projectRoot = Internal::ScanUpRootLocator("project.json"); !projectRoot.empty()) + // Step 2 Check the project-path key + // This is the project path root key, as in passed from command-line or .setreg files. + if (settingsRegistry.Get(projectRoot.Native(), projectRootKey)) { - settingsRegistry.Set(projectRootKey, projectRoot.c_str()); return projectRoot; } @@ -463,18 +499,6 @@ namespace AZ::SettingsRegistryMergeUtils void MergeSettingsToRegistry_Bootstrap(SettingsRegistryInterface& registry) { ConfigParserSettings parserSettings; - parserSettings.m_commentPrefixFunc = [](AZStd::string_view line) -> AZStd::string_view - { - constexpr AZStd::string_view commentPrefixes[]{ "--", ";","#" }; - for (AZStd::string_view commentPrefix : commentPrefixes) - { - if (size_t commentOffset = line.find(commentPrefix); commentOffset != AZStd::string_view::npos) - { - return line.substr(0, commentOffset); - } - } - return line; - }; parserSettings.m_registryRootPointerPath = BootstrapSettingsRootKey; MergeSettingsToRegistry_ConfigFile(registry, "bootstrap.cfg", parserSettings); } @@ -807,6 +831,11 @@ namespace AZ::SettingsRegistryMergeUtils ++argumentIndex; commandLinePath.resize(commandLineRootSize); } + + // This key is used allow Notification Handlers to know when the command line has been updated within the + // registry. The value itself is meaningless. The JSON path of {CommandLineValueChangedKey} + // being passed to the Notification Event Handler indicates that the command line has be updated + registry.Set(CommandLineValueChangedKey, true); } bool GetCommandLineFromRegistry(SettingsRegistryInterface& registry, AZ::CommandLine& commandLine) @@ -823,10 +852,16 @@ namespace AZ::SettingsRegistryMergeUtils } else if (valueName == "Value" && !value.empty()) { - m_arguments.push_back(value); + // Make sure value types are in quotes in case they start with a command option prefix + m_arguments.push_back(QuoteArgument(value)); } } + AZStd::string QuoteArgument(AZStd::string_view arg) + { + return !arg.empty() ? AZStd::string::format(R"("%.*s")", aznumeric_cast(arg.size()), arg.data()) : AZStd::string{ arg }; + } + // The first parameter is skipped by the ComamndLine::Parse function so initialize // the container with one empty element AZ::CommandLine::ParamContainer m_arguments{ 1 }; diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h index dad6c36d0f..10b3c2f18b 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h @@ -57,6 +57,9 @@ namespace AZ::SettingsRegistryMergeUtils //! Root key for where command line are stored at within the settings registry inline static constexpr char CommandLineRootKey[] = "/Amazon/AzCore/Runtime/CommandLine"; + //! Key set to trigger a notification that the CommandLine has been stored within the settings registry + //! The value of the key has no meaning. Notification Handlers only need to check if the key was supplied + inline static constexpr char CommandLineValueChangedKey[] = "/Amazon/AzCore/Runtime/CommandLineChanged"; //! Root key where raw project settings (project.json) file is merged to settings registry inline static constexpr char ProjectSettingsRootKey[] = "/Amazon/Project/Settings"; @@ -74,6 +77,20 @@ namespace AZ::SettingsRegistryMergeUtils //! If it's still not found, attempt to find the project (by similar means) then reconcile the //! engine root by inspecting project.json and the engine manifest file. AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry); + + //! The algorithm that is used to find the project root is as follows + //! 1. The first time this function is it performs a upward scan for a project.json file from + //! the executable directory and if found stores that path to an internal key. + //! In the same step it injects the path into the front of list of command line parameters + //! using the --regset="{BootstrapSettingsRootKey}/project_path=" value + //! 2. Next the "{BootstrapSettingsRootKey}/project_path" is checked to see if it has a project path set + //! + //! The order in which the project path settings are overridden proceeds in the following order + //! 1. project_path set in the /bootstrap.cfg file + //! 2. project_path set in a *.setreg/*.setregpatch file + //! 3. project_path found by scanning upwards from the executable directory to the project.json path + //! 4. project_path set on the Command line via either --regset="{BootstrapSettingsRootKey}/project_path=" + //! or --project_path= AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry); //! Query the specializations that will be used when loading the Settings Registry. diff --git a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp index 5acf4e75d1..7e968ffcd8 100644 --- a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp @@ -42,8 +42,14 @@ namespace AzFramework::ProjectManager AZ::CommandLine commandLine; commandLine.Parse(argc, argv); AZ::SettingsRegistryImpl settingsRegistry; + // Store the Command line to the Setting Registry + + AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(settingsRegistry); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {}); + // Retrieve Command Line from Settings Registry, it may have been updated by the call to FindEngineRoot() + // in MergeSettingstoRegistry_ConfigFile + AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(settingsRegistry, commandLine); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(settingsRegistry, commandLine, false); engineRootPath = AZ::SettingsRegistryMergeUtils::FindEngineRoot(settingsRegistry); projectRootPath = AZ::SettingsRegistryMergeUtils::FindProjectRoot(settingsRegistry); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index 0c631cf09e..f12ab71936 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -578,16 +578,6 @@ namespace AzToolsFramework */ virtual bool IsEditorInIsolationMode() = 0; - /*! - * Get the engine root path that the current tool is running under. - */ - virtual const char* GetEngineRootPath() const = 0; - - /** - * Get the version of the engine the current tools application is running under - */ - virtual const char* GetEngineVersion() const = 0; - /** * Creates and adds a new entity to the tools application from components which match at least one of the requiredTags * The tag matching occurs on AZ::Edit::SystemComponentTags attribute from the reflected class data in the serialization context diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 352048f5f0..22c1390828 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -224,112 +224,6 @@ namespace AzToolsFramework } // Internal -#define AZ_MAX_ENGINE_VERSION_LEN 64 - // Private Implementation class to manage the engine root and version - // Note: We are not using any AzCore classes because the ToolsApplication - // initialization happens early on, before the Allocators get instantiated, - // so we are using Qt privately instead - class ToolsApplication::EngineConfigImpl - { - private: - friend class ToolsApplication; - - typedef QMap EngineJsonMap; - - EngineConfigImpl(const char* logWindow, const char* fileName) - : m_logWindow(logWindow) - , m_fileName(fileName) - { - m_engineRoot[0] = '\0'; - m_engineVersion[0] = '\0'; - } - - char m_engineRoot[AZ_MAX_PATH_LEN]; - char m_engineVersion[AZ_MAX_ENGINE_VERSION_LEN]; - EngineJsonMap m_engineConfigMap; - const char* m_logWindow; - const char* m_fileName; - - - // Read an engine configuration into a map of key/value pairs - bool ReadEngineConfigIntoMap(QString engineJsonPath, EngineJsonMap& engineJsonMap) - { - QFile engineJsonFile(engineJsonPath); - if (!engineJsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) - { - AZ_Warning(m_logWindow, false, "Unable to open file '%s' in the current root directory", engineJsonPath.toUtf8().data()); - return false; - } - - QByteArray engineJsonData = engineJsonFile.readAll(); - engineJsonFile.close(); - QJsonDocument engineJsonDoc(QJsonDocument::fromJson(engineJsonData)); - if (engineJsonDoc.isNull()) - { - AZ_Warning(m_logWindow, false, "Unable to read file '%s' in the current root directory", engineJsonPath.toUtf8().data()); - return false; - } - - QJsonObject engineJsonRoot = engineJsonDoc.object(); - for (const QString& configKey : engineJsonRoot.keys()) - { - QJsonValue configValue = engineJsonRoot[configKey]; - if (configValue.isString() || configValue.isDouble()) - { - // Only map strings and numbers, ignore every other type - engineJsonMap[configKey] = configValue.toString(); - } - else - { - AZ_Warning(m_logWindow, false, "Ignoring key '%s' from '%s', unsupported type.", configKey.toUtf8().data(), engineJsonPath.toUtf8().data()); - } - } - return true; - } - - // Initialize the engine config object based on the current - bool Initialize(const char* currentEngineRoot) - { - // Start with the app root as the engine root (legacy), but check to see if the engine root - // is external to the app root - azstrncpy(m_engineRoot, AZ_ARRAY_SIZE(m_engineRoot), currentEngineRoot, strlen(currentEngineRoot) + 1); - - // From the appRoot, check and see if we can read any external engine reference in engine.json - QString engineJsonFileName = QString(m_fileName); - QString engineJsonFilePath = QDir(currentEngineRoot).absoluteFilePath(engineJsonFileName); - - // From the appRoot, check and see if we can read any external engine reference in engine.json - if (!QFile::exists(engineJsonFilePath)) - { - AZ_Warning(m_logWindow, false, "Unable to find '%s' in the current app root directory.", m_fileName); - return false; - } - if (!ReadEngineConfigIntoMap(engineJsonFilePath, m_engineConfigMap)) - { - AZ_Warning(m_logWindow, false, "Defaulting root engine path to '%s'", currentEngineRoot); - return false; - } - - // Read in the local engine version value - auto localEngineVersionValue = m_engineConfigMap.find(QString(AzToolsFramework::Internal::s_engineConfigEngineVersionKey)); - QString localEngineVersion(localEngineVersionValue.value()); - azstrncpy(m_engineVersion, AZ_ARRAY_SIZE(m_engineVersion), localEngineVersion.toUtf8().data(), localEngineVersion.length() + 1); - - return true; - } - - const char* GetEngineRoot() const - { - return m_engineRoot; - } - - const char* GetEngineVersion() const - { - return m_engineVersion; - } - }; - - ToolsApplication::ToolsApplication(int* argc, char*** argv) : AzFramework::Application(argc, argv) , m_selectionBounds(AZ::Aabb()) @@ -339,7 +233,6 @@ namespace AzToolsFramework , m_isInIsolationMode(false) { ToolsApplicationRequests::Bus::Handler::BusConnect(); - m_engineConfigImpl.reset(new ToolsApplication::EngineConfigImpl(AzToolsFramework::Internal::s_startupLogWindow, AzToolsFramework::Internal::s_engineConfigFileName)); m_undoCache.RegisterToUndoCacheInterface(); } @@ -391,7 +284,6 @@ namespace AzToolsFramework void ToolsApplication::Start(const Descriptor& descriptor, const StartupParameters& startupParameters/* = StartupParameters()*/) { Application::Start(descriptor, startupParameters); - InitializeEngineConfig(); m_editorEntityManager.Start(); @@ -399,14 +291,6 @@ namespace AzToolsFramework AZ_Assert(m_editorEntityAPI, "ToolsApplication - Could not retrieve instance of EditorEntityAPI"); } - void ToolsApplication::InitializeEngineConfig() - { - if (!m_engineConfigImpl->Initialize(GetEngineRoot())) - { - AZ_Warning(AzToolsFramework::Internal::s_startupLogWindow, false, "Defaulting engine root path to '%s'", GetEngineRoot()); - } - } - void ToolsApplication::StartCommon(AZ::Entity* systemEntity) { Application::StartCommon(systemEntity); @@ -1832,16 +1716,6 @@ namespace AzToolsFramework return m_isInIsolationMode; } - const char* ToolsApplication::GetEngineRootPath() const - { - return m_engineConfigImpl->GetEngineRoot(); - } - - const char* ToolsApplication::GetEngineVersion() const - { - return m_engineConfigImpl->GetEngineVersion(); - } - void ToolsApplication::CreateAndAddEntityFromComponentTags(const AZStd::vector& requiredTags, const char* entityName) { if (!entityName || !entityName[0]) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h index ef9f190309..0f038422ce 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h @@ -150,8 +150,6 @@ namespace AzToolsFramework void EnterEditorIsolationMode() override; void ExitEditorIsolationMode() override; bool IsEditorInIsolationMode() override; - const char* GetEngineRootPath() const override; - const char* GetEngineVersion() const override; void CreateAndAddEntityFromComponentTags(const AZStd::vector& requiredTags, const char* entityName) override; @@ -174,7 +172,6 @@ namespace AzToolsFramework void CreateUndosForDirtyEntities(); void ConsistencyCheckUndoCache(); - void InitializeEngineConfig(); AZ::Aabb m_selectionBounds; EntityIdList m_selectedEntities; EntityIdList m_highlightedEntities; @@ -186,9 +183,6 @@ namespace AzToolsFramework bool m_isInIsolationMode; EntityIdSet m_isolatedEntityIdSet; - class EngineConfigImpl; - AZStd::unique_ptr m_engineConfigImpl; - EditorEntityAPI* m_editorEntityAPI = nullptr; EditorEntityManager m_editorEntityManager; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp index bc27ffa5e1..261645e79a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp @@ -38,6 +38,7 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include #include #include #include @@ -1212,9 +1213,8 @@ namespace AzToolsFramework if (!QFile::exists(path)) { - const char* engineRoot = nullptr; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath); - QDir engineDir = engineRoot ? QDir(engineRoot) : QDir::current(); + AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath(); + QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current(); path = engineDir.absoluteFilePath(iconPath.c_str()); } diff --git a/Code/Sandbox/Editor/AssetEditor/AssetEditorWindow.cpp b/Code/Sandbox/Editor/AssetEditor/AssetEditorWindow.cpp index 4645019261..53e2884943 100644 --- a/Code/Sandbox/Editor/AssetEditor/AssetEditorWindow.cpp +++ b/Code/Sandbox/Editor/AssetEditor/AssetEditorWindow.cpp @@ -20,6 +20,7 @@ // AzCore #include #include +#include // AzToolsFramework #include @@ -104,13 +105,9 @@ void AssetEditorWindow::SaveAssetAs(const AZStd::string_view assetPath) return; } - const char* engineRoot; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath); + auto absoluteAssetPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / assetPath; - AZStd::string absoluteAssetPath; - AzFramework::StringFunc::Path::Join(engineRoot, assetPath.data(), absoluteAssetPath); - - if (!m_ui->m_assetEditorWidget->SaveAssetToPath(absoluteAssetPath)) + if (!m_ui->m_assetEditorWidget->SaveAssetToPath(absoluteAssetPath.Native())) { AZ_Warning("Asset Editor", false, "File was not saved correctly via SaveAssetAs."); } diff --git a/Code/Sandbox/Editor/PythonEditorFuncs.cpp b/Code/Sandbox/Editor/PythonEditorFuncs.cpp index 5c74a950c2..f5de22387c 100644 --- a/Code/Sandbox/Editor/PythonEditorFuncs.cpp +++ b/Code/Sandbox/Editor/PythonEditorFuncs.cpp @@ -19,6 +19,8 @@ #include #include +#include + // AzToolsFramework #include #include @@ -293,9 +295,8 @@ namespace // If not found try editor folder if (!CFileUtil::FileExists(path)) { - const char* engineRoot = nullptr; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath); - QDir engineDir = engineRoot ? QDir(engineRoot) : QDir::current(); + AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath(); + QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current(); QString scriptFolder = engineDir.absoluteFilePath("Editor/Scripts/"); Path::ConvertBackSlashToSlash(scriptFolder); diff --git a/Code/Sandbox/Editor/ToolBox.cpp b/Code/Sandbox/Editor/ToolBox.cpp index def7329e83..46c01ce864 100644 --- a/Code/Sandbox/Editor/ToolBox.cpp +++ b/Code/Sandbox/Editor/ToolBox.cpp @@ -18,6 +18,8 @@ #include "ToolBox.h" +#include + // AzToolsFramework #include #include @@ -419,9 +421,8 @@ void CToolBoxManager::Load(QString xmlpath, AmazonToolbar* pToolbar, bool bToolb } } - const char* engineRoot = nullptr; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(engineRoot, &AzToolsFramework::ToolsApplicationRequests::GetEngineRootPath); - QDir engineDir = engineRoot ? QDir(engineRoot) : QDir::current(); + AZ::IO::FixedMaxPathString engineRoot = AZ::Utils::GetEnginePath(); + QDir engineDir = !engineRoot.empty() ? QDir(QString(engineRoot.c_str())) : QDir::current(); string enginePath = PathUtil::AddSlash(engineDir.absolutePath().toUtf8().data()); From ee3f157fb8620e340f921a8b581b0273a2339c78 Mon Sep 17 00:00:00 2001 From: karlberg Date: Thu, 15 Apr 2021 20:41:08 -0700 Subject: [PATCH 44/74] Fix memory leak in multiplayer unit test --- Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp b/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp index 13adc6d774..c18c2ee5e3 100644 --- a/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp +++ b/Gems/Multiplayer/Code/Tests/MultiplayerSystemTests.cpp @@ -97,6 +97,10 @@ namespace UnitTest m_mpComponent->OnConnect(&connMock2); EXPECT_EQ(m_connectionAcquiredCount, 25); + + // Clean up connection data + m_mpComponent->OnDisconnect(&connMock1, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local); + m_mpComponent->OnDisconnect(&connMock2, AzNetworking::DisconnectReason::None, AzNetworking::TerminationEndpoint::Local); } } From 89a935cd29b4daf0f77d4f637fbc85fa46ae07fc Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 20:44:01 -0700 Subject: [PATCH 45/74] Minor update --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 812198668d..6a94a46b93 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 2; //ATOM-15196 + builderDescriptor.m_version = 3; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From 05359187c4a2d4aca2d15e59ffff771eaee8588d Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 20:45:53 -0700 Subject: [PATCH 46/74] Test update --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 6a94a46b93..812198668d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 3; //ATOM-15196 + builderDescriptor.m_version = 2; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From d0435b448959e69a38b7c914954ca40f75c6c1c8 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 20:46:48 -0700 Subject: [PATCH 47/74] Minor update --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 812198668d..6a94a46b93 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 2; //ATOM-15196 + builderDescriptor.m_version = 3; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From ca86068d8338a9484eccb08a8925a4b166fa3b32 Mon Sep 17 00:00:00 2001 From: moudgils Date: Thu, 15 Apr 2021 20:55:54 -0700 Subject: [PATCH 48/74] Minor update --- .../Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp index 6a94a46b93..92c30c28b1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/ResourcePool/ResourcePoolBuilder.cpp @@ -45,7 +45,7 @@ namespace AZ AssetBuilderSDK::AssetBuilderDesc builderDescriptor; builderDescriptor.m_name = "Atom Resource Pool Asset Builder"; - builderDescriptor.m_version = 3; //ATOM-15196 + builderDescriptor.m_version = 2; //ATOM-15196 builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt, AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); builderDescriptor.m_busId = azrtti_typeid(); From 1363a5b76ca15fd8dd276fc8c347ce3031b14b01 Mon Sep 17 00:00:00 2001 From: greerdv Date: Fri, 16 Apr 2021 16:52:30 +0100 Subject: [PATCH 49/74] fixing bugs with failing to disconnect from non-uniform scale event handlers in multiple places --- .../Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp | 1 + Gems/PhysX/Code/Source/EditorColliderComponent.cpp | 2 ++ Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp | 1 + Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp | 1 + Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp | 1 + 5 files changed, 6 insertions(+) diff --git a/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp b/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp index 0ea6be5e4d..3f36840e3d 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/EditorPolygonPrismShapeComponentMode.cpp @@ -65,6 +65,7 @@ namespace LmbrCentral ShapeComponentNotificationsBus::Handler::BusDisconnect(); PolygonPrismShapeComponentNotificationBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); + m_nonUniformScaleChangedHandler.Disconnect(); DestroyManipulators(); } diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index 4b72eb32ad..c470c05c58 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -391,6 +391,8 @@ namespace PhysX Physics::WorldBodyRequestBus::Handler::BusDisconnect(); m_colliderDebugDraw.Disconnect(); AZ::Data::AssetBus::MultiHandler::BusDisconnect(); + m_nonUniformScaleChangedHandler.Disconnect(); + EditorColliderComponentRequestBus::Handler::BusDisconnect(); AZ::Render::MeshComponentNotificationBus::Handler::BusDisconnect(); LmbrCentral::MeshComponentNotificationBus::Handler::BusDisconnect(); ColliderShapeRequestBus::Handler::BusDisconnect(); diff --git a/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp b/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp index 1dd25ced32..b4b730538d 100644 --- a/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorForceRegionComponent.cpp @@ -277,6 +277,7 @@ namespace PhysX force.Deactivate(); } + m_nonUniformScaleChangedHandler.Disconnect(); AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); EditorComponentBase::Deactivate(); } diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp index d5ce38d389..5445f7fc69 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp @@ -273,6 +273,7 @@ namespace PhysX m_debugDisplayDataChangeHandler.Disconnect(); Physics::WorldBodyRequestBus::Handler::BusDisconnect(); + m_nonUniformScaleChangedHandler.Disconnect(); m_sceneStartSimHandler.Disconnect(); Physics::ColliderComponentEventBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); diff --git a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp index a1b8516150..639a079c02 100644 --- a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp @@ -666,6 +666,7 @@ namespace PhysX Physics::WorldBodyRequestBus::Handler::BusDisconnect(); m_colliderDebugDraw.Disconnect(); + m_nonUniformScaleChangedHandler.Disconnect(); PhysX::ColliderShapeRequestBus::Handler::BusDisconnect(); LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); From f552fc7ccd97bc8ba7cc1841c4c4f5af5122332e Mon Sep 17 00:00:00 2001 From: hultonha Date: Fri, 16 Apr 2021 17:30:06 +0100 Subject: [PATCH 50/74] Fix for ReadMesh error reporting --- .../Code/Include/WhiteBox/WhiteBoxToolApi.h | 22 +++++++++++++++---- .../Source/Asset/WhiteBoxMeshAssetHandler.cpp | 7 ++++-- .../Code/Source/Core/WhiteBoxToolApi.cpp | 12 +++++----- .../Code/Source/EditorWhiteBoxComponent.cpp | 14 ++++++------ Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp | 3 ++- 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h index 5b8d384774..8e74c09f52 100644 --- a/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h +++ b/Gems/WhiteBox/Code/Include/WhiteBox/WhiteBoxToolApi.h @@ -729,15 +729,29 @@ namespace WhiteBox /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Serialization + //! The result of attempting to deserialize a white box mesh from a white box mesh stream. + enum class ReadResult + { + Full, //!< The white box mesh stream was full and was read into white box mesh (it is now initialized). + Empty, //!< The white box mesh stream was empty so no white box mesh was loaded. + Error //!< An error occurred while trying to deserialize white box mesh stream. + }; + //! Take an input stream of bytes and create a white box mesh from the deserialized data. - //! @return Will return false if any error was encountered during deserialization, true otherwise. + //! @return Will return ReadResult::Full if the white box mesh stream was filled with data and + //! the white box mesh was initialized, ReadResult::Empty if white box mesh stream did not contain + //! any data (white box mesh will be left empty) or ReadResult::Error if any error was encountered + //! during deserialization. //! @note A white box mesh must have been created first. - bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input); + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input); //! Take an input stream and create a white box mesh from the deserialized data. - //! @return Will return false if any error was encountered during deserialization, true otherwise. + //! @return Will return ReadResult::Full if the white box mesh stream was filled with data and + //! the white box mesh was initialized, ReadResult::Empty if white box mesh stream did not contain + //! any data (white box mesh will be left empty) or ReadResult::Error if any error was encountered + //! during deserialization. //! @note The input stream must not skip white space characters (std::noskipws must be set on the stream). - bool ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input); + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input); //! Take a white box mesh and write it out to a stream of bytes. //! @return Will return false if any error was encountered during serialization, true otherwise. diff --git a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp index 7aa12777e0..3ed22a3d1b 100644 --- a/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp +++ b/Gems/WhiteBox/Code/Source/Asset/WhiteBoxMeshAssetHandler.cpp @@ -118,12 +118,15 @@ namespace WhiteBox stream->Read(size, whiteBoxData.data()); auto whiteBoxMesh = WhiteBox::Api::CreateWhiteBoxMesh(); - const bool success = WhiteBox::Api::ReadMesh(*whiteBoxMesh, whiteBoxData); + const auto result = WhiteBox::Api::ReadMesh(*whiteBoxMesh, whiteBoxData); + // if result is not 'Full', then whiteBoxMeshAsset could be empty which is most likely an error + // as no data was loaded from the asset, or it was not correctly read in stream->Read(..) + const auto success = result == Api::ReadResult::Full; if (success) { whiteBoxMeshAsset->SetMesh(AZStd::move(whiteBoxMesh)); - whiteBoxMeshAsset->SetWhiteBoxData(whiteBoxData); + whiteBoxMeshAsset->SetWhiteBoxData(AZStd::move(whiteBoxData)); } return success ? AZ::Data::AssetHandler::LoadResult::LoadComplete diff --git a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp index 03f2545ae1..5803f066ae 100644 --- a/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp +++ b/Gems/WhiteBox/Code/Source/Core/WhiteBoxToolApi.cpp @@ -3403,13 +3403,13 @@ namespace WhiteBox return false; } - bool ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input) + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, const WhiteBoxMeshStream& input) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); if (input.empty()) { - return false; + return ReadResult::Empty; } std::string inputStr; @@ -3423,19 +3423,19 @@ namespace WhiteBox return ReadMesh(whiteBox, whiteBoxStream); } - bool ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input) + ReadResult ReadMesh(WhiteBoxMesh& whiteBox, std::istream& input) { const auto skipws = input.flags() & std::ios_base::skipws; AZ_Assert(skipws == 0, "Input stream must not skip white space characters"); if (skipws != 0) { - return false; + return ReadResult::Error; } AZStd::lock_guard lg(g_omSerializationLock); OpenMesh::IO::Options options{OpenMesh::IO::Options::FaceTexCoord | OpenMesh::IO::Options::FaceNormal}; - return OpenMesh::IO::read_mesh(whiteBox.mesh, input, ".om", options); + return OpenMesh::IO::read_mesh(whiteBox.mesh, input, ".om", options) ? ReadResult::Full : ReadResult::Error; } WhiteBoxMeshPtr CloneMesh(const WhiteBoxMesh& whiteBox) @@ -3449,7 +3449,7 @@ namespace WhiteBox } WhiteBoxMeshPtr newMesh = CreateWhiteBoxMesh(); - if (!ReadMesh(*newMesh, clonedData)) + if (ReadMesh(*newMesh, clonedData) != ReadResult::Full) { return nullptr; } diff --git a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp index 61012b8577..e88b4ce686 100644 --- a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp +++ b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponent.cpp @@ -348,14 +348,14 @@ namespace WhiteBox else { // attempt to load the mesh - if (Api::ReadMesh(*m_whiteBox, m_whiteBoxData)) + const auto result = Api::ReadMesh(*m_whiteBox, m_whiteBoxData); + AZ_Error("EditorWhiteBoxComponent", result != WhiteBox::Api::ReadResult::Error, "Error deserializing white box mesh stream"); + + // if the read was successful but the byte stream is empty + // (there was nothing to load), create a default mesh + if (result == Api::ReadResult::Empty) { - // if the read was successful but the byte stream is empty - // (there was nothing to load), create a default mesh - if (m_whiteBoxData.empty()) - { - Api::InitializeAsUnitCube(*m_whiteBox); - } + Api::InitializeAsUnitCube(*m_whiteBox); } } } diff --git a/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp b/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp index 1d55539720..1135a915ec 100644 --- a/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp +++ b/Gems/WhiteBox/Code/Tests/WhiteBoxTest.cpp @@ -470,6 +470,7 @@ namespace UnitTest TEST_F(WhiteBoxTestFixture, MeshNotDeserializedWithSkipWhiteSpaceStream) { namespace Api = WhiteBox::Api; + using testing::Eq; Api::InitializeAsUnitCube(*m_whiteBox); AZStd::vector serializedWhiteBox; @@ -485,7 +486,7 @@ namespace UnitTest // note: std::stringstream will default to skip white space characters AZ_TEST_START_TRACE_SUPPRESSION; - EXPECT_FALSE(Api::ReadMesh(*m_whiteBox, whiteBoxStream)); + EXPECT_THAT(Api::ReadMesh(*m_whiteBox, whiteBoxStream), Eq(Api::ReadResult::Error)); AZ_TEST_STOP_TRACE_SUPPRESSION(1); } From 8e34d784e60f0e9489bec5335fa6171af5e3cad5 Mon Sep 17 00:00:00 2001 From: qingtao Date: Fri, 16 Apr 2021 09:47:03 -0700 Subject: [PATCH 51/74] ATOM-15252 [Atom 0.8.5] Track View capture crashes when scene contains certain postfx The crash was because the "BlendColorGradingLutImageAttachmentId" attachment got imported to attachment database twice. This fix avoids import this attachment twice. It also avoid crash but only report a warning if an imported attachment wasn't used in any scope. Enable both RHI and RPI validation (no visiable performance impact observed. --- .../PostProcessing/BlendColorGradingLutsPass.cpp | 9 +++++++-- Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp | 2 +- .../RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp | 12 ++++++++++++ Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp index 206e58d5e6..e0ff253301 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/BlendColorGradingLutsPass.cpp @@ -131,8 +131,13 @@ namespace AZ AZ_Assert(m_blendedLut.m_lutImage != nullptr, "BlendColorGradingLutsPass unable to acquire LUT image"); AZ::RHI::AttachmentId imageAttachmentId = AZ::RHI::AttachmentId("BlendColorGradingLutImageAttachmentId"); - [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(imageAttachmentId, m_blendedLut.m_lutImage); - AZ_Error("BlendColorGradingLutsPass", result == RHI::ResultCode::Success, "Failed to import compute buffer with error %d", result); + + // import this attachment if it wasn't imported + if (!frameGraph.GetAttachmentDatabase().IsAttachmentValid(imageAttachmentId)) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(imageAttachmentId, m_blendedLut.m_lutImage); + AZ_Error("BlendColorGradingLutsPass", result == RHI::ResultCode::Success, "Failed to import BlendColorGradingLutImageAttachmentId with error %d", result); + } RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = imageAttachmentId; diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp index 4d35411e09..21eb634159 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/Base.cpp @@ -16,6 +16,6 @@ namespace AZ { namespace RHI { - bool Validation::s_isEnabled = BuildOptions::IsDebugBuild; + bool Validation::s_isEnabled = BuildOptions::IsDebugBuild || BuildOptions::IsProfileBuild; } } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp index 1ae8a4ae96..7fc1db179a 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp @@ -404,6 +404,12 @@ namespace AZ Buffer& buffer = static_cast(*bufferFrameAttachment.GetBuffer()); RHI::BufferScopeAttachment* scopeAttachment = bufferFrameAttachment.GetFirstScopeAttachment(); + if (scopeAttachment == nullptr) + { + AZ_WarningOnce("RHI", false, "Imported BufferFrameAttachment isn't used in any Scope"); + return; + } + D3D12_RESOURCE_TRANSITION_BARRIER transition; transition.pResource = buffer.GetMemoryView().GetMemory(); transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; @@ -471,6 +477,12 @@ namespace AZ Image& image = static_cast(*imageFrameAttachment.GetImage()); RHI::ImageScopeAttachment* scopeAttachment = imageFrameAttachment.GetFirstScopeAttachment(); + if (scopeAttachment == nullptr) + { + AZ_WarningOnce("RHI", false, "Imported ImageFrameAttachment isn't used in any Scope"); + return; + } + D3D12_RESOURCE_TRANSITION_BARRIER transition; transition.pResource = image.GetMemoryView().GetMemory(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp index 7012a7cf88..8addb16a23 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Base.cpp @@ -16,6 +16,6 @@ namespace AZ { namespace RPI { - bool Validation::s_isEnabled = RHI::BuildOptions::IsDebugBuild; + bool Validation::s_isEnabled = RHI::BuildOptions::IsDebugBuild || RHI::BuildOptions::IsProfileBuild; } } From bc9b2b4c2ee28ccd11fc4de120eadc4d3056f3cd Mon Sep 17 00:00:00 2001 From: qingtao Date: Fri, 16 Apr 2021 11:05:03 -0700 Subject: [PATCH 52/74] Fixed Mac compile issue. Set default refresh type to realtime (due to a known issue with OncePerSecond with ASV) --- Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h | 2 +- Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h index 6520844edd..ce6915699b 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.h @@ -249,7 +249,7 @@ namespace AZ bool m_showTimeline = false; // Controls how often the timestamp data is refreshed - RefreshType m_refreshType = RefreshType::OncePerSecond; + RefreshType m_refreshType = RefreshType::Realtime; AZStd::sys_time_t m_lastUpdateTimeMicroSecond; }; diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl index eb0e295129..fa9395dffc 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiGpuProfiler.inl @@ -16,6 +16,8 @@ #include #include +#include + namespace AZ { namespace Render @@ -725,7 +727,7 @@ namespace AZ ImGui::BeginTooltip(); ImGui::Text("Name: %s", passEntry->m_name.GetCStr()); ImGui::Text("Path: %s", passEntry->m_path.GetCStr()); - ImGui::Text("Duration in ticks: %lu", passEntry->m_timestampResult.GetDurationInTicks()); + ImGui::Text("Duration in ticks: %" PRIu64, passEntry->m_timestampResult.GetDurationInTicks()); ImGui::Text("Duration in microsecond: %.3f us", passEntry->m_timestampResult.GetDurationInNanoseconds()/1000.f); ImGui::EndTooltip(); } From 10faddb113333a77221ff3df8be4b619fe318332 Mon Sep 17 00:00:00 2001 From: alexpete Date: Fri, 16 Apr 2021 12:05:11 -0700 Subject: [PATCH 53/74] Integrating github/staging through commit ef88e6e --- CMakeLists.txt | 4 - .../Common/PerInstanceConstantBufferPool.cpp | 4 + .../CryEngine/RenderDll/Common/RenderMesh.cpp | 1 + Code/Framework/AzCore/AzCore/Math/Vector2.cpp | 4 +- .../Entity/EntityDebugDisplayBus.h | 2 - .../AzFramework/Font/FontInterface.h | 85 + .../AzFramework/Viewport/ScreenGeometry.h | 13 + .../AzFramework/Viewport/ViewportScreen.cpp | 27 +- .../AzFramework/Viewport/ViewportScreen.h | 5 + .../AzFramework/azframework_files.cmake | 1 + .../EditorTransformComponentSelection.cpp | 47 +- .../Editor/Objects/DisplayContextShared.inl | 22 - .../SandboxIntegration.cpp | 20 - .../SandboxIntegration.h | 2 - ...enticationNotificationBusBehaviorHandler.h | 69 +- .../AuthenticationProviderManager.h | 22 +- .../AuthenticationProviderScriptCanvasBus.h | 103 + .../AuthenticationProviderTypes.h | 8 + ...horizationNotificationBusBehaviorHandler.h | 11 +- ...ManagementNotificationBusBehaviorHandler.h | 49 +- .../AuthenticationProviderBus.h | 10 +- .../Authentication/AuthenticationTokens.h | 15 +- .../Authorization/ClientAuthAWSCredentials.h | 36 +- .../AWSCognitoUserManagementBus.h | 5 +- .../Source/AWSClientAuthSystemComponent.cpp | 44 +- .../AWSCognitoAuthenticationProvider.cpp | 2 +- .../AuthenticationProviderManager.cpp | 87 +- .../Authentication/AuthenticationTokens.cpp | 26 + .../AWSCognitoAuthorizationController.cpp | 6 +- .../AWSCognitoUserManagementController.cpp | 2 +- .../AuthenticationProviderManagerMock.h | 55 + ...tionProviderManagerScriptCanvasBusTest.cpp | 261 ++ .../AuthenticationProviderManagerTest.cpp | 48 +- .../Code/awsclientauth_files.cmake | 1 + .../Code/awsclientauth_test_files.cmake | 2 + .../cdk/auth/cognito_identity_pool_role.py | 3 +- .../Code/Source/AuxGeom/AuxGeomDrawQueue.cpp | 10 +- .../Code/Source/AuxGeom/AuxGeomDrawQueue.h | 2 +- .../Atom/RPI.Public/AuxGeom/AuxGeomDraw.h | 2 +- .../AtomDebugDisplayViewportInterface.cpp | 2123 ++++++++++------- .../AtomDebugDisplayViewportInterface.h | 55 +- .../AtomLyIntegration/AtomFont/AtomFont.h | 37 +- .../AtomLyIntegration/AtomFont/FFont.h | 58 +- .../AtomFont/Code/Source/AtomFont.cpp | 78 +- .../AtomFont/Code/Source/FFont.cpp | 268 ++- .../CoreLights/AreaLightComponentConfig.h | 3 + .../CoreLights/AreaLightComponentConfig.cpp | 5 + .../AreaLightComponentController.cpp | 9 + .../Source/CoreLights/DiskLightDelegate.cpp | 48 +- .../CoreLights/EditorAreaLightComponent.cpp | 57 +- .../Source/CoreLights/LightDelegateBase.h | 5 + .../Source/CoreLights/LightDelegateBase.inl | 6 + .../CoreLights/LightDelegateInterface.h | 3 + .../CoreLights/SimpleSpotLightDelegate.cpp | 35 +- .../CoreLights/SimpleSpotLightDelegate.h | 4 +- .../AtomShim_RenderAuxGeom.cpp | 4 +- cmake/FindTarget.cmake.in | 45 + cmake/Findo3de.cmake | 25 +- cmake/Findo3de.cmake.in | 36 + cmake/Platform/Common/Install_common.cmake | 11 +- 60 files changed, 2872 insertions(+), 1159 deletions(-) create mode 100644 Code/Framework/AzFramework/AzFramework/Font/FontInterface.h create mode 100644 Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h create mode 100644 Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerMock.h create mode 100644 Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp create mode 100644 cmake/FindTarget.cmake.in create mode 100644 cmake/Findo3de.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index c09cfc9588..6da92f9c2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,15 +23,11 @@ endif() include(cmake/Version.cmake) -set(INSTALLED_ENGINE TRUE) - if(NOT PROJECT_NAME) project(O3DE LANGUAGES C CXX VERSION ${LY_VERSION_STRING} ) - - set(INSTALLED_ENGINE FALSE) endif() include(cmake/Initialize.cmake) diff --git a/Code/CryEngine/RenderDll/Common/PerInstanceConstantBufferPool.cpp b/Code/CryEngine/RenderDll/Common/PerInstanceConstantBufferPool.cpp index 7fa69f6026..f2475c0b48 100644 --- a/Code/CryEngine/RenderDll/Common/PerInstanceConstantBufferPool.cpp +++ b/Code/CryEngine/RenderDll/Common/PerInstanceConstantBufferPool.cpp @@ -274,6 +274,10 @@ void PerInstanceConstantBufferPool::SetConstantBuffer(SRendItem* renderItem) deviceManager.BindConstantBuffer(eHWSC_Vertex, m_PooledIndirectConstantBuffer[indirectId], eConstantBufferShaderSlot_SPIIndex); deviceManager.BindConstantBuffer(eHWSC_Pixel, m_PooledIndirectConstantBuffer[indirectId], eConstantBufferShaderSlot_SPIIndex); #else + AZ::u32 itemIndex = directId % SPI_NUM_INSTS_PER_CB; + AZ::u32 first[1] = {itemIndex * static_cast(sizeof(HLSL_PerInstanceConstantBuffer))}; + AZ::u32 count[1] = {static_cast(sizeof(HLSL_PerInstanceConstantBuffer))}; + deviceManager.BindConstantBuffer(eHWSC_Vertex, m_PooledConstantBuffer[bufferIndex], eConstantBufferShaderSlot_SPI, first[0], count[0]); deviceManager.BindConstantBuffer(eHWSC_Pixel, m_PooledConstantBuffer[bufferIndex], eConstantBufferShaderSlot_SPI, first[0], count[0]); #endif diff --git a/Code/CryEngine/RenderDll/Common/RenderMesh.cpp b/Code/CryEngine/RenderDll/Common/RenderMesh.cpp index 10bbfbf0e6..357731fc6d 100644 --- a/Code/CryEngine/RenderDll/Common/RenderMesh.cpp +++ b/Code/CryEngine/RenderDll/Common/RenderMesh.cpp @@ -755,6 +755,7 @@ lSysUpdate: buffer_handle_t nVB = ~0u; # if BUFFER_ENABLE_DIRECT_ACCESS && !defined(NULL_RENDERER) nVB = MS->m_nID; + int nFrame = gRenDev->m_RP.m_TI[gRenDev->m_RP.m_nFillThreadID].m_nFrameUpdateID; if ((nVB != ~0u && (MS->m_nFrameCreate != nFrame || MS->m_nElements != m_nVerts)) || !CRenderer::CV_r_buffer_enable_lockless_updates) # endif goto lSysCreate; diff --git a/Code/Framework/AzCore/AzCore/Math/Vector2.cpp b/Code/Framework/AzCore/AzCore/Math/Vector2.cpp index bc5f6ecdad..c2a3a934b0 100644 --- a/Code/Framework/AzCore/AzCore/Math/Vector2.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Vector2.cpp @@ -167,14 +167,14 @@ namespace AZ } } - AZ_MATH_INLINE Vector2::Vector2(const Vector3& source) + Vector2::Vector2(const Vector3& source) : m_x(source.GetX()) , m_y(source.GetY()) { } - AZ_MATH_INLINE Vector2::Vector2(const Vector4& source) + Vector2::Vector2(const Vector4& source) : m_x(source.GetX()) , m_y(source.GetY()) { diff --git a/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h b/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h index a5d3e657f5..f84f0276e1 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h @@ -105,8 +105,6 @@ namespace AzFramework virtual bool SetDrawInFrontMode(bool bOn) { (void)bOn; return false; } virtual AZ::u32 GetState() { return 0; } virtual AZ::u32 SetState(AZ::u32 state) { (void)state; return 0; } - virtual AZ::u32 SetStateFlag(AZ::u32 state) { (void)state; return 0; } - virtual AZ::u32 ClearStateFlag(AZ::u32 state) { (void)state; return 0; } virtual void PushMatrix(const AZ::Transform& tm) { (void)tm; } virtual void PopMatrix() {} diff --git a/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h new file mode 100644 index 0000000000..7c5bcce6d6 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Font/FontInterface.h @@ -0,0 +1,85 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include +#include +#include +#include + +namespace AzFramework +{ + using FontId = uint32_t; + static constexpr FontId InvalidFontId = 0xffffffffu; + + enum class TextHorizontalAlignment : uint16_t + { + Left, + Right, + Center + }; + + enum class TextVerticalAlignment : uint16_t + { + Top, + Bottom, + Center, + }; + + //! Standard parameters for drawing text on screen + struct TextDrawParameters + { + ViewportId m_drawViewportId = InvalidViewportId; //! Viewport to draw into + AZ::Vector3 m_position; //! world space position for 3d draws, screen space x,y,depth for 2d. + AZ::Color m_color = AZ::Colors::White; //! Color to draw the text + AZ::Vector2 m_scale = AZ::Vector2(1.0f); //! font scale + TextHorizontalAlignment m_hAlign = TextHorizontalAlignment::Left; //! Horizontal text alignment + TextVerticalAlignment m_vAlign = TextVerticalAlignment::Top; //! Vertical text alignment + bool m_monospace = false; //! disable character proportional spacing + bool m_depthTest = false; //! Test character against the depth buffer + bool m_virtual800x600ScreenSize = true; //! Text placement and size are scaled relative to a virtual 800x600 resolution + bool m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger + bool m_multiline = true; //! text respects ascii newline characters + }; + + class FontDrawInterface + { + public: + AZ_RTTI(FontDrawInterface, "{545A7C14-CB3E-4A5B-B435-13EA606708EE}"); + + FontDrawInterface() = default; + virtual ~FontDrawInterface() = default; + + virtual void DrawScreenAlignedText2d( + const TextDrawParameters& params, + const AZStd::string_view& string) = 0; + virtual void DrawScreenAlignedText3d( + const TextDrawParameters& params, + const AZStd::string_view& string) = 0; + }; + + class FontQueryInterface + { + public: + AZ_RTTI(FontQueryInterface, "{4BDD8520-EBC1-4680-B25E-421BDF31750F}"); + + FontQueryInterface() = default; + virtual ~FontQueryInterface() = default; + + FontId GetFontId(const AZStd::string_view& fontName) const {return FontId(AZ::Crc32(fontName));} + virtual FontDrawInterface* GetFontDrawInterface(FontId) const = 0; + virtual FontDrawInterface* GetDefaultFontDrawInterface() const = 0; + + }; +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h b/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h index 1b570ebb8e..d3ae4e16f3 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ScreenGeometry.h @@ -14,6 +14,7 @@ #include #include +#include #include namespace AZ @@ -133,6 +134,18 @@ namespace AzFramework return !operator==(lhs, rhs); } + inline ScreenPoint ScreenPointFromNDC(const AZ::Vector3& screenNDC, const AZ::Vector2& viewportSize) + { + return ScreenPoint( + aznumeric_caster(std::round(screenNDC.GetX() * viewportSize.GetX())), + aznumeric_caster(std::round((1.0f - screenNDC.GetY()) * viewportSize.GetY()))); + } + + inline AZ::Vector2 NDCFromScreenPoint(const ScreenPoint& screenPoint, const AZ::Vector2& viewportSize) + { + return AZ::Vector2(aznumeric_cast(screenPoint.m_x), viewportSize.GetY() - aznumeric_cast(screenPoint.m_y)) / viewportSize; + } + //! Return an AZ::Vector2 from a ScreenPoint. inline AZ::Vector2 Vector2FromScreenPoint(const ScreenPoint& screenPoint) { diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp index 3ca16897ba..5d2d02a398 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.cpp @@ -101,20 +101,25 @@ namespace AzFramework cameraState.m_nearClip, cameraState.m_farClip); } - ScreenPoint WorldToScreen( - const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection, - const AZ::Vector2& viewportSize) + AZ::Vector3 WorldToScreenNDC( + const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection) { // transform the world space position to clip space const auto clipSpacePosition = cameraProjection * cameraView * AZ::Vector3ToVector4(worldPosition, 1.0f); // transform the clip space position to ndc space (perspective divide) const auto ndcPosition = clipSpacePosition / clipSpacePosition.GetW(); // transform ndc space from <-1,1> to <0, 1> range - const auto ndcNormalizedPosition = (AZ::Vector4ToVector2(ndcPosition) + AZ::Vector2::CreateOne()) * 0.5f; + return (AZ::Vector4ToVector3(ndcPosition) + AZ::Vector3::CreateOne()) * 0.5f; + } + + + ScreenPoint WorldToScreen( + const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection, + const AZ::Vector2& viewportSize) + { + const auto ndcNormalizedPosition = WorldToScreenNDC(worldPosition, cameraView, cameraProjection); // scale ndc position by screen dimensions to return screen position - return ScreenPoint( - aznumeric_caster(std::round(ndcNormalizedPosition.GetX() * viewportSize.GetX())), - aznumeric_caster(std::round(viewportSize.GetY() - (ndcNormalizedPosition.GetY() * viewportSize.GetY())))); + return ScreenPointFromNDC(ndcNormalizedPosition, viewportSize); } ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState) @@ -127,12 +132,8 @@ namespace AzFramework const ScreenPoint& screenPosition, const AZ::Matrix4x4& inverseCameraView, const AZ::Matrix4x4& inverseCameraProjection, const AZ::Vector2& viewportSize) { - const auto screenHeight = viewportSize.GetY(); - const auto flippedScreenPosition = - AZ::Vector2(aznumeric_caster(screenPosition.m_x), aznumeric_caster(screenHeight - screenPosition.m_y)); - - // convert screen space coordinates to <-1,1> range - const auto ndcPosition = (flippedScreenPosition / viewportSize) * 2.0f - AZ::Vector2::CreateOne(); + // convert screen space coordinates from <0, 1> to <-1,1> range + const auto ndcPosition = NDCFromScreenPoint(screenPosition, viewportSize) * 2.0f - AZ::Vector2::CreateOne(); // transform ndc space position to clip space const auto clipSpacePosition = inverseCameraProjection * Vector2ToVector4(ndcPosition, -1.0f, 1.0f); diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h index 582e051bbb..a2c650465f 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportScreen.h @@ -28,6 +28,11 @@ namespace AzFramework struct ScreenPoint; struct ViewportInfo; + //! Projects a position in world space to screen space normalized device coordinates for the given camera. + AZ::Vector3 WorldToScreenNDC( + const AZ::Vector3& worldPosition, const AZ::Matrix4x4& cameraView, const AZ::Matrix4x4& cameraProjection); + + //! Projects a position in world space to screen space for the given camera. ScreenPoint WorldToScreen(const AZ::Vector3& worldPosition, const CameraState& cameraState); diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index b37c1b259f..cde2afb930 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -145,6 +145,7 @@ set(FILES Components/NonUniformScaleComponent.cpp FileFunc/FileFunc.h FileFunc/FileFunc.cpp + Font/FontInterface.h Gem/GemInfo.cpp Gem/GemInfo.h StringFunc/StringFunc.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 83632708d9..433602e6d8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -53,7 +53,7 @@ namespace AzToolsFramework float, cl_viewportGizmoAxisLabelOffset, 1.15f, nullptr, AZ::ConsoleFunctorFlags::Null, "The offset of the label for the viewport axis gizmo"); AZ_CVAR( - float, cl_viewportGizmoAxisLabelSize, 2.0f, nullptr, AZ::ConsoleFunctorFlags::Null, + float, cl_viewportGizmoAxisLabelSize, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "The size of each label for the viewport axis gizmo"); AZ_CVAR( AZ::Vector2, cl_viewportGizmoAxisScreenPosition, AZ::Vector2(0.045f, 0.9f), nullptr, @@ -3434,19 +3434,22 @@ namespace AzToolsFramework const auto cameraProjection = AzFramework::CameraProjection(gizmoCameraState); // screen space offset to move the 2d gizmo around - const AZ::Vector3 screenPosition = - (AZ::Vector2ToVector3(cl_viewportGizmoAxisScreenPosition) - AZ::Vector3(0.5f, 0.5f, 0.0f)) * - AZ::Vector2ToVector3(gizmoCameraState.m_viewportSize); + const AZ::Vector2 screenOffset = AZ::Vector2(cl_viewportGizmoAxisScreenPosition) - AZ::Vector2(0.5f, 0.5f); // map from a position in world space (relative to the the gizmo camera near the origin) to a position in // screen space const auto calculateGizmoAxis = - [&cameraView, &cameraProjection, &gizmoCameraState, &screenPosition] - (const AZ::Vector3& position) - { - return AZ::Vector2ToVector3(AzFramework::Vector2FromScreenPoint( - AzFramework::WorldToScreen( - position, cameraView, cameraProjection, gizmoCameraState.m_viewportSize))) + screenPosition; + [&cameraView, &cameraProjection, &screenOffset] + (const AZ::Vector3& axis) + { + auto result = AZ::Vector2( + AzFramework::WorldToScreenNDC( + axis, + cameraView, + cameraProjection) + ); + result.SetY(1.0f - result.GetY()); + return result + screenOffset; }; // get all important axis positions in screen space @@ -3456,31 +3459,31 @@ namespace AzToolsFramework const auto gizmoEndAxisY = calculateGizmoAxis(-AZ::Vector3::CreateAxisY() * lineLength); const auto gizmoEndAxisZ = calculateGizmoAxis(-AZ::Vector3::CreateAxisZ() * lineLength); - const AZ::Vector3 gizmoAxisX = gizmoEndAxisX - gizmoStart; - const AZ::Vector3 gizmoAxisY = gizmoEndAxisY - gizmoStart; - const AZ::Vector3 gizmoAxisZ = gizmoEndAxisZ - gizmoStart; + const AZ::Vector2 gizmoAxisX = gizmoEndAxisX - gizmoStart; + const AZ::Vector2 gizmoAxisY = gizmoEndAxisY - gizmoStart; + const AZ::Vector2 gizmoAxisZ = gizmoEndAxisZ - gizmoStart; // draw the axes of the gizmo debugDisplay.SetLineWidth(cl_viewportGizmoAxisLineWidth); debugDisplay.SetColor(AZ::Colors::Red); - debugDisplay.DrawLine(gizmoStart, gizmoEndAxisX); + debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisX, 1.0f); debugDisplay.SetColor(AZ::Colors::Lime); - debugDisplay.DrawLine(gizmoStart, gizmoEndAxisY); + debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisY, 1.0f); debugDisplay.SetColor(AZ::Colors::Blue); - debugDisplay.DrawLine(gizmoStart, gizmoEndAxisZ); + debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisZ, 1.0f); debugDisplay.SetLineWidth(1.0f); const float labelOffset = cl_viewportGizmoAxisLabelOffset; - const auto labelOffsetX = gizmoStart + gizmoAxisX * labelOffset; - const auto labelOffsetY = gizmoStart + gizmoAxisY * labelOffset; - const auto labelOffsetZ = gizmoStart + gizmoAxisZ * labelOffset; + const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize; + const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize; + const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize; // draw the label of of each axis for the gizmo const float labelSize = cl_viewportGizmoAxisLabelSize; debugDisplay.SetColor(AZ::Colors::White); - debugDisplay.Draw2dTextLabel(labelOffsetX.GetX(), labelOffsetX.GetY(), labelSize, "X", true); - debugDisplay.Draw2dTextLabel(labelOffsetY.GetX(), labelOffsetY.GetY(), labelSize, "Y", true); - debugDisplay.Draw2dTextLabel(labelOffsetZ.GetX(), labelOffsetZ.GetY(), labelSize, "Z", true); + debugDisplay.Draw2dTextLabel(labelXScreenPosition.GetX(), labelXScreenPosition.GetY(), labelSize, "X", true); + debugDisplay.Draw2dTextLabel(labelYScreenPosition.GetX(), labelYScreenPosition.GetY(), labelSize, "Y", true); + debugDisplay.Draw2dTextLabel(labelZScreenPosition.GetX(), labelZScreenPosition.GetY(), labelSize, "Z", true); } void EditorTransformComponentSelection::DisplayViewportSelection2d( diff --git a/Code/Sandbox/Editor/Objects/DisplayContextShared.inl b/Code/Sandbox/Editor/Objects/DisplayContextShared.inl index a4baf1fe89..dd5c248357 100644 --- a/Code/Sandbox/Editor/Objects/DisplayContextShared.inl +++ b/Code/Sandbox/Editor/Objects/DisplayContextShared.inl @@ -1245,28 +1245,6 @@ uint32 DisplayContext::SetState(uint32 state) return old; } -//! Set a new render state flags. -//! @param returns previous render state. -uint32 DisplayContext::SetStateFlag(uint32 state) -{ - uint32 old = m_renderState; - m_renderState |= state; - m_renderState = pRenderAuxGeom->GetRenderFlags().m_renderFlags; - pRenderAuxGeom->SetRenderFlags(m_renderState); - return old; -} - -//! Clear specified flags in render state. -//! @param returns previous render state. -uint32 DisplayContext::ClearStateFlag(uint32 state) -{ - uint32 old = m_renderState; - m_renderState &= ~state; - m_renderState = pRenderAuxGeom->GetRenderFlags().m_renderFlags; - pRenderAuxGeom->SetRenderFlags(m_renderState); - return old; -} - ////////////////////////////////////////////////////////////////////////// void DisplayContext::DepthTestOff() { diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index e5311dbea9..d9e3d9bb8c 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -2777,26 +2777,6 @@ AZ::u32 SandboxIntegrationManager::SetState(AZ::u32 state) return 0; } -AZ::u32 SandboxIntegrationManager::SetStateFlag(AZ::u32 state) -{ - if (m_dc) - { - return m_dc->SetStateFlag(state); - } - - return 0; -} - -AZ::u32 SandboxIntegrationManager::ClearStateFlag(AZ::u32 state) -{ - if (m_dc) - { - return m_dc->ClearStateFlag(state); - } - - return 0; -} - void SandboxIntegrationManager::PushMatrix(const AZ::Transform& tm) { if (m_dc) diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h index e35fb5087a..36767605b2 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h @@ -268,8 +268,6 @@ private: bool SetDrawInFrontMode(bool bOn) override; AZ::u32 GetState() override; AZ::u32 SetState(AZ::u32 state) override; - AZ::u32 SetStateFlag(AZ::u32 state) override; - AZ::u32 ClearStateFlag(AZ::u32 state) override; void PushMatrix(const AZ::Transform& tm) override; void PopMatrix() override; diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h index c5e3c46cd4..c44327a5f2 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h +++ b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h @@ -12,6 +12,7 @@ #pragma once #include +#include namespace AWSClientAuth { @@ -28,74 +29,104 @@ namespace AWSClientAuth OnPasswordGrantMultiFactorConfirmSignInSuccess, OnPasswordGrantMultiFactorConfirmSignInFail, OnDeviceCodeGrantSignInSuccess, OnDeviceCodeGrantSignInFail, OnDeviceCodeGrantConfirmSignInSuccess, OnDeviceCodeGrantConfirmSignInFail, - OnRefreshTokensSuccess, OnRefreshTokensFail, - OnSignOut + OnRefreshTokensSuccess, OnRefreshTokensFail ); void OnPasswordGrantSingleFactorSignInSuccess(const AuthenticationTokens& authenticationToken) override { - Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken); + AZ::TickBus::QueueFunction([authenticationToken, this]() + { + Call(FN_OnPasswordGrantSingleFactorSignInSuccess, authenticationToken); + }); } void OnPasswordGrantSingleFactorSignInFail(const AZStd::string& error) override { - Call(FN_OnPasswordGrantSingleFactorSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnPasswordGrantSingleFactorSignInFail, error); + }); } void OnPasswordGrantMultiFactorSignInSuccess() override { - Call(FN_OnPasswordGrantMultiFactorSignInSuccess); + AZ::TickBus::QueueFunction([this]() + { + Call(FN_OnPasswordGrantMultiFactorSignInSuccess); + }); } void OnPasswordGrantMultiFactorSignInFail(const AZStd::string& error) override { - Call(FN_OnPasswordGrantMultiFactorSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnPasswordGrantMultiFactorSignInFail, error); + }); } void OnPasswordGrantMultiFactorConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override { - Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken); + AZ::TickBus::QueueFunction([authenticationToken, this]() + { + Call(FN_OnPasswordGrantMultiFactorConfirmSignInSuccess, authenticationToken); + }); } void OnPasswordGrantMultiFactorConfirmSignInFail(const AZStd::string& error) override { - Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnPasswordGrantMultiFactorConfirmSignInFail, error); + }); } void OnDeviceCodeGrantSignInSuccess( const AZStd::string& userCode, const AZStd::string& verificationUrl, const int codeExpiresInSeconds) override { - Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds); + AZ::TickBus::QueueFunction([userCode, verificationUrl, codeExpiresInSeconds, this]() + { + Call(FN_OnDeviceCodeGrantSignInSuccess, userCode, verificationUrl, codeExpiresInSeconds); + }); } void OnDeviceCodeGrantSignInFail(const AZStd::string& error) override { - Call(FN_OnDeviceCodeGrantSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnDeviceCodeGrantSignInFail, error); + }); } void OnDeviceCodeGrantConfirmSignInSuccess(const AuthenticationTokens& authenticationToken) override { - Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken); + AZ::TickBus::QueueFunction([authenticationToken, this]() + { + Call(FN_OnDeviceCodeGrantConfirmSignInSuccess, authenticationToken); + }); } void OnDeviceCodeGrantConfirmSignInFail(const AZStd::string& error) override { - Call(FN_OnDeviceCodeGrantConfirmSignInFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnDeviceCodeGrantConfirmSignInFail, error); + }); } void OnRefreshTokensSuccess(const AuthenticationTokens& authenticationToken) override { - Call(FN_OnRefreshTokensSuccess, authenticationToken); + AZ::TickBus::QueueFunction([authenticationToken, this]() + { + Call(FN_OnRefreshTokensSuccess, authenticationToken); + }); } void OnRefreshTokensFail(const AZStd::string& error) override { - Call(FN_OnRefreshTokensFail, error); - } - - void OnSignOut(const ProviderNameEnum& provideName) override - { - Call(FN_OnSignOut, provideName); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnRefreshTokensFail, error); + }); } }; } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderManager.h b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderManager.h index a9a2f2ad6e..a09a96ba5c 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderManager.h +++ b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderManager.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -23,7 +24,8 @@ namespace AWSClientAuth { //! Manages various authentication provider implementations and implements AuthenticationProvider Request bus. class AuthenticationProviderManager - : AuthenticationProviderRequestBus::Handler + : public AuthenticationProviderRequestBus::Handler + , public AuthenticationProviderScriptCanvasRequestBus::Handler { public: AZ_RTTI(AuthenticationProviderManager, "{45813BA5-9A46-4A2A-A923-C79CFBA0E63D}", IAuthenticationProviderRequests); @@ -43,6 +45,22 @@ namespace AWSClientAuth bool IsSignedIn(const ProviderNameEnum& providerName) override; bool SignOut(const ProviderNameEnum& providerName) override; AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) override; + + // AuthenticationProviderScriptCanvasRequest interface + bool Initialize(const AZStd::vector& providerNames, const AZStd::string& settingsRegistryPath) override; + void PasswordGrantSingleFactorSignInAsync( + const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override; + void PasswordGrantMultiFactorSignInAsync( + const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) override; + void PasswordGrantMultiFactorConfirmSignInAsync( + const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) override; + void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) override; + void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) override; + void RefreshTokensAsync(const AZStd::string& providerName) override; + void GetTokensWithRefreshAsync(const AZStd::string& providerName) override; + bool IsSignedIn(const AZStd::string& providerName) override; + bool SignOut(const AZStd::string& providerName) override; + AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) override; virtual AZStd::unique_ptr CreateAuthenticationProviderObject(const ProviderNameEnum& providerName); AZStd::map> m_authenticationProvidersMap; @@ -50,9 +68,9 @@ namespace AWSClientAuth private: bool IsProviderInitialized(const ProviderNameEnum& providerName); void ResetProviders(); + ProviderNameEnum GetProviderNameEnum(AZStd::string name); AZStd::shared_ptr m_settingsRegistry; - }; } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h new file mode 100644 index 0000000000..9ce508b497 --- /dev/null +++ b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h @@ -0,0 +1,103 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include +#include + +namespace AWSClientAuth +{ + //! Abstract class for authentication provider script canvas requests. + //! Private class to allow provide names to be string type instead of an enum as behavior context does not work well with enum's. + class IAuthenticationProviderScriptCanvasRequests + { + public: + AZ_TYPE_INFO(IAuthenticationProviderRequests, "{A8FD915F-9FF2-4BA3-8AA0-8CF7A94A323B}"); + + //! Parse the settings file for required settings for authentication providers. Instantiate and initialize authentication providers + //! @param providerNames List of provider names to instantiate and initialize for Authentication. + //! @param settingsRegistryPath Path for the settings registry file to use to configure providers. + //! @return bool True: if all providers initialized successfully. False: If any provider fails initialization. + virtual bool Initialize(const AZStd::vector& providerNames, const AZStd::string& settingsRegistryPath) = 0; + + //! Checks if user is signed in. + //! If access tokens are available and not expired. + //! @param providerName Provider to check signed in for + //! @return bool True if valid access token available, else False + virtual bool IsSignedIn(const AZStd::string& providerName) = 0; + + //! Get cached tokens from last last successful sign-in for the provider. + //! @param providerName Provider to get authentication tokens + //! @return AuthenticationTokens tokens from successful authentication. + virtual AuthenticationTokens GetAuthenticationTokens(const AZStd::string& providerName) = 0; + + // Below methods have corresponding notifications for success and failures. + + //! Call sign in endpoint for provider password grant flow. + //! @param providerName Provider to call sign in. + //! @param username Username to use to for sign in. + //! @param password Password to use to for sign in. + virtual void PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0; + + //! Call sign in endpoint for provider password grant multi factor authentication flow. + //! @param providerName Provider to call MFA sign in. + //! @param username Username to use for MFA sign in. + //! @param password Password to use for MFA sign in. + virtual void PasswordGrantMultiFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) = 0; + + //! Call confirm endpoint for provider password grant multi factor authentication flow . + //! @param providerName Provider to call MFA confirm sign in. + //! @param username Username to use for MFA confirm. + //! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm. + virtual void PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0; + + //! Call code-pair endpoint for provider device grant flow. + //! @param providerName Provider to call device sign in. + virtual void DeviceCodeGrantSignInAsync(const AZStd::string& providerName) = 0; + + //! Call tokens endpoint for provider device grant flow. + //! @param providerName Provider to call device confirm sign in. + virtual void DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) = 0; + + //! Call refresh endpoint for provider refresh grant flow. + //! @param providerName Provider to call refresh tokens. + virtual void RefreshTokensAsync(const AZStd::string& providerName) = 0; + + //! Call refresh token if token not valid. If token valid, fires corresponding event. + //! @param providerName Provider to get access token for. + //! events: OnRefreshTokensSuccess, OnRefreshTokensFail + virtual void GetTokensWithRefreshAsync(const AZStd::string& providerName) = 0; + + //! Signs user out. + //! Clears all cached tokens. + //! @param providerName Provider to sign out. + //! @return bool True: Successfully sign out. + virtual bool SignOut(const AZStd::string& providerName) = 0; + + ////////////////////////////////////////////////////////////////////////// + }; + + //! Authentication Request bus for different supported providers. + class AuthenticationProviderScriptCanvasRequests + : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + using MutexType = AZ::NullMutex; + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + }; + using AuthenticationProviderScriptCanvasRequestBus = AZ::EBus; + +} // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderTypes.h b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderTypes.h index 1e10e66307..8bd31d6aeb 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderTypes.h +++ b/Gems/AWSClientAuth/Code/Include/Private/Authentication/AuthenticationProviderTypes.h @@ -15,6 +15,14 @@ namespace AWSClientAuth { + constexpr char ProvideNameEnumStringNone[] = "None"; + constexpr char ProvideNameEnumStringAWSCognitoIDP[] = "AWSCognitoIDP"; + constexpr char ProvideNameEnumStringLoginWithAmazon[] = "LoginWithAmazon"; + constexpr char ProvideNameEnumStringGoogle[] = "Google"; + constexpr char ProvideNameEnumStringApple[] = "Apple"; + constexpr char ProvideNameEnumStringFacebook[] = "Facebook"; + constexpr char ProvideNameEnumStringTwitch[] = "Twitch"; + //! Holds Login with Amazon provider serialized settings class LWAProviderSetting { diff --git a/Gems/AWSClientAuth/Code/Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h b/Gems/AWSClientAuth/Code/Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h index f690445c26..e26896fa06 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h +++ b/Gems/AWSClientAuth/Code/Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h @@ -12,6 +12,7 @@ #pragma once #include +#include #include namespace AWSClientAuth @@ -28,12 +29,18 @@ namespace AWSClientAuth void OnRequestAWSCredentialsSuccess(const ClientAuthAWSCredentials& awsCredentials) override { - Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials); + AZ::TickBus::QueueFunction([awsCredentials, this]() + { + Call(FN_OnRequestAWSCredentialsSuccess, awsCredentials); + }); } void OnRequestAWSCredentialsFail(const AZStd::string& error) override { - Call(FN_OnRequestAWSCredentialsFail, error); + AZ::TickBus::QueueFunction([error, this]() + { + Call(FN_OnRequestAWSCredentialsFail, error); + }); } }; } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h b/Gems/AWSClientAuth/Code/Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h index 06f2ae6e58..f5c2ca7ed1 100644 --- a/Gems/AWSClientAuth/Code/Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h +++ b/Gems/AWSClientAuth/Code/Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h @@ -12,6 +12,7 @@ #pragma once #include +#include namespace AWSClientAuth { @@ -32,62 +33,86 @@ namespace AWSClientAuth void OnEmailSignUpSuccess(const AZStd::string& uuid) override { - Call(FN_OnEmailSignUpSuccess, uuid); + AZ::TickBus::QueueFunction([uuid, this]() { + Call(FN_OnEmailSignUpSuccess, uuid); + }); } void OnEmailSignUpFail(const AZStd::string& error) override { - Call(FN_OnEmailSignUpFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnEmailSignUpFail, error); + }); } void OnPhoneSignUpSuccess(const AZStd::string& uuid) override { - Call(FN_OnPhoneSignUpSuccess, uuid); + AZ::TickBus::QueueFunction([uuid, this]() { + Call(FN_OnPhoneSignUpSuccess, uuid); + }); } void OnPhoneSignUpFail(const AZStd::string& error) override { - Call(FN_OnPhoneSignUpFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnPhoneSignUpFail, error); + }); } void OnConfirmSignUpSuccess() override { - Call(FN_OnConfirmSignUpSuccess); + AZ::TickBus::QueueFunction([this]() { + Call(FN_OnConfirmSignUpSuccess); + }); } void OnConfirmSignUpFail(const AZStd::string& error) override { - Call(FN_OnConfirmSignUpFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnConfirmSignUpFail, error); + }); } void OnForgotPasswordSuccess() override { - Call(FN_OnForgotPasswordSuccess); + AZ::TickBus::QueueFunction([this]() { + Call(FN_OnForgotPasswordSuccess); + }); } void OnForgotPasswordFail(const AZStd::string& error) override { - Call(FN_OnForgotPasswordFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnForgotPasswordFail, error); + }); } void OnConfirmForgotPasswordSuccess() override { - Call(FN_OnConfirmForgotPasswordSuccess); + AZ::TickBus::QueueFunction([this]() { + Call(FN_OnConfirmForgotPasswordSuccess); + }); } void OnConfirmForgotPasswordFail(const AZStd::string& error) override { - Call(FN_OnConfirmForgotPasswordFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnConfirmForgotPasswordFail, error); + }); } void OnEnableMFASuccess() override { - Call(FN_OnEnableMFASuccess); + AZ::TickBus::QueueFunction([this]() { + Call(FN_OnEnableMFASuccess); + }); } void OnEnableMFAFail(const AZStd::string& error) override { - Call(FN_OnEnableMFAFail, error); + AZ::TickBus::QueueFunction([error, this]() { + Call(FN_OnEnableMFAFail, error); + }); } }; } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationProviderBus.h b/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationProviderBus.h index 693adf1e65..9e822849bc 100644 --- a/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationProviderBus.h +++ b/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationProviderBus.h @@ -16,7 +16,7 @@ namespace AWSClientAuth { - //@ Abstract class for authentication provider requests. + //! Abstract class for authentication provider requests. class IAuthenticationProviderRequests { public: @@ -35,32 +35,40 @@ namespace AWSClientAuth virtual bool IsSignedIn(const ProviderNameEnum& providerName) = 0; //! Get cached tokens from last last successful sign-in for the provider. + //! @param providerName Provider to get authentication tokens. + //! @return AuthenticationTokens tokens from successful authentication. virtual AuthenticationTokens GetAuthenticationTokens(const ProviderNameEnum& providerName) = 0; // Below methods have corresponding notifications for success and failures. //! Call sign in endpoint for provider password grant flow. + //! @param providerName Provider to call sign in. //! @param username Username to use to for sign in. //! @param password Password to use to for sign in. virtual void PasswordGrantSingleFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0; //! Call sign in endpoint for provider password grant multi factor authentication flow. + //! @param providerName Provider to call MFA sign in. //! @param username Username to use for MFA sign in. //! @param password Password to use for MFA sign in. virtual void PasswordGrantMultiFactorSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& password) = 0; //! Call confirm endpoint for provider password grant multi factor authentication flow . + //! @param providerName Provider to call MFA confirm sign in. //! @param username Username to use for MFA confirm. //! @param confirmationCode Confirmation code (sent to email/text) to use for MFA confirm. virtual void PasswordGrantMultiFactorConfirmSignInAsync(const ProviderNameEnum& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) = 0; //! Call code-pair endpoint for provider device grant flow. + //! @param providerName Provider to call device sign in. virtual void DeviceCodeGrantSignInAsync(const ProviderNameEnum& providerName) = 0; //! Call tokens endpoint for provider device grant flow. + //! @param providerName Provider to call device confirm sign in. virtual void DeviceCodeGrantConfirmSignInAsync(const ProviderNameEnum& providerName) = 0; //! Call refresh endpoint for provider refresh grant flow. + //! @param providerName Provider to call refresh tokens. virtual void RefreshTokensAsync(const ProviderNameEnum& providerName) = 0; //! Call refresh token if token not valid. If token valid, fires corresponding event. diff --git a/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationTokens.h b/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationTokens.h index 80138efd1b..3bb781f262 100644 --- a/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationTokens.h +++ b/Gems/AWSClientAuth/Code/Include/Public/Authentication/AuthenticationTokens.h @@ -11,20 +11,15 @@ */ #pragma once +#include #include #include +#include +#include namespace AWSClientAuth { - enum class ProviderNameEnum - { - None, - AWSCognitoIDP, - LoginWithAmazon, - Google, - Apple, - Facebook - }; + AZ_ENUM_CLASS(ProviderNameEnum, None, AWSCognitoIDP, LoginWithAmazon, Twitch, Google, Apple, Facebook); //! Used to share authentication tokens to caller and to AWSCognitoAuthorizationController. class AuthenticationTokens @@ -55,6 +50,8 @@ namespace AWSClientAuth //! @return Expiration time in seconds. int GetTokensExpireTimeSeconds() const; + static void Reflect(AZ::ReflectContext* context); + private: int m_tokensExpireTimeSeconds = 0; AZStd::string m_accessToken; diff --git a/Gems/AWSClientAuth/Code/Include/Public/Authorization/ClientAuthAWSCredentials.h b/Gems/AWSClientAuth/Code/Include/Public/Authorization/ClientAuthAWSCredentials.h index 71a5703efd..2daac42a49 100644 --- a/Gems/AWSClientAuth/Code/Include/Public/Authorization/ClientAuthAWSCredentials.h +++ b/Gems/AWSClientAuth/Code/Include/Public/Authorization/ClientAuthAWSCredentials.h @@ -12,7 +12,7 @@ #pragma once -#include +#include #include #include @@ -24,6 +24,14 @@ namespace AWSClientAuth { public: AZ_TYPE_INFO(ClientAuthAWSCredentials, "{02FB32C4-B94E-4084-9049-3DF32F87BD76}"); + ClientAuthAWSCredentials() = default; + ClientAuthAWSCredentials(const ClientAuthAWSCredentials& other) + : m_accessKeyId(other.m_accessKeyId) + , m_secretKey(other.m_secretKey) + , m_sessionToken(other.m_sessionToken) + + { + } ClientAuthAWSCredentials(const AZStd::string& accessKeyId, const AZStd::string& secretKey, const AZStd::string& sessionToken) { @@ -50,6 +58,32 @@ namespace AWSClientAuth return m_sessionToken; } + static void Reflect(AZ::ReflectContext* context) + { + auto serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Field("AWSAccessKeyId", &ClientAuthAWSCredentials::m_accessKeyId) + ->Field("AWSSecretKey", &ClientAuthAWSCredentials::m_secretKey) + ->Field("AWSSessionToken", &ClientAuthAWSCredentials::m_sessionToken); + } + + AZ::BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth") + ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value) + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Constructor() + ->Constructor() + ->Property("AWSAccessKeyId", BehaviorValueGetter(&ClientAuthAWSCredentials::m_accessKeyId), BehaviorValueSetter(&ClientAuthAWSCredentials::m_accessKeyId)) + ->Property("AWSSecretKey", BehaviorValueGetter(&ClientAuthAWSCredentials::m_secretKey), BehaviorValueSetter(&ClientAuthAWSCredentials::m_secretKey)) + ->Property("AWSSessionToken", BehaviorValueGetter(&ClientAuthAWSCredentials::m_sessionToken), BehaviorValueSetter(&ClientAuthAWSCredentials::m_sessionToken)); + } + } + private: AZStd::string m_accessKeyId; AZStd::string m_secretKey; diff --git a/Gems/AWSClientAuth/Code/Include/Public/UserManagement/AWSCognitoUserManagementBus.h b/Gems/AWSClientAuth/Code/Include/Public/UserManagement/AWSCognitoUserManagementBus.h index 89ddf0a999..aff68db365 100644 --- a/Gems/AWSClientAuth/Code/Include/Public/UserManagement/AWSCognitoUserManagementBus.h +++ b/Gems/AWSClientAuth/Code/Include/Public/UserManagement/AWSCognitoUserManagementBus.h @@ -22,11 +22,12 @@ namespace AWSClientAuth public: AZ_TYPE_INFO(IAWSCognitoUserManagementRequests, "{A4C90F21-7056-4827-8C6B-401E6945697D}"); - //! Initialize Cognito User pool. + //! Initialize Cognito User pool using settings from resource mappings. //! @param settingsRegistryPath settingsRegistryPath Path for the settings registry file to use. virtual bool Initialize() = 0; // Requests interface + //! Cognito user pool email sign up start. //! @param username User name to use for sign up. //! @param password Password to use for sign up. @@ -59,7 +60,7 @@ namespace AWSClientAuth virtual void EnableMFAAsync(const AZStd::string& accessToken) = 0; }; - //! Manages various authentication provider implementations and implements AuthenticationProvider Request bus. + //! Implements AWS Cognito user pool user management requests. class AWSCognitoUserManagementRequests : public AZ::EBusTraits { diff --git a/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp b/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp index 20efa354cc..008d56da0b 100644 --- a/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp +++ b/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp @@ -22,6 +22,11 @@ #include #include +namespace AZ +{ + AZ_TYPE_INFO_SPECIALIZE(AWSClientAuth::ProviderNameEnum, "{FB34B23A-B249-47A2-B1F1-C05284B50CCC}"); +} + namespace AWSClientAuth { constexpr char SerializeComponentName[] = "AWSClientAuth"; @@ -44,20 +49,35 @@ namespace AWSClientAuth AWSClientAuth::GoogleProviderSetting::Reflect(*serialize); } + AWSClientAuth::AuthenticationTokens::Reflect(context); + AWSClientAuth::ClientAuthAWSCredentials::Reflect(context); + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { - behaviorContext->EBus("AuthenticationProviderRequestBus") + behaviorContext->Enum<(int)ProviderNameEnum::None>("ProviderNameEnum_None") + ->Enum<(int)ProviderNameEnum::AWSCognitoIDP>("ProviderNameEnum_AWSCognitoIDP") + ->Enum<(int)ProviderNameEnum::LoginWithAmazon>("ProviderNameEnum_LoginWithAmazon") + ->Enum<(int)ProviderNameEnum::Google>("ProviderNameEnum_Google"); + + behaviorContext->EBus("AuthenticationProviderRequestBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) - ->Event("Initialize", &AuthenticationProviderRequestBus::Events::Initialize) - ->Event("IsSignedIn", &AuthenticationProviderRequestBus::Events::IsSignedIn) - ->Event("GetAuthenticationTokens", &AuthenticationProviderRequestBus::Events::GetAuthenticationTokens) + ->Event("Initialize", &AuthenticationProviderScriptCanvasRequestBus::Events::Initialize) + ->Event("IsSignedIn", &AuthenticationProviderScriptCanvasRequestBus::Events::IsSignedIn) + ->Event("GetAuthenticationTokens", &AuthenticationProviderScriptCanvasRequestBus::Events::GetAuthenticationTokens) + ->Event( + "PasswordGrantSingleFactorSignInAsync", + &AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantSingleFactorSignInAsync) ->Event( - "PasswordGrantSingleFactorSignInAsync", &AuthenticationProviderRequestBus::Events::PasswordGrantSingleFactorSignInAsync) - ->Event("DeviceCodeGrantSignInAsync", &AuthenticationProviderRequestBus::Events::DeviceCodeGrantSignInAsync) - ->Event("DeviceCodeGrantConfirmSignInAsync", &AuthenticationProviderRequestBus::Events::DeviceCodeGrantConfirmSignInAsync) - ->Event("RefreshTokensAsync", &AuthenticationProviderRequestBus::Events::RefreshTokensAsync) - ->Event("GetTokensWithRefreshAsync", &AuthenticationProviderRequestBus::Events::GetTokensWithRefreshAsync) - ->Event("SignOut", &AuthenticationProviderRequestBus::Events::SignOut); + "PasswordGrantMultiFactorSignInAsync", + &AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantMultiFactorSignInAsync) + ->Event( + "PasswordGrantMultiFactorConfirmSignInAsync", + &AuthenticationProviderScriptCanvasRequestBus::Events::PasswordGrantMultiFactorConfirmSignInAsync) + ->Event("DeviceCodeGrantSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::DeviceCodeGrantSignInAsync) + ->Event("DeviceCodeGrantConfirmSignInAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::DeviceCodeGrantConfirmSignInAsync) + ->Event("RefreshTokensAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::RefreshTokensAsync) + ->Event("GetTokensWithRefreshAsync", &AuthenticationProviderScriptCanvasRequestBus::Events::GetTokensWithRefreshAsync) + ->Event("SignOut", &AuthenticationProviderScriptCanvasRequestBus::Events::SignOut); behaviorContext->EBus("AWSCognitoAuthorizationRequestBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) @@ -77,11 +97,15 @@ namespace AWSClientAuth ->Event("ConfirmForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmForgotPasswordAsync) ->Event("EnableMFAAsync", &AWSCognitoUserManagementRequestBus::Events::EnableMFAAsync); + behaviorContext->EBus("AuthenticationProviderNotificationBus") + ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Handler(); behaviorContext->EBus("AWSCognitoUserManagementNotificationBus") + ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Handler(); behaviorContext->EBus("AWSCognitoAuthorizationNotificationBus") + ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Handler(); } } diff --git a/Gems/AWSClientAuth/Code/Source/Authentication/AWSCognitoAuthenticationProvider.cpp b/Gems/AWSClientAuth/Code/Source/Authentication/AWSCognitoAuthenticationProvider.cpp index eca5ba22c2..74865c0044 100644 --- a/Gems/AWSClientAuth/Code/Source/Authentication/AWSCognitoAuthenticationProvider.cpp +++ b/Gems/AWSClientAuth/Code/Source/Authentication/AWSCognitoAuthenticationProvider.cpp @@ -40,7 +40,7 @@ namespace AWSClientAuth AZ_UNUSED(settingsRegistry); AWSCore::AWSResourceMappingRequestBus::BroadcastResult( m_cognitoAppClientId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoAppClientIdResourceMappingKey); - AZ_Warning("AWSCognitoAuthenticationProvider", m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail."); + AZ_Warning("AWSCognitoAuthenticationProvider", !m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail."); return !m_cognitoAppClientId.empty(); } diff --git a/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationProviderManager.cpp b/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationProviderManager.cpp index 76d7c45c71..f6e5efd106 100644 --- a/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationProviderManager.cpp +++ b/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationProviderManager.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -25,12 +26,14 @@ namespace AWSClientAuth { AZ::Interface::Register(this); AuthenticationProviderRequestBus::Handler::BusConnect(); + AuthenticationProviderScriptCanvasRequestBus::Handler::BusConnect(); } AuthenticationProviderManager::~AuthenticationProviderManager() { ResetProviders(); m_settingsRegistry.reset(); + AuthenticationProviderScriptCanvasRequestBus::Handler::BusDisconnect(); AuthenticationProviderRequestBus::Handler::BusDisconnect(); AZ::Interface::Unregister(this); } @@ -38,12 +41,19 @@ namespace AWSClientAuth bool AuthenticationProviderManager::Initialize(const AZStd::vector& providerNames, const AZStd::string& settingsRegistryPath) { ResetProviders(); + AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIO, "File IO is not initialized."); + m_settingsRegistry.reset(); m_settingsRegistry = AZStd::make_shared(); - if (!m_settingsRegistry->MergeSettingsFile(settingsRegistryPath, AZ::SettingsRegistryInterface::Format::JsonMergePatch)) + AZStd::array resolvedPath{}; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(settingsRegistryPath.data(), resolvedPath.data(), resolvedPath.size()); + + + if (!m_settingsRegistry->MergeSettingsFile(resolvedPath.data(), AZ::SettingsRegistryInterface::Format::JsonMergePatch)) { - AZ_Error("AuthenticationProviderManager", true, "Error merging settings registry for path: %s", settingsRegistryPath.c_str()); + AZ_Error("AuthenticationProviderManager", true, "Error merging settings registry for path: %s", resolvedPath.data()); return false; } @@ -112,6 +122,7 @@ namespace AWSClientAuth { AuthenticationProviderNotificationBus::Broadcast(&AuthenticationProviderNotifications::OnRefreshTokensFail , "Provider is not initialized"); + return; } AuthenticationTokens tokens = m_authenticationProvidersMap[providerName]->GetAuthenticationTokens(); @@ -181,5 +192,77 @@ namespace AWSClientAuth } } + ProviderNameEnum AuthenticationProviderManager::GetProviderNameEnum(AZStd::string name) + { + auto enumValue = ProviderNameEnumNamespace::FromStringToProviderNameEnum(name); + if (enumValue.has_value()) + { + return enumValue.value(); + } + AZ_Warning("AuthenticationProviderManager", true, "Incorrect string value for enum: %s", name.c_str()); + return ProviderNameEnum::None; + } + + bool AuthenticationProviderManager::Initialize( + const AZStd::vector& providerNames, const AZStd::string& settingsRegistryPath) + { + AZStd::vector providerNamesEnum; + for (auto name : providerNames) + { + providerNamesEnum.push_back(GetProviderNameEnum(name)); + } + return Initialize(providerNamesEnum, settingsRegistryPath); + } + + void AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) + { + PasswordGrantSingleFactorSignInAsync(GetProviderNameEnum(providerName), username, password); + } + + void AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& password) + { + PasswordGrantMultiFactorSignInAsync(GetProviderNameEnum(providerName), username, password); + } + + void AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync(const AZStd::string& providerName, const AZStd::string& username, const AZStd::string& confirmationCode) + { + PasswordGrantMultiFactorConfirmSignInAsync(GetProviderNameEnum(providerName), username, confirmationCode); + } + + void AuthenticationProviderManager::DeviceCodeGrantSignInAsync(const AZStd::string& providerName) + { + DeviceCodeGrantSignInAsync(GetProviderNameEnum(providerName)); + } + + void AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync(const AZStd::string& providerName) + { + DeviceCodeGrantConfirmSignInAsync(GetProviderNameEnum(providerName)); + } + + void AuthenticationProviderManager::RefreshTokensAsync(const AZStd::string& providerName) + { + RefreshTokensAsync(GetProviderNameEnum(providerName)); + } + + void AuthenticationProviderManager::GetTokensWithRefreshAsync(const AZStd::string& providerName) + { + GetTokensWithRefreshAsync(GetProviderNameEnum(providerName)); + } + + bool AuthenticationProviderManager::IsSignedIn(const AZStd::string& providerName) + { + return IsSignedIn(GetProviderNameEnum(providerName)); + } + + bool AuthenticationProviderManager::SignOut(const AZStd::string& providerName) + { + return SignOut(GetProviderNameEnum(providerName)); + } + + AuthenticationTokens AuthenticationProviderManager::GetAuthenticationTokens(const AZStd::string& providerName) + { + return GetAuthenticationTokens(GetProviderNameEnum(providerName)); + } + } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationTokens.cpp b/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationTokens.cpp index 9c078ad99c..737d6ae929 100644 --- a/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationTokens.cpp +++ b/Gems/AWSClientAuth/Code/Source/Authentication/AuthenticationTokens.cpp @@ -79,4 +79,30 @@ namespace AWSClientAuth { return m_tokensExpireTimeSeconds; } + + void AuthenticationTokens::Reflect(AZ::ReflectContext* context) + { + auto serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Field("AccessToken", &AuthenticationTokens::m_accessToken) + ->Field("OpenIdToken", &AuthenticationTokens::m_openIdToken) + ->Field("RefreshToken", &AuthenticationTokens::m_refreshToken); + } + + AZ::BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::Category, "AWSClientAuth") + ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value) + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Constructor() + ->Constructor() + ->Property("AccessToken", BehaviorValueGetter(&AuthenticationTokens::m_accessToken), BehaviorValueSetter(&AuthenticationTokens::m_accessToken)) + ->Property("OpenIdToken", BehaviorValueGetter(&AuthenticationTokens::m_openIdToken), BehaviorValueSetter(&AuthenticationTokens::m_accessToken)) + ->Property("RefreshToken", BehaviorValueGetter(&AuthenticationTokens::m_refreshToken), BehaviorValueSetter(&AuthenticationTokens::m_accessToken)); + } + } } // namespace AWSClientAuth diff --git a/Gems/AWSClientAuth/Code/Source/Authorization/AWSCognitoAuthorizationController.cpp b/Gems/AWSClientAuth/Code/Source/Authorization/AWSCognitoAuthorizationController.cpp index 4c10d968fc..5e2c07bdbb 100644 --- a/Gems/AWSClientAuth/Code/Source/Authorization/AWSCognitoAuthorizationController.cpp +++ b/Gems/AWSClientAuth/Code/Source/Authorization/AWSCognitoAuthorizationController.cpp @@ -71,15 +71,15 @@ namespace AWSClientAuth if (m_awsAccountId.empty() || m_cognitoIdentityPoolId.empty()) { - AZ_Warning("AWSCognitoUserManagementController", m_awsAccountId.empty(), "Missing AWS account id in resource mappings."); - AZ_Warning("AWSCognitoUserManagementController", m_cognitoIdentityPoolId.empty(), "Missing Cognito Identity pool id in resource mappings."); + AZ_Warning("AWSCognitoAuthorizationController", !m_awsAccountId.empty(), "Missing AWS account id not configured."); + AZ_Warning("AWSCognitoAuthorizationController", !m_cognitoIdentityPoolId.empty(), "Missing Cognito Identity pool id in resource mappings."); return false; } AZStd::string userPoolId; AWSCore::AWSResourceMappingRequestBus::BroadcastResult( userPoolId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoUserPoolIdResourceMappingKey); - AZ_Warning("AWSCognitoUserManagementController", userPoolId.empty(), "Missing Cognito USer pool id in resource mappings. Cognito IDP authenticated identities will no work."); + AZ_Warning("AWSCognitoAuthorizationController", !userPoolId.empty(), "Missing Cognito User pool id in resource mappings. Cognito IDP authenticated identities will no work."); AZStd::string defaultRegion; AWSCore::AWSResourceMappingRequestBus::BroadcastResult( diff --git a/Gems/AWSClientAuth/Code/Source/UserManagement/AWSCognitoUserManagementController.cpp b/Gems/AWSClientAuth/Code/Source/UserManagement/AWSCognitoUserManagementController.cpp index 19d5d47d33..755b0e1f15 100644 --- a/Gems/AWSClientAuth/Code/Source/UserManagement/AWSCognitoUserManagementController.cpp +++ b/Gems/AWSClientAuth/Code/Source/UserManagement/AWSCognitoUserManagementController.cpp @@ -54,7 +54,7 @@ namespace AWSClientAuth AWSCore::AWSResourceMappingRequestBus::BroadcastResult( m_cognitoAppClientId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoAppClientIdResourceMappingKey); AZ_Warning( - "AWSCognitoUserManagementController", m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail."); + "AWSCognitoUserManagementController", !m_cognitoAppClientId.empty(), "Missing Cognito App Client Id from resource mappings. Calls to Cognito will fail."); return !m_cognitoAppClientId.empty(); } diff --git a/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerMock.h b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerMock.h new file mode 100644 index 0000000000..e7b233c786 --- /dev/null +++ b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerMock.h @@ -0,0 +1,55 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include + +namespace AWSClientAuthUnitTest +{ + class AuthenticationProviderManagerLocalMock + : public AWSClientAuth::AuthenticationProviderManager + { + public: + using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::GetAuthenticationTokens; + using AWSClientAuth::AuthenticationProviderManager::GetTokensWithRefreshAsync; + using AWSClientAuth::AuthenticationProviderManager::Initialize; + using AWSClientAuth::AuthenticationProviderManager::IsSignedIn; + using AWSClientAuth::AuthenticationProviderManager::m_authenticationProvidersMap; + using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync; + using AWSClientAuth::AuthenticationProviderManager::RefreshTokensAsync; + using AWSClientAuth::AuthenticationProviderManager::SignOut; + + AZStd::unique_ptr CreateAuthenticationProviderObjectMock( + const AWSClientAuth::ProviderNameEnum& providerName) + { + auto providerObject = AWSClientAuth::AuthenticationProviderManager::CreateAuthenticationProviderObject(providerName); + providerObject.reset(); + return AZStd::make_unique>(); + } + + AuthenticationProviderManagerLocalMock() + { + ON_CALL(*this, CreateAuthenticationProviderObject(testing::_)) + .WillByDefault(testing::Invoke(this, &AuthenticationProviderManagerLocalMock::CreateAuthenticationProviderObjectMock)); + } + + MOCK_METHOD1( + CreateAuthenticationProviderObject, + AZStd::unique_ptr(const AWSClientAuth::ProviderNameEnum&)); + }; +} // namespace AWSClientAuthUnitTest diff --git a/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp new file mode 100644 index 0000000000..7673840299 --- /dev/null +++ b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp @@ -0,0 +1,261 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class AuthenticationProviderManagerScriptCanvasTest + : public AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture +{ +protected: + void SetUp() override + { + AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::SetUp(); + + AWSClientAuth::LWAProviderSetting::Reflect(*m_serializeContext); + AWSClientAuth::GoogleProviderSetting::Reflect(*m_serializeContext); + + m_settingspath = AZStd::string::format("%s/%s/authenticationProvider.setreg", + m_testFolder->c_str(), AZ::SettingsRegistryInterface::RegistryFolder); + CreateTestFile("authenticationProvider.setreg" + , R"({ + "AWS": + { + "LoginWithAmazon": + { + "AppClientId": "TestLWAClientId", + "GrantType": "device_code", + "Scope": "profile", + "ResponseType": "device_code", + "OAuthCodeURL": "https://api.amazon.com/auth/o2/create/codepair", + "OAuthTokensURL": "https://oauth2.googleapis.com/token" + }, + "Google": + { + "AppClientId": "TestGoogleClientId", + "ClientSecret": "123", + "GrantType": "urn:ietf:params:oauth:grant-type:device_code", + "Scope": "profile", + "OAuthCodeURL": "https://oauth2.googleapis.com/device/code", + "OAuthTokensURL": "https://oauth2.googleapis.com/token" + } + } + })"); + + m_mockController = AZStd::make_unique>(); + } + + void TearDown() override + { + m_mockController.reset(); + AWSClientAuthUnitTest::AWSClientAuthGemAllocatorFixture::TearDown(); + } + +public: + AZStd::unique_ptr> m_mockController; + AZStd::string m_settingspath; + AZStd::vector m_enabledProviderNames { AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, + AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuth::ProvideNameEnumStringGoogle}; +}; + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Success) +{ + ASSERT_TRUE(m_mockController->Initialize(m_enabledProviderNames, m_settingspath)); + ASSERT_TRUE(m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP] != nullptr); +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock *cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + + EXPECT_CALL(*cognitoProviderMock, PasswordGrantSingleFactorSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantSingleFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantSingleFactorSignInAsync_Fail_NonConfiguredProviderError) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + m_mockController->PasswordGrantSingleFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringApple, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock* lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, PasswordGrantMultiFactorSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantMultiFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + + EXPECT_CALL(*lwaProviderMock, PasswordGrantMultiFactorSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantMultiFactorSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, PasswordGrantMultiFactorConfirmSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock *cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock *lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, PasswordGrantMultiFactorConfirmSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantMultiFactorConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + + EXPECT_CALL(*lwaProviderMock, PasswordGrantMultiFactorConfirmSignInAsync(testing::_, testing::_)).Times(1); + m_mockController->PasswordGrantMultiFactorConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon, AWSClientAuthUnitTest::TEST_USERNAME, AWSClientAuthUnitTest::TEST_PASSWORD); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock* lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, DeviceCodeGrantSignInAsync()).Times(1); + m_mockController->DeviceCodeGrantSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + EXPECT_CALL(*lwaProviderMock, DeviceCodeGrantSignInAsync()).Times(1); + m_mockController->DeviceCodeGrantSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon); + + cognitoProviderMock = nullptr; +} + + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, DeviceCodeGrantConfirmSignInAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock* lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, DeviceCodeGrantConfirmSignInAsync()).Times(1); + m_mockController->DeviceCodeGrantConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + EXPECT_CALL(*lwaProviderMock, DeviceCodeGrantConfirmSignInAsync()).Times(1); + m_mockController->DeviceCodeGrantConfirmSignInAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, RefreshTokenAsync_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock *cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + testing::NiceMock *lwaProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::LoginWithAmazon].get(); + + EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(1); + m_mockController->RefreshTokensAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + EXPECT_CALL(*lwaProviderMock, RefreshTokensAsync()).Times(1); + m_mockController->RefreshTokensAsync(AWSClientAuth::ProvideNameEnumStringLoginWithAmazon); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_ValidToken_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + + AWSClientAuth::AuthenticationTokens tokens( + AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, + AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 600); + EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens)); + EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(0); + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(1); + m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_InvalidToken_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + AWSClientAuth::AuthenticationTokens tokens; + EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens)); + EXPECT_CALL(*cognitoProviderMock, RefreshTokensAsync()).Times(1); + m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokensWithRefreshAsync_NotInitializedProvider_Fail) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(0); + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensFail(testing::_)).Times(1); + m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, GetTokens_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + + AWSClientAuth::AuthenticationTokens tokens( + AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, + AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 60); + + EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens)); + m_mockController->GetAuthenticationTokens(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, IsSignedIn_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* cognitoProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::AWSCognitoIDP].get(); + + AWSClientAuth::AuthenticationTokens tokens( + AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, + AWSClientAuth::ProviderNameEnum::AWSCognitoIDP, 60); + EXPECT_CALL(*cognitoProviderMock, GetAuthenticationTokens()).Times(1).WillOnce(testing::Return(tokens)); + m_mockController->IsSignedIn(AWSClientAuth::ProvideNameEnumStringAWSCognitoIDP); + + cognitoProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, SignOut_Success) +{ + m_mockController->Initialize(m_enabledProviderNames, m_settingspath); + testing::NiceMock* googleProviderMock = (testing::NiceMock*)m_mockController->m_authenticationProvidersMap[AWSClientAuth::ProviderNameEnum::Google].get(); + + EXPECT_CALL(*googleProviderMock, SignOut()).Times(1); + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnSignOut(testing::_)).Times(1); + m_mockController->SignOut(AWSClientAuth::ProvideNameEnumStringGoogle); + + googleProviderMock = nullptr; +} + +TEST_F(AuthenticationProviderManagerScriptCanvasTest, Initialize_Fail_InvalidPath) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + ASSERT_FALSE(m_mockController->Initialize(m_enabledProviderNames, "")); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); +} diff --git a/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerTest.cpp b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerTest.cpp index 9e7d189f5d..4b5bdfb841 100644 --- a/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerTest.cpp +++ b/Gems/AWSClientAuth/Code/Tests/Authentication/AuthenticationProviderManagerTest.cpp @@ -10,8 +10,6 @@ * */ -#include -#include #include #include #include @@ -20,42 +18,7 @@ #include #include #include - -namespace AWSClientAuthUnitTest -{ - class AuthenticationProviderManagerLocalMock - : public AWSClientAuth::AuthenticationProviderManager - { - public: - using AWSClientAuth::AuthenticationProviderManager::m_authenticationProvidersMap; - using AWSClientAuth::AuthenticationProviderManager::Initialize; - using AWSClientAuth::AuthenticationProviderManager::PasswordGrantSingleFactorSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::PasswordGrantMultiFactorConfirmSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::DeviceCodeGrantConfirmSignInAsync; - using AWSClientAuth::AuthenticationProviderManager::RefreshTokensAsync; - using AWSClientAuth::AuthenticationProviderManager::GetTokensWithRefreshAsync; - using AWSClientAuth::AuthenticationProviderManager::GetAuthenticationTokens; - using AWSClientAuth::AuthenticationProviderManager::SignOut; - using AWSClientAuth::AuthenticationProviderManager::IsSignedIn; - - AZStd::unique_ptr CreateAuthenticationProviderObjectMock(const AWSClientAuth::ProviderNameEnum& providerName) - { - auto providerObject = AWSClientAuth::AuthenticationProviderManager::CreateAuthenticationProviderObject(providerName); - providerObject.reset(); - return AZStd::make_unique>(); - } - - AuthenticationProviderManagerLocalMock() - { - ON_CALL(*this, CreateAuthenticationProviderObject(testing::_)).WillByDefault( - testing::Invoke(this, &AuthenticationProviderManagerLocalMock::CreateAuthenticationProviderObjectMock)); - } - - MOCK_METHOD1(CreateAuthenticationProviderObject, AZStd::unique_ptr(const AWSClientAuth::ProviderNameEnum&)); - }; -} +#include class AuthenticationProviderManagerTest @@ -239,6 +202,15 @@ TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_InvalidToken cognitoProviderMock = nullptr; } +TEST_F(AuthenticationProviderManagerTest, GetTokensWithRefreshAsync_NotInitializedProvider_Fail) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensSuccess(testing::_)).Times(0); + EXPECT_CALL(m_authenticationProviderNotificationsBusMock, OnRefreshTokensFail(testing::_)).Times(1); + m_mockController->GetTokensWithRefreshAsync(AWSClientAuth::ProviderNameEnum::AWSCognitoIDP); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); +} + TEST_F(AuthenticationProviderManagerTest, GetTokens_Success) { m_mockController->Initialize(m_enabledProviderNames, m_settingspath); diff --git a/Gems/AWSClientAuth/Code/awsclientauth_files.cmake b/Gems/AWSClientAuth/Code/awsclientauth_files.cmake index 79da00076c..7e4734992f 100644 --- a/Gems/AWSClientAuth/Code/awsclientauth_files.cmake +++ b/Gems/AWSClientAuth/Code/awsclientauth_files.cmake @@ -20,6 +20,7 @@ set(FILES Include/Private/AWSClientAuthBus.h Include/Private/AWSClientAuthResourceMappingConstants.h Include/Private/Authentication/AuthenticationProviderTypes.h + Include/Private/Authentication/AuthenticationProviderScriptCanvasBus.h Include/Private/Authentication/AuthenticationProviderManager.h Include/Private/Authentication/AuthenticationNotificationBusBehaviorHandler.h diff --git a/Gems/AWSClientAuth/Code/awsclientauth_test_files.cmake b/Gems/AWSClientAuth/Code/awsclientauth_test_files.cmake index 6d3de7cc54..18aaa697dd 100644 --- a/Gems/AWSClientAuth/Code/awsclientauth_test_files.cmake +++ b/Gems/AWSClientAuth/Code/awsclientauth_test_files.cmake @@ -14,7 +14,9 @@ set(FILES Tests/AWSClientAuthGemTest.cpp Tests/AWSClientAuthSystemComponentTest.cpp + Tests/Authentication/AuthenticationProviderManagerMock.h Tests/Authentication/AuthenticationProviderManagerTest.cpp + Tests/Authentication/AuthenticationProviderManagerScriptCanvasBusTest.cpp Tests/Authentication/AWSCognitoAuthenticationProviderTest.cpp Tests/Authentication/LWAAuthenticationProviderTest.cpp Tests/Authentication/GoogleAuthenticationProviderTest.cpp diff --git a/Gems/AWSClientAuth/cdk/auth/cognito_identity_pool_role.py b/Gems/AWSClientAuth/cdk/auth/cognito_identity_pool_role.py index 0ebef83eba..3a2e413617 100755 --- a/Gems/AWSClientAuth/cdk/auth/cognito_identity_pool_role.py +++ b/Gems/AWSClientAuth/cdk/auth/cognito_identity_pool_role.py @@ -56,8 +56,7 @@ class CognitoIdentityPoolRole: # basic permissions stack_statement = iam.PolicyStatement( actions=[ - 's3:Get*', - 's3:List*' + 's3:ListBuckets' ], effect=iam.Effect.ALLOW, resources=[ diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp index fd4b5b28d1..dc53498c8b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp @@ -289,7 +289,7 @@ namespace AZ void AuxGeomDrawQueue::DrawQuad( float width, float height, - const AZ::Transform& transform, + const AZ::Matrix3x4& transform, const AZ::Color& color, DrawStyle style, DepthTest depthTest, @@ -302,8 +302,8 @@ namespace AZ return; } - Transform noScaleTransform = transform; - noScaleTransform.ExtractScale(); + AZ::Matrix3x4 noScaleTransform = transform; + AZ::Vector3 scale = noScaleTransform.ExtractScale(); ShapeBufferEntry shape; shape.m_shapeType = ShapeType_Quad; @@ -311,9 +311,9 @@ namespace AZ shape.m_depthWrite = ConvertRPIDepthWriteFlag(depthWrite); shape.m_faceCullMode = ConvertRPIFaceCullFlag(faceCull); shape.m_color = color; - shape.m_rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform); + shape.m_rotationMatrix = Matrix3x3::CreateFromMatrix3x4(noScaleTransform); shape.m_position = transform.GetTranslation(); - shape.m_scale = transform.GetScale() * Vector3(width, 1.0f, height); + shape.m_scale = scale * Vector3(width, 1.0f, height); shape.m_pointSize = m_pointSize; shape.m_viewProjOverrideIndex = viewProjOverrideIndex; diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.h b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.h index b959173ed1..53220c031d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.h +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.h @@ -62,7 +62,7 @@ namespace AZ void DrawTriangles(const AuxGeomDynamicIndexedDrawArguments& args, FaceCullMode faceCull = FaceCullMode::None) override; // Fixed shape draws - void DrawQuad(float width, float height, const AZ::Transform& transform, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; + void DrawQuad(float width, float height, const AZ::Matrix3x4& transform, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; void DrawSphere(const AZ::Vector3& center, float radius, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; void DrawDisk(const AZ::Vector3& center, const AZ::Vector3& direction, float radius, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; void DrawCone(const AZ::Vector3& center, const AZ::Vector3& direction, float radius, float height, const AZ::Color& color, DrawStyle style, DepthTest depthTest, DepthWrite depthWrite, FaceCullMode faceCull, int32_t viewProjOverrideIndex) override; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h index afba71a457..0e7f11e46e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/AuxGeom/AuxGeomDraw.h @@ -138,7 +138,7 @@ namespace AZ //! @param depthWrite If depth writing should be enabled //! @param faceCull Which (if any) facing triangles should be culled //! @param viewProjOverrideIndex Which view projection override entry to use, -1 if unused - virtual void DrawQuad(float width, float height, const AZ::Transform& transform, const AZ::Color& color, DrawStyle style = DrawStyle::Shaded, DepthTest depthTest = DepthTest::On, DepthWrite depthWrite = DepthWrite::On, FaceCullMode faceCull = FaceCullMode::Back, int32_t viewProjOverrideIndex = -1) = 0; + virtual void DrawQuad(float width, float height, const AZ::Matrix3x4& transform, const AZ::Color& color, DrawStyle style = DrawStyle::Shaded, DepthTest depthTest = DepthTest::On, DepthWrite depthWrite = DepthWrite::On, FaceCullMode faceCull = FaceCullMode::Back, int32_t viewProjOverrideIndex = -1) = 0; //! Draw a sphere. //! @param center The center of the sphere. diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index ec7aa17151..4cab7b8869 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -15,811 +15,1206 @@ #include #include #include +#include +#include #include #include #include -namespace AZ +#include + +namespace // unnamed namespace to hold copies of Cry AuxGeom state enum's, this is to avoid creating a dependency on IRenderAuxGeom.h { - namespace AtomBridge + // Notes: + // Don't change the xxxShift values, they need to match the values from legacy cry rendering + // This also applies to the individual flags in EAuxGeomPublicRenderflags_*! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + enum EAuxGeomPublicRenderflagBitMasks + { + e_Mode2D3DShift = 31, + e_Mode2D3DMask = 0x1 << e_Mode2D3DShift, + + e_AlphaBlendingShift = 29, + e_AlphaBlendingMask = 0x3 << e_AlphaBlendingShift, + + e_DrawInFrontShift = 28, + e_DrawInFrontMask = 0x1 << e_DrawInFrontShift, + + e_FillModeShift = 26, + e_FillModeMask = 0x3 << e_FillModeShift, + + e_CullModeShift = 24, + e_CullModeMask = 0x3 << e_CullModeShift, + + e_DepthWriteShift = 23, + e_DepthWriteMask = 0x1 << e_DepthWriteShift, + + e_DepthTestShift = 22, + e_DepthTestMask = 0x1 << e_DepthTestShift, + + e_PublicParamsMask = e_Mode2D3DMask | e_AlphaBlendingMask | e_DrawInFrontMask | e_FillModeMask | + e_CullModeMask | e_DepthWriteMask | e_DepthTestMask + }; + + // Notes: + // e_Mode2D renders in normalized [0.. 1] screen space. + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_Mode2D3D + { + e_Mode3D = 0x0 << e_Mode2D3DShift, + e_Mode2D = 0x1 << e_Mode2D3DShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_AlphaBlendMode + { + e_AlphaNone = 0x0 << e_AlphaBlendingShift, + e_AlphaAdditive = 0x1 << e_AlphaBlendingShift, + e_AlphaBlended = 0x2 << e_AlphaBlendingShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_DrawInFrontMode + { + e_DrawInFrontOff = 0x0 << e_DrawInFrontShift, + e_DrawInFrontOn = 0x1 << e_DrawInFrontShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_FillMode + { + e_FillModeSolid = 0x0 << e_FillModeShift, + e_FillModeWireframe = 0x1 << e_FillModeShift, + e_FillModePoint = 0x2 << e_FillModeShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_CullMode { + e_CullModeNone = 0x0 << e_CullModeShift, + e_CullModeFront = 0x1 << e_CullModeShift, + e_CullModeBack = 0x2 << e_CullModeShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_DepthWrite + { + e_DepthWriteOn = 0x0 << e_DepthWriteShift, + e_DepthWriteOff = 0x1 << e_DepthWriteShift, + }; + + // Notes: + // Don't change the xxxShift values blindly as they affect the rendering output + // that is two primitives have to be rendered after 3d primitives, alpha blended + // geometry have to be rendered after opaque ones, etc. + // This also applies to the individual flags in EAuxGeomPublicRenderflagBitMasks! + // Remarks: + // Bits 0 - 22 are currently reserved for prim type and per draw call render parameters (point size, etc.) + // Check RenderAuxGeom.h in ../RenderDll/Common + // See also: + // EAuxGeomPublicRenderflagBitMasks + enum EAuxGeomPublicRenderflags_DepthTest + { + e_DepthTestOn = 0x0 << e_DepthTestShift, + e_DepthTestOff = 0x1 << e_DepthTestShift, + }; +}; + +namespace AZ::AtomBridge +{ - //////////////////////////////////////////////////////////////////////// - SingleColorDynamicSizeLineHelper::SingleColorDynamicSizeLineHelper( - int estimatedNumLineSegments - ) + //////////////////////////////////////////////////////////////////////// + SingleColorDynamicSizeLineHelper::SingleColorDynamicSizeLineHelper( + int estimatedNumLineSegments + ) + { + m_points.reserve(estimatedNumLineSegments * 2); + } + + void SingleColorDynamicSizeLineHelper::AddLineSegment( + const AZ::Vector3& lineStart, + const AZ::Vector3& lineEnd + ) + { + m_points.push_back(lineStart); + m_points.push_back(lineEnd); + } + + void SingleColorDynamicSizeLineHelper::Draw( + AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, + const RenderState& rendState + ) const + { + if (auxGeomDrawPtr && !m_points.empty()) { - m_points.reserve(estimatedNumLineSegments * 2); + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = m_points.data(); + drawArgs.m_vertCount = aznumeric_cast(m_points.size()); + drawArgs.m_colors = &rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = rendState.m_lineWidth; + drawArgs.m_opacityType = rendState.m_opacityType; + drawArgs.m_depthTest = rendState.m_depthTest; + drawArgs.m_depthWrite = rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = rendState.m_viewProjOverrideIndex; + auxGeomDrawPtr->DrawLines( drawArgs ); } + } - void SingleColorDynamicSizeLineHelper::AddLineSegment( - const AZ::Vector3& lineStart, - const AZ::Vector3& lineEnd - ) + void SingleColorDynamicSizeLineHelper::Draw2d( + AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, + const RenderState& rendState + ) const + { + if (auxGeomDrawPtr && !m_points.empty()) { - m_points.push_back(lineStart); - m_points.push_back(lineEnd); + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = m_points.data(); + drawArgs.m_vertCount = aznumeric_cast(m_points.size()); + drawArgs.m_colors = &rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = rendState.m_lineWidth; + drawArgs.m_opacityType = rendState.m_opacityType; + drawArgs.m_depthTest = rendState.m_depthTest; + drawArgs.m_depthWrite = rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = auxGeomDrawPtr->GetOrAdd2DViewProjOverride(); + auxGeomDrawPtr->DrawLines( drawArgs ); } + } + + void SingleColorDynamicSizeLineHelper::Reset() + { + m_points.clear(); + } + //////////////////////////////////////////////////////////////////////// - void SingleColorDynamicSizeLineHelper::Draw( - AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, - const RenderState& rendState - ) const + // Partial implementation of the DebugDisplayRequestBus on Atom. + // Commented out function prototypes are waiting to be implemented. + // work tracked in [ATOM-3459] + AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(AZ::RPI::ViewportContextPtr viewportContextPtr) + { + ResetRenderState(); + m_viewportId = viewportContextPtr->GetId(); + m_defaultInstance = false; + auto setupScene = [this](RPI::ScenePtr scene) { - if (auxGeomDrawPtr && !m_points.empty()) - { - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = m_points.data(); - drawArgs.m_vertCount = aznumeric_cast(m_points.size()); - drawArgs.m_colors = &rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = rendState.m_lineWidth; - drawArgs.m_opacityType = rendState.m_opacityType; - drawArgs.m_depthTest = rendState.m_depthTest; - drawArgs.m_depthWrite = rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = rendState.m_viewProjOverrideIndex; - auxGeomDrawPtr->DrawLines( drawArgs ); - } - } + auto viewportContextManager = AZ::Interface::Get(); + AZ::RPI::ViewportContextPtr viewportContextPtr = viewportContextManager->GetViewportContextById(m_viewportId); + InitInternal(scene.get(), viewportContextPtr); + }; + setupScene(viewportContextPtr->GetRenderScene()); + m_sceneChangeHandler = AZ::RPI::ViewportContext::SceneChangedEvent::Handler(setupScene); + viewportContextPtr->ConnectSceneChangedHandler(m_sceneChangeHandler); + } - void SingleColorDynamicSizeLineHelper::Reset() + AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(uint32_t defaultInstanceAddress) + { + ResetRenderState(); + m_viewportId = defaultInstanceAddress; + m_defaultInstance = true; + RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get(); + InitInternal(scene, nullptr); + } + + void AtomDebugDisplayViewportInterface::InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr) + { + AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); + if (!scene) { - m_points.clear(); + m_auxGeomPtr = nullptr; + return; } - //////////////////////////////////////////////////////////////////////// - - // Partial implementation of the DebugDisplayRequestBus on Atom. - // Commented out function prototypes are waiting to be implemented. - // work tracked in [ATOM-3459] - AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(AZ::RPI::ViewportContextPtr viewportContextPtr) + auto auxGeomFP = scene->GetFeatureProcessor(); + if (!auxGeomFP) { - ResetRenderState(); - m_viewportId = viewportContextPtr->GetId(); - m_defaultInstance = false; - auto setupScene = [this](RPI::ScenePtr scene) - { - auto viewportContextManager = AZ::Interface::Get(); - AZ::RPI::ViewportContextPtr viewportContextPtr = viewportContextManager->GetViewportContextById(m_viewportId); - InitInternal(scene.get(), viewportContextPtr); - }; - setupScene(viewportContextPtr->GetRenderScene()); - m_sceneChangeHandler = AZ::RPI::ViewportContext::SceneChangedEvent::Handler(setupScene); - viewportContextPtr->ConnectSceneChangedHandler(m_sceneChangeHandler); + m_auxGeomPtr = nullptr; + return; } - - AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(uint32_t defaultInstanceAddress) + if (m_defaultInstance) { - ResetRenderState(); - m_viewportId = defaultInstanceAddress; - m_defaultInstance = true; - RPI::Scene* scene = RPI::RPISystemInterface::Get()->GetDefaultScene().get(); - InitInternal(scene, nullptr); + m_auxGeomPtr = auxGeomFP->GetDrawQueue(); } + else + { + m_auxGeomPtr = auxGeomFP->GetOrCreateDrawQueueForView(viewportContextPtr->GetDefaultView().get()); + } + AzFramework::DebugDisplayRequestBus::Handler::BusConnect(m_viewportId); + } - void AtomDebugDisplayViewportInterface::InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr) + AtomDebugDisplayViewportInterface::~AtomDebugDisplayViewportInterface() + { + AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); + m_viewportId = AzFramework::InvalidViewportId; + m_auxGeomPtr = nullptr; + } + + void AtomDebugDisplayViewportInterface::ResetRenderState() + { + m_rendState = RenderState(); + for (int index = 0; index < RenderState::TransformStackSize; ++index) { - AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); - if (!scene) - { - m_auxGeomPtr = nullptr; - return; - } - auto auxGeomFP = scene->GetFeatureProcessor(); - if (!auxGeomFP) - { - m_auxGeomPtr = nullptr; - return; - } - if (m_defaultInstance) - { - m_auxGeomPtr = auxGeomFP->GetDrawQueue(); - } - else - { - m_auxGeomPtr = auxGeomFP->GetOrCreateDrawQueueForView(viewportContextPtr->GetDefaultView().get()); - } - AzFramework::DebugDisplayRequestBus::Handler::BusConnect(m_viewportId); + m_rendState.m_transformStack[index] = AZ::Matrix3x4::Identity(); } + } + + void AtomDebugDisplayViewportInterface::SetColor(float r, float g, float b, float a) + { + m_rendState.m_color = AZ::Color(r, g, b, a); + } - AtomDebugDisplayViewportInterface::~AtomDebugDisplayViewportInterface() + void AtomDebugDisplayViewportInterface::SetColor(const AZ::Color& color) + { + m_rendState.m_color = color; + } + + void AtomDebugDisplayViewportInterface::SetColor(const AZ::Vector4& color) + { + m_rendState.m_color = AZ::Color(color); + } + + void AtomDebugDisplayViewportInterface::SetAlpha(float a) + { + m_rendState.m_color.SetA(a); + if (a < 1.0f) { - AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); - m_viewportId = AzFramework::InvalidViewportId; - m_auxGeomPtr = nullptr; + m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque; } + else + { + m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Translucent; + } + } - void AtomDebugDisplayViewportInterface::ResetRenderState() + void AtomDebugDisplayViewportInterface::DrawQuad( + const AZ::Vector3& p1, + const AZ::Vector3& p2, + const AZ::Vector3& p3, + const AZ::Vector3& p4) + { + if (m_auxGeomPtr) { - m_rendState = RenderState(); - for (int index = 0; index < RenderState::TransformStackSize; ++index) - { - m_rendState.m_transformStack[index] = AZ::Matrix3x4::Identity(); - } + AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; + AZ::Vector3 triangles[6]; + triangles[0] = wsPoints[0]; + triangles[1] = wsPoints[1]; + triangles[2] = wsPoints[2]; + triangles[3] = wsPoints[2]; + triangles[4] = wsPoints[3]; + triangles[5] = wsPoints[0]; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = triangles; + drawArgs.m_vertCount = 6; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); } + } - void AtomDebugDisplayViewportInterface::SetColor(float r, float g, float b, float a) + void AtomDebugDisplayViewportInterface::DrawQuad(float width, float height) + { + if (!m_auxGeomPtr || width <= 0.0f || height <= 0.0f) { - m_rendState.m_color = AZ::Color(r, g, b, a); + return; } - void AtomDebugDisplayViewportInterface::SetColor(const AZ::Color& color) + m_auxGeomPtr->DrawQuad( + width, + height, + GetCurrentTransform(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex); + } + + void AtomDebugDisplayViewportInterface::DrawWireQuad( + const AZ::Vector3& p1, + const AZ::Vector3& p2, + const AZ::Vector3& p3, + const AZ::Vector3& p4) + { + if (m_auxGeomPtr) { - m_rendState.m_color = color; + AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = wsPoints; + drawArgs.m_vertCount = 4; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawPolylines(drawArgs, AZ::RPI::AuxGeomDraw::PolylineEnd::Closed); } + } - void AtomDebugDisplayViewportInterface::SetColor(const AZ::Vector4& color) + void AtomDebugDisplayViewportInterface::DrawWireQuad(float width, float height) + { + if (!m_auxGeomPtr || width <= 0.0f || height <= 0.0f) { - m_rendState.m_color = AZ::Color(color); + return; } - void AtomDebugDisplayViewportInterface::SetAlpha(float a) + m_auxGeomPtr->DrawQuad( + width, + height, + GetCurrentTransform(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Line, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex); + } + + void AtomDebugDisplayViewportInterface::DrawQuadGradient( + const AZ::Vector3& p1, + const AZ::Vector3& p2, + const AZ::Vector3& p3, + const AZ::Vector3& p4, + const AZ::Vector4& firstColor, + const AZ::Vector4& secondColor) + { + if (m_auxGeomPtr) { - m_rendState.m_color.SetA(a); - if (a < 1.0f) - { - m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque; - } - else - { - m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Translucent; - } + AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; + AZ::Vector3 triangles[6]; + AZ::Color colors[6]; + triangles[0] = wsPoints[0]; colors[0] = firstColor; + triangles[1] = wsPoints[1]; colors[1] = firstColor; + triangles[2] = wsPoints[2]; colors[2] = secondColor; + triangles[3] = wsPoints[2]; colors[3] = secondColor; + triangles[4] = wsPoints[3]; colors[4] = secondColor; + triangles[5] = wsPoints[0]; colors[5] = firstColor; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = triangles; + drawArgs.m_vertCount = 6; + drawArgs.m_colors = colors; + drawArgs.m_colorCount = 6; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); } + } - void AtomDebugDisplayViewportInterface::DrawQuad( - const AZ::Vector3& p1, - const AZ::Vector3& p2, - const AZ::Vector3& p3, - const AZ::Vector3& p4) + void AtomDebugDisplayViewportInterface::DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; - AZ::Vector3 triangles[6]; - triangles[0] = wsPoints[0]; - triangles[1] = wsPoints[1]; - triangles[2] = wsPoints[2]; - triangles[3] = wsPoints[2]; - triangles[4] = wsPoints[3]; - triangles[5] = wsPoints[0]; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = triangles; - drawArgs.m_vertCount = 6; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } + AZ::Vector3 verts[3] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3)}; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = verts; + drawArgs.m_vertCount = 3; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); } + } - // void DrawQuad(float width, float height) override - // void DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override; - // void DrawWireQuad(float width, float height) override; + void AtomDebugDisplayViewportInterface::DrawTriangles(const AZStd::vector& vertices, const AZ::Color& color) + { + if (m_auxGeomPtr) + { + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = vertices.data(); + drawArgs.m_vertCount = aznumeric_cast(vertices.size()); + drawArgs.m_colors = &color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); + } + } - void AtomDebugDisplayViewportInterface::DrawQuadGradient( - const AZ::Vector3& p1, - const AZ::Vector3& p2, - const AZ::Vector3& p3, - const AZ::Vector3& p4, - const AZ::Vector4& firstColor, - const AZ::Vector4& secondColor) + void AtomDebugDisplayViewportInterface::DrawTrianglesIndexed( + const AZStd::vector& vertices, + const AZStd::vector& indices, + const AZ::Color& color) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZ::Vector3 wsPoints[4] = { ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3), ToWorldSpacePosition(p4) }; - AZ::Vector3 triangles[6]; - AZ::Color colors[6]; - triangles[0] = wsPoints[0]; colors[0] = firstColor; - triangles[1] = wsPoints[1]; colors[1] = firstColor; - triangles[2] = wsPoints[2]; colors[2] = secondColor; - triangles[3] = wsPoints[2]; colors[3] = secondColor; - triangles[4] = wsPoints[3]; colors[4] = secondColor; - triangles[5] = wsPoints[0]; colors[5] = firstColor; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = triangles; - drawArgs.m_vertCount = 6; - drawArgs.m_colors = colors; - drawArgs.m_colorCount = 6; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } + AZ::RPI::AuxGeomDraw::AuxGeomDynamicIndexedDrawArguments drawArgs; + drawArgs.m_verts = vertices.data(); + drawArgs.m_vertCount = aznumeric_cast(vertices.size()); + drawArgs.m_indices = indices.data(); + drawArgs.m_indexCount = aznumeric_cast(indices.size()); + drawArgs.m_colors = &color; + drawArgs.m_colorCount = 1; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawTriangles(drawArgs); } + } - void AtomDebugDisplayViewportInterface::DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3) + void AtomDebugDisplayViewportInterface::DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZ::Vector3 verts[3] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2), ToWorldSpacePosition(p3)}; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = verts; - drawArgs.m_vertCount = 3; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } + m_auxGeomPtr->DrawAabb( + AZ::Aabb::CreateFromMinMax(min, max), + GetCurrentTransform(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Line, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); } + } - void AtomDebugDisplayViewportInterface::DrawTriangles(const AZStd::vector& vertices, const AZ::Color& color) + void AtomDebugDisplayViewportInterface::DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = vertices.data(); - drawArgs.m_vertCount = aznumeric_cast(vertices.size()); - drawArgs.m_colors = &color; - drawArgs.m_colorCount = 1; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } + m_auxGeomPtr->DrawAabb( + AZ::Aabb::CreateFromMinMax(min, max), + GetCurrentTransform(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Solid, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex); } + } - void AtomDebugDisplayViewportInterface::DrawTrianglesIndexed( - const AZStd::vector& vertices, - const AZStd::vector& indices, - const AZ::Color& color) + void AtomDebugDisplayViewportInterface::DrawSolidOBB( + const AZ::Vector3& center, + const AZ::Vector3& axisX, + const AZ::Vector3& axisY, + const AZ::Vector3& axisZ, + const AZ::Vector3& halfExtents) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZ::RPI::AuxGeomDraw::AuxGeomDynamicIndexedDrawArguments drawArgs; - drawArgs.m_verts = vertices.data(); - drawArgs.m_vertCount = aznumeric_cast(vertices.size()); - drawArgs.m_indices = indices.data(); - drawArgs.m_indexCount = aznumeric_cast(indices.size()); - drawArgs.m_colors = &color; - drawArgs.m_colorCount = 1; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawTriangles(drawArgs); - } + AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x3(AZ::Matrix3x3::CreateFromColumns(axisX, axisY, axisZ)); + AZ::Obb obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(center, rotation, halfExtents); + m_auxGeomPtr->DrawObb( + obb, + AZ::Vector3::CreateZero(), + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Solid, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex); } + } - void AtomDebugDisplayViewportInterface::DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) + void AtomDebugDisplayViewportInterface::DrawPoint(const AZ::Vector3& p, int nSize) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - m_auxGeomPtr->DrawAabb( - AZ::Aabb::CreateFromMinMax(min, max), - GetCurrentTransform(), - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Line, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } + AZ::Vector3 wsPoint = ToWorldSpacePosition(p); + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = &wsPoint; + drawArgs.m_vertCount = 1; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = aznumeric_cast(nSize); + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawPoints(drawArgs); } + } - void AtomDebugDisplayViewportInterface::DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max) + void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - m_auxGeomPtr->DrawAabb( - AZ::Aabb::CreateFromMinMax(min, max), - GetCurrentTransform(), - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Solid, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex); - } + AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)}; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = verts; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawLines(drawArgs); } + } - void AtomDebugDisplayViewportInterface::DrawSolidOBB( - const AZ::Vector3& center, - const AZ::Vector3& axisX, - const AZ::Vector3& axisY, - const AZ::Vector3& axisZ, - const AZ::Vector3& halfExtents) + void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x3(AZ::Matrix3x3::CreateFromColumns(axisX, axisY, axisZ)); - AZ::Obb obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(center, rotation, halfExtents); - m_auxGeomPtr->DrawObb( - obb, - AZ::Vector3::CreateZero(), - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Solid, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex); - } + AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)}; + AZ::Color colors[2] = {col1, col2}; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = verts; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = colors; + drawArgs.m_colorCount = 2; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawLines(drawArgs); } + } - void AtomDebugDisplayViewportInterface::DrawPoint(const AZ::Vector3& p, int nSize) + void AtomDebugDisplayViewportInterface::DrawLines(const AZStd::vector& lines, const AZ::Color& color) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZ::Vector3 wsPoint = ToWorldSpacePosition(p); - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = &wsPoint; - drawArgs.m_vertCount = 1; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = aznumeric_cast(nSize); - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawPoints(drawArgs); - } + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = lines.data(); + drawArgs.m_vertCount = aznumeric_cast(lines.size()); + drawArgs.m_colors = &color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawLines(drawArgs); } + } - void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2) + void AtomDebugDisplayViewportInterface::DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) + AZStd::vector wsPoints(static_cast(numPoints)); + for (int index = 0; index < numPoints; ++index) { - AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)}; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = verts; - drawArgs.m_vertCount = 2; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawLines(drawArgs); + wsPoints[index] = ToWorldSpacePosition(pnts[index]); } + AZ::RPI::AuxGeomDraw::PolylineEnd polylineEnd = cycled ? AZ::RPI::AuxGeomDraw::PolylineEnd::Closed : AZ::RPI::AuxGeomDraw::PolylineEnd::Open; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = wsPoints.data(); + drawArgs.m_vertCount = aznumeric_cast(numPoints); + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + m_auxGeomPtr->DrawPolylines(drawArgs, polylineEnd); } + } - void AtomDebugDisplayViewportInterface::DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2) + void AtomDebugDisplayViewportInterface::DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZ::Vector3 verts[2] = {ToWorldSpacePosition(p1), ToWorldSpacePosition(p2)}; - AZ::Color colors[2] = {col1, col2}; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = verts; - drawArgs.m_vertCount = 2; - drawArgs.m_colors = colors; - drawArgs.m_colorCount = 2; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawLines(drawArgs); - } + AZ::Vector3 points[4]; + points[0] = AZ::Vector3(p1.GetX(), p1.GetY(), z); + points[1] = AZ::Vector3(p2.GetX(), p1.GetY(), z); + points[2] = AZ::Vector3(p2.GetX(), p2.GetY(), z); + points[3] = AZ::Vector3(p1.GetX(), p2.GetY(), z); + + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = points; + drawArgs.m_vertCount = 4; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride(); + m_auxGeomPtr->DrawPolylines(drawArgs, AZ::RPI::AuxGeomDraw::PolylineEnd::Closed); } + } - void AtomDebugDisplayViewportInterface::DrawLines(const AZStd::vector& lines, const AZ::Color& color) + void AtomDebugDisplayViewportInterface::DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = lines.data(); - drawArgs.m_vertCount = aznumeric_cast(lines.size()); - drawArgs.m_colors = &color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawLines(drawArgs); - } + AZ::Vector3 points[2]; + points[0] = AZ::Vector3(p1.GetX(), p1.GetY(), z); + points[1] = AZ::Vector3(p2.GetX(), p2.GetY(), z); + + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = points; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride(); + m_auxGeomPtr->DrawLines(drawArgs); } + } - void AtomDebugDisplayViewportInterface::DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled) + void AtomDebugDisplayViewportInterface::DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - AZStd::vector wsPoints(static_cast(numPoints)); - for (int index = 0; index < numPoints; ++index) - { - wsPoints[index] = ToWorldSpacePosition(pnts[index]); - } - AZ::RPI::AuxGeomDraw::PolylineEnd polylineEnd = cycled ? AZ::RPI::AuxGeomDraw::PolylineEnd::Closed : AZ::RPI::AuxGeomDraw::PolylineEnd::Open; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = wsPoints.data(); - drawArgs.m_vertCount = aznumeric_cast(numPoints); - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - m_auxGeomPtr->DrawPolylines(drawArgs, polylineEnd); - } + AZ::Vector3 points[2]; + points[0] = AZ::Vector3(p1.GetX(), p1.GetY(), z); + points[1] = AZ::Vector3(p2.GetX(), p2.GetY(), z); + AZ::Color colors[2] = {firstColor, secondColor}; + + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = points; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = colors; + drawArgs.m_colorCount = 2; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride(); + m_auxGeomPtr->DrawLines(drawArgs); } + } - // void AtomDebugDisplayViewportInterface::DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; - // void AtomDebugDisplayViewportInterface::DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; - // void AtomDebugDisplayViewportInterface::DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override; - // void AtomDebugDisplayViewportInterface::DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) override; + void AtomDebugDisplayViewportInterface::DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) + { + if (m_auxGeomPtr) + { + // Draw axis aligned arc + constexpr float angularStepDegrees = 10.0f; + constexpr float startAngleDegrees = 0.0f; + constexpr float sweepAngleDegrees = 360.0f; + const float stepAngle = DegToRad(angularStepDegrees); + const float startAngle = DegToRad(startAngleDegrees); + const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; + SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + AZ::Vector3 pos = AZ::Vector3(center.GetX(), center.GetY(), z); + CreateAxisAlignedArc( + lines, + stepAngle, + startAngle, + stopAngle, + pos, + radiusV3, + CircleAxis::CircleAxisZ + ); + lines.Draw2d(m_auxGeomPtr, m_rendState); + } + } - void AtomDebugDisplayViewportInterface::DrawArc( - const AZ::Vector3& pos, - float radius, - float startAngleDegrees, - float sweepAngleDegrees, - float angularStepDegrees, - int referenceAxis) + void AtomDebugDisplayViewportInterface::DrawArc( + const AZ::Vector3& pos, + float radius, + float startAngleDegrees, + float sweepAngleDegrees, + float angularStepDegrees, + int referenceAxis) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - // Draw axis aligned arc - const float stepAngle = DegToRad(angularStepDegrees); - const float startAngle = DegToRad(startAngleDegrees); - const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; - SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - CreateAxisAlignedArc( - lines, - stepAngle, - startAngle, - stopAngle, - pos, - radiusV3, - static_cast(referenceAxis) - ); - lines.Draw(m_auxGeomPtr, m_rendState); - } + // Draw axis aligned arc + const float stepAngle = DegToRad(angularStepDegrees); + const float startAngle = DegToRad(startAngleDegrees); + const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; + SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + CreateAxisAlignedArc( + lines, + stepAngle, + startAngle, + stopAngle, + pos, + radiusV3, + static_cast(referenceAxis) + ); + lines.Draw(m_auxGeomPtr, m_rendState); } + } - void AtomDebugDisplayViewportInterface::DrawArc( - const AZ::Vector3& pos, - float radius, - float startAngleDegrees, - float sweepAngleDegrees, - float angularStepDegrees, - const AZ::Vector3& fixedAxis) + void AtomDebugDisplayViewportInterface::DrawArc( + const AZ::Vector3& pos, + float radius, + float startAngleDegrees, + float sweepAngleDegrees, + float angularStepDegrees, + const AZ::Vector3& fixedAxis) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - // Draw arbitraty axis arc - const float stepAngle = DegToRad(angularStepDegrees); - const float startAngle = DegToRad(startAngleDegrees); - const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; - SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - CreateArbitraryAxisArc( - lines, - stepAngle, - startAngle, - stopAngle, - pos, - radiusV3, - fixedAxis - ); - lines.Draw(m_auxGeomPtr, m_rendState); - } + // Draw arbitraty axis arc + const float stepAngle = DegToRad(angularStepDegrees); + const float startAngle = DegToRad(startAngleDegrees); + const float stopAngle = DegToRad(sweepAngleDegrees) + startAngle; + SingleColorDynamicSizeLineHelper lines(1+static_cast(sweepAngleDegrees/angularStepDegrees)); + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + CreateArbitraryAxisArc( + lines, + stepAngle, + startAngle, + stopAngle, + pos, + radiusV3, + fixedAxis + ); + lines.Draw(m_auxGeomPtr, m_rendState); } - - void AtomDebugDisplayViewportInterface::DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis) + } + + void AtomDebugDisplayViewportInterface::DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - // Draw circle with default radius. - const float step = DegToRad(10.0f); - const float maxAngle = DegToRad(360.0f) + step; - SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr. - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - CreateAxisAlignedArc( - lines, - step, - 0.0f, - maxAngle, - pos, - radiusV3, - static_cast(nUnchangedAxis)); - lines.Draw(m_auxGeomPtr, m_rendState); - } + // Draw circle with default radius. + const float step = DegToRad(10.0f); + const float maxAngle = DegToRad(360.0f) + step; + SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr. + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + CreateAxisAlignedArc( + lines, + step, + 0.0f, + maxAngle, + pos, + radiusV3, + static_cast(nUnchangedAxis)); + lines.Draw(m_auxGeomPtr, m_rendState); } + } - void AtomDebugDisplayViewportInterface::DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis) + void AtomDebugDisplayViewportInterface::DrawHalfDottedCircle(const AZ::Vector3& pos, float radius, const AZ::Vector3& viewPos, int nUnchangedAxis) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - // Draw circle with single radius. - const float step = DegToRad(10.0f); - const float maxAngle = DegToRad(360.0f) + step; - SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr. - - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); - const AZ::Vector3 worldView = ToWorldSpacePosition(viewPos); - const AZ::Vector3 worldDir = worldView - worldPos; - - CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, radiusV3, static_cast(nUnchangedAxis%CircleAxisMax), - [&worldPos, &worldDir](const AZ::Vector3& lineStart, const AZ::Vector3& lineEnd, int segmentIndex) + // Draw circle with single radius. + const float step = DegToRad(10.0f); + const float maxAngle = DegToRad(360.0f) + step; + SingleColorStaticSizeLineHelper<40> lines; // hard code 40 lines until DegToRad is constexpr. + + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); + const AZ::Vector3 worldView = ToWorldSpacePosition(viewPos); + const AZ::Vector3 worldDir = worldView - worldPos; + + CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, radiusV3, static_cast(nUnchangedAxis%CircleAxisMax), + [&worldPos, &worldDir](const AZ::Vector3& lineStart, const AZ::Vector3& lineEnd, int segmentIndex) + { + AZ_UNUSED(lineEnd); + const float dot = (lineStart - worldPos).Dot(worldDir); + const bool facing = dot > 0.0f; + // if so skip every other line to produce a dotted effect + if (facing || segmentIndex % 2 == 0) { - AZ_UNUSED(lineEnd); - const float dot = (lineStart - worldPos).Dot(worldDir); - const bool facing = dot > 0.0f; - // if so skip every other line to produce a dotted effect - if (facing || segmentIndex % 2 == 0) - { - return true; - } - return false; - }); - lines.Draw(m_auxGeomPtr, m_rendState); - } + return true; + } + return false; + }); + lines.Draw(m_auxGeomPtr, m_rendState); } + } - void AtomDebugDisplayViewportInterface::DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded) + void AtomDebugDisplayViewportInterface::DrawCone(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius, float height, bool drawShaded) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); - const AZ::Vector3 worldDir = ToWorldSpaceVector(dir); - m_auxGeomPtr->DrawCone( - worldPos, - worldDir, - radius, - height, - m_rendState.m_color, - drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } + const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); + const AZ::Vector3 worldDir = ToWorldSpaceVector(dir); + m_auxGeomPtr->DrawCone( + worldPos, + worldDir, + radius, + height, + m_rendState.m_color, + drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); } - - void AtomDebugDisplayViewportInterface::DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) + } + + void AtomDebugDisplayViewportInterface::DrawWireCylinder(const AZ::Vector3& center, const AZ::Vector3& axis, float radius, float height) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - const AZ::Vector3 worldCenter = ToWorldSpacePosition(center); - const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis); - m_auxGeomPtr->DrawCylinder( - worldCenter, - worldAxis, - radius, - height, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Line, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } + const AZ::Vector3 worldCenter = ToWorldSpacePosition(center); + const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis); + m_auxGeomPtr->DrawCylinder( + worldCenter, + worldAxis, + radius, + height, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Line, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); } + } - void AtomDebugDisplayViewportInterface::DrawSolidCylinder( - const AZ::Vector3& center, - const AZ::Vector3& axis, - float radius, - float height, - bool drawShaded) + void AtomDebugDisplayViewportInterface::DrawSolidCylinder( + const AZ::Vector3& center, + const AZ::Vector3& axis, + float radius, + float height, + bool drawShaded) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - const AZ::Vector3 worldCenter = ToWorldSpacePosition(center); - const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis); - m_auxGeomPtr->DrawCylinder( - worldCenter, - worldAxis, - radius, - height, - m_rendState.m_color, - drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } + const AZ::Vector3 worldCenter = ToWorldSpacePosition(center); + const AZ::Vector3 worldAxis = ToWorldSpaceVector(axis); + m_auxGeomPtr->DrawCylinder( + worldCenter, + worldAxis, + radius, + height, + m_rendState.m_color, + drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); } + } - void AtomDebugDisplayViewportInterface::DrawWireCapsule( - const AZ::Vector3& center, - const AZ::Vector3& axis, - float radius, - float heightStraightSection) + void AtomDebugDisplayViewportInterface::DrawWireCapsule( + const AZ::Vector3& center, + const AZ::Vector3& axis, + float radius, + float heightStraightSection) + { + if (m_auxGeomPtr && radius > FLT_EPSILON && axis.GetLengthSq() > FLT_EPSILON) { - if (m_auxGeomPtr && radius > FLT_EPSILON && axis.GetLengthSq() > FLT_EPSILON) - { - AZ::Vector3 axisNormalized = axis.GetNormalizedEstimate(); - SingleColorStaticSizeLineHelper<(16+1) * 5> lines; // 360/22.5 = 16, 5 possible calls to CreateArbitraryAxisArc - AZ::Vector3 radiusV3 = AZ::Vector3(radius); - float stepAngle = DegToRad(22.5f); - float Deg0 = DegToRad(0.0f); - - - // Draw cylinder part (or just a circle around the middle) - if (heightStraightSection > FLT_EPSILON) - { - DrawWireCylinder(center, axis, radius, heightStraightSection); - } - else - { - float Deg360 = DegToRad(360.0f); - CreateArbitraryAxisArc( - lines, - stepAngle, - Deg0, - Deg360, - center, - radiusV3, - axisNormalized - ); - } - - float Deg90 = DegToRad(90.0f); - float Deg180 = DegToRad(180.0f); - - AZ::Vector3 ortho1Normalized, ortho2Normalized; - CalcBasisVectors(axisNormalized, ortho1Normalized, ortho2Normalized); - AZ::Vector3 centerToTopCircleCenter = axisNormalized * heightStraightSection * 0.5f; - AZ::Vector3 topCenter = center + centerToTopCircleCenter; - AZ::Vector3 bottomCenter = center - centerToTopCircleCenter; - - // Draw top cap as two criss-crossing 180deg arcs - CreateArbitraryAxisArc( - lines, - stepAngle, - Deg90, - Deg90 + Deg180, - topCenter, - radiusV3, - ortho1Normalized - ); + AZ::Vector3 axisNormalized = axis.GetNormalizedEstimate(); + SingleColorStaticSizeLineHelper<(16+1) * 5> lines; // 360/22.5 = 16, 5 possible calls to CreateArbitraryAxisArc + AZ::Vector3 radiusV3 = AZ::Vector3(radius); + float stepAngle = DegToRad(22.5f); + float Deg0 = DegToRad(0.0f); - CreateArbitraryAxisArc( - lines, - stepAngle, - Deg180, - Deg180 + Deg180, - topCenter, - radiusV3, - ortho2Normalized - ); - - // Draw bottom cap - CreateArbitraryAxisArc( - lines, - stepAngle, - -Deg90, - -Deg90 + Deg180, - bottomCenter, - radiusV3, - ortho1Normalized - ); + // Draw cylinder part (or just a circle around the middle) + if (heightStraightSection > FLT_EPSILON) + { + DrawWireCylinder(center, axis, radius, heightStraightSection); + } + else + { + float Deg360 = DegToRad(360.0f); CreateArbitraryAxisArc( - lines, - stepAngle, - Deg0, - Deg0 + Deg180, - bottomCenter, - radiusV3, - ortho2Normalized - ); - - lines.Draw(m_auxGeomPtr, m_rendState); + lines, + stepAngle, + Deg0, + Deg360, + center, + radiusV3, + axisNormalized + ); } + + float Deg90 = DegToRad(90.0f); + float Deg180 = DegToRad(180.0f); + + AZ::Vector3 ortho1Normalized, ortho2Normalized; + CalcBasisVectors(axisNormalized, ortho1Normalized, ortho2Normalized); + AZ::Vector3 centerToTopCircleCenter = axisNormalized * heightStraightSection * 0.5f; + AZ::Vector3 topCenter = center + centerToTopCircleCenter; + AZ::Vector3 bottomCenter = center - centerToTopCircleCenter; + + // Draw top cap as two criss-crossing 180deg arcs + CreateArbitraryAxisArc( + lines, + stepAngle, + Deg90, + Deg90 + Deg180, + topCenter, + radiusV3, + ortho1Normalized + ); + + CreateArbitraryAxisArc( + lines, + stepAngle, + Deg180, + Deg180 + Deg180, + topCenter, + radiusV3, + ortho2Normalized + ); + + // Draw bottom cap + CreateArbitraryAxisArc( + lines, + stepAngle, + -Deg90, + -Deg90 + Deg180, + bottomCenter, + radiusV3, + ortho1Normalized + ); + + CreateArbitraryAxisArc( + lines, + stepAngle, + Deg0, + Deg0 + Deg180, + bottomCenter, + radiusV3, + ortho2Normalized + ); + + lines.Draw(m_auxGeomPtr, m_rendState); } + } - void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, float radius) + void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, float radius) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - m_auxGeomPtr->DrawSphere( - ToWorldSpacePosition(pos), - radius, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Line, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } + m_auxGeomPtr->DrawSphere( + ToWorldSpacePosition(pos), + radius, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Line, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); } + } - void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius) + void AtomDebugDisplayViewportInterface::DrawWireSphere(const AZ::Vector3& pos, const AZ::Vector3 radius) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - // This matches Cry behavior, the DrawWireSphere above may need modifying to use the same approach. - // Draw 3 axis aligned circles - const float step = DegToRad(10.0f); - const float maxAngle = DegToRad(360.0f) + step; - SingleColorStaticSizeLineHelper<40*3> lines; // hard code to 40 lines * 3 circles until DegToRad is constexpr. - - // Z Axis - AZ::Vector3 axisRadius(radius.GetX(), radius.GetY(), 0.0f); - CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisZ); - - // X Axis - axisRadius = AZ::Vector3(0.0f, radius.GetY(), radius.GetZ()); - CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisX); - - // Y Axis - axisRadius = AZ::Vector3(radius.GetX(), 0.0f, radius.GetZ()); - CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisY); - lines.Draw(m_auxGeomPtr, m_rendState); - } + // This matches Cry behavior, the DrawWireSphere above may need modifying to use the same approach. + // Draw 3 axis aligned circles + const float step = DegToRad(10.0f); + const float maxAngle = DegToRad(360.0f) + step; + SingleColorStaticSizeLineHelper<40*3> lines; // hard code to 40 lines * 3 circles until DegToRad is constexpr. + + // Z Axis + AZ::Vector3 axisRadius(radius.GetX(), radius.GetY(), 0.0f); + CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisZ); + + // X Axis + axisRadius = AZ::Vector3(0.0f, radius.GetY(), radius.GetZ()); + CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisX); + + // Y Axis + axisRadius = AZ::Vector3(radius.GetX(), 0.0f, radius.GetZ()); + CreateAxisAlignedArc(lines, step, 0.0f, maxAngle, pos, axisRadius, CircleAxisY); + lines.Draw(m_auxGeomPtr, m_rendState); } + } - void AtomDebugDisplayViewportInterface::DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) + void AtomDebugDisplayViewportInterface::DrawWireDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) - { - // Draw 3 axis aligned circles - const float stepAngle = DegToRad(11.25f); - const float startAngle = DegToRad(0.0f); - const float stopAngle = DegToRad(360.0f) + startAngle; - SingleColorDynamicSizeLineHelper lines(2+static_cast(360.0f/11.25f)); // num disk segments + 1 for azis line + 1 for spare - const AZ::Vector3 radiusV3 = AZ::Vector3(radius); - CreateArbitraryAxisArc( - lines, - stepAngle, - startAngle, - stopAngle, - pos, - radiusV3, - dir + // Draw 3 axis aligned circles + const float stepAngle = DegToRad(11.25f); + const float startAngle = DegToRad(0.0f); + const float stopAngle = DegToRad(360.0f) + startAngle; + SingleColorDynamicSizeLineHelper lines(2+static_cast(360.0f/11.25f)); // num disk segments + 1 for azis line + 1 for spare + const AZ::Vector3 radiusV3 = AZ::Vector3(radius); + CreateArbitraryAxisArc( + lines, + stepAngle, + startAngle, + stopAngle, + pos, + radiusV3, + dir + ); + + lines.AddLineSegment(ToWorldSpacePosition(pos), ToWorldSpacePosition(pos + dir * (radius * 0.2f))); // 0.2f comes from Code\Sandbox\Editor\Objects\DisplayContextShared.inl DisplayContext::DrawWireDisk + lines.Draw(m_auxGeomPtr, m_rendState); + } + } + + void AtomDebugDisplayViewportInterface::DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded) + { + if (m_auxGeomPtr) + { + // get the max scaled radius in case the transform on the stack is scaled non-uniformly + const float transformedRadiusX = ToWorldSpaceVector(AZ::Vector3(radius, 0.0f, 0.0f)).GetLengthEstimate(); + const float transformedRadiusY = ToWorldSpaceVector(AZ::Vector3(0.0f, radius, 0.0f)).GetLengthEstimate(); + const float transformedRadiusZ = ToWorldSpaceVector(AZ::Vector3(0.0f, 0.0f, radius)).GetLengthEstimate(); + const float maxTransformedRadius = + AZ::GetMax(transformedRadiusX, AZ::GetMax(transformedRadiusY, transformedRadiusZ)); + + AZ::RPI::AuxGeomDraw::DrawStyle drawStyle = drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid; + m_auxGeomPtr->DrawSphere( + ToWorldSpacePosition(pos), + maxTransformedRadius, + m_rendState.m_color, + drawStyle, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex ); + } + } - lines.AddLineSegment(ToWorldSpacePosition(pos), ToWorldSpacePosition(pos + dir * (radius * 0.2f))); // 0.2f comes from Code\Sandbox\Editor\Objects\DisplayContextShared.inl DisplayContext::DrawWireDisk - lines.Draw(m_auxGeomPtr, m_rendState); - } + void AtomDebugDisplayViewportInterface::DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) + { + if (m_auxGeomPtr) + { + const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); + const AZ::Vector3 worldDir = ToWorldSpaceVector(dir); + m_auxGeomPtr->DrawDisk( + worldPos, + worldDir, + radius, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); } + } - void AtomDebugDisplayViewportInterface::DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded) + void AtomDebugDisplayViewportInterface::DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float headScale, bool dualEndedArrow) + { + if (m_auxGeomPtr) { - if (m_auxGeomPtr) + float f2dScale = 1.0f; + float arrowLen = 0.4f * headScale; + float arrowRadius = 0.1f * headScale; + // if (flags & DISPLAY_2D) + // { + // f2dScale = 1.2f * ToWorldSpaceVector(Vec3(1, 0, 0)).GetLength(); + // } + AZ::Vector3 dir = trg - src; + dir = ToWorldSpaceVector(dir.GetNormalized()); + AZ::Vector3 verts[2] = {ToWorldSpacePosition(src), ToWorldSpacePosition(trg)}; + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = verts; + drawArgs.m_vertCount = 2; + drawArgs.m_colors = &m_rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = m_rendState.m_lineWidth; + drawArgs.m_opacityType = m_rendState.m_opacityType; + drawArgs.m_depthTest = m_rendState.m_depthTest; + drawArgs.m_depthWrite = m_rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; + if (!dualEndedArrow) { - // get the max scaled radius in case the transform on the stack is scaled non-uniformly - const float transformedRadiusX = ToWorldSpaceVector(AZ::Vector3(radius, 0.0f, 0.0f)).GetLengthEstimate(); - const float transformedRadiusY = ToWorldSpaceVector(AZ::Vector3(0.0f, radius, 0.0f)).GetLengthEstimate(); - const float transformedRadiusZ = ToWorldSpaceVector(AZ::Vector3(0.0f, 0.0f, radius)).GetLengthEstimate(); - const float maxTransformedRadius = - AZ::GetMax(transformedRadiusX, AZ::GetMax(transformedRadiusY, transformedRadiusZ)); - - AZ::RPI::AuxGeomDraw::DrawStyle drawStyle = drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid; - m_auxGeomPtr->DrawSphere( - ToWorldSpacePosition(pos), - maxTransformedRadius, - m_rendState.m_color, - drawStyle, + verts[1] -= dir * arrowLen; + m_auxGeomPtr->DrawLines(drawArgs); + m_auxGeomPtr->DrawCone( + verts[1], + dir, + arrowRadius * f2dScale, + arrowLen * f2dScale, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, m_rendState.m_depthTest, m_rendState.m_depthWrite, m_rendState.m_faceCullMode, m_rendState.m_viewProjOverrideIndex ); } - } - - void AtomDebugDisplayViewportInterface::DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) - { - if (m_auxGeomPtr) + else { - const AZ::Vector3 worldPos = ToWorldSpacePosition(pos); - const AZ::Vector3 worldDir = ToWorldSpaceVector(dir); - m_auxGeomPtr->DrawDisk( - worldPos, - worldDir, - radius, + verts[0] += dir * arrowLen; + verts[1] -= dir * arrowLen; + m_auxGeomPtr->DrawLines(drawArgs); + m_auxGeomPtr->DrawCone( + verts[0], + -dir, + arrowRadius * f2dScale, + arrowLen * f2dScale, + m_rendState.m_color, + AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, + m_rendState.m_depthTest, + m_rendState.m_depthWrite, + m_rendState.m_faceCullMode, + m_rendState.m_viewProjOverrideIndex + ); + m_auxGeomPtr->DrawCone( + verts[1], + dir, + arrowRadius * f2dScale, + arrowLen * f2dScale, m_rendState.m_color, AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, m_rendState.m_depthTest, @@ -829,179 +1224,297 @@ namespace AZ ); } } + } - void AtomDebugDisplayViewportInterface::DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float headScale, bool dualEndedArrow) + void AtomDebugDisplayViewportInterface::DrawTextLabel( + const AZ::Vector3& pos, + float size, + const char* text, + const bool center, + int srcOffsetX [[maybe_unused]], + int srcOffsetY [[maybe_unused]]) + { + AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface::Get()->GetDefaultFontDrawInterface(); + if (!fontDrawInterface || !text || size == 0.0f) { - if (m_auxGeomPtr) - { - float f2dScale = 1.0f; - float arrowLen = 0.4f * headScale; - float arrowRadius = 0.1f * headScale; - // if (flags & DISPLAY_2D) - // { - // f2dScale = 1.2f * ToWorldSpaceVector(Vec3(1, 0, 0)).GetLength(); - // } - AZ::Vector3 dir = trg - src; - dir = ToWorldSpaceVector(dir.GetNormalized()); - AZ::Vector3 verts[2] = {ToWorldSpacePosition(src), ToWorldSpacePosition(trg)}; - AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; - drawArgs.m_verts = verts; - drawArgs.m_vertCount = 2; - drawArgs.m_colors = &m_rendState.m_color; - drawArgs.m_colorCount = 1; - drawArgs.m_size = m_rendState.m_lineWidth; - drawArgs.m_opacityType = m_rendState.m_opacityType; - drawArgs.m_depthTest = m_rendState.m_depthTest; - drawArgs.m_depthWrite = m_rendState.m_depthWrite; - drawArgs.m_viewProjectionOverrideIndex = m_rendState.m_viewProjOverrideIndex; - if (!dualEndedArrow) - { - verts[1] -= dir * arrowLen; - m_auxGeomPtr->DrawLines(drawArgs); - m_auxGeomPtr->DrawCone( - verts[1], - dir, - arrowRadius * f2dScale, - arrowLen * f2dScale, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } - else - { - verts[0] += dir * arrowLen; - verts[1] -= dir * arrowLen; - m_auxGeomPtr->DrawLines(drawArgs); - m_auxGeomPtr->DrawCone( - verts[0], - -dir, - arrowRadius * f2dScale, - arrowLen * f2dScale, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - m_auxGeomPtr->DrawCone( - verts[1], - dir, - arrowRadius * f2dScale, - arrowLen * f2dScale, - m_rendState.m_color, - AZ::RPI::AuxGeomDraw::DrawStyle::Shaded, - m_rendState.m_depthTest, - m_rendState.m_depthWrite, - m_rendState.m_faceCullMode, - m_rendState.m_viewProjOverrideIndex - ); - } - } + return; } + // if 2d draw need to project pos to screen first + AzFramework::TextDrawParameters params; + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works + params.m_position = pos; + params.m_color = m_rendState.m_color; + params.m_scale = AZ::Vector2(size); + params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment + params.m_monospace = false; //! disable character proportional spacing + params.m_depthTest = false; //! Test character against the depth buffer + params.m_virtual800x600ScreenSize = true; //! Text placement and size are scaled relative to a virtual 800x600 resolution + params.m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger + params.m_multiline = true; //! text respects ascii newline characters + + fontDrawInterface->DrawScreenAlignedText3d(params, text); + } - // void AtomDebugDisplayViewportInterface::DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) override; - // void AtomDebugDisplayViewportInterface::Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) override; - // void AtomDebugDisplayViewportInterface::DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) override; - // unhandledled on Atom - virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; - // void AtomDebugDisplayViewportInterface::DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; - - void AtomDebugDisplayViewportInterface::SetLineWidth(float width) + void AtomDebugDisplayViewportInterface::Draw2dTextLabel( + float x, + float y, + float size, + const char* text, + bool center) + { + AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface::Get()->GetDefaultFontDrawInterface(); + if (!fontDrawInterface || !text || size == 0.0f) { - AZ_Assert(width >= 0.0f && width <= 255.0f, "Width (%f) exceeds allowable range [0 - 255]", width); - m_rendState.m_lineWidth = static_cast(width); + return; } + // if 2d draw need to project pos to screen first + AzFramework::TextDrawParameters params; + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + params.m_drawViewportId = viewportContext->GetId(); // get the viewport ID so default viewport works + params.m_position = AZ::Vector3(x, y, 1.0f); + params.m_color = m_rendState.m_color; + params.m_scale = AZ::Vector2(size); + params.m_hAlign = center ? AzFramework::TextHorizontalAlignment::Center : AzFramework::TextHorizontalAlignment::Left; //! Horizontal text alignment + params.m_monospace = false; //! disable character proportional spacing + params.m_depthTest = false; //! Test character against the depth buffer + params.m_virtual800x600ScreenSize = true; //! Text placement and size are scaled relative to a virtual 800x600 resolution + params.m_scaleWithWindow = false; //! Font gets bigger as the window gets bigger + params.m_multiline = true; //! text respects ascii newline characters + + fontDrawInterface->DrawScreenAlignedText2d(params, text); + } - // bool AtomDebugDisplayViewportInterface::IsVisible(const AZ::Aabb& bounds) override; - // int AtomDebugDisplayViewportInterface::SetFillMode(int nFillMode) override; - float AtomDebugDisplayViewportInterface::GetLineWidth() - { - return m_rendState.m_lineWidth; - } + void AtomDebugDisplayViewportInterface::DrawTextOn2DBox( + const AZ::Vector3& pos [[maybe_unused]], + const char* text [[maybe_unused]], + float textScale [[maybe_unused]], + const AZ::Vector4& TextColor [[maybe_unused]], + const AZ::Vector4& TextBackColor [[maybe_unused]]) + { + AZ_Assert(false, "Unexpected use of legacy api, please file a feature request with the rendering team to get this implemented!"); + } + // unhandledled on Atom - virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; + // void AtomDebugDisplayViewportInterface::DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; + + void AtomDebugDisplayViewportInterface::SetLineWidth(float width) + { + AZ_Assert(width >= 0.0f && width <= 255.0f, "Width (%f) exceeds allowable range [0 - 255]", width); + m_rendState.m_lineWidth = static_cast(width); + } + + bool AtomDebugDisplayViewportInterface::IsVisible(const AZ::Aabb& bounds) + { + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + const AZ::Matrix4x4& worldToClip = viewportContext->GetDefaultView()->GetWorldToClipMatrix(); + AZ::Frustum frustum = AZ::Frustum::CreateFromMatrixColumnMajor(worldToClip, Frustum::ReverseDepth::True); + return frustum.IntersectAabb(bounds) != AZ::IntersectResult::Exterior; + } + // int AtomDebugDisplayViewportInterface::SetFillMode(int nFillMode) override; + float AtomDebugDisplayViewportInterface::GetLineWidth() + { + return m_rendState.m_lineWidth; + } + + float AtomDebugDisplayViewportInterface::GetAspectRatio() + { + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); + auto windowSize = viewportContext->GetViewportSize(); + return aznumeric_cast(windowSize.m_width)/aznumeric_cast(windowSize.m_height); + } + + void AtomDebugDisplayViewportInterface::DepthTestOff() + { + m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::Off; + } + + void AtomDebugDisplayViewportInterface::DepthTestOn() + { + m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::On; + } + + void AtomDebugDisplayViewportInterface::DepthWriteOff() + { + m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::Off; + } + + void AtomDebugDisplayViewportInterface::DepthWriteOn() + { + m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::On; + } + + void AtomDebugDisplayViewportInterface::CullOff() + { + m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::None; + } + + void AtomDebugDisplayViewportInterface::CullOn() + { + m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Back; + } + + bool AtomDebugDisplayViewportInterface::SetDrawInFrontMode(bool on) + { + AZ_UNUSED(on); + return false; + } + + AZ::u32 AtomDebugDisplayViewportInterface::GetState() + { + return ConvertRenderStateToCry(); + } + + AZ::u32 AtomDebugDisplayViewportInterface::SetState(AZ::u32 state) + { + uint32_t currentState = ConvertRenderStateToCry(); + uint32_t changedState = (state & e_PublicParamsMask) ^ currentState; - float AtomDebugDisplayViewportInterface::GetAspectRatio() + if (changedState & e_Mode2D3DMask) { - auto viewContextManager = AZ::Interface::Get(); - AZ::RPI::ViewportContextPtr viewportContext; - if (m_defaultInstance) + // this is the only way to turn on 2d Mode under Atom + if (state & e_Mode2D) { - viewportContext = viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName()); + AZ_Assert((currentState & e_DrawInFrontOn) == 0 && (changedState & e_DrawInFrontOn) == 0, "Atom doesnt support Draw In Front and 2d at the same time"); + m_rendState.m_viewProjOverrideIndex = m_auxGeomPtr->GetOrAdd2DViewProjOverride(); + m_rendState.m_2dMode = true; } - else + else // switch back to mode 3d { - viewportContext = viewContextManager->GetViewportContextById(m_viewportId); + m_rendState.m_viewProjOverrideIndex = -1; + m_rendState.m_2dMode = false; } - auto windowSize = viewportContext->GetViewportSize(); - return aznumeric_cast(windowSize.m_width)/aznumeric_cast(windowSize.m_height); } - void AtomDebugDisplayViewportInterface::DepthTestOff() + if (changedState & e_AlphaBlendingMask) { - m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::Off; + switch (state&e_AlphaBlendingMask) + { + case e_AlphaNone: + m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Opaque; + break; + case e_AlphaAdditive: + [[fallthrough]]; // Additive not currently supported in Atom AuxGeom implementation + case e_AlphaBlended: + m_rendState.m_opacityType = AZ::RPI::AuxGeomDraw::OpacityType::Translucent; + break; + } } - void AtomDebugDisplayViewportInterface::DepthTestOn() + if (changedState & e_DrawInFrontMask) { - m_rendState.m_depthTest = AZ::RPI::AuxGeomDraw::DepthTest::On; + AZ_Assert( // either state is turning DrawInFront off or Mode 2D has to be off + (state & e_DrawInFrontOn) == 0 || + ((currentState & e_Mode2D) == 0 && (changedState & e_Mode2D) == 0), + "Atom doesnt support Draw In Front and 2d at the same time"); + SetDrawInFrontMode(changedState & e_DrawInFrontOn); } - - void AtomDebugDisplayViewportInterface::DepthWriteOff() + + if (changedState & e_CullModeMask) { - m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::Off; + switch (state & e_CullModeMask) + { + case e_CullModeNone: + CullOff(); + break; + case e_CullModeFront: + // Currently no other way to set front face culling in DebugDisplayRequestBus + m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Front; + break; + case e_CullModeBack: + CullOn(); + break; + } } - - void AtomDebugDisplayViewportInterface::DepthWriteOn() + + if (changedState & e_DepthWriteMask) { - m_rendState.m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::On; + if (state & e_DepthWriteOff) + { + DepthWriteOff(); + } + else + { + DepthWriteOn(); + } } - - void AtomDebugDisplayViewportInterface::CullOff() + + if (changedState & e_DepthTestMask) { - m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::None; + if (state & e_DepthTestOff) + { + DepthTestOff(); + } + else + { + DepthTestOn(); + } } - - void AtomDebugDisplayViewportInterface::CullOn() + + return currentState; + } + + void AtomDebugDisplayViewportInterface::PushMatrix(const AZ::Transform& tm) + { + AZ_Assert(m_rendState.m_currentTransform < RenderState::TransformStackSize, "Exceeded AtomDebugDisplayViewportInterface matrix stack size"); + if (m_rendState.m_currentTransform < RenderState::TransformStackSize) { - m_rendState.m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Back; + m_rendState.m_currentTransform++; + m_rendState.m_transformStack[m_rendState.m_currentTransform] = m_rendState.m_transformStack[m_rendState.m_currentTransform - 1] * AZ::Matrix3x4::CreateFromTransform(tm); } - - bool AtomDebugDisplayViewportInterface::SetDrawInFrontMode(bool on) + } + + void AtomDebugDisplayViewportInterface::PopMatrix() + { + AZ_Assert(m_rendState.m_currentTransform > 0, "Underflowed AtomDebugDisplayViewportInterface matrix stack"); + if (m_rendState.m_currentTransform > 0) { - AZ_UNUSED(on); - return false; + m_rendState.m_currentTransform--; } - - // AZ::u32 AtomDebugDisplayViewportInterface::GetState() override; - // AZ::u32 AtomDebugDisplayViewportInterface::SetState(AZ::u32 state) override; - // AZ::u32 AtomDebugDisplayViewportInterface::SetStateFlag(AZ::u32 state) override; - // AZ::u32 AtomDebugDisplayViewportInterface::ClearStateFlag(AZ::u32 state) override; + } + + const AZ::Matrix3x4& AtomDebugDisplayViewportInterface::GetCurrentTransform() const + { + return m_rendState.m_transformStack[m_rendState.m_currentTransform]; + } - void AtomDebugDisplayViewportInterface::PushMatrix(const AZ::Transform& tm) + AZ::RPI::ViewportContextPtr AtomDebugDisplayViewportInterface::GetViewportContext() const + { + auto viewContextManager = AZ::Interface::Get(); + if (m_defaultInstance) { - AZ_Assert(m_rendState.m_currentTransform < RenderState::TransformStackSize, "Exceeded AtomDebugDisplayViewportInterface matrix stack size"); - if (m_rendState.m_currentTransform < RenderState::TransformStackSize) - { - m_rendState.m_currentTransform++; - m_rendState.m_transformStack[m_rendState.m_currentTransform] = m_rendState.m_transformStack[m_rendState.m_currentTransform - 1] * AZ::Matrix3x4::CreateFromTransform(tm); - } + return viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName()); } - - void AtomDebugDisplayViewportInterface::PopMatrix() + else { - AZ_Assert(m_rendState.m_currentTransform > 0, "Underflowed AtomDebugDisplayViewportInterface matrix stack"); - if (m_rendState.m_currentTransform > 0) - { - m_rendState.m_currentTransform--; - } + return viewContextManager->GetViewportContextById(m_viewportId); } + } - const AZ::Matrix3x4& AtomDebugDisplayViewportInterface::GetCurrentTransform() const + uint32_t AtomDebugDisplayViewportInterface::ConvertRenderStateToCry() const + { + uint32_t result = 0; + + result |= m_rendState.m_2dMode ? e_Mode2D : e_Mode3D; + result |= m_rendState.m_opacityType == AZ::RPI::AuxGeomDraw::OpacityType::Opaque ? e_AlphaNone : e_AlphaBlended; + result |= m_rendState.m_drawInFront ? e_DrawInFrontOn : e_DrawInFrontOff; + result |= m_rendState.m_depthTest == AZ::RPI::AuxGeomDraw::DepthTest::On ? e_DepthTestOn : e_DepthTestOff; + result |= m_rendState.m_depthWrite == AZ::RPI::AuxGeomDraw::DepthWrite::On ? e_DepthWriteOn : e_DepthWriteOff; + switch (m_rendState.m_faceCullMode) { - return m_rendState.m_transformStack[m_rendState.m_currentTransform]; + case AZ::RPI::AuxGeomDraw::FaceCullMode::None: + result |= e_CullModeNone; + break; + case AZ::RPI::AuxGeomDraw::FaceCullMode::Front: + result |= e_CullModeFront; + break; + case AZ::RPI::AuxGeomDraw::FaceCullMode::Back: + result |= e_CullModeBack; + break; + default: + AZ_Assert(false, "Trying to convert an unknown culling mode to cry!"); + break; } + + return result; } } diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h index 48091ea8d8..021d816ca4 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h @@ -42,6 +42,10 @@ namespace AZ::AtomBridge AZ::RPI::AuxGeomDraw::DepthWrite m_depthWrite = AZ::RPI::AuxGeomDraw::DepthWrite::On; AZ::RPI::AuxGeomDraw::FaceCullMode m_faceCullMode = AZ::RPI::AuxGeomDraw::FaceCullMode::Back; int32_t m_viewProjOverrideIndex = -1; // will be used to implement SetDrawInFrontMode & 2D mode + + // separate tracking for Cry only state + bool m_drawInFront = false; + bool m_2dMode = false; }; //! Utility class to collect line segments when the number of segments is known at compile time. @@ -77,6 +81,24 @@ namespace AZ::AtomBridge } } + void Draw2d(AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, const RenderState& rendState) const + { + if (auxGeomDrawPtr && !m_points.empty()) + { + AZ::RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments drawArgs; + drawArgs.m_verts = m_points.data(); + drawArgs.m_vertCount = aznumeric_cast(m_points.size()); + drawArgs.m_colors = &rendState.m_color; + drawArgs.m_colorCount = 1; + drawArgs.m_size = rendState.m_lineWidth; + drawArgs.m_opacityType = rendState.m_opacityType; + drawArgs.m_depthTest = rendState.m_depthTest; + drawArgs.m_depthWrite = rendState.m_depthWrite; + drawArgs.m_viewProjectionOverrideIndex = auxGeomDrawPtr->GetOrAdd2DViewProjOverride(); + auxGeomDrawPtr->DrawLines( drawArgs ); + } + } + void Reset() { m_points.clear(); @@ -91,6 +113,7 @@ namespace AZ::AtomBridge SingleColorDynamicSizeLineHelper(int estimatedNumLineSegments); void AddLineSegment(const AZ::Vector3& lineStart, const AZ::Vector3& lineEnd); void Draw(AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, const RenderState& rendState) const; + void Draw2d(AZ::RPI::AuxGeomDrawPtr auxGeomDrawPtr, const RenderState& rendState) const; void Reset(); AZStd::vector m_points; @@ -119,9 +142,9 @@ namespace AZ::AtomBridge void SetColor(const AZ::Vector4& color) override; void SetAlpha(float a) override; void DrawQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override; - // void DrawQuad(float width, float height) overr - // void DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override; - // void DrawWireQuad(float width, float height) override; + void DrawQuad(float width, float height) override; + void DrawWireQuad(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4) override; + void DrawWireQuad(float width, float height) override; void DrawQuadGradient(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3, const AZ::Vector3& p4, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override; void DrawTri(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector3& p3) override; void DrawTriangles(const AZStd::vector& vertices, const AZ::Color& color) override; @@ -134,10 +157,10 @@ namespace AZ::AtomBridge void DrawLine(const AZ::Vector3& p1, const AZ::Vector3& p2, const AZ::Vector4& col1, const AZ::Vector4& col2) override; void DrawLines(const AZStd::vector& lines, const AZ::Color& color) override; void DrawPolyLine(const AZ::Vector3* pnts, int numPoints, bool cycled = true) override; - // void DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; - // void DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; - // void DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override; - // void DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) override; + void DrawWireQuad2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; + void DrawLine2d(const AZ::Vector2& p1, const AZ::Vector2& p2, float z) override; + void DrawLine2dGradient(const AZ::Vector2& p1, const AZ::Vector2& p2, float z, const AZ::Vector4& firstColor, const AZ::Vector4& secondColor) override; + void DrawWireCircle2d(const AZ::Vector2& center, float radius, float z) override; void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, int referenceAxis = 2) override; void DrawArc(const AZ::Vector3& pos, float radius, float startAngleDegrees, float sweepAngleDegrees, float angularStepDegrees, const AZ::Vector3& fixedAxis) override; void DrawCircle(const AZ::Vector3& pos, float radius, int nUnchangedAxis = 2 /*z axis*/) override; @@ -152,13 +175,13 @@ namespace AZ::AtomBridge void DrawBall(const AZ::Vector3& pos, float radius, bool drawShaded) override; void DrawDisk(const AZ::Vector3& pos, const AZ::Vector3& dir, float radius) override; void DrawArrow(const AZ::Vector3& src, const AZ::Vector3& trg, float headScale = 1.0f, bool dualEndedArrow = false) override; - // void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) override; - // void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) override; - // void DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) override; + void DrawTextLabel(const AZ::Vector3& pos, float size, const char* text, const bool bCenter = false, int srcOffsetX = 0, int srcOffsetY = 0) override; + void Draw2dTextLabel(float x, float y, float size, const char* text, bool bCenter = false) override; + void DrawTextOn2DBox(const AZ::Vector3& pos, const char* text, float textScale, const AZ::Vector4& TextColor, const AZ::Vector4& TextBackColor) override; // unhandled on Atom - virtual void DrawTextureLabel(ITexture* texture, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; // void DrawTextureLabel(int textureId, const AZ::Vector3& pos, float sizeX, float sizeY, int texIconFlags) override; void SetLineWidth(float width) override; - // bool IsVisible(const AZ::Aabb& bounds) override; + bool IsVisible(const AZ::Aabb& bounds) override; // int SetFillMode(int nFillMode) override; float GetLineWidth() override; float GetAspectRatio() override; @@ -169,10 +192,8 @@ namespace AZ::AtomBridge void CullOff() override; void CullOn() override; bool SetDrawInFrontMode(bool on) override; - // AZ::u32 GetState() override; - // AZ::u32 SetState(AZ::u32 state) override; - // AZ::u32 SetStateFlag(AZ::u32 state) override; - // AZ::u32 ClearStateFlag(AZ::u32 state) override; + AZ::u32 GetState() override; + AZ::u32 SetState(AZ::u32 state) override; void PushMatrix(const AZ::Transform& tm) override; void PopMatrix() override; @@ -226,6 +247,10 @@ namespace AZ::AtomBridge void InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr); + AZ::RPI::ViewportContextPtr GetViewportContext() const; + + uint32_t ConvertRenderStateToCry() const; + RenderState m_rendState; AZ::RPI::AuxGeomDrawPtr m_auxGeomPtr; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h index b1feaf1d87..2969e35a51 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h @@ -20,8 +20,14 @@ #include #include #include +#include #include +#include +#include + +#include + namespace AZ { class FFont; @@ -33,6 +39,8 @@ namespace AZ //! and manages their loading & saving together. class AtomFont : public ICryFont + , public AzFramework::FontQueryInterface + , public AzFramework::SceneSystemNotificationBus::Handler { friend class FFont; @@ -79,16 +87,31 @@ namespace AZ void ReloadAllFonts() override; ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////// + // FontQueryInterface implementation + AzFramework::FontDrawInterface* GetFontDrawInterface(AzFramework::FontId fontId) const override; + AzFramework::FontDrawInterface* GetDefaultFontDrawInterface() const override; + + // SceneSystemNotificationBus handlers + void SceneAboutToBeRemoved(AzFramework::Scene& scene) override; + + + // Atom DynamicDraw interface management + AZ::RHI::Ptr GetOrCreateDynamicDrawForScene(AZ::RPI::Scene* scene); + + public: void UnregisterFont(const char* fontName); private: - typedef std::map FontMap; - typedef FontMap::iterator FontMapItor; - typedef FontMap::const_iterator FontMapConstItor; + using FontMap = std::unordered_map; + using FontMapItor = FontMap::iterator; + using FontMapConstItor = FontMap::const_iterator; - typedef AZStd::map> FontFamilyMap; - typedef AZStd::map FontFamilyReverseLookupMap; + using FontFamilyMap = AZStd::unordered_map>; + using FontFamilyReverseLookupMap = AZStd::unordered_map; + + using SceneToDynamicDrawMap = AZStd::unordered_map>; private: //! Convenience method for loading fonts @@ -119,9 +142,13 @@ namespace AZ FontFamilyReverseLookupMap m_fontFamilyReverseLookup; // m_persistedFontFamilies; //!< Stores persisted fonts (if "persist font families" is enabled) + SceneToDynamicDrawMap m_sceneToDynamicDrawMap; + AZStd::shared_mutex m_sceneToDynamicDrawMutex; }; } #endif diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index 4f87334b46..96f5e09fc3 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,8 @@ namespace AZ void operator () (const AZStd::intrusive_refcount* ptr) const; }; + using TextDrawContext = STextDrawContext; + //! FFont is the implementation of IFFont used to draw text with a particular font (e.g. Consolas Italic) //! FFont manages creation of a gpu texture to cache the font and generates draw commands that use that texture. //! FFont's are managed by AtomFont as either individual font instances or a font family @@ -64,12 +67,12 @@ namespace AZ class FFont : public IFFont , public AZStd::intrusive_refcount + , public AzFramework::FontDrawInterface , private AZ::Render::Bootstrap::NotificationBus::Handler { using ref_count = AZStd::intrusive_refcount; friend FontDeleter; public: - using TextDrawContext = STextDrawContext; //! Determines how characters of different sizes should be handled during render. enum class SizeBehavior { @@ -201,6 +204,14 @@ namespace AZ uint32_t GetFontTextureVersion() override; ///////////////////////////////////////////////////////////////////////////////////////////////////// + // AzFramework::FontDrawInterface implementation + void DrawScreenAlignedText2d( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) override; + + void DrawScreenAlignedText3d( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) override; public: FFont(AtomFont* atomFont, const char* fontName); @@ -220,8 +231,18 @@ namespace AZ bool InitCache(); void Prepare(const char* str, bool updateTexture, const AtomFont::GlyphSize& glyphSize = AtomFont::defaultGlyphSize); - void DrawStringUInternal(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx); - Vec2 GetTextSizeUInternal(const char* str, const bool asciiMultiLine, const TextDrawContext& ctx); + void DrawStringUInternal( + const RHI::Viewport& viewport, + RPI::ViewportContext* viewportContext, + float x, + float y, + float z, + const char* str, + const bool asciiMultiLine, + const TextDrawContext& ctx); + Vec2 GetTextSizeUInternal(const RHI::Viewport& viewport, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx); + Vec2 GetKerningInternal(const RHI::Viewport& viewport, uint32_t leftGlyph, uint32_t rightGlyph, const TextDrawContext& ctx) const; + float GetBaselineInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const; // returns true if add operation was successful, false otherwise using AddFunction = AZStd::function; @@ -229,6 +250,7 @@ namespace AZ //! This function is used by both DrawStringUInternal and WriteTextQuadsToBuffers //! To do this is takes a function pointer that implement the appropriate AddQuad behavior int CreateQuadsForText( + const RHI::Viewport& viewport, float x, float y, float z, @@ -247,16 +269,16 @@ namespace AZ float rcpCellWidth; }; - TextScaleInfoInternal CalculateScaleInternal(const TextDrawContext& ctx) const; + TextScaleInfoInternal CalculateScaleInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const; Vec2 GetRestoredFontSize(const TextDrawContext& ctx) const; bool UpdateTexture(); - void ScaleCoord(float& x, float& y) const; + void ScaleCoord(const RHI::Viewport& viewport, float& x, float& y) const; - void InitWindowContext(); - void InitViewportContext(); + void InitDefaultWindowContext(); + void InitDefaultViewportContext(); void OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) override; @@ -272,8 +294,8 @@ namespace AZ size_t m_fontBufferSize = 0; unsigned char* m_fontBuffer = nullptr; - AZStd::shared_ptr m_windowContext; - AZStd::shared_ptr m_viewportContext; + AZStd::shared_ptr m_defaultWindowContext; + AZStd::shared_ptr m_defaultViewportContext; AZ::Data::Instance m_fontStreamingImage; AZ::RHI::Ptr m_fontImage; @@ -296,8 +318,6 @@ namespace AZ FontShaderData m_fontShaderData; - AZ::RHI::Ptr m_dynamicDraw; - bool m_monospacedFont = false; //!< True if this font is fixed/monospaced, false otherwise (obtained from FreeType) float m_sizeRatio = IFFontConstants::defaultSizeRatio; @@ -325,25 +345,25 @@ namespace AZ } } -inline void AZ::FFont::InitWindowContext() +inline void AZ::FFont::InitDefaultWindowContext() { - if (!m_windowContext) + if (!m_defaultWindowContext) { // font is created before window & viewport in the editor so need to do late init // TODO need to deal with multiple windows, such as the editor - AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_windowContext, &AZ::Render::Bootstrap::DefaultWindowInterface::GetDefaultWindowContext); - AZ_Assert(m_windowContext, "Unable to get the main window context"); + AZ::Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_defaultWindowContext, &AZ::Render::Bootstrap::DefaultWindowInterface::GetDefaultWindowContext); + AZ_Assert(m_defaultWindowContext, "Unable to get the main window context"); } } -inline void AZ::FFont::InitViewportContext() +inline void AZ::FFont::InitDefaultViewportContext() { - if (!m_viewportContext) + if (!m_defaultViewportContext) { // font is created before window & viewport in the editor so need to do late init auto viewContextManager = AZ::Interface::Get(); - m_viewportContext = viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName()); - AZ_Assert(m_viewportContext, "Unable to get the viewport context"); + m_defaultViewportContext = viewContextManager->GetViewportContextByName(viewContextManager->GetDefaultViewportContextName()); + AZ_Assert(m_defaultViewportContext, "Unable to get the viewport context"); } } diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp index 0a081d01f1..636583fe98 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFont.cpp @@ -28,8 +28,12 @@ #include #include +#include +#include #include +#include +#include // Static member definitions const AZ::AtomFont::GlyphSize AZ::AtomFont::defaultGlyphSize = AZ::AtomFont::GlyphSize(ICryFont::defaultGlyphSizeX, ICryFont::defaultGlyphSizeY); @@ -348,10 +352,14 @@ AZ::AtomFont::AtomFont(ISystem* system) REGISTER_COMMAND("r_ReloadFonts", ReloadFonts, VF_NULL, "Reload all fonts"); #endif + AZ::Interface::Register(this); } AZ::AtomFont::~AtomFont() { + AZ::Interface::Unregister(this); + m_defaultFontDrawInterface = nullptr; + // Persist fonts for application lifetime to prevent unnecessary work m_persistedFontFamilies.clear(); @@ -372,24 +380,41 @@ IFFont* AZ::AtomFont::NewFont(const char* fontName) { string name = fontName; name.MakeLower(); + AzFramework::FontId fontId = GetFontId(name.c_str()); - FontMapItor it = m_fonts.find(CONST_TEMP_STRING(name.c_str())); + FontMapItor it = m_fonts.find(fontId); if (it != m_fonts.end()) { return it->second; } FFont* font = new FFont(this, name.c_str()); - m_fonts.insert(FontMapItor::value_type(name, font)); + m_fonts.insert(FontMapItor::value_type(fontId, font)); + if(!m_defaultFontDrawInterface) + { + m_defaultFontDrawInterface = static_cast(font); + } return font; } IFFont* AZ::AtomFont::GetFont(const char* fontName) const { - FontMapConstItor it = m_fonts.find(CONST_TEMP_STRING(string(fontName).MakeLower())); + AzFramework::FontId fontId = GetFontId(string(fontName).MakeLower().c_str()); + FontMapConstItor it = m_fonts.find(fontId); return it != m_fonts.end() ? it->second : 0; } +AzFramework::FontDrawInterface* AZ::AtomFont::GetFontDrawInterface(AzFramework::FontId fontId) const +{ + FontMapConstItor it = m_fonts.find(fontId); + return (it != m_fonts.end()) ? it->second : nullptr; +} + +AzFramework::FontDrawInterface* AZ::AtomFont::GetDefaultFontDrawInterface() const +{ + return m_defaultFontDrawInterface; +} + FontFamilyPtr AZ::AtomFont::LoadFontFamily(const char* fontFamilyName) { FontFamilyPtr fontFamily(nullptr); @@ -648,7 +673,8 @@ void AZ::AtomFont::ReloadAllFonts() void AZ::AtomFont::UnregisterFont(const char* fontName) { - FontMapItor it = m_fonts.find(CONST_TEMP_STRING(fontName)); + AzFramework::FontId fontId = GetFontId(string(fontName).MakeLower().c_str()); + FontMapItor it = m_fonts.find(fontId); #if defined(AZ_ENABLE_TRACING) IFFont* fontPtr = it->second; @@ -823,5 +849,49 @@ XmlNodeRef AZ::AtomFont::LoadFontFamilyXml(const char* fontFamilyName, string& o return root; } +void AZ::AtomFont::SceneAboutToBeRemoved(AzFramework::Scene& scene) +{ + AZ::RPI::Scene* rpiScene = scene.GetSubsystem(); + + AZStd::lock_guard lock(m_sceneToDynamicDrawMutex); + if ( auto it = m_sceneToDynamicDrawMap.find(rpiScene); it != m_sceneToDynamicDrawMap.end()) + { + m_sceneToDynamicDrawMap.erase(it); + } +} + +AZ::RHI::Ptr AZ::AtomFont::GetOrCreateDynamicDrawForScene(AZ::RPI::Scene* scene) +{ + static const char* shaderFilepath = "Shaders/SimpleTextured.azshader"; + + { + // shared lock while reading + AZStd::shared_lock lock(m_sceneToDynamicDrawMutex); + + if (auto it = m_sceneToDynamicDrawMap.find(scene); it != m_sceneToDynamicDrawMap.end()) + { + return it->second; + } + } + + // Create and initialize DynamicDrawContext for font draw + AZ::RHI::Ptr dynamicDraw = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(scene); + + Data::Instance shader = AZ::RPI::LoadShader(shaderFilepath); + AZ::RPI::ShaderOptionList shaderOptions; + shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("false"))); + shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true"))); + dynamicDraw->InitShaderWithVariant(shader, &shaderOptions); + dynamicDraw->InitVertexFormat({{"POSITION", RHI::Format::R32G32B32_FLOAT}, {"COLOR", RHI::Format::R8G8B8A8_UNORM}, {"TEXCOORD0", RHI::Format::R32G32_FLOAT}}); + dynamicDraw->EndInit(); + + // exclusive lock while writing + AZStd::lock_guard lock(m_sceneToDynamicDrawMutex); + m_sceneToDynamicDrawMap.insert(AZStd::make_pair(scene, dynamicDraw)); + + return dynamicDraw; +} + + #endif diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index bb4eb23d8f..d32302a07b 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -23,6 +23,9 @@ #include #include +#include +#include + #include #include @@ -42,6 +45,8 @@ #include #include #include +#include +#include #include #include @@ -49,6 +54,7 @@ #include +static const AZ::Vector2 UiDraw_TextSizeFactor = AZ::Vector2(12.0f, 12.0f); static const int TabCharCount = 4; // set buffer sizes to hold max characters that can be drawn in 1 DrawString call static const size_t MaxVerts = 8 * 1024; // 2048 quads @@ -78,6 +84,7 @@ AZ::FFont::FFont(AtomFont* atomFont, const char* fontName) AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect(); } + bool AZ::FFont::InitFont() { if (m_fontInitialized) @@ -85,24 +92,14 @@ bool AZ::FFont::InitFont() return true; } - InitWindowContext(); - InitViewportContext(); - - const char* shaderFilepath = "Shaders/SimpleTextured.azshader"; + InitDefaultWindowContext(); + InitDefaultViewportContext(); // Create and initialize DynamicDrawContext for font draw - m_dynamicDraw = RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(m_viewportContext->GetRenderScene().get()); - - Data::Instance shader = AZ::RPI::LoadShader(shaderFilepath); - AZ::RPI::ShaderOptionList shaderOptions; - shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("false"))); - shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true"))); - m_dynamicDraw->InitShaderWithVariant(shader, &shaderOptions); - m_dynamicDraw->InitVertexFormat({{"POSITION", RHI::Format::R32G32B32_FLOAT}, {"COLOR", RHI::Format::R8G8B8A8_UNORM}, {"TEXCOORD0", RHI::Format::R32G32_FLOAT}}); - m_dynamicDraw->EndInit(); + AZ::RPI::Ptr dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(m_defaultViewportContext->GetRenderScene().get()); // Save draw srg input indices for later use - Data::Instance drawSrg = m_dynamicDraw->NewDrawSrg(); + Data::Instance drawSrg = dynamicDraw->NewDrawSrg(); const RHI::ShaderResourceGroupLayout* layout = drawSrg->GetAsset()->GetLayout(); m_fontShaderData.m_imageInputIndex = layout->FindShaderInputImageIndex(AZ::Name(ShaderInputs::TextureIndexName)); @@ -257,27 +254,39 @@ void AZ::FFont::Free() void AZ::FFont::DrawString(float x, float y, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) { - if (!str || !m_vertexBuffer) + if (!str) { return; } - DrawStringUInternal(x, y, 1.0f, str, asciiMultiLine, ctx); + DrawStringUInternal(m_defaultWindowContext->GetViewport(), m_defaultViewportContext.get(), x, y, 1.0f, str, asciiMultiLine, ctx); } void AZ::FFont::DrawString(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) { - if (!str || !m_vertexBuffer) + if (!str) { return; } - DrawStringUInternal(x, y, z, str, asciiMultiLine, ctx); + DrawStringUInternal(m_defaultWindowContext->GetViewport(), m_defaultViewportContext.get(), x, y, z, str, asciiMultiLine, ctx); } -void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) +void AZ::FFont::DrawStringUInternal( + const RHI::Viewport& viewport, + RPI::ViewportContext* viewportContext, + float x, + float y, + float z, + const char* str, + const bool asciiMultiLine, + const TextDrawContext& ctx) { - if (!str || !m_fontTexture || ctx.m_fxIdx >= m_effects.size() || m_effects[ctx.m_fxIdx].m_passes.empty()) + if (!str + || !m_vertexBuffer // vertex buffer isn't created until BootstrapScene is ready, Editor tries to render text before that. + || !m_fontTexture + || ctx.m_fxIdx >= m_effects.size() + || m_effects[ctx.m_fxIdx].m_passes.empty()) { return; } @@ -296,7 +305,6 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, const bool orthoMode = ctx.m_overrideViewProjMatrices; - const RHI::Viewport& viewport = m_windowContext->GetViewport(); const float viewX = viewport.m_minX; const float viewY = viewport.m_minY; const float viewWidth = viewport.m_maxX - viewport.m_minX; @@ -307,7 +315,7 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, Matrix4x4 modelViewProjMat; if (!orthoMode) { - AZ::RPI::ViewPtr view = m_viewportContext->GetDefaultView(); + AZ::RPI::ViewPtr view = viewportContext->GetDefaultView(); modelViewProjMat = view->GetWorldToClipMatrix(); } else @@ -322,7 +330,7 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, size_t startingVertexCount = m_vertexCount; // Local function that is passed into CreateQuadsForText as the AddQuad function - AddFunction AddQuad = [this, startingVertexCount] + AZ::FFont::AddFunction AddQuad = [this, startingVertexCount] (const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, const Vec2& tc0, const Vec2& tc1, const Vec2& tc2, const Vec2& tc3, uint32_t packedColor) { const bool vertexSpaceLeft = m_vertexCount + 4 < MaxVerts; @@ -367,18 +375,19 @@ void AZ::FFont::DrawStringUInternal(float x, float y, float z, const char* str, int numQuads = 0; { AZStd::lock_guard lock(m_vertexDataMutex); - numQuads = CreateQuadsForText(x, y, z, str, asciiMultiLine, ctx, AddQuad); + numQuads = CreateQuadsForText(viewport, x, y, z, str, asciiMultiLine, ctx, AddQuad); } if (numQuads) { + auto dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(viewportContext->GetRenderScene().get()); //setup per draw srg - auto drawSrg = m_dynamicDraw->NewDrawSrg(); + auto drawSrg = dynamicDraw->NewDrawSrg(); drawSrg->SetConstant(m_fontShaderData.m_viewProjInputIndex, modelViewProjMat); drawSrg->SetImageView(m_fontShaderData.m_imageInputIndex, m_fontStreamingImage->GetImageView()); drawSrg->Compile(); - m_dynamicDraw->DrawIndexed(m_vertexBuffer, m_vertexCount, m_indexBuffer, m_indexCount, RHI::IndexFormat::Uint16, drawSrg); + dynamicDraw->DrawIndexed(m_vertexBuffer, m_vertexCount, m_indexBuffer, m_indexCount, RHI::IndexFormat::Uint16, drawSrg); m_indexCount = 0; m_vertexCount = 0; } @@ -391,10 +400,14 @@ Vec2 AZ::FFont::GetTextSize(const char* str, const bool asciiMultiLine, const Te return Vec2(0.0f, 0.0f); } - return GetTextSizeUInternal(str, asciiMultiLine, ctx); + return GetTextSizeUInternal(m_defaultWindowContext->GetViewport(), str, asciiMultiLine, ctx); } -Vec2 AZ::FFont::GetTextSizeUInternal(const char* str, const bool asciiMultiLine, const TextDrawContext& ctx) +Vec2 AZ::FFont::GetTextSizeUInternal( + const RHI::Viewport& viewport, + const char* str, + const bool asciiMultiLine, + const TextDrawContext& ctx) { const size_t fxSize = m_effects.size(); @@ -411,12 +424,12 @@ Vec2 AZ::FFont::GetTextSizeUInternal(const char* str, const bool asciiMultiLine, Vec2 size = ctx.m_size; if (ctx.m_sizeIn800x600) { - ScaleCoord(size.x, size.y); + ScaleCoord(viewport, size.x, size.y); } // This scaling takes into account the logical size of the font relative // to any additional scaling applied (such as from "size ratio"). - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); + const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx)); float maxW = 0; float maxH = 0; @@ -733,7 +746,7 @@ uint32_t AZ::FFont::WriteTextQuadsToBuffers(SVF_P2F_C4B_T2F_F4B* verts, uint16_t return true; }; - CreateQuadsForText(x, y, z, str, asciiMultiLine, ctx, AddQuad); + CreateQuadsForText(m_defaultWindowContext->GetViewport(), x, y, z, str, asciiMultiLine, ctx, AddQuad); return numQuadsWritten; } @@ -743,7 +756,7 @@ uint32_t AZ::FFont::GetFontTextureVersion() return m_fontImageVersion; } -int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx, +int AZ::FFont::CreateQuadsForText(const RHI::Viewport& viewport, float x, float y, float z, const char* str, const bool asciiMultiLine, const TextDrawContext& ctx, AddFunction AddQuad) { int numQuads = 0; @@ -768,17 +781,17 @@ int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, co Vec2 size = ctx.m_size; if (ctx.m_sizeIn800x600) { - ScaleCoord(size.x, size.y); + ScaleCoord(viewport, size.x, size.y); } // This scaling takes into account the logical size of the font relative // to any additional scaling applied (such as from "size ratio"). - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); + const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx)); Vec2 baseXY = Vec2(x, y); // in pixels if (ctx.m_sizeIn800x600) { - ScaleCoord(baseXY.x, baseXY.y); + ScaleCoord(viewport, baseXY.x, baseXY.y); } // snap for pixel perfect rendering (better quality for text) @@ -826,7 +839,7 @@ int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, co ColorB tempColor(255, 255, 255, 255); uint32_t frameColor = tempColor.pack_abgr8888(); //note: this ends up in r,g,b,a order on little-endian machines - Vec2 textSize = GetTextSizeUInternal(str, asciiMultiLine, ctx); + Vec2 textSize = GetTextSizeUInternal(viewport, str, asciiMultiLine, ctx); float x0 = baseXY.x - 12; float y0 = baseXY.y - 6; @@ -1107,13 +1120,13 @@ int AZ::FFont::CreateQuadsForText(float x, float y, float z, const char* str, co return numQuads; } -AZ::FFont::TextScaleInfoInternal AZ::FFont::CalculateScaleInternal(const TextDrawContext& ctx) const +AZ::FFont::TextScaleInfoInternal AZ::FFont::CalculateScaleInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const { Vec2 size = GetRestoredFontSize(ctx); // in pixel if (ctx.m_sizeIn800x600) { - ScaleCoord(size.x, size.y); + ScaleCoord(viewport, size.x, size.y); } float rcpCellWidth; @@ -1196,7 +1209,7 @@ void AZ::FFont::WrapText(string& result, float maxWidth, const char* str, const maxWidth = gEnv->pRenderer->ScaleCoordX(maxWidth); } - Vec2 strSize = GetTextSizeUInternal(result.c_str(), true, ctx); + Vec2 strSize = GetTextSize(result.c_str(), true, ctx); if (strSize.x <= maxWidth) { @@ -1245,7 +1258,7 @@ void AZ::FFont::WrapText(string& result, float maxWidth, const char* str, const // Note: This is not unicode compatible, since char-width depends on surrounding context (ie, combining diacritics etc) char codepoint[5]; Unicode::Convert(codepoint, ch); - curCharWidth = GetTextSizeUInternal(codepoint, true, ctx).x; + curCharWidth = GetTextSize(codepoint, true, ctx).x; // keep track of spaces // they are good for splitting the string @@ -1425,7 +1438,12 @@ void AZ::FFont::AddCharsToFontTexture(const char* chars, int glyphSizeX, int gly Vec2 AZ::FFont::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph, const TextDrawContext& ctx) const { - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); + return GetKerningInternal(m_defaultWindowContext->GetViewport(), leftGlyph, rightGlyph, ctx); +} + +Vec2 AZ::FFont::GetKerningInternal(const RHI::Viewport& viewport, uint32_t leftGlyph, uint32_t rightGlyph, const TextDrawContext& ctx) const +{ + const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx)); return m_fontTexture->GetKerning(leftGlyph, rightGlyph) * scaleInfo.scale.x; } @@ -1436,12 +1454,18 @@ float AZ::FFont::GetAscender(const TextDrawContext& ctx) const float AZ::FFont::GetBaseline(const TextDrawContext& ctx) const { - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); + return GetBaselineInternal(m_defaultWindowContext->GetViewport(), ctx); +} + +float AZ::FFont::GetBaselineInternal(const RHI::Viewport& viewport, const TextDrawContext& ctx) const +{ + const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(viewport, ctx)); // Calculate baseline the same way as the font renderer which uses the glyph height * size ratio. // Adding 1 because FontTexture always adds 1 to the char height in GetTextureCoord return (round(m_fontTexture->GetCellHeight() * GetSizeRatio()) + 1.0f) * scaleInfo.scale.y; } + bool AZ::FFont::InitTexture() { using namespace AZ; @@ -1565,14 +1589,8 @@ Vec2 AZ::FFont::GetRestoredFontSize(const TextDrawContext& ctx) const return Vec2(ctx.m_size.x * restoringScale, ctx.m_size.y * restoringScale); } -void AZ::FFont::ScaleCoord(float& x, float& y) const +void AZ::FFont::ScaleCoord(const RHI::Viewport& viewport, float& x, float& y) const { - if (!m_windowContext) - { - return; - } - - const RHI::Viewport& viewport = m_windowContext->GetViewport(); float width = viewport.m_maxX - viewport.m_minX; float height = viewport.m_maxY - viewport.m_minY; @@ -1580,11 +1598,161 @@ void AZ::FFont::ScaleCoord(float& x, float& y) const y *= height / WindowScaleHeight; } + void AZ::FFont::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene) { InitFont(); } +static void SetCommonContextFlags(AZ::TextDrawContext& ctx, const AzFramework::TextDrawParameters& params) +{ + if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Center) + { + ctx.m_drawTextFlags |= eDrawText_Center; + } + + if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Right) + { + ctx.m_drawTextFlags |= eDrawText_Right; + } + + if (params.m_vAlign == AzFramework::TextVerticalAlignment::Center) + { + ctx.m_drawTextFlags |= eDrawText_CenterV; + } + + if (params.m_vAlign == AzFramework::TextVerticalAlignment::Bottom) + { + ctx.m_drawTextFlags |= eDrawText_Bottom; + } + + if (params.m_monospace) + { + ctx.m_drawTextFlags |= eDrawText_Monospace; + } + + if (params.m_depthTest) + { + ctx.m_drawTextFlags |= eDrawText_DepthTest; + } + + if (params.m_virtual800x600ScreenSize) + { + ctx.m_drawTextFlags |= eDrawText_800x600; + } + + if (!params.m_scaleWithWindow) + { + ctx.m_drawTextFlags |= eDrawText_FixedSize; + } +} + +void AZ::FFont::DrawScreenAlignedText2d( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) +{ + if (params.m_drawViewportId == AzFramework::InvalidViewportId || + string.empty()) + { + return; + } + + //Code mostly duplicated from CRenderer::Draw2dTextWithDepth + float posX = params.m_position.GetX(); + float posY = params.m_position.GetY(); + AZ::RPI::ViewportContext* viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId).get(); + const AZ::RHI::Viewport& viewport = viewportContext->GetWindowContext()->GetViewport(); + if (params.m_virtual800x600ScreenSize) + { + posX *= WindowScaleWidth / (viewport.m_maxX - viewport.m_minX); + posY *= WindowScaleHeight / (viewport.m_maxY - viewport.m_minY); + } + TextDrawContext ctx; + ctx.SetBaseState(GS_NODEPTHTEST); + ctx.SetColor(AZColorToLYColorF(params.m_color)); + ctx.SetCharWidthScale((params.m_monospace || params.m_scaleWithWindow) ? 0.5f : 1.0f); + ctx.EnableFrame(false); + ctx.SetProportional(!params.m_monospace && params.m_scaleWithWindow); + ctx.SetSizeIn800x600(params.m_scaleWithWindow && params.m_virtual800x600ScreenSize); + ctx.SetSize(AZVec2ToLYVec2(UiDraw_TextSizeFactor * params.m_scale)); + if (params.m_monospace || !params.m_scaleWithWindow) + { + ScaleCoord(viewport, posX, posY); + } + + if (params.m_hAlign != AzFramework::TextHorizontalAlignment::Left || + params.m_vAlign != AzFramework::TextVerticalAlignment::Top) + { + Vec2 textSize = GetTextSizeUInternal(viewport, string.data(), params.m_multiline, ctx); + + // If we're using virtual 800x600 coordinates, convert the text size from + // pixels to that before using it as an offset. + if (ctx.m_sizeIn800x600) + { + float width = 1.0f; + float height = 1.0f; + ScaleCoord(viewport, width, height); + textSize.x /= width; + textSize.y /= height; + } + + if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Center) + { + posX -= textSize.x * 0.5f; + } + else if (params.m_hAlign == AzFramework::TextHorizontalAlignment::Right) + { + posX -= textSize.x; + } + + if (params.m_vAlign == AzFramework::TextVerticalAlignment::Center) + { + posY -= textSize.y * 0.5f; + } + else if (params.m_vAlign == AzFramework::TextVerticalAlignment::Bottom) + { + posY -= textSize.y; + } + } + SetCommonContextFlags(ctx, params); + ctx.m_drawTextFlags |= eDrawText_2D; + + DrawStringUInternal( + viewport, + viewportContext, + posX, + posY, + params.m_position.GetZ(), // Z + string.data(), + params.m_multiline, + ctx + ); +} + +void AZ::FFont::DrawScreenAlignedText3d( + const AzFramework::TextDrawParameters& params, + const AZStd::string_view& string) +{ + if (params.m_drawViewportId == AzFramework::InvalidViewportId || + string.empty()) + { + return; + } + AZ::RPI::ViewportContext* viewportContext = AZ::Interface::Get()->GetViewportContextById(params.m_drawViewportId).get(); + AZ::RPI::ViewPtr currentView = viewportContext->GetDefaultView(); + if (!currentView) + { + return; + } + AZ::Vector3 positionNDC = AzFramework::WorldToScreenNDC( + params.m_position, + currentView->GetViewToWorldMatrix(), + currentView->GetViewToClipMatrix() + ); + AzFramework::TextDrawParameters param2d = params; + param2d.m_position = positionNDC; + DrawScreenAlignedText2d(param2d, string); +} -#endif +#endif //USE_NULLFONT_ALWAYS diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h index 857e795257..fe40cabc12 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h @@ -73,6 +73,9 @@ namespace AZ bool RequiresShapeComponent() const; + //! Returns true if the light type is anything other than unknown. + bool LightTypeIsSelected() const; + //! Returns true if m_attenuationRadiusMode is set to LightAttenuationRadiusMode::Automatic bool IsAttenuationRadiusModeAutomatic() const; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp index 2afa6514cd..2dc439b846 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp @@ -73,6 +73,11 @@ namespace AZ || m_lightType == LightType::Polygon; } + bool AreaLightComponentConfig::LightTypeIsSelected() const + { + return m_lightType != LightType::Unknown; + } + bool AreaLightComponentConfig::IsAttenuationRadiusModeAutomatic() const { return m_attenuationRadiusMode == LightAttenuationRadiusMode::Automatic; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index 1bbc2a411e..c1c957ed4c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -234,6 +234,11 @@ namespace AZ::Render !(m_configuration.m_lightType == AreaLightComponentConfig::LightType::Polygon && m_configuration.m_shapeType != PoylgonShapeTypeId), "The light type is a polygon, but the shape component is not."); } + + if (m_configuration.m_lightType == AreaLightComponentConfig::LightType::SimpleSpot) + { + m_configuration.m_enableShutters = true; // Simple spot always has shutters. + } } void AreaLightComponentController::ConfigurationChanged() @@ -620,6 +625,10 @@ namespace AZ::Render break; } } + if (m_lightShapeDelegate) + { + m_lightShapeDelegate->SetConfig(&m_configuration); + } } } // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp index 32b6a9f0b7..2758da2b38 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -51,14 +51,52 @@ namespace AZ::Render return m_shapeBus->GetRadius() * GetTransform().GetScale().GetMaxElement(); } - void DiskLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + void DiskLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& /*color*/, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const { if (isSelected) { - debugDisplay.SetColor(color); - - // Draw a disk for the attenuation radius - debugDisplay.DrawWireSphere(transform.GetTranslation(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity)); + debugDisplay.PushMatrix(transform); + float radius = GetConfig()->m_attenuationRadius; + + if (GetConfig()->m_enableShutters) + { + + float innerRadians = DegToRad(GetConfig()->m_innerShutterAngleDegrees); + float outerRadians = DegToRad(GetConfig()->m_outerShutterAngleDegrees); + + // Draw a cone using the cone angle and attenuation radius + innerRadians = GetMin(innerRadians, outerRadians); + float coneRadiusInner = sin(innerRadians) * radius; + float coneHeightInner = cos(innerRadians) * radius; + float coneRadiusOuter = sin(outerRadians) * radius; + float coneHeightOuter = cos(outerRadians) * radius; + + auto DrawConicalFrustum = [&debugDisplay](uint32_t numRadiusLines, float topRadius, float bottomRadius, float height, float brightness) + { + debugDisplay.SetColor(Color(brightness, brightness, brightness, 1.0f)); + debugDisplay.DrawWireDisk(Vector3(0.0, 0.0, height), Vector3::CreateAxisZ(), bottomRadius); + + for (uint32_t i = 0; i < numRadiusLines; ++i) + { + float radiusLineAngle = float(i) / numRadiusLines * Constants::TwoPi; + debugDisplay.DrawLine( + Vector3(cos(radiusLineAngle) * topRadius, sin(radiusLineAngle) * topRadius, 0), + Vector3(cos(radiusLineAngle) * bottomRadius, sin(radiusLineAngle) * bottomRadius, height) + ); + } + }; + + DrawConicalFrustum(16, m_shapeBus->GetRadius(), m_shapeBus->GetRadius() + coneRadiusInner, coneHeightInner, 1.0f); + DrawConicalFrustum(16, m_shapeBus->GetRadius(), m_shapeBus->GetRadius() + coneRadiusOuter, coneHeightOuter, 0.65f); + + } + else + { + debugDisplay.DrawWireDisk(Vector3::CreateZero(), Vector3::CreateAxisZ(), radius); + debugDisplay.DrawArc(Vector3::CreateZero(), radius, 90.0f, 180.0f, -3.0f, 0); + debugDisplay.DrawArc(Vector3::CreateZero(), radius, 0.0f, 180.0f, 3.0f, 1); + } + debugDisplay.PopMatrix(); } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index bdff97b48e..6a07a8a737 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -67,50 +67,56 @@ namespace AZ editContext->Class( "AreaLightComponentConfig", "") ->ClassElement(Edit::ClassElements::EditorData, "") - ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_lightType, "Light Type", "Which type of light this component represents.") - ->EnumAttribute(AreaLightComponentConfig::LightType::Unknown, "Choose a Light Type") - ->EnumAttribute(AreaLightComponentConfig::LightType::Sphere, "Point (Sphere)") - ->EnumAttribute(AreaLightComponentConfig::LightType::SimplePoint, "Point (Simple)") - ->EnumAttribute(AreaLightComponentConfig::LightType::SpotDisk, "Spot (Disk)") - ->EnumAttribute(AreaLightComponentConfig::LightType::SimpleSpot, "Spot (Simple)") + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_lightType, "Light type", "Which type of light this component represents.") + ->EnumAttribute(AreaLightComponentConfig::LightType::Unknown, "Choose a light type") + ->EnumAttribute(AreaLightComponentConfig::LightType::Sphere, "Point (sphere)") + ->EnumAttribute(AreaLightComponentConfig::LightType::SimplePoint, "Point (simple punctual)") + ->EnumAttribute(AreaLightComponentConfig::LightType::SpotDisk, "Spot (disk)") + ->EnumAttribute(AreaLightComponentConfig::LightType::SimpleSpot, "Spot (simple punctual)") ->EnumAttribute(AreaLightComponentConfig::LightType::Capsule, "Capsule") ->EnumAttribute(AreaLightComponentConfig::LightType::Quad, "Quad") ->EnumAttribute(AreaLightComponentConfig::LightType::Polygon, "Polygon") ->DataElement(Edit::UIHandlers::Color, &AreaLightComponentConfig::m_color, "Color", "Color of the light") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->Attribute("ColorEditorConfiguration", RPI::ColorUtils::GetLinearRgbEditorConfig()) - ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_intensityMode, "Intensity Mode", "Allows specifying which photometric unit to work in.") + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_intensityMode, "Intensity mode", "Allows specifying which photometric unit to work in.") ->Attribute(AZ::Edit::Attributes::EnumValues, &AreaLightComponentConfig::GetValidPhotometricUnits) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_intensity, "Intensity", "Intensity of the light in the set photometric unit.") ->Attribute(Edit::Attributes::Min, &AreaLightComponentConfig::GetIntensityMin) ->Attribute(Edit::Attributes::Max, &AreaLightComponentConfig::GetIntensityMax) ->Attribute(Edit::Attributes::SoftMin, &AreaLightComponentConfig::GetIntensitySoftMin) ->Attribute(Edit::Attributes::SoftMax, &AreaLightComponentConfig::GetIntensitySoftMax) ->Attribute(Edit::Attributes::Suffix, &AreaLightComponentConfig::GetIntensitySuffix) - ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_lightEmitsBothDirections, "Both Directions", "Whether light should emit from both sides of the surface or just the front") + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) + ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_lightEmitsBothDirections, "Both directions", "Whether light should emit from both sides of the surface or just the front") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsBothDirections) - ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_useFastApproximation, "Fast Approximation", "Whether the light should use the default high quality linear transformed cosine technique or a faster approximation.") + ->DataElement(Edit::UIHandlers::CheckBox, &AreaLightComponentConfig::m_useFastApproximation, "Fast approximation", "Whether the light should use the default high quality linear transformed cosine technique or a faster approximation.") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsFastApproximation) - ->ClassElement(Edit::ClassElements::Group, "Attenuation Radius") + ->ClassElement(Edit::ClassElements::Group, "Attenuation radius") ->Attribute(Edit::Attributes::AutoExpand, true) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_attenuationRadiusMode, "Mode", "Controls whether the attenation radius is calculated automatically or set explicitly.") ->EnumAttribute(LightAttenuationRadiusMode::Automatic, "Automatic") ->EnumAttribute(LightAttenuationRadiusMode::Explicit, "Explicit") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_attenuationRadius, "Radius", "The distance at which this light no longer has an affect.") ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsAttenuationRadiusModeAutomatic) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::LightTypeIsSelected) ->ClassElement(Edit::ClassElements::Group, "Shutters") ->Attribute(Edit::Attributes::AutoExpand, true) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) - ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShutters, "Enable Shutters", "Restrict the light to a specific beam angle depending on shape.") + ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShutters, "Enable shutters", "Restrict the light to a specific beam angle depending on shape.") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::ShuttersMustBeEnabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_innerShutterAngleDegrees, "Inner Angle", "The inner angle of the shutters where the light beam begins to be occluded.") + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_innerShutterAngleDegrees, "Inner angle", "The inner angle of the shutters where the light beam begins to be occluded.") ->Attribute(Edit::Attributes::Min, 0.0f) ->Attribute(Edit::Attributes::Max, 180.0f) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShuttersDisabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_outerShutterAngleDegrees, "Outer Angle", "The outer angle of the shutters where the light beam is completely occluded.") + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_outerShutterAngleDegrees, "Outer angle", "The outer angle of the shutters where the light beam is completely occluded.") ->Attribute(Edit::Attributes::Min, 0.0f) ->Attribute(Edit::Attributes::Max, 180.0f) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters) @@ -119,9 +125,9 @@ namespace AZ ->ClassElement(Edit::ClassElements::Group, "Shadows") ->Attribute(Edit::Attributes::AutoExpand, true) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShadow, "Enable Shadow", "Enable shadow for the light") + ->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShadow, "Enable shadow", "Enable shadow for the light") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowmapMaxSize, "Shadowmap Size", "Width/Height of shadowmap") + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowmapMaxSize, "Shadowmap size", "Width and height of shadowmap") ->EnumAttribute(ShadowmapSize::Size256, " 256") ->EnumAttribute(ShadowmapSize::Size512, " 512") ->EnumAttribute(ShadowmapSize::Size1024, "1024") @@ -129,13 +135,13 @@ namespace AZ ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) - ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowFilterMethod, "Shadow Filter Method", + ->DataElement(Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_shadowFilterMethod, "Shadow filter method", "Filtering method of edge-softening of shadows.\n" " None: no filtering\n" - " PCF: Percentage-Closer Filtering\n" - " ESM: Exponential Shadow Maps\n" + " PCF: Percentage-closer Filtering\n" + " ESM: Exponential shadow maps\n" " ESM+PCF: ESM with a PCF fallback\n" - "For BehaviorContext (or TrackView), None=0, PCF=1, ESM=2, ESM+PCF=3") + "For BehaviorContext (or track view), None=0, PCF=1, ESM=2, ESM+PCF=3") ->EnumAttribute(ShadowFilterMethod::None, "None") ->EnumAttribute(ShadowFilterMethod::Pcf, "PCF") ->EnumAttribute(ShadowFilterMethod::Esm, "ESM") @@ -143,7 +149,7 @@ namespace AZ ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShadowsDisabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_boundaryWidthInDegrees, "Softening Boundary Width", + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_boundaryWidthInDegrees, "Softening boundary width", "Width of the boundary between shadowed area and lit one. " "Units are in degrees. " "If this is 0, softening edge is disabled.") @@ -152,26 +158,27 @@ namespace AZ ->Attribute(Edit::Attributes::Suffix, " deg") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsPcfBoundarySearchDisabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_predictionSampleCount, "Prediction Sample Count", + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_predictionSampleCount, "Prediction sample count", "Sample Count for prediction of whether the pixel is on the boundary. Specific to PCF and ESM+PCF.") ->Attribute(Edit::Attributes::Min, 4) ->Attribute(Edit::Attributes::Max, 16) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsPcfBoundarySearchDisabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_filteringSampleCount, "Filtering Sample Count", + ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_filteringSampleCount, "Filtering sample count", "It is used only when the pixel is predicted to be on the boundary. Specific to PCF and ESM+PCF.") ->Attribute(Edit::Attributes::Min, 4) ->Attribute(Edit::Attributes::Max, 64) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) ->DataElement( - Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_pcfMethod, "Pcf Method", - "Type of Pcf to use.\n" + Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_pcfMethod, "Pcf method", + "Type of PCF to use.\n" " Boundary search: do several taps to first determine if we are on a shadow boundary\n" " Bicubic: a smooth, fixed-size kernel \n") - ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary Search") + ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search") ->EnumAttribute(PcfMethod::Bicubic, "Bicubic") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) + ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled); ; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h index 4cf94c1a58..da221341c3 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -40,6 +41,8 @@ namespace AZ LightDelegateBase(EntityId entityId, bool isVisible); virtual ~LightDelegateBase(); + void SetConfig(const AreaLightComponentConfig* config) override; + // LightDelegateInterface overrides... void SetChroma(const AZ::Color& chroma) override; void SetIntensity(float intensity) override; @@ -66,6 +69,7 @@ namespace AZ // Trivial getters FeatureProcessorType* GetFeatureProcessor() const { return m_featureProcessor; }; + const AreaLightComponentConfig* GetConfig() const { return m_componentConfig; }; typename FeatureProcessorType::LightHandle GetLightHandle() const { return m_lightHandle; }; const AZ::Transform& GetTransform() const { return m_transform; }; bool GetShuttersEnabled() { return m_shuttersEnabled; }; @@ -81,6 +85,7 @@ namespace AZ private: FeatureProcessorType* m_featureProcessor = nullptr; typename FeatureProcessorType::LightHandle m_lightHandle; + const AreaLightComponentConfig* m_componentConfig = nullptr; LmbrCentral::ShapeComponentRequests* m_shapeBus; AZ::Transform m_transform; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl index ee4a29f1b0..406df42547 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.inl @@ -59,6 +59,12 @@ namespace AZ m_featureProcessor->SetRgbIntensity(m_lightHandle, m_photometricValue.GetCombinedRgb()); } } + + template + void LightDelegateBase::SetConfig(const AreaLightComponentConfig* config) + { + m_componentConfig = config; + } template void LightDelegateBase::SetChroma(const AZ::Color& color) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h index 110a7d73ad..b3f5fb6014 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h @@ -33,6 +33,9 @@ namespace AZ { public: virtual ~LightDelegateInterface() {}; + + //! Sets the area light component config so delegates don't have to cache the same data locally. + virtual void SetConfig(const AreaLightComponentConfig* config) = 0; //! Sets the color of the light independent of light intensity. The color is a mask on the total light intensity. virtual void SetChroma(const AZ::Color& chroma) = 0; //! Sets the light intensity diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp index 255f527557..705a71571a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.cpp @@ -44,15 +44,40 @@ namespace AZ::Render { GetFeatureProcessor()->SetConeAngles(GetLightHandle(), DegToRad(innerAngleDegrees), DegToRad(outerAngleDegrees)); } - - void SimpleSpotLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& color, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const + + void SimpleSpotLightDelegate::DrawDebugDisplay(const Transform& transform, const Color& /*color*/, AzFramework::DebugDisplayRequests& debugDisplay, bool isSelected) const { if (isSelected) { - debugDisplay.SetColor(color); + float innerRadians = DegToRad(GetConfig()->m_innerShutterAngleDegrees); + float outerRadians = DegToRad(GetConfig()->m_outerShutterAngleDegrees); + float radius = GetConfig()->m_attenuationRadius; + + // Draw a cone using the cone angle and attenuation radius + innerRadians = GetMin(innerRadians, outerRadians); + float coneRadiusInner = sin(innerRadians) * radius; + float coneHeightInner = cos(innerRadians) * radius; + float coneRadiusOuter = sin(outerRadians) * radius; + float coneHeightOuter = cos(outerRadians) * radius; + + debugDisplay.PushMatrix(transform); + + auto DrawCone = [&debugDisplay](uint32_t numRadiusLines, float radius, float height, float brightness) + { + debugDisplay.SetColor(Color(brightness, brightness, brightness, 1.0f)); + debugDisplay.DrawWireDisk(Vector3(0.0, 0.0, height), Vector3::CreateAxisZ(), radius); + + for (uint32_t i = 0; i < numRadiusLines; ++i) + { + float radiusLineAngle = float(i) / numRadiusLines * Constants::TwoPi; + debugDisplay.DrawLine(Vector3::CreateZero(), Vector3(cos(radiusLineAngle) * radius, sin(radiusLineAngle) * radius, height)); + } + }; + + DrawCone(16, coneRadiusInner, coneHeightInner, 1.0f); + DrawCone(16, coneRadiusOuter, coneHeightOuter, 0.65f); - // Draw a cone for the cone angle and attenuation radius - debugDisplay.DrawCone(transform.GetTranslation(), transform.GetBasisX(), CalculateAttenuationRadius(AreaLightComponentConfig::CutoffIntensity), false); + debugDisplay.PopMatrix(); } } } // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h index 66569fc27c..28359daaef 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h @@ -25,6 +25,8 @@ namespace AZ class SimpleSpotLightDelegate final : public LightDelegateBase { + using Base = LightDelegateBase; + public: SimpleSpotLightDelegate(EntityId entityId, bool isVisible); @@ -34,9 +36,9 @@ namespace AZ float GetSurfaceArea() const override; float GetEffectiveSolidAngle() const override { return PhotometricValue::DirectionalEffectiveSteradians; } void SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) override; + private: virtual void HandleShapeChanged(); - }; } // namespace Render diff --git a/Gems/AtomLyIntegration/CryRenderAtomShim/AtomShim_RenderAuxGeom.cpp b/Gems/AtomLyIntegration/CryRenderAtomShim/AtomShim_RenderAuxGeom.cpp index 093e068e2a..955b240514 100644 --- a/Gems/AtomLyIntegration/CryRenderAtomShim/AtomShim_RenderAuxGeom.cpp +++ b/Gems/AtomLyIntegration/CryRenderAtomShim/AtomShim_RenderAuxGeom.cpp @@ -519,8 +519,8 @@ void CAtomShimRenderAuxGeom::DrawQuad(float width, float height, const Matrix34& if (auto auxGeom = AZ::RPI::AuxGeomFeatureProcessorInterface::GetDrawQueueForScene(defaultScene)) { AZ::RPI::AuxGeomDraw::DrawStyle drawStyle = drawShaded ? AZ::RPI::AuxGeomDraw::DrawStyle::Shaded : AZ::RPI::AuxGeomDraw::DrawStyle::Solid; - AZ::Transform transform = LYTransformToAZTransform(matWorld); - auxGeom->DrawQuad(width, height, transform, LYColorBToAZColor(col), drawStyle, m_drawArgs.m_depthTest); + AZ::Matrix3x4 local2World = LYTransformToAZMatrix3x4(matWorld); + auxGeom->DrawQuad(width, height, local2World, LYColorBToAZColor(col), drawStyle, m_drawArgs.m_depthTest); } } diff --git a/cmake/FindTarget.cmake.in b/cmake/FindTarget.cmake.in new file mode 100644 index 0000000000..7d0129d05a --- /dev/null +++ b/cmake/FindTarget.cmake.in @@ -0,0 +1,45 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +# Generated by O3DE + +include(FindPackageHandleStandardArgs) + +ly_add_target( + +NAME @NAME_PLACEHOLDER@ UNKNOWN IMPORTED + +@NAMESPACE_PLACEHOLDER@ + +@INCLUDE_DIRECTORIES_PLACEHOLDER@ + +@BUILD_DEPENDENCIES_PLACEHOLDER@ + +@RUNTIME_DEPENDENCIES_PLACEHOLDER@ + +@COMPILE_DEFINITIONS_PLACEHOLDER@ +) + +# The below if was generated from if (NOT HEADER_ONLY_PLACEHOLDER) +# HEADER_ONLY_PLACEHOLDER evaluates to TRUE or FALSE +if (NOT @HEADER_ONLY_PLACEHOLDER@) + # Load information for each installed configuration. + foreach(config @ALL_CONFIGS@) + set(@NAME_PLACEHOLDER@_${config}_FOUND FALSE) + include("${LY_ROOT_FOLDER}/cmake_autogen/@NAME_PLACEHOLDER@/@NAME_PLACEHOLDER@_${config}.cmake") + endforeach() + + find_package_handle_standard_args(@NAME_PLACEHOLDER@ + "Could not find package @NAME_PLACEHOLDER@" + @TARGET_CONFIG_FOUND_VARS_PLACEHOLDER@) +else() + set(@NAME_PLACEHOLDER@_FOUND TRUE) +endif() \ No newline at end of file diff --git a/cmake/Findo3de.cmake b/cmake/Findo3de.cmake index 30246ebd4b..0b4d0b75e7 100644 --- a/cmake/Findo3de.cmake +++ b/cmake/Findo3de.cmake @@ -27,24 +27,19 @@ if(json_error) message(FATAL_ERROR "Unable to read key 'engine_name' from '${current_path}/../engine.json', error: ${json_error}") endif() -if(NOT this_engine_name STREQUAL LY_ENGINE_NAME_TO_USE) - set(o3de_FOUND FALSE) - set(o3de_NOT_FOUND_MESSAGE) - find_package_handle_standard_args(o3de - "Could not find an engine with matching ${LY_ENGINE_NAME_TO_USE}" - o3de_FOUND - ) - return() +set(found_matching_engine FALSE) +if(this_engine_name STREQUAL LY_ENGINE_NAME_TO_USE) + set(found_matching_engine TRUE) endif() +find_package_handle_standard_args(o3de + "Could not find an engine with matching ${LY_ENGINE_NAME_TO_USE}" + found_matching_engine +) + macro(o3de_initialize) + set(INSTALLED_ENGINE FALSE) set(LY_PROJECTS ${CMAKE_CURRENT_LIST_DIR}) o3de_current_file_path(current_path) add_subdirectory(${current_path}/.. o3de) -endmacro() - -message(STATUS "Found ${this_engine_name} in ${current_path}") -set(o3de_FOUND FALSE) -find_package_handle_standard_args(o3de - o3de_FOUND -) \ No newline at end of file +endmacro() \ No newline at end of file diff --git a/cmake/Findo3de.cmake.in b/cmake/Findo3de.cmake.in new file mode 100644 index 0000000000..7ecb73e874 --- /dev/null +++ b/cmake/Findo3de.cmake.in @@ -0,0 +1,36 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +# Generated by O3DE + +include(FindPackageHandleStandardArgs) + +# This will be called from within the installed engine's CMakeLists.txt +macro(ly_find_o3de_packages) + @FIND_PACKAGES_PLACEHOLDER@ + find_package(LauncherGenerator) +endmacro() + + +function(o3de_current_file_path path) + set(${path} ${CMAKE_CURRENT_FUNCTION_LIST_DIR} PARENT_SCOPE) +endfunction() + + +# We are using the engine's CMakeLists.txt to handle initialization/importing targets +# Since this is external to the project's source, we need to specify an output directory +# even though we don't build +macro(o3de_initialize) + set(INSTALLED_ENGINE TRUE) + set(LY_PROJECTS ${CMAKE_SOURCE_DIR}) + o3de_current_file_path(current_path) + add_subdirectory(${current_path}/.. o3de) +endmacro() \ No newline at end of file diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 9164105f3a..7ac9a3afa8 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -13,13 +13,6 @@ #! ly_install_target: registers the target to be installed by cmake install. # # \arg:NAME name of the target -# \arg:NAMESPACE namespace declaration for this target. It will be used for IDE and dependencies -# \arg:INCLUDE_DIRECTORIES paths to the include directories -# \arg:BUILD_DEPENDENCIES list of interfaces this target depends on (could be a compilation dependency -# if the dependency is only exposing an include path, or could be a linking -# dependency is exposing a lib) -# \arg:RUNTIME_DEPENDENCIES list of dependencies this target depends on at runtime -# \arg:COMPILE_DEFINITIONS list of compilation definitions this target will use to compile function(ly_install_target ly_install_target_NAME) # All include directories marked PUBLIC or INTERFACE will be installed @@ -143,7 +136,7 @@ function(ly_generate_target_find_file) set(HEADER_ONLY_PLACEHOLDER TRUE) endif() - configure_file(${LY_ROOT_FOLDER}/cmake/FindTargetTemplate.cmake ${CMAKE_CURRENT_BINARY_DIR}/Find${ly_generate_target_find_file_NAME}.cmake @ONLY) + configure_file(${LY_ROOT_FOLDER}/cmake/FindTarget.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/Find${ly_generate_target_find_file_NAME}.cmake @ONLY) endfunction() @@ -214,7 +207,7 @@ function(ly_setup_o3de_install) string(REPLACE ";" "\n" FIND_PACKAGES_PLACEHOLDER "${find_package_list}") - configure_file(${LY_ROOT_FOLDER}/cmake/Findo3deTemplate.cmake ${CMAKE_CURRENT_BINARY_DIR}/Findo3de.cmake @ONLY) + configure_file(${LY_ROOT_FOLDER}/cmake/Findo3de.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/Findo3de.cmake @ONLY) ly_install_launcher_target_generator() From 8378f52ba6c757a2760050a02a3a31f49c80fae5 Mon Sep 17 00:00:00 2001 From: hershey5045 <43485729+hershey5045@users.noreply.github.com> Date: Fri, 16 Apr 2021 12:06:05 -0700 Subject: [PATCH 54/74] Fix bug in ShaderVariantAssetBuilder. Add cvar in MeshDrawPacket class. (#61) Fix bug in ShaderVariantAssetBuilder. Add a console variable to force root shader variant usage. --- .../Code/Source/Editor/ShaderVariantAssetBuilder.cpp | 2 +- .../Include/Atom/Feature/Mesh/MeshFeatureProcessor.h | 9 ++++++++- .../Common/Code/Source/Mesh/MeshFeatureProcessor.cpp | 5 +++++ .../RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp | 11 ++++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 034d0c7cf2..1e3c7b6759 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -162,7 +162,7 @@ namespace AZ AZStd::string expectedHigherPrecedenceFileFullPath; AzFramework::StringFunc::Path::Join(gameProjectPath, RPI::ShaderVariantTreeAsset::CommonSubFolder, expectedHigherPrecedenceFileFullPath, false /* handle directory overlap? */, false /* be case insensitive? */); AzFramework::StringFunc::Path::Join(expectedHigherPrecedenceFileFullPath.c_str(), shaderProductFileRelativePath.c_str(), expectedHigherPrecedenceFileFullPath, false /* handle directory overlap? */, false /* be case insensitive? */); - AzFramework::StringFunc::Path::ReplaceExtension(expectedHigherPrecedenceFileFullPath, AZ::RPI::ShaderVariantAsset::Extension); + AzFramework::StringFunc::Path::ReplaceExtension(expectedHigherPrecedenceFileFullPath, AZ::RPI::ShaderVariantListSourceData::Extension); AzFramework::StringFunc::Path::Normalize(expectedHigherPrecedenceFileFullPath); AZStd::string normalizedShaderVariantListFileFullPath = shaderVariantListFileFullPath; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index a595471813..7ad8bd8283 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace AZ { @@ -160,8 +161,14 @@ namespace AZ // called when reflection probes are modified in the editor so that meshes can re-evaluate their probes void UpdateMeshReflectionProbes(); - private: + void ForceRebuildDrawPackets(const AZ::ConsoleCommandContainer& arguments); + AZ_CONSOLEFUNC(MeshFeatureProcessor, + ForceRebuildDrawPackets, + AZ::ConsoleFunctorFlags::Null, + "(For Testing) Invalidates all mesh draw packets, causing them to rebuild on the next frame." + ); + MeshFeatureProcessor(const MeshFeatureProcessor&) = delete; // RPI::SceneNotificationBus::Handler overrides... diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 95bbe13586..5f39c6bc38 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -387,6 +387,11 @@ namespace AZ } } + void MeshFeatureProcessor::ForceRebuildDrawPackets([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments) + { + m_forceRebuildDrawPackets = true; + } + void MeshFeatureProcessor::OnRenderPipelineAdded(RPI::RenderPipelinePtr pipeline) { m_forceRebuildDrawPackets = true;; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp index 1e5eaab20c..d0a277304e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp @@ -17,11 +17,20 @@ #include #include #include +#include namespace AZ { namespace RPI { + AZ_CVAR(bool, + r_forceRootShaderVariantUsage, + false, + [](const bool&) { AZ::Interface::Get()->PerformCommand("MeshFeatureProcessor.ForceRebuildDrawPackets"); }, + ConsoleFunctorFlags::Null, + "(For Testing) Forces usage of root shader variant in the mesh draw packet level, ignoring any other shader variants that may exist." + ); + MeshDrawPacket::MeshDrawPacket( ModelLod& modelLod, size_t modelLodMeshIndex, @@ -187,7 +196,7 @@ namespace AZ } const ShaderVariantId finalVariantId = shaderOptions.GetShaderVariantId(); - const ShaderVariant& variant = shader->GetVariant(finalVariantId); + const ShaderVariant& variant = r_forceRootShaderVariantUsage ? shader->GetRootVariant() : shader->GetVariant(finalVariantId); Data::Instance drawSrg; if (drawSrgAsset) From 3e9c08687273700c287356117edf12ddfe80b881 Mon Sep 17 00:00:00 2001 From: jckand Date: Fri, 16 Apr 2021 14:40:44 -0500 Subject: [PATCH 55/74] LYN-2764: Replacing image asset for ImageGradient automated test --- .../Assets/ImageGradients/image_grad_test_gsi.png | 3 +++ AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png | 3 --- .../ImageGradient_ProcessedImageAssignedSuccessfully.py | 4 ++-- .../largeworlds/gradient_signal/test_ImageGradient.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 AutomatedTesting/Assets/ImageGradients/image_grad_test_gsi.png delete mode 100644 AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png diff --git a/AutomatedTesting/Assets/ImageGradients/image_grad_test_gsi.png b/AutomatedTesting/Assets/ImageGradients/image_grad_test_gsi.png new file mode 100644 index 0000000000..228aa877ce --- /dev/null +++ b/AutomatedTesting/Assets/ImageGradients/image_grad_test_gsi.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:171f38d536d7b805cc644513d22dae5552a4eef2bffb88e97e089898cf769530 +size 2126 diff --git a/AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png b/AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png deleted file mode 100644 index eab76f1f78..0000000000 --- a/AutomatedTesting/Assets/ImageGradients/lumberyard_gsi.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6388466c97009fd3993e5d3b59a2b0961f623c6becbd0a12a0a5eb7bd8da5d4e -size 12302 diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py index 6b4a8bf17c..ccc8c3f101 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py @@ -77,13 +77,13 @@ class TestImageGradient(EditorTestHelper): # 3) Assign the processed gradient signal image as the Image Gradient's image asset and verify success # First, check for the base image in the workspace - base_image = "lumberyard_gsi.png" + base_image = "image_grad_test_gsi.png" base_image_path = os.path.join("AutomatedTesting", "Assets", "ImageGradients", base_image) if os.path.isfile(base_image_path): print(f"{base_image} was found in the workspace") # Next, assign the processed image to the Image Gradient's Image Asset property - processed_image_path = os.path.join("Assets", "ImageGradients", "lumberyard_gsi.gradimage") + processed_image_path = os.path.join("Assets", "ImageGradients", "image_grad_test_gsi.gradimage") asset_id = asset.AssetCatalogRequestBus(bus.Broadcast, "GetAssetIdByPath", processed_image_path, math.Uuid(), False) hydra.get_set_test(image_gradient_entity, 0, "Configuration|Image Asset", asset_id) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py index 11712f8b65..8fc582c2c8 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py @@ -57,7 +57,7 @@ class TestImageGradientRequiresShape(object): "Entity has a Image Gradient component", "Entity has a Gradient Transform Modifier component", "Entity has a Box Shape component", - "lumberyard_gsi.png was found in the workspace", + "image_grad_test_gsi.png was found in the workspace", "Entity Configuration|Image Asset: SUCCESS", "ImageGradient_ProcessedImageAssignedSucessfully: result=SUCCESS", ] From 854167c68e56a0a7ba2dc210cfd84b167ac34a0a Mon Sep 17 00:00:00 2001 From: guthadam Date: Fri, 16 Apr 2021 14:53:31 -0500 Subject: [PATCH 56/74] Ensure default material selection works when dialog is opened https://jira.agscollab.com/browse/ATOM-15267 --- .../CreateMaterialDialog.cpp | 29 ++++++++++++++----- .../CreateMaterialDialog.h | 1 + 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp index 20d1b587b5..76aee99e52 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.cpp @@ -60,13 +60,17 @@ namespace MaterialEditor AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, nullptr, enumerateCB, nullptr); //Update the material type file info whenever the combo box selection changes - QObject::connect(m_ui->m_materialTypeComboBox, static_cast(&QComboBox::currentIndexChanged), m_ui->m_materialTypeComboBox, [this](int index) { - QVariant data = m_ui->m_materialTypeComboBox->itemData(index); - m_materialTypeFileInfo = QFileInfo(data.toString()); - }); + QObject::connect(m_ui->m_materialTypeComboBox, static_cast(&QComboBox::currentIndexChanged), this, [this]() { UpdateMaterialTypeSelection(); }); + QObject::connect(m_ui->m_materialTypeComboBox, &QComboBox::currentTextChanged, this, [this]() { UpdateMaterialTypeSelection(); }); - //Select StandardPBR by default but we will later data drive this with editor settings - m_ui->m_materialTypeComboBox->setCurrentText("StandardPBR"); + // Select StandardPBR by default but we will later data drive this with editor settings + const int index = m_ui->m_materialTypeComboBox->findText("StandardPBR"); + if (index >= 0) + { + m_ui->m_materialTypeComboBox->setCurrentIndex(index); + } + + UpdateMaterialTypeSelection(); } void CreateMaterialDialog::InitMaterialFileSelection() @@ -88,15 +92,24 @@ namespace MaterialEditor m_materialFileInfo.absoluteFilePath(), QString("Material (*.material)")); - //Reject empty or invalid filenames which indicate user cancellation + // Reject empty or invalid filenames which indicate user cancellation if (!fileInfo.absoluteFilePath().isEmpty()) { m_materialFileInfo = fileInfo; m_ui->m_materialFilePicker->setText(m_materialFileInfo.fileName()); } - }); + }); } + void CreateMaterialDialog::UpdateMaterialTypeSelection() + { + const int index = m_ui->m_materialTypeComboBox->currentIndex(); + if (index >= 0) + { + const QVariant itemData = m_ui->m_materialTypeComboBox->itemData(index); + m_materialTypeFileInfo = QFileInfo(itemData.toString()); + } + } } // namespace MaterialEditor #include diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h index bf39671343..54d7c2175d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/CreateMaterialDialog/CreateMaterialDialog.h @@ -36,5 +36,6 @@ namespace MaterialEditor QScopedPointer m_ui; void InitMaterialTypeSelection(); void InitMaterialFileSelection(); + void UpdateMaterialTypeSelection(); }; } // namespace MaterialEditor From c98a1cebaaa613b3ea1634ce7f4e3269691a5ca7 Mon Sep 17 00:00:00 2001 From: alexpete Date: Fri, 16 Apr 2021 13:33:16 -0700 Subject: [PATCH 57/74] GetDefaultView needs full View definition --- .../Code/Source/AtomDebugDisplayViewportInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index 4cab7b8869..77f15284f1 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -17,8 +17,8 @@ #include #include #include - #include +#include #include #include From 41981412c5a2dcd9065725399ed465fa18301164 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 16 Apr 2021 13:56:46 -0700 Subject: [PATCH 58/74] SPEC-6370 Mark a build as "NOT_BUILT" if it didnt build anything --- scripts/build/Jenkins/Jenkinsfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 3d9ddd0411..f77c139342 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -469,6 +469,8 @@ try { return } + def someBuildHappened = false + // Build and Post-Build Testing Stage def buildConfigs = [:] @@ -479,6 +481,7 @@ try { def envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) envVars['JOB_NAME'] = "${branchName}_${platform.key}_${build_job.key}" // backwards compatibility, some scripts rely on this def nodeLabel = envVars['NODE_LABEL'] + someBuildHappened = true buildConfigs["${platform.key} [${build_job.key}]"] = { node("${nodeLabel}") { @@ -538,6 +541,9 @@ try { echo 'All builds successful' } + if (!someBuildHappened) { + currentBuild.result = 'NOT_BUILT' + } } catch(Exception e) { error "Exception: ${e}" From 0db617f4d849d71bc77aec41731e0f1d210c137d Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Fri, 16 Apr 2021 14:19:45 -0700 Subject: [PATCH 59/74] Make EMotionFX shaders load from the Shaders directory, instead of prepending "Shaders" to all filenames (#56) Because the `shaderPath` variable is used as a base directory, it needs to end with the directory separator. Otherwise the parts before the data dir become a file prefix used when loading all shaders. Attempts to load "Line_VS.glsl" from "Shaders/" end up instead trying to load "ShadersLine_VS.glsl". --- .../Rendering/OpenGL2/Source/GLRenderUtil.cpp | 10 +++- .../Rendering/OpenGL2/Source/GLSLShader.cpp | 20 ++++---- .../Rendering/OpenGL2/Source/GLSLShader.h | 7 +-- .../OpenGL2/Source/GraphicsManager.cpp | 47 +++++++------------ .../OpenGL2/Source/GraphicsManager.h | 19 ++++---- .../OpenGL2/Source/PostProcessShader.cpp | 3 +- .../OpenGL2/Source/PostProcessShader.h | 3 +- .../Rendering/OpenGL2/Source/ShaderCache.cpp | 6 +-- .../Rendering/OpenGL2/Source/shadercache.h | 4 +- .../OpenGLRender/OpenGLRenderPlugin.cpp | 2 +- 10 files changed, 59 insertions(+), 62 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp index 3ef3908271..b8b4843555 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLRenderUtil.cpp @@ -131,8 +131,14 @@ namespace RenderGL void GLRenderUtil::Validate() { - mLineShader->Validate(); - mMeshShader->Validate(); + if (mLineShader) + { + mLineShader->Validate(); + } + if (mMeshShader) + { + mMeshShader->Validate(); + } } // destroy the allocated memory diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp index 54b926c4fa..b11c3cb955 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp @@ -116,12 +116,12 @@ namespace RenderGL } - bool GLSLShader::CompileShader(const GLenum type, unsigned int* outShader, const char* filename) + bool GLSLShader::CompileShader(const GLenum type, unsigned int* outShader, AZ::IO::PathView filename) { - QFile file(filename); + QFile file(QString::fromUtf8(filename.Native().data(), aznumeric_caster(filename.Native().size()))); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - AZ_Error("EMotionFX", false, "[GLSL] Failed to open shader file '%s'.", filename); + AZ_Error("EMotionFX", false, "[GLSL] Failed to open shader file '%.*s'.", AZ_STRING_ARG(filename.Native())); return false; } @@ -156,7 +156,7 @@ namespace RenderGL if (success == false) { - MCore::LogError("[GLSL] Failed to compile shader '%s'.", filename); + MCore::LogError("[GLSL] Failed to compile shader '%.*s'.", AZ_STRING_ARG(filename.Native())); return false; } @@ -212,7 +212,7 @@ namespace RenderGL // Init - bool GLSLShader::Init(const char* vFile, const char* pFile, MCore::Array& defines) + bool GLSLShader::Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines) { initializeOpenGLFunctions(); /*const char* args[] = { "unroll all", @@ -225,24 +225,24 @@ namespace RenderGL glUseProgram(0); // compile shaders - if (vFile && CompileShader(GL_VERTEX_SHADER, &mVertexShader, vFile) == false) + if (!vertexFileName.empty() && CompileShader(GL_VERTEX_SHADER, &mVertexShader, vertexFileName) == false) { return false; } - if (pFile && CompileShader(GL_FRAGMENT_SHADER, &mPixelShader, pFile) == false) + if (!pixelFileName.empty() && CompileShader(GL_FRAGMENT_SHADER, &mPixelShader, pixelFileName) == false) { return false; } // create program mProgram = glCreateProgram(); - if (vFile) + if (!vertexFileName.empty()) { glAttachShader(mProgram, mVertexShader); } - if (pFile) + if (!pixelFileName.empty()) { glAttachShader(mProgram, mPixelShader); } @@ -256,7 +256,7 @@ namespace RenderGL if (!success) { - MCore::LogInfo("[OpenGL] Failed to link shaders '%s' and '%s' ", vFile, pFile); + MCore::LogInfo("[OpenGL] Failed to link shaders '%.*s' and '%.*s' ", AZ_STRING_ARG(vertexFileName.Native()), AZ_STRING_ARG(pixelFileName.Native())); InfoLog(mProgram, &QOpenGLExtraFunctions::glGetProgramInfoLog); return false; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h index b9251dd718..73aee4313f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.h @@ -14,6 +14,7 @@ #define __RENDERGL_GLSLSHADER_H #include +#include #include "Shader.h" // include OpenGL @@ -45,7 +46,7 @@ namespace RenderGL MCORE_INLINE unsigned int GetProgram() const { return mProgram; } bool CheckIfIsDefined(const char* attributeName); - bool Init(const char* vertexFileName, const char* pixelFileName, MCore::Array& defines); + bool Init(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines); void SetAttribute(const char* name, uint32 dim, uint32 type, uint32 stride, size_t offset) override; void SetUniform(const char* name, float value) override; @@ -81,11 +82,11 @@ namespace RenderGL ShaderParameter* FindAttribute(const char* name); ShaderParameter* FindUniform(const char* name); - bool CompileShader(const GLenum type, unsigned int* outShader, const char* filename); + bool CompileShader(const GLenum type, unsigned int* outShader, AZ::IO::PathView filename); template void InfoLog(GLuint object, T func); - AZStd::string mFileName; + AZ::IO::Path mFileName; MCore::Array mActivatedAttribs; MCore::Array mActivatedTextures; diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp index 127f18ba67..5512028ad5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.cpp @@ -203,7 +203,7 @@ namespace RenderGL // try to initialize the graphics system - bool GraphicsManager::Init(const char* shaderPath) + bool GraphicsManager::Init(AZ::IO::PathView shaderPath) { initializeOpenGLFunctions(); @@ -364,7 +364,7 @@ namespace RenderGL // try to load a texture - Texture* GraphicsManager::LoadTexture([[maybe_unused]] const char* filename, [[maybe_unused]] bool createMipMaps) + Texture* GraphicsManager::LoadTexture([[maybe_unused]] AZ::IO::PathView filename, [[maybe_unused]] bool createMipMaps) { //Texture Library is no longer used //temporarily blank @@ -373,19 +373,19 @@ namespace RenderGL // try to load a texture - Texture* GraphicsManager::LoadTexture(const char* filename) + Texture* GraphicsManager::LoadTexture(AZ::IO::PathView filename) { return LoadTexture(filename, mCreateMipMaps); } // LoadPostProcessShader - PostProcessShader* GraphicsManager::LoadPostProcessShader(const char* cFileName) + PostProcessShader* GraphicsManager::LoadPostProcessShader(AZ::IO::PathView cFileName) { - AZStd::string filename = mShaderPath + AZStd::string(cFileName); + AZ::IO::PathView filename = mShaderPath / cFileName; // check if the shader is already in the cache - Shader* s = mShaderCache.FindShader(filename.c_str()); + Shader* s = mShaderCache.FindShader(filename.Native()); if (s) { return (PostProcessShader*)s; @@ -393,19 +393,19 @@ namespace RenderGL // load the shader from disk PostProcessShader* shader = new PostProcessShader(); - if (!shader->Init(filename.c_str())) + if (!shader->Init(filename)) { delete shader; return nullptr; } - mShaderCache.AddShader(filename.c_str(), shader); + mShaderCache.AddShader(filename.Native(), shader); return shader; } // LoadShader - GLSLShader* GraphicsManager::LoadShader(const char* vertexFileName, const char* pixelFileName) + GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName) { MCore::Array defines; return LoadShader(vertexFileName, pixelFileName, defines); @@ -413,34 +413,21 @@ namespace RenderGL // LoadShader - GLSLShader* GraphicsManager::LoadShader(const char* vFile, const char* pFile, MCore::Array& defines) + GLSLShader* GraphicsManager::LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines) { - AZStd::string vStr; - AZStd::string pStr; - - if (vFile) - { - vStr = AZStd::string::format("%s%s", mShaderPath.c_str(), vFile); - } - - if (pFile) - { - pStr = AZStd::string::format("%s%s", mShaderPath.c_str(), pFile); - } + const AZ::IO::Path vertexPath {vertexFileName.empty() ? AZ::IO::Path{} : mShaderPath / vertexFileName}; + const AZ::IO::Path pixelPath {pixelFileName.empty() ? AZ::IO::Path{} : mShaderPath / pixelFileName}; // construct the lookup string for the shader cache - AZStd::string dStr; + AZStd::string cacheLookupStr = vertexPath.Native() + pixelPath.Native(); const uint32 numDefines = defines.GetLength(); for (uint32 n = 0; n < numDefines; n++) { - dStr += AZStd::string::format("#%s", defines[n].c_str()); + cacheLookupStr += AZStd::string::format("#%s", defines[n].c_str()); } - AZStd::string cStr; - cStr = AZStd::string::format("%s%s%s", vStr.c_str(), pStr.c_str(), dStr.c_str()); - // check if the shader is already in the cache - Shader* cShader = mShaderCache.FindShader(cStr.c_str()); + Shader* cShader = mShaderCache.FindShader(cacheLookupStr); if (cShader) { return (GLSLShader*)cShader; @@ -448,13 +435,13 @@ namespace RenderGL // load the shader from disk GLSLShader* shader = new GLSLShader(); - if (!shader->Init(vFile ? vStr.c_str() : nullptr, pFile ? pStr.c_str() : nullptr, defines)) + if (!shader->Init(vertexPath, pixelPath, defines)) { delete shader; return nullptr; } - mShaderCache.AddShader(cStr.c_str(), shader); + mShaderCache.AddShader(cacheLookupStr, shader); return shader; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h index 811fe2998b..4aaf6a16d1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GraphicsManager.h @@ -13,6 +13,7 @@ #ifndef __RENDERGL_GRAPHICSMANAGER__H #define __RENDERGL_GRAPHICSMANAGER__H +#include #include #include #include @@ -57,21 +58,21 @@ namespace RenderGL const char* GetDeviceName(); const char* GetDeviceVendor(); MCORE_INLINE RenderTexture* GetRenderTexture() { return mRenderTexture; } - MCORE_INLINE const char* GetShaderPath() const { return mShaderPath.c_str(); } + MCORE_INLINE AZ::IO::PathView GetShaderPath() const { return mShaderPath; } MCORE_INLINE TextureCache* GetTextureCache() { return &mTextureCache; } - bool Init(const char* shaderPath = "Shaders/"); + bool Init(AZ::IO::PathView shaderPath = "Shaders"); bool GetIsPostProcessingEnabled() const { return mPostProcessing; } - PostProcessShader* LoadPostProcessShader(const char* filename); - GLSLShader* LoadShader(const char* vertexFileName, const char* pixelFileName); - GLSLShader* LoadShader(const char* vertexFileName, const char* pixelFileName, MCore::Array& defines); + PostProcessShader* LoadPostProcessShader(AZ::IO::PathView filename); + GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName); + GLSLShader* LoadShader(AZ::IO::PathView vertexFileName, AZ::IO::PathView pixelFileName, MCore::Array& defines); MCORE_INLINE void SetGBuffer(GBuffer* gBuffer) { mGBuffer = gBuffer; } MCORE_INLINE GBuffer* GetGBuffer() { return mGBuffer; } - Texture* LoadTexture(const char* filename, bool createMipMaps); - Texture* LoadTexture(const char* filename); + Texture* LoadTexture(AZ::IO::PathView filename, bool createMipMaps); + Texture* LoadTexture(AZ::IO::PathView filename); void SetCreateMipMaps(bool createMipMaps) { mCreateMipMaps = createMipMaps; } MCORE_INLINE bool GetCreateMipMaps() const { return mCreateMipMaps; } @@ -96,7 +97,7 @@ namespace RenderGL void SetShader(Shader* shader); MCORE_INLINE void SetRenderTexture(RenderTexture* texture) { mRenderTexture = texture; } - MCORE_INLINE void SetShaderPath(const char* shaderPath) { mShaderPath = shaderPath; } + MCORE_INLINE void SetShaderPath(AZ::IO::PathView shaderPath) { mShaderPath = shaderPath; } MCORE_INLINE void SetBloomEnabled(bool enabled) { mBloomEnabled = enabled; } MCORE_INLINE void SetBloomThreshold(float threshold) { mBloomThreshold = threshold; } @@ -154,7 +155,7 @@ namespace RenderGL MCommon::Camera* mCamera; /**< The camera used for rendering. */ ShaderCache mShaderCache; /**< The shader manager used to load and manage vertex and pixel shaders. */ - AZStd::string mShaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */ + AZ::IO::Path mShaderPath; /**< The absolute path to the directory where the shaders are located. This string will be added as prefix to each shader file the user tries to load. */ MCore::RGBAColor mClearColor; /**< The scene background color. */ MCore::RGBAColor mGradientSourceColor; /**< The background gradient source color. */ MCore::RGBAColor mGradientTargetColor; /**< The background gradient target color. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp index 11f46d2d13..8c5c79391f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.cpp @@ -11,6 +11,7 @@ */ #include +#include #include "PostProcessShader.h" #include "GraphicsManager.h" @@ -82,7 +83,7 @@ namespace RenderGL // Init - bool PostProcessShader::Init(const char* filename) + bool PostProcessShader::Init(AZ::IO::PathView filename) { MCore::Array defines; return GLSLShader::Init(nullptr, filename, defines); diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h index c16554faa7..b3068a9b8a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/PostProcessShader.h @@ -13,6 +13,7 @@ #ifndef __RENDERGL_POSTPROCESS_SHADER_H #define __RENDERGL_POSTPROCESS_SHADER_H +#include #include "GLSLShader.h" #include "RenderTexture.h" @@ -34,7 +35,7 @@ namespace RenderGL void Deactivate() override; - bool Init(const char* filename); + bool Init(AZ::IO::PathView filename); void Render(); private: diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp index cef9c93388..b3f2accb66 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/ShaderCache.cpp @@ -48,7 +48,7 @@ namespace RenderGL // add the shader to the cache (assume there are no duplicate names) - void ShaderCache::AddShader(const char* filename, Shader* shader) + void ShaderCache::AddShader(AZStd::string_view filename, Shader* shader) { mEntries.AddEmpty(); mEntries.GetLast().mName = filename; @@ -57,12 +57,12 @@ namespace RenderGL // try to locate a shader based on its name - Shader* ShaderCache::FindShader(const char* filename) const + Shader* ShaderCache::FindShader(AZStd::string_view filename) const { const uint32 numEntries = mEntries.GetLength(); for (uint32 i = 0; i < numEntries; ++i) { - if (AzFramework::StringFunc::Equal(mEntries[i].mName.c_str(), filename, false /* no case */)) // non-case-sensitive name compare + if (AzFramework::StringFunc::Equal(mEntries[i].mName, filename, false /* no case */)) // non-case-sensitive name compare { return mEntries[i].mShader; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h index d7ec884e6a..98bb87d373 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/shadercache.h @@ -33,8 +33,8 @@ namespace RenderGL ~ShaderCache(); // automatically calls Release void Release(); - void AddShader(const char* filename, Shader* shader); - Shader* FindShader(const char* filename) const; + void AddShader(AZStd::string_view filename, Shader* shader); + Shader* FindShader(AZStd::string_view filename) const; bool CheckIfHasShader(Shader* shader) const; private: diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp index 99f203d6e7..bfd6a3921f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.cpp @@ -64,7 +64,7 @@ namespace EMStudio // create graphics manager and initialize it mGraphicsManager = new RenderGL::GraphicsManager(); - if (mGraphicsManager->Init(shaderPath.c_str()) == false) + if (mGraphicsManager->Init(shaderPath) == false) { MCore::LogError("Could not initialize OpenGL graphics manager."); return false; From 01a2ea64235761b4b9f7eaa284052eee4ec656b6 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 16 Apr 2021 14:21:20 -0700 Subject: [PATCH 60/74] Moving thumbnail assets to AtomLyIntegration --- .../Common/Assets}/Materials/basic_grey.material | 0 .../Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename Gems/Atom/{Tools/MaterialEditor/Assets/MaterialEditor => Feature/Common/Assets}/Materials/basic_grey.material (100%) diff --git a/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/Materials/basic_grey.material b/Gems/Atom/Feature/Common/Assets/Materials/basic_grey.material similarity index 100% rename from Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/Materials/basic_grey.material rename to Gems/Atom/Feature/Common/Assets/Materials/basic_grey.material diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h index 9c8ea57cea..8a7bace6aa 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererData.h @@ -36,7 +36,7 @@ namespace AZ struct ThumbnailRendererData final { static constexpr const char* LightingPresetPath = "lightingpresets/thumbnail.lightingpreset.azasset"; - static constexpr const char* DefaultModelPath = "materialeditor/viewportmodels/quadsphere.azmodel"; + static constexpr const char* DefaultModelPath = "models/sphere.azmodel"; static constexpr const char* DefaultMaterialPath = "materials/basic_grey.azmaterial"; RPI::ScenePtr m_scene; From 73f275f479ad7ef48bd0f00291ecf1196eb241f8 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Fri, 16 Apr 2021 15:37:26 -0700 Subject: [PATCH 61/74] Get FindOpenGLInterface to use ly_add_external_target() instead --- cmake/3rdParty.cmake | 4 ---- cmake/3rdParty/FindOpenGLInterface.cmake | 14 +++++++------- .../Platform/Linux/OpenGLInterface_linux.cmake | 10 ---------- .../Platform/Linux/cmake_linux_files.cmake | 1 - .../Platform/Mac/OpenGLInterface_mac.cmake | 7 ++----- .../Platform/Windows/OpenGLInterface_windows.cmake | 10 ---------- .../Platform/Windows/cmake_windows_files.cmake | 1 - 7 files changed, 9 insertions(+), 38 deletions(-) delete mode 100644 cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake delete mode 100644 cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake diff --git a/cmake/3rdParty.cmake b/cmake/3rdParty.cmake index 4cd3ab2917..8d0c030302 100644 --- a/cmake/3rdParty.cmake +++ b/cmake/3rdParty.cmake @@ -116,10 +116,6 @@ function(ly_add_external_target) # Setting BASE_PATH variable in the parent scope to allow for the Find<3rdParty>.cmake scripts to use them set(BASE_PATH ${BASE_PATH} PARENT_SCOPE) - if(NOT EXISTS ${BASE_PATH}) - message(FATAL_ERROR "Cannot find 3rdParty library ${ly_add_external_target_NAME} on path ${BASE_PATH}") - endif() - add_library(3rdParty::${NAME_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) if(ly_add_external_target_INCLUDE_DIRECTORIES) diff --git a/cmake/3rdParty/FindOpenGLInterface.cmake b/cmake/3rdParty/FindOpenGLInterface.cmake index 99bf19c4d7..1e4992290f 100644 --- a/cmake/3rdParty/FindOpenGLInterface.cmake +++ b/cmake/3rdParty/FindOpenGLInterface.cmake @@ -9,11 +9,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -find_package(OpenGL QUIET REQUIRED) -# Imported targets (like OpenGL::GL) are scoped to a directory. Add a -# a global scope -add_library(3rdParty::OpenGLInterface INTERFACE IMPORTED GLOBAL) -target_link_libraries(3rdParty::OpenGLInterface INTERFACE OpenGL::GL) +find_package(OpenGL) -set(pal_file ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/OpenGLInterface_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) -include(${pal_file}) \ No newline at end of file +ly_add_external_target( + NAME OpenGLInterface + VERSION "" + BUILD_DEPENDENCIES + OpenGL::GL +) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake b/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/cmake/3rdParty/Platform/Linux/OpenGLInterface_linux.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# diff --git a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake index cce929b909..2b1ba4d0e5 100644 --- a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake +++ b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake @@ -16,7 +16,6 @@ set(FILES Clang_linux.cmake dyad_linux.cmake FbxSdk_linux.cmake - OpenGLInterface_linux.cmake OpenSSL_linux.cmake Wwise_linux.cmake ) diff --git a/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake b/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake index c9a52f4b1b..7d0d47740f 100644 --- a/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/OpenGLInterface_mac.cmake @@ -9,8 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -target_compile_definitions(3rdParty::OpenGLInterface - INTERFACE - # MacOS 10.14 deprecates OpenGL. This silences the warnings for now. - GL_SILENCE_DEPRECATION -) \ No newline at end of file +# MacOS 10.14 deprecates OpenGL. This silences the warnings for now. +set(OPENGLINTERFACE_COMPILE_DEFINITIONS GL_SILENCE_DEPRECATION) \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake b/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/cmake/3rdParty/Platform/Windows/OpenGLInterface_windows.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index 675ae7f695..2c7890fcc4 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -18,7 +18,6 @@ set(FILES dyad_windows.cmake FbxSdk_windows.cmake libav_windows.cmake - OpenGLInterface_windows.cmake OpenSSL_windows.cmake Wwise_windows.cmake ) From a6c7815685b5e8ec69eb725c23208828ff797ba0 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 16 Apr 2021 16:06:54 -0700 Subject: [PATCH 62/74] SPEC-6371 Change the asset_profile and test_profile steps to be no_unity so it doesnt recompile --- .../Tests/AssetSeedManager.cpp | 12 +++---- .../build/Platform/Linux/build_config.json | 32 +++++++++++++++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp b/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp index 2003f8eafd..5ccbd95f09 100644 --- a/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp +++ b/Code/Framework/AzToolsFramework/Tests/AssetSeedManager.cpp @@ -68,7 +68,7 @@ namespace UnitTest { assets[idx] = AssetId(AZ::Uuid::CreateRandom(), 0); AZ::Data::AssetInfo info; - info.m_relativePath = AZStd::string::format("Asset%d.txt", idx); + info.m_relativePath = AZStd::string::format("asset%d.txt", idx); m_assetsPath[idx] = info.m_relativePath; info.m_assetId = assets[idx]; m_assetRegistry->RegisterAsset(assets[idx], info); @@ -623,7 +623,7 @@ namespace UnitTest EXPECT_TRUE(Search(assetList1, assets[fileIndex])); if (m_fileStreams[0][fileIndex].Open(m_assetsPathFull[0][fileIndex].c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary | AZ::IO::OpenMode::ModeCreatePath)) { - AZStd::string fileContent = AZStd::string::format("Asset%d.txt", fileIndex); + AZStd::string fileContent = AZStd::string::format("asset%d.txt", fileIndex); m_fileStreams[0][fileIndex].Write(fileContent.size(), fileContent.c_str()); m_fileStreams[0][fileIndex].Close(); } @@ -654,7 +654,7 @@ namespace UnitTest EXPECT_TRUE(Search(assetList1, assets[fileIndex])); if (m_fileStreams[0][fileIndex].Open(m_assetsPathFull[0][fileIndex].c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary | AZ::IO::OpenMode::ModeCreatePath)) { - AZStd::string fileContent = AZStd::string::format("Asset%d.txt", fileIndex + 1);// changing file content + AZStd::string fileContent = AZStd::string::format("asset%d.txt", fileIndex + 1);// changing file content m_fileStreams[0][fileIndex].Write(fileContent.size(), fileContent.c_str()); m_fileStreams[0][fileIndex].Close(); } @@ -987,7 +987,7 @@ namespace UnitTest m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); - m_assetSeedManager->RemoveSeedAsset("Asset0.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->RemoveSeedAsset("asset0.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(secondSeedList.size(), 0); } @@ -1003,7 +1003,7 @@ namespace UnitTest m_assetSeedManager->AddSeedAsset(assets[0], AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); - m_assetSeedManager->RemoveSeedAsset("Asset0.txt", AzFramework::PlatformFlags::Platform_PC); + m_assetSeedManager->RemoveSeedAsset("asset0.txt", AzFramework::PlatformFlags::Platform_PC); const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(secondSeedList.size(), 1); } @@ -1017,7 +1017,7 @@ namespace UnitTest EXPECT_EQ(seedList.size(), 1); - m_assetSeedManager->RemoveSeedAsset("Asset1.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); + m_assetSeedManager->RemoveSeedAsset("asset1.txt", AzFramework::PlatformFlags::Platform_PC | AzFramework::PlatformFlags::Platform_OSX); const AzFramework::AssetSeedList& secondSeedList = m_assetSeedManager->GetAssetSeedList(); EXPECT_EQ(secondSeedList.size(), 1); } diff --git a/scripts/build/Platform/Linux/build_config.json b/scripts/build/Platform/Linux/build_config.json index d7f5ddc9d0..426bf1d7ce 100644 --- a/scripts/build/Platform/Linux/build_config.json +++ b/scripts/build/Platform/Linux/build_config.json @@ -7,14 +7,14 @@ "CMAKE_LY_PROJECTS": "AutomatedTesting" } }, - "profile_pipe": { + "profile_nounity_pipe": { "TAGS": [ "default" ], "steps": [ "profile_nounity", - "asset_profile", - "test_profile" + "asset_profile_nounity", + "test_profile_nounity" ] }, "metrics": { @@ -84,6 +84,18 @@ "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest" } }, + "test_profile_nounity": { + "TAGS": [], + "COMMAND": "build_test_linux.sh", + "PARAMETERS": { + "CONFIGURATION": "profile", + "OUTPUT_DIRECTORY": "build/linux", + "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=FALSE -DLY_PARALLEL_LINK_JOBS=4", + "CMAKE_LY_PROJECTS": "AutomatedTesting", + "CMAKE_TARGET": "all", + "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest" + } + }, "asset_profile": { "TAGS": [ "weekly-build-metrics" @@ -100,6 +112,20 @@ "ASSET_PROCESSOR_PLATFORMS": "pc,server" } }, + "asset_profile_nounity": { + "TAGS": [], + "COMMAND": "build_asset_linux.sh", + "PARAMETERS": { + "CONFIGURATION": "profile", + "OUTPUT_DIRECTORY": "build/linux", + "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=FALSE -DLY_PARALLEL_LINK_JOBS=4", + "CMAKE_LY_PROJECTS": "AutomatedTesting", + "CMAKE_TARGET": "AssetProcessorBatch", + "ASSET_PROCESSOR_BINARY": "bin/profile/AssetProcessorBatch", + "ASSET_PROCESSOR_OPTIONS": "/zeroAnalysisMode", + "ASSET_PROCESSOR_PLATFORMS": "pc,server" + } + }, "asset_clean_profile": { "TAGS": [ "nightly" From 250f8d8db01811dbeb5e0e1fee1f27320acb6f47 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 16 Apr 2021 16:36:21 -0700 Subject: [PATCH 63/74] SPEC-6246 Prevent job overrides from PR branches (#110) --- scripts/build/Jenkins/Jenkinsfile | 35 ++++++++++++++++++------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index f77c139342..297c406b7b 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -26,8 +26,7 @@ def pipelineParameters = [ booleanParam(defaultValue: false, description: 'Deletes the contents of the output directory before building. This will cause a \"clean\" build. NOTE: does not imply CLEAN_ASSETS', name: 'CLEAN_OUTPUT_DIRECTORY'), booleanParam(defaultValue: false, description: 'Deletes the contents of the output directories of the AssetProcessor before building.', name: 'CLEAN_ASSETS'), booleanParam(defaultValue: false, description: 'Deletes the contents of the workspace and forces a complete pull.', name: 'CLEAN_WORKSPACE'), - booleanParam(defaultValue: false, description: 'Recreates the volume used for the workspace. The volume will be created out of a snapshot taken from main.', name: 'RECREATE_VOLUME'), - string(defaultValue: '', description: 'Filters and overrides the list of jobs to run for each of the below platforms (comma-separated). Can\'t be used during a pull request.', name: 'JOB_LIST_OVERRIDE') + booleanParam(defaultValue: false, description: 'Recreates the volume used for the workspace. The volume will be created out of a snapshot taken from main.', name: 'RECREATE_VOLUME') ] def palSh(cmd, lbl = '', winSlashReplacement = true) { @@ -76,18 +75,22 @@ def palRmDir(path) { } } -def IsJobEnabled(buildTypeMap, pipelineName, platformName) { - def job_list_override = params.JOB_LIST_OVERRIDE.tokenize(',') +def IsPullRequest(branchName) { + // temporarily using the name to detect if we are in a PR + // In the future we will check with github + return branchName.startsWith('PR-') +} + +def IsJobEnabled(branchName, buildTypeMap, pipelineName, platformName) { + if (IsPullRequest(branchName)) { + return buildTypeMap.value.TAGS && buildTypeMap.value.TAGS.contains(pipelineName) + } + def job_list_override = params.JOB_LIST_OVERRIDE ? params.JOB_LIST_OVERRIDE.tokenize(',') : '' if (!job_list_override.isEmpty()) { return params[platformName] && job_list_override.contains(buildTypeMap.key); } else { - if (params[platformName]) { - if(buildTypeMap.value.TAGS) { - return buildTypeMap.value.TAGS.contains(pipelineName) - } - } + return params[platformName] && buildTypeMap.value.TAGS && buildTypeMap.value.TAGS.contains(pipelineName) } - return false } def GetRunningPipelineName(JENKINS_JOB_NAME) { @@ -448,8 +451,12 @@ try { pipelineConfig = LoadPipelineConfig(pipelineName, branchName) // Add each platform as a parameter that the user can disable if needed - pipelineConfig.platforms.each { platform -> - pipelineParameters.add(booleanParam(defaultValue: true, description: '', name: platform.key)) + if (!IsPullRequest(branchName)) { + pipelineParameters.add(stringParam(defaultValue: '', description: 'Filters and overrides the list of jobs to run for each of the below platforms (comma-separated). Can\'t be used during a pull request.', name: 'JOB_LIST_OVERRIDE')) + + pipelineConfig.platforms.each { platform -> + pipelineParameters.add(booleanParam(defaultValue: true, description: '', name: platform.key)) + } } pipelineProperties.add(parameters(pipelineParameters)) properties(pipelineProperties) @@ -462,7 +469,7 @@ try { } } - if(env.BUILD_NUMBER == '1' && !branchName.startsWith('PR-')) { + if(env.BUILD_NUMBER == '1' && !IsPullRequest(branchName)) { // Exit pipeline early on the intial build. This allows Jenkins to load the pipeline for the branch and enables users // to select build parameters on their first actual build. See https://issues.jenkins.io/browse/JENKINS-41929 currentBuild.result = 'SUCCESS' @@ -477,7 +484,7 @@ try { // Platform Builds run on EC2 pipelineConfig.platforms.each { platform -> platform.value.build_types.each { build_job -> - if (IsJobEnabled(build_job, pipelineName, platform.key)) { // User can filter jobs, jobs are tagged by pipeline + if (IsJobEnabled(branchName, build_job, pipelineName, platform.key)) { // User can filter jobs, jobs are tagged by pipeline def envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, build_job.value.PIPELINE_ENV ?: EMPTY_JSON, pipelineName) envVars['JOB_NAME'] = "${branchName}_${platform.key}_${build_job.key}" // backwards compatibility, some scripts rely on this def nodeLabel = envVars['NODE_LABEL'] From a519bd6d0cc04845584094b55f3b9db20e1555b5 Mon Sep 17 00:00:00 2001 From: nvsickle Date: Thu, 15 Apr 2021 15:15:53 -0700 Subject: [PATCH 64/74] Fix EditorViewportWidget stealing keyboard focus grabKeyboard was used by CRenderViewport to ensure it received some events, but that logic is no longer needed and the corresponding release was removed. This just removes grabKeyboard entirely - eventually all input event logic will be removed as well. --- Code/Sandbox/Editor/EditorViewportWidget.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index a3b2542418..695a0fa5f1 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -1617,11 +1617,6 @@ void EditorViewportWidget::keyPressEvent(QKeyEvent* event) // because we want the movement to be butter smooth. if (!event->isAutoRepeat()) { - if (m_keyDown.isEmpty()) - { - grabKeyboard(); - } - m_keyDown.insert(event->key()); } From ab11b234a867b2c0927c03d07e392eede63b350b Mon Sep 17 00:00:00 2001 From: mcgarrah Date: Thu, 15 Apr 2021 15:02:35 -0500 Subject: [PATCH 65/74] Removed AssetProcessor Settings from the bootstrap.cfg file as they are being shadowed by the /Engine/Registry/bootstrap.setreg file. Attempting to set those values in the bootstrap.cfg would only result in them being overridden when the bootstrap.setreg is merged into the settings registry --- bootstrap.cfg | 90 ++++++--------------------------------------------- 1 file changed, 9 insertions(+), 81 deletions(-) diff --git a/bootstrap.cfg b/bootstrap.cfg index cbe6ed025e..3486806a5d 100644 --- a/bootstrap.cfg +++ b/bootstrap.cfg @@ -1,84 +1,12 @@ --- When you see an option that does not have a platform preceeding it, that is the default --- value for anything not specificly set per platform. So if remote_filesystem=0 and you have --- ios_remote_file_system=1 then remote filesystem will be off for all platforms except ios --- Any of the settings in this file can be prefixed with a platform name: --- android, ios, mac, linux, windows, etc... --- or left unprefixed, to set all platforms not specified. The rules apply in the order they're declared +; This file is deprecated and is only use currently for setting the path when running O3DE in an engine-centric manner +; By engine-centric, what is meant is using CMake to configure from the directory and passing in the LY_PROJECTS value project_path=AutomatedTesting --- remote_filesystem - enable Virtual File System (VFS) --- This feature allows a remote instance of the game to run off assets --- on the asset processor computers cache instead of deploying them the remote device --- By default it is off and can be overridden for any platform -remote_filesystem=0 -provo_remote_filesystem=0 -android_remote_filesystem=0 -ios_remote_filesystem=0 -mac_remote_filesystem=0 - --- What type of assets are we going to load? --- We need to know this before we establish VFS because different platform assets --- are stored in different root folders in the cache. These correspond to the names --- In the asset processor config file. This value also controls what config file is read --- when you read system_xxxx_xxxx.cfg (for example, system_windows_pc.cfg or system_android_es3.cfg) --- by default, pc assets (in the 'pc' folder) are used, with RC being fed 'pc' as the platform --- by default on console we use the default assets=pc for better iteration times --- we should turn on console specific assets only when in release and/or testing assets and/or loading performance --- that way most people will not need to have 3 different caches taking up disk space -assets = pc --- provo_assets = provo --- salem_assets = salem --- jasper_assets = jasper -android_assets = es3 -ios_assets = ios -mac_assets = osx_gl - --- Add the IP address of your console to the allowed list that will connect to the asset processor here --- You can list addresses or CIDR's. CIDR's are helpful if you are using DHCP. A CIDR looks like an ip address with --- a /n on the end means how many bits are significant. 8bits.8bits.8bits.8bits = /32 --- Example: 192.168.1.3 --- Example: 192.168.1.3, 192.168.1.15 --- Example: 192.168.1.0/24 will allow any address starting with 192.168.1. --- Example: 192.168.0.0/16 will allow any address starting with 192.168. --- Example: 192.168.0.0/8 will allow any address starting with 192. --- allowed_list = - --- IP address and optionally port of the asset processor. --- Set your PC IP here: (and uncomment the next line) --- If you are running your asset processor on a windows machine you --- can find out your ip address by opening a cmd prompt and typing in ipconfig --- remote_ip = 127.0.0.1 --- remote_port = 45643 - --- Which way do you want to connect the asset processor to the game: 1=game connects to AP "connect", 0=AP connects to game "listen" --- Note: android and IOS over USB port forwarding may need to listen instead of connect -connect_to_remote=0 -windows_connect_to_remote=1 -provo_connect_to_remote=1 -salem_connect_to_remote=0 -jasper_connect_to_remote=0 -android_connect_to_remote=0 -ios_connect_to_remote=0 -mac_connect_to_remote=0 - --- Should we tell the game to wait and not proceed unless we have a connection to the AP or --- do we allow it to continue to try to connect in the background without waiting --- Note: Certain options REQUIRE that we do not proceed unless we have a connection, and will override this option to 1 when set --- Since remote_filesystem=1 requires a connection to proceed it will override our option to 1 -wait_for_connect=0 -provo_wait_for_connect=0 -salem_wait_for_connect=0 -jasper_wait_for_connect=0 -windows_wait_for_connect=1 -android_wait_for_connect=0 -ios_wait_for_connect=0 -mac_wait_for_connect=0 - --- How long applications should wait while attempting to connect to an already launched AP(in seconds) --- connect_ap_timeout=3 - --- How long application should wait when launching the AP and wait for the AP to connect back to it(in seconds) --- This time is dependent on Machine load as well as how long it takes for the new AP instance to initialize --- A debug AP takes longer to start up than a profile AP --- launch_ap_timeout=15 +; The Asset Processor Specific settings are now the /Engine/Registry/bootstrap.setreg settings +; The Engine specific settings can be overridden in order of least precedence to most +; 1. Override the settings in a "/Registry/*.setreg(patch)" file (Shared per Gem Settings) +; 2. Override the settings in a "/Registry/*.setreg(patch)" file (Shared per Project Settings) +; 3. Override the settings in a "/Registry/*.setreg(patch)" file (User per Project Settings) +; 4. Override the settings in a "~/.o3de/Registry/*.setreg(patch)" file (User Global Settings) +; Where "~" is %USERPROFILE% on Windows and $HOME on Unix like platforms \ No newline at end of file From 373f60f29c5a91b27216dd72adb6533966c8af7d Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 15 Apr 2021 21:44:50 -0500 Subject: [PATCH 66/74] Added a call to update the runtime file paths again after merging all Engine, Gem and Project Settings Registry in case they modified the asset platform key which is used for setting the project cache root --- Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp | 2 ++ .../AzGameFramework/Application/GameApplication.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index b8d3e12712..5266cefca2 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -909,6 +909,8 @@ namespace AZ SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true); #endif + // Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry); } void ComponentApplication::SetSettingsRegistrySpecializations(SettingsRegistryInterface::Specializations& specializations) diff --git a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp index f4fc9364f7..edd4af293d 100644 --- a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp +++ b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp @@ -80,6 +80,8 @@ namespace AzGameFramework AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true); #endif + // Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry); } AZ::ComponentTypeList GameApplication::GetRequiredSystemComponents() const From 6b1e2c52b1bae499b4ac18b769c64de7eb48d7c7 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 15 Apr 2021 16:48:04 -0500 Subject: [PATCH 67/74] Adding newline at end of file of bootstrap.cfg --- bootstrap.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.cfg b/bootstrap.cfg index 3486806a5d..aa7af07645 100644 --- a/bootstrap.cfg +++ b/bootstrap.cfg @@ -9,4 +9,4 @@ project_path=AutomatedTesting ; 2. Override the settings in a "/Registry/*.setreg(patch)" file (Shared per Project Settings) ; 3. Override the settings in a "/Registry/*.setreg(patch)" file (User per Project Settings) ; 4. Override the settings in a "~/.o3de/Registry/*.setreg(patch)" file (User Global Settings) -; Where "~" is %USERPROFILE% on Windows and $HOME on Unix like platforms \ No newline at end of file +; Where "~" is %USERPROFILE% on Windows and $HOME on Unix like platforms From bf2732a26d698246296db8089d80948e69131281 Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Apr 2021 17:54:37 -0500 Subject: [PATCH 68/74] Moved the PlatformDefaults files from AzFramework to AzCore --- .../Platform => AzCore/AzCore/PlatformId}/PlatformDefaults.cpp | 0 .../Platform => AzCore/AzCore/PlatformId}/PlatformDefaults.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Code/Framework/{AzFramework/AzFramework/Platform => AzCore/AzCore/PlatformId}/PlatformDefaults.cpp (100%) rename Code/Framework/{AzFramework/AzFramework/Platform => AzCore/AzCore/PlatformId}/PlatformDefaults.h (100%) diff --git a/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.cpp b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp similarity index 100% rename from Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.cpp rename to Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp diff --git a/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h similarity index 100% rename from Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h rename to Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h From 96ef3499316b8d1d255e74d1f33e0ee40c52de1b Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Apr 2021 18:05:11 -0500 Subject: [PATCH 69/74] Update the AzFramework and AzCore cmake files to point at the new location of the PlatformDefaults.h and PlatformDefaults.cpp file Added an inline namespace for the PlatformDefaults code to ease with aliasing it into the AzFramework namespace --- .../AzCore/PlatformId/PlatformDefaults.cpp | 492 +++++++++--------- .../AzCore/PlatformId/PlatformDefaults.h | 256 ++++----- .../AzCore/AzCore/azcore_files.cmake | 2 + .../AzFramework/Platform/PlatformDefaults.h | 23 + .../AzFramework/azframework_files.cmake | 1 - 5 files changed, 401 insertions(+), 373 deletions(-) create mode 100644 Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h diff --git a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp index 81154bae35..63aad1ecf4 100644 --- a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp +++ b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.cpp @@ -11,328 +11,330 @@ */ #include -#include +#include #include -namespace AzFramework +namespace AZ { - static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformES3, PlatformIOS, PlatformOSX, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient }; - - const char* PlatformIdToPalFolder(AzFramework::PlatformId platform) + inline namespace PlatformDefaults { + static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformES3, PlatformIOS, PlatformOSX, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient }; + + const char* PlatformIdToPalFolder(AZ::PlatformId platform) + { #ifdef IOS #define AZ_REDEFINE_IOS_AT_END IOS #undef IOS #endif - switch (platform) - { - case AzFramework::PC: - return "PC"; - case AzFramework::ES3: - return "Android"; - case AzFramework::IOS: - return "iOS"; - case AzFramework::OSX: - return "Mac"; - case AzFramework::PROVO: - return "Provo"; - case AzFramework::SALEM: - return "Salem"; - case AzFramework::JASPER: - return "Jasper"; - case AzFramework::SERVER: - return "Server"; - case AzFramework::ALL: - case AzFramework::ALL_CLIENT: - case AzFramework::NumPlatformIds: - case AzFramework::Invalid: - default: - return ""; - } + switch (platform) + { + case AZ::PC: + return "PC"; + case AZ::ES3: + return "Android"; + case AZ::IOS: + return "iOS"; + case AZ::OSX: + return "Mac"; + case AZ::PROVO: + return "Provo"; + case AZ::SALEM: + return "Salem"; + case AZ::JASPER: + return "Jasper"; + case AZ::SERVER: + return "Server"; + case AZ::ALL: + case AZ::ALL_CLIENT: + case AZ::NumPlatformIds: + case AZ::Invalid: + default: + return ""; + } #ifdef AZ_REDEFINE_IOS_AT_END #define IOS AZ_REDEFINE_IOS_AT_END #endif - } - - const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform) - { - if (osPlatform == PlatformCodeNameWindows || osPlatform == PlatformCodeNameLinux) - { - return PlatformPC; } - else if (osPlatform == PlatformCodeNameMac) - { - return PlatformOSX; - } - else if (osPlatform == PlatformCodeNameAndroid) - { - return PlatformES3; - } - else if (osPlatform == PlatformCodeNameiOS) - { - return PlatformIOS; - } - else if (osPlatform == PlatformCodeNameProvo) + + const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform) { - return PlatformProvo; + if (osPlatform == PlatformCodeNameWindows || osPlatform == PlatformCodeNameLinux) + { + return PlatformPC; + } + else if (osPlatform == PlatformCodeNameMac) + { + return PlatformOSX; + } + else if (osPlatform == PlatformCodeNameAndroid) + { + return PlatformES3; + } + else if (osPlatform == PlatformCodeNameiOS) + { + return PlatformIOS; + } + else if (osPlatform == PlatformCodeNameProvo) + { + return PlatformProvo; + } + else if (osPlatform == PlatformCodeNameSalem) + { + return PlatformSalem; + } + else if (osPlatform == PlatformCodeNameJasper) + { + return PlatformJasper; + } + + AZ_Error("PlatformDefault", false, R"(Supplied OS platform "%.*s" does not have a corresponding default asset platform)", + aznumeric_cast(osPlatform.size()), osPlatform.data()); + return ""; } - else if (osPlatform == PlatformCodeNameSalem) + + PlatformFlags PlatformHelper::GetPlatformFlagFromPlatformIndex(PlatformId platformIndex) { - return PlatformSalem; + if (platformIndex < 0 || platformIndex > PlatformId::NumPlatformIds) + { + return PlatformFlags::Platform_NONE; + } + if (platformIndex == PlatformId::ALL) + { + return PlatformFlags::Platform_ALL; + } + if (platformIndex == PlatformId::ALL_CLIENT) + { + return PlatformFlags::Platform_ALL_CLIENT; + } + return static_cast(1 << platformIndex); } - else if (osPlatform == PlatformCodeNameJasper) + + AZStd::fixed_vector PlatformHelper::GetPlatforms(PlatformFlags platformFlags) { - return PlatformJasper; - } + AZStd::fixed_vector platforms; + for (int platformNum = 0; platformNum < PlatformId::NumPlatformIds; ++platformNum) + { + const bool isAllPlatforms = PlatformId::ALL == static_cast(platformNum) + && ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE); - AZ_Error("PlatformDefault", false, R"(Supplied OS platform "%.*s" does not have a corresponding default asset platform)", - aznumeric_cast(osPlatform.size()), osPlatform.data()); - return ""; - } + const bool isAllClientPlatforms = PlatformId::ALL_CLIENT == static_cast(platformNum) + && ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE); - PlatformFlags PlatformHelper::GetPlatformFlagFromPlatformIndex(PlatformId platformIndex) - { - if (platformIndex < 0 || platformIndex > PlatformId::NumPlatformIds) - { - return PlatformFlags::Platform_NONE; - } - if (platformIndex == PlatformId::ALL) - { - return PlatformFlags::Platform_ALL; + if (isAllPlatforms || isAllClientPlatforms + || (platformFlags & static_cast(1 << platformNum)) != PlatformFlags::Platform_NONE) + { + platforms.push_back(PlatformNames[platformNum]); + } + } + + return platforms; } - if (platformIndex == PlatformId::ALL_CLIENT) + + AZStd::fixed_vector PlatformHelper::GetPlatformsInterpreted(PlatformFlags platformFlags) { - return PlatformFlags::Platform_ALL_CLIENT; + return GetPlatforms(GetPlatformFlagsInterpreted(platformFlags)); } - return static_cast(1 << platformIndex); - } - AZStd::fixed_vector PlatformHelper::GetPlatforms(PlatformFlags platformFlags) - { - AZStd::fixed_vector platforms; - for (int platformNum = 0; platformNum < PlatformId::NumPlatformIds; ++platformNum) + AZStd::fixed_vector PlatformHelper::GetPlatformIndices(PlatformFlags platformFlags) { - const bool isAllPlatforms = PlatformId::ALL == static_cast(platformNum) - && ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE); - - const bool isAllClientPlatforms = PlatformId::ALL_CLIENT == static_cast(platformNum) - && ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE); - - if (isAllPlatforms || isAllClientPlatforms - || (platformFlags & static_cast(1 << platformNum)) != PlatformFlags::Platform_NONE) + AZStd::fixed_vector platformIndices; + for (int i = 0; i < PlatformId::NumPlatformIds; i++) { - platforms.push_back(PlatformNames[platformNum]); + PlatformId index = static_cast(i); + if ((GetPlatformFlagFromPlatformIndex(index) & platformFlags) != PlatformFlags::Platform_NONE) + { + platformIndices.emplace_back(index); + } } + return platformIndices; } - return platforms; - } - - AZStd::fixed_vector PlatformHelper::GetPlatformsInterpreted(PlatformFlags platformFlags) - { - return GetPlatforms(GetPlatformFlagsInterpreted(platformFlags)); - } + AZStd::fixed_vector PlatformHelper::GetPlatformIndicesInterpreted(PlatformFlags platformFlags) + { + return GetPlatformIndices(GetPlatformFlagsInterpreted(platformFlags)); + } - AZStd::fixed_vector PlatformHelper::GetPlatformIndices(PlatformFlags platformFlags) - { - AZStd::fixed_vector platformIndices; - for (int i = 0; i < PlatformId::NumPlatformIds; i++) + PlatformFlags PlatformHelper::GetPlatformFlag(AZStd::string_view platform) { - PlatformId index = static_cast(i); - if ((GetPlatformFlagFromPlatformIndex(index) & platformFlags) != PlatformFlags::Platform_NONE) + int platformIndex = GetPlatformIndexFromName(platform); + if (platformIndex == PlatformId::Invalid) { - platformIndices.emplace_back(index); + AZ_Error("PlatformDefault", false, "Invalid Platform ( %.*s ).\n", static_cast(platform.length()), platform.data()); + return PlatformFlags::Platform_NONE; } - } - return platformIndices; - } - AZStd::fixed_vector PlatformHelper::GetPlatformIndicesInterpreted(PlatformFlags platformFlags) - { - return GetPlatformIndices(GetPlatformFlagsInterpreted(platformFlags)); - } + if (platformIndex == PlatformId::ALL) + { + return PlatformFlags::Platform_ALL; + } - PlatformFlags PlatformHelper::GetPlatformFlag(AZStd::string_view platform) - { - int platformIndex = GetPlatformIndexFromName(platform); - if (platformIndex == PlatformId::Invalid) - { - AZ_Error("PlatformDefault", false, "Invalid Platform ( %.*s ).\n", static_cast(platform.length()), platform.data()); - return PlatformFlags::Platform_NONE; - } + if (platformIndex == PlatformId::ALL_CLIENT) + { + return PlatformFlags::Platform_ALL_CLIENT; + } - if(platformIndex == PlatformId::ALL) - { - return PlatformFlags::Platform_ALL; + return static_cast(1 << platformIndex); } - if (platformIndex == PlatformId::ALL_CLIENT) + const char* PlatformHelper::GetPlatformName(PlatformId platform) { - return PlatformFlags::Platform_ALL_CLIENT; + if (platform < 0 || platform > PlatformId::NumPlatformIds) + { + return "invalid"; + } + return PlatformNames[platform]; } - return static_cast(1 << platformIndex); - } - - const char* PlatformHelper::GetPlatformName(PlatformId platform) - { - if (platform < 0 || platform > PlatformId::NumPlatformIds) + void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, AZStd::string_view platformId) { - return "invalid"; + PlatformId platform = GetPlatformIdFromName(platformId); + AZ_Assert(platform != PlatformId::Invalid, "Unsupported Platform ID: %.*s", static_cast(platformId.length()), platformId.data()); + AppendPlatformCodeNames(platformCodes, platform); } - return PlatformNames[platform]; - } - void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, AZStd::string_view platformId) - { - PlatformId platform = GetPlatformIdFromName(platformId); - AZ_Assert(platform != PlatformId::Invalid, "Unsupported Platform ID: %.*s", static_cast(platformId.length()), platformId.data()); - AppendPlatformCodeNames(platformCodes, platform); - } - - void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, PlatformId platformId) - { -// The IOS SDK has a macro that defines IOS as 1 which causes the enum below to be incorrectly converted to "PlatformId::1". + void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, PlatformId platformId) + { + // The IOS SDK has a macro that defines IOS as 1 which causes the enum below to be incorrectly converted to "PlatformId::1". #pragma push_macro("IOS") #undef IOS // To reduce work the Asset Processor groups assets that can be shared between hardware platforms together. For this // reason "PC" can for instance cover both the Windows and Linux platforms and "IOS" can cover AppleTV and iOS. - switch (platformId) - { - case PlatformId::PC: - platformCodes.emplace_back(PlatformCodeNameWindows); - platformCodes.emplace_back(PlatformCodeNameLinux); - break; - case PlatformId::ES3: - platformCodes.emplace_back(PlatformCodeNameAndroid); - break; - case PlatformId::IOS: - platformCodes.emplace_back(PlatformCodeNameiOS); - break; - case PlatformId::OSX: - platformCodes.emplace_back(PlatformCodeNameMac); - break; - case PlatformId::PROVO: - platformCodes.emplace_back(PlatformCodeNameProvo); - break; - case PlatformId::SALEM: - platformCodes.emplace_back(PlatformCodeNameSalem); - break; - case PlatformId::JASPER: - platformCodes.emplace_back(PlatformCodeNameJasper); - break; - case PlatformId::SERVER: - // Server is not a hardware platform - break; - default: - AZ_Assert(false, "Unsupported Platform ID: %i", platformId); - break; - } -#pragma pop_macro("IOS") - } - - int PlatformHelper::GetPlatformIndexFromName(AZStd::string_view platformName) - { - for (int idx = 0; idx < PlatformId::NumPlatformIds; idx++) - { - if (platformName == PlatformNames[idx]) + switch (platformId) { - return idx; + case PlatformId::PC: + platformCodes.emplace_back(PlatformCodeNameWindows); + platformCodes.emplace_back(PlatformCodeNameLinux); + break; + case PlatformId::ES3: + platformCodes.emplace_back(PlatformCodeNameAndroid); + break; + case PlatformId::IOS: + platformCodes.emplace_back(PlatformCodeNameiOS); + break; + case PlatformId::OSX: + platformCodes.emplace_back(PlatformCodeNameMac); + break; + case PlatformId::PROVO: + platformCodes.emplace_back(PlatformCodeNameProvo); + break; + case PlatformId::SALEM: + platformCodes.emplace_back(PlatformCodeNameSalem); + break; + case PlatformId::JASPER: + platformCodes.emplace_back(PlatformCodeNameJasper); + break; + case PlatformId::SERVER: + // Server is not a hardware platform + break; + default: + AZ_Assert(false, "Unsupported Platform ID: %i", platformId); + break; } +#pragma pop_macro("IOS") } - return PlatformId::Invalid; - } - - PlatformId PlatformHelper::GetPlatformIdFromName(AZStd::string_view platformName) - { - return aznumeric_caster(GetPlatformIndexFromName(platformName)); - } - - AssetPlatformCombinedString PlatformHelper::GetCommaSeparatedPlatformList(PlatformFlags platformFlags) - { - AZStd::fixed_vector platformNames = GetPlatforms(platformFlags); - AssetPlatformCombinedString platformsString; - AZ::StringFunc::Join(platformsString, platformNames.begin(), platformNames.end(), ", "); - return platformsString; - } - - PlatformFlags PlatformHelper::GetPlatformFlagsInterpreted(PlatformFlags platformFlags) - { - PlatformFlags returnFlags = PlatformFlags::Platform_NONE; - - if((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE) + int PlatformHelper::GetPlatformIndexFromName(AZStd::string_view platformName) { - for (int i = 0; i < NumPlatforms; ++i) + for (int idx = 0; idx < PlatformId::NumPlatformIds; idx++) { - auto platformId = static_cast(i); - - if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT) + if (platformName == PlatformNames[idx]) { - returnFlags |= GetPlatformFlagFromPlatformIndex(platformId); + return idx; } } + + return PlatformId::Invalid; } - else if((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE) + + PlatformId PlatformHelper::GetPlatformIdFromName(AZStd::string_view platformName) { - for (int i = 0; i < NumPlatforms; ++i) - { - auto platformId = static_cast(i); - - if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT && platformId != PlatformId::SERVER) - { - returnFlags |= GetPlatformFlagFromPlatformIndex(platformId); - } - } + return aznumeric_caster(GetPlatformIndexFromName(platformName)); } - else + + AssetPlatformCombinedString PlatformHelper::GetCommaSeparatedPlatformList(PlatformFlags platformFlags) { - returnFlags = platformFlags; + AZStd::fixed_vector platformNames = GetPlatforms(platformFlags); + AssetPlatformCombinedString platformsString; + AZ::StringFunc::Join(platformsString, platformNames.begin(), platformNames.end(), ", "); + return platformsString; } - return returnFlags; - } + PlatformFlags PlatformHelper::GetPlatformFlagsInterpreted(PlatformFlags platformFlags) + { + PlatformFlags returnFlags = PlatformFlags::Platform_NONE; - bool PlatformHelper::IsSpecialPlatform(PlatformFlags platformFlags) - { - return (platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE - || (platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE; - } + if ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE) + { + for (int i = 0; i < NumPlatforms; ++i) + { + auto platformId = static_cast(i); - bool HasFlagHelper(PlatformFlags flags, PlatformFlags checkPlatform) - { - return (flags & checkPlatform) == checkPlatform; - } + if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT) + { + returnFlags |= GetPlatformFlagFromPlatformIndex(platformId); + } + } + } + else if ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE) + { + for (int i = 0; i < NumPlatforms; ++i) + { + auto platformId = static_cast(i); + if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT && platformId != PlatformId::SERVER) + { + returnFlags |= GetPlatformFlagFromPlatformIndex(platformId); + } + } + } + else + { + returnFlags = platformFlags; + } - bool PlatformHelper::HasPlatformFlag(PlatformFlags flags, PlatformId checkPlatform) - { - // If checkPlatform contains any kind of invalid id, just exit out here - if(checkPlatform == PlatformId::Invalid || checkPlatform == NumPlatforms) - { - return false; + return returnFlags; } - // ALL_CLIENT + SERVER = ALL - if(HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT | PlatformFlags::Platform_SERVER)) + bool PlatformHelper::IsSpecialPlatform(PlatformFlags platformFlags) { - flags = PlatformFlags::Platform_ALL; + return (platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE + || (platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE; } - if(HasFlagHelper(flags, PlatformFlags::Platform_ALL)) + bool HasFlagHelper(PlatformFlags flags, PlatformFlags checkPlatform) { - // It doesn't matter what checkPlatform is set to in this case, just return true - return true; + return (flags & checkPlatform) == checkPlatform; } - if(HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT)) + + bool PlatformHelper::HasPlatformFlag(PlatformFlags flags, PlatformId checkPlatform) { - return checkPlatform != PlatformId::SERVER; - } + // If checkPlatform contains any kind of invalid id, just exit out here + if (checkPlatform == PlatformId::Invalid || checkPlatform == NumPlatforms) + { + return false; + } - return HasFlagHelper(flags, GetPlatformFlagFromPlatformIndex(checkPlatform)); - } + // ALL_CLIENT + SERVER = ALL + if (HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT | PlatformFlags::Platform_SERVER)) + { + flags = PlatformFlags::Platform_ALL; + } + if (HasFlagHelper(flags, PlatformFlags::Platform_ALL)) + { + // It doesn't matter what checkPlatform is set to in this case, just return true + return true; + } + + if (HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT)) + { + return checkPlatform != PlatformId::SERVER; + } + + return HasFlagHelper(flags, GetPlatformFlagFromPlatformIndex(checkPlatform)); + } + } } diff --git a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h index d7f467ec0f..2d67c860cd 100644 --- a/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h +++ b/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.h @@ -22,134 +22,136 @@ #pragma push_macro("IOS") #undef IOS -namespace AzFramework +namespace AZ { - constexpr char PlatformPC[] = "pc"; - constexpr char PlatformES3[] = "es3"; - constexpr char PlatformIOS[] = "ios"; - constexpr char PlatformOSX[] = "osx_gl"; - constexpr char PlatformProvo[] = "provo"; - constexpr char PlatformSalem[] = "salem"; - constexpr char PlatformJasper[] = "jasper"; - constexpr char PlatformServer[] = "server"; - - constexpr char PlatformCodeNameWindows[] = "Windows"; - constexpr char PlatformCodeNameLinux[] = "Linux"; - constexpr char PlatformCodeNameAndroid[] = "Android"; - constexpr char PlatformCodeNameiOS[] = "iOS"; - constexpr char PlatformCodeNameMac[] = "Mac"; - constexpr char PlatformCodeNameProvo[] = "Provo"; - constexpr char PlatformCodeNameSalem[] = "Salem"; - constexpr char PlatformCodeNameJasper[] = "Jasper"; - constexpr char PlatformAll[] = "all"; - constexpr char PlatformAllClient[] = "all_client"; - - // Used for the capacity of a fixed vector to store the code names of platforms - // The value needs to be higher than the number of unique OS platforms that are supported(at this time 8) - constexpr size_t MaxPlatformCodeNames = 16; - - //! This platform enum have platform values in sequence and can also be used to get the platform count. - AZ_ENUM_WITH_UNDERLYING_TYPE(PlatformId, int, - (Invalid, -1), - PC, - ES3, - IOS, - OSX, - PROVO, - SALEM, - JASPER, - SERVER, // Corresponds to the customer's flavor of "server" which could be windows, ubuntu, etc - ALL, - ALL_CLIENT, - - // Add new platforms above this - NumPlatformIds - ); - constexpr int NumClientPlatforms = 7; - constexpr int NumPlatforms = NumClientPlatforms + 1; // 1 "Server" platform currently - enum class PlatformFlags : AZ::u32 + inline namespace PlatformDefaults { - Platform_NONE = 0x00, - Platform_PC = 1 << PlatformId::PC, - Platform_ES3 = 1 << PlatformId::ES3, - Platform_IOS = 1 << PlatformId::IOS, - Platform_OSX = 1 << PlatformId::OSX, - Platform_PROVO = 1 << PlatformId::PROVO, - Platform_SALEM = 1 << PlatformId::SALEM, - Platform_JASPER = 1 << PlatformId::JASPER, - Platform_SERVER = 1 << PlatformId::SERVER, - - // A special platform that will always correspond to all platforms, even if new ones are added - Platform_ALL = 1ULL << 30, - - // A special platform that will always correspond to all non-server platforms, even if new ones are added - Platform_ALL_CLIENT = 1ULL << 31, - - AllNamedPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER, - }; - - AZ_DEFINE_ENUM_BITWISE_OPERATORS(PlatformFlags); - - // 32 characters should be more than enough to store a platform name - using AssetPlatformFixedString = AZStd::fixed_string<32>; - // Fixed string which can store a comma separated list of platforms names - // Additional byte is added to take into account the comma - using AssetPlatformCombinedString = AZStd::fixed_string<(AssetPlatformFixedString{}.max_size() + 1) * PlatformId::NumPlatformIds>; - - const char* PlatformIdToPalFolder(AzFramework::PlatformId platform); - - const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform); - - //! Platform Helper is an utility class that can be used to retrieve platform related information - class PlatformHelper - { - public: - - //! Given a platformIndex returns the platform name - static const char* GetPlatformName(PlatformId platform); - - //! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME. - static void AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, AZStd::string_view platformName); - - //! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME. - static void AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, PlatformId platformId); - - //! Given a platform name returns a platform index. - //! If the platform is not found, the method returns -1. - static int GetPlatformIndexFromName(AZStd::string_view platformName); - - //! Given a platform name returns a platform id. - //! If the platform is not found, the method returns -1. - static PlatformId GetPlatformIdFromName(AZStd::string_view platformName); - - //! Given a platformIndex returns the platformFlags - static PlatformFlags GetPlatformFlagFromPlatformIndex(PlatformId platform); - - //! Given a platformFlags returns all the platform identifiers that are set. - static AZStd::fixed_vector GetPlatforms(PlatformFlags platformFlags); - //! Given a platformFlags returns all the platform identifiers that are set, with special flags interpreted. Do not use the result for saving - static AZStd::fixed_vector GetPlatformsInterpreted(PlatformFlags platformFlags); - - //! Given a platformFlags return a list of PlatformId indices - static AZStd::fixed_vector GetPlatformIndices(PlatformFlags platformFlags); - //! Given a platformFlags return a list of PlatformId indices, with special flags interpreted. Do not use the result for saving - static AZStd::fixed_vector GetPlatformIndicesInterpreted(PlatformFlags platformFlags); - - //! Given a platform identifier returns its corresponding platform flag. - static PlatformFlags GetPlatformFlag(AZStd::string_view platform); - - //! Given any platformFlags returns a string listing the input platforms - static AssetPlatformCombinedString GetCommaSeparatedPlatformList(PlatformFlags platformFlags); - - //! If platformFlags contains any special flags, they are removed and replaced with the normal flags they represent - static PlatformFlags GetPlatformFlagsInterpreted(PlatformFlags platformFlags); - - //! Returns true if platformFlags contains any special flags - static bool IsSpecialPlatform(PlatformFlags platformFlags); - - //! Returns true if platformFlags has checkPlatform flag set. - static bool HasPlatformFlag(PlatformFlags platformFlags, PlatformId checkPlatform); - }; + constexpr char PlatformPC[] = "pc"; + constexpr char PlatformES3[] = "es3"; + constexpr char PlatformIOS[] = "ios"; + constexpr char PlatformOSX[] = "osx_gl"; + constexpr char PlatformProvo[] = "provo"; + constexpr char PlatformSalem[] = "salem"; + constexpr char PlatformJasper[] = "jasper"; + constexpr char PlatformServer[] = "server"; + + constexpr char PlatformCodeNameWindows[] = "Windows"; + constexpr char PlatformCodeNameLinux[] = "Linux"; + constexpr char PlatformCodeNameAndroid[] = "Android"; + constexpr char PlatformCodeNameiOS[] = "iOS"; + constexpr char PlatformCodeNameMac[] = "Mac"; + constexpr char PlatformCodeNameProvo[] = "Provo"; + constexpr char PlatformCodeNameSalem[] = "Salem"; + constexpr char PlatformCodeNameJasper[] = "Jasper"; + constexpr char PlatformAll[] = "all"; + constexpr char PlatformAllClient[] = "all_client"; + + // Used for the capacity of a fixed vector to store the code names of platforms + // The value needs to be higher than the number of unique OS platforms that are supported(at this time 8) + constexpr size_t MaxPlatformCodeNames = 16; + + //! This platform enum have platform values in sequence and can also be used to get the platform count. + AZ_ENUM_WITH_UNDERLYING_TYPE(PlatformId, int, + (Invalid, -1), + PC, + ES3, + IOS, + OSX, + PROVO, + SALEM, + JASPER, + SERVER, // Corresponds to the customer's flavor of "server" which could be windows, ubuntu, etc + ALL, + ALL_CLIENT, + + // Add new platforms above this + NumPlatformIds + ); + constexpr int NumClientPlatforms = 7; + constexpr int NumPlatforms = NumClientPlatforms + 1; // 1 "Server" platform currently + enum class PlatformFlags : AZ::u32 + { + Platform_NONE = 0x00, + Platform_PC = 1 << PlatformId::PC, + Platform_ES3 = 1 << PlatformId::ES3, + Platform_IOS = 1 << PlatformId::IOS, + Platform_OSX = 1 << PlatformId::OSX, + Platform_PROVO = 1 << PlatformId::PROVO, + Platform_SALEM = 1 << PlatformId::SALEM, + Platform_JASPER = 1 << PlatformId::JASPER, + Platform_SERVER = 1 << PlatformId::SERVER, + + // A special platform that will always correspond to all platforms, even if new ones are added + Platform_ALL = 1ULL << 30, + + // A special platform that will always correspond to all non-server platforms, even if new ones are added + Platform_ALL_CLIENT = 1ULL << 31, + + AllNamedPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER, + }; + + AZ_DEFINE_ENUM_BITWISE_OPERATORS(PlatformFlags); + + // 32 characters should be more than enough to store a platform name + using AssetPlatformFixedString = AZStd::fixed_string<32>; + // Fixed string which can store a comma separated list of platforms names + // Additional byte is added to take into account the comma + using AssetPlatformCombinedString = AZStd::fixed_string < (AssetPlatformFixedString{}.max_size() + 1)* PlatformId::NumPlatformIds > ; + + const char* PlatformIdToPalFolder(PlatformId platform); + + const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform); + + //! Platform Helper is an utility class that can be used to retrieve platform related information + class PlatformHelper + { + public: + + //! Given a platformIndex returns the platform name + static const char* GetPlatformName(PlatformId platform); + + //! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME. + static void AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, AZStd::string_view platformName); + + //! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME. + static void AppendPlatformCodeNames(AZStd::fixed_vector& platformCodes, PlatformId platformId); + + //! Given a platform name returns a platform index. + //! If the platform is not found, the method returns -1. + static int GetPlatformIndexFromName(AZStd::string_view platformName); + + //! Given a platform name returns a platform id. + //! If the platform is not found, the method returns -1. + static PlatformId GetPlatformIdFromName(AZStd::string_view platformName); + + //! Given a platformIndex returns the platformFlags + static PlatformFlags GetPlatformFlagFromPlatformIndex(PlatformId platform); + + //! Given a platformFlags returns all the platform identifiers that are set. + static AZStd::fixed_vector GetPlatforms(PlatformFlags platformFlags); + //! Given a platformFlags returns all the platform identifiers that are set, with special flags interpreted. Do not use the result for saving + static AZStd::fixed_vector GetPlatformsInterpreted(PlatformFlags platformFlags); + + //! Given a platformFlags return a list of PlatformId indices + static AZStd::fixed_vector GetPlatformIndices(PlatformFlags platformFlags); + //! Given a platformFlags return a list of PlatformId indices, with special flags interpreted. Do not use the result for saving + static AZStd::fixed_vector GetPlatformIndicesInterpreted(PlatformFlags platformFlags); + + //! Given a platform identifier returns its corresponding platform flag. + static PlatformFlags GetPlatformFlag(AZStd::string_view platform); + + //! Given any platformFlags returns a string listing the input platforms + static AssetPlatformCombinedString GetCommaSeparatedPlatformList(PlatformFlags platformFlags); + + //! If platformFlags contains any special flags, they are removed and replaced with the normal flags they represent + static PlatformFlags GetPlatformFlagsInterpreted(PlatformFlags platformFlags); + + //! Returns true if platformFlags contains any special flags + static bool IsSpecialPlatform(PlatformFlags platformFlags); + + //! Returns true if platformFlags has checkPlatform flag set. + static bool HasPlatformFlag(PlatformFlags platformFlags, PlatformId checkPlatform); + }; + } } - #pragma pop_macro("IOS") diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index e100b240c2..5357ed66a6 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -607,6 +607,8 @@ set(FILES Utils/Utils.h Script/lua/lua.h Memory/HeapSchema.cpp + PlatformId/PlatformDefaults.h + PlatformId/PlatformDefaults.cpp PlatformId/PlatformId.h PlatformId/PlatformId.cpp Socket/AzSocket_fwd.h diff --git a/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h b/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h new file mode 100644 index 0000000000..13f7fa20e5 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Platform/PlatformDefaults.h @@ -0,0 +1,23 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +// As the Platform defaults is needed within AzCore, +// those structures have been moved to AzCore and brought into +// The AzFramework namespace for backwards compatibility +namespace AzFramework +{ + using namespace AZ::PlatformDefaults; +} diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index cde2afb930..312a3766ac 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -317,7 +317,6 @@ set(FILES Terrain/TerrainDataRequestBus.h Terrain/TerrainDataRequestBus.cpp Platform/PlatformDefaults.h - Platform/PlatformDefaults.cpp Windowing/WindowBus.h Windowing/NativeWindow.cpp Windowing/NativeWindow.h From 603ee5bf838612125e962a4676897914a03251da Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Apr 2021 18:07:33 -0500 Subject: [PATCH 70/74] Updated the MergeSettingsToRegistry_AddRuntimeFilePaths to use the default asset platform associated with the OS, if the /Amazon/AzCore/Bootstrap/assets key isn't found in the settings registry --- .../Settings/SettingsRegistryMergeUtils.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 392e95bf6e..d68bdc97f3 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -463,18 +464,6 @@ namespace AZ::SettingsRegistryMergeUtils void MergeSettingsToRegistry_Bootstrap(SettingsRegistryInterface& registry) { ConfigParserSettings parserSettings; - parserSettings.m_commentPrefixFunc = [](AZStd::string_view line) -> AZStd::string_view - { - constexpr AZStd::string_view commentPrefixes[]{ "--", ";","#" }; - for (AZStd::string_view commentPrefix : commentPrefixes) - { - if (size_t commentOffset = line.find(commentPrefix); commentOffset != AZStd::string_view::npos) - { - return line.substr(0, commentOffset); - } - } - return line; - }; parserSettings.m_registryRootPointerPath = BootstrapSettingsRootKey; MergeSettingsToRegistry_ConfigFile(registry, "bootstrap.cfg", parserSettings); } @@ -501,9 +490,10 @@ namespace AZ::SettingsRegistryMergeUtils // and if that's missing just get "assets". constexpr char platformName[] = AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER; - SettingsRegistryInterface::FixedValueString assetPlatform; buffer = AZStd::fixed_string::format("%s/%s_assets", BootstrapSettingsRootKey, platformName); AZStd::string_view assetPlatformKey(buffer); + // Use the platform codename to retrieve the default asset platform value + SettingsRegistryInterface::FixedValueString assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME); if (!registry.Get(assetPlatform, assetPlatformKey)) { buffer = AZStd::fixed_string::format("%s/assets", BootstrapSettingsRootKey); From 41db22be3d0d1699850f840fcd75830af3d001b1 Mon Sep 17 00:00:00 2001 From: chiyenteng <82238204+chiyenteng@users.noreply.github.com> Date: Fri, 16 Apr 2021 17:06:58 -0700 Subject: [PATCH 71/74] [CherryPick][LYN-2738] Fix Reflect functions of IAnimSequence and CAnimSequence (#103) * [CherryPick][LYN-2738] Fix Reflect functions of IAnimSequence and CAnimSequence (#85) --- Code/CryEngine/CryCommon/IMovieSystem.h | 14 +++++- .../Code/Source/Cinematics/AnimSequence.cpp | 45 +++++++++++++------ .../Code/Source/Cinematics/AnimSequence.h | 2 +- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/Code/CryEngine/CryCommon/IMovieSystem.h b/Code/CryEngine/CryCommon/IMovieSystem.h index 654ccfd240..7a1125ae2b 100644 --- a/Code/CryEngine/CryCommon/IMovieSystem.h +++ b/Code/CryEngine/CryCommon/IMovieSystem.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -914,9 +915,18 @@ struct IAnimStringTable */ struct IAnimSequence { - AZ_RTTI(IAnimSequence, "{A60F95F5-5A4A-47DB-B3BB-525BBC0BC8DB}") + AZ_RTTI(IAnimSequence, "{A60F95F5-5A4A-47DB-B3BB-525BBC0BC8DB}"); + AZ_CLASS_ALLOCATOR(IAnimSequence, AZ::SystemAllocator, 0); - static const int kSequenceVersion = 4; + static const int kSequenceVersion = 5; + + static void Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context); serializeContext != nullptr) + { + serializeContext->Class(); + } + } //! Flags used for SetFlags(),GetFlags(),SetParentFlags(),GetParentFlags() methods. enum EAnimSequenceFlags diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp index 8d6c547c0e..ffbdce8ed6 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp @@ -823,20 +823,37 @@ void CAnimSequence::SetId(uint32 newId) } ////////////////////////////////////////////////////////////////////////// -void CAnimSequence::Reflect(AZ::SerializeContext* serializeContext) -{ - serializeContext->Class() - ->Version(4) - ->Field("Name", &CAnimSequence::m_name) - ->Field("SequenceEntityId", &CAnimSequence::m_sequenceEntityId) - ->Field("Flags", &CAnimSequence::m_flags) - ->Field("TimeRange", &CAnimSequence::m_timeRange) - ->Field("ID", &CAnimSequence::m_id) - ->Field("Nodes", &CAnimSequence::m_nodes) - ->Field("SequenceType", &CAnimSequence::m_sequenceType) - ->Field("Events", &CAnimSequence::m_events) - ->Field("Expanded", &CAnimSequence::m_expanded) - ->Field("ActiveDirectorNodeId", &CAnimSequence::m_activeDirectorNodeId); +static bool AnimSequenceVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 5) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid()); + } + + return true; +} + +void CAnimSequence::Reflect(AZ::ReflectContext* context) +{ + IAnimSequence::Reflect(context); + + if (auto serializeContext = azrtti_cast(context); serializeContext != nullptr) + { + serializeContext->Class() + ->Version(IAnimSequence::kSequenceVersion, &AnimSequenceVersionConverter) + ->Field("Name", &CAnimSequence::m_name) + ->Field("SequenceEntityId", &CAnimSequence::m_sequenceEntityId) + ->Field("Flags", &CAnimSequence::m_flags) + ->Field("TimeRange", &CAnimSequence::m_timeRange) + ->Field("ID", &CAnimSequence::m_id) + ->Field("Nodes", &CAnimSequence::m_nodes) + ->Field("SequenceType", &CAnimSequence::m_sequenceType) + ->Field("Events", &CAnimSequence::m_events) + ->Field("Expanded", &CAnimSequence::m_expanded) + ->Field("ActiveDirectorNodeId", &CAnimSequence::m_activeDirectorNodeId); + } } ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h index 3069896f50..d54b48c9eb 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h @@ -154,7 +154,7 @@ public: return m_nextTrackId++; } - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: void ComputeTimeRange(); From 37b4b69bb9d9330f08059a9de802016dd93940e7 Mon Sep 17 00:00:00 2001 From: mcgarrah <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 16 Apr 2021 20:07:20 -0500 Subject: [PATCH 72/74] Adding the */Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.* path to the pal allowed list to allow mention of the IOS macro in the PlatformDefaults.h/PlatformDefaults.cpp file --- scripts/commit_validation/commit_validation/pal_allowedlist.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/commit_validation/commit_validation/pal_allowedlist.txt b/scripts/commit_validation/commit_validation/pal_allowedlist.txt index 3b1dfdb3b9..278262d59c 100644 --- a/scripts/commit_validation/commit_validation/pal_allowedlist.txt +++ b/scripts/commit_validation/commit_validation/pal_allowedlist.txt @@ -17,6 +17,7 @@ */Code/Framework/AzCore/AzCore/Math/VectorFloat.h */Code/Framework/AzCore/AzCore/Memory/dlmalloc.inl */Code/Framework/AzCore/AzCore/Memory/nedmalloc.inl +*/Code/Framework/AzCore/AzCore/PlatformId/PlatformDefaults.* */Code/Framework/AzCore/AzCore/PlatformDef.h */Code/Framework/AzCore/AzCore/std/containers/compressed_pair.h */Code/Framework/AzCore/AzCore/std/containers/variant.h From 456bcb3bf9d04692849259310ef82d37ded2eef0 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Sun, 18 Apr 2021 14:57:52 -0700 Subject: [PATCH 73/74] Updated the EnvironmentCubeMapPipeline to match recent changes to the MainPipeline. Set the multisample state on the EnvironmentCubeMapPipeline render settings. --- .../Passes/EnvironmentCubeMapForwardMSAA.pass | 19 +-- .../Passes/EnvironmentCubeMapPipeline.pass | 114 +++--------------- .../Passes/EnvironmentCubeMapSkyBox.pass | 7 +- .../ReflectionProbe/ReflectionProbe.cpp | 3 + .../Pass/Specific/EnvironmentCubeMapPass.cpp | 12 +- 5 files changed, 44 insertions(+), 111 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass index 60de5e10b9..aa422aa227 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapForwardMSAA.pass @@ -49,11 +49,6 @@ "IsArray": 1 } }, - { - "Name": "DepthStencilInputOutput", - "SlotType": "InputOutput", - "ScopeAttachmentUsage": "DepthStencil" - }, { "Name": "TileLightData", "SlotType": "Input", @@ -66,6 +61,13 @@ "ShaderInputName": "m_lightListRemapped", "ScopeAttachmentUsage": "Shader" }, + // Input/Outputs... + { + "Name": "DepthStencilInputOutput", + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "DepthStencil" + }, + // Outputs... { "Name": "DiffuseOutput", "SlotType": "Output", @@ -222,11 +224,12 @@ "Attachment": "Output" } }, + "MultisampleSource": { + "Pass": "This", + "Attachment": "DepthStencilInputOutput" + }, "ImageDescriptor": { "Format": "R8G8B8A8_UNORM", - "MultisampleState": { - "samples": 4 - }, "SharedQueueMask": "Graphics" } }, diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass index 79a42b11f7..0e2fb93359 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapPipeline.pass @@ -9,7 +9,8 @@ "Slots": [ { "Name": "Output", - "SlotType": 2 + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "RenderTarget" } ], "PassRequests": [ @@ -101,13 +102,8 @@ ] }, { - "Name": "DepthMSAAPass", - "TemplateName": "EnvironmentCubeMapDepthMSAAPassTemplate", - "PassData": { - "$type": "RasterPassData", - "DrawListTag": "depth", - "PipelineViewTag": "MainCamera" - }, + "Name": "DepthPrePass", + "TemplateName": "DepthMSAAParentTemplate", "Connections": [ { "LocalSlot": "SkinnedMeshes", @@ -115,38 +111,19 @@ "Pass": "SkinningPass", "Attachment": "SkinnedMeshOutputStream" } - } - ] - }, - // The light culling system can do highly accurate culling of transparent objects but it needs - // more depth information than the opaque geometry pass can provide - // Specifically the minimum and maximum depth of transparent objects - { - "Name": "DepthTransparentMinPass", - "TemplateName": "DepthPassTemplate", - "PassData": { - "$type": "RasterPassData", - "DrawListTag": "depthTransparentMin", - "PipelineViewTag": "MainCamera" - }, - "Connections": [ + }, { - "LocalSlot": "SkinnedMeshes", + "LocalSlot": "SwapChainOutput", "AttachmentRef": { - "Pass": "SkinningPass", - "Attachment": "SkinnedMeshOutputStream" + "Pass": "Parent", + "Attachment": "Output" } } ] }, { - "Name": "DepthTransparentMaxPass", - "TemplateName": "DepthMaxPassTemplate", - "PassData": { - "$type": "RasterPassData", - "DrawListTag": "depthTransparentMax", - "PipelineViewTag": "MainCamera" - }, + "Name": "LightCullingPass", + "TemplateName": "LightCullingParentTemplate", "Connections": [ { "LocalSlot": "SkinnedMeshes", @@ -154,76 +131,23 @@ "Pass": "SkinningPass", "Attachment": "SkinnedMeshOutputStream" } - } - ] - }, - { - "Name": "LightCullingTilePreparePass", - "TemplateName": "LightCullingTilePrepareMSAATemplate", - "Connections": [ - { - "LocalSlot": "Depth", - "AttachmentRef": { - "Pass": "DepthMSAAPass", - "Attachment": "Output" - } }, { - "LocalSlot": "DepthTransparentMin", + "LocalSlot": "DepthMSAA", "AttachmentRef": { - "Pass": "DepthTransparentMinPass", - "Attachment": "Output" + "Pass": "DepthPrePass", + "Attachment": "DepthMSAA" } }, { - "LocalSlot": "DepthTransparentMax", + "LocalSlot": "SwapChainOutput", "AttachmentRef": { - "Pass": "DepthTransparentMaxPass", + "Pass": "Parent", "Attachment": "Output" } } ] }, - { - "Name": "LightCullingPass", - "TemplateName": "LightCullingTemplate", - "Connections": [ - { - "LocalSlot": "TileLightData", - "AttachmentRef": { - "Pass": "LightCullingTilePreparePass", - "Attachment": "TileLightData" - } - } - ] - }, - { - "Name": "LightCullingRemapPass", - "TemplateName": "LightCullingRemapTemplate", - "Connections": [ - { - "LocalSlot": "TileLightData", - "AttachmentRef": { - "Pass": "LightCullingTilePreparePass", - "Attachment": "TileLightData" - } - }, - { - "LocalSlot": "LightCount", - "AttachmentRef": { - "Pass": "LightCullingPass", - "Attachment": "LightCount" - } - }, - { - "LocalSlot": "LightList", - "AttachmentRef": { - "Pass": "LightCullingPass", - "Attachment": "LightList" - } - } - ] - }, { "Name": "ForwardMSAAPass", "TemplateName": "EnvironmentCubeMapForwardMSAAPassTemplate", @@ -259,21 +183,21 @@ { "LocalSlot": "DepthStencilInputOutput", "AttachmentRef": { - "Pass": "DepthMSAAPass", - "Attachment": "Output" + "Pass": "DepthPrePass", + "Attachment": "DepthMSAA" } }, { "LocalSlot": "TileLightData", "AttachmentRef": { - "Pass": "LightCullingRemapPass", + "Pass": "LightCullingPass", "Attachment": "TileLightData" } }, { "LocalSlot": "LightListRemapped", "AttachmentRef": { - "Pass": "LightCullingRemapPass", + "Pass": "LightCullingPass", "Attachment": "LightListRemapped" } } diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapSkyBox.pass b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapSkyBox.pass index b16cd1cbcc..4c74f9e967 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapSkyBox.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapSkyBox.pass @@ -32,11 +32,12 @@ "Attachment": "SpecularInputOutput" } }, + "MultisampleSource": { + "Pass": "This", + "Attachment": "SpecularInputOutput" + }, "ImageDescriptor": { "Format": "R16G16B16A16_FLOAT", - "MultisampleState": { - "samples": 4 - }, "SharedQueueMask": "Graphics" } } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 86c012731c..0826739119 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -248,6 +248,9 @@ namespace AZ AZ::RPI::RenderPipelineDescriptor environmentCubeMapPipelineDesc; environmentCubeMapPipelineDesc.m_mainViewTagName = "MainCamera"; + environmentCubeMapPipelineDesc.m_renderSettings.m_multisampleState.m_samples = 4; + environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_width = RPI::EnvironmentCubeMapPass::CubeMapFaceSize; + environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_height = RPI::EnvironmentCubeMapPass::CubeMapFaceSize; // create a unique name for the pipeline AZ::Uuid uuid = AZ::Uuid::CreateRandom(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp index 5ba43f9f7e..78d99de7d6 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp @@ -57,7 +57,7 @@ namespace AZ PassConnection childInputConnection; childInputConnection.m_localSlot = "Output"; childInputConnection.m_attachmentRef.m_pass = "Parent"; - childInputConnection.m_attachmentRef.m_attachment = "CubeMapOutput"; + childInputConnection.m_attachmentRef.m_attachment = "Output"; childRequest.m_connections.emplace_back(childInputConnection); PassSystemInterface* passSystem = PassSystemInterface::Get(); @@ -120,15 +120,17 @@ namespace AZ // create output PassAttachment m_passAttachment = aznew PassAttachment(); - m_passAttachment->m_name = "CubeMapOutput"; - m_passAttachment->m_path = "CubeMapOutput"; + m_passAttachment->m_name = "Output"; + //m_passAttachment->m_path = "Output"; + AZ::Name attachmentPath(AZStd::string::format("%s.%s", GetPathName().GetCStr(), m_passAttachment->m_name.GetCStr())); + m_passAttachment->m_path = attachmentPath; m_passAttachment->m_lifetime = RHI::AttachmentLifetimeType::Transient; m_passAttachment->m_descriptor = m_outputImageDesc; // create pass attachment binding PassAttachmentBinding outputAttachment; - outputAttachment.m_name = "CubeMapOutput"; - outputAttachment.m_slotType = PassSlotType::Output; + outputAttachment.m_name = "Output"; + outputAttachment.m_slotType = PassSlotType::InputOutput; outputAttachment.m_attachment = m_passAttachment; outputAttachment.m_scopeAttachmentUsage = RHI::ScopeAttachmentUsage::RenderTarget; From 46b9f1934de4f8bb280526104fb3e042d50696a1 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Sun, 18 Apr 2021 23:15:02 -0700 Subject: [PATCH 74/74] Removed commented line --- .../Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp index 78d99de7d6..c72712bce5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/EnvironmentCubeMapPass.cpp @@ -121,7 +121,6 @@ namespace AZ // create output PassAttachment m_passAttachment = aznew PassAttachment(); m_passAttachment->m_name = "Output"; - //m_passAttachment->m_path = "Output"; AZ::Name attachmentPath(AZStd::string::format("%s.%s", GetPathName().GetCStr(), m_passAttachment->m_name.GetCStr())); m_passAttachment->m_path = attachmentPath; m_passAttachment->m_lifetime = RHI::AttachmentLifetimeType::Transient;