From 2fb2813b485f624cef957c68310e47e3597c51bc Mon Sep 17 00:00:00 2001 From: greerdv Date: Wed, 14 Apr 2021 14:05:59 +0100 Subject: [PATCH 001/277] updating atom mesh component to support non-uniform scale component --- Code/Framework/AzCore/AzCore/Math/Aabb.cpp | 31 ++++++++++++++- Code/Framework/AzCore/AzCore/Math/Aabb.h | 10 ++++- Code/Framework/AzCore/AzCore/Math/Aabb.inl | 8 ++++ .../Atom/Feature/Mesh/MeshFeatureProcessor.h | 4 +- .../Mesh/MeshFeatureProcessorInterface.h | 8 ++-- .../ReflectionProbeFeatureProcessor.h | 2 +- ...ReflectionProbeFeatureProcessorInterface.h | 2 +- .../TransformServiceFeatureProcessor.h | 4 +- ...ransformServiceFeatureProcessorInterface.h | 8 ++-- .../Code/Mocks/MockMeshFeatureProcessor.h | 4 +- .../Code/Source/AuxGeom/AuxGeomDrawQueue.cpp | 2 +- .../DiffuseProbeGridRayTracingPass.cpp | 8 ++-- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 18 ++++----- .../RayTracingAccelerationStructurePass.cpp | 2 +- .../RayTracing/RayTracingFeatureProcessor.cpp | 6 +-- .../RayTracing/RayTracingFeatureProcessor.h | 4 +- .../ReflectionProbe/ReflectionProbe.cpp | 8 ++-- .../Source/ReflectionProbe/ReflectionProbe.h | 2 +- .../ReflectionProbeFeatureProcessor.cpp | 8 ++-- .../TransformServiceFeatureProcessor.cpp | 8 ++-- .../RHI/RayTracingAccelerationStructure.h | 6 +-- .../RHI/RayTracingAccelerationStructure.cpp | 6 +-- .../DX12/Code/Source/RHI/RayTracingTlas.cpp | 3 +- .../Vulkan/Code/Source/RHI/RayTracingTlas.cpp | 4 +- .../Include/Atom/RPI.Public/Model/Model.h | 4 +- .../Code/Source/RPI.Public/Model/Model.cpp | 6 +-- .../Code/Source/Mesh/EditorMeshComponent.cpp | 5 ++- .../Source/Mesh/MeshComponentController.cpp | 38 ++++++++++++++++--- .../Source/Mesh/MeshComponentController.h | 10 +++++ .../ReflectionProbeComponentController.cpp | 2 +- .../Code/Source/AtomActorInstance.cpp | 5 ++- .../Editor/EditorBlastMeshDataComponent.cpp | 4 +- .../Code/Source/Family/ActorRenderManager.cpp | 6 +-- .../Code/Tests/ActorRenderManagerTest.cpp | 2 +- .../Rendering/Atom/WhiteBoxAtomRenderMesh.cpp | 2 +- 35 files changed, 166 insertions(+), 84 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp index 94e138d88d..48e51cce48 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp @@ -146,8 +146,8 @@ namespace AZ ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) ->Method("GetTranslated", &Aabb::GetTranslated) ->Method("GetSurfaceArea", &Aabb::GetSurfaceArea) - ->Method("GetTransformedObb", &Aabb::GetTransformedObb) - ->Method("GetTransformedAabb", &Aabb::GetTransformedAabb) + ->Method("GetTransformedObb", static_cast(&Aabb::GetTransformedObb)) + ->Method("GetTransformedAabb", static_cast(&Aabb::GetTransformedAabb)) ->Method("ApplyTransform", &Aabb::ApplyTransform) ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) ->Method("Clone", [](const Aabb& rhs) -> Aabb { return rhs; }) @@ -195,6 +195,20 @@ namespace AZ } + Obb Aabb::GetTransformedObb(const Matrix3x4& matrix3x4) const + { + Matrix3x4 matrixNoScale = matrix3x4; + const AZ::Vector3 scale = matrixNoScale.ExtractScale(); + const AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x4(matrixNoScale); + + return Obb::CreateFromPositionRotationAndHalfLengths( + matrix3x4 * GetCenter(), + rotation, + 0.5f * scale * GetExtents() + ); + } + + void Aabb::ApplyTransform(const Transform& transform) { Vector3 a, b, axisCoeffs; @@ -224,4 +238,17 @@ namespace AZ m_min = newMin; m_max = newMax; } + + + void Aabb::ApplyMatrix3x4(const Matrix3x4& matrix3x4) + { + const AZ::Vector3 extents = GetExtents(); + const AZ::Vector3 center = GetCenter(); + AZ::Vector3 newHalfExtents( + 0.5f * matrix3x4.GetRowAsVector3(0).GetAbs().Dot(extents), + 0.5f * matrix3x4.GetRowAsVector3(1).GetAbs().Dot(extents), + 0.5f * matrix3x4.GetRowAsVector3(2).GetAbs().Dot(extents)); + m_min = center - newHalfExtents; + m_max = center + newHalfExtents; + } } diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.h b/Code/Framework/AzCore/AzCore/Math/Aabb.h index 0aebd099f4..474ac2e2ee 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.h +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.h @@ -129,12 +129,20 @@ namespace AZ void ApplyTransform(const Transform& transform); + void ApplyMatrix3x4(const Matrix3x4& matrix3x4); + + //! Transforms an Aabb and returns the resulting Obb. + Obb GetTransformedObb(const Transform& transform) const; + //! Transforms an Aabb and returns the resulting Obb. - class Obb GetTransformedObb(const Transform& transform) const; + Obb GetTransformedObb(const Matrix3x4& matrix3x4) const; //! Returns a new AABB containing the transformed AABB. Aabb GetTransformedAabb(const Transform& transform) const; + //! Returns a new AABB containing the transformed AABB. + Aabb GetTransformedAabb(const Matrix3x4& matrix3x4) const; + //! Checks if this aabb is equal to another within a floating point tolerance. bool IsClose(const Aabb& rhs, float tolerance = Constants::Tolerance) const; diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.inl b/Code/Framework/AzCore/AzCore/Math/Aabb.inl index 5e6a5ae188..94ad3e3e7d 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.inl +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.inl @@ -300,6 +300,14 @@ namespace AZ } + AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Matrix3x4& matrix3x4) const + { + Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max); + aabb.ApplyMatrix3x4(matrix3x4); + return aabb; + } + + AZ_MATH_INLINE bool Aabb::IsClose(const Aabb& rhs, float tolerance) const { return m_min.IsClose(rhs.m_min, tolerance) && m_max.IsClose(rhs.m_max, tolerance); 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..cc26ff862a 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 @@ -144,8 +144,8 @@ namespace AZ const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const override; void ConnectModelChangeEventHandler(const MeshHandle& meshHandle, ModelChangedEvent::Handler& handler) override; - void SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform) override; - Transform GetTransform(const MeshHandle& meshHandle) override; + void SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) override; + Matrix3x4 GetMatrix3x4(const MeshHandle& meshHandle) override; void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index 77e3467fb9..ef8084d534 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -61,10 +61,10 @@ namespace AZ virtual const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const = 0; //! Connects a handler to any changes to an RPI::Model. Changes include loading and reloading. virtual void ConnectModelChangeEventHandler(const MeshHandle& meshHandle, ModelChangedEvent::Handler& handler) = 0; - //! Sets the transform for a given mesh handle. - virtual void SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform) = 0; - //! Gets the transform for a given mesh handle. - virtual Transform GetTransform(const MeshHandle& meshHandle) = 0; + //! Sets the Matrix3x4 for a given mesh handle. + virtual void SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) = 0; + //! Gets the Matrix3x4 for a given mesh handle. + virtual Matrix3x4 GetMatrix3x4(const MeshHandle& meshHandle) = 0; //! Sets the sort key for a given mesh handle. virtual void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) = 0; //! Gets the sort key for a given mesh handle. diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h index a89875aaa6..610bb40369 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h @@ -37,7 +37,7 @@ namespace AZ void SetProbeOuterExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& outerExtents) override; void SetProbeInnerExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& innerExtents) override; void SetProbeCubeMap(const ReflectionProbeHandle& probe, Data::Instance& cubeMapImage) override; - void SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform) override; + void SetProbeMatrix3x4(const ReflectionProbeHandle& probe, const AZ::Matrix3x4& matrix3x4) override; void BakeProbe(const ReflectionProbeHandle& probe, BuildCubeMapCallback callback) override; void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) override; bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const override { return (probe.get() != nullptr); } diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h index 8b277e97c8..3053d9d44f 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h @@ -48,7 +48,7 @@ namespace AZ virtual void SetProbeOuterExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& outerExtents) = 0; virtual void SetProbeInnerExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& innerExtents) = 0; virtual void SetProbeCubeMap(const ReflectionProbeHandle& handle, Data::Instance& cubeMapImage) = 0; - virtual void SetProbeTransform(const ReflectionProbeHandle& handle, const AZ::Transform& transform) = 0; + virtual void SetProbeMatrix3x4(const ReflectionProbeHandle& handle, const AZ::Matrix3x4& matrix3x4) = 0; virtual void BakeProbe(const ReflectionProbeHandle& handle, BuildCubeMapCallback callback) = 0; virtual void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) = 0; virtual bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const = 0; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h index 2344f745f8..d6338d6b0c 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h @@ -50,8 +50,8 @@ namespace AZ // TransformServiceFeatureProcessorInterface overrides ... ObjectId ReserveObjectId() override; void ReleaseObjectId(ObjectId& id) override; - void SetTransformForId(ObjectId id, const AZ::Transform& transform) override; - AZ::Transform GetTransformForId(ObjectId id) const override; + void SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& matrix3x4) override; + AZ::Matrix3x4 GetMatrix3x4ForId(ObjectId id) const override; private: diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h index 0b17a9a5a0..b75257c485 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h @@ -34,10 +34,10 @@ namespace AZ //! Releases an object ID to be used by others. The passed in handle is invalidated. virtual void ReleaseObjectId(ObjectId& id) = 0; - //! Sets the transform for a given id. Id must be one reserved earlier. - virtual void SetTransformForId(ObjectId id, const AZ::Transform& transform) = 0; - //! Gets the transform for a given id. Id must be one reserved earlier. - virtual AZ::Transform GetTransformForId(ObjectId) const = 0; + //! Sets the Matrix3x4 for a given id. Id must be one reserved earlier. + virtual void SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& transform) = 0; + //! Gets the Matrix3x4 for a given id. Id must be one reserved earlier. + virtual AZ::Matrix3x4 GetMatrix3x4ForId(ObjectId) const = 0; }; } diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index 6fc1ac0e30..b6428754b5 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -31,11 +31,11 @@ namespace UnitTest MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr(const MeshHandle&)); MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&)); MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&)); - MOCK_METHOD2(SetTransform, void(const MeshHandle&, const AZ::Transform&)); + MOCK_METHOD2(SetMatrix3x4, void(const MeshHandle&, const AZ::Matrix3x4&)); MOCK_METHOD2(SetExcludeFromReflectionCubeMaps, void(const MeshHandle&, bool)); MOCK_METHOD2(SetMaterialAssignmentMap, void(const MeshHandle&, const AZ::Data::Instance&)); MOCK_METHOD2(SetMaterialAssignmentMap, void(const MeshHandle&, const AZ::Render::MaterialAssignmentMap&)); - MOCK_METHOD1(GetTransform, AZ::Transform (const MeshHandle&)); + MOCK_METHOD1(GetMatrix3x4, AZ::Matrix3x4 (const MeshHandle&)); MOCK_METHOD2(SetSortKey, void (const MeshHandle&, AZ::RHI::DrawItemSortKey)); MOCK_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&)); MOCK_METHOD2(SetLodOverride, void(const MeshHandle&, AZ::RPI::Cullable::LodOverride)); diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp index fd4b5b28d1..c412746676 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp @@ -504,7 +504,7 @@ namespace AZ box.m_faceCullMode = ConvertRPIFaceCullFlag(faceCull); box.m_color = color; box.m_scale = localMatrix3x4.ExtractScale() * extents; - box.m_position = localMatrix3x4.GetTranslation() + center; + box.m_position = matrix3x4 * center; box.m_rotationMatrix = Matrix3x3::CreateFromMatrix3x4(localMatrix3x4); box.m_pointSize = m_pointSize; box.m_viewProjOverrideIndex = viewProjOverrideIndex; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp index f6eeaf2971..f5e4f29cea 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp @@ -186,10 +186,10 @@ namespace AZ // set irradiance color and worldInverseTranspose constants Vector4 color(subMesh.m_irradianceColor.GetR(), subMesh.m_irradianceColor.GetG(), subMesh.m_irradianceColor.GetB(), 1.0f); - AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); - AZ::Transform noScaleTransform = meshTransform; - noScaleTransform.ExtractScale(); - AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform); + AZ::Matrix3x4 meshMatrix3x4 = transformFeatureProcessor->GetMatrix3x4ForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); + AZ::Matrix3x4 noScaleMatrix3x4 = meshMatrix3x4; + noScaleMatrix3x4.ExtractScale(); + AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromMatrix3x4(noScaleMatrix3x4); rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose(); m_closestHitData[m_meshCount].m_materialColor = color; diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 1f5b8ecc65..40873ccea0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -256,7 +256,7 @@ namespace AZ } } - void MeshFeatureProcessor::SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform) + void MeshFeatureProcessor::SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) { if (meshHandle.IsValid()) { @@ -264,26 +264,26 @@ namespace AZ meshData.m_cullBoundsNeedsUpdate = true; meshData.m_objectSrgNeedsUpdate = true; - m_transformService->SetTransformForId(meshHandle->m_objectId, transform); + m_transformService->SetMatrix3x4ForId(meshHandle->m_objectId, matrix3x4); // ray tracing data needs to be updated with the new transform if (m_rayTracingFeatureProcessor) { - m_rayTracingFeatureProcessor->SetMeshTransform(meshHandle->m_objectId, transform); + m_rayTracingFeatureProcessor->SetMeshMatrix3x4(meshHandle->m_objectId, matrix3x4); } } } - Transform MeshFeatureProcessor::GetTransform(const MeshHandle& meshHandle) + Matrix3x4 MeshFeatureProcessor::GetMatrix3x4(const MeshHandle& meshHandle) { if (meshHandle.IsValid()) { - return m_transformService->GetTransformForId(meshHandle->m_objectId); + return m_transformService->GetMatrix3x4ForId(meshHandle->m_objectId); } else { AZ_Assert(false, "Invalid mesh handle"); - return Transform::CreateIdentity(); + return Matrix3x4::CreateIdentity(); } } @@ -841,7 +841,7 @@ namespace AZ AZ_Assert(m_cullBoundsNeedsUpdate, "This function only needs to be called if the culling bounds need to be rebuilt"); AZ_Assert(m_model, "The model has not finished loading yet"); - Transform localToWorld = transformService->GetTransformForId(m_objectId); + Matrix3x4 localToWorld = transformService->GetMatrix3x4ForId(m_objectId); Vector3 center; float radius; @@ -919,11 +919,11 @@ namespace AZ // retrieve the list of probes that contain the centerpoint of the mesh TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor(); - Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId); + Matrix3x4 matrix3x4 = transformServiceFeatureProcessor->GetMatrix3x4ForId(m_objectId); ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor(); ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes; - reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes); + reflectionProbeFeatureProcessor->FindReflectionProbes(matrix3x4.GetTranslation(), reflectionProbes); if (!reflectionProbes.empty() && reflectionProbes[0]) { diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp index f874f87b4a..7e39f968fd 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp @@ -83,7 +83,7 @@ namespace AZ ->InstanceID(blasIndex) ->HitGroupIndex(blasIndex) ->Blas(rayTracingSubMesh.m_blas) - ->Transform(rayTracingMesh.second.m_transform) + ->Matrix3x4(rayTracingMesh.second.m_matrix3x4) ; } diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index abced377a0..1e7fc464df 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -97,7 +97,7 @@ namespace AZ } // set initial transform - mesh.m_transform = m_transformServiceFeatureProcessor->GetTransformForId(objectId); + mesh.m_matrix3x4 = m_transformServiceFeatureProcessor->GetMatrix3x4ForId(objectId); m_revision++; m_subMeshCount += aznumeric_cast(subMeshes.size()); @@ -119,7 +119,7 @@ namespace AZ } } - void RayTracingFeatureProcessor::SetMeshTransform(const ObjectId objectId, AZ::Transform transform) + void RayTracingFeatureProcessor::SetMeshMatrix3x4(const ObjectId objectId, const AZ::Matrix3x4 matrix3x4) { if (!m_rayTracingEnabled) { @@ -129,7 +129,7 @@ namespace AZ MeshMap::iterator itMesh = m_meshes.find(objectId.GetIndex()); if (itMesh != m_meshes.end()) { - itMesh->second.m_transform = transform; + itMesh->second.m_matrix3x4 = matrix3x4; m_revision++; } } diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h index 09a4a6f63c..af5bfd0d51 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h @@ -66,7 +66,7 @@ namespace AZ SubMeshVector m_subMeshes; // mesh transform - AZ::Transform m_transform = AZ::Transform::CreateIdentity(); + AZ::Matrix3x4 m_matrix3x4 = AZ::Matrix3x4::CreateIdentity(); // flag indicating if the Blas objects in the sub-meshes are built bool m_blasBuilt = false; @@ -85,7 +85,7 @@ namespace AZ //! Sets the ray tracing mesh transform //! This will cause an update to the RayTracing acceleration structure on the next frame - void SetMeshTransform(const ObjectId objectId, const AZ::Transform transform); + void SetMeshMatrix3x4(const ObjectId objectId, const AZ::Matrix3x4 matrix3x4); //! Retrieves ray tracing data for all meshes in the scene const MeshMap& GetMeshes() const { return m_meshes; } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 51303436ee..f56902ebde 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -70,7 +70,7 @@ namespace AZ m_visualizationMeshHandle = m_meshFeatureProcessor->AcquireMesh(m_visualizationModelAsset); m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_visualizationMeshHandle, true); m_meshFeatureProcessor->SetRayTracingEnabled(m_visualizationMeshHandle, false); - m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, AZ::Transform::CreateIdentity()); + m_meshFeatureProcessor->SetMatrix3x4(m_visualizationMeshHandle, AZ::Matrix3x4::CreateIdentity()); // We have to pre-load this asset before creating a Material instance because the InstanceDatabase will attempt a blocking load which could deadlock, // particularly when slices are involved. @@ -206,10 +206,10 @@ namespace AZ } - void ReflectionProbe::SetTransform(const AZ::Transform& transform) + void ReflectionProbe::SetMatrix3x4(const AZ::Matrix3x4& matrix3x4) { - m_position = transform.GetTranslation(); - m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, transform); + m_position = matrix3x4.GetTranslation(); + m_meshFeatureProcessor->SetMatrix3x4(m_visualizationMeshHandle, matrix3x4); m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_outerExtents / 2.0f); m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_innerExtents / 2.0f); m_updateSrg = true; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index 22645a4ed3..6b23afb1fc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -76,7 +76,7 @@ namespace AZ void Simulate(uint32_t probeIndex); const Vector3& GetPosition() const { return m_position; } - void SetTransform(const AZ::Transform& transform); + void SetMatrix3x4(const AZ::Matrix3x4& matrix3x4); const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; } void SetOuterExtents(const AZ::Vector3& outerExtents); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index 80719564b1..8631e334b4 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -223,7 +223,7 @@ namespace AZ { AZStd::shared_ptr reflectionProbe = AZStd::make_shared(); reflectionProbe->Init(GetParentScene(), &m_reflectionRenderData); - reflectionProbe->SetTransform(transform); + reflectionProbe->SetMatrix3x4(AZ::Matrix3x4::CreateFromTransform(transform)); reflectionProbe->SetUseParallaxCorrection(useParallaxCorrection); m_reflectionProbes.push_back(reflectionProbe); m_probeSortRequired = true; @@ -264,10 +264,10 @@ namespace AZ probe->SetCubeMapImage(cubeMapImage); } - void ReflectionProbeFeatureProcessor::SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform) + void ReflectionProbeFeatureProcessor::SetProbeMatrix3x4(const ReflectionProbeHandle& probe, const AZ::Matrix3x4& matrix3x4) { - AZ_Assert(probe.get(), "SetProbeTransform called with an invalid handle"); - probe->SetTransform(transform); + AZ_Assert(probe.get(), "SetProbeMatrix3x4 called with an invalid handle"); + probe->SetMatrix3x4(matrix3x4); m_probeSortRequired = true; } diff --git a/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp index a4f255185a..a3a91ca620 100644 --- a/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp @@ -210,14 +210,12 @@ namespace AZ } } - void TransformServiceFeatureProcessor::SetTransformForId(ObjectId id, const AZ::Transform& transform) + void TransformServiceFeatureProcessor::SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& matrix3x4) { AZ_Error("TransformServiceFeatureProcessor", m_isWriteable, "Transform data cannot be written to during this phase"); AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to set the transform for an invalid handle."); if (id.IsValid()) { - AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(transform); - matrix3x4.StoreToRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform); // Inverse transpose to take the non-uniform scale out of the transform for usage with normals. @@ -226,10 +224,10 @@ namespace AZ } } - AZ::Transform TransformServiceFeatureProcessor::GetTransformForId(ObjectId id) const + AZ::Matrix3x4 TransformServiceFeatureProcessor::GetMatrix3x4ForId(ObjectId id) const { AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to set the transform for an invalid handle."); - return AZ::Transform::CreateFromMatrix3x4( Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform) ); + return AZ::Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform); } } } diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h index 09ba2b1d59..0225673efd 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h @@ -12,7 +12,7 @@ #pragma once #include -#include +#include #include #include #include @@ -110,7 +110,7 @@ namespace AZ { uint32_t m_instanceID = 0; uint32_t m_hitGroupIndex = 0; - AZ::Transform m_transform = AZ::Transform::CreateIdentity(); + AZ::Matrix3x4 m_matrix3x4 = AZ::Matrix3x4::CreateIdentity(); RHI::Ptr m_blas; }; using RayTracingTlasInstanceVector = AZStd::vector; @@ -153,7 +153,7 @@ namespace AZ RayTracingTlasDescriptor* Instance(); RayTracingTlasDescriptor* InstanceID(uint32_t instanceID); RayTracingTlasDescriptor* HitGroupIndex(uint32_t hitGroupIndex); - RayTracingTlasDescriptor* Transform(const AZ::Transform& transform); + RayTracingTlasDescriptor* Matrix3x4(const AZ::Matrix3x4& matrix3x4); RayTracingTlasDescriptor* Blas(RHI::Ptr& blas); RayTracingTlasDescriptor* InstancesBuffer(RHI::Ptr& tlasInstances); RayTracingTlasDescriptor* NumInstances(uint32_t numInstancesInBuffer); diff --git a/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp b/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp index 37e5b316d6..dadaeee5d4 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp @@ -78,10 +78,10 @@ namespace AZ return this; } - RayTracingTlasDescriptor* RayTracingTlasDescriptor::Transform(const AZ::Transform& transform) + RayTracingTlasDescriptor* RayTracingTlasDescriptor::Matrix3x4(const AZ::Matrix3x4& matrix3x4) { - AZ_Assert(m_buildContext, "Transform property can only be added to an Instance entry"); - m_buildContext->m_transform = transform; + AZ_Assert(m_buildContext, "Matrix3x4 property can only be added to an Instance entry"); + m_buildContext->m_matrix3x4 = matrix3x4; return this; } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp index 77d8d38e42..8c01b798a6 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp @@ -89,8 +89,7 @@ namespace AZ mappedData[i].InstanceID = instance.m_instanceID; mappedData[i].InstanceContributionToHitGroupIndex = instance.m_hitGroupIndex; // convert transform to row-major 3x4 - AZ::Matrix3x4 matrix34 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform); - matrix34.StoreToRowMajorFloat12(&mappedData[i].Transform[0][0]); + instance.m_matrix3x4.StoreToRowMajorFloat12(&mappedData[i].Transform[0][0]); mappedData[i].AccelerationStructure = static_cast(blas->GetBuffers().m_blasBuffer.get())->GetMemoryView().GetGpuAddress(); // [GFX TODO][ATOM-5270] Add ray tracing TLAS instance mask support mappedData[i].InstanceMask = 0x1; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp index 9720fecb6d..161104060e 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp @@ -92,9 +92,7 @@ namespace AZ mappedData[i].instanceCustomIndex = instance.m_instanceID; mappedData[i].instanceShaderBindingTableRecordOffset = instance.m_hitGroupIndex; - // convert transform to row-major 3x4 - AZ::Matrix3x4 matrix34 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform); - matrix34.StoreToRowMajorFloat12(&mappedData[i].transform.matrix[0][0]); + instance.m_matrix3x4.StoreToRowMajorFloat12(&mappedData[i].transform.matrix[0][0]); RayTracingBlas* blas = static_cast(instance.m_blas.get()); VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {}; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h index 5cd464962b..ada429ee05 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h @@ -72,11 +72,13 @@ namespace AZ //! [GFX TODO][ATOM-4343 Bake mesh spatial during AP processing] //! //! @param modelTransform a transform that puts the model into the ray's coordinate space + //! @param nonUniformScale Non-uniform scale applied in the model's local frame. //! @param rayStart position where the ray starts //! @param dir direction where the ray ends (does not have to be unit length) //! @param distanceFactor if an intersection is detected, this will be set such that distanceFactor * dir.length == distance to intersection //! @return true if the ray intersects the mesh - bool RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const; + bool RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, + const AZ::Vector3& dir, float& distanceFactor) const; //! Get available UV names from the model and its lods. const AZStd::unordered_set& GetUvNames() const; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp index 84c10cb272..ad56b6e33a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp @@ -164,15 +164,15 @@ namespace AZ return false; } - bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const + bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); const AZ::Transform inverseTM = modelTransform.GetInverse(); - const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart); + const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart) / nonUniformScale; // Instead of just rotating 'dir' we need it to be scaled too, so that 'distanceFactor' will be in the target units rather than object local units. const AZ::Vector3 rayDest = rayStart + dir; - const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest); + const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest) / nonUniformScale; const AZ::Vector3 rayDirLocal = rayDestLocal - raySrcLocal; return LocalRayIntersection(raySrcLocal, rayDirLocal, distanceFactor); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index 0afe96588f..86a3c12557 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -137,7 +137,10 @@ namespace AZ AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - return m_controller.GetModel()->RayIntersection(transform, src, dir, distance); + AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne(); + AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, GetEntityId(), &AZ::NonUniformScaleRequests::GetScale); + + return m_controller.GetModel()->RayIntersection(transform, nonUniformScale, src, dir, distance); } bool EditorMeshComponent::SupportsEditorRayIntersect() diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index db64d26a54..1404db717f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -180,6 +180,11 @@ namespace AZ m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity(m_entityId); AZ_Error("MeshComponentController", m_meshFeatureProcessor, "Unable to find a MeshFeatureProcessorInterface on the entityId."); + m_cachedNonUniformScale = AZ::Vector3::CreateOne(); + AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale); + AZ::NonUniformScaleRequestBus::Event(m_entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent, + m_nonUniformScaleChangedHandler); + MeshComponentRequestBus::Handler::BusConnect(m_entityId); TransformNotificationBus::Handler::BusConnect(m_entityId); MaterialReceiverRequestBus::Handler::BusConnect(m_entityId); @@ -216,11 +221,24 @@ namespace AZ return m_configuration; } - void MeshComponentController::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) + void MeshComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, [[maybe_unused]] const AZ::Transform& world) + { + UpdateOverallMatrix(); + } + + void MeshComponentController::HandleNonUniformScaleChange(const AZ::Vector3 & nonUniformScale) + { + m_cachedNonUniformScale = nonUniformScale; + UpdateOverallMatrix(); + } + + void MeshComponentController::UpdateOverallMatrix() { if (m_meshFeatureProcessor) { - m_meshFeatureProcessor->SetTransform(m_meshHandle, world); + Matrix3x4 world = Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()); + world.MultiplyByScale(m_cachedNonUniformScale); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, world); } } @@ -266,8 +284,8 @@ namespace AZ m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials); m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler); - const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : Transform::Identity(); - m_meshFeatureProcessor->SetTransform(m_meshHandle, transform); + const AZ::Matrix3x4& matrix3x4 = m_transformInterface ? Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()) : Matrix3x4::Identity(); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, matrix3x4); m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey); m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride); m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps); @@ -403,7 +421,17 @@ namespace AZ Aabb MeshComponentController::GetLocalBounds() { const Data::Instance model = GetModel(); - return model ? model->GetAabb() : Aabb::CreateNull(); + if (model) + { + Aabb aabb = model->GetAabb(); + aabb.SetMin(aabb.GetMin() * m_cachedNonUniformScale); + aabb.SetMax(aabb.GetMax() * m_cachedNonUniformScale); + return aabb; + } + else + { + return Aabb::CreateNull(); + } } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 184756d931..68c7ed8063 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -14,6 +14,7 @@ #include #include +#include #include @@ -120,17 +121,26 @@ namespace AZ void UnregisterModel(); void RefreshModelRegistration(); + void HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale); + void UpdateOverallMatrix(); + Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; Render::MeshFeatureProcessorInterface::MeshHandle m_meshHandle; TransformInterface* m_transformInterface = nullptr; AZ::EntityId m_entityId; bool m_isVisible = true; MeshComponentConfig m_configuration; + AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne(); MeshFeatureProcessorInterface::ModelChangedEvent::Handler m_changeEventHandler { [&](Data::Instance model) { HandleModelChange(model); } }; + + AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler + { + [&](const AZ::Vector3& nonUniformScale) { HandleNonUniformScaleChange(nonUniformScale); } + }; }; } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp index 005e9a6ff5..57aaa6a83f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp @@ -199,7 +199,7 @@ namespace AZ return; } - m_featureProcessor->SetProbeTransform(m_handle, world); + m_featureProcessor->SetProbeMatrix3x4(m_handle, Matrix3x4::CreateFromTransform(world)); } void ReflectionProbeComponentController::OnShapeChanged(ShapeChangeReasons changeReason) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index b0d52e0776..fd98dfe666 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -187,8 +187,9 @@ namespace AZ void AtomActorInstance::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) { - // The mesh transform is used to determine where the actor instance is actually rendered - m_meshFeatureProcessor->SetTransform(*m_meshHandle, world); // handle validity is checked internally. + // The mesh Matrix3x4 is used to determine where the actor instance is actually rendered + AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(world); + m_meshFeatureProcessor->SetMatrix3x4(*m_meshHandle, matrix3x4); // handle validity is checked internally. if (m_skinnedMeshRenderProxy.IsValid()) { diff --git a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp index d2aa81900b..5fd9c678dc 100644 --- a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp +++ b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp @@ -193,7 +193,7 @@ namespace Blast AZ::Transform transform = AZ::Transform::Identity(); AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformInterface::GetWorldTM); - m_meshFeatureProcessor->SetTransform(m_meshHandle, transform); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(transform)); } } @@ -232,7 +232,7 @@ namespace Blast { if (m_meshFeatureProcessor) { - m_meshFeatureProcessor->SetTransform(m_meshHandle, world); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(world)); } } } // namespace Blast diff --git a/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp b/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp index deb6362ee3..d057e5a619 100644 --- a/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp +++ b/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp @@ -74,10 +74,10 @@ namespace Blast { if (m_chunkActors[chunkId]) { - auto transform = m_chunkActors[chunkId]->GetWorldBody()->GetTransform(); + auto matrix3x4 = AZ::Matrix3x4::CreateFromTransform(m_chunkActors[chunkId]->GetWorldBody()->GetTransform()); // Multiply by scale because the transform on the world body does not store scale - transform.MultiplyByScale(m_scale); - m_meshFeatureProcessor->SetTransform(m_chunkMeshHandles[chunkId], transform); + matrix3x4.MultiplyByScale(m_scale); + m_meshFeatureProcessor->SetMatrix3x4(m_chunkMeshHandles[chunkId], matrix3x4); } } } diff --git a/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp b/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp index 4036023397..0a7cd229a3 100644 --- a/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp +++ b/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp @@ -114,7 +114,7 @@ namespace Blast // ActorRenderManager::SyncMeshes { - EXPECT_CALL(*m_mockMeshFeatureProcessor, SetTransform(_, _)) + EXPECT_CALL(*m_mockMeshFeatureProcessor, SetMatrix3x4(_, _)) .Times(aznumeric_cast(m_actorFactory->m_mockActors[0]->GetChunkIndices().size())); actorRenderManager->SyncMeshes(); } diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp index 9aa29cb288..9c3428ad63 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp @@ -248,7 +248,7 @@ namespace WhiteBox void AtomRenderMesh::UpdateTransform(const AZ::Transform& worldFromLocal) { - m_meshFeatureProcessor->SetTransform(m_meshHandle, worldFromLocal); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(worldFromLocal)); } void AtomRenderMesh::UpdateMaterial([[maybe_unused]] const WhiteBoxMaterial& material) From 217009de2b8752da208a1c53eaf1062d722f7000 Mon Sep 17 00:00:00 2001 From: greerdv Date: Wed, 14 Apr 2021 18:25:38 +0100 Subject: [PATCH 002/277] adding tests for transforming Aabb with Matrix3x4 and fixing bug in implementation --- Code/Framework/AzCore/AzCore/Math/Aabb.cpp | 2 +- .../Framework/AzCore/Tests/Math/AabbTests.cpp | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp index 48e51cce48..3f7cb4ecf5 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp @@ -243,7 +243,7 @@ namespace AZ void Aabb::ApplyMatrix3x4(const Matrix3x4& matrix3x4) { const AZ::Vector3 extents = GetExtents(); - const AZ::Vector3 center = GetCenter(); + const AZ::Vector3 center = matrix3x4 * GetCenter(); AZ::Vector3 newHalfExtents( 0.5f * matrix3x4.GetRowAsVector3(0).GetAbs().Dot(extents), 0.5f * matrix3x4.GetRowAsVector3(1).GetAbs().Dot(extents), diff --git a/Code/Framework/AzCore/Tests/Math/AabbTests.cpp b/Code/Framework/AzCore/Tests/Math/AabbTests.cpp index 20a4d2ed85..6b7317f5b3 100644 --- a/Code/Framework/AzCore/Tests/Math/AabbTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/AabbTests.cpp @@ -15,6 +15,7 @@ #include #include #include +#include using namespace AZ; @@ -385,4 +386,64 @@ namespace UnitTest EXPECT_TRUE(aabb.GetMin().IsClose(transAabb.GetMin())); EXPECT_TRUE(aabb.GetMax().IsClose(transAabb.GetMax())); } + + TEST(MATH_AabbTransform, GetTransformedObbMatrix3x4) + { + Vector3 min(-1.0f, -2.0f, -3.0f); + Vector3 max(4.0f, 3.0f, 2.0f); + Aabb aabb = Aabb::CreateFromMinMax(min, max); + + Quaternion rotation(0.46f, 0.26f, 0.58f, 0.62f); + Vector3 translation(5.0f, 7.0f, 9.0f); + + Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation); + + matrix3x4.MultiplyByScale(Vector3(0.5f, 1.5f, 2.0f)); + + Obb obb = aabb.GetTransformedObb(matrix3x4); + + EXPECT_THAT(obb.GetRotation(), IsClose(rotation)); + EXPECT_THAT(obb.GetHalfLengths(), IsClose(Vector3(1.25f, 3.75f, 5.0f))); + EXPECT_THAT(obb.GetPosition(), IsClose(Vector3(3.928f, 7.9156f, 9.3708f))); + } + + TEST(MATH_AabbTransform, GetTransformedAabbMatrix3x4) + { + Vector3 min(2.0f, 3.0f, 5.0f); + Vector3 max(6.0f, 5.0f, 11.0f); + Aabb aabb = Aabb::CreateFromMinMax(min, max); + + Quaternion rotation(0.34f, 0.46f, 0.58f, 0.58f); + Vector3 translation(-3.0f, -4.0f, -5.0f); + + Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation); + + matrix3x4.MultiplyByScale(Vector3(1.2f, 0.8f, 2.0f)); + + Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4); + + EXPECT_THAT(transformedAabb.GetMin(), IsClose(Vector3(4.1488f, -0.01216f, -0.31904f))); + EXPECT_THAT(transformedAabb.GetMax(), IsClose(Vector3(16.3216f, 6.54272f, 5.98112f))); + } + + TEST(MATH_AabbTransform, GetTransformedObbFitsInsideTransformedAabb) + { + Vector3 min(4.0f, 3.0f, 1.0f); + Vector3 max(7.0f, 6.0f, 8.0f); + Aabb aabb = Aabb::CreateFromMinMax(min, max); + + Quaternion rotation(0.40f, 0.40f, 0.64f, 0.52f); + Vector3 translation(-2.0f, 4.0f, -3.0f); + + Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation); + + matrix3x4.MultiplyByScale(Vector3(2.2f, 0.6f, 1.4f)); + + Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4); + Obb transformedObb = aabb.GetTransformedObb(matrix3x4); + Aabb aabbContainingTransformedObb = Aabb::CreateFromObb(transformedObb); + + EXPECT_THAT(transformedAabb.GetMin(), IsClose(aabbContainingTransformedObb.GetMin())); + EXPECT_THAT(transformedAabb.GetMax(), IsClose(aabbContainingTransformedObb.GetMax())); + } } From 0f13a71bd284a22254b628b94c81241a22ce0ade Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 14 Apr 2021 16:01:26 -0500 Subject: [PATCH 003/277] [LYN-2255] Refactored some EditorEntityHelpers so they can be re-used. --- .../Entity/EditorEntityHelpers.cpp | 81 +++++++++++++++++++ .../Entity/EditorEntityHelpers.h | 6 ++ .../Prefab/PrefabPublicHandler.cpp | 19 +---- .../Prefab/PrefabPublicHandler.h | 1 - .../Tests/Entity/EditorEntityHelpersTests.cpp | 71 ++++++++++++++++ .../Tests/aztoolsframeworktests_files.cmake | 2 + .../SandboxIntegration.cpp | 16 +++- 7 files changed, 174 insertions(+), 22 deletions(-) create mode 100644 Code/Framework/AzToolsFramework/Tests/Entity/EditorEntityHelpersTests.cpp diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp index 6ab3625dd2..629dcd639d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp @@ -136,6 +136,48 @@ namespace AzToolsFramework return entity->GetName(); } + EntityList EntityIdListToEntityList(const EntityIdList& inputEntityIds) + { + EntityList entities; + entities.reserve(inputEntityIds.size()); + + for (AZ::EntityId entityId : inputEntityIds) + { + if (!entityId.IsValid()) + { + continue; + } + + if (auto entity = GetEntityById(entityId)) + { + entities.emplace_back(entity); + } + } + + return entities; + } + + EntityList EntityIdSetToEntityList(const EntityIdSet& inputEntityIds) + { + EntityList entities; + entities.reserve(inputEntityIds.size()); + + for (AZ::EntityId entityId : inputEntityIds) + { + if (!entityId.IsValid()) + { + continue; + } + + if (auto entity = GetEntityById(entityId)) + { + entities.emplace_back(entity); + } + } + + return entities; + } + void GetAllComponentsForEntity(const AZ::Entity* entity, AZ::Entity::ComponentArrayType& componentsOnEntity) { if (entity) @@ -1068,6 +1110,45 @@ namespace AzToolsFramework return !allEntityClonesContainer.m_entities.empty(); } + EntityIdSet GetCulledEntityHierarchy(const EntityIdList& entities) + { + EntityIdSet culledEntities; + + for (const AZ::EntityId& entityId : entities) + { + bool selectionIncludesTransformHeritage = false; + AZ::EntityId parentEntityId = entityId; + do + { + AZ::EntityId nextParentId; + AZ::TransformBus::EventResult( + /*result*/ nextParentId, + /*address*/ parentEntityId, + &AZ::TransformBus::Events::GetParentId); + parentEntityId = nextParentId; + if (!parentEntityId.IsValid()) + { + break; + } + for (const AZ::EntityId& parentCheck : entities) + { + if (parentCheck == parentEntityId) + { + selectionIncludesTransformHeritage = true; + break; + } + } + } while (parentEntityId.IsValid() && !selectionIncludesTransformHeritage); + + if (!selectionIncludesTransformHeritage) + { + culledEntities.insert(entityId); + } + } + + return culledEntities; + } + namespace Internal { void CloneSliceEntitiesAndChildren( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.h index 39f4c37c29..3ef03296f4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.h @@ -47,6 +47,9 @@ namespace AzToolsFramework AZStd::string GetEntityName(const AZ::EntityId& entityId, const AZStd::string_view& nameOverride = {}); + EntityList EntityIdListToEntityList(const EntityIdList& inputEntityIds); + EntityList EntityIdSetToEntityList(const EntityIdSet & inputEntityIds); + template struct AddComponents { @@ -202,4 +205,7 @@ namespace AzToolsFramework /// Wrap EBus SetSelectedEntities call. void SelectEntities(const AzToolsFramework::EntityIdList& entities); + /// Return a set of entities, culling any that have an ancestor in the list. + EntityIdSet GetCulledEntityHierarchy(const EntityIdList & entities); + }; // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 417a524e77..43ee7b7033 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -61,8 +61,7 @@ namespace AzToolsFramework PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZStd::string_view filePath) { // Retrieve entityList from entityIds - EntityList inputEntityList; - EntityIdListToEntityList(entityIds, inputEntityList); + EntityList inputEntityList = EntityIdListToEntityList(entityIds); // Find common root and top level entities bool entitiesHaveCommonRoot = false; @@ -419,8 +418,7 @@ namespace AzToolsFramework InstanceOptionalReference instance = GetOwnerInstanceByEntityId(entityIds[0]); // Retrieve entityList from entityIds - EntityList inputEntityList; - EntityIdListToEntityList(entityIds, inputEntityList); + EntityList inputEntityList = EntityIdListToEntityList(entityIds); AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); @@ -767,18 +765,5 @@ namespace AzToolsFramework return true; } - - void PrefabPublicHandler::EntityIdListToEntityList(const EntityIdList& inputEntityIds, EntityList& outEntities) - { - outEntities.reserve(inputEntityIds.size()); - - for (AZ::EntityId entityId : inputEntityIds) - { - if (entityId.IsValid()) - { - outEntities.emplace_back(GetEntityById(entityId)); - } - } - } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h index 46a7f946ba..4eb03a7abb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h @@ -70,7 +70,6 @@ namespace AzToolsFramework static Instance* GetParentInstance(Instance* instance); static Instance* GetAncestorOfInstanceThatIsChildOfRoot(const Instance* ancestor, Instance* descendant); static void GenerateContainerEntityTransform(const EntityList& topLevelEntities, AZ::Vector3& translation, AZ::Quaternion& rotation); - static void EntityIdListToEntityList(const EntityIdList& inputEntityIds, EntityList& outEntities); InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr; InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr; diff --git a/Code/Framework/AzToolsFramework/Tests/Entity/EditorEntityHelpersTests.cpp b/Code/Framework/AzToolsFramework/Tests/Entity/EditorEntityHelpersTests.cpp new file mode 100644 index 0000000000..6bf6beb878 --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/Entity/EditorEntityHelpersTests.cpp @@ -0,0 +1,71 @@ +/* +* 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 + +namespace UnitTest +{ + using namespace AZ; + using namespace AzToolsFramework; + + class EditorEntityHelpersTest + : public ToolsApplicationFixture + { + void SetUpEditorFixtureImpl() override + { + m_parent1 = CreateDefaultEditorEntity("Parent1"); + m_child1 = CreateDefaultEditorEntity("Child1"); + m_child2 = CreateDefaultEditorEntity("Child2"); + m_grandChild1 = CreateDefaultEditorEntity("GrandChild1"); + m_parent2 = CreateDefaultEditorEntity("Parent2"); + + AZ::TransformBus::Event(m_child1, &AZ::TransformBus::Events::SetParent, m_parent1); + AZ::TransformBus::Event(m_child2, &AZ::TransformBus::Events::SetParent, m_parent1); + AZ::TransformBus::Event(m_grandChild1, &AZ::TransformBus::Events::SetParent, m_child1); + } + + public: + AZ::EntityId m_parent1; + AZ::EntityId m_child1; + AZ::EntityId m_child2; + AZ::EntityId m_grandChild1; + AZ::EntityId m_parent2; + }; + + TEST_F(EditorEntityHelpersTest, EditorEntityHelpersTests_GetCulledEntityHierarchy) + { + EntityIdList testEntityIds{ m_parent1, m_child1, m_child2, m_grandChild1, m_parent2 }; + + EntityIdSet culledSet = GetCulledEntityHierarchy(testEntityIds); + + // There should only be two EntityIds returned (m_parent1, and m_parent2), + // since all the others should be culled out since they have a common ancestor + // in the list already + EXPECT_EQ(culledSet.size(), 2); + + EntityIdList foundEntityIds{ m_parent1, m_parent2 }; + for (auto& entityId : foundEntityIds) + { + EXPECT_TRUE(AZStd::find(culledSet.begin(), culledSet.end(), entityId) != culledSet.end()); + } + + EntityIdList culledEntityIds{ m_child1, m_child2, m_grandChild1 }; + for (auto& entityId : culledEntityIds) + { + EXPECT_FALSE(AZStd::find(culledSet.begin(), culledSet.end(), entityId) != culledSet.end()); + } + } +} diff --git a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake index 7a2cd373a2..e54aa187e4 100644 --- a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake +++ b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake @@ -85,7 +85,9 @@ set(FILES Prefab/SpawnableSortEntitiesTestFixture.cpp Prefab/SpawnableSortEntitiesTestFixture.h Entity/EditorEntityContextComponentTests.cpp + Entity/EditorEntityHelpersTests.cpp Entity/EditorEntitySearchComponentTests.cpp + Entity/EditorEntitySelectionTests.cpp SliceStabilityTests/SliceStabilityTestFramework.h SliceStabilityTests/SliceStabilityTestFramework.cpp SliceStabilityTests/SliceStabilityCreateTests.cpp diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index e5311dbea9..69040245f8 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -670,9 +670,13 @@ void SandboxIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu, con action = menu->addAction(QObject::tr("Create layer")); QObject::connect(action, &QAction::triggered, [this] { ContextMenu_NewLayer(); }); + AzToolsFramework::EntityIdList entities; + AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( + entities, + &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); + SetupLayerContextMenu(menu); - AzToolsFramework::EntityIdSet flattenedSelection; - GetSelectedEntitiesSetWithFlattenedHierarchy(flattenedSelection); + AzToolsFramework::EntityIdSet flattenedSelection = AzToolsFramework::GetCulledEntityHierarchy(entities); AzToolsFramework::SetupAddToLayerMenu(menu, flattenedSelection, [this] { return ContextMenu_NewLayer(); }); SetupSliceContextMenu(menu); @@ -1220,8 +1224,12 @@ void SandboxIntegrationManager::CloneSelection(bool& handled) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); - AzToolsFramework::EntityIdSet duplicationSet; - GetSelectedEntitiesSetWithFlattenedHierarchy(duplicationSet); + AzToolsFramework::EntityIdList entities; + AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( + entities, + &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities); + + AzToolsFramework::EntityIdSet duplicationSet = AzToolsFramework::GetCulledEntityHierarchy(entities); if (duplicationSet.size() > 0) { From 11b6874d92a4e555097fe12f83f2f841918d6a02 Mon Sep 17 00:00:00 2001 From: scottr Date: Wed, 14 Apr 2021 15:39:22 -0700 Subject: [PATCH 004/277] [cpack_installer] initial support for installable components --- cmake/Platform/Common/Install_common.cmake | 48 +++++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 9164105f3a..25f2bd6e69 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -9,6 +9,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(_default_component "com.o3de.default") #! ly_install_target: registers the target to be installed by cmake install. # @@ -22,6 +23,12 @@ # \arg:COMPILE_DEFINITIONS list of compilation definitions this target will use to compile function(ly_install_target ly_install_target_NAME) + set(options) + set(oneValueArgs NAMESPACE COMPONENT) + set(multiValueArgs INCLUDE_DIRECTORIES BUILD_DEPENDENCIES RUNTIME_DEPENDENCIES COMPILE_DEFINITIONS) + + cmake_parse_arguments(ly_install_target "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + # All include directories marked PUBLIC or INTERFACE will be installed set(include_location "include") get_target_property(include_directories ${ly_install_target_NAME} INTERFACE_INCLUDE_DIRECTORIES) @@ -43,14 +50,23 @@ function(ly_install_target ly_install_target_NAME) install( TARGETS ${ly_install_target_NAME} EXPORT ${ly_install_target_NAME}Targets - LIBRARY DESTINATION lib/$ - ARCHIVE DESTINATION lib/$ - RUNTIME DESTINATION bin/$ - PUBLIC_HEADER DESTINATION ${include_location} + LIBRARY + DESTINATION lib/$ + COMPONENT ${ly_install_target_COMPONENT} + ARCHIVE + DESTINATION lib/$ + COMPONENT ${ly_install_target_COMPONENT} + RUNTIME + DESTINATION bin/$ + COMPONENT ${ly_install_target_COMPONENT} + PUBLIC_HEADER + DESTINATION ${include_location} + COMPONENT ${ly_install_target_COMPONENT} ) - + install(EXPORT ${ly_install_target_NAME}Targets DESTINATION cmake_autogen/${ly_install_target_NAME} + COMPONENT ${ly_install_target_COMPONENT} ) # Header only targets(i.e., INTERFACE) don't have outputs @@ -60,11 +76,13 @@ function(ly_install_target ly_install_target_NAME) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${ly_install_target_NAME}_$.cmake" DESTINATION cmake_autogen/${ly_install_target_NAME} + COMPONENT ${ly_install_target_COMPONENT} ) endif() install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Find${ly_install_target_NAME}.cmake" - DESTINATION cmake + DESTINATION . + COMPONENT ${ly_install_target_COMPONENT} ) endfunction() @@ -81,7 +99,7 @@ endfunction() # \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_generate_target_find_file) - + set(options) set(oneValueArgs NAME NAMESPACE) set(multiValueArgs COMPILE_DEFINITIONS BUILD_DEPENDENCIES RUNTIME_DEPENDENCIES INCLUDE_DIRECTORIES) @@ -154,7 +172,7 @@ endfunction() # These per config files will be included by the target's find file to set the location of the binary/ # \arg:NAME name of the target function(ly_generate_target_config_file NAME) - + # SHARED_LIBRARY is omitted from this list because we link to the implib on Windows set(BINARY_DIR_OUTPUTS EXECUTABLE APPLICATION) set(target_file_contents "") @@ -205,7 +223,7 @@ endfunction() #! ly_setup_o3de_install: generates the Findo3de.cmake file and setup install locations for scripts, tools, assets etc., function(ly_setup_o3de_install) - + get_property(all_targets GLOBAL PROPERTY LY_ALL_TARGETS) unset(find_package_list) foreach(target IN LISTS all_targets) @@ -222,10 +240,12 @@ function(ly_setup_o3de_install) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Findo3de.cmake" DESTINATION cmake + COMPONENT ${_default_component} ) install(FILES "${CMAKE_SOURCE_DIR}/CMakeLists.txt" DESTINATION . + COMPONENT ${_default_component} ) endfunction() @@ -237,14 +257,15 @@ function(ly_install_o3de_directories) # List of directories we want to install relative to engine root set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole ctest_scripts scripts) foreach(dir ${DIRECTORIES_TO_INSTALL}) - + get_filename_component(install_path ${dir} DIRECTORY) if (NOT install_path) set(install_path .) endif() - + install(DIRECTORY "${CMAKE_SOURCE_DIR}/${dir}" DESTINATION ${install_path} + COMPONENT ${_default_component} ) endforeach() @@ -252,11 +273,13 @@ function(ly_install_o3de_directories) # Directories which have excludes install(DIRECTORY "${CMAKE_SOURCE_DIR}/cmake" DESTINATION . + COMPONENT ${_default_component} REGEX "Findo3de.cmake" EXCLUDE ) install(DIRECTORY "${CMAKE_SOURCE_DIR}/python" DESTINATION . + COMPONENT ${_default_component} REGEX "downloaded_packages" EXCLUDE REGEX "runtime" EXCLUDE ) @@ -273,12 +296,15 @@ function(ly_install_launcher_target_generator) ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/LauncherProject.cpp ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/StaticModules.in DESTINATION LauncherGenerator + COMPONENT ${_default_component} ) install(DIRECTORY ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/Platform DESTINATION LauncherGenerator + COMPONENT ${_default_component} ) install(FILES ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/FindLauncherGenerator.cmake DESTINATION cmake + COMPONENT ${_default_component} ) endfunction() \ No newline at end of file From a371edd07fa94d1c231162cc24062eb3452a95bb Mon Sep 17 00:00:00 2001 From: srikappa Date: Wed, 14 Apr 2021 17:26:14 -0700 Subject: [PATCH 005/277] Initial commit of CreatePrefab work --- .../PrefabEditorEntityOwnershipService.cpp | 25 ++- .../PrefabEditorEntityOwnershipService.h | 2 +- .../Prefab/Instance/Instance.cpp | 2 +- .../Instance/InstanceUpdateExecutor.cpp | 57 ++++- .../Prefab/Instance/InstanceUpdateExecutor.h | 14 ++ .../Prefab/PrefabPublicHandler.cpp | 201 ++++++++++++------ .../Prefab/PrefabPublicHandler.h | 5 +- .../Prefab/PrefabPublicInterface.h | 2 +- .../Prefab/PrefabSystemComponent.cpp | 33 ++- .../UI/Prefab/PrefabIntegrationManager.cpp | 16 +- .../UI/Prefab/PrefabIntegrationManager.h | 4 + 11 files changed, 276 insertions(+), 85 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 4b23b46ffd..2424658ecf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -279,18 +279,29 @@ namespace AzToolsFramework AZStd::unique_ptr createdPrefabInstance = m_prefabSystemComponent->CreatePrefab(entities, AZStd::move(nestedPrefabInstances), filePath); - if (!instanceToParentUnder) - { - instanceToParentUnder = *m_rootInstance; - } - if (createdPrefabInstance) { + if (!instanceToParentUnder) + { + instanceToParentUnder = *m_rootInstance; + } + Prefab::Instance& addedInstance = instanceToParentUnder->get().AddInstance(AZStd::move(createdPrefabInstance)); - HandleEntitiesAdded({addedInstance.m_containerEntity.get()}); + AZ::Entity* containerEntity = addedInstance.m_containerEntity.get(); + containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent()); + HandleEntitiesAdded({containerEntity}); + HandleEntitiesAdded(entities); + + // Update the template of the instance since we modified the entities of the instance by calling HandleEntitiesAdded. + Prefab::PrefabDom serializedInstance; + if (Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(addedInstance, serializedInstance)) + { + m_prefabSystemComponent->UpdatePrefabTemplate(addedInstance.GetTemplateId(), serializedInstance); + } + return addedInstance; } - HandleEntitiesAdded(entities); + return AZStd::nullopt; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h index ad11547506..36a60cc501 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h @@ -186,7 +186,7 @@ namespace AzToolsFramework PlayInEditorData m_playInEditorData; ////////////////////////////////////////////////////////////////////////// - // PrefabSystemComponentInterface interface implementation + // PrefabEditorEntityOwnershipInterface implementation Prefab::InstanceOptionalReference CreatePrefab( const AZStd::vector& entities, AZStd::vector>&& nestedPrefabInstances, AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp index 0a5b43482e..bd4c343a3c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp @@ -283,7 +283,7 @@ namespace AzToolsFramework { if (!m_instanceEntityMapper->RegisterEntityToInstance(entityId, *this)) { - AZ_Assert(false, + AZ_Error("Prefab", false, "Prefab - Failed to register entity with id %s with a Prefab Instance derived from source asset %s " "This entity is likely already registered. Check for a double add.", entityId.ToString().c_str(), diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.cpp index 65de6b713c..7df1602bff 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -117,6 +118,8 @@ namespace AzToolsFramework currentTemplateId); isUpdateSuccessful = false; + m_instancesUpdateQueue.pop(); + continue; } } @@ -139,9 +142,16 @@ namespace AzToolsFramework } m_instancesUpdateQueue.pop(); - } + for (auto entityIdIterator = selectedEntityIds.begin(); entityIdIterator != selectedEntityIds.end(); entityIdIterator++) + { + AZ::Entity* entity = GetEntityById(*entityIdIterator); + if (entity == nullptr) + { + selectedEntityIds.erase(entityIdIterator--); + } + } ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetSelectedEntities, selectedEntityIds); // Enable the Outliner @@ -163,5 +173,50 @@ namespace AzToolsFramework return isUpdateSuccessful; } + + Instance* InstanceUpdateExecutor::UniqueInstanceQueue::front() + { + return m_instancesQueue.front(); + } + + void InstanceUpdateExecutor::UniqueInstanceQueue::pop() + { + m_instancesSet.erase(m_instancesQueue.front()); + m_instancesQueue.pop(); + } + + void InstanceUpdateExecutor::UniqueInstanceQueue::emplace(Instance* instance) + { + Instance* ancestorInstance = instance; + + while (ancestorInstance != nullptr) + { + if (m_instancesSet.contains(ancestorInstance)) + { + return; + } + + auto parent = ancestorInstance->GetParentInstance(); + if (parent.has_value()) + { + ancestorInstance = &(parent->get()); + } + else + { + ancestorInstance = nullptr; + } + } + + // TODO - remove child instances too? + // Optimization. + + m_instancesQueue.emplace(instance); + m_instancesSet.emplace(instance); + } + + size_t InstanceUpdateExecutor::UniqueInstanceQueue::size() + { + return m_instancesQueue.size(); + } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.h index 04bd189816..a29e19dc8a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,19 @@ namespace AzToolsFramework PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr; TemplateInstanceMapperInterface* m_templateInstanceMapperInterface = nullptr; int m_instanceCountToUpdateInBatch = 0; + + class UniqueInstanceQueue + { + public: + Instance* front(); + void pop(); + void emplace(Instance* instance); + size_t size(); + private: + AZStd::queue m_instancesQueue; + AZStd::unordered_set m_instancesSet; + }; + //UniqueInstanceQueue m_instancesUpdateQueue; AZStd::queue m_instancesUpdateQueue; bool m_updatingTemplateInstancesInQueue { false }; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 417a524e77..292ee3c7f8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -15,15 +15,16 @@ #include #include +#include #include #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -37,12 +38,14 @@ namespace AzToolsFramework void PrefabPublicHandler::RegisterPrefabPublicHandlerInterface() { m_instanceEntityMapperInterface = AZ::Interface::Get(); - AZ_Assert( - m_instanceEntityMapperInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceEntityMapperInterface"); + AZ_Assert(m_instanceEntityMapperInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceEntityMapperInterface"); m_instanceToTemplateInterface = AZ::Interface::Get(); AZ_Assert(m_instanceToTemplateInterface, "PrefabPublicHandler - Could not retrieve instance of InstanceToTemplateInterface"); + m_prefabLoaderInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabLoaderInterface, "Could not get PrefabLoaderInterface on PrefabPublicHandler construction."); + m_prefabSystemComponentInterface = AZ::Interface::Get(); AZ_Assert(m_prefabSystemComponentInterface, "Could not get PrefabSystemComponentInterface on PrefabPublicHandler construction."); @@ -58,7 +61,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; @@ -70,17 +73,14 @@ namespace AzToolsFramework EntityList topLevelEntities; AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - entitiesHaveCommonRoot, - &AzToolsFramework::ToolsApplicationRequests::FindCommonRootInactive, - inputEntityList, - commonRootEntityId, - &topLevelEntities - ); + entitiesHaveCommonRoot, &AzToolsFramework::ToolsApplicationRequests::FindCommonRootInactive, inputEntityList, + commonRootEntityId, &topLevelEntities); // Bail if entities don't share a common root if (!entitiesHaveCommonRoot) { - return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root.")); + return AZ::Failure( + AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root.")); } AZ::Entity* commonRootEntity = nullptr; @@ -91,58 +91,139 @@ namespace AzToolsFramework // Retrieve the owning instance of the common root entity, which will be our new instance's parent instance. InstanceOptionalReference commonRootEntityOwningInstance = GetOwnerInstanceByEntityId(commonRootEntityId); - AZ_Assert(commonRootEntityOwningInstance.has_value(), "Failed to create prefab : " + AZ_Assert( + commonRootEntityOwningInstance.has_value(), + "Failed to create prefab : " "Couldn't get a valid owning instance for the common root entity of the enities provided"); AZStd::vector entities; AZStd::vector> instances; - // Retrieve all entities affected and identify Instances - if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances)) - { - return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root.")); - } + InstanceOptionalReference instance; - auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - if (!prefabEditorEntityOwnershipInterface) { - return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error " - "(PrefabEditorEntityOwnershipInterface unavailable).")); - } + // Initialize Undo Batch object + ScopedUndoBatch undoBatch("Create Prefab"); - InstanceOptionalReference instance = prefabEditorEntityOwnershipInterface->CreatePrefab( - entities, AZStd::move(instances), filePath, commonRootEntityOwningInstance); + TemplateId commonRootOwningTemplateId = commonRootEntityOwningInstance->get().GetTemplateId(); - if (!instance) - { - return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error " - "(A null instance is returned).")); - } + PrefabDom commonRootInstanceDomBeforeCreate; + m_instanceToTemplateInterface->GenerateDomForInstance( + commonRootInstanceDomBeforeCreate, commonRootEntityOwningInstance->get()); + + // Retrieve all entities affected and identify Instances + if (!RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonRootEntityOwningInstance->get(), entities, instances)) + { + return AZ::Failure( + AZStd::string("Could not create a new prefab out of the entities provided - entities do not share a common root.")); + } + + auto prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + if (!prefabEditorEntityOwnershipInterface) + { + return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error " + "(PrefabEditorEntityOwnershipInterface unavailable).")); + } - AZ::EntityId containerEntityId = instance->get().GetContainerEntityId(); - AZ::Vector3 containerEntityTranslation(AZ::Vector3::CreateZero()); - AZ::Quaternion containerEntityRotation(AZ::Quaternion::CreateZero()); + // When you move instances from another template, you have to remove the links and propagate changes to target template. + auto linkRemoveUndo = aznew PrefabUndoInstanceLink("Undo Link Remove Node"); + for (auto& nestedInstance : instances) + { + PrefabDom emptyLinkDom; + linkRemoveUndo->Capture( + commonRootOwningTemplateId, nestedInstance->GetTemplateId(), nestedInstance->GetInstanceAlias(), emptyLinkDom, + nestedInstance->GetLinkId()); + linkRemoveUndo->SetParent(undoBatch.GetUndoBatch()); + } - // Set the transform (translation, rotation) of the container entity - GenerateContainerEntityTransform(topLevelEntities, containerEntityTranslation, containerEntityRotation); + // Create the Prefab + instance = prefabEditorEntityOwnershipInterface->CreatePrefab( + entities, AZStd::move(instances), filePath, commonRootEntityOwningInstance); - AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalTranslation, containerEntityTranslation); - AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, containerEntityRotation); + if (!instance) + { + return AZ::Failure(AZStd::string("Could not create a new prefab out of the entities provided - internal error " + "(A null instance is returned).")); + } - // Set container entity to be child of common root - AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetParent, commonRootEntityId); - - // Assign the EditorPrefabComponent to the instance container - EntityCompositionRequests::AddComponentsOutcome outcome; - EntityCompositionRequestBus::BroadcastResult( - outcome, &EntityCompositionRequests::AddComponentsToEntities, EntityIdList{containerEntityId}, - AZ::ComponentTypeList{azrtti_typeid()}); - - // Change top level entities to be parented to the container entity - for (AZ::Entity* topLevelEntity : topLevelEntities) - { - AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId); + PrefabDom commonRootInstanceDomAfterCreate; + m_instanceToTemplateInterface->GenerateDomForInstance( + commonRootInstanceDomAfterCreate, commonRootEntityOwningInstance->get()); + + auto commonRootInstanceUndoNode = aznew PrefabUndoInstance("Undo Instance Node"); + commonRootInstanceUndoNode->Capture( + commonRootInstanceDomBeforeCreate, commonRootInstanceDomAfterCreate, commonRootOwningTemplateId); + commonRootInstanceUndoNode->SetParent(undoBatch.GetUndoBatch()); + commonRootInstanceUndoNode->Redo(); + + linkRemoveUndo->Redo(); + + + AZ::EntityId containerEntityId = instance->get().GetContainerEntityId(); + AZ::Entity* containerEntity = GetEntityById(containerEntityId); + + // Apply Transform changes as overrides + { + Prefab::PrefabDom containerEntityDomBefore; + m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomBefore, *containerEntity); + + AZ::Vector3 containerEntityTranslation(AZ::Vector3::CreateZero()); + AZ::Quaternion containerEntityRotation(AZ::Quaternion::CreateZero()); + + // Set the transform (translation, rotation) of the container entity + GenerateContainerEntityTransform(topLevelEntities, containerEntityTranslation, containerEntityRotation); + + // Set container entity to be child of common root + AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetParent, commonRootEntityId); + + AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalTranslation, containerEntityTranslation); + AZ::TransformBus::Event(containerEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, containerEntityRotation); + + PrefabDom containerEntityDomAfter; + m_instanceToTemplateInterface->GenerateDomForEntity(containerEntityDomAfter, *containerEntity); + + PrefabDom patch; + m_instanceToTemplateInterface->GeneratePatch(patch, containerEntityDomBefore, containerEntityDomAfter); + + m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(patch, containerEntityId); + + + auto linkAddUndo = aznew PrefabUndoInstanceLink("Undo Link Add Node"); + linkAddUndo->Capture( + commonRootEntityOwningInstance->get().GetTemplateId(), instance->get().GetTemplateId(), instance->get().GetInstanceAlias(), + patch, InvalidLinkId); + linkAddUndo->SetParent(undoBatch.GetUndoBatch()); + + linkAddUndo->Redo(); + + // Update the cache - this prevents these changes from being stored in the regular undo/redo nodes + m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter)); + } + + // Change top level entities to be parented to the container entity + // Mark them as dirty so this change is correctly applied to the template + for (AZ::Entity* topLevelEntity : topLevelEntities) + { + m_prefabUndoCache.UpdateCache(topLevelEntity->GetId()); + undoBatch.MarkEntityDirty(topLevelEntity->GetId()); + AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId); + } + + /* + // Select Container Entity + { + auto selectionUndo = aznew SelectionCommand({containerEntityId}, "Select Prefab Container Entity"); + selectionUndo->SetParent(undoBatch.GetUndoBatch()); + + ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo); + }*/ } + + // Save Template to file + m_prefabLoaderInterface->SaveTemplate(instance->get().GetTemplateId()); + + // This function does not support undo/redo yet, so clear the undo stack to prevent issues. + //AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequestBus::Events::FlushUndo); return AZ::Success(); } @@ -174,14 +255,7 @@ namespace AzToolsFramework AZStd::string("SavePrefab - Path error. Path could be invalid, or the prefab may not be loaded in this level.")); } - auto prefabLoaderInterface = AZ::Interface::Get(); - if (prefabLoaderInterface == nullptr) - { - return AZ::Failure(AZStd::string( - "Could not save prefab - internal error (PrefabLoaderInterface unavailable).")); - } - - if (!prefabLoaderInterface->SaveTemplate(templateId)) + if (!m_prefabLoaderInterface->SaveTemplate(templateId)) { return AZ::Failure(AZStd::string("Could not save prefab - internal error (Json write operation failure).")); } @@ -260,15 +334,15 @@ namespace AzToolsFramework // Create Undo node on entities if they belong to an instance InstanceOptionalReference instanceOptionalReference = m_instanceEntityMapperInterface->FindOwningInstance(entityId); - if (instanceOptionalReference.has_value()) + if (instanceOptionalReference.has_value() && !IsInstanceContainerEntity(entityId)) { - PrefabDom beforeState; - m_prefabUndoCache.Retrieve(entityId, beforeState); - PrefabDom afterState; AZ::Entity* entity = GetEntityById(entityId); if (entity) { + PrefabDom beforeState; + m_prefabUndoCache.Retrieve(entityId, beforeState); + m_instanceToTemplateInterface->GenerateDomForEntity(afterState, *entity); PrefabDom patch; @@ -287,7 +361,10 @@ namespace AzToolsFramework // Update the cache m_prefabUndoCache.Store(entityId, AZStd::move(afterState)); } - + else + { + m_prefabUndoCache.PurgeCache(entityId); + } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h index 46a7f946ba..de892470ab 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h @@ -27,8 +27,10 @@ namespace AzToolsFramework namespace Prefab { class Instance; + class InstanceEntityMapperInterface; class InstanceToTemplateInterface; + class PrefabLoaderInterface; class PrefabSystemComponentInterface; class PrefabPublicHandler final @@ -42,7 +44,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; @@ -74,6 +76,7 @@ namespace AzToolsFramework InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr; InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr; + PrefabLoaderInterface* m_prefabLoaderInterface = nullptr; PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr; // Caches entity states for undo/redo purposes 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/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index bf9fd658c6..37620ed9ec 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -104,7 +104,6 @@ namespace AzToolsFramework return nullptr; } - AZStd::unique_ptr newInstance = AZStd::make_unique(AZStd::move(containerEntity)); for (AZ::Entity* entity : entities) @@ -120,8 +119,11 @@ namespace AzToolsFramework newInstance->AddInstance(AZStd::move(instance)); } - - newInstance->SetTemplateSourcePath(relativeFilePath); + /* + AzToolsFramework::EditorEntityContextRequestBus::Broadcast( + &AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, EntityList{containerEntity->GetId()}); + */ + newInstance->SetTemplateSourcePath(filePath); TemplateId newTemplateId = CreateTemplateFromInstance(*newInstance); if (newTemplateId == InvalidTemplateId) @@ -157,11 +159,16 @@ namespace AzToolsFramework void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) { - PrefabDom& templateDomToUpdate = FindTemplateDom(templateId); - if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal) + auto templateRef = FindTemplate(templateId); + if (templateRef.has_value()) { - templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator()); - PropagateTemplateChanges(templateId); + PrefabDom& templateDomToUpdate = templateRef->get().GetPrefabDom(); + if (AZ::JsonSerialization::Compare(templateDomToUpdate, updatedDom) != AZ::JsonSerializerCompareResult::Equal) + { + templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator()); + templateRef->get().MarkAsDirty(true); + PropagateTemplateChanges(templateId); + } } } @@ -615,7 +622,12 @@ namespace AzToolsFramework instancesValue = memberFound->value; } - instancesValue->get().AddMember(rapidjson::StringRef(instanceAlias.c_str()), PrefabDomValue(), targetTemplateDom.GetAllocator()); + // Only add the instance if it's not there already + if (instancesValue->get().FindMember(rapidjson::StringRef(instanceAlias.c_str())) == instancesValue->get().MemberEnd()) + { + instancesValue->get().AddMember( + rapidjson::StringRef(instanceAlias.c_str()), PrefabDomValue(), targetTemplateDom.GetAllocator()); + } Template& sourceTemplate = sourceTemplateRef->get(); @@ -628,9 +640,12 @@ namespace AzToolsFramework newLink.GetLinkDom().AddMember(rapidjson::StringRef(PrefabDomUtils::SourceName), rapidjson::StringRef(sourceTemplate.GetFilePath().c_str()), newLink.GetLinkDom().GetAllocator()); + PrefabDom linkPatchCopy; + linkPatchCopy.CopyFrom(linkPatch->get(), newLink.GetLinkDom().GetAllocator()); + if (linkPatch && linkPatch->get().IsArray() && !(linkPatch->get().Empty())) { - m_instanceToTemplatePropagator.AddPatchesToLink(linkPatch.value(), newLink); + m_instanceToTemplatePropagator.AddPatchesToLink(linkPatchCopy, newLink); } //update the target template dom to have the proper values for the source template dom 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 79a34f87b03aebcdd10a02dbb7424b629a0fe9f0 Mon Sep 17 00:00:00 2001 From: greerdv Date: Thu, 15 Apr 2021 08:28:50 +0100 Subject: [PATCH 006/277] fixing merge conflicts --- .../temp/128x128_RGBA8.tga.streamingimage | Bin 0 -> 28066 bytes .../RayTracingAccelerationStructurePass.cpp | 2 +- .../RayTracing/RayTracingFeatureProcessor.cpp | 8 ++++---- 3 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/temp/128x128_RGBA8.tga.streamingimage diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/temp/128x128_RGBA8.tga.streamingimage b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/temp/128x128_RGBA8.tga.streamingimage new file mode 100644 index 0000000000000000000000000000000000000000..b867b7cfb19ea2f70157e69cd9534fd8bfb04002 GIT binary patch literal 28066 zcmeHw3tUvy+Www_jG0lKM3T}r0q0=BDqi7`=Dv~mQ43nCrM-=cf zB48sNjRQ{PWiZ4M%QDSUw7?RRDKCtmj)o%_9p?YMdpYVsJ$?PNb2{G_zkWZ@Gi%T6 zz1H)-&-<>m-n9?Mah%ipf+1`2d!%I!bJ^sa^oYLfy(uHV%TVEczi2)X?Y zdpzG13{KTgS=#*4mR*gV*1q=r7fBJz9v$H`?0DLYWXsF>+O&6{Z}V-_LR_!mBCMm% zw7+{xb6%I|yR-;6F8qh&xb*Y7?M|OJzO;Dt^>?PHI?oKkV}-vUI1zEj=WV!%lRM{B zXMCM>ZH#P0(?4F>UbpMJcR#`Hhj9D<@ym)R!MwQdzu#N+LhlXo!#^GE>!uBVBtsE@ z$M4|x=Wmrr@A#bKMn0DMqRQv{qIS`76GyFCyS{AZqqB$Xe?BPEPq6IZd%d6DJ92H| z`cI$gwE2loCM-Mg@WMGILF2j7nEUHT?ii}S#^f(M z`M>BpTttN546nNgB7`i$?Xmigjw#}&D~CVdbLHQE+#hi@D;A$W$VI&Ryid;EzqG&l zZ(RoplJ_i~8UEOdeYQ0F&wQvfRuyi#vMKj28W(<|Df3$E&+T?D{ITf2ooxL%ZXMoj z+V=Nae~#-TYT{!?-$jej39&x^$-9IbwA`~35z{|)PMts8H#_>xmlqfLt{#_uBC*tt zKQ1Er_{XVt?>ILyV%93t%!bvAp4v7s<-IG4`gezZyE>foy7dE7NB;U8!S())12?kf ziY@4&8MecH(;^=J_`7v09ynyvjHFSXXxcs^DP+W>>GpS=`n_SB9)9xD5%0TE5-~I6L|MKr((2%9k3ts*}lcqYbch>GI z$HmArxQG{jX*qcpGZJzmzwWf^v({g|M}8IVQJ!-8E)N|3-sbXNcYH43Mh=suPWXKW zifrYshAX_s=T7(d-1#1#KX8xF@1LRE{rUg+-{(fYvwXvYvz#tBr0$Pgz1AiA#pUxR zhVcga;F}9a6rUdY-iB>K2|w)|@{j$|vmSrxkIr@@Hv5dadKVMy%0&pjy?*x279q@b z4A;HOoh?DI==;!-pnIn6Xt{UVey@&5@6{1F;5|Aby+0l4de4ra<+pdlO4FogH$ z2wHx7M=;E+5x)hoIe>N;&&qvuY|K~(_iLspnKL~t%-e6HTkR+Ge3fgkP zzu4#biJm8HE#n>%0LKg#Od)J9;M|13Gi6*9aw56CkaH6RN7-W}K@1n%xLy+ExV{}X z=4bm`l4$<-l+BzAem^j#T`G^|DQ0JSp5>|fu6Q81Tv^MWcfp@_JpZKpI_RYF&GxTR`duy_ISWh;|B=?v^WP_);BZob>Ao{@jK8XcxLH|9^7KzT;KxEuS;-L)rmITCf_`do4Cs5CLZ|6n4`x#i-H{2 z_wA5!w6e2kX8`M~>)4_p8-;J}@TA-dz%X%A+f%wAXSTf|Mxx=5~7i zc~hEoVlMb+uM6$B@b;omHwwvKf)@<9*glkJyR@lCO)l2;z1otF045-K(xtsfz(=7C>;J|Q;ZhaWvFwv3h+PL`#{W& z(>+ANAtQQO%L=&h1IQkF2$qH}_9YxPq>0Cc;Wd85cX&{6RB2Tk?qIn2d4|FFZFs_S zj92yD3b3XTiXUkr~^gN1|0?pt~geB2m`Yn(uTWWPr zyQn{F27U_mqJTX-Ca|BfZ(gw_5B94_X)%kSFJ9Xh9$|W-Z2WK64`$yP9Ub=V${qNi zI^~=z^{>MEoTP{I0bA)a$G~q_&T1=?`E@9%TXW`f#;;K(4(U+>ev84UXE*RI4jaJu zF2ML(i+T&E4R4Cs0sh-gbr}kNg)_&1|1$#wqh>^hpq-nmVEiwSD-0)o6C)4ID)sad z98Rj^@%$;lQ9Ho5C8_OHYM&nkJ-7`gMS|}tmms=ciT3yju#fJdksrk!lbdZ1-*b9lQ{=WZMabI`eQV~z%%Z(qsBBc-~Lk9YGH+_rR0`tj${3&!`l zn|!;0@3NF8S9<;mtI@~%!IC8H#m_}g_3GwgH5N&RJq8TE&Cl=kAbwwcmhsR0RVIF8 zL<#)=bCLIqp5V7o94{w4K=e^uK`8P6?o`IVbkWmONe@=cV*JN0inckU@tqz^{x6xH zvFf8Z1@wRMYrMZt@3Y8z2Kd$_D!_MVNzCD-gW-ylTHTD1SNFpIQ^`IR>So=90amhy z)WUGmlUm)2Pg?gjKiV$UW#}o7lxDN;S&?;EGukP>fPUShf|R3yn^#njKH~c(R{|>w> zm*;<^u9s>T+-gfGjezvkAS^PNgd*M6L;UxI8u}GF0&G>$0*{B)B_Xah?ZaJ1D zBm8}9TFDI30~&9uu~586NA@s4rWK_33sj`{;fZ;{BM0j7arH2_Mwl#;h zKjPf28|*=45_9UKUa$w^OQDQV{hFS)Zf`x`_7EJ%$x4ZLBfYU2y?y*1iskuUjQN$p z+eaezjcu9(z6+3VgKt^vXl4&Fh<8RGnK(6?*~2S{&twmq7A7>!fj*F4!hFQLbBOQn zc)kfA-3t4Fzptw-HjqA?-dA#s^1~rDgZ7bqTs~GZW96CcJil;%Vbkf7x{MS3M7tY? z)KGq4ySU^+#tBc(Zcnx#KJ;#}HvKrK%2Q;w?`{C!VtZro$*oyEcwAvw%Gn#o94*dj zGm_esz%ACReT$E_3A%B;#%5_5R(#wgn0_y%r9gM>>{aA%qG-Aw(s{1_2kS88b1`Hu z3bk2NbHKWn^qRL1*h6J8@heHC{t#cE>A)}inb!+^Q20Lh1SWeRf6kc6_@#UXP!~Ur z;pK5lL)DFD)5L+B`(6!ix8)%62YlTe@Cdc1Zu!zLSE^1lo1PF@w*?feu+sckspj*? zpFLmtpX&kqecjq6THfC)Dy;o`K9CSU&N59*`KhtUM;824Y<%3sX|AM4M)3W{aN>KK z>(j`8fhF%w;rVx^{EX~jgPPex$Bm@tg|gC2hRGicFc9z!efaJs-!%uAK6HV9QT|~4 zv7~7Z_$U9R_+Yz`P&emHKY@c^dqeDmnJYbkcQ+ViLe75uaxv{d+U?c$A~F7LAw(FZ zK>WWffBqk1TZ~Y5`}dnp=cT7H`#`woS}a%kRvvYk&f5p{ywP-pkJq~!I#(0lwO?Q0 z@gz&;A&TFX#XO&Shdq?72Zq1%`p{_BZCc3qCjTHlm%h&ME6bjqN_@W+!s8>OW(0?* z6B|vVWrd^Lu^B+Wt!_^%)gD^-m+Kw17DmhrhHuwy`MLpw+~m!X9%y3ONftyy^x-f zJ#0;5_OZs0v5M^F>&;9*NY4qM{(|8y@NcrOt3Q%Hj29E%M!ihZV)1=rbWRZX&9RU^ z*soo#Z0E%I)f3sNbq-L3*po)WDk+*=EfbXHxr**D1QK*rgbXfv)z$zvkxZ`zw^ThuQ)>U3$?1z z6fwB4`&IBw@fO$|@Ms~mSCAfnesdSWmA-)m?VEGKr&^_=^{1nrx8(=OAG4<|(LycQ zUstCDtzuwod(sccz0c5YzH`S}CW~plruX)dMGcFE9++GyKQZEig;9j3@%|1h%UwWt zvTMhU(nZAY9v$=o?G46`8(}|^%)()w?rcRkMsR&_H&y(Trxo)F6DJc{sw!4r z4f!bi)%?XK^5+#t2JIWak@(JkpJ5gs5*wFJXZ%vWtOmi+BYDj00r`8dR~~O4J+U68 zQkhL&ZR)!FuUlcI^|Z)Hm8uQ*@@HO2!oY5nA1D-&ZMY@cu#$8)!WF9xhTbAS_i^Vg zxzhFhy}i9(miev@1)sFurT6ysd25s}&p*v)$sST?`gS6Fpm;@Cznrzx^8(7g(o_3n zSBJl!{fhMAv@6-a0bgi5<=YT?cC47S1(56wS2UFIbD zqz5LGMuUi-XC2#4Uu_>!lh|Bqu0727i@ z-9K!FmGqVTJ8m3nC;d%?e}_Jc?}x3ZAbo~?sQR?a&9jEBxJ>atg?0&dWm`b)!WN1L zkr5H|C0vPCk+7Pd&-L%$-@8wH;`@>-T@Si_Li;gH>z^Bl8k(l@=2kI(tRa0 z`>%B;=C7d3T)IBDdo%d1#CXCSOxek~JpbQjTau_fabj*>6WVFL5_GF3_~ZKU71n~# zFZ}>b13R(nX+Hy4^^l-0FTlKz&j(bh*|S{*39A(e>3qINeD!#y>qT{8w^px39GW+NnQimtC$R z{x7*wf9dyZSI*6L-DKkZ-JsX&k*^_A{f>O?-_7rDylFQ=)R6{KFPnX+0ZIHR*Y@uU%n1816EZ z@ZiVMzILJCmzbXueppyb{0Go{Za%P70P^wQ6zBo*G2jv3huWV@1OK@^|6u`_rGyKx zUPtYTlY#Ny;iU6XgtHegOzWkDcjft}yTX2G{fzMOz4$#`LhC7n>rK9^UGaOEe^={) zTN=)#iT^PhI={Pt+W+hI{@3iGX|2=ca@PygU$e<%x_V~q!v0|k`&0ZQeyaC_EZ}P= zCmbUD**|pDZpCVpo^am#xqN%ajjt>t{Lbq-;-1{Ga3bE(ophYX^RQmH)qk+{;q8Tl_QoxXFJtoF6|){1e|T z4IfIy8`A#o@ZT(T@*V5cpXCE4^VKsT8_=-?E~G%-OT@XST2no=pIM;AM8PYp`r%gUp;OT=6m$}wu_r)k3QFN z9OZvLMS7$Cx>FzS@iff$|Ci){HjdMA;;xSV*e;igzmXP!{~U|iT$_0LxJRlrystmy zL(^5Nupf+JK38)C{mEazJXB`|L3bCvEG*+wnUpv{2L6`irymT&s0wXdY*gf z>9f2))BF#7>0?G+BpgTcKN&t)G4tZ3(Z25SH2)*4U%_7=Py2Cz#)Ep`f$s4%|C9OX z^=A*BC3}dc`Ja!s-q3Vo~ z8k6aoSt>aa?gM|1r~y>fmV4-}xn=%CYBCR*pa(~`g{2Z+SGmT}*qo@|zB&x;+x%(% z2YX0d{Wjq;f0}O*jvG(c_w^@#1iy))eHo_tA7Nit;y=*;HTW~}FX2o@Ew#hEh;LOy zM5Gh9BwZDp{drfYu3>dWMK>qQY&XOMTK|E38;5mc{L%h2_|;Dx2EM@`t^W|ei>5L@ zDgL0{n7iOC@fqI_`Xuw#8$Z>ZHH{wFDW2B5ee^~{m62gu|A9RiFCW`Dc{Hx4`Jeog_1wNJurXo=kWKI%jG?{ga`VQzw6-dS5A}{9LX&U zp!FYfV`60WXVSt7@Jaherbd-|-zE=zMP8Xdb|>|qH!^<-Zyy1)o`UAcrP0h@X#K~m zN>oRO5Z>lb>%q8Q9nzERW1D|4*5~p2i9Oqd6*c8<3!wEJWQSPqnf#r#@azxKsQ`us_0U z-X^S#-wOMbfZuKD^nI=*PJztNu|d(bA39>|J}XZGbxCQR$Ugs+~=hCOJtG(KYB zmP^^?!Dl;aY5WM=uXBhG(ph8=oKT|wkLL&1;W&F1!!GeWoX%{oPwSET=yTwEeS^;2 ztZw?bJpahl!|?YZH74+V?jZP{dN_dekMPm09)%Tohk1WD!{0yAO2Pl(fMSf72?S;( z0K-0L{TEQ39M0^+g7sg*lZHt3)~GVX`x-ykPhvo4W*@ZvOW*GzTR_1}Bf54j*8NIH=9Iq5@xLq$dJHjGcQA4GRU@KYO2? zad8y!tJRVo5dXO;xE`3+gJnKO!>)AMF#w%y@>zuP|e zd~|{5&EIS0oJT%+Fo3@wm*3oSDXmBP)E|N2-}%kz#-Gabw@e*1nDRLdaNQx|e@x&c zOTr;@ZF9=89q@nfzZ3Zo*~h0Jz#a<61U4Ama&+cK^@odq!9VGz3GIJ-gJIs^VJ|a7 zJY4JG*J^3MAMR_- zU&OE+`~9+_GGkdz4%tU3*#r6aciV{X%+kz5#RkG>z6747EhT*bw*B%0;mpz;%kfHK z?;>OK*_Gv^=4Doqe{td>tId+JXVf#9)np&yf--B%RbiiC@5~d#m$1Mtw>JrOF+DQD zC+wx5&~9(yK92Ep-~xLK-d+>!IWdrL&$laVmo=U--D7~kZ$Wd)HM3?@>RUesQvBvL zwdyNXY57~GO#;4l5_Buf2f_ba%0RMTojFnY{f_dUTQ@5M9enT21^;=URz4>f%wdbA-&gTQNBnx|6Sg{OUWL37na#} zWdX-$-mr%<>!FW;=Vg{s{z&|vC|gPG)s#QL-EHQtSB{-IFSDA)TiCnIYB| zic8;X{+{~Qg+R*Bxq=k=xkG82(%*{V`Gxx{t3NH@v}JQlAg$NwYSoG(TgpG#vUyS< z~<58&TpUww9dZA;4LCBWdH;Y%jp6GZKs&O&sYAczqjVQHEx|B zNV$RO+9g>hC_c3JHdH+GAmjfj+#m994erkKs|^l0)A|$PANPU(d0C#s7xDk&myCZ0KCxG`Jza0}qWQN5 z?Zv_2U7$LW8+Ek3w&&s>f#$*QLNLk=o@MT~Ew8my;qO%M(7UM2s+|je2j7%WLho%G z-{t+iitK~@{p0kNLFE6ueH7X&O0o!N*^9CM#Pu$+?#}B#_&Tkh5Z`+~r`pH9#FnU z_OSE~#y7=p=z}tTJj0}iWDiq=%JU82zwK1`x4AiGR8O?S{~de}XbTMf!MD@|f;$Vs zjLp_lUNqi>ow%^yrSGl%{kLKv7oF}Lyzb_CCwIZcOWLNK(++#^aX~&0e`q4!x)NM|kmT;2*dT@=M}BJr@2yFRMCZ z)$%wo_|HsYeAD^}>HYe5z&H4(`flP|x0u@#Q=H{V_Ct8Xd*Ht~=O+GO0r-diJFZ_h zAN<2U==X5Fa%CLjpYEqAXi+YCBaQ4Kknw9*%nv6$u<-g#`tVi=@jWY$=4Yh$69*BV z6iD@3I^=`U^ZYIFck+*X;J#wuY05x{e|Hgteba2Uc;yn`@ONi!?Y17jBcA_Oet+xr zqz|{xC#4*-2Z|RGA8SPq=WG+jZ>k>^7nRutcLd)vGfOF-6hhx$>dE|_<`>WlYxp4E z->Z4OD700){sQ5wYSKsOfpzvPJpb33e%R#k6Bz$gKgsnjlP4<~K8*b_;#)n9_|NgQ zBt7lGAIBJO;pE9Y|7d5|Crsr1-;?$`xqQ2PPAKD>?x(4>E2fWR*qitTju=e-e*ye{ z>8FAJkCqXh6iD@1qz3_y5dSfOG(RJMm$fPXw^!2Ut2N&+*?9u}tcv3#;W0lLh2+qvbmgQV0`xY13tWQ74`}+xsACUWs z!4LENSJ8PH_`mf9Pp0>D-bz?dRx!p0{Laj(4i0&(7wP@0gBahmUQPMm#K4T8ImKDm zX?{%nM+`;$hyT<1IFE;+q+g$N6Hg3ceBZcUq3~z=Px~Kq{VTqR|1lT9=VD(jzePT> zM;h{j3xU00uf+dzkH8*~FMbGqNgsSfz~GnqqpM9(JRvOK*?hI$i`Lgbze3E79c5Sl z!sly^kqSBH=YMGY{!iOO>-$suxILc`ac5^|9mw${z3{PB$UV4h)0(mzJH->&hurgl zm1F0WWu2z^hq%aI;Vof&Q+$Em%lma?_;u(B@inM3^uIXk^d{_Q16K@wf(x1n|EK*B zY9IVK>;e2cuwNI%1Ly&r52f}2?o9t_{fn?qTi~~BUc{#c^Mf93z^}pXN%hyd<`j8n zLHYjUSM9uB>zeIK2`4?++_IAIk4deN!=F!)K0^MuNVy#6x&i)+{riu8egP-=r}ar^ z?qu30w~d#GJ281j(+B+c%ItD^dv2wv*v>FlXp?soGR)hL-7bGvC@iP;DA*J6=`Q5< z5TqyuoL_TK<2|e;?rOcYPy9@B?vKUudZ8Jm17&|lT_IDdrmC?CbS z45j|7hK|AcLzf^2p3|S5KcegDyxEk;*m;xlQF}db{zUhplbX&GhEGiIUR!y%axo zKF5;ur5~NoTR)NYzdpMz9Oo~DTi@o-V+rQ!>HJ=AZs#JL$3p)r4X-St{_lL3KYtf= z%*gPzdG>GVy!{#j&con5^@d5T|86=1S@O zj5p5DdetqoGW&`A&Eo-n*PmFD*@@@3!q8tKLH#<;t5AP&yiM}Aq3nFZE6ajI=zL1? zEY|wk^~J3Q$BFJDmq+u*!W z7?0}=)L+qbx}MIL|FDjoAKh75pH1flOXAr1l48T*BsyQT;zgV%!TF)Bt9pgd`GN>3 zt2bX7x#H`rpU~c*?;d>vr)YrdF68Mo&S+1zC~GyG?Xb0P<#BOz zwS8SB@q2a?@!d{;?PR}==&r8hZB|cT40{1KEec>*y2xcH>g&zH&gc93qrS4|P&zNC zYNYpfcqT94^DVhtF}^c*ASZi?wlnD!j<@xn^awleP#B(vdUtPGPB_)GPjju$J{V5* z>J@9KUVWN)C-|lF3fB(e`m^PtlMR`N==__#e#3BqQ&+x!-je%pKH;i|Q$Byb0QG`< zXgp9q>>){|@u2e|$FtaZft{6ZIq04#Z!)VV?zpk-RH`4J)|KJ9@Y7vUFKBv_Oa9Dj z&Vm54Zv_f~WvKsF_@%o&1wA$x`ad_zm(}Zznz5L#_x(7|*Gl!kz><+dTrEm z52;y0<=Zm5`P?+|`mw0jh^Rq*{vThjeSWOd1&#Q9vJcf{ljg!Fe7*CLNtRRCyT z34gMH;bH?$c;oNVUeqsQJd)wRgzXL8E(so=%%49JiJY8%_kPo_)(>igW=&fS`Ols` zdo)+}=b}Dvg>`)cs~6n8gy9Bb>@sZktLDFedcm~|Q6JnZgs`9U&rbfR2gB@zum3~; z)6sv_``qY%5MS>%?q>fNq8{X&beyCAm-nLcz_#2S% zqDCnBH`FJb*SO@Dw?#ckvW4nLE`EagA=Gz}{iA#&aYrKhkNP39e_+*IKf>KnAHvsz ztDfa_P60n}3wRCvRjDE(J7d3Bbs+Nu>0f^ofJ8ou{$YRjAoP#=mot&?Z#>0wU}L3r z6ZU&L#Zx?zVSo4f*I4hhbc`pxm&m*g_A6Xh&Rxpab7Ft~_t$G+KQ2ha>SwUgKHFAa z?s5e66xCSa$99OiDu?ZtAFu4Vk@iFKCS!jb`{ks6wEsD+8}`GoKTi5*!uUMNnY()> z9rZee{-XRv@c?%K^Uw936#v{;%jLs`XD@}uYPA&qB&bi)__O^i%5SipX)KOqnDQC) z*LXUQt#=QpK|KT3H?M!=Ha6rLZE3YV;SlXt;gvvr1V2*!0`?1qy^Z!p+-T)0yqX;Q zkDSnk{YQ?=c%AJxa&YVOcvt7qudtt-Y{CAb(pIkNp`SV_ko2C`i)-@P{$b~8>^EQo zpmZMF51{x*_}xH;rHg9(%)lYeY=4O2AGU`hMcnM8v>!<8FXLambN<ofKH*nV7&Wx^qvZ`JerFE%d+zOV!9D_B2?sHrs2di(KgwqAA|@r~Bc zcFrZN40QB2JsA5Vz!|HSVt-VvoYaBsuNQ>odB8p*dvK<{fyuvkQvRdD`bz8kr!{W9 zUe%jxNQ*y^bDGxYu-zq}&<_1YeFEiIV)XwVf7XA>M``_97s1vm>$A^CVL!^cJ>HGq zf1vn@^(yPG#jO97?^6GFy~po2csZ~^#jiJD|HzW0!TLh(WLiJE5J>h+{eL%r_7|0b zl;6;P!lZ{V9#fTp)L+^^>cfSV1)#qp5Z|c3zjr^V^>}o{c$C6l$UeLca`_8R*<h`7iqpYj;%Kh0N&|2h5n^%#51j1T$sv&7;2dW`4cq@MixTjFrG-s-?_4`l0Y z%j0PM&aRx=mG!?a{FDdw)0Dx^)PIW?*)!H#6i;zsV**n$Zu0wk``g+cehs%l{5Xw} zNApn(hx~DFxjR^{{SbhPe$4-zn<2M=zf31`cVgd{z9V2U77w%~mOMY6ANyboy5KD^%v^UJyv_I|gB8a7|7 zdk6EyDwmN%YGV2MD6|e-!tnp<-z=XHMmN+0s&IeY9FK78{>XPwpWmg1<-7JvxcLK8{`|F2=!AbU ze)!LhKXez*)e6^h&XYM8@r$!zOYck?-vt>UdzjG?DrAhq|b{4Qd#BZ zab9G96rVge)z373xwv11;?DTn5%su^=jjiJd6mnVt;Kpc`IE$0A&+%}o?`!E)QqmY zUc@?)Ugq4yVO;tCW_1Rx@5<47vj;c(mz(#)@3r>7*T^3ZWOZB~$NOLZ6M_RN^ggw! zlX%~utx)_U-am!)CcOU!?@vsr)x1g9&ld(@cMSgeYS?iu0q1)!xh5Q1fcJr5KJ?j! zARKpuU3lyh(ZBnoP8yEp^Mm$H)^J?40Oyfm66-3Xq&SYOs^aiv-_`N-eSF6&pfSr{K=saWO8=NRT8;?Zx`_yW={G?_ z>3M}%|2-+7{aU*h-A_}SB7ciB?e&75(({KQ|FPqJMsXir60C3N=2D>-N$i~ZS$}E! zuXi`#eSL|OO?K{y*InstanceID(blasIndex) ->HitGroupIndex(blasIndex) ->Blas(rayTracingSubMesh.m_blas) - ->Transform(rayTracingMesh.second.m_transform) + ->Matrix3x4(rayTracingMesh.second.m_matrix3x4) ; } diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index 99748677d9..d5c9bedf80 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -295,10 +295,10 @@ namespace AZ for (const auto& mesh : m_meshes) { - AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); - AZ::Transform noScaleTransform = meshTransform; - noScaleTransform.ExtractScale(); - AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform); + AZ::Matrix3x4 meshMatrix3x4 = transformFeatureProcessor->GetMatrix3x4ForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); + AZ::Matrix3x4 noScaleMatrix3x4 = meshMatrix3x4; + noScaleMatrix3x4.ExtractScale(); + AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromMatrix3x4(noScaleMatrix3x4); rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose(); const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes; From 2bfb93e5e1fec303714a50df7fc7f03fac862c8d Mon Sep 17 00:00:00 2001 From: greerdv Date: Thu, 15 Apr 2021 12:34:35 +0100 Subject: [PATCH 007/277] fixing non-uniform scale for mesh on activation --- .../Code/Source/Mesh/MeshComponentController.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 17ee56f36e..59f4a8a92a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -293,7 +293,9 @@ namespace AZ m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials); m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler); - const AZ::Matrix3x4& matrix3x4 = m_transformInterface ? Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()) : Matrix3x4::Identity(); + const AZ::Matrix3x4& matrix3x4 = m_transformInterface + ? Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()) * Matrix3x4::CreateScale(m_cachedNonUniformScale) + : Matrix3x4::Identity(); m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, matrix3x4); m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey); m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride); From 53e84b38209532ba2071232162b40b98f93cfe4f Mon Sep 17 00:00:00 2001 From: luissemp Date: Thu, 15 Apr 2021 09:35:09 -0700 Subject: [PATCH 008/277] Fixed scoping rules for variables --- .../Code/Source/Widgets/GraphCanvasLabel.cpp | 2 + .../Code/Editor/Components/EditorGraph.cpp | 2 +- .../Editor/Model/EntityMimeDataHandler.cpp | 2 +- .../GraphValidationDockWidget.cpp | 2 +- .../VariablePanel/GraphVariablesTableView.cpp | 29 +++++++++++- .../VariablePanel/VariableDockWidget.cpp | 2 +- .../Include/ScriptCanvas/Utils/NodeUtils.cpp | 2 + .../ScriptCanvas/Variable/GraphVariable.cpp | 44 ++++++++++++++----- .../ScriptCanvas/Variable/GraphVariable.h | 8 +++- .../GraphVariableManagerComponent.cpp | 8 +++- .../Variable/GraphVariableManagerComponent.h | 2 +- .../ScriptCanvas/Variable/VariableBus.h | 2 +- .../VariableListFullCreation.cpp | 2 +- .../ScriptCanvasActions/VariableActions.cpp | 4 +- .../Framework/ScriptCanvasTestUtilities.h | 2 +- .../Code/Tests/ScriptCanvas_Variables.cpp | 34 +++++++------- 16 files changed, 103 insertions(+), 44 deletions(-) diff --git a/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp b/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp index 21f56e2f39..11b230515a 100644 --- a/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp +++ b/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasLabel.cpp @@ -437,5 +437,7 @@ namespace GraphCanvas default: return QGraphicsWidget::sizeHint(which, constraint); } + + return QGraphicsWidget::sizeHint(which, constraint); } } diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index b14fd7d4c2..9c9297ec1c 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -2347,7 +2347,7 @@ namespace ScriptCanvasEditor AZ::Outcome addOutcome; // #functions2 slot<->variable re-use the activeDatum, send the pointer (actually, all of the source slot information, and make a special conversion) - ScriptCanvas::GraphVariableManagerRequestBus::EventResult(addOutcome, GetScriptCanvasId(), &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, variableDatum); + ScriptCanvas::GraphVariableManagerRequestBus::EventResult(addOutcome, GetScriptCanvasId(), &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, variableDatum, true); if (addOutcome.IsSuccess()) { diff --git a/Gems/ScriptCanvas/Code/Editor/Model/EntityMimeDataHandler.cpp b/Gems/ScriptCanvas/Code/Editor/Model/EntityMimeDataHandler.cpp index 97b9078fab..040019a74e 100644 --- a/Gems/ScriptCanvas/Code/Editor/Model/EntityMimeDataHandler.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Model/EntityMimeDataHandler.cpp @@ -172,7 +172,7 @@ namespace ScriptCanvasEditor { ScriptCanvas::Datum datum = ScriptCanvas::Datum(entityId); - AZ::Outcome addVariableOutcome = variableManagerRequests->AddVariable(variableName, datum); + AZ::Outcome addVariableOutcome = variableManagerRequests->AddVariable(variableName, datum, false); if (addVariableOutcome.IsSuccess()) { diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ValidationPanel/GraphValidationDockWidget.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ValidationPanel/GraphValidationDockWidget.cpp index f3eb7a18d1..fb31fbbb7e 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/ValidationPanel/GraphValidationDockWidget.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/ValidationPanel/GraphValidationDockWidget.cpp @@ -1011,7 +1011,7 @@ namespace ScriptCanvasEditor ScriptCanvas::Datum datum(variableType, ScriptCanvas::Datum::eOriginality::Original); AZ::Outcome outcome = AZ::Failure(AZStd::string()); - ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_activeGraphIds.scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, varName, datum); + ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_activeGraphIds.scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, varName, datum, false); if (outcome.IsSuccess()) { diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.cpp index 7f6abe9b3c..946f30bde8 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.cpp @@ -41,6 +41,7 @@ #include #include +#include namespace ScriptCanvasEditor { @@ -538,7 +539,24 @@ namespace ScriptCanvasEditor } else if (index.column() == ColumnIndex::Scope) { - // Scope is not changed by users + ScriptCanvas::GraphVariable* graphVariable = nullptr; + ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, varId.m_identifier); + + if (graphVariable) + { + QString comboBoxValue = value.toString(); + + if (!comboBoxValue.isEmpty()) + { + AZStd::string scopeLabel = ScriptCanvas::VariableFlags::GetScopeDisplayLabel(graphVariable->GetScope()); + if (scopeLabel.compare(comboBoxValue.toUtf8().data()) != 0) + { + modifiedData = true; + graphVariable->SetScope(ScriptCanvas::VariableFlags::GetScopeFromLabel(comboBoxValue.toUtf8().data())); + AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::Refresh_EntireTree); + } + } + } } else if (index.column() == ColumnIndex::InitialValueSource) { @@ -607,8 +625,17 @@ namespace ScriptCanvasEditor } else if (index.column() == ColumnIndex::Scope) { + ScriptCanvas::GraphScopedVariableId varId = FindScopedVariableIdForIndex(index); + + ScriptCanvas::GraphVariable* graphVariable = nullptr; + ScriptCanvas::GraphVariableManagerRequestBus::EventResult(graphVariable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::FindVariableById, varId.m_identifier); + + if (graphVariable->GetScope() != ScriptCanvas::VariableFlags::Scope::FunctionReadOnly) + { itemFlags |= Qt::ItemIsEditable; } + + } else if (index.column() == ColumnIndex::InitialValueSource) { itemFlags |= Qt::ItemIsEditable; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariableDockWidget.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariableDockWidget.cpp index 6668df21f9..b86532d283 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariableDockWidget.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariableDockWidget.cpp @@ -812,7 +812,7 @@ namespace ScriptCanvasEditor ScriptCanvas::Datum datum(varType, ScriptCanvas::Datum::eOriginality::Original); AZ::Outcome outcome = AZ::Failure(AZStd::string()); - ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, datum); + ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, datum, false); AZ_Warning("VariablePanel", outcome.IsSuccess(), "Could not create new variable: %s", outcome.GetError().c_str()); GeneralRequestBus::Broadcast(&GeneralRequests::PostUndoPoint, m_scriptCanvasId); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp index c1eb2eed36..06ad79c21d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/NodeUtils.cpp @@ -81,6 +81,8 @@ namespace ScriptCanvas { return ConstructCustomNodeIdentifier(scriptCanvasNode->RTTI_GetType()); } + + return NodeTypeIdentifier(0); } NodeTypeIdentifier NodeUtils::ConstructEBusIdentifier(ScriptCanvas::EBusBusId ebusIdentifier) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.cpp index f9c1c0c357..6e5fe82720 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.cpp @@ -43,20 +43,12 @@ namespace ScriptCanvas { const char* GetScopeDisplayLabel(Scope scopeType) { - switch (scopeType) - { - case Scope::Graph: - return "Graph"; - case Scope::Function: - return "Function"; - default: - return "?"; - } + return GraphVariable::s_ScopeNames[static_cast(scopeType)]; } Scope GetScopeFromLabel(const char* label) { - if (strcmp("Function", label) == 0) + if (strcmp(GraphVariable::s_ScopeNames[static_cast(VariableFlags::Scope::Function)], label) == 0) { return Scope::Function; } @@ -71,6 +63,7 @@ namespace ScriptCanvas case Scope::Graph: return "Variable is accessible in the entire graph."; case Scope::Function: + case Scope::FunctionReadOnly: return "Variable is accessible only in the execution path of the function that defined it"; default: return "?"; @@ -162,6 +155,14 @@ namespace ScriptCanvas "From Component" }; + const char* GraphVariable::s_ScopeNames[static_cast(VariableFlags::Scope::COUNT)] = + { + "Graph", + "Function", + "Function", + }; + + void GraphVariable::Reflect(AZ::ReflectContext* context) { if (auto serializeContext = azrtti_cast(context)) @@ -197,6 +198,13 @@ namespace ScriptCanvas return choices; }; + auto scopeChoices = [] { + AZStd::vector< AZStd::pair> choices; + choices.emplace_back(AZStd::make_pair(VariableFlags::Scope::Graph, s_ScopeNames[0])); + choices.emplace_back(AZStd::make_pair(VariableFlags::Scope::Function, s_ScopeNames[1])); + return choices; + }; + editContext->Class("Variable", "Represents a Variable field within a Script Canvas Graph") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, &GraphVariable::GetVisibility) @@ -215,8 +223,8 @@ namespace ScriptCanvas ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GraphVariable::OnValueChanged) ->DataElement(AZ::Edit::UIHandlers::ComboBox, &GraphVariable::m_scope, "Scope", "Controls the scope of this variable. i.e. If this is exposed as input to this script, or output from this script, or if the variable is just locally scoped.") - ->Attribute(AZ::Edit::Attributes::Visibility, &GraphVariable::GetInputControlVisibility) - ->Attribute(AZ::Edit::Attributes::GenericValueList, &GraphVariable::GetScopes) + ->Attribute(AZ::Edit::Attributes::Visibility, &GraphVariable::GetScopeControlVisibility) + ->Attribute(AZ::Edit::Attributes::GenericValueList, scopeChoices) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GraphVariable::OnScopeTypedChanged) ->DataElement(AZ::Edit::UIHandlers::Default, &GraphVariable::m_networkProperties, "Network Properties", "Enables whether or not this value should be network synchronized") @@ -382,6 +390,16 @@ namespace ScriptCanvas m_inputControlVisibility = inputControlVisibility; } + AZ::Crc32 GraphVariable::GetScopeControlVisibility() const + { + if (m_scope == VariableFlags::Scope::FunctionReadOnly) + { + return AZ::Edit::PropertyVisibility::Hide; + } + + return GetInputControlVisibility(); + } + AZ::Crc32 GraphVariable::GetInputControlVisibility() const { return m_inputControlVisibility; @@ -462,6 +480,8 @@ namespace ScriptCanvas return m_scope == VariableFlags::Scope::Graph; // All graph variables are in function local scope case VariableFlags::Scope::Function: + case VariableFlags::Scope::FunctionReadOnly: + return true; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h index 9b5e5cc9d1..4aa3729d7c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h @@ -52,8 +52,10 @@ namespace ScriptCanvas enum class Scope : AZ::u8 { - Graph = 0, - Function = 1, + Graph, + Function, + FunctionReadOnly, + COUNT }; enum InitialValueSource : AZ::u8 @@ -142,6 +144,7 @@ namespace ScriptCanvas void SetScriptInputControlVisibility(const AZ::Crc32& inputControlVisibility); AZ::Crc32 GetInputControlVisibility() const; + AZ::Crc32 GetScopeControlVisibility() const; AZ::Crc32 GetScriptInputControlVisibility() const; AZ::Crc32 GetNetworkSettingsVisibility() const; AZ::Crc32 GetFunctionInputControlVisibility() const; @@ -181,6 +184,7 @@ namespace ScriptCanvas int GetSortPriority() const; static const char* s_InitialValueSourceNames[VariableFlags::InitialValueSource::COUNT]; + static const char* GraphVariable::s_ScopeNames[VariableFlags::Scope::COUNT]; private: diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp index 47f76af4ee..fc5d39148d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp @@ -225,7 +225,7 @@ namespace ScriptCanvas } // #functions2 slot<->variable add this to the graph, using the old datum - AZ::Outcome GraphVariableManagerComponent::AddVariable(AZStd::string_view name, const Datum& value) + AZ::Outcome GraphVariableManagerComponent::AddVariable(AZStd::string_view name, const Datum& value, bool functionScope) { if (FindVariable(name)) { @@ -245,6 +245,10 @@ namespace ScriptCanvas GraphVariable* variable = m_variableData.FindVariable(newId); variable->SetOwningScriptCanvasId(GetScriptCanvasId()); + if (functionScope) + { + variable->SetScope(VariableFlags::Scope::FunctionReadOnly); + } VariableRequestBus::MultiHandler::BusConnect(GraphScopedVariableId(m_scriptCanvasId, newId)); GraphVariableManagerNotificationBus::Event(GetScriptCanvasId(), &GraphVariableManagerNotifications::OnVariableAddedToGraph, newId, name); @@ -254,7 +258,7 @@ namespace ScriptCanvas AZ::Outcome GraphVariableManagerComponent::AddVariablePair(const AZStd::pair& keyValuePair) { - return AddVariable(keyValuePair.first, keyValuePair.second); + return AddVariable(keyValuePair.first, keyValuePair.second, false); } VariableValidationOutcome GraphVariableManagerComponent::IsNameValid(AZStd::string_view varName) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.h index 38d8200a4c..5a75d339d0 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.h @@ -63,7 +63,7 @@ namespace ScriptCanvas //// GraphVariableManagerRequestBus AZ::Outcome CloneVariable(const GraphVariable& variableConfiguration) override; AZ::Outcome RemapVariable(const GraphVariable& variableConfiguration) override; - AZ::Outcome AddVariable(AZStd::string_view name, const Datum& value) override; + AZ::Outcome AddVariable(AZStd::string_view name, const Datum& value, bool functionScope) override; AZ::Outcome AddVariablePair(const AZStd::pair& nameValuePair) override; VariableValidationOutcome IsNameValid(AZStd::string_view key) override; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/VariableBus.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/VariableBus.h index 7c486ff5c7..f7948907af 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/VariableBus.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/VariableBus.h @@ -90,7 +90,7 @@ namespace ScriptCanvas //! returns an AZ::Outcome which on success contains the VariableId and on Failure contains a string with error information virtual AZ::Outcome CloneVariable(const GraphVariable& baseVariable) = 0; virtual AZ::Outcome RemapVariable(const GraphVariable& variableConfiguration) = 0; - virtual AZ::Outcome AddVariable(AZStd::string_view key, const Datum& value) = 0; + virtual AZ::Outcome AddVariable(AZStd::string_view key, const Datum& value, bool functionScope) = 0; virtual AZ::Outcome AddVariablePair(const AZStd::pair& keyValuePair) = 0; virtual VariableValidationOutcome IsNameValid(AZStd::string_view variableName) = 0; diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/VariableListFullCreation.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/VariableListFullCreation.cpp index fd3d7b3e9b..9a523aaf61 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/VariableListFullCreation.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/VariableListFullCreation.cpp @@ -63,7 +63,7 @@ namespace ScriptCanvasDeveloperEditor ScriptCanvas::Datum datum(dataType, ScriptCanvas::Datum::eOriginality::Original); AZ::Outcome outcome = AZ::Failure(AZStd::string()); - m_variableRequests->AddVariable(variableName, datum); + m_variableRequests->AddVariable(variableName, datum, false); ++m_variableCounter; } diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/VariableActions.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/VariableActions.cpp index 18bebecd2a..2e338e5d01 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/VariableActions.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/VariableActions.cpp @@ -144,7 +144,7 @@ namespace ScriptCanvasDeveloper { ScriptCanvasEditor::SceneCounterRequestBus::EventResult(variableCounter, m_scriptCanvasId, &ScriptCanvasEditor::SceneCounterRequests::GetNewVariableCounter); - // Cribbed from VariableDockWidget. Shuld always be in sync with that. + // From VariableDockWidget, Should always be in sync with that. variableName = AZStd::string::format("Variable %u", variableCounter); ScriptCanvas::GraphVariableManagerRequestBus::EventResult(nameAvailable, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::IsNameAvailable, variableName); @@ -154,7 +154,7 @@ namespace ScriptCanvasDeveloper ScriptCanvas::Datum datum(m_dataType, ScriptCanvas::Datum::eOriginality::Original); AZ::Outcome outcome = AZ::Failure(AZStd::string()); - ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, datum); + ScriptCanvas::GraphVariableManagerRequestBus::EventResult(outcome, m_scriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, datum, false); if (outcome) { diff --git a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.h b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.h index b9ca80c6ff..dcaad30479 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.h +++ b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.h @@ -96,7 +96,7 @@ namespace ScriptCanvasTests { using namespace ScriptCanvas; AZ::Outcome addVariableOutcome = AZ::Failure(AZStd::string()); - GraphVariableManagerRequestBus::EventResult(addVariableOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, variableName, Datum(value)); + GraphVariableManagerRequestBus::EventResult(addVariableOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, variableName, Datum(value), false); if (!addVariableOutcome) { AZ_Warning("Script Canvas Test", false, "%s", addVariableOutcome.GetError().data()); diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_Variables.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_Variables.cpp index 1c23048405..2a8be6688c 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_Variables.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_Variables.cpp @@ -104,27 +104,27 @@ TEST_F(ScriptCanvasTestFixture, CreateVariableTest) auto stringArrayDatum = Datum(StringArray()); AZ::Outcome addPropertyOutcome(AZ::Failure(AZStd::string("Uninitialized"))); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "FirstVector3", vector3Datum1); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "FirstVector3", vector3Datum1, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "SecondVector3", vector3Datum2); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "SecondVector3", vector3Datum2, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "FirstVector4", vector4Datum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "FirstVector4", vector4Datum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "ProjectionMatrix", behaviorMatrix4x4Datum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "ProjectionMatrix", behaviorMatrix4x4Datum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "My String Array", stringArrayDatum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "My String Array", stringArrayDatum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); @@ -169,12 +169,12 @@ TEST_F(ScriptCanvasTestFixture, AddVariableFailTest) const AZStd::string_view propertyName = "SameName"; AZ::Outcome addPropertyOutcome(AZ::Failure(AZStd::string("Uninitialized"))); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, propertyName, vector3Datum1); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, propertyName, vector3Datum1, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, propertyName, vector3Datum2); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, propertyName, vector3Datum2, false); EXPECT_FALSE(addPropertyOutcome); propertyEntity.reset(); @@ -208,35 +208,35 @@ TEST_F(ScriptCanvasTestFixture, RemoveVariableTest) size_t numVariablesAdded = 0U; AZ::Outcome addPropertyOutcome(AZ::Failure(AZStd::string("Uninitialized"))); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "FirstVector3", vector3Datum1); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "FirstVector3", vector3Datum1, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); const VariableId firstVector3Id = addPropertyOutcome.GetValue(); ++numVariablesAdded; addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "SecondVector3", vector3Datum2); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "SecondVector3", vector3Datum2, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); const VariableId secondVector3Id = addPropertyOutcome.GetValue(); ++numVariablesAdded; addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "FirstVector4", vector4Datum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "FirstVector4", vector4Datum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); const VariableId firstVector4Id = addPropertyOutcome.GetValue(); ++numVariablesAdded; addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "ProjectionMatrix", behaviorMatrix4x4Datum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "ProjectionMatrix", behaviorMatrix4x4Datum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); const VariableId projectionMatrixId = addPropertyOutcome.GetValue(); ++numVariablesAdded; addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "My String Array", stringArrayDatum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "My String Array", stringArrayDatum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); const VariableId stringArrayId = addPropertyOutcome.GetValue(); @@ -294,7 +294,7 @@ TEST_F(ScriptCanvasTestFixture, RemoveVariableTest) { // Re-add removed Property addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "ProjectionMatrix", behaviorMatrix4x4Datum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "ProjectionMatrix", behaviorMatrix4x4Datum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); @@ -332,7 +332,7 @@ TEST_F(ScriptCanvasTestFixture, FindVariableTest) const AZStd::string_view propertyName = "StringProperty"; AZ::Outcome addPropertyOutcome(AZ::Failure(AZStd::string("Uninitialized"))); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, propertyName, stringVariableDatum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, propertyName, stringVariableDatum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); const VariableId stringVariableId = addPropertyOutcome.GetValue(); @@ -391,7 +391,7 @@ TEST_F(ScriptCanvasTestFixture, ModifyVariableTest) const AZStd::string_view propertyName = "StringProperty"; AZ::Outcome addPropertyOutcome(AZ::Failure(AZStd::string("Uninitialized"))); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, propertyName, stringVariableDatum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, propertyName, stringVariableDatum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); const VariableId stringVariableId = addPropertyOutcome.GetValue(); @@ -449,7 +449,7 @@ TEST_F(ScriptCanvasTestFixture, SerializationTest) auto stringArrayDatum = Datum(StringArray()); AZ::Outcome addPropertyOutcome(AZ::Failure(AZStd::string("Uninitialized"))); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "My String Array", stringArrayDatum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "My String Array", stringArrayDatum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); @@ -493,7 +493,7 @@ TEST_F(ScriptCanvasTestFixture, SerializationTest) auto identityMatrixDatum = Datum(Data::Matrix3x3Type::CreateIdentity()); addPropertyOutcome = AZ::Failure(AZStd::string("Uninitialized")); - GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "Super Matrix Bros", identityMatrixDatum); + GraphVariableManagerRequestBus::EventResult(addPropertyOutcome, scriptCanvasId, &GraphVariableManagerRequests::AddVariable, "Super Matrix Bros", identityMatrixDatum, false); EXPECT_TRUE(addPropertyOutcome); EXPECT_TRUE(addPropertyOutcome.GetValue().IsValid()); From f5791ee60a9b4f1982fdc81bae554ea1f5af99ee Mon Sep 17 00:00:00 2001 From: luissemp Date: Thu, 15 Apr 2021 10:08:07 -0700 Subject: [PATCH 009/277] Fixed compile error and added Setters to Node Palette --- .../Editor/View/Widgets/NodePalette/NodePaletteModel.cpp | 8 ++++++++ .../Code/Include/ScriptCanvas/Variable/GraphVariable.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp index bce247aee7..4154c3982e 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp @@ -578,6 +578,14 @@ namespace categoryPath.append(displayName.c_str()); } + for (auto property : behaviorClass->m_properties) + { + if (property.second->m_setter) + { + RegisterMethod(nodePaletteModel, behaviorContext, categoryPath, behaviorClass, property.first, *property.second->m_setter, behaviorClass->IsMethodOverloaded(property.first)); + } + } + for (auto methodIter : behaviorClass->m_methods) { if (!IsExplicitOverload(*methodIter.second)) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h index 4aa3729d7c..af25100fbe 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h @@ -184,7 +184,7 @@ namespace ScriptCanvas int GetSortPriority() const; static const char* s_InitialValueSourceNames[VariableFlags::InitialValueSource::COUNT]; - static const char* GraphVariable::s_ScopeNames[VariableFlags::Scope::COUNT]; + static const char* GraphVariable::s_ScopeNames[static_cast(VariableFlags::Scope::COUNT)]; private: From 80f8c0f68b3e8b511fa7fe106adc20e23c3180eb Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Thu, 15 Apr 2021 13:21:24 -0500 Subject: [PATCH 010/277] behavior context class SceneGraph::NodeIndex -> "NodeIndex" --- .../Gem/PythonTests/CMakeLists.txt | 25 ++++++++++++++++--- .../SceneCore/Containers/SceneGraph.cpp | 4 +-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index ea9c365978..056c7982a6 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -117,12 +117,30 @@ endif() #endif() ## Editor Python Bindings ## +#if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) +# ly_add_pytest( +# NAME AutomatedTesting::EditorPythonBindings +# TEST_SUITE sandbox +# TEST_SERIAL +# PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings +# TIMEOUT 3600 +# RUNTIME_DEPENDENCIES +# Legacy::Editor +# Legacy::CryRenderNULL +# AZ::AssetProcessor +# AutomatedTesting.Assets +# Gem::EditorPythonBindings.Editor +# COMPONENT TestTools +# ) +#endif() + +## Python Asset Builder ## if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_pytest( - NAME AutomatedTesting::EditorPythonBindings - TEST_SUITE sandbox + NAME AutomatedTesting::PythonAssetBuilder + TEST_SUITE periodic TEST_SERIAL - PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings + PATH ${CMAKE_CURRENT_LIST_DIR}/PythonAssetBuilder TIMEOUT 3600 RUNTIME_DEPENDENCIES Legacy::Editor @@ -130,6 +148,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) AZ::AssetProcessor AutomatedTesting.Assets Gem::EditorPythonBindings.Editor + Gem::PythonAssetBuilder.Editor COMPONENT TestTools ) endif() diff --git a/Code/Tools/SceneAPI/SceneCore/Containers/SceneGraph.cpp b/Code/Tools/SceneAPI/SceneCore/Containers/SceneGraph.cpp index 934b0154c9..87c265481f 100644 --- a/Code/Tools/SceneAPI/SceneCore/Containers/SceneGraph.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Containers/SceneGraph.cpp @@ -43,7 +43,7 @@ namespace AZ AZ::BehaviorContext* behaviorContext = azrtti_cast(context); if (behaviorContext) { - behaviorContext->Class() + behaviorContext->Class("NodeIndex") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Module, "scene.graph") ->Constructor<>() @@ -57,7 +57,7 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString) ; - behaviorContext->Class() + behaviorContext->Class("SceneGraphName") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Module, "scene.graph") ->Constructor() From f938fde4b0f7549c4975cf5c6ebf95e77e89de8c Mon Sep 17 00:00:00 2001 From: luissemp Date: Thu, 15 Apr 2021 11:54:45 -0700 Subject: [PATCH 011/277] Compile fix --- .../Code/Include/ScriptCanvas/Variable/GraphVariable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h index af25100fbe..d305bedd08 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariable.h @@ -184,7 +184,7 @@ namespace ScriptCanvas int GetSortPriority() const; static const char* s_InitialValueSourceNames[VariableFlags::InitialValueSource::COUNT]; - static const char* GraphVariable::s_ScopeNames[static_cast(VariableFlags::Scope::COUNT)]; + static const char* s_ScopeNames[static_cast(VariableFlags::Scope::COUNT)]; private: From a5fdbddedaba651f097982dfa0facfacd404b9be Mon Sep 17 00:00:00 2001 From: pereslav Date: Thu, 15 Apr 2021 20:24:50 +0100 Subject: [PATCH 012/277] Merged MultiplayerPipeline from CodeCommit --- .../Serialization/ISerializer.inl | 18 ++ Gems/Multiplayer/Code/CMakeLists.txt | 21 ++ .../Code/Source/MultiplayerGem.cpp | 4 + .../Code/Source/MultiplayerToolsModule.cpp | 65 +++++++ .../Code/Source/MultiplayerToolsModule.h | 33 ++++ .../Code/Source/MultiplayerTypes.h | 47 ++++- .../EntityReplicationManager.cpp | 2 +- .../NetworkEntity/INetworkEntityManager.h | 6 +- .../NetworkEntity/NetworkEntityManager.cpp | 110 ++++++++++- .../NetworkEntity/NetworkEntityManager.h | 31 ++- .../NetworkEntity/NetworkSpawnableLibrary.cpp | 81 ++++++++ .../NetworkEntity/NetworkSpawnableLibrary.h | 43 ++++ .../Pipeline/NetBindMarkerComponent.cpp | 35 ++++ .../Source/Pipeline/NetBindMarkerComponent.h | 39 ++++ .../Pipeline/NetworkPrefabProcessor.cpp | 184 ++++++++++++++++++ .../Source/Pipeline/NetworkPrefabProcessor.h | 43 ++++ .../NetworkSpawnableHolderComponent.cpp | 42 ++++ .../NetworkSpawnableHolderComponent.h | 44 +++++ Gems/Multiplayer/Code/multiplayer_files.cmake | 6 + .../Code/multiplayer_tools_files.cmake | 19 ++ Gems/Multiplayer/Registry/prefab.tools.setreg | 26 +++ 21 files changed, 890 insertions(+), 9 deletions(-) create mode 100644 Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp create mode 100644 Gems/Multiplayer/Code/Source/MultiplayerToolsModule.h create mode 100644 Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp create mode 100644 Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h create mode 100644 Gems/Multiplayer/Code/multiplayer_tools_files.cmake create mode 100644 Gems/Multiplayer/Registry/prefab.tools.setreg diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl b/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl index 2d983c2061..2720f09f4b 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl @@ -18,6 +18,8 @@ #include #include #include +#include "AzCore/Name/Name.h" +#include "AzCore/Name/NameDictionary.h" namespace AzNetworking { @@ -173,6 +175,22 @@ namespace AzNetworking return true; } }; + + template<> + struct SerializeObjectHelper + { + static bool SerializeObject(ISerializer& serializer, AZ::Name& value) + { + AZ::Name::Hash nameHash = value.GetHash(); + bool result = serializer.Serialize(nameHash, "NameHash"); + + if (result && serializer.GetSerializerMode() == SerializerMode::WriteToObject) + { + value = AZ::NameDictionary::Instance().FindName(nameHash); + } + return result; + } + }; } #include diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index dde5e387f6..d395938e8c 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -56,6 +56,27 @@ ly_add_target( Gem::CertificateManager ) + +if (PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_target( + NAME Multiplayer.Tools MODULE + NAMESPACE Gem + OUTPUT_NAME Gem.Multiplayer.Tools + FILES_CMAKE + multiplayer_tools_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Source + . + PUBLIC + Include + BUILD_DEPENDENCIES + PRIVATE + AZ::AzToolsFramework + Gem::Multiplayer.Static + ) +endif() + ################################################################################ # Tests ################################################################################ diff --git a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp index 9fa1413be5..15d4e2f6f0 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include namespace Multiplayer { @@ -26,6 +28,8 @@ namespace Multiplayer AzNetworking::NetworkingSystemComponent::CreateDescriptor(), MultiplayerSystemComponent::CreateDescriptor(), NetBindComponent::CreateDescriptor(), + NetBindMarkerComponent::CreateDescriptor(), + NetworkSpawnableHolderComponent::CreateDescriptor(), }); CreateComponentDescriptors(m_descriptors); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp new file mode 100644 index 0000000000..16f13f9ee8 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp @@ -0,0 +1,65 @@ +/* +* 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 "Pipeline/NetworkPrefabProcessor.h" +#include "AzCore/Serialization/Json/RegistrationContext.h" +#include "Prefab/Instance/InstanceSerializer.h" + +namespace Multiplayer +{ + //! Multiplayer system component wraps the bridging logic between the game and transport layer. + class MultiplayerToolsSystemComponent final + : public AZ::Component + { + public: + AZ_COMPONENT(MultiplayerToolsSystemComponent, "{65AF5342-0ECE-423B-B646-AF55A122F72B}"); + + static void Reflect(AZ::ReflectContext* context) + { + NetworkPrefabProcessor::Reflect(context); + } + + MultiplayerToolsSystemComponent() = default; + ~MultiplayerToolsSystemComponent() override = default; + + /// AZ::Component overrides. + void Activate() override + { + + } + + void Deactivate() override + { + + } + }; + + MultiplayerToolsModule::MultiplayerToolsModule() + : AZ::Module() + { + m_descriptors.insert(m_descriptors.end(), { + MultiplayerToolsSystemComponent::CreateDescriptor(), + }); + } + + AZ::ComponentTypeList MultiplayerToolsModule::GetRequiredSystemComponents() const + { + return AZ::ComponentTypeList + { + azrtti_typeid(), + }; + } +} // namespace Multiplayer + +AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer2_Tools, Multiplayer::MultiplayerToolsModule); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.h b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.h new file mode 100644 index 0000000000..823bd63a1d --- /dev/null +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.h @@ -0,0 +1,33 @@ +/* +* 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 MultiplayerToolsModule + : public AZ::Module + { + public: + + AZ_RTTI(MultiplayerToolsModule, "{3F726172-21FC-48FA-8CFA-7D87EBA07E55}", AZ::Module); + AZ_CLASS_ALLOCATOR(MultiplayerToolsModule, AZ::SystemAllocator, 0); + + MultiplayerToolsModule(); + ~MultiplayerToolsModule() override = default; + + AZ::ComponentTypeList GetRequiredSystemComponents() const override; + }; +} // namespace Multiplayer + diff --git a/Gems/Multiplayer/Code/Source/MultiplayerTypes.h b/Gems/Multiplayer/Code/Source/MultiplayerTypes.h index b387602843..ad491f4016 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerTypes.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerTypes.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace Multiplayer { @@ -69,14 +70,54 @@ namespace Multiplayer True }; + template + bool Serialize(TYPE& value, const char* name); + + inline NetEntityId MakeEntityId(uint8_t a_ServerId, int32_t a_NextId) + { + constexpr int32_t MAX_ENTITYID = 0x00FFFFFF; + + AZ_Assert((a_NextId < MAX_ENTITYID) && (a_NextId > 0), "Requested Id out of range"); + + NetEntityId ret = NetEntityId(((static_cast(a_ServerId) << 24) & 0xFF000000) | (a_NextId & MAX_ENTITYID)); + return ret; + } + // This is just a placeholder // The level/prefab cooking will devise the actual solution for identifying a dynamically spawnable entity within a prefab struct PrefabEntityId { AZ_TYPE_INFO(PrefabEntityId, "{EFD37465-CCAC-4E87-A825-41B4010A2C75}"); - bool operator==(const PrefabEntityId&) const { return true; } - bool operator!=(const PrefabEntityId& rhs) const { return !(*this == rhs); } - bool Serialize(AzNetworking::ISerializer&) { return true; } + + static constexpr uint32_t AllIndices = AZStd::numeric_limits::max(); + + AZ::Name m_prefabName; + uint32_t m_entityOffset = AllIndices; + + PrefabEntityId() = default; + + explicit PrefabEntityId(AZ::Name name, uint32_t entityOffset = AllIndices) + : m_prefabName(name) + , m_entityOffset(entityOffset) + { + } + + bool operator==(const PrefabEntityId& rhs) const + { + return m_prefabName == rhs.m_prefabName && m_entityOffset == rhs.m_entityOffset; + } + + bool operator!=(const PrefabEntityId& rhs) const + { + return !(*this == rhs); + } + + bool Serialize(AzNetworking::ISerializer& serializer) + { + serializer.Serialize(m_prefabName, "prefabName"); + serializer.Serialize(m_entityOffset, "entityOffset"); + return serializer.IsValid(); + } }; } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index e58b7fde9d..e19bc7685b 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -544,7 +544,7 @@ namespace Multiplayer if (createEntity) { //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()); + AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab %s", prefabEntityId.m_prefabName.GetCStr()); if (replicatorEntity == nullptr) { return false; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h index 2262cccd19..be4f32752d 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h @@ -16,6 +16,7 @@ #include #include #include +#include namespace Multiplayer { @@ -35,6 +36,7 @@ namespace Multiplayer AZ_RTTI(INetworkEntityManager, "{109759DE-9492-439C-A0B1-AE46E6FD029C}"); using OwnedEntitySet = AZStd::unordered_set; + using EntityList = AZStd::vector; virtual ~INetworkEntityManager() = default; @@ -50,7 +52,9 @@ namespace Multiplayer //! @return the HostId for this INetworkEntityManager instance virtual HostId GetHostId() const = 0; - // TODO: Spawn methods for entities within slices/prefabs/levels + //! Creates new entities of the given archetype + //! @param prefabEntryId the name of the spawnable to spawn + virtual void CreateEntitiesImmediate(const PrefabEntityId& prefabEntryId) = 0; //! Returns an ConstEntityPtr for the provided entityId. //! @param netEntityId the netEntityId to get an ConstEntityPtr for diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 46d1617760..d92becfb97 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -32,12 +32,15 @@ namespace Multiplayer , m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event")) , m_entityAddedEventHandler([this](AZ::Entity* entity) { OnEntityAdded(entity); }) , m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); }) + , m_rootSpawnableMonitor(*this) { AZ::Interface::Register(this); + AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); } NetworkEntityManager::~NetworkEntityManager() { + AzFramework::RootSpawnableNotificationBus::Handler::BusDisconnect(); AZ::Interface::Unregister(this); } @@ -147,7 +150,6 @@ namespace Multiplayer //{ // rootSlice->RemoveEntity(entity); //} - m_nonNetworkedEntities.clear(); m_networkEntityTracker.clear(); } @@ -282,7 +284,7 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { - const NetEntityId netEntityId = m_nextEntityId++; + const NetEntityId netEntityId = NextId(); netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority); } } @@ -334,4 +336,108 @@ namespace Multiplayer m_networkEntityTracker.erase(entityId); } } + + INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable) + { + INetworkEntityManager::EntityList returnList; + + AZ::SerializeContext* serializeContext = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + + const AzFramework::Spawnable::EntityList& entities = spawnable.GetEntities(); + size_t entitiesSize = entities.size(); + + for (size_t i = 0; i < entitiesSize; ++i) + { + AZ::Entity* clone = serializeContext->CloneObject(entities[i].get()); + AZ_Assert(clone != nullptr, "Failed to clone spawnable entity."); + clone->SetId(AZ::Entity::MakeId()); + + NetBindComponent* netBindComponent = clone->FindComponent(); + if (netBindComponent != nullptr) + { + PrefabEntityId prefabEntityId; + prefabEntityId.m_prefabName = m_networkPrefabLibrary.GetPrefabNameFromAssetId(spawnable.GetId()); + prefabEntityId.m_entityOffset = aznumeric_cast(i); + + const NetEntityId netEntityId = NextId(); + netBindComponent->PreInit(clone, prefabEntityId, netEntityId, NetEntityRole::Authority); + + AzFramework::GameEntityContextRequestBus::Broadcast( + &AzFramework::GameEntityContextRequestBus::Events::AddGameEntity, clone); + + returnList.push_back(netBindComponent->GetEntityHandle()); + + } + else + { + delete clone; + } + } + + return returnList; + } + + void NetworkEntityManager::CreateEntitiesImmediate([[maybe_unused]] const PrefabEntityId& a_SliceEntryId) + { + } + + Multiplayer::NetEntityId NetworkEntityManager::NextId() + { + const NetEntityId netEntityId = m_nextEntityId++; + return netEntityId; + } + + void NetworkEntityManager::OnRootSpawnableAssigned( + [[maybe_unused]] AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) + { + AZStd::string hint = rootSpawnable.GetHint(); + + size_t extensionPos = hint.find(".spawnable"); + if (extensionPos == AZStd::string::npos) + { + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root spawnable hint doesn't have .spawnable extension"); + return; + } + + AZStd::string newhint = hint.replace(extensionPos, 0, ".network"); + auto rootSpawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(AZ::Name(newhint)); + if (!rootSpawnableAssetId.IsValid()) + { + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Network spawnable asset ID is invalid"); + return; + } + + m_rootSpawnableAsset = AZ::Data::Asset( + rootSpawnableAssetId, azrtti_typeid(), newhint); + if (m_rootSpawnableAsset.QueueLoad()) + { + m_rootSpawnableMonitor.Connect(rootSpawnableAssetId); + } + else + { + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Unable to queue networked root spawnable '%s' for loading.", + m_rootSpawnableAsset.GetHint().c_str()); + } + } + + void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) + { + m_rootSpawnableMonitor.Disconnect(); + } + + + NetworkEntityManager::NetworkSpawnableMonitor::NetworkSpawnableMonitor( + NetworkEntityManager& entityManager) + : m_entityManager(entityManager) + { + } + + void NetworkEntityManager::NetworkSpawnableMonitor::OnAssetReady(AZ::Data::Asset asset) + { + AzFramework::Spawnable* spawnable = asset.GetAs(); + AZ_Assert(spawnable, "NetworkSpawnableMonitor: Loaded asset data didn't contain a Spawanble."); + + m_entityManager.CreateEntitiesImmediate(*spawnable); + } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index b154983f4c..20c67a74fd 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -14,11 +14,15 @@ #include #include +#include +#include #include #include #include #include #include +#include + namespace Multiplayer { @@ -26,6 +30,7 @@ namespace Multiplayer //! This class creates and manages all networked entities. class NetworkEntityManager final : public INetworkEntityManager + , public AzFramework::RootSpawnableNotificationBus::Handler { public: NetworkEntityManager(); @@ -40,6 +45,11 @@ namespace Multiplayer NetworkEntityAuthorityTracker* GetNetworkEntityAuthorityTracker() override; HostId GetHostId() const override; ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const override; + + EntityList CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable); + + void CreateEntitiesImmediate(const PrefabEntityId& a_SliceEntryId) override; + uint32_t GetEntityCount() const override; NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) override; void MarkForRemoval(const ConstNetworkEntityHandle& entityHandle) override; @@ -61,19 +71,32 @@ namespace Multiplayer void DispatchLocalDeferredRpcMessages(); void UpdateEntityDomain(); void OnEntityExitDomain(NetEntityId entityId); + //! RootSpawnableNotificationBus + //! @{ + void OnRootSpawnableAssigned(AZ::Data::Asset rootSpawnable, uint32_t generation) override; + void OnRootSpawnableReleased(uint32_t generation) override; + //! @} private: + class NetworkSpawnableMonitor final : public AzFramework::SpawnableMonitor + { + public: + explicit NetworkSpawnableMonitor(NetworkEntityManager& entityManager); + void OnAssetReady(AZ::Data::Asset asset) override; + + NetworkEntityManager& m_entityManager; + }; void OnEntityAdded(AZ::Entity* entity); void OnEntityRemoved(AZ::Entity* entity); void RemoveEntities(); + NetEntityId NextId(); + NetworkEntityTracker m_networkEntityTracker; NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker; AZ::ScheduledEvent m_removeEntitiesEvent; AZStd::vector m_removeList; - AZStd::vector m_nonNetworkedEntities; // Contains entities that we've instantiated, but are not networked entities - AZStd::unique_ptr m_entityDomain; AZ::ScheduledEvent m_updateEntityDomainEvent; @@ -95,5 +118,9 @@ namespace Multiplayer // This is done to prevent local and network sent RPC's from having different dispatch behaviours typedef AZStd::deque DeferredRpcMessages; DeferredRpcMessages m_localDeferredRpcMessages; + + NetworkSpawnableLibrary m_networkPrefabLibrary; + NetworkSpawnableMonitor m_rootSpawnableMonitor; + AZ::Data::Asset m_rootSpawnableAsset; }; } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp new file mode 100644 index 0000000000..ad2e18e222 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp @@ -0,0 +1,81 @@ +/* + * 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 + +namespace Multiplayer +{ + NetworkSpawnableLibrary::NetworkSpawnableLibrary() + { + AzFramework::AssetCatalogEventBus::Handler::BusConnect(); + } + + NetworkSpawnableLibrary::~NetworkSpawnableLibrary() + { + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); + } + + void NetworkSpawnableLibrary::BuildPrefabsList() + { + auto enumerateCallback = [this](const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info) + { + if (info.m_assetType == AZ::AzTypeInfo::Uuid()) + { + ProcessSpawnableAsset(info.m_relativePath, id); + } + }; + + AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::EnumerateAssets, nullptr, + enumerateCallback, nullptr); + } + + void NetworkSpawnableLibrary::ProcessSpawnableAsset(const AZStd::string& relativePath, const AZ::Data::AssetId id) + { + const AZ::Name name = AZ::Name(relativePath); + m_spawnables[name] = id; + m_spawnablesReverseLookup[id] = name; + + } + + void NetworkSpawnableLibrary::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) + { + BuildPrefabsList(); + } + + AZ::Name NetworkSpawnableLibrary::GetPrefabNameFromAssetId(AZ::Data::AssetId assetId) + { + if (assetId.IsValid()) + { + auto it = m_spawnablesReverseLookup.find(assetId); + if (it != m_spawnablesReverseLookup.end()) + { + return it->second; + } + } + + return {}; + } + + AZ::Data::AssetId NetworkSpawnableLibrary::GetAssetIdByName(AZ::Name name) + { + auto it = m_spawnables.find(name); + if (it != m_spawnables.end()) + { + return it->second; + } + + return {}; + } +} diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h new file mode 100644 index 0000000000..a2c3d4ae56 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h @@ -0,0 +1,43 @@ +/* +* 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 + +namespace Multiplayer +{ + /// Implementation of the network prefab library interface. + class NetworkSpawnableLibrary final + : private AzFramework::AssetCatalogEventBus::Handler + { + public: + NetworkSpawnableLibrary(); + ~NetworkSpawnableLibrary(); + + void BuildPrefabsList(); + void ProcessSpawnableAsset(const AZStd::string& relativePath, AZ::Data::AssetId id); + + /// AssetCatalogEventBus overrides. + void OnCatalogLoaded(const char* catalogFile) override; + + AZ::Name GetPrefabNameFromAssetId(AZ::Data::AssetId assetId); + AZ::Data::AssetId GetAssetIdByName(AZ::Name name); + + private: + AZStd::unordered_map m_spawnables; + AZStd::unordered_map m_spawnablesReverseLookup; + }; +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp new file mode 100644 index 0000000000..84983b700e --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp @@ -0,0 +1,35 @@ +/* + * 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 + +namespace Multiplayer +{ + void NetBindMarkerComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1); + } + } + + void NetBindMarkerComponent::Activate() + { + } + + void NetBindMarkerComponent::Deactivate() + { + } +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h new file mode 100644 index 0000000000..ebafead73c --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h @@ -0,0 +1,39 @@ +/* +* 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 NetBindMarkerComponent + //! @brief Component for tracking net entities in the original non-networked spawnable. + class NetBindMarkerComponent final : public AZ::Component + { + public: + AZ_COMPONENT(NetBindMarkerComponent, "{40612C1B-427D-45C6-A2F0-04E16DF5B718}"); + + static void Reflect(AZ::ReflectContext* context); + + NetBindMarkerComponent() = default; + ~NetBindMarkerComponent() override = default; + + //! AZ::Component overrides. + //! @{ + void Activate() override; + void Deactivate() override; + //! @} + + private: + }; +} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp new file mode 100644 index 0000000000..0995ec29d8 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -0,0 +1,184 @@ +/* + * 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 + +namespace Multiplayer +{ + using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor; + using AzToolsFramework::Prefab::PrefabConversionUtils::ProcessedObjectStore; + + void NetworkPrefabProcessor::Process(PrefabProcessorContext& context) + { + context.ListPrefabs([&context](AZStd::string_view prefabName, PrefabDom& prefab) { + ProcessPrefab(context, prefabName, prefab); + }); + } + + void NetworkPrefabProcessor::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context); serializeContext != nullptr) + { + serializeContext->Class()->Version(1); + } + } + + static AZStd::vector GetEntitiesFromInstance(AZStd::unique_ptr& instance) + { + AZStd::vector result; + + instance->GetNestedEntities([&result](const AZStd::unique_ptr& entity) { + result.emplace_back(entity.get()); + return true; + }); + + if (instance->HasContainerEntity()) + { + auto containerEntityReference = instance->GetContainerEntity(); + result.emplace_back(&containerEntityReference->get()); + } + + return result; + } + void NetworkPrefabProcessor::ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab) + { + using namespace AzToolsFramework::Prefab; + + // convert Prefab DOM into Prefab Instance. + AZStd::unique_ptr sourceInstance(aznew Instance()); + if (!PrefabDomUtils::LoadInstanceFromPrefabDom(*sourceInstance, prefab, + PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId)) + { + PrefabDomValueReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName); + + AZStd::string errorMessage("NetworkPrefabProcessor: Failed to Load Prefab Instance from given Prefab Dom."); + if (sourceReference.has_value() && sourceReference->get().IsString() && sourceReference->get().GetStringLength() != 0) + { + AZStd::string_view source(sourceReference->get().GetString(), sourceReference->get().GetStringLength()); + errorMessage += AZStd::string::format("Prefab Source: %.*s", AZ_STRING_ARG(source)); + } + AZ_Error("NetworkPrefabProcessor", false, errorMessage.c_str()); + return; + } + + AZStd::string uniqueName = prefabName; + uniqueName += ".network.spawnable"; + + auto serializer = [](AZStd::vector& output, const ProcessedObjectStore& object) -> bool { + AZ::IO::ByteContainerStream stream(&output); + auto& asset = object.GetAsset(); + return AZ::Utils::SaveObjectToStream(stream, AZ::DataStream::ST_JSON, &asset, asset.GetType()); + }; + + auto&& [object, networkSpawnable] = + ProcessedObjectStore::Create(uniqueName, context.GetSourceUuid(), AZStd::move(serializer)); + + // grab all nested entities from the Instance as source entities. + AZStd::vector sourceEntities = GetEntitiesFromInstance(sourceInstance); + AZStd::vector networkedEntityIds; + networkedEntityIds.reserve(sourceEntities.size()); + + for (auto* sourceEntity : sourceEntities) + { + if (sourceEntity->FindComponent()) + { + networkedEntityIds.push_back(sourceEntity->GetId()); + } + } + if (!PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefab)) + { + AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed."); + return; + } + + AZStd::unique_ptr networkInstance(aznew Instance()); + + for (auto entityId : networkedEntityIds) + { + AZ::Entity* netEntity = sourceInstance->DetachEntity(entityId).release(); + + networkInstance->AddEntity(*netEntity); + + AZ::Entity* breadcrumbEntity = aznew AZ::Entity(netEntity->GetName()); + breadcrumbEntity->SetRuntimeActiveByDefault(netEntity->IsRuntimeActiveByDefault()); + breadcrumbEntity->CreateComponent(); + AzFramework::TransformComponent* transformComponent = netEntity->FindComponent(); + breadcrumbEntity->CreateComponent(*transformComponent); + + // TODO: Add NetBindMarkerComponent here referring to the net entity + sourceInstance->AddEntity(*breadcrumbEntity); + } + + // Add net spawnable asset holder + { + AZ::Data::AssetId assetId = networkSpawnable->GetId(); + AZ::Data::Asset networkSpawnableAsset; + networkSpawnableAsset.Create(assetId); + + EntityOptionalReference containerEntityRef = sourceInstance->GetContainerEntity(); + if (containerEntityRef.has_value()) + { + auto* networkSpawnableHolderComponent = containerEntityRef.value().get().CreateComponent(); + networkSpawnableHolderComponent->SetNetworkSpawnableAsset(networkSpawnableAsset); + } + else + { + AZ::Entity* networkSpawnableHolderEntity = aznew AZ::Entity(uniqueName); + auto* networkSpawnableHolderComponent = networkSpawnableHolderEntity->CreateComponent(); + networkSpawnableHolderComponent->SetNetworkSpawnableAsset(networkSpawnableAsset); + sourceInstance->AddEntity(*networkSpawnableHolderEntity); + } + } + + // save the final result in the target Prefab DOM. + PrefabDom networkPrefab; + if (!PrefabDomUtils::StoreInstanceInPrefabDom(*networkInstance, networkPrefab)) + { + AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed."); + return; + } + + if (!PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefab)) + { + AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed."); + return; + } + + + bool result = SpawnableUtils::CreateSpawnable(*networkSpawnable, networkPrefab); + if (result) + { + AzFramework::Spawnable::EntityList& entities = networkSpawnable->GetEntities(); + for (auto it = entities.begin(); it != entities.end(); ++it) + { + (*it)->InvalidateDependencies(); + (*it)->EvaluateDependencies(); + } + context.GetProcessedObjects().push_back(AZStd::move(object)); + } + else + { + AZ_Error("Prefabs", false, "Failed to convert prefab '%.*s' to a spawnable.", AZ_STRING_ARG(prefabName)); + context.ErrorEncountered(); + } + } +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h new file mode 100644 index 0000000000..ea927a1453 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h @@ -0,0 +1,43 @@ +/* + * 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 AzToolsFramework::Prefab::PrefabConversionUtils +{ + class PrefabProcessorContext; +} + +namespace Multiplayer +{ + using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor; + using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext; + using AzToolsFramework::Prefab::PrefabDom; + + class NetworkPrefabProcessor : public PrefabProcessor + { + public: + AZ_CLASS_ALLOCATOR(NetworkPrefabProcessor, AZ::SystemAllocator, 0); + AZ_RTTI(NetworkPrefabProcessor, "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}", PrefabProcessor); + + ~NetworkPrefabProcessor() override = default; + + void Process(PrefabProcessorContext& context) override; + + static void Reflect(AZ::ReflectContext* context); + + protected: + static void ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab); + }; +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp new file mode 100644 index 0000000000..26592fb935 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp @@ -0,0 +1,42 @@ +/* + * 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 + +namespace Multiplayer +{ + void NetworkSpawnableHolderComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1) + ->Field("AssetRef", &NetworkSpawnableHolderComponent::m_networkSpawnableAsset); + } + } + + void NetworkSpawnableHolderComponent::Activate() + { + } + + void NetworkSpawnableHolderComponent::Deactivate() + { + } + + void NetworkSpawnableHolderComponent::SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset) + { + m_networkSpawnableAsset = networkSpawnableAsset; + } + +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h new file mode 100644 index 0000000000..81f0959c74 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h @@ -0,0 +1,44 @@ +/* +* 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 + +namespace Multiplayer +{ + //! @class NetworkSpawnableHolderComponent + //! @brief Component for holding a reference to the network spawnable to make sure it is loaded with the original one. + class NetworkSpawnableHolderComponent final : public AZ::Component + { + public: + AZ_COMPONENT(NetworkSpawnableHolderComponent, "{B0E3ADEE-FCB4-4A32-8D4F-6920F1CB08E4}"); + + static void Reflect(AZ::ReflectContext* context); + + NetworkSpawnableHolderComponent() = default; + ~NetworkSpawnableHolderComponent() override = default; + + //! AZ::Component overrides. + //! @{ + void Activate() override; + void Deactivate() override; + //! @} + + void SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset); + + private: + AZ::Data::Asset m_networkSpawnableAsset{ AZ::Data::AssetLoadBehavior::PreLoad }; + }; +} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index eea9379df9..9a7dd52cb8 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -60,6 +60,8 @@ set(FILES Source/NetworkEntity/NetworkEntityHandle.inl Source/NetworkEntity/NetworkEntityManager.cpp Source/NetworkEntity/NetworkEntityManager.h + Source/NetworkEntity/NetworkSpawnableLibrary.cpp + Source/NetworkEntity/NetworkSpawnableLibrary.h Source/NetworkEntity/NetworkEntityRpcMessage.cpp Source/NetworkEntity/NetworkEntityRpcMessage.h Source/NetworkEntity/NetworkEntityTracker.cpp @@ -81,6 +83,10 @@ set(FILES Source/NetworkTime/NetworkTime.h Source/NetworkTime/RewindableObject.h Source/NetworkTime/RewindableObject.inl + Source/Pipeline/NetBindMarkerComponent.cpp + Source/Pipeline/NetBindMarkerComponent.h + Source/Pipeline/NetworkSpawnableHolderComponent.cpp + Source/Pipeline/NetworkSpawnableHolderComponent.h Source/ReplicationWindows/IReplicationWindow.h Source/ReplicationWindows/ServerToClientReplicationWindow.cpp Source/ReplicationWindows/ServerToClientReplicationWindow.h diff --git a/Gems/Multiplayer/Code/multiplayer_tools_files.cmake b/Gems/Multiplayer/Code/multiplayer_tools_files.cmake new file mode 100644 index 0000000000..1be02fd999 --- /dev/null +++ b/Gems/Multiplayer/Code/multiplayer_tools_files.cmake @@ -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. +# + +set(FILES + Source/Multiplayer_precompiled.cpp + Source/Multiplayer_precompiled.h + Source/Pipeline/NetworkPrefabProcessor.cpp + Source/Pipeline/NetworkPrefabProcessor.h + Source/MultiplayerToolsModule.h + Source/MultiplayerToolsModule.cpp +) diff --git a/Gems/Multiplayer/Registry/prefab.tools.setreg b/Gems/Multiplayer/Registry/prefab.tools.setreg new file mode 100644 index 0000000000..4f20f88df9 --- /dev/null +++ b/Gems/Multiplayer/Registry/prefab.tools.setreg @@ -0,0 +1,26 @@ +{ + "Amazon": + { + "Tools": + { + "Prefab": + { + "Processing": + { + "Stack": + { + "GameObjectCreation": + [ + { "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover" }, + { "$type": "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}" }, + { + "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor", + "SerializationFormat": "Text" // Options are "Binary" (default) or "Text". Prefer "Binary" for performance. + } + ] + } + } + } + } + } +} \ No newline at end of file From ba04c7858fd7bc9f400f779859ec9e77ff41f5ac Mon Sep 17 00:00:00 2001 From: luissemp Date: Thu, 15 Apr 2021 16:01:36 -0700 Subject: [PATCH 013/277] Fixed ability to set Array as data input into function definition node, WIP --- .../View/Widgets/VariablePanel/SlotTypeSelectorWidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/SlotTypeSelectorWidget.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/SlotTypeSelectorWidget.cpp index 99bec928cc..d345778f71 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/SlotTypeSelectorWidget.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/SlotTypeSelectorWidget.cpp @@ -73,6 +73,8 @@ namespace ScriptCanvasEditor { ui->setupUi(this); + ui->variablePalette->SetActiveScene(scriptCanvasId); + ui->searchFilter->setClearButtonEnabled(true); QObject::connect(ui->searchFilter, &QLineEdit::textChanged, this, &SlotTypeSelectorWidget::OnQuickFilterChanged); QObject::connect(ui->slotName, &QLineEdit::returnPressed, this, &SlotTypeSelectorWidget::OnReturnPressed); From 62f67b16da0a5e0b3ba41ca9b46e73690a0cfbf5 Mon Sep 17 00:00:00 2001 From: scottr Date: Thu, 15 Apr 2021 16:12:12 -0700 Subject: [PATCH 014/277] [cpack_installer] wrapped stray PrefabBuilder.Tests around PAL_TRAIT_BUILD_TESTS_SUPPORTED --- Gems/Prefab/PrefabBuilder/CMakeLists.txt | 36 +++++++++++++----------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Gems/Prefab/PrefabBuilder/CMakeLists.txt b/Gems/Prefab/PrefabBuilder/CMakeLists.txt index 5ab614eecb..22b89287ca 100644 --- a/Gems/Prefab/PrefabBuilder/CMakeLists.txt +++ b/Gems/Prefab/PrefabBuilder/CMakeLists.txt @@ -38,23 +38,6 @@ ly_add_target( Gem::PrefabBuilder.Static ) -ly_add_target( - NAME PrefabBuilder.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} - NAMESPACE Gem - FILES_CMAKE - prefabbuilder_tests_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - . - BUILD_DEPENDENCIES - PRIVATE - AZ::AzTest - Gem::PrefabBuilder.Static -) -ly_add_googletest( - NAME Gem::PrefabBuilder.Tests -) - ly_add_target_dependencies( TARGETS AssetBuilder @@ -63,3 +46,22 @@ ly_add_target_dependencies( DEPENDENT_TARGETS Gem::PrefabBuilder ) + +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) + ly_add_target( + NAME PrefabBuilder.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE Gem + FILES_CMAKE + prefabbuilder_tests_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + . + BUILD_DEPENDENCIES + PRIVATE + AZ::AzTest + Gem::PrefabBuilder.Static + ) + ly_add_googletest( + NAME Gem::PrefabBuilder.Tests + ) +endif() From 4962218d2932517b23a72beff1e4e2bce8e2f0cc Mon Sep 17 00:00:00 2001 From: pereslav Date: Fri, 16 Apr 2021 00:19:43 +0100 Subject: [PATCH 015/277] Refactored root spawnable instantiation, added selective instantiation of root spawnable entities --- .../Serialization/ISerializer.inl | 4 +- .../Code/Source/MultiplayerGem.cpp | 2 +- .../Code/Source/MultiplayerToolsModule.cpp | 8 +- .../Code/Source/MultiplayerTypes.h | 15 +- .../EntityReplicationManager.cpp | 12 +- .../NetworkEntity/INetworkEntityManager.h | 3 +- .../NetworkEntity/NetworkEntityManager.cpp | 133 +++++++++++++----- .../NetworkEntity/NetworkEntityManager.h | 17 +-- .../Pipeline/NetworkPrefabProcessor.cpp | 3 +- .../NetworkSpawnableHolderComponent.cpp | 9 ++ .../NetworkSpawnableHolderComponent.h | 3 +- 11 files changed, 134 insertions(+), 75 deletions(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl b/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl index 2720f09f4b..df3b08f798 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl @@ -18,8 +18,8 @@ #include #include #include -#include "AzCore/Name/Name.h" -#include "AzCore/Name/NameDictionary.h" +#include +#include namespace AzNetworking { diff --git a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp index 15d4e2f6f0..596a1b40fa 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp @@ -15,9 +15,9 @@ #include #include #include -#include #include #include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp index 16f13f9ee8..71b04585ad 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp @@ -12,13 +12,13 @@ #include #include -#include "Pipeline/NetworkPrefabProcessor.h" -#include "AzCore/Serialization/Json/RegistrationContext.h" -#include "Prefab/Instance/InstanceSerializer.h" +#include +#include +#include namespace Multiplayer { - //! Multiplayer system component wraps the bridging logic between the game and transport layer. + //! Multiplayer Tools system component provides serialize context reflection for tools-only systems. class MultiplayerToolsSystemComponent final : public AZ::Component { diff --git a/Gems/Multiplayer/Code/Source/MultiplayerTypes.h b/Gems/Multiplayer/Code/Source/MultiplayerTypes.h index ad491f4016..7ffaa8a56e 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerTypes.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerTypes.h @@ -13,11 +13,11 @@ #pragma once #include +#include #include #include #include #include -#include namespace Multiplayer { @@ -70,19 +70,6 @@ namespace Multiplayer True }; - template - bool Serialize(TYPE& value, const char* name); - - inline NetEntityId MakeEntityId(uint8_t a_ServerId, int32_t a_NextId) - { - constexpr int32_t MAX_ENTITYID = 0x00FFFFFF; - - AZ_Assert((a_NextId < MAX_ENTITYID) && (a_NextId > 0), "Requested Id out of range"); - - NetEntityId ret = NetEntityId(((static_cast(a_ServerId) << 24) & 0xFF000000) | (a_NextId & MAX_ENTITYID)); - return ret; - } - // This is just a placeholder // The level/prefab cooking will devise the actual solution for identifying a dynamically spawnable entity within a prefab struct PrefabEntityId diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index e19bc7685b..3295f9e45e 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace Multiplayer { @@ -532,7 +533,7 @@ namespace Multiplayer NetEntityId netEntityId, NetEntityRole localNetworkRole, AzNetworking::ISerializer& serializer, - [[maybe_unused]] const PrefabEntityId& prefabEntityId + const PrefabEntityId& prefabEntityId ) { ConstNetworkEntityHandle replicatorEntity = GetNetworkEntityManager()->GetEntity(netEntityId); @@ -544,6 +545,15 @@ namespace Multiplayer if (createEntity) { //replicatorEntity = GetNetworkEntityManager()->CreateSingleEntityImmediateInternal(prefabEntityId, EntitySpawnType::Replicate, AutoActivate::DoNotActivate, netEntityId, localNetworkRole, AZ::Transform::Identity()); + INetworkEntityManager::EntityList entityList = GetNetworkEntityManager()->CreateEntitiesImmediate( + prefabEntityId, netEntityId, localNetworkRole, + AZ::Transform::Identity()); + + if (entityList.size() == 1) + { + replicatorEntity = entityList[0]; + } + AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab %s", prefabEntityId.m_prefabName.GetCStr()); if (replicatorEntity == nullptr) { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h index be4f32752d..557a912a31 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h @@ -54,7 +54,8 @@ namespace Multiplayer //! Creates new entities of the given archetype //! @param prefabEntryId the name of the spawnable to spawn - virtual void CreateEntitiesImmediate(const PrefabEntityId& prefabEntryId) = 0; + virtual EntityList CreateEntitiesImmediate( + const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole, const AZ::Transform& transform) = 0; //! Returns an ConstEntityPtr for the provided entityId. //! @param netEntityId the netEntityId to get an ConstEntityPtr for diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index d92becfb97..80ad654cae 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include namespace Multiplayer { @@ -32,7 +35,6 @@ namespace Multiplayer , m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event")) , m_entityAddedEventHandler([this](AZ::Entity* entity) { OnEntityAdded(entity); }) , m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); }) - , m_rootSpawnableMonitor(*this) { AZ::Interface::Register(this); AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); @@ -284,8 +286,8 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { - const NetEntityId netEntityId = NextId(); - netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority); + //const NetEntityId netEntityId = NextId(); + //netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority); } } @@ -337,7 +339,8 @@ namespace Multiplayer } } - INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable) + INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate( + const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole) { INetworkEntityManager::EntityList returnList; @@ -361,7 +364,7 @@ namespace Multiplayer prefabEntityId.m_entityOffset = aznumeric_cast(i); const NetEntityId netEntityId = NextId(); - netBindComponent->PreInit(clone, prefabEntityId, netEntityId, NetEntityRole::Authority); + netBindComponent->PreInit(clone, prefabEntityId, netEntityId, netEntityRole); AzFramework::GameEntityContextRequestBus::Broadcast( &AzFramework::GameEntityContextRequestBus::Events::AddGameEntity, clone); @@ -378,8 +381,62 @@ namespace Multiplayer return returnList; } - void NetworkEntityManager::CreateEntitiesImmediate([[maybe_unused]] const PrefabEntityId& a_SliceEntryId) + INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate( + const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole, + const AZ::Transform& transform) { + INetworkEntityManager::EntityList returnList; + + // TODO: Implement for non-root spawnables + auto spawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(prefabEntryId.m_prefabName); + if (spawnableAssetId == m_rootSpawnableAsset.GetId()) + { + AzFramework::Spawnable* netSpawnable = m_rootSpawnableAsset.GetAs(); + if (!netSpawnable) + { + return returnList; + } + + const uint32_t entityIndex = prefabEntryId.m_entityOffset; + + if (entityIndex == PrefabEntityId::AllIndices) + { + return CreateEntitiesImmediate(*netSpawnable, netEntityRole); + } + + const AzFramework::Spawnable::EntityList& entities = netSpawnable->GetEntities(); + size_t entitiesSize = entities.size(); + if (entityIndex >= entitiesSize) + { + return returnList; + } + + AZ::SerializeContext* serializeContext = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + + AZ::Entity* clone = serializeContext->CloneObject(entities[entityIndex].get()); + AZ_Assert(clone != nullptr, "Failed to clone spawnable entity."); + clone->SetId(AZ::Entity::MakeId()); + + NetBindComponent* netBindComponent = clone->FindComponent(); + if (netBindComponent) + { + netBindComponent->PreInit(clone, prefabEntryId, netEntityId, netEntityRole); + + auto* transformComponent = clone->FindComponent(); + if (transformComponent) + { + transformComponent->SetWorldTM(transform); + } + + AzFramework::GameEntityContextRequestBus::Broadcast( + &AzFramework::GameEntityContextRequestBus::Events::AddGameEntity, clone); + + returnList.push_back(netBindComponent->GetEntityHandle()); + } + } + + return returnList; } Multiplayer::NetEntityId NetworkEntityManager::NextId() @@ -389,55 +446,57 @@ namespace Multiplayer } void NetworkEntityManager::OnRootSpawnableAssigned( - [[maybe_unused]] AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) + AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) { - AZStd::string hint = rootSpawnable.GetHint(); - - size_t extensionPos = hint.find(".spawnable"); - if (extensionPos == AZStd::string::npos) + AzFramework::Spawnable* rootSpawnableData = rootSpawnable.GetAs(); + const auto& entityList = rootSpawnableData->GetEntities(); + if (entityList.size() == 0) { - AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root spawnable hint doesn't have .spawnable extension"); + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root spawnable doesn't have any entities."); return; } - AZStd::string newhint = hint.replace(extensionPos, 0, ".network"); - auto rootSpawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(AZ::Name(newhint)); - if (!rootSpawnableAssetId.IsValid()) + const auto& rootEntity = entityList[0]; + auto* spawnableHolder = rootEntity->FindComponent(); + if (!spawnableHolder) { - AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Network spawnable asset ID is invalid"); + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root entity doesn't have NetworkSpawnableHolderComponent."); return; } - m_rootSpawnableAsset = AZ::Data::Asset( - rootSpawnableAssetId, azrtti_typeid(), newhint); - if (m_rootSpawnableAsset.QueueLoad()) + AZ::Data::Asset netSpawnableAsset = spawnableHolder->GetNetworkSpawnableAsset(); + AzFramework::Spawnable* netSpawnable = netSpawnableAsset.GetAs(); + if (!netSpawnable) { - m_rootSpawnableMonitor.Connect(rootSpawnableAssetId); + // TODO: Temp sync load until JsonSerialization of loadBehavior is fixed. + netSpawnableAsset = AZ::Data::AssetManager::Instance().GetAsset( + netSpawnableAsset.GetId(), AZ::Data::AssetLoadBehavior::PreLoad); + AZ::Data::AssetManager::Instance().BlockUntilLoadComplete(netSpawnableAsset); + + netSpawnable = netSpawnableAsset.GetAs(); } - else + + if (!netSpawnable) { - AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Unable to queue networked root spawnable '%s' for loading.", - m_rootSpawnableAsset.GetHint().c_str()); + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Net spawnable doesn't have any data."); + return; } - } - void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) - { - m_rootSpawnableMonitor.Disconnect(); - } + m_rootSpawnableAsset = netSpawnableAsset; + const auto agentType = AZ::Interface::Get()->GetAgentType(); + const bool spawnImmediately = + (agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer); - NetworkEntityManager::NetworkSpawnableMonitor::NetworkSpawnableMonitor( - NetworkEntityManager& entityManager) - : m_entityManager(entityManager) - { + if (spawnImmediately) + { + CreateEntitiesImmediate(*netSpawnable, NetEntityRole::Authority); + } } - void NetworkEntityManager::NetworkSpawnableMonitor::OnAssetReady(AZ::Data::Asset asset) + void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) { - AzFramework::Spawnable* spawnable = asset.GetAs(); - AZ_Assert(spawnable, "NetworkSpawnableMonitor: Loaded asset data didn't contain a Spawanble."); - - m_entityManager.CreateEntitiesImmediate(*spawnable); + // TODO: Do we need to clear all entities here? + m_rootSpawnableAsset.Release(); } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index 20c67a74fd..d9d21d6b7b 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -46,9 +45,11 @@ namespace Multiplayer HostId GetHostId() const override; ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const override; - EntityList CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable); + EntityList CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole); - void CreateEntitiesImmediate(const PrefabEntityId& a_SliceEntryId) override; + EntityList CreateEntitiesImmediate( + const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole, + const AZ::Transform& transform) override; uint32_t GetEntityCount() const override; NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) override; @@ -78,15 +79,6 @@ namespace Multiplayer //! @} private: - class NetworkSpawnableMonitor final : public AzFramework::SpawnableMonitor - { - public: - explicit NetworkSpawnableMonitor(NetworkEntityManager& entityManager); - void OnAssetReady(AZ::Data::Asset asset) override; - - NetworkEntityManager& m_entityManager; - }; - void OnEntityAdded(AZ::Entity* entity); void OnEntityRemoved(AZ::Entity* entity); void RemoveEntities(); @@ -120,7 +112,6 @@ namespace Multiplayer DeferredRpcMessages m_localDeferredRpcMessages; NetworkSpawnableLibrary m_networkPrefabLibrary; - NetworkSpawnableMonitor m_rootSpawnableMonitor; AZ::Data::Asset m_rootSpawnableAsset; }; } diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp index 0995ec29d8..2006272135 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -124,7 +124,7 @@ namespace Multiplayer AzFramework::TransformComponent* transformComponent = netEntity->FindComponent(); breadcrumbEntity->CreateComponent(*transformComponent); - // TODO: Add NetBindMarkerComponent here referring to the net entity + // TODO: Configure NetBindMarkerComponent to refer to the net entity sourceInstance->AddEntity(*breadcrumbEntity); } @@ -133,6 +133,7 @@ namespace Multiplayer AZ::Data::AssetId assetId = networkSpawnable->GetId(); AZ::Data::Asset networkSpawnableAsset; networkSpawnableAsset.Create(assetId); + networkSpawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad); EntityOptionalReference containerEntityRef = sourceInstance->GetContainerEntity(); if (containerEntityRef.has_value()) diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp index 26592fb935..3c3d1f079d 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp @@ -39,4 +39,13 @@ namespace Multiplayer m_networkSpawnableAsset = networkSpawnableAsset; } + AZ::Data::Asset NetworkSpawnableHolderComponent::GetNetworkSpawnableAsset() + { + return m_networkSpawnableAsset; + } + + NetworkSpawnableHolderComponent::NetworkSpawnableHolderComponent() + { + } + } diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h index 81f0959c74..54a9a4e42f 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h @@ -27,7 +27,7 @@ namespace Multiplayer static void Reflect(AZ::ReflectContext* context); - NetworkSpawnableHolderComponent() = default; + NetworkSpawnableHolderComponent();; ~NetworkSpawnableHolderComponent() override = default; //! AZ::Component overrides. @@ -37,6 +37,7 @@ namespace Multiplayer //! @} void SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset); + AZ::Data::Asset GetNetworkSpawnableAsset(); private: AZ::Data::Asset m_networkSpawnableAsset{ AZ::Data::AssetLoadBehavior::PreLoad }; From 778d60bd0c47ad25e43b166928dfa64e54202167 Mon Sep 17 00:00:00 2001 From: srikappa Date: Thu, 15 Apr 2021 18:45:48 -0700 Subject: [PATCH 016/277] Replaced unique instance queue with checks in template to instance mapper --- .../Instance/InstanceUpdateExecutor.cpp | 54 ++++--------------- .../Prefab/Instance/InstanceUpdateExecutor.h | 14 ----- .../Prefab/PrefabPublicHandler.cpp | 2 +- .../Prefab/PrefabSystemComponent.cpp | 5 +- 4 files changed, 14 insertions(+), 61 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.cpp index 7df1602bff..d84edd6212 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.cpp @@ -123,6 +123,15 @@ namespace AzToolsFramework } } + auto findInstancesResult = m_templateInstanceMapperInterface->FindInstancesOwnedByTemplate(instanceTemplateId)->get(); + + if (findInstancesResult.find(instanceToUpdate) == findInstancesResult.end()) + { + isUpdateSuccessful = false; + m_instancesUpdateQueue.pop(); + continue; + } + Template& currentTemplate = currentTemplateReference->get(); Instance::EntityList newEntities; if (PrefabDomUtils::LoadInstanceFromPrefabDom(*instanceToUpdate, newEntities, currentTemplate.GetPrefabDom())) @@ -173,50 +182,5 @@ namespace AzToolsFramework return isUpdateSuccessful; } - - Instance* InstanceUpdateExecutor::UniqueInstanceQueue::front() - { - return m_instancesQueue.front(); - } - - void InstanceUpdateExecutor::UniqueInstanceQueue::pop() - { - m_instancesSet.erase(m_instancesQueue.front()); - m_instancesQueue.pop(); - } - - void InstanceUpdateExecutor::UniqueInstanceQueue::emplace(Instance* instance) - { - Instance* ancestorInstance = instance; - - while (ancestorInstance != nullptr) - { - if (m_instancesSet.contains(ancestorInstance)) - { - return; - } - - auto parent = ancestorInstance->GetParentInstance(); - if (parent.has_value()) - { - ancestorInstance = &(parent->get()); - } - else - { - ancestorInstance = nullptr; - } - } - - // TODO - remove child instances too? - // Optimization. - - m_instancesQueue.emplace(instance); - m_instancesSet.emplace(instance); - } - - size_t InstanceUpdateExecutor::UniqueInstanceQueue::size() - { - return m_instancesQueue.size(); - } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.h index a29e19dc8a..04bd189816 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceUpdateExecutor.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -46,19 +45,6 @@ namespace AzToolsFramework PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr; TemplateInstanceMapperInterface* m_templateInstanceMapperInterface = nullptr; int m_instanceCountToUpdateInBatch = 0; - - class UniqueInstanceQueue - { - public: - Instance* front(); - void pop(); - void emplace(Instance* instance); - size_t size(); - private: - AZStd::queue m_instancesQueue; - AZStd::unordered_set m_instancesSet; - }; - //UniqueInstanceQueue m_instancesUpdateQueue; AZStd::queue m_instancesUpdateQueue; bool m_updatingTemplateInstancesInQueue { false }; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 292ee3c7f8..b97e9ebd98 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -334,7 +334,7 @@ namespace AzToolsFramework // Create Undo node on entities if they belong to an instance InstanceOptionalReference instanceOptionalReference = m_instanceEntityMapperInterface->FindOwningInstance(entityId); - if (instanceOptionalReference.has_value() && !IsInstanceContainerEntity(entityId)) + if (instanceOptionalReference.has_value()) { PrefabDom afterState; AZ::Entity* entity = GetEntityById(entityId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 37620ed9ec..7a9ec0a62e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -144,7 +144,6 @@ namespace AzToolsFramework void PrefabSystemComponent::PropagateTemplateChanges(TemplateId templateId) { - UpdatePrefabInstances(templateId); auto templateIdToLinkIdsIterator = m_templateToLinkIdsMap.find(templateId); if (templateIdToLinkIdsIterator != m_templateToLinkIdsMap.end()) { @@ -155,6 +154,10 @@ namespace AzToolsFramework templateIdToLinkIdsIterator->second.end())); UpdateLinkedInstances(linkIdsToUpdateQueue); } + else + { + UpdatePrefabInstances(templateId); + } } void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) From 23c9f7ab78fd4e075d0b1772f02d81c370da0274 Mon Sep 17 00:00:00 2001 From: scottr Date: Fri, 16 Apr 2021 10:18:36 -0700 Subject: [PATCH 017/277] [cpack_installer] initial CPack IFW support --- CMakeLists.txt | 7 +++++-- cmake/CPack.cmake | 33 +++++++++++++++++++++++++++++++++ cmake/cmake_files.cmake | 1 + 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 cmake/CPack.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c09cfc9588..2e0af34c08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,7 +125,10 @@ endif() include(cmake/RuntimeDependencies.cmake) # 5. Perform test impact framework post steps once all of the targets have been enumerated ly_test_impact_post_step() -# 6. Generate the O3DE find file and setup install locations for scripts, tools, assets etc., required by the engine +# 6. Generate the O3DE find file and setup install locations for scripts, tools, assets etc., required by the engine if(NOT INSTALLED_ENGINE) ly_setup_o3de_install() -endif() \ No newline at end of file +endif() + +# IMPORTANT: must be included last +include(cmake/CPack.cmake) \ No newline at end of file diff --git a/cmake/CPack.cmake b/cmake/CPack.cmake new file mode 100644 index 0000000000..46cd044ced --- /dev/null +++ b/cmake/CPack.cmake @@ -0,0 +1,33 @@ +# +# 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. +# + +set(CPACK_GENERATOR "IFW") + +set(CPACK_PACKAGE_VENDOR "O3DE") +set(CPACK_PACKAGE_VERSION "1.0.0") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Installation Tool") + +set(CPACK_PACKAGE_FILE_NAME "o3de_installer") + +set(DEFAULT_LICENSE_NAME "Apache 2.0") +set(DEFAULT_LICENSE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt) + +set(CPACK_RESOURCE_FILE_LICENSE ${DEFAULT_LICENSE_FILE}) + +set(CPACK_IFW_PACKAGE_TITLE "O3DE Installer") +set(CPACK_IFW_PACKAGE_PUBLISHER "O3DE") + +set(CPACK_IFW_TARGET_DIRECTORY "@ApplicationsDir@/O3DE/${LY_VERSION_STRING}") +set(CPACK_IFW_PACKAGE_START_MENU_DIRECTORY "O3DE") + +# IMPORTANT: required to be included AFTER setting all property overrides +include(CPack REQUIRED) +include(CPackIFW REQUIRED) \ No newline at end of file diff --git a/cmake/cmake_files.cmake b/cmake/cmake_files.cmake index 2b0f65ca99..18efa314d5 100644 --- a/cmake/cmake_files.cmake +++ b/cmake/cmake_files.cmake @@ -14,6 +14,7 @@ set(FILES 3rdPartyPackages.cmake CommandExecution.cmake Configurations.cmake + CPack.cmake Dependencies.cmake Deployment.cmake EngineFinder.cmake From 40aef17b5545b7dc5a223b3e2d263ae5e8f8152d Mon Sep 17 00:00:00 2001 From: scottr Date: Fri, 16 Apr 2021 10:22:39 -0700 Subject: [PATCH 018/277] [cpack_installer] added option to override the inclusion of test targets in build --- cmake/PAL.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/PAL.cmake b/cmake/PAL.cmake index 734baad8a3..5131005c72 100644 --- a/cmake/PAL.cmake +++ b/cmake/PAL.cmake @@ -85,3 +85,9 @@ ly_include_cmake_file_list(${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_fi include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) include(${pal_dir}/Toolchain_${PAL_PLATFORM_NAME_LOWERCASE}.cmake OPTIONAL) + +set(LY_DISABLE_TEST_MODULES FALSE CACHE BOOL "Option to forcibly disable the inclusion of test targets in the build") + +if(LY_DISABLE_TEST_MODULES) + ly_set(PAL_TRAIT_BUILD_TESTS_SUPPORTED FALSE) +endif() From 808fd1d3ba2843a2e0e19205726f4ca957e5fcd8 Mon Sep 17 00:00:00 2001 From: moraaar Date: Fri, 16 Apr 2021 18:24:29 +0100 Subject: [PATCH 019/277] Cloth works with Actors in Atom. Cloth system uses MeshAssetHelper to read model mesh information for actors too. --- .../Code/Source/AtomActorInstance.cpp | 48 +++++++------------ .../Code/Source/AtomActorInstance.h | 9 ---- .../ClothComponentMesh/ClothComponentMesh.cpp | 15 ++++-- .../NvCloth/Code/Source/Utils/AssetHelper.cpp | 26 ++-------- .../Code/Source/Utils/MeshAssetHelper.cpp | 6 +++ .../Code/Source/Utils/MeshAssetHelper.h | 4 +- 6 files changed, 41 insertions(+), 67 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 0a17a6444d..cd5f3bb6c5 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -212,19 +212,26 @@ namespace AZ void AtomActorInstance::SetModelAsset([[maybe_unused]] Data::Asset modelAsset) { - // Atom Actor Instance is not based on an actual Model Asset yet, - // it's created at runtime from an Actor Asset. + // Changing model asset is not supported by Atom Actor Instance. + // The model asset is obtained from the Actor inside the ActorAsset, + // which is passed to the constructor. To set a different model asset + // this instance should use a different Actor. + AZ_Assert(false, "AtomActorInstance::SetModelAsset not supported"); } const Data::Asset& AtomActorInstance::GetModelAsset() const { - return m_skinnedMeshInstance->m_model->GetModelAsset(); + AZ_Assert(GetActor(), "Expecting a Atom Actor Instance having a valid Actor."); + return GetActor()->GetMeshAsset(); } void AtomActorInstance::SetModelAssetId([[maybe_unused]] Data::AssetId modelAssetId) { - // Atom Actor Instance is not based on an actual Model Asset yet, - // it's created at runtime from an Actor Asset. + // Changing model asset is not supported by Atom Actor Instance. + // The model asset is obtained from the Actor inside the ActorAsset, + // which is passed to the constructor. To set a different model asset + // this instance should use a different Actor. + AZ_Assert(false, "AtomActorInstance::SetModelAssetId not supported"); } Data::AssetId AtomActorInstance::GetModelAssetId() const @@ -234,8 +241,11 @@ namespace AZ void AtomActorInstance::SetModelAssetPath([[maybe_unused]] const AZStd::string& modelAssetPath) { - // Atom Actor Instance is not based on an actual Model Asset yet, - // it's created at runtime from an Actor Asset. + // Changing model asset is not supported by Atom Actor Instance. + // The model asset is obtained from the Actor inside the ActorAsset, + // which is passed to the constructor. To set a different model asset + // this instance should use a different Actor. + AZ_Assert(false, "AtomActorInstance::SetModelAssetPath not supported"); } AZStd::string AtomActorInstance::GetModelAssetPath() const @@ -278,28 +288,6 @@ namespace AZ return IsVisible(); } - void AtomActorInstance::SetMeshAsset(const AZ::Data::AssetId& id) - { - AZ::Data::Asset asset = - AZ::Data::AssetManager::Instance().GetAsset( - id, m_actorAsset.GetAutoLoadBehavior()); - if (asset) - { - m_actorAsset = asset; - Create(); - } - } - - AZ::Data::Asset AtomActorInstance::GetMeshAsset() - { - return m_actorAsset; - } - - bool AtomActorInstance::GetVisibility() - { - return static_cast(*this).GetVisibility(); - } - AZ::u32 AtomActorInstance::GetJointCount() { return m_actorInstance->GetActor()->GetSkeleton()->GetNumNodes(); @@ -469,7 +457,6 @@ namespace AZ TransformNotificationBus::Handler::BusConnect(m_entityId); MaterialComponentNotificationBus::Handler::BusConnect(m_entityId); MeshComponentRequestBus::Handler::BusConnect(m_entityId); - LmbrCentral::MeshComponentRequestBus::Handler::BusConnect(m_entityId); const Data::Instance model = m_meshFeatureProcessor->GetModel(*m_meshHandle); MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, model->GetModelAsset(), model); @@ -479,7 +466,6 @@ namespace AZ { MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelPreDestroy); - LmbrCentral::MeshComponentRequestBus::Handler::BusDisconnect(); MeshComponentRequestBus::Handler::BusDisconnect(); MaterialComponentNotificationBus::Handler::BusDisconnect(); TransformNotificationBus::Handler::BusDisconnect(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h index e14a0a7c4f..a2cf042efa 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h @@ -62,7 +62,6 @@ namespace AZ , public AzFramework::BoundsRequestBus::Handler , public AZ::Render::MaterialComponentNotificationBus::Handler , public AZ::Render::MeshComponentRequestBus::Handler - , public LmbrCentral::MeshComponentRequestBus::Handler , private AZ::Render::SkinnedMeshFeatureProcessorNotificationBus::Handler , private AZ::Render::SkinnedMeshOutputStreamNotificationBus::Handler , private LmbrCentral::SkeletalHierarchyRequestBus::Handler @@ -143,14 +142,6 @@ namespace AZ bool GetVisibility() const override; // GetWorldBounds/GetLocalBounds already overridden by BoundsRequestBus::Handler - ////////////////////////////////////////////////////////////////////////// - // LmbrCentral::MeshComponentRequestBus::Handler - void SetMeshAsset(const AZ::Data::AssetId& id) override; - AZ::Data::Asset GetMeshAsset() override; - bool GetVisibility() override; - // SetVisibility already overridden by MeshComponentRequestBus::Handler - // GetWorldBounds/GetLocalBounds already overridden by BoundsRequestBus::Handler - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SkeletalHierarchyRequestBus::Handler overrides... AZ::u32 GetJointCount() override; diff --git a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp index cf2593048f..92dbfdb89a 100644 --- a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp +++ b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp @@ -448,9 +448,18 @@ namespace NvCloth const auto& renderTangents = renderData.m_tangents; const auto& renderBitangents = renderData.m_bitangents; - AZ::Data::Asset modelAsset; - AZ::Render::MeshComponentRequestBus::EventResult( - modelAsset, m_entityId, &AZ::Render::MeshComponentRequestBus::Events::GetModelAsset); + // Since Atom has a 1:1 relation with between ModelAsset buffers and Model buffers, + // internally it created a new asset for the model instance. So it's important to + // get the asset from the model when we want to write to them, instead of getting the + // ModelAsset directly from the bus (which returns the original asset shared by all entities). + AZ::Data::Instance model; + AZ::Render::MeshComponentRequestBus::EventResult(model, m_entityId, &AZ::Render::MeshComponentRequestBus::Events::GetModel); + if (!model) + { + return; + } + + AZ::Data::Asset modelAsset = model->GetModelAsset(); if (!modelAsset.IsReady()) { return; diff --git a/Gems/NvCloth/Code/Source/Utils/AssetHelper.cpp b/Gems/NvCloth/Code/Source/Utils/AssetHelper.cpp index cb4d644065..c7558580b3 100644 --- a/Gems/NvCloth/Code/Source/Utils/AssetHelper.cpp +++ b/Gems/NvCloth/Code/Source/Utils/AssetHelper.cpp @@ -13,11 +13,7 @@ #include #include -#include -#include - -#include namespace NvCloth { @@ -30,25 +26,9 @@ namespace NvCloth AZStd::unique_ptr AssetHelper::CreateAssetHelper(AZ::EntityId entityId) { - // Does the entity have an Actor Asset? - EMotionFX::ActorInstance* actorInstance = nullptr; - EMotionFX::Integration::ActorComponentRequestBus::EventResult( - actorInstance, entityId, &EMotionFX::Integration::ActorComponentRequestBus::Events::GetActorInstance); - if (actorInstance) - { - return AZStd::make_unique(entityId); - } - - AZ::Data::Asset modelAsset; - AZ::Render::MeshComponentRequestBus::EventResult( - modelAsset, entityId, &AZ::Render::MeshComponentRequestBus::Events::GetModelAsset); - if (modelAsset.GetId().IsValid()) - { - return AZStd::make_unique(entityId); - } - - AZ_Warning("AssetHelper", false, "Unexpected asset type"); - return nullptr; + return entityId.IsValid() + ? AZStd::make_unique(entityId) + : nullptr; } float AssetHelper::ConvertBackstopOffset(float backstopOffset) diff --git a/Gems/NvCloth/Code/Source/Utils/MeshAssetHelper.cpp b/Gems/NvCloth/Code/Source/Utils/MeshAssetHelper.cpp index fa8d6e5455..6852d245d2 100644 --- a/Gems/NvCloth/Code/Source/Utils/MeshAssetHelper.cpp +++ b/Gems/NvCloth/Code/Source/Utils/MeshAssetHelper.cpp @@ -14,11 +14,17 @@ #include +#include + namespace NvCloth { MeshAssetHelper::MeshAssetHelper(AZ::EntityId entityId) : AssetHelper(entityId) { + EMotionFX::ActorInstance* actorInstance = nullptr; + EMotionFX::Integration::ActorComponentRequestBus::EventResult( + actorInstance, entityId, &EMotionFX::Integration::ActorComponentRequestBus::Events::GetActorInstance); + m_supportSkinnedAnimation = actorInstance != nullptr; } void MeshAssetHelper::GatherClothMeshNodes(MeshNodeList& meshNodes) diff --git a/Gems/NvCloth/Code/Source/Utils/MeshAssetHelper.h b/Gems/NvCloth/Code/Source/Utils/MeshAssetHelper.h index b558519bd4..a7849583e7 100644 --- a/Gems/NvCloth/Code/Source/Utils/MeshAssetHelper.h +++ b/Gems/NvCloth/Code/Source/Utils/MeshAssetHelper.h @@ -35,12 +35,14 @@ namespace NvCloth MeshClothInfo& meshClothInfo) override; bool DoesSupportSkinnedAnimation() const override { - return false; + return m_supportSkinnedAnimation; } private: bool CopyDataFromMeshes( const AZStd::vector& meshes, MeshClothInfo& meshClothInfo); + + bool m_supportSkinnedAnimation = false; }; } // namespace NvCloth From 9e6a5ecbaf3e8619bffd11f2d4944145a42560cf Mon Sep 17 00:00:00 2001 From: moraaar Date: Fri, 16 Apr 2021 18:25:24 +0100 Subject: [PATCH 020/277] Fix cloth chicken actor asset in NvCloth gem. --- .../cloth/Chicken/Actor/chicken.fbx.assetinfo | 534 ++++++------------ 1 file changed, 172 insertions(+), 362 deletions(-) diff --git a/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken.fbx.assetinfo b/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken.fbx.assetinfo index 808b024189..a6024e0c5f 100644 --- a/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken.fbx.assetinfo +++ b/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken.fbx.assetinfo @@ -1,362 +1,172 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +{ + "values": [ + { + "$type": "ActorGroup", + "name": "chicken", + "id": "{C086F309-EE7E-5AFD-A9C2-69DE5BA48461}", + "rules": { + "rules": [ + { + "$type": "MetaDataRule", + "metaData": "AdjustActor -actorID $(ACTORID) -name \"chicken\"\r\nActorSetCollisionMeshes -actorID $(ACTORID) -lod 0 -nodeList \"\"\r\nAdjustActor -actorID $(ACTORID) -nodesExcludedFromBounds \"\" -nodeAction \"select\"\r\nAdjustActor -actorID $(ACTORID) -nodeAction \"replace\" -attachmentNodes \"\"\r\n" + }, + { + "$type": "ActorPhysicsSetupRule", + "data": { + "config": { + "clothConfig": { + "nodes": [ + { + "name": "def_c_head_joint", + "shapes": [ + [ + { + "Visible": true, + "Position": [ + -0.08505599945783615, + 0.0, + 0.009370899759232998 + ], + "Rotation": [ + 0.7071437239646912, + 0.0, + 0.0, + 0.708984375 + ], + "propertyVisibilityFlags": 248 + }, + { + "$type": "CapsuleShapeConfiguration", + "Height": 0.191273495554924, + "Radius": 0.05063670128583908 + } + ] + ] + }, + { + "name": "def_c_neck_joint", + "shapes": [ + [ + { + "Visible": true, + "Position": [ + -0.03810190036892891, + 0.0, + -0.03132440149784088 + ], + "propertyVisibilityFlags": 248 + }, + { + "$type": "SphereShapeConfiguration", + "Radius": 0.16069939732551576 + } + ] + ] + }, + { + "name": "def_c_spine_end", + "shapes": [ + [ + { + "Visible": true, + "Position": [ + -2.0000000233721949e-7, + 0.012646200135350228, + -0.24104370176792146 + ], + "propertyVisibilityFlags": 248 + }, + { + "$type": "SphereShapeConfiguration", + "Radius": 0.24875959753990174 + } + ] + ] + } + ] + } + } + } + }, + { + "$type": "CoordinateSystemRule" + } + ] + } + }, + { + "$type": "{07B356B7-3635-40B5-878A-FAC4EFD5AD86} MeshGroup", + "name": "chicken", + "nodeSelectionList": { + "selectedNodes": [ + {}, + "RootNode", + "RootNode.chicken_skeleton", + "RootNode.chicken_feet_skin", + "RootNode.chicken_eyes_skin", + "RootNode.chicken_body_skin", + "RootNode.chicken_mohawk", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.def_l_lwrLeg_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.def_r_lwrLeg_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_l_wing1_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_r_wing1_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.def_l_lwrLeg_joint.def_l_foot_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.def_r_lwrLeg_joint.def_r_foot_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_tail1_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_l_wing1_joint.def_l_wing2_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_r_wing1_joint.def_r_wing2_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_l_uprLeg_joint.def_l_lwrLeg_joint.def_l_foot_joint.def_l_ball_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_r_uprLeg_joint.def_r_lwrLeg_joint.def_r_foot_joint.def_r_ball_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_tail1_joint.def_c_tail2_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_l_wing1_joint.def_l_wing2_joint.def_l_wing_end", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_r_wing1_joint.def_r_wing2_joint.def_r_wing_end", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_mouth_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_mouth_joint.def_c_mouth_end", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.def_c_waddle2_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.def_c_feather3_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.def_c_waddle2_joint.def_c_waddle3_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.def_c_feather3_joint.def_c_feather4_joint", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_waddle1_joint.def_c_waddle2_joint.def_c_waddle3_joint.def_c_waddle_end", + "RootNode.chicken_skeleton.def_c_chickenRoot_joint.def_c_spine1_joint.def_c_spine2_joint.def_c_spine3_joint.def_c_spine_end.def_c_neck_joint.def_c_head_joint.def_c_feather1_joint.def_c_feather2_joint.def_c_feather3_joint.def_c_feather4_joint.def_c_feather_end" + ] + }, + "rules": { + "rules": [ + { + "$type": "SkinRule" + }, + { + "$type": "StaticMeshAdvancedRule", + "vertexColorStreamName": "Disabled" + }, + { + "$type": "MaterialRule" + }, + { + "$type": "CoordinateSystemRule" + }, + { + "$type": "ClothRule", + "meshNodeName": "RootNode.chicken_mohawk", + "inverseMassesStreamName": "colorSet1", + "motionConstraintsStreamName": "Default: 1.0", + "backstopStreamName": "None" + } + ] + }, + "id": "{55E26F74-B35F-4BC1-87BB-83E3DE85C346}" + } + ] +} \ No newline at end of file From 4b3662ac0a47cb6e962653e3acd838183c701eed Mon Sep 17 00:00:00 2001 From: moraaar Date: Fri, 16 Apr 2021 18:26:17 +0100 Subject: [PATCH 021/277] Sort out cloth tests after Actors work with model mesh assets. --- .../ActorClothCollidersTest.cpp | 10 ++-- .../ClothComponentMeshTest.cpp | 28 ++++++++--- .../Components/EditorClothComponentTest.cpp | 20 ++++---- Gems/NvCloth/Code/Tests/System/ClothTest.cpp | 2 +- .../Code/Tests/System/FabricCookerTest.cpp | 44 ++++++++-------- .../Code/Tests/Utils/ActorAssetHelperTest.cpp | 50 +++++++++++++------ 6 files changed, 96 insertions(+), 58 deletions(-) diff --git a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ActorClothCollidersTest.cpp b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ActorClothCollidersTest.cpp index 946f9e0af2..e3a321cebd 100644 --- a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ActorClothCollidersTest.cpp +++ b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ActorClothCollidersTest.cpp @@ -145,8 +145,8 @@ namespace UnitTest const AZStd::vector& capsuleColliders = actorClothColliders->GetCapsuleColliders(); const AZStd::vector& nativeCapsuleIndices = actorClothColliders->GetCapsuleIndices(); - EXPECT_EQ(sphereColliders.size(), 1); - EXPECT_EQ(nativeSpheres.size(), 1); + ASSERT_EQ(sphereColliders.size(), 1); + ASSERT_EQ(nativeSpheres.size(), 1); EXPECT_TRUE(capsuleColliders.empty()); EXPECT_TRUE(nativeCapsuleIndices.empty()); @@ -189,9 +189,9 @@ namespace UnitTest const AZStd::vector& nativeCapsuleIndices = actorClothColliders->GetCapsuleIndices(); EXPECT_TRUE(sphereColliders.empty()); - EXPECT_EQ(nativeSpheres.size(), 2); // Each capsule produces 2 spheres - EXPECT_EQ(capsuleColliders.size(), 1); - EXPECT_EQ(nativeCapsuleIndices.size(), 2); // Each capsule is 2 indices + ASSERT_EQ(nativeSpheres.size(), 2); // Each capsule produces 2 spheres + ASSERT_EQ(capsuleColliders.size(), 1); + ASSERT_EQ(nativeCapsuleIndices.size(), 2); // Each capsule is 2 indices EXPECT_NEAR(capsuleColliders[0].m_height, height, Tolerance); EXPECT_NEAR(capsuleColliders[0].m_radius, radius, Tolerance); diff --git a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothComponentMeshTest.cpp b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothComponentMeshTest.cpp index c463c30226..3d5b7713b3 100644 --- a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothComponentMeshTest.cpp +++ b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ClothComponentMeshTest.cpp @@ -144,8 +144,12 @@ namespace UnitTest EXPECT_TRUE(renderData.m_bitangents.empty()); EXPECT_TRUE(renderData.m_normals.empty()); } - - TEST_F(NvClothComponentMesh, ClothComponentMesh_InitWithEntityActorWithNoClothData_TriggersError) + + // [TODO LYN-1891] + // Revisit when Cloth Component Mesh works with Actors adapted to Atom models. + // Editor Cloth component now uses the new AZ::Render::MeshComponentNotificationBus::OnModelReady + // notification and this test does not setup a model yet. + TEST_F(NvClothComponentMesh, DISABLED_ClothComponentMesh_InitWithEntityActorWithNoClothData_TriggersError) { { auto actor = AZStd::make_unique("actor_test"); @@ -165,8 +169,12 @@ namespace UnitTest AZ_TEST_STOP_TRACE_SUPPRESSION(1); // Expect 1 error } - - TEST_F(NvClothComponentMesh, ClothComponentMesh_InitWithEntityActor_ReturnsValidRenderData) + + // [TODO LYN-1891] + // Revisit when Cloth Component Mesh works with Actors adapted to Atom models. + // Editor Cloth component now uses the new AZ::Render::MeshComponentNotificationBus::OnModelReady + // notification and this test does not setup a model yet. + TEST_F(NvClothComponentMesh, DISABLED_ClothComponentMesh_InitWithEntityActor_ReturnsValidRenderData) { { auto actor = AZStd::make_unique("actor_test"); @@ -265,7 +273,11 @@ namespace UnitTest EXPECT_TRUE(renderData.m_normals.empty()); } - TEST_F(NvClothComponentMesh, ClothComponentMesh_UpdateConfigurationDifferentEntity_ReturnsRenderDataFromNewEntity) + // [TODO LYN-1891] + // Revisit when Cloth Component Mesh works with Actors adapted to Atom models. + // Editor Cloth component now uses the new AZ::Render::MeshComponentNotificationBus::OnModelReady + // notification and this test does not setup a model yet. + TEST_F(NvClothComponentMesh, DISABLED_ClothComponentMesh_UpdateConfigurationDifferentEntity_ReturnsRenderDataFromNewEntity) { { auto actor = AZStd::make_unique("actor_test"); @@ -341,7 +353,11 @@ namespace UnitTest EXPECT_TRUE(renderData.m_normals.empty()); } - TEST_F(NvClothComponentMesh, ClothComponentMesh_UpdateConfigurationNewMeshNode_ReturnsRenderDataFromNewMeshNode) + // [TODO LYN-1891] + // Revisit when Cloth Component Mesh works with Actors adapted to Atom models. + // Editor Cloth component now uses the new AZ::Render::MeshComponentNotificationBus::OnModelReady + // notification and this test does not setup a model yet. + TEST_F(NvClothComponentMesh, DISABLED_ClothComponentMesh_UpdateConfigurationNewMeshNode_ReturnsRenderDataFromNewMeshNode) { const AZStd::string meshNode2Name = "cloth_node_2"; diff --git a/Gems/NvCloth/Code/Tests/Components/EditorClothComponentTest.cpp b/Gems/NvCloth/Code/Tests/Components/EditorClothComponentTest.cpp index bb3218a4f5..7dc191bd9a 100644 --- a/Gems/NvCloth/Code/Tests/Components/EditorClothComponentTest.cpp +++ b/Gems/NvCloth/Code/Tests/Components/EditorClothComponentTest.cpp @@ -184,7 +184,7 @@ namespace UnitTest const NvCloth::MeshNodeList& meshNodeList = editorClothComponent->GetMeshNodeList(); - EXPECT_EQ(meshNodeList.size(), 1); + ASSERT_EQ(meshNodeList.size(), 1); EXPECT_TRUE(meshNodeList[0] == NvCloth::Internal::StatusMessageNoAsset); } @@ -208,7 +208,7 @@ namespace UnitTest const NvCloth::MeshNodeList& meshNodeList = editorClothComponent->GetMeshNodeList(); - EXPECT_EQ(meshNodeList.size(), 1); + ASSERT_EQ(meshNodeList.size(), 1); EXPECT_TRUE(meshNodeList[0] == NvCloth::Internal::StatusMessageNoClothNodes); } @@ -234,7 +234,7 @@ namespace UnitTest const NvCloth::MeshNodeList& meshNodeList = editorClothComponent->GetMeshNodeList(); - EXPECT_EQ(meshNodeList.size(), 1); + ASSERT_EQ(meshNodeList.size(), 1); EXPECT_TRUE(meshNodeList[0] == NvCloth::Internal::StatusMessageNoClothNodes); } @@ -261,7 +261,7 @@ namespace UnitTest const NvCloth::MeshNodeList& meshNodeList = editorClothComponent->GetMeshNodeList(); - EXPECT_EQ(meshNodeList.size(), 2); + ASSERT_EQ(meshNodeList.size(), 2); EXPECT_TRUE(meshNodeList[0] == NvCloth::Internal::StatusMessageSelectNode); EXPECT_TRUE(meshNodeList[1] == MeshNodeName); } @@ -322,9 +322,11 @@ namespace UnitTest EXPECT_TRUE(meshNodesWithBackstopData.find(MeshNodeName) != meshNodesWithBackstopData.end()); } - // [TODO LYN-2252] - // Enable test once OnModelDestroyed is available. - TEST_F(NvClothEditorClothComponent, DISABLED_EditorClothComponent_OnMeshDestroyed_ReturnsMeshNodeListWithNoAssetMessage) + // [TODO LYN-1891] + // Revisit when Cloth Component Mesh works with Actors adapted to Atom models. + // Editor Cloth component now uses the new AZ::Render::MeshComponentNotificationBus::OnModelReady + // notification and this test does not setup a model yet. + TEST_F(NvClothEditorClothComponent, DISABLED_EditorClothComponent_OnModelPreDestroy_ReturnsMeshNodeListWithNoAssetMessage) { auto editorEntity = CreateInactiveEditorEntity("ClothComponentEditorEntity"); auto* editorClothComponent = editorEntity->CreateComponent(); @@ -341,12 +343,12 @@ namespace UnitTest editorActorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor))); } - //editorClothComponent->OnModelDestroyed(); + editorClothComponent->OnModelPreDestroy(); const NvCloth::MeshNodeList& meshNodeList = editorClothComponent->GetMeshNodeList(); const auto& meshNodesWithBackstopData = editorClothComponent->GetMeshNodesWithBackstopData(); - EXPECT_EQ(meshNodeList.size(), 1); + ASSERT_EQ(meshNodeList.size(), 1); EXPECT_TRUE(meshNodeList[0] == NvCloth::Internal::StatusMessageNoAsset); EXPECT_TRUE(meshNodesWithBackstopData.empty()); } diff --git a/Gems/NvCloth/Code/Tests/System/ClothTest.cpp b/Gems/NvCloth/Code/Tests/System/ClothTest.cpp index 2c3ae610e4..08959a9196 100644 --- a/Gems/NvCloth/Code/Tests/System/ClothTest.cpp +++ b/Gems/NvCloth/Code/Tests/System/ClothTest.cpp @@ -506,7 +506,7 @@ namespace UnitTest EXPECT_EQ(initialParticles.size(), nvClothCurrentParticles.size()); EXPECT_EQ(initialParticles.size(), nvClothPreviousParticles.size()); - for (size_t i = 0; i < nvClothCurrentParticles.size(); ++i) + for (size_t i = 0; i < initialParticles.size(); ++i) { ExpectEq(initialParticles[i], nvClothCurrentParticles[i]); ExpectEq(initialParticles[i], nvClothPreviousParticles[i]); diff --git a/Gems/NvCloth/Code/Tests/System/FabricCookerTest.cpp b/Gems/NvCloth/Code/Tests/System/FabricCookerTest.cpp index 16a5d2efa3..d2d312c2ca 100644 --- a/Gems/NvCloth/Code/Tests/System/FabricCookerTest.cpp +++ b/Gems/NvCloth/Code/Tests/System/FabricCookerTest.cpp @@ -283,7 +283,7 @@ namespace UnitTest AZStd::vector remappedVertices; NvCloth::Internal::WeldVertices(vertices, indices, weldedVertices, weldedIndices, remappedVertices); - EXPECT_EQ(weldedVertices.size(), expectedSizeAfterWelding); + ASSERT_EQ(weldedVertices.size(), expectedSizeAfterWelding); EXPECT_THAT(weldedVertices[0].GetAsVector3(), IsCloseTolerance(vertexPosition, Tolerance)); EXPECT_NEAR(weldedVertices[0].GetW(), lowestInverseMass, Tolerance); } @@ -307,9 +307,9 @@ namespace UnitTest AZStd::vector remappedVertices; NvCloth::Internal::WeldVertices(vertices, indices, weldedVertices, weldedIndices, remappedVertices); - EXPECT_EQ(weldedVertices.size(), expectedSizeAfterWelding); - EXPECT_EQ(weldedIndices.size(), indices.size()); - EXPECT_EQ(remappedVertices.size(), vertices.size()); + ASSERT_EQ(weldedVertices.size(), expectedSizeAfterWelding); + ASSERT_EQ(weldedIndices.size(), indices.size()); + ASSERT_EQ(remappedVertices.size(), vertices.size()); for (size_t i = 0; i < remappedVertices.size(); ++i) { @@ -347,9 +347,9 @@ namespace UnitTest // The result after calling WeldVertices is expected to have the same size. // The vertices inside will be reordered though due to the welding process. - EXPECT_EQ(weldedVertices.size(), vertices.size()); - EXPECT_EQ(weldedIndices.size(), indices.size()); - EXPECT_EQ(remappedVertices.size(), vertices.size()); + ASSERT_EQ(weldedVertices.size(), vertices.size()); + ASSERT_EQ(weldedIndices.size(), indices.size()); + ASSERT_EQ(remappedVertices.size(), vertices.size()); for (size_t i = 0; i < remappedVertices.size(); ++i) { @@ -422,9 +422,9 @@ namespace UnitTest AZStd::vector remappedVertices; NvCloth::Internal::RemoveStaticTriangles(vertices, indices, simplifiedVertices, simplifiedIndices, remappedVertices); - EXPECT_EQ(simplifiedVertices.size(), expectedVerticesSizeAfterSimplification); - EXPECT_EQ(simplifiedIndices.size(), expectedIndicesSizeAfterSimplification); - EXPECT_EQ(remappedVertices.size(), vertices.size()); + ASSERT_EQ(simplifiedVertices.size(), expectedVerticesSizeAfterSimplification); + ASSERT_EQ(simplifiedIndices.size(), expectedIndicesSizeAfterSimplification); + ASSERT_EQ(remappedVertices.size(), vertices.size()); for (size_t i = 0; i < remappedVertices.size(); ++i) { @@ -477,9 +477,9 @@ namespace UnitTest AZStd::vector remappedVertices; NvCloth::Internal::RemoveStaticTriangles(vertices, indices, simplifiedVertices, simplifiedIndices, remappedVertices); - EXPECT_EQ(simplifiedVertices.size(), expectedVerticesSizeAfterSimplification); - EXPECT_EQ(simplifiedIndices.size(), expectedIndicesSizeAfterSimplification); - EXPECT_EQ(remappedVertices.size(), vertices.size()); + ASSERT_EQ(simplifiedVertices.size(), expectedVerticesSizeAfterSimplification); + ASSERT_EQ(simplifiedIndices.size(), expectedIndicesSizeAfterSimplification); + ASSERT_EQ(remappedVertices.size(), vertices.size()); for (size_t i = 0; i < remappedVertices.size(); ++i) { @@ -532,9 +532,9 @@ namespace UnitTest // The result after calling RemoveStaticTriangles is expected to have the same size. // The vertices will be reordered though due to the processing during simplification. - EXPECT_EQ(simplifiedVertices.size(), vertices.size()); - EXPECT_EQ(simplifiedIndices.size(), indices.size()); - EXPECT_EQ(remappedVertices.size(), vertices.size()); + ASSERT_EQ(simplifiedVertices.size(), vertices.size()); + ASSERT_EQ(simplifiedIndices.size(), indices.size()); + ASSERT_EQ(remappedVertices.size(), vertices.size()); for (size_t i = 0; i < remappedVertices.size(); ++i) { @@ -576,9 +576,9 @@ namespace UnitTest AZStd::vector remappedVertices; AZ::Interface::Get()->SimplifyMesh(vertices, indices, simplifiedVertices, simplifiedIndices, remappedVertices, removeStaticTriangles); - EXPECT_EQ(simplifiedVertices.size(), expectedVerticesSizeAfterSimplification); - EXPECT_EQ(simplifiedIndices.size(), expectedIndicesSizeAfterSimplification); - EXPECT_EQ(remappedVertices.size(), vertices.size()); + ASSERT_EQ(simplifiedVertices.size(), expectedVerticesSizeAfterSimplification); + ASSERT_EQ(simplifiedIndices.size(), expectedIndicesSizeAfterSimplification); + ASSERT_EQ(remappedVertices.size(), vertices.size()); for (size_t i = 0; i < remappedVertices.size(); ++i) { @@ -635,9 +635,9 @@ namespace UnitTest AZStd::vector remappedVertices; AZ::Interface::Get()->SimplifyMesh(vertices, indices, simplifiedVertices, simplifiedIndices, remappedVertices, removeStaticTriangles); - EXPECT_EQ(simplifiedVertices.size(), expectedVerticesSizeAfterSimplification); - EXPECT_EQ(simplifiedIndices.size(), expectedIndicesSizeAfterSimplification); - EXPECT_EQ(remappedVertices.size(), vertices.size()); + ASSERT_EQ(simplifiedVertices.size(), expectedVerticesSizeAfterSimplification); + ASSERT_EQ(simplifiedIndices.size(), expectedIndicesSizeAfterSimplification); + ASSERT_EQ(remappedVertices.size(), vertices.size()); for (size_t i = 0; i < remappedVertices.size(); ++i) { diff --git a/Gems/NvCloth/Code/Tests/Utils/ActorAssetHelperTest.cpp b/Gems/NvCloth/Code/Tests/Utils/ActorAssetHelperTest.cpp index 481bf70c67..de0ba9031e 100644 --- a/Gems/NvCloth/Code/Tests/Utils/ActorAssetHelperTest.cpp +++ b/Gems/NvCloth/Code/Tests/Utils/ActorAssetHelperTest.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -24,7 +24,7 @@ namespace UnitTest { //! Fixture to setup entity with actor component and the tests data. - class NvClothActorAssetHelper + class NvClothMeshAssetHelper : public ::testing::Test { public: @@ -75,7 +75,7 @@ namespace UnitTest AZStd::unique_ptr m_entity; }; - void NvClothActorAssetHelper::SetUp() + void NvClothMeshAssetHelper::SetUp() { m_entity = AZStd::make_unique(); m_entity->CreateComponent(); @@ -84,14 +84,14 @@ namespace UnitTest m_entity->Activate(); } - void NvClothActorAssetHelper::TearDown() + void NvClothMeshAssetHelper::TearDown() { m_entity->Deactivate(); m_actorComponent = nullptr; m_entity.reset(); } - TEST_F(NvClothActorAssetHelper, ActorAssetHelper_CreateAssetHelperWithInvalidEntityId_ReturnsNull) + TEST_F(NvClothMeshAssetHelper, MeshAssetHelper_CreateAssetHelperWithInvalidEntityId_ReturnsNull) { AZ::EntityId entityId; @@ -100,7 +100,18 @@ namespace UnitTest EXPECT_TRUE(assetHelper.get() == nullptr); } - TEST_F(NvClothActorAssetHelper, ActorAssetHelper_CreateAssetHelperWithActor_ReturnsValidActorAssetHelper) + TEST_F(NvClothMeshAssetHelper, MeshAssetHelper_CreateAssetHelperWithValidEntityId_ReturnsValidMeshAssetHelper) + { + AZStd::unique_ptr entity = AZStd::make_unique(); + + AZStd::unique_ptr assetHelper = NvCloth::AssetHelper::CreateAssetHelper(entity->GetId()); + + EXPECT_TRUE(assetHelper.get() != nullptr); + EXPECT_TRUE(azrtti_cast(assetHelper.get()) != nullptr); + EXPECT_FALSE(assetHelper->DoesSupportSkinnedAnimation()); + } + + TEST_F(NvClothMeshAssetHelper, MeshAssetHelper_CreateAssetHelperWithActor_ReturnsValidMeshAssetHelper) { { auto actor = AZStd::make_unique("actor_test"); @@ -112,10 +123,11 @@ namespace UnitTest AZStd::unique_ptr assetHelper = NvCloth::AssetHelper::CreateAssetHelper(m_actorComponent->GetEntityId()); EXPECT_TRUE(assetHelper.get() != nullptr); - EXPECT_TRUE(azrtti_cast(assetHelper.get()) != nullptr); + EXPECT_TRUE(azrtti_cast(assetHelper.get()) != nullptr); + EXPECT_TRUE(assetHelper->DoesSupportSkinnedAnimation()); } - TEST_F(NvClothActorAssetHelper, ActorAssetHelper_DoesSupportSkinnedAnimation_ReturnsTrue) + TEST_F(NvClothMeshAssetHelper, MeshAssetHelper_DoesSupportSkinnedAnimation_ReturnsTrue) { { auto actor = AZStd::make_unique("actor_test"); @@ -129,7 +141,7 @@ namespace UnitTest EXPECT_TRUE(assetHelper->DoesSupportSkinnedAnimation()); } - TEST_F(NvClothActorAssetHelper, ActorAssetHelper_GatherClothMeshNodesWithEmptyActor_ReturnsEmptyInfo) + TEST_F(NvClothMeshAssetHelper, MeshAssetHelper_GatherClothMeshNodesWithEmptyActor_ReturnsEmptyInfo) { { auto actor = AZStd::make_unique("actor_test"); @@ -146,7 +158,7 @@ namespace UnitTest EXPECT_TRUE(meshNodes.empty()); } - TEST_F(NvClothActorAssetHelper, ActorAssetHelper_ObtainClothMeshNodeInfoWithEmptyActor_ReturnsFalse) + TEST_F(NvClothMeshAssetHelper, MeshAssetHelper_ObtainClothMeshNodeInfoWithEmptyActor_ReturnsFalse) { { auto actor = AZStd::make_unique("actor_test"); @@ -164,7 +176,11 @@ namespace UnitTest EXPECT_FALSE(infoObtained); } - TEST_F(NvClothActorAssetHelper, ActorAssetHelper_GatherClothMeshNodesWithActor_ReturnsCorrectMeshNodeList) + // [TODO LYN-1891] + // Revisit when Cloth Component Mesh works with Actors adapted to Atom models. + // Editor Cloth component now uses the new AZ::Render::MeshComponentNotificationBus::OnModelReady + // notification and this test does not setup a model yet. + TEST_F(NvClothMeshAssetHelper, DISABLED_MeshAssetHelper_GatherClothMeshNodesWithActor_ReturnsCorrectMeshNodeList) { { auto actor = AZStd::make_unique("actor_test"); @@ -185,12 +201,16 @@ namespace UnitTest NvCloth::MeshNodeList meshNodes; assetHelper->GatherClothMeshNodes(meshNodes); - EXPECT_EQ(meshNodes.size(), 2); + ASSERT_EQ(meshNodes.size(), 2); EXPECT_TRUE(meshNodes[0] == MeshNode1Name); EXPECT_TRUE(meshNodes[1] == MeshNode2Name); } - - TEST_F(NvClothActorAssetHelper, ActorAssetHelper_ObtainClothMeshNodeInfoWithActor_ReturnsCorrectClothInfo) + + // [TODO LYN-1891] + // Revisit when Cloth Component Mesh works with Actors adapted to Atom models. + // Editor Cloth component now uses the new AZ::Render::MeshComponentNotificationBus::OnModelReady + // notification and this test does not setup a model yet. + TEST_F(NvClothMeshAssetHelper, DISABLED_MeshAssetHelper_ObtainClothMeshNodeInfoWithActor_ReturnsCorrectClothInfo) { { auto actor = AZStd::make_unique("actor_test"); @@ -215,7 +235,7 @@ namespace UnitTest EXPECT_TRUE(infoObtained); EXPECT_EQ(meshNodeInfo.m_lodLevel, LodLevel); - EXPECT_EQ(meshNodeInfo.m_subMeshes.size(), 1); + ASSERT_EQ(meshNodeInfo.m_subMeshes.size(), 1); EXPECT_EQ(meshNodeInfo.m_subMeshes[0].m_primitiveIndex, 2); EXPECT_EQ(meshNodeInfo.m_subMeshes[0].m_verticesFirstIndex, 0); EXPECT_EQ(meshNodeInfo.m_subMeshes[0].m_numVertices, MeshVertices.size()); From beafc80939e882ed9cc1d94e33c71e1d00ccb4f8 Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Fri, 16 Apr 2021 18:34:28 +0100 Subject: [PATCH 022/277] Fixed entities not being deselected when entering game mode in editor. added protections around physx AZ::Events handlers that are connected/disconnected on selection events. jira: LYN-2998 --- .../Entity/EditorEntityContextComponent.cpp | 10 ++++++++-- .../PhysX/Code/Source/EditorShapeColliderComponent.cpp | 10 ++++++++-- .../Components/EditorCharacterControllerComponent.cpp | 5 ++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.cpp index ad458b0434..44c8487272 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.cpp @@ -491,6 +491,14 @@ namespace AzToolsFramework EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditorBegin); + //cache the current selected entities. + ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities); + //deselect entities if selected when entering game mode before deactivating the entities in StartPlayInEditor(...) + if (!m_selectedBeforeStartingGame.empty()) + { + ToolsApplicationRequests::Bus::Broadcast(&ToolsApplicationRequests::MarkEntitiesDeselected, m_selectedBeforeStartingGame); + } + if (m_isLegacySliceService) { SliceEditorEntityOwnershipService* editorEntityOwnershipService = @@ -507,8 +515,6 @@ namespace AzToolsFramework m_isRunningGame = true; - ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities); - EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditor); } diff --git a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp index a1b8516150..4ee41d2be4 100644 --- a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp @@ -686,8 +686,14 @@ namespace PhysX { if (auto* physXSystem = GetPhysXSystem()) { - physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler); - physXSystem->RegisterOnDefaultMaterialLibraryChangedEventHandler(m_onDefaultMaterialLibraryChangedEventHandler); + if (!m_physXConfigChangedHandler.IsConnected()) + { + physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler); + } + if (!m_onDefaultMaterialLibraryChangedEventHandler.IsConnected()) + { + physXSystem->RegisterOnDefaultMaterialLibraryChangedEventHandler(m_onDefaultMaterialLibraryChangedEventHandler); + } } } diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/EditorCharacterControllerComponent.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/Components/EditorCharacterControllerComponent.cpp index 3f76b269e7..9a85274910 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/EditorCharacterControllerComponent.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/EditorCharacterControllerComponent.cpp @@ -149,7 +149,10 @@ namespace PhysX { if (auto* physXSystem = GetPhysXSystem()) { - physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler); + if (!m_physXConfigChangedHandler.IsConnected()) + { + physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler); + } } } From f0cf27b8d35ba6f9ec3aa3d22aaa50fcda8cc9bf Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Fri, 16 Apr 2021 13:58:57 -0500 Subject: [PATCH 023/277] adding the testing files for testing for python asset building and scripting the scene_api gets a small update for mesh_group_add_advanced_coordinate_system(self, --- .../Gem/Editor/Scripts/__init__.py | 10 ++ .../Gem/Editor/Scripts/bootstrap.py | 13 ++ .../PythonAssetBuilder/AssetBuilder_test.py | 57 +++++++++ .../AssetBuilder_test_case.py | 52 ++++++++ .../PythonAssetBuilder/__init__.py | 10 ++ .../PythonAssetBuilder/bootstrap_tests.py | 17 +++ .../export_chunks_builder.py | 88 +++++++++++++ .../PythonAssetBuilder/geom_group.fbx | 3 + .../geom_group.fbx.assetinfo | 9 ++ .../PythonAssetBuilder/mock_asset_builder.py | 121 ++++++++++++++++++ .../PythonAssetBuilder/test_asset.mock | 1 + .../Editor/Scripts/scene_api/scene_data.py | 15 ++- 12 files changed, 391 insertions(+), 5 deletions(-) create mode 100644 AutomatedTesting/Gem/Editor/Scripts/__init__.py create mode 100644 AutomatedTesting/Gem/Editor/Scripts/bootstrap.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/__init__.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/bootstrap_tests.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx.assetinfo create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py create mode 100644 AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/test_asset.mock diff --git a/AutomatedTesting/Gem/Editor/Scripts/__init__.py b/AutomatedTesting/Gem/Editor/Scripts/__init__.py new file mode 100644 index 0000000000..79f8fa4422 --- /dev/null +++ b/AutomatedTesting/Gem/Editor/Scripts/__init__.py @@ -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/AutomatedTesting/Gem/Editor/Scripts/bootstrap.py b/AutomatedTesting/Gem/Editor/Scripts/bootstrap.py new file mode 100644 index 0000000000..e41f9c1767 --- /dev/null +++ b/AutomatedTesting/Gem/Editor/Scripts/bootstrap.py @@ -0,0 +1,13 @@ +""" +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. +""" +import sys, os +sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../PythonTests') +from PythonAssetBuilder import bootstrap_tests diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py new file mode 100644 index 0000000000..e914182542 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py @@ -0,0 +1,57 @@ +""" +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. +""" +# +# This launches the AssetProcessor and Editor then attempts to find the expected +# assets created by a Python Asset Builder and the output of a scene pipeline script +# +import sys +import os +import pytest +import logging +pytest.importorskip('ly_test_tools') + +import ly_test_tools.environment.file_system as file_system +import ly_test_tools.log.log_monitor +import ly_test_tools.environment.waiter as waiter + +@pytest.mark.SUITE_sandbox +@pytest.mark.parametrize('launcher_platform', ['windows_editor']) +@pytest.mark.parametrize('project', ['AutomatedTesting']) +@pytest.mark.parametrize('level', ['auto_test']) +class TestPythonAssetProcessing(object): + def test_DetectPythonCreatedAsset(self, request, editor, level, launcher_platform): + unexpected_lines = [] + expected_lines = [ + 'Mock asset exists', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_negative.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_positive.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found' + ] + timeout = 180 + halt_on_unexpected = False + test_directory = os.path.join(os.path.dirname(__file__)) + testFile = os.path.join(test_directory, 'AssetBuilder_test_case.py') + editor.args.extend(['-NullRenderer', "--skipWelcomeScreenDialog", "--autotest_mode", "--runpythontest", testFile]) + + with editor.start(): + editorlog_file = os.path.join(editor.workspace.paths.project_log(), 'Editor.log') + log_monitor = ly_test_tools.log.log_monitor.LogMonitor(editor, editorlog_file) + waiter.wait_for( + lambda: editor.is_alive(), + timeout, + exc=("Log file '{}' was never opened by another process.".format(editorlog_file)), + interval=1) + log_monitor.monitor_log_for_lines(expected_lines, unexpected_lines, halt_on_unexpected, timeout) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py new file mode 100644 index 0000000000..608c2d224d --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py @@ -0,0 +1,52 @@ +""" +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. +""" +import azlmbr.bus +import azlmbr.asset +import azlmbr.editor +import azlmbr.math +import azlmbr.legacy.general + +def raise_and_stop(msg): + print (msg) + azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt') + +# These tests are meant to check that the test_asset.mock source asset turned into +# a test_asset.mock_asset product asset via the Python asset builder system +mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0) +mockAssetPath = 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset' +assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', mockAssetPath, mockAssetType, False) +if (assetId.is_valid() is False): + raise_and_stop(f'Mock AssetId is not valid!') + +if (assetId.to_string().endswith(':54c06b89') is False): + raise_and_stop(f'Mock AssetId has unexpected sub-id for {mockAssetPath}!') + +print ('Mock asset exists') + +# These tests detect if the geom_group.fbx file turns into a number of azmodel product assets +def test_azmodel_product(generatedModelAssetPath, expectedSubId): + azModelAssetType = azlmbr.math.Uuid_CreateString('{2C7477B6-69C5-45BE-8163-BCD6A275B6D8}', 0) + assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', generatedModelAssetPath, azModelAssetType, False) + assetIdString = assetId.to_string() + if (assetIdString.endswith(':' + expectedSubId) is False): + raise_and_stop(f'Asset has unexpected asset ID ({assetIdString}) for ({generatedModelAssetPath})!') + else: + print(f'Expected subId for asset ({generatedModelAssetPath}) found') + +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel', '10412075') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_positive.azmodel', '10d16e68') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_negative.azmodel', '10a71973') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Y_positive.azmodel', '10130556') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Y_negative.azmodel', '1065724d') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Z_positive.azmodel', '1024be55') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Z_negative.azmodel', '1052c94e') + +azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt') diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/__init__.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/__init__.py new file mode 100644 index 0000000000..6ed3dc4bda --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/__init__.py @@ -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. +""" \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/bootstrap_tests.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/bootstrap_tests.py new file mode 100644 index 0000000000..9e7b738a4d --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/bootstrap_tests.py @@ -0,0 +1,17 @@ +""" +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. +""" +import os +import sys +try: + sys.path.append(os.path.dirname(os.path.abspath(__file__))) + import mock_asset_builder +except: + print ('skipping asset builder testing via mock_asset_builder') diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py new file mode 100644 index 0000000000..ad68a486b1 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py @@ -0,0 +1,88 @@ +""" +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. +""" +import uuid, os +import azlmbr.scene as sceneApi +import azlmbr.scene.graph +from scene_api import scene_data as sceneData + +def get_mesh_node_names(sceneGraph): + meshDataList = [] + node = sceneGraph.get_root() + children = [] + + while node.IsValid(): + # store children to process after siblings + if sceneGraph.has_node_child(node): + children.append(sceneGraph.get_node_child(node)) + + # store any node that has mesh data content + nodeContent = sceneGraph.get_node_content(node) + if nodeContent is not None and nodeContent.CastWithTypeName('MeshData'): + if sceneGraph.is_node_end_point(node) is False: + meshDataList.append(sceneData.SceneGraphName(sceneGraph.get_node_name(node))) + + # advance to next node + if sceneGraph.has_node_sibling(node): + node = sceneGraph.get_node_sibling(node) + elif children: + node = children.pop() + else: + node = azlmbr.scene.graph.NodeIndex() + + return meshDataList + +def update_manifest(scene): + graph = sceneData.SceneGraph(scene.graph) + meshNameList = get_mesh_node_names(graph) + sceneManifest = sceneData.SceneManifest() + sourceFilenameOnly = os.path.basename(scene.sourceFilename) + sourceFilenameOnly = sourceFilenameOnly.replace('.','_') + + for activeMeshIndex in range(len(meshNameList)): + chunkName = meshNameList[activeMeshIndex] + chunkPath = chunkName.get_path() + meshGroupName = '{}_{}'.format(sourceFilenameOnly, chunkName.get_name()) + meshGroup = sceneManifest.add_mesh_group(meshGroupName) + meshGroup['id'] = '{' + str(uuid.uuid5(uuid.NAMESPACE_DNS, sourceFilenameOnly + chunkPath)) + '}' + sceneManifest.mesh_group_add_comment(meshGroup, 'auto generated by scene manifest') + sceneManifest.mesh_group_add_advanced_coordinate_system(meshGroup, None, None, None, 1.0) + + # create selection node list + pathSet = set() + for meshIndex in range(len(meshNameList)): + targetPath = meshNameList[meshIndex].get_path() + if (activeMeshIndex == meshIndex): + sceneManifest.mesh_group_select_node(meshGroup, targetPath) + else: + if targetPath not in pathSet: + pathSet.update(targetPath) + sceneManifest.mesh_group_unselect_node(meshGroup, targetPath) + + return sceneManifest.export() + +mySceneJobHandler = None + +def on_update_manifest(args): + scene = args[0] + result = update_manifest(scene) + global mySceneJobHandler + mySceneJobHandler.disconnect() + mySceneJobHandler = None + return result + +def main(): + global mySceneJobHandler + mySceneJobHandler = sceneApi.ScriptBuildingNotificationBusHandler() + mySceneJobHandler.connect() + mySceneJobHandler.add_callback('OnUpdateManifest', on_update_manifest) + +if __name__ == "__main__": + main() diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx new file mode 100644 index 0000000000..8945a5505a --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66d38948309ef273adf74b63eaa38f8fc2e2bdfbab3933d2ee082ce6a8cb108e +size 30496 diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx.assetinfo b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx.assetinfo new file mode 100644 index 0000000000..707c6f3705 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/geom_group.fbx.assetinfo @@ -0,0 +1,9 @@ +{ + "values": + [ + { + "$type": "ScriptProcessorRule", + "scriptFilename": "Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py" + } + ] +} diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py new file mode 100644 index 0000000000..00a656abd0 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py @@ -0,0 +1,121 @@ +""" +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. +""" +import azlmbr.asset +import azlmbr.asset.builder +import azlmbr.bus +import azlmbr.math +import os, traceback, binascii, sys + +jobKeyName = 'Mock Asset' + +def log_exception_traceback(): + exc_type, exc_value, exc_tb = sys.exc_info() + data = traceback.format_exception(exc_type, exc_value, exc_tb) + print(str(data)) + +# creates a single job to compile for each platform +def create_jobs(request): + # create job descriptor for each platform + jobDescriptorList = [] + for platformInfo in request.enabledPlatforms: + jobDesc = azlmbr.asset.builder.JobDescriptor() + jobDesc.jobKey = jobKeyName + jobDesc.set_platform_identifier(platformInfo.identifier) + jobDescriptorList.append(jobDesc) + + response = azlmbr.asset.builder.CreateJobsResponse() + response.result = azlmbr.asset.builder.CreateJobsResponse_ResultSuccess + response.createJobOutputs = jobDescriptorList + return response + +def on_create_jobs(args): + try: + request = args[0] + return create_jobs(request) + except: + log_exception_traceback() + # returing back a default CreateJobsResponse() records an asset error + return azlmbr.asset.builder.CreateJobsResponse() + +def process_file(request): + # prepare output folder + basePath, _ = os.path.split(request.sourceFile) + outputPath = os.path.join(request.tempDirPath, basePath) + os.makedirs(outputPath, exist_ok=True) + + # write out a mock file + basePath, sourceFile = os.path.split(request.sourceFile) + mockFilename = os.path.splitext(sourceFile)[0] + '.mock_asset' + mockFilename = os.path.join(basePath, mockFilename) + mockFilename = mockFilename.replace('\\', '/').lower() + tempFilename = os.path.join(request.tempDirPath, mockFilename) + + # write out a tempFilename like a JSON or something? + fileOutput = open(tempFilename, "w") + fileOutput.write('{}') + fileOutput.close() + + # generate a product asset file entry + subId = binascii.crc32(mockFilename.encode()) + mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0) + product = azlmbr.asset.builder.JobProduct(mockFilename, mockAssetType, subId) + product.dependenciesHandled = True + productOutputs = [] + productOutputs.append(product) + + # fill out response object + response = azlmbr.asset.builder.ProcessJobResponse() + response.outputProducts = productOutputs + response.resultCode = azlmbr.asset.builder.ProcessJobResponse_Success + response.dependenciesHandled = True + return response + +# using the incoming 'request' find the type of job via 'jobKey' to determine what to do +def on_process_job(args): + try: + request = args[0] + if (request.jobDescription.jobKey.startswith(jobKeyName)): + return process_file(request) + except: + log_exception_traceback() + # returning back an empty ProcessJobResponse() will record an error + return azlmbr.asset.builder.ProcessJobResponse() + +# register asset builder +def register_asset_builder(busId): + assetPattern = azlmbr.asset.builder.AssetBuilderPattern() + assetPattern.pattern = '*.mock' + assetPattern.type = azlmbr.asset.builder.AssetBuilderPattern_Wildcard + + builderDescriptor = azlmbr.asset.builder.AssetBuilderDesc() + builderDescriptor.name = "Mock Builder" + builderDescriptor.patterns = [assetPattern] + builderDescriptor.busId = busId + builderDescriptor.version = 1 + + outcome = azlmbr.asset.builder.PythonAssetBuilderRequestBus(azlmbr.bus.Broadcast, 'RegisterAssetBuilder', builderDescriptor) + if outcome.IsSuccess(): + # created the asset builder to hook into the notification bus + handler = azlmbr.asset.builder.PythonBuilderNotificationBusHandler() + handler.connect(busId) + handler.add_callback('OnCreateJobsRequest', on_create_jobs) + handler.add_callback('OnProcessJobRequest', on_process_job) + return handler + +# create the asset builder handler +busIdString = '{CF5C74C1-9ED4-5851-95B1-0B15090DBEC7}' +busId = azlmbr.math.Uuid_CreateString(busIdString, 0) +handler = None +try: + handler = register_asset_builder(busId) +except: + handler = None + log_exception_traceback() diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/test_asset.mock b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/test_asset.mock new file mode 100644 index 0000000000..6d6a52e643 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/test_asset.mock @@ -0,0 +1 @@ +mock data \ No newline at end of file diff --git a/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py b/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py index 7db3daa276..4583262b25 100755 --- a/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py +++ b/Gems/PythonAssetBuilder/Editor/Scripts/scene_api/scene_data.py @@ -114,12 +114,17 @@ class SceneManifest(): def mesh_group_unselect_node(self, meshGroup, nodeName): meshGroup['nodeSelectionList']['unselectedNodes'].append(nodeName) - def mesh_group_set_origin(self, meshGroup, originNodeName, x, y, z, scale): + def mesh_group_add_advanced_coordinate_system(self, meshGroup, originNodeName, translation, rotation, scale): originRule = {} - originRule['$type'] = 'OriginRule' - originRule['originNodeName'] = 'World' if originNodeName is None else originNodeName - originRule['translation'] = [x, y, z] - originRule['scale'] = scale + originRule['$type'] = 'CoordinateSystemRule' + originRule['useAdvancedData'] = True + originRule['originNodeName'] = '' if originNodeName is None else originNodeName + if translation is not None: + originRule['translation'] = translation + if rotation is not None: + originRule['rotation'] = rotation + if scale != 1.0: + originRule['scale'] = scale meshGroup['rules']['rules'].append(originRule) def mesh_group_add_comment(self, meshGroup, comment): From 3299730899789aa4de285635bf922c0cc62992be Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Fri, 16 Apr 2021 14:23:01 -0500 Subject: [PATCH 024/277] re-adding EPB tests --- .../Gem/PythonTests/CMakeLists.txt | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index 056c7982a6..a8ea3f9837 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -117,22 +117,22 @@ endif() #endif() ## Editor Python Bindings ## -#if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) -# ly_add_pytest( -# NAME AutomatedTesting::EditorPythonBindings -# TEST_SUITE sandbox -# TEST_SERIAL -# PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings -# TIMEOUT 3600 -# RUNTIME_DEPENDENCIES -# Legacy::Editor -# Legacy::CryRenderNULL -# AZ::AssetProcessor -# AutomatedTesting.Assets -# Gem::EditorPythonBindings.Editor -# COMPONENT TestTools -# ) -#endif() +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_pytest( + NAME AutomatedTesting::EditorPythonBindings + TEST_SUITE sandbox + TEST_SERIAL + PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings + TIMEOUT 3600 + RUNTIME_DEPENDENCIES + Legacy::Editor + Legacy::CryRenderNULL + AZ::AssetProcessor + AutomatedTesting.Assets + Gem::EditorPythonBindings.Editor + COMPONENT TestTools + ) +endif() ## Python Asset Builder ## if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) From 3d91b19c194c5736606a10d02846b4e2e5c74f8f Mon Sep 17 00:00:00 2001 From: jackalbe <23512001+jackalbe@users.noreply.github.com> Date: Fri, 16 Apr 2021 15:41:03 -0500 Subject: [PATCH 025/277] printing wrong asset ID in message cleaned up comment --- .../PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py | 2 +- .../Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py index 608c2d224d..54857c2067 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py @@ -24,7 +24,7 @@ mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080 mockAssetPath = 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset' assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', mockAssetPath, mockAssetType, False) if (assetId.is_valid() is False): - raise_and_stop(f'Mock AssetId is not valid!') + raise_and_stop(f'Mock AssetId is not valid! Got {assetId.to_string()} instead') if (assetId.to_string().endswith(':54c06b89') is False): raise_and_stop(f'Mock AssetId has unexpected sub-id for {mockAssetPath}!') diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py index 00a656abd0..c60871ac46 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/mock_asset_builder.py @@ -58,7 +58,7 @@ def process_file(request): mockFilename = mockFilename.replace('\\', '/').lower() tempFilename = os.path.join(request.tempDirPath, mockFilename) - # write out a tempFilename like a JSON or something? + # write out a tempFilename like a JSON fileOutput = open(tempFilename, "w") fileOutput.write('{}') fileOutput.close() From db9b0f141fbeacc24606d5d109766559d4912b62 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 16 Apr 2021 16:13:39 -0700 Subject: [PATCH 026/277] Double click launches Material Editor --- .../Window/MaterialBrowserInteractions.cpp | 356 ----------------- .../MaterialEditorBrowserInteractions.cpp | 358 ++++++++++++++++++ ....h => MaterialEditorBrowserInteractions.h} | 8 +- .../Window/MaterialEditorWindowComponent.cpp | 2 +- .../Window/MaterialEditorWindowComponent.h | 4 +- .../Code/materialeditorwindow_files.cmake | 4 +- .../EditorMaterialSystemComponent.cpp | 2 + .../Material/EditorMaterialSystemComponent.h | 4 + .../Material/MaterialBrowserInteractions.cpp | 54 +++ .../Material/MaterialBrowserInteractions.h | 52 +++ ...egration_commonfeatures_editor_files.cmake | 2 + 11 files changed, 481 insertions(+), 365 deletions(-) delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp create mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp rename Gems/Atom/Tools/MaterialEditor/Code/Source/Window/{MaterialBrowserInteractions.h => MaterialEditorBrowserInteractions.h} (91%) create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp deleted file mode 100644 index b0412c001c..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp +++ /dev/null @@ -1,356 +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. -* -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -namespace MaterialEditor -{ - MaterialBrowserInteractions::MaterialBrowserInteractions() - { - using namespace AzToolsFramework::AssetBrowser; - - AssetBrowserInteractionNotificationBus::Handler::BusConnect(); - } - - MaterialBrowserInteractions::~MaterialBrowserInteractions() - { - AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); - } - - void MaterialBrowserInteractions::AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector& entries) - { - AssetBrowserEntry* entry = entries.empty() ? nullptr : entries.front(); - if (!entry) - { - return; - } - - m_caller = caller; - QObject::connect(m_caller, &QObject::destroyed, [this]() - { - m_caller = nullptr; - }); - - AddGenericContextMenuActions(caller, menu, entry); - - if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) - { - const auto source = azalias_cast(entry); - if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) - { - AddContextMenuActionsForMaterialSource(caller, menu, source); - } - else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) - { - AddContextMenuActionsForMaterialTypeSource(caller, menu, source); - } - else - { - AddContextMenuActionsForOtherSource(caller, menu, source); - } - } - else if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder) - { - const auto folder = azalias_cast(entry); - AddContextMenuActionsForFolder(caller, menu, folder); - } - } - - 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]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - menu->addSeparator(); - - menu->addAction("Create Material...", [entry]() - { - const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( - QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + - AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, - entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); - }); - - AddPerforceMenuActions(caller, menu, entry); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) - { - menu->addAction("Open", [entry]() - { - QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str())); - }); - - menu->addAction("Duplicate...", [entry, caller]() - { - const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); - if (!duplicateFileInfo.absoluteFilePath().isEmpty()) - { - if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) - { - QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); - - // Auto add file to source control - AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - } - } - }); - - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - AddPerforceMenuActions(caller, menu, entry); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) - { - menu->addAction("Open", [entry]() - { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); - }); - - menu->addAction("Duplicate...", [entry, caller]() - { - const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); - if (!duplicateFileInfo.absoluteFilePath().isEmpty()) - { - if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) - { - QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); - - // Auto add file to source control - AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - } - } - }); - - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - menu->addSeparator(); - - menu->addAction("Create Child Material...", [entry]() - { - const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( - QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + - AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, - entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); - }); - - menu->addSeparator(); - - QAction* openParentAction = menu->addAction("Open Parent Material", [entry]() - { - AZ_UNUSED(entry); - // ToDo - }); - openParentAction->setEnabled(false); - - AddPerforceMenuActions(caller, menu, entry); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForFolder(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry* entry) - { - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - QAction* createFolderAction = menu->addAction(QObject::tr("Create new sub folder...")); - QObject::connect(createFolderAction, &QAction::triggered, caller, [caller, entry]() - { - bool ok; - QString newFolderName = QInputDialog::getText(caller, "Enter new folder name", "name:", QLineEdit::Normal, "NewFolder", &ok); - if (ok) - { - if (newFolderName.isEmpty()) - { - QMessageBox msgBox(QMessageBox::Icon::Critical, "Error", "Folder name can't be empty", QMessageBox::Ok, caller); - msgBox.exec(); - } - else - { - AZStd::string newFolderPath; - AzFramework::StringFunc::Path::Join(entry->GetFullPath().c_str(), newFolderName.toUtf8().constData(), newFolderPath); - QDir dir(newFolderPath.c_str()); - if (dir.exists()) - { - QMessageBox::critical(caller, "Error", "Folder with this name already exists"); - return; - } - auto result = dir.mkdir(newFolderPath.c_str()); - if (!result) - { - AZ_Error("MaterialBrowser", false, "Failed to make new folder"); - return; - } - } - } - }); - } - - void MaterialBrowserInteractions::AddPerforceMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) - { - using namespace AzToolsFramework; - - bool isActive = false; - SourceControlConnectionRequestBus::BroadcastResult(isActive, &SourceControlConnectionRequests::IsActive); - - if (isActive) - { - menu->addSeparator(); - - AZStd::string path = entry->GetFullPath(); - AzFramework::StringFunc::Path::Normalize(path); - - QMenu* sourceControlMenu = menu->addMenu("Source Control"); - - // Update the enabled state of source control menu actions only if menu is shown - QMenu::connect(sourceControlMenu, &QMenu::aboutToShow, [this, path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::GetFileInfo, path.c_str(), - [this](bool success, const SourceControlFileInfo& info) { UpdateSourceControlActions(success, info); }); - }); - - // add get latest action - m_getLatestAction = sourceControlMenu->addAction("Get Latest", [path, this]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestLatest, path.c_str(), - [](bool, const SourceControlFileInfo&) {}); - }); - QObject::connect(m_getLatestAction, &QObject::destroyed, [this]() - { - m_getLatestAction = nullptr; - }); - m_getLatestAction->setEnabled(false); - - // add add action - m_addAction = sourceControlMenu->addAction("Add", [path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, - [path](bool, const SourceControlFileInfo&) - { - SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); - }); - }); - QObject::connect(m_addAction, &QObject::destroyed, [this]() - { - m_addAction = nullptr; - }); - m_addAction->setEnabled(false); - - // add checkout action - m_checkOutAction = sourceControlMenu->addAction("Check Out", [path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, - [path](bool, const SourceControlFileInfo&) - { - SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); - }); - }); - QObject::connect(m_checkOutAction, &QObject::destroyed, [this]() - { - m_checkOutAction = nullptr; - }); - m_checkOutAction->setEnabled(false); - - // add undo checkout action - m_undoCheckOutAction = sourceControlMenu->addAction("Undo Check Out", [path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestRevert, path.c_str(), - [path](bool, const SourceControlFileInfo&) - { - SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); - }); - }); - QObject::connect(m_undoCheckOutAction, &QObject::destroyed, [this]() - { - m_undoCheckOutAction = nullptr; - }); - m_undoCheckOutAction->setEnabled(false); - } - } - - void MaterialBrowserInteractions::UpdateSourceControlActions(bool success, AzToolsFramework::SourceControlFileInfo info) - { - if (!success && m_caller) - { - QMessageBox::critical(m_caller, "Error", "Source control operation failed."); - } - if (m_getLatestAction) - { - m_getLatestAction->setEnabled(info.IsManaged() && info.HasFlag(AzToolsFramework::SCF_OutOfDate)); - } - if (m_addAction) - { - m_addAction->setEnabled(!info.IsManaged()); - } - if (m_checkOutAction) - { - m_checkOutAction->setEnabled(info.IsManaged() && info.IsReadOnly() && !info.IsLockedByOther()); - } - if (m_undoCheckOutAction) - { - m_undoCheckOutAction->setEnabled(info.IsManaged() && !info.IsReadOnly()); - } - } -} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp new file mode 100644 index 0000000000..92e02d5b42 --- /dev/null +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp @@ -0,0 +1,358 @@ +/* +* 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 +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +namespace MaterialEditor +{ + MaterialEditorBrowserInteractions::MaterialEditorBrowserInteractions() + { + using namespace AzToolsFramework::AssetBrowser; + + AssetBrowserInteractionNotificationBus::Handler::BusConnect(); + } + + MaterialEditorBrowserInteractions::~MaterialEditorBrowserInteractions() + { + AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector& entries) + { + AssetBrowserEntry* entry = entries.empty() ? nullptr : entries.front(); + if (!entry) + { + return; + } + + m_caller = caller; + QObject::connect(m_caller, &QObject::destroyed, [this]() + { + m_caller = nullptr; + }); + + AddGenericContextMenuActions(caller, menu, entry); + + if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) + { + const auto source = azalias_cast(entry); + if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) + { + AddContextMenuActionsForMaterialSource(caller, menu, source); + } + else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) + { + AddContextMenuActionsForMaterialTypeSource(caller, menu, source); + } + else + { + AddContextMenuActionsForOtherSource(caller, menu, source); + } + } + else if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder) + { + const auto folder = azalias_cast(entry); + AddContextMenuActionsForFolder(caller, menu, folder); + } + } + + void MaterialEditorBrowserInteractions::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 MaterialEditorBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) + { + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + menu->addSeparator(); + + menu->addAction("Create Material...", [entry]() + { + const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( + QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); + + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); + }); + + AddPerforceMenuActions(caller, menu, entry); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) + { + menu->addAction("Open", [entry]() + { + QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str())); + }); + + menu->addAction("Duplicate...", [entry, caller]() + { + const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); + if (!duplicateFileInfo.absoluteFilePath().isEmpty()) + { + if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) + { + QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); + + // Auto add file to source control + AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, + duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); + } + } + }); + + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + AddPerforceMenuActions(caller, menu, entry); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) + { + menu->addAction("Open", [entry]() + { + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); + }); + + menu->addAction("Duplicate...", [entry, caller]() + { + const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); + if (!duplicateFileInfo.absoluteFilePath().isEmpty()) + { + if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) + { + QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); + + // Auto add file to source control + AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, + duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); + } + } + }); + + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + menu->addSeparator(); + + menu->addAction("Create Child Material...", [entry]() + { + const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( + QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); + + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); + }); + + menu->addSeparator(); + + QAction* openParentAction = menu->addAction("Open Parent Material", [entry]() + { + AZ_UNUSED(entry); + // ToDo + }); + openParentAction->setEnabled(false); + + AddPerforceMenuActions(caller, menu, entry); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForFolder(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry* entry) + { + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + QAction* createFolderAction = menu->addAction(QObject::tr("Create new sub folder...")); + QObject::connect(createFolderAction, &QAction::triggered, caller, [caller, entry]() + { + bool ok; + QString newFolderName = QInputDialog::getText(caller, "Enter new folder name", "name:", QLineEdit::Normal, "NewFolder", &ok); + if (ok) + { + if (newFolderName.isEmpty()) + { + QMessageBox msgBox(QMessageBox::Icon::Critical, "Error", "Folder name can't be empty", QMessageBox::Ok, caller); + msgBox.exec(); + } + else + { + AZStd::string newFolderPath; + AzFramework::StringFunc::Path::Join(entry->GetFullPath().c_str(), newFolderName.toUtf8().constData(), newFolderPath); + QDir dir(newFolderPath.c_str()); + if (dir.exists()) + { + QMessageBox::critical(caller, "Error", "Folder with this name already exists"); + return; + } + auto result = dir.mkdir(newFolderPath.c_str()); + if (!result) + { + AZ_Error("MaterialBrowser", false, "Failed to make new folder"); + return; + } + } + } + }); + } + + void MaterialEditorBrowserInteractions::AddPerforceMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) + { + using namespace AzToolsFramework; + + bool isActive = false; + SourceControlConnectionRequestBus::BroadcastResult(isActive, &SourceControlConnectionRequests::IsActive); + + if (isActive) + { + menu->addSeparator(); + + AZStd::string path = entry->GetFullPath(); + AzFramework::StringFunc::Path::Normalize(path); + + QMenu* sourceControlMenu = menu->addMenu("Source Control"); + + // Update the enabled state of source control menu actions only if menu is shown + QMenu::connect(sourceControlMenu, &QMenu::aboutToShow, [this, path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::GetFileInfo, path.c_str(), + [this](bool success, const SourceControlFileInfo& info) { UpdateSourceControlActions(success, info); }); + }); + + // add get latest action + m_getLatestAction = sourceControlMenu->addAction("Get Latest", [path, this]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestLatest, path.c_str(), + [](bool, const SourceControlFileInfo&) {}); + }); + QObject::connect(m_getLatestAction, &QObject::destroyed, [this]() + { + m_getLatestAction = nullptr; + }); + m_getLatestAction->setEnabled(false); + + // add add action + m_addAction = sourceControlMenu->addAction("Add", [path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, + [path](bool, const SourceControlFileInfo&) + { + SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); + }); + }); + QObject::connect(m_addAction, &QObject::destroyed, [this]() + { + m_addAction = nullptr; + }); + m_addAction->setEnabled(false); + + // add checkout action + m_checkOutAction = sourceControlMenu->addAction("Check Out", [path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, + [path](bool, const SourceControlFileInfo&) + { + SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); + }); + }); + QObject::connect(m_checkOutAction, &QObject::destroyed, [this]() + { + m_checkOutAction = nullptr; + }); + m_checkOutAction->setEnabled(false); + + // add undo checkout action + m_undoCheckOutAction = sourceControlMenu->addAction("Undo Check Out", [path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestRevert, path.c_str(), + [path](bool, const SourceControlFileInfo&) + { + SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); + }); + }); + QObject::connect(m_undoCheckOutAction, &QObject::destroyed, [this]() + { + m_undoCheckOutAction = nullptr; + }); + m_undoCheckOutAction->setEnabled(false); + } + } + + void MaterialEditorBrowserInteractions::UpdateSourceControlActions(bool success, AzToolsFramework::SourceControlFileInfo info) + { + if (!success && m_caller) + { + QMessageBox::critical(m_caller, "Error", "Source control operation failed."); + } + if (m_getLatestAction) + { + m_getLatestAction->setEnabled(info.IsManaged() && info.HasFlag(AzToolsFramework::SCF_OutOfDate)); + } + if (m_addAction) + { + m_addAction->setEnabled(!info.IsManaged()); + } + if (m_checkOutAction) + { + m_checkOutAction->setEnabled(info.IsManaged() && info.IsReadOnly() && !info.IsLockedByOther()); + } + if (m_undoCheckOutAction) + { + m_undoCheckOutAction->setEnabled(info.IsManaged() && !info.IsReadOnly()); + } + } +} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.h similarity index 91% rename from Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h rename to Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.h index 2806cee6d4..7ee3ec833d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.h @@ -31,14 +31,14 @@ namespace AzToolsFramework namespace MaterialEditor { - class MaterialBrowserInteractions + class MaterialEditorBrowserInteractions : public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler { public: - AZ_CLASS_ALLOCATOR(MaterialBrowserInteractions, AZ::SystemAllocator, 0); + AZ_CLASS_ALLOCATOR(MaterialEditorBrowserInteractions, AZ::SystemAllocator, 0); - MaterialBrowserInteractions(); - ~MaterialBrowserInteractions(); + MaterialEditorBrowserInteractions(); + ~MaterialEditorBrowserInteractions(); private: //! AssetBrowserInteractionNotificationBus::Handler overrides... diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 6f03510301..a1ff8da635 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -98,7 +98,7 @@ namespace MaterialEditor void MaterialEditorWindowComponent::CreateMaterialEditorWindow() { - m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions); + m_materialEditorBrowserInteractions.reset(aznew MaterialEditorBrowserInteractions); m_window.reset(aznew MaterialEditorWindow); m_window->show(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h index f727fcc97c..1ea05d6530 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h @@ -16,7 +16,7 @@ #include #include -#include +#include #include namespace MaterialEditor @@ -57,6 +57,6 @@ namespace MaterialEditor //////////////////////////////////////////////////////////////////////// AZStd::unique_ptr m_window; - AZStd::unique_ptr m_materialBrowserInteractions; + AZStd::unique_ptr m_materialEditorBrowserInteractions; }; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake index fef3aeefb7..1547dbf48f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake @@ -14,8 +14,8 @@ set(FILES Include/Atom/Window/MaterialEditorWindowNotificationBus.h Include/Atom/Window/MaterialEditorWindowRequestBus.h Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h - Source/Window/MaterialBrowserInteractions.h - Source/Window/MaterialBrowserInteractions.cpp + Source/Window/MaterialEditorBrowserInteractions.h + Source/Window/MaterialEditorBrowserInteractions.cpp Source/Window/MaterialEditorWindow.h Source/Window/MaterialEditorWindow.cpp Source/Window/MaterialEditorWindowModule.cpp diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp index 82f65b205d..94dfb39419 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp @@ -100,6 +100,7 @@ namespace AZ AzToolsFramework::EditorMenuNotificationBus::Handler::BusConnect(); SetupThumbnails(); + m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions); } void EditorMaterialSystemComponent::Deactivate() @@ -111,6 +112,7 @@ namespace AZ AzToolsFramework::EditorMenuNotificationBus::Handler::BusDisconnect(); TeardownThumbnails(); + m_materialBrowserInteractions.reset(); if (m_openMaterialEditorAction) { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h index de065f679e..09ad1c1b9c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h @@ -22,6 +22,8 @@ #include +#include + namespace AZ { namespace Render @@ -76,6 +78,8 @@ namespace AZ AzFramework::TargetInfo m_materialEditorTarget; QAction* m_openMaterialEditorAction = nullptr; + + AZStd::unique_ptr m_materialBrowserInteractions; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp new file mode 100644 index 0000000000..82fa47a810 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp @@ -0,0 +1,54 @@ +/* +* 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 + +namespace AZ +{ + namespace Render + { + MaterialBrowserInteractions::MaterialBrowserInteractions() + { + AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); + } + + MaterialBrowserInteractions::~MaterialBrowserInteractions() + { + AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); + } + + void MaterialBrowserInteractions::AddSourceFileOpeners(const char* fullSourceFileName, [[maybe_unused]] const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers) + { + if (HandlesSource(fullSourceFileName)) + { + openers.push_back( + { + "Material_Editor", + "Open in Material Editor...", + QIcon(), + [&](const char* fullSourceFileNameInCallback, [[maybe_unused]] const AZ::Uuid& sourceUUID) + { + EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, fullSourceFileNameInCallback); + } + }); + } + } + + bool MaterialBrowserInteractions::HandlesSource(AZStd::string_view fileName) const + { + return AZStd::wildcard_match("*.material", fileName.data()); + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h new file mode 100644 index 0000000000..bd9791d3a5 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h @@ -0,0 +1,52 @@ +/* +* 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 + +class QWidget; +class QMenu; +class QAction; + +namespace AzToolsFramework +{ + namespace AssetBrowser + { + class AssetBrowserEntry; + class SourceAssetBrowserEntry; + class FolderAssetBrowserEntry; + } +} + +namespace AZ +{ + namespace Render + { + class MaterialBrowserInteractions + : public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler + { + public: + AZ_CLASS_ALLOCATOR(MaterialBrowserInteractions, AZ::SystemAllocator, 0); + + MaterialBrowserInteractions(); + ~MaterialBrowserInteractions(); + + private: + //! AssetBrowserInteractionNotificationBus::Handler overrides... + void AddSourceFileOpeners(const char* fullSourceFileName, const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers) override; + + bool HandlesSource(AZStd::string_view fileName) const; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake index f77b175cd7..fe475da189 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake @@ -41,6 +41,8 @@ set(FILES Source/Material/EditorMaterialModelUvNameMapInspector.h Source/Material/EditorMaterialSystemComponent.cpp Source/Material/EditorMaterialSystemComponent.h + Source/Material/MaterialBrowserInteractions.h + Source/Material/MaterialBrowserInteractions.cpp Source/Material/MaterialThumbnail.cpp Source/Material/MaterialThumbnail.h Source/Mesh/EditorMeshComponent.h From 22d6e1ec0dfd41a49d2e8b37e4ee71566a274838 Mon Sep 17 00:00:00 2001 From: srikappa Date: Fri, 16 Apr 2021 16:18:34 -0700 Subject: [PATCH 027/277] Modularized undo instannce update undo operation and enabled setting container entity to be selected --- .../Prefab/PrefabPublicHandler.cpp | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index b97e9ebd98..0ce929217d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -146,15 +146,8 @@ namespace AzToolsFramework "(A null instance is returned).")); } - PrefabDom commonRootInstanceDomAfterCreate; - m_instanceToTemplateInterface->GenerateDomForInstance( - commonRootInstanceDomAfterCreate, commonRootEntityOwningInstance->get()); - - auto commonRootInstanceUndoNode = aznew PrefabUndoInstance("Undo Instance Node"); - commonRootInstanceUndoNode->Capture( - commonRootInstanceDomBeforeCreate, commonRootInstanceDomAfterCreate, commonRootOwningTemplateId); - commonRootInstanceUndoNode->SetParent(undoBatch.GetUndoBatch()); - commonRootInstanceUndoNode->Redo(); + PrefabUndoHelpers::UpdatePrefabInstance( + commonRootEntityOwningInstance->get(), "Undo detaching entity", commonRootInstanceDomBeforeCreate, undoBatch.GetUndoBatch()); linkRemoveUndo->Redo(); @@ -208,22 +201,17 @@ namespace AzToolsFramework undoBatch.MarkEntityDirty(topLevelEntity->GetId()); AZ::TransformBus::Event(topLevelEntity->GetId(), &AZ::TransformBus::Events::SetParent, containerEntityId); } - - /* + // Select Container Entity { auto selectionUndo = aznew SelectionCommand({containerEntityId}, "Select Prefab Container Entity"); selectionUndo->SetParent(undoBatch.GetUndoBatch()); - ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo); - }*/ + } } // Save Template to file m_prefabLoaderInterface->SaveTemplate(instance->get().GetTemplateId()); - - // This function does not support undo/redo yet, so clear the undo stack to prevent issues. - //AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequestBus::Events::FlushUndo); return AZ::Success(); } From b3cc14dd5cfddb945584c6274c88614b7baade10 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 16 Apr 2021 18:59:21 -0700 Subject: [PATCH 028/277] disabling source control thumbnails in material editor --- .../MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp index bd7e1d94ab..6272312b90 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp @@ -73,7 +73,7 @@ namespace MaterialEditor m_filterModel->SetFilter(CreateFilter()); m_ui->m_assetBrowserTreeViewWidget->setModel(m_filterModel); - m_ui->m_assetBrowserTreeViewWidget->SetShowSourceControlIcons(true); + m_ui->m_assetBrowserTreeViewWidget->SetShowSourceControlIcons(false); m_ui->m_assetBrowserTreeViewWidget->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection); // Maintains the tree expansion state between runs From d614b357e5cc1fe20398eb4a0244c3120be1e10f Mon Sep 17 00:00:00 2001 From: guthadam Date: Fri, 16 Apr 2021 22:11:01 -0500 Subject: [PATCH 029/277] ATOM-5921 Material Editor: Select newly created materials in the asset browser The code was previously using asset browser notifications to listen for new files being added in order to select newly created materials. Attempting to change the selection within the notification failed because the new entry still had not been added. Now the material browser queues and processes the selection on tick. https://jira.agscollab.com/browse/ATOM-5921 --- .../Source/Window/MaterialBrowserWidget.cpp | 120 ++++++++---------- .../Source/Window/MaterialBrowserWidget.h | 26 ++-- 2 files changed, 66 insertions(+), 80 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp index bd7e1d94ab..408ee1a478 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.cpp @@ -10,36 +10,32 @@ * */ +#include +#include +#include +#include #include - -#include -#include -#include +#include #include -#include +#include +#include #include -#include - -#include -#include - -#include -#include +#include +#include #include - #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT -#include -#include -#include -#include #include +#include #include -#include +#include #include -#include +#include +#include +#include +#include AZ_POP_DISABLE_WARNING namespace MaterialEditor @@ -99,7 +95,6 @@ namespace MaterialEditor } }); - AssetBrowserModelNotificationBus::Handler::BusConnect(); MaterialDocumentNotificationBus::Handler::BusConnect(); } @@ -108,7 +103,7 @@ namespace MaterialEditor // Maintains the tree expansion state between runs m_ui->m_assetBrowserTreeViewWidget->SaveState(); MaterialDocumentNotificationBus::Handler::BusDisconnect(); - AssetBrowserModelNotificationBus::Handler::BusDisconnect(); + AZ::TickBus::Handler::BusDisconnect(); } AzToolsFramework::AssetBrowser::FilterConstType MaterialBrowserWidget::CreateFilter() const @@ -151,72 +146,65 @@ namespace MaterialEditor for (const AssetBrowserEntry* entry : entries) { - const SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry); - if (!sourceEntry) - { - const ProductAssetBrowserEntry* productEntry = azrtti_cast(entry); - if (productEntry) - { - sourceEntry = azrtti_cast(productEntry->GetParent()); - } - } - - if (sourceEntry) + if (entry) { - if (AzFramework::StringFunc::Path::IsExtension(sourceEntry->GetFullPath().c_str(), MaterialExtension)) + if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, sourceEntry->GetFullPath()); + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); } - else if (AzFramework::StringFunc::Path::IsExtension(sourceEntry->GetFullPath().c_str(), MaterialTypeExtension)) + else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) { //ignore MaterialTypeExtension } else { - QDesktopServices::openUrl(QUrl::fromLocalFile(sourceEntry->GetFullPath().c_str())); + QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str())); } } } } - void MaterialBrowserWidget::EntryAdded(const AssetBrowserEntry* entry) - { - if (m_pathToSelect.empty()) - { - return; - } - - const SourceAssetBrowserEntry* sourceEntry = azrtti_cast(entry); - if (!sourceEntry) - { - const ProductAssetBrowserEntry* productEntry = azrtti_cast(entry); - if (productEntry) - { - sourceEntry = azrtti_cast(productEntry->GetParent()); - } - } - - if (sourceEntry) - { - AZStd::string sourcePath = sourceEntry->GetFullPath(); - AzFramework::StringFunc::Path::Normalize(sourcePath); - if (m_pathToSelect == sourcePath) - { - m_ui->m_assetBrowserTreeViewWidget->SelectFileAtPath(m_pathToSelect); - m_pathToSelect.clear(); - } - } - } - void MaterialBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId) { AZStd::string absolutePath; MaterialDocumentRequestBus::EventResult(absolutePath, documentId, &MaterialDocumentRequestBus::Events::GetAbsolutePath); if (!absolutePath.empty()) { + // Selecting a new asset in the browser is not guaranteed to happen immediately. + // The asset browser model notifications are sent before the model is updated. + // Instead of relying on the notifications, queue the selection and process it on tick until this change occurs. m_pathToSelect = absolutePath; AzFramework::StringFunc::Path::Normalize(m_pathToSelect); - m_ui->m_assetBrowserTreeViewWidget->SelectFileAtPath(m_pathToSelect); + AZ::TickBus::Handler::BusConnect(); + } + } + + void MaterialBrowserWidget::OnTick(float deltaTime, AZ::ScriptTimePoint time) + { + AZ_UNUSED(time); + AZ_UNUSED(deltaTime); + + if (!m_pathToSelect.empty()) + { + // Attempt to select the new path + AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast( + &AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Events::SelectFileAtPath, m_pathToSelect); + + // Iterate over the selected entries to verify if the selection was made + for (const AssetBrowserEntry* entry : m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets()) + { + if (entry) + { + AZStd::string sourcePath = entry->GetFullPath(); + AzFramework::StringFunc::Path::Normalize(sourcePath); + if (m_pathToSelect == sourcePath) + { + // Once the selection is confirmed, cancel the operation and disconnect + AZ::TickBus::Handler::BusDisconnect(); + m_pathToSelect.clear(); + } + } + } } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h index d33f568ba3..38ff894214 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserWidget.h @@ -13,11 +13,11 @@ #pragma once #if !defined(Q_MOC_RUN) +#include +#include #include -#include #include #include -#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include @@ -26,8 +26,6 @@ AZ_POP_DISABLE_WARNING #endif - - namespace AzToolsFramework { namespace AssetBrowser @@ -50,8 +48,8 @@ namespace MaterialEditor //! Provides a tree view of all available materials and other assets exposed by the MaterialEditor. class MaterialBrowserWidget : public QWidget - , public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler - , public MaterialDocumentNotificationBus::Handler + , protected AZ::TickBus::Handler + , protected MaterialDocumentNotificationBus::Handler { Q_OBJECT public: @@ -62,20 +60,20 @@ namespace MaterialEditor AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const; void OpenSelectedEntries(); + // MaterialDocumentNotificationBus::Handler implementation + void OnDocumentOpened(const AZ::Uuid& documentId) override; + + // AZ::TickBus::Handler + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + + void OpenOptionsMenu(); + QScopedPointer m_ui; AzToolsFramework::AssetBrowser::AssetBrowserFilterModel* m_filterModel = nullptr; //! if new asset is being created with this path it will automatically be selected AZStd::string m_pathToSelect; - // AssetBrowserModelNotificationBus::Handler implementation - void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override; - - // MaterialDocumentNotificationBus::Handler implementation - void OnDocumentOpened(const AZ::Uuid& documentId) override; - - void OpenOptionsMenu(); - QByteArray m_materialBrowserState; }; } // namespace MaterialEditor From 82f6d249eb11edb3907c59d97e67b5348558f6e5 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Fri, 16 Apr 2021 23:01:27 -0700 Subject: [PATCH 030/277] ATOM-14765 Add More Texture Preset Masks Several image preset files had a full list of file masks for only one platform. I made sure that the same list was applied to every platform including the default preset. Removed the "Swizzle" command from Displacement.preset. Swizzle "aaa1" is wrong since this preset expects a single channel image. Added "_col" to Albedo.preset as an abbreviation for "_color". Added "_rough" to Roughness.preset as it's a common abbreviation. Added "_rgbmask" filter to LayerMask.preset to correspond to the "_mask" filter in Grayscale.preset. Added a warning when an image can't be processed according to the assigned preset due to dimension issues. Otherwise it's difficult to figure out why it's using the ReferenceImage preset instead of what was expected. Resized the "bark" textures to make them compatible with the image presets. Removed the "bark1disp2.jgp" image and just applied the changes to the original bark1disp.jpg". It's just blurred a bit to remove excessive noise. Renamed all the "bark" textures to include an underscore "_" after "bark1" to get the image pipeline to properly recognize the file masks. Testing: AtomSampleViewer automation. All assets in AtomTest build. Opened several levels in AtomTest. --- .../BuilderSettings/BuilderSettingManager.cpp | 4 ++ .../Code/Source/ImageBuilderComponent.cpp | 2 +- .../ImageProcessingAtom/Config/Albedo.preset | 5 ++ .../Config/AmbientOcclusion.preset | 20 ++++++-- .../Config/Displacement.preset | 49 +++++++++++++++---- .../Config/Emissive.preset | 24 +++++++-- .../Config/LayerMask.preset | 15 ++++-- .../Config/NormalsWithSmoothness.preset | 24 +++++++-- .../ImageProcessingAtom/Config/Opacity.preset | 40 ++++++++++++--- .../Config/Reflectance.preset | 15 ++++-- .../001_ManyFeatures.material | 12 ++--- .../002_ParallaxPdo.material | 8 +-- .../TestData/Textures/cc0/bark1_col.jpg | 3 ++ .../TestData/Textures/cc0/bark1_disp.jpg | 3 ++ .../TestData/Textures/cc0/bark1_norm.jpg | 3 ++ .../TestData/Textures/cc0/bark1_roughness.jpg | 3 ++ .../TestData/Textures/cc0/bark1col.jpg | 3 -- .../TestData/Textures/cc0/bark1disp.jpg | 3 -- .../TestData/Textures/cc0/bark1disp2.jpg | 3 -- .../TestData/Textures/cc0/bark1norm.jpg | 3 -- .../TestData/Textures/cc0/bark1roughness.jpg | 3 -- 21 files changed, 182 insertions(+), 63 deletions(-) create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/bark1_col.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/bark1_disp.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/bark1_norm.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/bark1_roughness.jpg delete mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/bark1col.jpg delete mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/bark1disp.jpg delete mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/bark1disp2.jpg delete mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/bark1norm.jpg delete mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/bark1roughness.jpg diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp index e30fb9c6a2..3b6c906c10 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp @@ -524,6 +524,10 @@ namespace ImageProcessingAtom { return outPreset; } + else + { + AZ_Warning("Image Processing", false, "Image dimensions are not compatible with preset '%s'. The default preset will be used.", presetInfo->m_name.c_str()); + } } //uncompressed one which could be used for almost everything diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp index 4de024c088..5d5fd21b44 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp @@ -79,7 +79,7 @@ namespace ImageProcessingAtom builderDescriptor.m_busId = azrtti_typeid(); builderDescriptor.m_createJobFunction = AZStd::bind(&ImageBuilderWorker::CreateJobs, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); builderDescriptor.m_processJobFunction = AZStd::bind(&ImageBuilderWorker::ProcessJob, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); - builderDescriptor.m_version = 19; // [ATOM-14459] + builderDescriptor.m_version = 22; // [ATOM-14765] builderDescriptor.m_analysisFingerprint = ImageProcessingAtom::BuilderSettingManager::Instance()->GetAnalysisFingerprint(); m_imageBuilder.BusConnect(builderDescriptor.m_busId); AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDescriptor); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset index d81fefede2..c00185e255 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset @@ -11,6 +11,7 @@ "_basecolor", "_diff", "_color", + "_col", "_albedo", "_alb", "_bc", @@ -31,6 +32,7 @@ "FileMasks": [ "_diff", "_color", + "_col", "_albedo", "_alb", "_basecolor", @@ -51,6 +53,7 @@ "FileMasks": [ "_diff", "_color", + "_col", "_albedo", "_alb", "_basecolor", @@ -71,6 +74,7 @@ "FileMasks": [ "_diff", "_color", + "_col", "_albedo", "_alb", "_basecolor", @@ -91,6 +95,7 @@ "FileMasks": [ "_diff", "_color", + "_col", "_albedo", "_alb", "_basecolor", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset index 222a1d4c7b..6b1197e28d 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset @@ -9,7 +9,10 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_ao" + "_ao", + "_ambocc", + "_amb", + "_ambientocclusion" ], "PixelFormat": "BC4" }, @@ -33,7 +36,10 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_ao" + "_ao", + "_ambocc", + "_amb", + "_ambientocclusion" ], "PixelFormat": "EAC_R11" }, @@ -43,7 +49,10 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_ao" + "_ao", + "_ambocc", + "_amb", + "_ambientocclusion" ], "PixelFormat": "BC4" }, @@ -53,7 +62,10 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_ao" + "_ao", + "_ambocc", + "_amb", + "_ambientocclusion" ], "PixelFormat": "BC4" } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset index 1cac9c1d3a..569ff6ce23 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset @@ -9,12 +9,20 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_displ" + "_displ", + "_disp", + "_dsp", + "_d", + "_dm", + "_displacement", + "_height", + "_hm", + "_ht", + "_h" ], "PixelFormat": "BC4", "DiscardAlpha": true, "IsPowerOf2": true, - "Swizzle": "aaa1", "MipMapSetting": { "MipGenType": "Box" } @@ -26,13 +34,21 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_displ" + "_displ", + "_disp", + "_dsp", + "_d", + "_dm", + "_displacement", + "_height", + "_hm", + "_ht", + "_h" ], "PixelFormat": "EAC_R11", "DiscardAlpha": true, "IsPowerOf2": true, "SizeReduceLevel": 3, - "Swizzle": "aaa1", "MipMapSetting": { "MipGenType": "Box" } @@ -57,7 +73,6 @@ "PixelFormat": "EAC_R11", "DiscardAlpha": true, "IsPowerOf2": true, - "Swizzle": "aaa1", "MipMapSetting": { "MipGenType": "Box" } @@ -68,12 +83,20 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_displ" + "_displ", + "_disp", + "_dsp", + "_d", + "_dm", + "_displacement", + "_height", + "_hm", + "_ht", + "_h" ], "PixelFormat": "BC4", "DiscardAlpha": true, "IsPowerOf2": true, - "Swizzle": "aaa1", "MipMapSetting": { "MipGenType": "Box" } @@ -84,12 +107,20 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_displ" + "_displ", + "_disp", + "_dsp", + "_d", + "_dm", + "_displacement", + "_height", + "_hm", + "_ht", + "_h" ], "PixelFormat": "BC4", "DiscardAlpha": true, "IsPowerOf2": true, - "Swizzle": "aaa1", "MipMapSetting": { "MipGenType": "Box" } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset index d3290eb469..5dc75397a0 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset @@ -8,7 +8,11 @@ "Name": "Emissive", "RGB_Weight": "CIEXYZ", "FileMasks": [ - "_emissive" + "_emissive", + "_e", + "_glow", + "_em", + "_emit" ], "PixelFormat": "BC7", "DiscardAlpha": true @@ -33,7 +37,11 @@ "Name": "Emissive", "RGB_Weight": "CIEXYZ", "FileMasks": [ - "_emissive" + "_emissive", + "_e", + "_glow", + "_em", + "_emit" ], "PixelFormat": "ASTC_6x6", "DiscardAlpha": true @@ -43,7 +51,11 @@ "Name": "Emissive", "RGB_Weight": "CIEXYZ", "FileMasks": [ - "_emissive" + "_emissive", + "_e", + "_glow", + "_em", + "_emit" ], "PixelFormat": "BC7", "DiscardAlpha": true @@ -53,7 +65,11 @@ "Name": "Emissive", "RGB_Weight": "CIEXYZ", "FileMasks": [ - "_emissive" + "_emissive", + "_e", + "_glow", + "_em", + "_emit" ], "PixelFormat": "BC7", "DiscardAlpha": true diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LayerMask.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LayerMask.preset index 363a6f9f9d..66927b175c 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LayerMask.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LayerMask.preset @@ -9,7 +9,8 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_layers" + "_layers", + "_rgbmask" ], "PixelFormat": "R8G8B8X8" }, @@ -20,7 +21,8 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_layers" + "_layers", + "_rgbmask" ], "PixelFormat": "R8G8B8X8" }, @@ -30,7 +32,8 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_layers" + "_layers", + "_rgbmask" ], "PixelFormat": "R8G8B8X8" }, @@ -40,7 +43,8 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_layers" + "_layers", + "_rgbmask" ], "PixelFormat": "R8G8B8X8" }, @@ -50,7 +54,8 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_layers" + "_layers", + "_rgbmask" ], "PixelFormat": "R8G8B8X8" } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness.preset index fb8b1da6a4..fdb24ecd09 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness.preset @@ -9,7 +9,11 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_ddna" + "_ddna", + "_normala", + "_nrma", + "_nma", + "_na" ], "PixelFormat": "BC5s", "PixelFormatAlpha": "BC4", @@ -48,7 +52,11 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_ddna" + "_ddna", + "_normala", + "_nrma", + "_nma", + "_na" ], "PixelFormat": "ASTC_4x4", "PixelFormatAlpha": "ASTC_4x4", @@ -65,7 +73,11 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_ddna" + "_ddna", + "_normala", + "_nrma", + "_nma", + "_na" ], "PixelFormat": "BC5s", "PixelFormatAlpha": "BC4", @@ -82,7 +94,11 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_ddna" + "_ddna", + "_normala", + "_nrma", + "_nma", + "_na" ], "PixelFormat": "BC5s", "PixelFormatAlpha": "BC4", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset index bd9299d71d..6d0d9009a5 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset @@ -9,9 +9,16 @@ "SourceColor": "Linear", "DestColor": "Linear", "FileMasks": [ - "_sss", - "_trans", - "_opac" + "_sss", + "_trans", + "_opac", + "_opacity", + "_o", + "_opac", + "_op", + "_mask", + "_msk", + "_blend" ], "PixelFormat": "BC4", "IsPowerOf2": true, @@ -28,7 +35,14 @@ "FileMasks": [ "_sss", "_trans", - "_opac" + "_opac", + "_opacity", + "_o", + "_opac", + "_op", + "_mask", + "_msk", + "_blend" ], "PixelFormat": "EAC_R11", "IsPowerOf2": true, @@ -67,7 +81,14 @@ "FileMasks": [ "_sss", "_trans", - "_opac" + "_opac", + "_opacity", + "_o", + "_opac", + "_op", + "_mask", + "_msk", + "_blend" ], "PixelFormat": "BC4", "IsPowerOf2": true, @@ -83,7 +104,14 @@ "FileMasks": [ "_sss", "_trans", - "_opac" + "_opac", + "_opacity", + "_o", + "_opac", + "_op", + "_mask", + "_msk", + "_blend" ], "PixelFormat": "BC4", "IsPowerOf2": true, diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset index ca773debbb..7a6af50728 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset @@ -24,7 +24,8 @@ "_mt", "_metalness", "_metallic", - "_roughness" + "_roughness", + "_rough" ], "PixelFormat": "BC1", "IsPowerOf2": true, @@ -53,7 +54,8 @@ "_mt", "_metalness", "_metallic", - "_roughness" + "_roughness", + "_rough" ], "PixelFormat": "ETC2", "IsPowerOf2": true, @@ -81,7 +83,8 @@ "_mt", "_metalness", "_metallic", - "_roughness" + "_roughness", + "_rough" ], "PixelFormat": "ASTC_6x6", "IsPowerOf2": true, @@ -109,7 +112,8 @@ "_mt", "_metalness", "_metallic", - "_roughness" + "_roughness", + "_rough" ], "PixelFormat": "BC1", "IsPowerOf2": true, @@ -137,7 +141,8 @@ "_mt", "_metalness", "_metallic", - "_roughness" + "_roughness", + "_rough" ], "PixelFormat": "BC1", "IsPowerOf2": true, diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material index c013eecae5..e84c6296be 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material @@ -7,7 +7,7 @@ "layer1_ambientOcclusion": { "enable": true, "factor": 1.6399999856948853, - "textureMap": "TestData/Textures/cc0/bark1disp2.jpg" + "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, "layer1_baseColor": { "color": [ @@ -16,7 +16,7 @@ 0.12039368599653244, 1.0 ], - "textureMap": "TestData/Textures/cc0/bark1col.jpg" + "textureMap": "TestData/Textures/cc0/bark1_col.jpg" }, "layer1_emissive": { "color": [ @@ -30,16 +30,16 @@ "layer1_normal": { "factor": 0.4444443881511688, "flipY": true, - "textureMap": "TestData/Textures/cc0/bark1norm.jpg" + "textureMap": "TestData/Textures/cc0/bark1_norm.jpg" }, "layer1_parallax": { "enable": true, "factor": 0.02500000037252903, - "textureMap": "TestData/Textures/cc0/bark1disp2.jpg" + "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, "layer1_roughness": { "lowerBound": 0.010100999847054482, - "textureMap": "TestData/Textures/cc0/bark1roughness.jpg" + "textureMap": "TestData/Textures/cc0/bark1_roughness.jpg" }, "layer1_specularF0": { "factor": 0.5099999904632568, @@ -55,7 +55,7 @@ }, "layer2_ambientOcclusion": { "factor": 1.2200000286102296, - "textureMap": "TestData/Textures/cc0/bark1disp2.jpg" + "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, "layer2_baseColor": { "textureMap": "TestData/Textures/cc0/Lava004_1K_Color.jpg" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material index 471b437bd2..126e1a7fcb 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/002_ParallaxPdo.material @@ -5,18 +5,18 @@ "propertyLayoutVersion": 3, "properties": { "layer1_baseColor": { - "textureMap": "TestData/Textures/cc0/bark1col.jpg" + "textureMap": "TestData/Textures/cc0/bark1_col.jpg" }, "layer1_normal": { - "textureMap": "TestData/Textures/cc0/bark1norm.jpg" + "textureMap": "TestData/Textures/cc0/bark1_norm.jpg" }, "layer1_parallax": { "enable": true, "factor": 0.03999999910593033, - "textureMap": "TestData/Textures/cc0/bark1disp2.jpg" + "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, "layer1_roughness": { - "textureMap": "TestData/Textures/cc0/bark1roughness.jpg" + "textureMap": "TestData/Textures/cc0/bark1_roughness.jpg" }, "layer2_baseColor": { "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/bark1_col.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/bark1_col.jpg new file mode 100644 index 0000000000..0a4c5f380c --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/bark1_col.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd44119610135ca5674de7144647df6580d7ac3e03576e9a8e87e741548e7364 +size 2105853 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/bark1_disp.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/bark1_disp.jpg new file mode 100644 index 0000000000..57c74af488 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/bark1_disp.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4dbb74aac2450d6457bb02d36bd3d74e671c2dc7e938e090331151ecc52d545b +size 845683 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/bark1_norm.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/bark1_norm.jpg new file mode 100644 index 0000000000..41b1d6d30b --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/bark1_norm.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e69a3844c3a595245619a9dda4ed8981476a516ad3648a8b4dfb8151a68b0db5 +size 4439966 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/bark1_roughness.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/bark1_roughness.jpg new file mode 100644 index 0000000000..2e7ccba4e0 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/bark1_roughness.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8caa5961599624a6414d7277c389dd85b175b9587989b815ffd90aff8f62b6c +size 1747230 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/bark1col.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/bark1col.jpg deleted file mode 100644 index 944a968d5b..0000000000 --- a/Gems/Atom/TestData/TestData/Textures/cc0/bark1col.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:24f5c234f11a1b29de9000b5a7ba74262f1bc5ebd2227ca1e85a12fa0e8b5237 -size 8273450 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/bark1disp.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/bark1disp.jpg deleted file mode 100644 index c8a2a44e9b..0000000000 --- a/Gems/Atom/TestData/TestData/Textures/cc0/bark1disp.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0112ac235da74c60105b0e1a2da49c1e4ab7b89a60960a60cec54ad65db0b4b6 -size 4585685 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/bark1disp2.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/bark1disp2.jpg deleted file mode 100644 index f93d68141b..0000000000 --- a/Gems/Atom/TestData/TestData/Textures/cc0/bark1disp2.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6a202449e5d787e76d959b6bee7a4b60b3821441ac918944c21358742ed1c546 -size 878112 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/bark1norm.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/bark1norm.jpg deleted file mode 100644 index f68ed8b696..0000000000 --- a/Gems/Atom/TestData/TestData/Textures/cc0/bark1norm.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b0100b3c356d76ae1cb4c42bd4cc9c58ff359155aab6b9e3c1b205fe25956738 -size 16848020 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/bark1roughness.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/bark1roughness.jpg deleted file mode 100644 index f6e7acd7b6..0000000000 --- a/Gems/Atom/TestData/TestData/Textures/cc0/bark1roughness.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:11badf07e6a7d0501c915f669ff1b14c8744d427d47d06e2fdca46b8f86839c9 -size 4441528 From 0c10e769c5bd9c0058a51226782e687590a61e37 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sat, 17 Apr 2021 00:13:14 -0700 Subject: [PATCH 031/277] ATOM-14040 Add Support for Cavity Maps Before working on adding cavity map support, I am replacing the 010_SpecularOcclusion test case with maps that make it easier to distinguish what's going on. The brick map was just too noisy. This simpler tile map will make it easier to see if there are artifacts like banding that get introduced somewhere along the way. There are corresponding changes in AtomSampleViewer for the baseline screenshot. --- .../010_AmbientOcclusion.material | 14 ++++++++++---- .../Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg | 3 +++ .../TestData/Textures/cc0/Tiles009_1K_Color.jpg | 3 +++ .../Textures/cc0/Tiles009_1K_Displacement.jpg | 3 +++ .../TestData/Textures/cc0/Tiles009_1K_Normal.jpg | 3 +++ .../Textures/cc0/Tiles009_1K_Roughness.jpg | 3 +++ 6 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Color.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Displacement.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Normal.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Roughness.jpg diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material index 66843b3a2c..2c0b6767f3 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material @@ -1,15 +1,21 @@ { "description": "", - "materialType": "Materials\\Types\\StandardPBR.materialtype", + "materialType": "Materials/Types/StandardPBR.materialtype", + "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { "ambientOcclusion": { "enable": true, - "factor": 1.25, - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_ao.png" + "factor": 2.0, + "textureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg" }, "baseColor": { - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_bc.png" + "color": [ + 1.0, + 1.0, + 0.21223773062229157, + 1.0 + ] } } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg new file mode 100644 index 0000000000..3494ef8a6c --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de6b49c1c4965896a190ed5f40c7d91f9deb942d859fd96264828df768098a83 +size 45257 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Color.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Color.jpg new file mode 100644 index 0000000000..bf62c26631 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Color.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0172df6b91bb42bf6c41d18a6fdb7088397663d71f0c2d3ee504a4e91a7e5e98 +size 426462 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Displacement.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Displacement.jpg new file mode 100644 index 0000000000..49efd77e18 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Displacement.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9de0bb2f58936658e8bd3599e487cbd6af3394c772d3132cd77a73774cfb5994 +size 230692 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Normal.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Normal.jpg new file mode 100644 index 0000000000..c61e7f316b --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Normal.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48a8690b74141da4e7e06cd10b47f0eb787b5333a915cd1e048ab24bec485ad0 +size 759052 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Roughness.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Roughness.jpg new file mode 100644 index 0000000000..bef45f0995 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Roughness.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddd79ef9962100cd5a9eec686bdcfb98db19ab410329e50df53d6781f9d8b441 +size 421004 From 4e75a099b8e4a1658f04109d03df2068feeeaf5d Mon Sep 17 00:00:00 2001 From: karlberg Date: Sat, 17 Apr 2021 19:06:28 -0700 Subject: [PATCH 032/277] Initial Imgui debug display for stats, some hookup between entity replication and the spawnable code to make testing possible --- Gems/Multiplayer/Code/CMakeLists.txt | 38 ++++-- .../Source/AutoGen/AutoComponent_Source.jinja | 6 + .../Source/Imgui/MultiplayerImguiModule.cpp | 36 +++++ .../Source/Imgui/MultiplayerImguiModule.h | 31 +++++ .../Imgui/MultiplayerImguiSystemComponent.cpp | 123 ++++++++++++++++++ .../Imgui/MultiplayerImguiSystemComponent.h | 56 ++++++++ .../Source/MultiplayerSystemComponent.cpp | 18 ++- .../Code/Source/MultiplayerToolsModule.cpp | 2 +- .../EntityReplicationManager.cpp | 4 +- .../NetworkEntity/NetworkEntityManager.cpp | 12 +- .../NetworkSpawnableHolderComponent.cpp | 9 +- .../Code/multiplayer_imgui_files.cmake | 19 +++ 12 files changed, 328 insertions(+), 26 deletions(-) create mode 100644 Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp create mode 100644 Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h create mode 100644 Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp create mode 100644 Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h create mode 100644 Gems/Multiplayer/Code/multiplayer_imgui_files.cmake diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index d395938e8c..8cde5e01e2 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -18,16 +18,16 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE ${pal_source_dir} - Source AZ::AzNetworking + Source . + PUBLIC + Include BUILD_DEPENDENCIES PUBLIC AZ::AzCore AZ::AzFramework AZ::AzNetworking - Gem::CertificateManager - 3rdParty::AWSNativeSDK::Core AUTOGEN_RULES *.AutoPackets.xml,AutoPackets_Header.jinja,$path/$fileprefix.AutoPackets.h *.AutoPackets.xml,AutoPackets_Inline.jinja,$path/$fileprefix.AutoPackets.inl @@ -49,6 +49,8 @@ ly_add_target( PRIVATE Source . + PUBLIC + Include BUILD_DEPENDENCIES PRIVATE Gem::Multiplayer.Static @@ -56,7 +58,6 @@ ly_add_target( Gem::CertificateManager ) - if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( NAME Multiplayer.Tools MODULE @@ -77,10 +78,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) ) endif() -################################################################################ -# Tests -################################################################################ -if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) +if (PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME Multiplayer.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem @@ -92,6 +90,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ${pal_source_dir} Source . + PUBLIC + Include BUILD_DEPENDENCIES PRIVATE AZ::AzTest @@ -101,3 +101,25 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) NAME Gem::Multiplayer.Tests ) endif() + +ly_add_target( + NAME Multiplayer.Imgui ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} + NAMESPACE Gem + FILES_CMAKE + multiplayer_imgui_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Source + . + PUBLIC + Include + BUILD_DEPENDENCIES + PRIVATE + AZ::AzCore + AZ::AtomCore + AZ::AzFramework + AZ::AzNetworking + Gem::Atom_Feature_Common.Static + Gem::Multiplayer.Static + Gem::ImGui.Static +) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index aee15bc190..d6907876e1 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -1168,6 +1168,12 @@ namespace {{ Component.attrib['Namespace'] }} void {{ ComponentBaseName }}::Init() { + if (m_netBindComponent == nullptr) + { + AZLOG_ERROR("NetBindComponent is null, ensure NetworkAttach is called prior to activating a networked entity"); + return; + } + {{ DefineComponentServiceProxyGrabs(Component, ClassType, ComponentName)|indent(8) }} {% if ComponentDerived %} OnInit(); diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp new file mode 100644 index 0000000000..1b59a704dc --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp @@ -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. +* +*/ + +#include +#include +#include + +namespace Multiplayer +{ + MultiplayerImguiModule::MultiplayerImguiModule() + : AZ::Module() + { + m_descriptors.insert(m_descriptors.end(), { + MultiplayerImguiSystemComponent::CreateDescriptor(), + }); + } + + AZ::ComponentTypeList MultiplayerImguiModule::GetRequiredSystemComponents() const + { + return AZ::ComponentTypeList + { + azrtti_typeid(), + }; + } +} + +AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Imgui, Multiplayer::MultiplayerImguiModule); diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h new file mode 100644 index 0000000000..ce0ed244be --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h @@ -0,0 +1,31 @@ +/* +* 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 MultiplayerImguiModule + : public AZ::Module + { + public: + AZ_RTTI(MultiplayerImguiModule, "{9E1460FA-4513-4B5E-86B4-9DD8ADEFA714}", AZ::Module); + AZ_CLASS_ALLOCATOR(MultiplayerImguiModule, AZ::SystemAllocator, 0); + + MultiplayerImguiModule(); + ~MultiplayerImguiModule() override = default; + + AZ::ComponentTypeList GetRequiredSystemComponents() const override; + }; +} diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp new file mode 100644 index 0000000000..a53dd2800f --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp @@ -0,0 +1,123 @@ +/* +* 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 + +namespace Multiplayer +{ + void MultiplayerImguiSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1); + } + } + + void MultiplayerImguiSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("MultiplayerImguiSystemComponent")); + } + + void MultiplayerImguiSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) + { + ; + } + + void MultiplayerImguiSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile) + { + incompatbile.push_back(AZ_CRC_CE("MultiplayerImguiSystemComponent")); + } + + void MultiplayerImguiSystemComponent::Activate() + { +#ifdef IMGUI_ENABLED + ImGui::ImGuiUpdateListenerBus::Handler::BusConnect(); +#endif + } + + void MultiplayerImguiSystemComponent::Deactivate() + { +#ifdef IMGUI_ENABLED + ImGui::ImGuiUpdateListenerBus::Handler::BusDisconnect(); +#endif + } + +#ifdef IMGUI_ENABLED + void MultiplayerImguiSystemComponent::OnImGuiMainMenuUpdate() + { + if (ImGui::BeginMenu("Multiplayer")) + { + //{ + // static int lossPercent{ 0 }; + // lossPercent = static_cast(net_UdpDebugLossPercent); + // if (ImGui::SliderInt("UDP Loss Percent", &lossPercent, 0, 100)) + // { + // net_UdpDebugLossPercent = lossPercent; + // m_ClientAgent.UpdateConnectionCvars(net_UdpDebugLossPercent); + // } + //} + // + //{ + // static int latency{ 0 }; + // latency = static_cast(net_UdpDebugLatencyMs); + // if (ImGui::SliderInt("UDP Latency Ms", &latency, 0, 3000)) + // { + // net_UdpDebugLatencyMs = latency; + // m_ClientAgent.UpdateConnectionCvars(net_UdpDebugLatencyMs); + // } + //} + // + //{ + // static int variance{ 0 }; + // variance = static_cast(net_UdpDebugVarianceMs); + // if (ImGui::SliderInt("UDP Variance Ms", &variance, 0, 1000)) + // { + // net_UdpDebugVarianceMs = variance; + // m_ClientAgent.UpdateConnectionCvars(net_UdpDebugVarianceMs); + // } + //} + + ImGui::Checkbox("Multiplayer Stats", &m_displayStats); + ImGui::EndMenu(); + } + } + + void MultiplayerImguiSystemComponent::OnImGuiUpdate() + { + if (m_displayStats) + { + if (ImGui::Begin("Multiplayer Stats", &m_displayStats, ImGuiWindowFlags_HorizontalScrollbar)) + { + IMultiplayer* multiplayer = AZ::Interface::Get(); + Multiplayer::MultiplayerStats& stats = multiplayer->GetStats(); + ImGui::Text("Multiplayer operating in %s mode", GetEnumString(multiplayer->GetAgentType())); + ImGui::Text("Total networked entities: %llu", aznumeric_cast(stats.m_entityCount)); + ImGui::Text("Total client connections: %llu", aznumeric_cast(stats.m_clientConnectionCount)); + ImGui::Text("Total server connections: %llu", aznumeric_cast(stats.m_serverConnectionCount)); + ImGui::Text("Total property updates sent: %llu", aznumeric_cast(stats.m_propertyUpdatesSent)); + ImGui::Text("Total property updates sent bytes: %llu", aznumeric_cast(stats.m_propertyUpdatesSentBytes)); + ImGui::Text("Total property updates received: %llu", aznumeric_cast(stats.m_propertyUpdatesRecv)); + ImGui::Text("Total property updates received bytes: %llu", aznumeric_cast(stats.m_propertyUpdatesRecvBytes)); + ImGui::Text("Total RPCs sent: %llu", aznumeric_cast(stats.m_rpcsSent)); + ImGui::Text("Total RPCs sent bytes: %llu", aznumeric_cast(stats.m_rpcsSentBytes)); + ImGui::Text("Total RPCs received: %llu", aznumeric_cast(stats.m_rpcsRecv)); + ImGui::Text("Total RPCs received bytes: %llu", aznumeric_cast(stats.m_rpcsRecvBytes)); + } + ImGui::End(); + } + } +#endif +} diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h new file mode 100644 index 0000000000..1650d62264 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h @@ -0,0 +1,56 @@ +/* +* 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 + +#ifdef IMGUI_ENABLED +# include +# include +#endif + +namespace Multiplayer +{ + class MultiplayerImguiSystemComponent final + : public AZ::Component +#ifdef IMGUI_ENABLED + , public ImGui::ImGuiUpdateListenerBus::Handler +#endif + { + public: + AZ_COMPONENT(MultiplayerImguiSystemComponent, "{060BF3F1-0BFE-4FCE-9C3C-EE991F0DA581}"); + + static void Reflect(AZ::ReflectContext* context); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile); + + ~MultiplayerImguiSystemComponent() override = default; + + //! AZ::Component overrides + //! @{ + void Activate() override; + void Deactivate() override; + //! @} + +#ifdef IMGUI_ENABLED + //! ImGui::ImGuiUpdateListenerBus overrides + //! @{ + void OnImGuiMainMenuUpdate() override; + void OnImGuiUpdate() override; + //! @} +#endif + private: + bool m_displayStats = false; + }; +} diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 70323d7de3..e40e9e9d66 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -133,23 +133,33 @@ namespace Multiplayer // 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(); + stats.m_serverConnectionCount = 0; + stats.m_clientConnectionCount = 0; + // Send out the game state update to all connections { - auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection) + auto sendNetworkUpdates = [serverGameTimeMs, &stats](IConnection& connection) { if (connection.GetUserData() != nullptr) { IConnectionData* connectionData = reinterpret_cast(connection.GetUserData()); connectionData->Update(serverGameTimeMs); + if (connectionData->GetConnectionDataType() == ConnectionDataType::ServerToClient) + { + stats.m_clientConnectionCount++; + } + else + { + stats.m_serverConnectionCount++; + } } }; m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates); } - MultiplayerStats& stats = GetStats(); - stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount(); - MultiplayerPackets::SyncConsole packet; AZ::ThreadSafeDeque::DequeType cvarUpdates; m_cvarCommands.Swap(cvarUpdates); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp index 71b04585ad..4c57924eb4 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp @@ -62,4 +62,4 @@ namespace Multiplayer } } // namespace Multiplayer -AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer2_Tools, Multiplayer::MultiplayerToolsModule); +AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Tools, Multiplayer::MultiplayerToolsModule); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index a3bb2029d2..2d2c668497 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -9,7 +9,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ - +#pragma optimize("", off) #include #include #include @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index c06d7bc8f9..257173b347 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -39,12 +39,6 @@ namespace Multiplayer { AZ::Interface::Register(this); AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); - 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() @@ -58,6 +52,12 @@ namespace Multiplayer m_hostId = hostId; m_entityDomain = AZStd::move(entityDomain); m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true); + if (AZ::Interface::Get() != nullptr) + { + // Null guard needed for unit tests + AZ::Interface::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler); + AZ::Interface::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler); + } } NetworkEntityTracker* NetworkEntityManager::GetNetworkEntityTracker() diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp index 3c3d1f079d..6087376b30 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp @@ -26,6 +26,10 @@ namespace Multiplayer } } + NetworkSpawnableHolderComponent::NetworkSpawnableHolderComponent() + { + } + void NetworkSpawnableHolderComponent::Activate() { } @@ -43,9 +47,4 @@ namespace Multiplayer { return m_networkSpawnableAsset; } - - NetworkSpawnableHolderComponent::NetworkSpawnableHolderComponent() - { - } - } diff --git a/Gems/Multiplayer/Code/multiplayer_imgui_files.cmake b/Gems/Multiplayer/Code/multiplayer_imgui_files.cmake new file mode 100644 index 0000000000..57623772d2 --- /dev/null +++ b/Gems/Multiplayer/Code/multiplayer_imgui_files.cmake @@ -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. +# + +set(FILES + Source/Multiplayer_precompiled.cpp + Source/Multiplayer_precompiled.h + Source/Imgui/MultiplayerImguiModule.cpp + Source/Imgui/MultiplayerImguiModule.h + Source/Imgui/MultiplayerImguiSystemComponent.cpp + Source/Imgui/MultiplayerImguiSystemComponent.h +) From 8fead27c45395924ff5dfc3775810bbaa078058e Mon Sep 17 00:00:00 2001 From: guthadam Date: Sun, 18 Apr 2021 12:12:32 -0500 Subject: [PATCH 033/277] ATOM-13950 Material Editor: Removing auto select option from lighting and model presets Remove option from presets Updated code to select current default options Will data drive default options with editor settings or settings registry in upcoming tasks https://jira.agscollab.com/browse/ATOM-13950 --- .../greenwich_park_02.lightingconfig.json | 2 -- .../Include/Atom/Feature/Utils/LightingPreset.h | 1 - .../Code/Include/Atom/Feature/Utils/ModelPreset.h | 1 - .../Code/Source/Utils/EditorLightingPreset.cpp | 1 - .../Common/Code/Source/Utils/EditorModelPreset.cpp | 1 - .../Common/Code/Source/Utils/LightingPreset.cpp | 4 +--- .../Common/Code/Source/Utils/ModelPreset.cpp | 4 +--- .../urban_street_02.lightingpreset.azasset | 1 - .../_TEMPLATE_.lightingconfig.json.template | 2 -- .../neutral_urban.lightingpreset.azasset | 1 - .../ViewportModels/Shaderball.modelpreset.azasset | 1 - .../Source/Viewport/MaterialViewportComponent.cpp | 13 ++++++++++--- .../EnvHDRi/photo_studio_01.lightingconfig.json | 2 -- 13 files changed, 12 insertions(+), 22 deletions(-) diff --git a/AutomatedTesting/LightingPresets/greenwich_park_02.lightingconfig.json b/AutomatedTesting/LightingPresets/greenwich_park_02.lightingconfig.json index 1646dd18a2..bfb92bbb6f 100644 --- a/AutomatedTesting/LightingPresets/greenwich_park_02.lightingconfig.json +++ b/AutomatedTesting/LightingPresets/greenwich_park_02.lightingconfig.json @@ -1,7 +1,6 @@ { "configurations": [ { - "autoSelect": false, "displayName": "Greenwich Park 02", "skyboxImageAsset": { "assetId": { @@ -64,7 +63,6 @@ "shadowCatcherOpacity": 0.20000000298023225 }, { - "autoSelect": false, "displayName": "Greenwich Park 02 (Alt)", "skyboxImageAsset": { "assetId": { diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h index 1c220e0d8d..f1d8337a35 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h @@ -78,7 +78,6 @@ namespace AZ AZ_CLASS_ALLOCATOR(LightingPreset, AZ::SystemAllocator, 0); static void Reflect(AZ::ReflectContext* context); - bool m_autoSelect = false; AZStd::string m_displayName; AZ::Data::Asset m_iblDiffuseImageAsset; AZ::Data::Asset m_iblSpecularImageAsset; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ModelPreset.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ModelPreset.h index 896d6fb78f..9ca8c13859 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ModelPreset.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/ModelPreset.h @@ -32,7 +32,6 @@ namespace AZ AZ_CLASS_ALLOCATOR(ModelPreset, AZ::SystemAllocator, 0); static void Reflect(AZ::ReflectContext* context); - bool m_autoSelect = false; AZStd::string m_displayName; AZ::Data::Asset m_modelAsset; AZ::Data::Asset m_previewImageAsset; diff --git a/Gems/Atom/Feature/Common/Code/Source/Utils/EditorLightingPreset.cpp b/Gems/Atom/Feature/Common/Code/Source/Utils/EditorLightingPreset.cpp index e7f9c8b09f..1da9463bd8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Utils/EditorLightingPreset.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Utils/EditorLightingPreset.cpp @@ -112,7 +112,6 @@ namespace AZ ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::Default, &LightingPreset::m_displayName, "Display Name", "Identifier used for display and selection") - ->DataElement(AZ::Edit::UIHandlers::Default, &LightingPreset::m_autoSelect, "Auto Select", "When true, the configuration is automatically selected when loaded") ->DataElement(AZ::Edit::UIHandlers::Default, &LightingPreset::m_iblDiffuseImageAsset, "IBL Diffuse Image Asset", "IBL diffuse image asset reference") ->DataElement(AZ::Edit::UIHandlers::Default, &LightingPreset::m_iblSpecularImageAsset, "IBL Specular Image Asset", "IBL specular image asset reference") ->DataElement(AZ::Edit::UIHandlers::Default, &LightingPreset::m_skyboxImageAsset, "Skybox Image Asset", "Skybox image asset reference") diff --git a/Gems/Atom/Feature/Common/Code/Source/Utils/EditorModelPreset.cpp b/Gems/Atom/Feature/Common/Code/Source/Utils/EditorModelPreset.cpp index b8b0b610f3..bed320c45d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Utils/EditorModelPreset.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Utils/EditorModelPreset.cpp @@ -32,7 +32,6 @@ namespace AZ ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::Default, &ModelPreset::m_displayName, "Display Name", "Identifier used for display and selection") - ->DataElement(AZ::Edit::UIHandlers::Default, &ModelPreset::m_autoSelect, "Auto Select", "When true, the configuration is automatically selected when loaded") ->DataElement(AZ::Edit::UIHandlers::Default, &ModelPreset::m_modelAsset, "Model Asset", "Model asset reference") ->DataElement(AZ::Edit::UIHandlers::Default, &ModelPreset::m_previewImageAsset, "Preview Image Asset", "Preview image asset reference") ; diff --git a/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp b/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp index 837a725a9f..77924b87a3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp @@ -105,8 +105,7 @@ namespace AZ serializeContext->RegisterGenericType>(); serializeContext->Class() - ->Version(4) - ->Field("autoSelect", &LightingPreset::m_autoSelect) + ->Version(5) ->Field("displayName", &LightingPreset::m_displayName) ->Field("iblDiffuseImageAsset", &LightingPreset::m_iblDiffuseImageAsset) ->Field("iblSpecularImageAsset", &LightingPreset::m_iblSpecularImageAsset) @@ -128,7 +127,6 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Module, "render") ->Constructor() ->Constructor() - ->Property("autoSelect", BehaviorValueProperty(&LightingPreset::m_autoSelect)) ->Property("displayName", BehaviorValueProperty(&LightingPreset::m_displayName)) ->Property("alternateSkyboxImageAsset", BehaviorValueProperty(&LightingPreset::m_alternateSkyboxImageAsset)) ->Property("skyboxImageAsset", BehaviorValueProperty(&LightingPreset::m_skyboxImageAsset)) diff --git a/Gems/Atom/Feature/Common/Code/Source/Utils/ModelPreset.cpp b/Gems/Atom/Feature/Common/Code/Source/Utils/ModelPreset.cpp index e93bfa527a..2795617c18 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Utils/ModelPreset.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Utils/ModelPreset.cpp @@ -25,8 +25,7 @@ namespace AZ if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(2) - ->Field("autoSelect", &ModelPreset::m_autoSelect) + ->Version(3) ->Field("displayName", &ModelPreset::m_displayName) ->Field("modelAsset", &ModelPreset::m_modelAsset) ->Field("previewImageAsset", &ModelPreset::m_previewImageAsset) @@ -41,7 +40,6 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Module, "render") ->Constructor() ->Constructor() - ->Property("autoSelect", BehaviorValueProperty(&ModelPreset::m_autoSelect)) ->Property("displayName", BehaviorValueProperty(&ModelPreset::m_displayName)) ->Property("modelAsset", BehaviorValueProperty(&ModelPreset::m_modelAsset)) ->Property("previewImageAsset", BehaviorValueProperty(&ModelPreset::m_previewImageAsset)) diff --git a/Gems/Atom/TestData/TestData/LightingPresets/urban_street_02.lightingpreset.azasset b/Gems/Atom/TestData/TestData/LightingPresets/urban_street_02.lightingpreset.azasset index d0a290649b..a676d5fba6 100644 --- a/Gems/Atom/TestData/TestData/LightingPresets/urban_street_02.lightingpreset.azasset +++ b/Gems/Atom/TestData/TestData/LightingPresets/urban_street_02.lightingpreset.azasset @@ -3,7 +3,6 @@ "Version": 1, "ClassName": "AZ::Render::LightingPreset", "ClassData": { - "autoSelect": false, "displayName": "Urban Street 02", "skyboxImageAsset": { "assetId": { diff --git a/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/LightingPresets/_TEMPLATE_.lightingconfig.json.template b/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/LightingPresets/_TEMPLATE_.lightingconfig.json.template index 7cfa7edbc3..6d87c5eb7b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/LightingPresets/_TEMPLATE_.lightingconfig.json.template +++ b/Gems/Atom/Tools/MaterialEditor/Assets/MaterialEditor/LightingPresets/_TEMPLATE_.lightingconfig.json.template @@ -2,7 +2,6 @@ "configurations": [ { "displayName": "Substance: