diff --git a/Code/CryEngine/CryCommon/CREVolumeObject.h b/Code/CryEngine/CryCommon/CREVolumeObject.h index d84c7b3e50..2137053a8e 100644 --- a/Code/CryEngine/CryCommon/CREVolumeObject.h +++ b/Code/CryEngine/CryCommon/CREVolumeObject.h @@ -55,7 +55,7 @@ public: Matrix34 m_matInv; Vec3 m_eyePosInWS; Vec3 m_eyePosInOS; - Plane m_volumeTraceStartPlane; + Plane_tpl m_volumeTraceStartPlane; AABB m_renderBoundsOS; bool m_viewerInsideVolume; bool m_nearPlaneIntersectsVolume; diff --git a/Code/CryEngine/CryCommon/CREWaterOcean.h b/Code/CryEngine/CryCommon/CREWaterOcean.h index 784588309f..e8ca310d41 100644 --- a/Code/CryEngine/CryCommon/CREWaterOcean.h +++ b/Code/CryEngine/CryCommon/CREWaterOcean.h @@ -25,7 +25,7 @@ public: virtual void mfPrepare(bool bCheckOverflow); virtual bool mfDraw(CShader* ef, SShaderPass* sfm); - virtual void mfGetPlane(Plane& pl); + virtual void mfGetPlane(Plane_tpl& pl); virtual void Create(uint32 nVerticesCount, SVF_P3F_C4B_T2F* pVertices, uint32 nIndicesCount, const void* pIndices, uint32 nIndexSizeof); void ReleaseOcean(); diff --git a/Code/CryEngine/CryCommon/CREWaterVolume.h b/Code/CryEngine/CryCommon/CREWaterVolume.h index 3e7a0636e6..89102e3097 100644 --- a/Code/CryEngine/CryCommon/CREWaterVolume.h +++ b/Code/CryEngine/CryCommon/CREWaterVolume.h @@ -27,7 +27,7 @@ public: virtual ~CREWaterVolume(); virtual void mfPrepare(bool bCheckOverflow); virtual bool mfDraw(CShader* ef, SShaderPass* sfm); - virtual void mfGetPlane(Plane& pl); + virtual void mfGetPlane(Plane_tpl& pl); virtual void mfCenter(Vec3& vCenter, CRenderObject* pObj); virtual void GetMemoryUsage(ICrySizer* pSizer) const @@ -69,7 +69,7 @@ public: Vec3 m_center; AABB m_WSBBox; - Plane m_fogPlane; + Plane_tpl m_fogPlane; float m_fogDensity; Vec3 m_fogColor; bool m_fogColorAffectedBySun; diff --git a/Code/CryEngine/CryCommon/Cry_Camera.h b/Code/CryEngine/CryCommon/Cry_Camera.h index a744d7335f..56a764d897 100644 --- a/Code/CryEngine/CryCommon/Cry_Camera.h +++ b/Code/CryEngine/CryCommon/Cry_Camera.h @@ -594,7 +594,7 @@ public: ILINE const Vec3& GetFPVertex(int nId) const; //get far-plane vertices ILINE const Vec3& GetPPVertex(int nId) const; //get projection-plane vertices - ILINE const Plane* GetFrustumPlane(int numplane) const { return &m_fp[numplane]; } + ILINE const Plane_tpl* GetFrustumPlane(int numplane) const { return &m_fp[numplane]; } ////////////////////////////////////////////////////////////////////////// // Z-Buffer ranges. @@ -720,7 +720,7 @@ private: Vec3 m_cltn, m_crtn, m_clbn, m_crbn; //this are the 4 vertices of the near-plane in cam-space Vec3 m_cltf, m_crtf, m_clbf, m_crbf; //this are the 4 vertices of the farclip-plane in cam-space - Plane m_fp [FRUSTUM_PLANES]; // + Plane_tpl m_fp [FRUSTUM_PLANES]; // uint32 m_idx1[FRUSTUM_PLANES], m_idy1[FRUSTUM_PLANES], m_idz1[FRUSTUM_PLANES]; // uint32 m_idx2[FRUSTUM_PLANES], m_idy2[FRUSTUM_PLANES], m_idz2[FRUSTUM_PLANES]; // @@ -742,7 +742,7 @@ public: m_crtp = arrvVerts[2]; m_crbp = arrvVerts[3]; } - inline void SetFrustumPlane(int i, const Plane& plane) + inline void SetFrustumPlane(int i, const Plane_tpl& plane) { m_fp[i] = plane; //do not break strict aliasing rules, use union instead of reinterpret_casts @@ -1180,12 +1180,12 @@ inline void CCamera::UpdateFrustum() //------------------------------------------------------------------------------- //--- calculate the six frustum-planes using the frustum edges in world-space --- //------------------------------------------------------------------------------- - m_fp[FR_PLANE_NEAR ] = Plane::CreatePlane(m_crtn + GetPosition(), m_cltn + GetPosition(), m_crbn + GetPosition()); - m_fp[FR_PLANE_RIGHT ] = Plane::CreatePlane(m_crbf + GetPosition(), m_crtf + GetPosition(), GetPosition()); - m_fp[FR_PLANE_LEFT ] = Plane::CreatePlane(m_cltf + GetPosition(), m_clbf + GetPosition(), GetPosition()); - m_fp[FR_PLANE_TOP ] = Plane::CreatePlane(m_crtf + GetPosition(), m_cltf + GetPosition(), GetPosition()); - m_fp[FR_PLANE_BOTTOM] = Plane::CreatePlane(m_clbf + GetPosition(), m_crbf + GetPosition(), GetPosition()); - m_fp[FR_PLANE_FAR ] = Plane::CreatePlane(m_crtf + GetPosition(), m_crbf + GetPosition(), m_cltf + GetPosition()); //clip-plane + m_fp[FR_PLANE_NEAR ] = Plane_tpl::CreatePlane(m_crtn + GetPosition(), m_cltn + GetPosition(), m_crbn + GetPosition()); + m_fp[FR_PLANE_RIGHT ] = Plane_tpl::CreatePlane(m_crbf + GetPosition(), m_crtf + GetPosition(), GetPosition()); + m_fp[FR_PLANE_LEFT ] = Plane_tpl::CreatePlane(m_cltf + GetPosition(), m_clbf + GetPosition(), GetPosition()); + m_fp[FR_PLANE_TOP ] = Plane_tpl::CreatePlane(m_crtf + GetPosition(), m_cltf + GetPosition(), GetPosition()); + m_fp[FR_PLANE_BOTTOM] = Plane_tpl::CreatePlane(m_clbf + GetPosition(), m_crbf + GetPosition(), GetPosition()); + m_fp[FR_PLANE_FAR ] = Plane_tpl::CreatePlane(m_crtf + GetPosition(), m_crbf + GetPosition(), m_cltf + GetPosition()); //clip-plane uint32 rh = m_Matrix.IsOrthonormalRH(); if (rh == 0) diff --git a/Code/CryEngine/CryCommon/Cry_GeoDistance.h b/Code/CryEngine/CryCommon/Cry_GeoDistance.h index 92c1f65d87..47794c7671 100644 --- a/Code/CryEngine/CryCommon/Cry_GeoDistance.h +++ b/Code/CryEngine/CryCommon/Cry_GeoDistance.h @@ -1168,17 +1168,6 @@ namespace Distance { return fDist2; } - // Compute both the min and max distances of a box to a plane, in the sense of the plane normal. - inline void AABB_Plane(float* pfDistMin, float* pfDistMax, const AABB& box, const Plane& pl) - { - float fDist0 = pl.DistFromPlane(box.min), - fDistX = (box.max.x - box.min.x) * pl.n.x, - fDistY = (box.max.y - box.min.y) * pl.n.y, - fDistZ = (box.max.z - box.min.z) * pl.n.z; - *pfDistMin = fDist0 + min(fDistX, 0.f) + min(fDistY, 0.f) + min(fDistZ, 0.f); - *pfDistMax = fDist0 + max(fDistX, 0.f) + max(fDistY, 0.f) + max(fDistZ, 0.f); - } - //---------------------------------------------------------------------------------- // Distance: Sphere_Triangle //---------------------------------------------------------------------------------- diff --git a/Code/CryEngine/CryCommon/Cry_GeoIntersect.h b/Code/CryEngine/CryCommon/Cry_GeoIntersect.h index c2f556c4b7..89f6d8ebaf 100644 --- a/Code/CryEngine/CryCommon/Cry_GeoIntersect.h +++ b/Code/CryEngine/CryCommon/Cry_GeoIntersect.h @@ -22,7 +22,7 @@ #include namespace Intersect { - inline bool Ray_Plane(const Ray& ray, const Plane& plane, Vec3& output, bool bSingleSidePlane = true) + inline bool Ray_Plane(const Ray& ray, const Plane_tpl& plane, Vec3& output, bool bSingleSidePlane = true) { float cosine = plane.n | ray.direction; @@ -49,7 +49,7 @@ namespace Intersect { return true; //intersection occurred } - inline bool Line_Plane(const Line& line, const Plane& plane, Vec3& output, bool bSingleSidePlane = true) + inline bool Line_Plane(const Line& line, const Plane_tpl& plane, Vec3& output, bool bSingleSidePlane = true) { float cosine = plane.n | line.direction; diff --git a/Code/CryEngine/CryCommon/Cry_GeoOverlap.h b/Code/CryEngine/CryCommon/Cry_GeoOverlap.h index 3f2c7081d7..ab560b7518 100644 --- a/Code/CryEngine/CryCommon/Cry_GeoOverlap.h +++ b/Code/CryEngine/CryCommon/Cry_GeoOverlap.h @@ -945,29 +945,6 @@ namespace Overlap { } } - - /*! - * - * we use the SEPARATING-AXIS-TEST for OBB/Plane overlap. - * - * Example: - * bool result=Overlap::OBB_Plane( pos,obb, plane ); - * - */ - inline bool OBB_Plane(const Vec3& pos, const OBB& obb, const Plane& plane) - { - //the new center-position in world-space - Vec3 p = obb.m33 * obb.c + pos; - //extract the orientation-vectors from the columns of the 3x3 matrix - //and scale them by the half-lengths - Vec3 ax = Vec3(obb.m33.m00, obb.m33.m10, obb.m33.m20) * obb.h.x; - Vec3 ay = Vec3(obb.m33.m01, obb.m33.m11, obb.m33.m21) * obb.h.y; - Vec3 az = Vec3(obb.m33.m02, obb.m33.m12, obb.m33.m22) * obb.h.z; - //check OBB against Plane, using the plane-normal as separating axis - return fabsf(plane | p) < (fabsf(plane.n | ax) + fabsf(plane.n | ay) + fabsf(plane.n | az)); - } - - /*! * * we use the SEPARATING AXIS TEST to check if a triangle and AABB overlap. @@ -1214,7 +1191,7 @@ namespace Overlap { //test if the box intersects the plane of the triangle //compute plane equation of triangle: normal*x+d=0 - Plane plane = Plane::CreatePlane((e0 % e1), v0); + Plane_tpl plane = Plane_tpl::CreatePlane((e0 % e1), v0); Vec3 vmin, vmax; if (plane.n.x > 0.0f) @@ -1505,7 +1482,7 @@ namespace Overlap { //test if the box overlaps the plane of the triangle //compute plane equation of triangle: normal*x+d=0 - Plane plane = Plane::CreatePlane((e0 % e1), v0); + Plane_tpl plane = Plane_tpl::CreatePlane((e0 % e1), v0); Vec3 vmin, vmax; if (plane.n.x > 0.0f) diff --git a/Code/CryEngine/CryCommon/I3DEngine.h b/Code/CryEngine/CryCommon/I3DEngine.h index 8d3801ecb4..883b0a6d3b 100644 --- a/Code/CryEngine/CryCommon/I3DEngine.h +++ b/Code/CryEngine/CryCommon/I3DEngine.h @@ -458,7 +458,7 @@ struct SClipVolumeBlendInfo { static const int BlendPlaneCount = 2; - Plane blendPlanes[BlendPlaneCount]; + Plane_tpl blendPlanes[BlendPlaneCount]; struct IClipVolume* blendVolumes[BlendPlaneCount]; }; diff --git a/Code/CryEngine/CryCommon/IEntityRenderState.h b/Code/CryEngine/CryCommon/IEntityRenderState.h index 912f4632ab..92ff354eff 100644 --- a/Code/CryEngine/CryCommon/IEntityRenderState.h +++ b/Code/CryEngine/CryCommon/IEntityRenderState.h @@ -731,8 +731,8 @@ struct IWaterVolumeRenderNode virtual void SetAuxPhysParams(pe_params_area*) = 0; virtual void CreateOcean(uint64 volumeID, /* TBD */ bool keepSerializationParams = false) = 0; - virtual void CreateArea(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, const Vec2& surfUVScale, const Plane& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; - virtual void CreateRiver(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, float uTexCoordBegin, float uTexCoordEnd, const Vec2& surfUVScale, const Plane& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; + virtual void CreateArea(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, const Vec2& surfUVScale, const Plane_tpl& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; + virtual void CreateRiver(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, float uTexCoordBegin, float uTexCoordEnd, const Vec2& surfUVScale, const Plane_tpl& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; virtual void CreateRiver(uint64 volumeID, const AZStd::vector& verticies, const AZ::Transform& transform, float uTexCoordBegin, float uTexCoordEnd, const AZ::Vector2& surfUVScale, const AZ::Plane& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; virtual void SetAreaPhysicsArea(const Vec3* pVertices, unsigned int numVertices, bool keepSerializationParams = false) = 0; diff --git a/Code/CryEngine/CryCommon/RendElement.h b/Code/CryEngine/CryCommon/RendElement.h index c3dc1c080d..41bcf2bf67 100644 --- a/Code/CryEngine/CryCommon/RendElement.h +++ b/Code/CryEngine/CryCommon/RendElement.h @@ -119,7 +119,7 @@ struct IRenderElement virtual void mfCenter(Vec3& centr, CRenderObject* pObj) = 0; virtual void mfGetBBox(Vec3& vMins, Vec3& vMaxs) = 0; virtual void mfReset() = 0; - virtual void mfGetPlane(Plane& pl) = 0; + virtual void mfGetPlane(Plane_tpl& pl) = 0; virtual void mfExport(struct SShaderSerializeContext& SC) = 0; virtual void mfImport(struct SShaderSerializeContext& SC, uint32& offset) = 0; virtual void mfPrecache(const SShaderItem& SH) = 0; @@ -265,7 +265,7 @@ public: void mfPrecache([[maybe_unused]] const SShaderItem& SH) override {} void mfExport([[maybe_unused]] struct SShaderSerializeContext& SC) override { CryFatalError("mfExport has not been implemented for this render element type"); } void mfImport([[maybe_unused]] struct SShaderSerializeContext& SC, [[maybe_unused]] uint32& offset) override { CryFatalError("mfImport has not been implemented for this render element type"); } - void mfGetPlane(Plane& pl) override; + void mfGetPlane(Plane_tpl& pl) override; void* mfGetPointer([[maybe_unused]] ESrcPointer ePT, [[maybe_unused]] int* Stride, [[maybe_unused]] EParamType Type, [[maybe_unused]] ESrcPointer Dst, [[maybe_unused]] int Flags) override { return nullptr; } uint16 mfGetFlags() override { return m_Flags; } diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index e118104687..f2e8f1eb4a 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -157,9 +157,6 @@ AZ_POP_DISABLE_WARNING #include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h" -// LmbrCentral -#include - // AWSNativeSDK #include #include diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.cpp new file mode 100644 index 0000000000..138d619d97 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.cpp @@ -0,0 +1,355 @@ +/* +* 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 "AttachmentComponent.h" +#include +#include +#include +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + /// Behavior Context handler for AttachmentComponentNotificationBus + class BehaviorAttachmentComponentNotificationBusHandler : public LmbrCentral::AttachmentComponentNotificationBus::Handler, + public AZ::BehaviorEBusHandler + { + public: + AZ_EBUS_BEHAVIOR_BINDER( + BehaviorAttachmentComponentNotificationBusHandler, "{636B95A0-5C7D-4EE7-8645-955665315451}", AZ::SystemAllocator, + OnAttached, OnDetached); + + void OnAttached(AZ::EntityId id) override + { + Call(FN_OnAttached, id); + } + + void OnDetached(AZ::EntityId id) override + { + Call(FN_OnDetached, id); + } + }; + + void AttachmentConfiguration::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1) + ->Field("Target ID", &AttachmentConfiguration::m_targetId) + ->Field("Target Bone Name", &AttachmentConfiguration::m_targetBoneName) + ->Field("Target Offset", &AttachmentConfiguration::m_targetOffset) + ->Field("Attached Initially", &AttachmentConfiguration::m_attachedInitially) + ->Field("Scale Source", &AttachmentConfiguration::m_scaleSource); + } + AZ::BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->EBus("AttachmentComponentRequestBus") + ->Event("Attach", &LmbrCentral::AttachmentComponentRequestBus::Events::Attach) + ->Event("Detach", &LmbrCentral::AttachmentComponentRequestBus::Events::Detach) + ->Event("SetAttachmentOffset", &LmbrCentral::AttachmentComponentRequestBus::Events::SetAttachmentOffset); + + behaviorContext->EBus("AttachmentComponentNotificationBus") + ->Handler(); + } + } + + void AttachmentComponent::Reflect(AZ::ReflectContext* context) + { + AttachmentConfiguration::Reflect(context); + + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class()->Version(1)->Field( + "Configuration", &AttachmentComponent::m_initialConfiguration); + } + } + + //========================================================================= + // BoneFollower + //========================================================================= + + void BoneFollower::Activate(AZ::Entity* owner, const AttachmentConfiguration& configuration, bool targetCanAnimate) + { + AZ_Assert(owner, "owner is required"); + AZ_Assert(!m_ownerId.IsValid(), "BoneFollower is already Activated"); + + m_ownerId = owner->GetId(); + m_targetCanAnimate = targetCanAnimate; + m_isUpdatingOwnerTransform = false; + m_scaleSource = configuration.m_scaleSource; + + m_cachedOwnerTransform = AZ::Transform::CreateIdentity(); + EBUS_EVENT_ID_RESULT(m_cachedOwnerTransform, m_ownerId, AZ::TransformBus, GetWorldTM); + + if (configuration.m_attachedInitially) + { + Attach(configuration.m_targetId, configuration.m_targetBoneName.c_str(), configuration.m_targetOffset); + } + + LmbrCentral::AttachmentComponentRequestBus::Handler::BusConnect(m_ownerId); + } + + void BoneFollower::Deactivate() + { + AZ_Assert(m_ownerId.IsValid(), "BoneFollower was never Activated"); + + LmbrCentral::AttachmentComponentRequestBus::Handler::BusDisconnect(); + Detach(); + m_ownerId.SetInvalid(); + } + + AZ::EntityId BoneFollower::GetTargetEntityId() + { + return m_targetId; + } + + AZ::Transform BoneFollower::GetOffset() + { + return m_targetOffset; + } + + void BoneFollower::Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) + { + AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use.") + + // safe to try and detach, even if we weren't attached + Detach(); + + if (!targetId.IsValid()) + { + return; + } + + if (targetId == m_ownerId) + { + AZ_Error("Attachment Component", false, "AttachmentComponent cannot target itself"); + return; + } + + // Note: the target entity may not be activated yet. That's ok. + // When mesh is ready we are notified via MeshComponentEvents::OnModelReady + // When transform is ready we are notified via TransformNotificationBus::OnTransformChanged + + m_targetId = targetId; + m_targetBoneName = targetBoneName; + m_targetOffset = offset; + + BindTargetBone(); + + m_targetBoneTransform = AZ::Transform::Identity(); + + m_isTargetEntityTransformKnown = false; // target's transform may not be available yet + + AZ::TransformBus::EventResult( + m_cachedOwnerTransform, m_ownerId, &AZ::TransformBus::Events::GetWorldTM); // owner query will always succeed + + MeshComponentNotificationBus::Handler::BusConnect(m_targetId); // fires OnModelReady if asset is already ready + AZ::TransformNotificationBus::Handler::BusConnect(m_targetId); + if (m_targetCanAnimate) + { + // Only register for per-frame updates when target can animate + AZ::TickBus::Handler::BusConnect(); + } + + // update owner's transform + UpdateOwnerTransformIfNecessary(); + + // alert others that we've attached + LmbrCentral::AttachmentComponentNotificationBus::Event(m_targetId, &LmbrCentral::AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId); + } + + void BoneFollower::Detach() + { + AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use."); + + if (m_targetId.IsValid()) + { + // alert others that we're detaching + EBUS_EVENT_ID(m_targetId, LmbrCentral::AttachmentComponentNotificationBus, OnDetached, m_ownerId); + + MeshComponentNotificationBus::Handler::BusDisconnect(); + AZ::TransformNotificationBus::Handler::BusDisconnect(m_targetId); + AZ::TickBus::Handler::BusDisconnect(); + + m_targetId.SetInvalid(); + } + } + + const char* BoneFollower::GetJointName() + { + return m_targetBoneName.c_str(); + } + + void BoneFollower::SetAttachmentOffset(const AZ::Transform& offset) + { + AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use."); + + if (m_targetId.IsValid()) + { + m_targetOffset = offset; + UpdateOwnerTransformIfNecessary(); + } + } + + void BoneFollower::OnModelReady([[maybe_unused]] const AZ::Data::Asset& modelAsset, [[maybe_unused]] const AZ::Data::Instance& model) + { + // reset character values + BindTargetBone(); + m_targetBoneTransform = QueryBoneTransform(); + + // move owner if necessary + UpdateOwnerTransformIfNecessary(); + } + + void BoneFollower::BindTargetBone() + { + m_targetBoneId = -1; + LmbrCentral::SkeletalHierarchyRequestBus::EventResult( + m_targetBoneId, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointIndexByName, m_targetBoneName.c_str()); + } + + void BoneFollower::UpdateOwnerTransformIfNecessary() + { + // Can't update until target entity's transform is known + if (!m_isTargetEntityTransformKnown) + { + if (AZ::TransformBus::GetNumOfEventHandlers(m_targetId) == 0) + { + return; + } + + AZ::TransformBus::EventResult(m_targetEntityTransform, m_targetId, &AZ::TransformBus::Events::GetWorldTM); + m_isTargetEntityTransformKnown = true; + } + + AZ::Transform finalTransform; + if (m_scaleSource == AttachmentConfiguration::ScaleSource::WorldScale) + { + // apply offset in world-space + finalTransform = m_targetEntityTransform * m_targetBoneTransform; + finalTransform.SetScale(AZ::Vector3::CreateOne()); + finalTransform *= m_targetOffset; + } + else if (m_scaleSource == AttachmentConfiguration::ScaleSource::TargetEntityScale) + { + // apply offset in target-entity-space (ignoring bone scale) + AZ::Transform boneNoScale = m_targetBoneTransform; + boneNoScale.SetScale(AZ::Vector3::CreateOne()); + + finalTransform = m_targetEntityTransform * boneNoScale * m_targetOffset; + } + else // AttachmentConfiguration::ScaleSource::TargetEntityScale + { + // apply offset in target-bone-space + finalTransform = m_targetEntityTransform * m_targetBoneTransform * m_targetOffset; + } + + if (m_cachedOwnerTransform != finalTransform) + { + AZ_Warning( + "Attachment Component", !m_isUpdatingOwnerTransform, + "AttachmentComponent detected a cycle when updating transform, do not target child entities."); + if (!m_isUpdatingOwnerTransform) + { + m_cachedOwnerTransform = finalTransform; + m_isUpdatingOwnerTransform = true; + EBUS_EVENT_ID(m_ownerId, AZ::TransformBus, SetWorldTM, finalTransform); + m_isUpdatingOwnerTransform = false; + } + } + } + + AZ::Transform BoneFollower::QueryBoneTransform() const + { + AZ::Transform boneTransform = AZ::Transform::CreateIdentity(); + + if (m_targetBoneId >= 0) + { + LmbrCentral::SkeletalHierarchyRequestBus::EventResult( + boneTransform, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointTransformCharacterRelative, m_targetBoneId); + } + + return boneTransform; + } + + // fires when target's transform changes + void BoneFollower::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) + { + m_targetEntityTransform = world; + m_isTargetEntityTransformKnown = true; + UpdateOwnerTransformIfNecessary(); + } + + void BoneFollower::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) + { + m_targetBoneTransform = QueryBoneTransform(); + UpdateOwnerTransformIfNecessary(); + } + + int BoneFollower::GetTickOrder() + { + return AZ::TICK_ATTACHMENT; + } + + void BoneFollower::Reattach(bool detachFirst) + { +#ifdef AZ_ENABLE_TRACING + AZ::Entity* ownerEntity = nullptr; + AZ::Entity* targetEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(ownerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_ownerId); + AZ::ComponentApplicationBus::BroadcastResult(targetEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_targetId); + AZ_TracePrintf( + "BoneFollower", "Reattaching entity '%s' to entity '%s'", ownerEntity ? ownerEntity->GetName().c_str() : "", + targetEntity ? targetEntity->GetName().c_str() : ""); +#endif + + if (m_targetId.IsValid() && detachFirst) + { + LmbrCentral::AttachmentComponentNotificationBus::Event(m_targetId, &LmbrCentral::AttachmentComponentNotificationBus::Events::OnDetached, m_ownerId); + } + + if (m_targetId != m_ownerId) + { + LmbrCentral::AttachmentComponentNotificationBus::Event(m_targetId, &LmbrCentral::AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId); + } + } + + //========================================================================= + // AttachmentComponent + //========================================================================= + + void AttachmentComponent::Activate() + { +#ifdef AZ_ENABLE_TRACING + bool isStaticTransform = false; + AZ::TransformBus::EventResult(isStaticTransform, GetEntityId(), &AZ::TransformBus::Events::IsStaticTransform); + AZ_Warning( + "Attachment Component", !isStaticTransform, "Attachment needs to move, but entity '%s' %s has a static transform.", + GetEntity()->GetName().c_str(), GetEntityId().ToString().c_str()); +#endif + + m_boneFollower.Activate(GetEntity(), m_initialConfiguration, true); + } + + void AttachmentComponent::Deactivate() + { + m_boneFollower.Deactivate(); + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h new file mode 100644 index 0000000000..ac03663f22 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h @@ -0,0 +1,189 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include +#include +#include +#include +#include +#include + +struct ISkeletonPose; + +namespace AZ +{ + namespace Render + { + /*! + * Configuration data for AttachmentComponent. + */ + struct AttachmentConfiguration + { + AZ_TYPE_INFO(AttachmentConfiguration, "{74B5DC69-DE44-4640-836A-55339E116795}"); + + virtual ~AttachmentConfiguration() = default; + + static void Reflect(AZ::ReflectContext* context); + + //! Attach to this entity. + AZ::EntityId m_targetId; + + //! Attach to this bone on target entity. + AZStd::string m_targetBoneName; + + //! Offset from target. + AZ::Transform m_targetOffset = AZ::Transform::Identity(); + + //! Whether to attach to target upon activation. + //! If false, the entity remains detached until Attach() is called. + bool m_attachedInitially = true; + + //! Source from which to retrieve scale information. + enum class ScaleSource : AZ::u8 + { + WorldScale, // Scaled in world space. + TargetEntityScale, // Adopt scaling of attachment target entity. + TargetBoneScale, // Adopt scaling of attachment target entity/joint. + }; + ScaleSource m_scaleSource = ScaleSource::WorldScale; + }; + + /* + * Common functionality for game and editor attachment components. + * The BoneFollower tracks movement of the target's bone and + * updates the owning entity's TransformComponent to follow. + * This class should be a member within the attachment component + * and be activated/deactivated along with the component. + * \ref AttachmentComponent + */ + class BoneFollower + : public LmbrCentral::AttachmentComponentRequestBus::Handler + , public AZ::TransformNotificationBus::Handler + , public AZ::Render::MeshComponentNotificationBus::Handler + , public AZ::Data::AssetBus::Handler + , public AZ::TickBus::Handler + { + public: + void Activate(AZ::Entity* owner, const AttachmentConfiguration& initialConfiguration, bool targetCanAnimate); + void Deactivate(); + + //////////////////////////////////////////////////////////////////////// + // AttachmentComponentRequests + void Reattach(bool detachFirst); + void Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) override; + void Detach() override; + void SetAttachmentOffset(const AZ::Transform& offset) override; + const char* GetJointName() override; + AZ::EntityId GetTargetEntityId() override; + AZ::Transform GetOffset() override; + //////////////////////////////////////////////////////////////////////// + + private: + + //////////////////////////////////////////////////////////////////////// + // AZ::TickBus + //! Check target bone transform every frame. + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + //! Make sure target bone transform updates after animation update. + int GetTickOrder() override; + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // AZ::TransformNotificationBus + //! When target's transform changes + void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // MeshComponentEvents + //! When target's mesh changes + void OnModelReady(const AZ::Data::Asset& modelAsset, const AZ::Data::Instance& model) override; + //////////////////////////////////////////////////////////////////////// + + void BindTargetBone(); + + AZ::Transform QueryBoneTransform() const; + + void UpdateOwnerTransformIfNecessary(); + + //! Entity which which is being attached. + AZ::EntityId m_ownerId; + + //! Whether to query bone position per-frame (false while in editor) + bool m_targetCanAnimate = false; + + AZ::EntityId m_targetId; + AZStd::string m_targetBoneName; + AZ::Transform m_targetOffset; //!< local transform + AZ::Transform m_targetBoneTransform; //!< local transform of bone + AZ::Transform m_targetEntityTransform; //!< world transform of target + bool m_isTargetEntityTransformKnown = false; + + //! Cached value, so we don't update owner's position unnecessarily. + AZ::Transform m_cachedOwnerTransform; + bool m_isUpdatingOwnerTransform = false; //!< detect infinite loops when updating owner's transform + + // Cached character values to avoid repeated lookup. + // These are set by calling ResetCharacter() + int m_targetBoneId; //!< negative when bone not found + + AttachmentConfiguration::ScaleSource m_scaleSource; + }; + + /*! + * The AttachmentComponent lets an entity stick to a particular bone on + * a target entity. This is achieved by tracking movement of the target's + * bone and updating the entity's TransformComponent accordingly. + */ + class AttachmentComponent + : public AZ::Component + { + public: + AZ_COMPONENT(AttachmentComponent, "{2D17A64A-7AC5-4C02-AC36-C5E8141FFDDF}"); + + friend class EditorAttachmentComponent; + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63)); + } + + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63)); + } + + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); + } + + ~AttachmentComponent() override = default; + + private: + //////////////////////////////////////////////////////////////////////// + // AZ::Component + void Activate() override; + void Deactivate() override; + //////////////////////////////////////////////////////////////////////// + + //! Initial configuration for m_attachment + AttachmentConfiguration m_initialConfiguration; + + //! Implements actual attachment functionality + BoneFollower m_boneFollower; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp new file mode 100644 index 0000000000..3b50c0a48c --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp @@ -0,0 +1,242 @@ +/* +* 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 "EditorAttachmentComponent.h" +#include +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + void EditorAttachmentComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1) + ->Field("Target ID", &EditorAttachmentComponent::m_targetId) + ->Field("Target Bone Name", &EditorAttachmentComponent::m_targetBoneName) + ->Field("Position Offset", &EditorAttachmentComponent::m_positionOffset) + ->Field("Rotation Offset", &EditorAttachmentComponent::m_rotationOffset) + ->Field("Scale Offset", &EditorAttachmentComponent::m_scaleOffset) + ->Field("Attached Initially", &EditorAttachmentComponent::m_attachedInitially) + ->Field("Scale Source", &EditorAttachmentComponent::m_scaleSource); + + AZ::EditContext* editContext = serializeContext->GetEditContext(); + if (editContext) + { + editContext + ->Class( + "Attachment", "The Attachment component lets an entity attach to a bone on the skeleton of another entity") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Category, "Animation") + ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Attachment.svg") + ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Attachment.png") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute( + AZ::Edit::Attributes::HelpPageURL, + "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-attachment.html") + ->DataElement(0, &EditorAttachmentComponent::m_targetId, "Target entity", "Attach to this entity.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetIdChanged) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_targetBoneName, "Joint name", + "Attach to this joint on target entity.") + ->Attribute(AZ::Edit::Attributes::StringList, &EditorAttachmentComponent::GetTargetBoneOptions) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetBoneChanged) + ->DataElement( + 0, &EditorAttachmentComponent::m_positionOffset, "Position offset", "Local position offset from target bone") + ->Attribute(AZ::Edit::Attributes::Suffix, "m") + ->Attribute(AZ::Edit::Attributes::Step, 0.01f) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) + ->DataElement( + 0, &EditorAttachmentComponent::m_rotationOffset, "Rotation offset", "Local rotation offset from target bone") + ->Attribute(AZ::Edit::Attributes::Suffix, "deg") + ->Attribute(AZ::Edit::Attributes::Step, 0.01f) + ->Attribute(AZ::Edit::Attributes::Min, -AZ::RadToDeg(AZ::Constants::TwoPi)) + ->Attribute(AZ::Edit::Attributes::Max, AZ::RadToDeg(AZ::Constants::TwoPi)) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) + ->DataElement(0, &EditorAttachmentComponent::m_scaleOffset, "Scale offset", "Local scale offset from target entity") + ->Attribute(AZ::Edit::Attributes::Step, 0.1f) + ->Attribute(AZ::Edit::Attributes::Min, 0.001f) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) + ->DataElement( + 0, &EditorAttachmentComponent::m_attachedInitially, "Attached initially", + "Whether to attach to target upon activation.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnAttachedInitiallyChanged) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_scaleSource, "Scaling", + "How object scale should be determined. " + "Use world scale = Attached object is scaled in world space, Use target entity scale = Attached object adopts " + "scale of target entity., Use target bone scale = Attached object adopts scale of target entity/joint.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnScaleSourceChanged) + ->EnumAttribute(AttachmentConfiguration::ScaleSource::WorldScale, "Use world scale") + ->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetEntityScale, "Use target entity scale") + ->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetBoneScale, "Use target bone scale"); + } + } + } + + void EditorAttachmentComponent::Activate() + { + Base::Activate(); + m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(), + false); // Entity's don't animate in Editor + } + + void EditorAttachmentComponent::Deactivate() + { + m_boneFollower.Deactivate(); + Base::Deactivate(); + } + + void EditorAttachmentComponent::BuildGameEntity(AZ::Entity* gameEntity) + { + AttachmentComponent* component = gameEntity->CreateComponent(); + if (component) + { + component->m_initialConfiguration = CreateAttachmentConfiguration(); + } + } + + AttachmentConfiguration EditorAttachmentComponent::CreateAttachmentConfiguration() const + { + AttachmentConfiguration configuration; + configuration.m_targetId = m_targetId; + configuration.m_targetBoneName = m_targetBoneName; + configuration.m_targetOffset = GetTargetOffset(); + configuration.m_attachedInitially = m_attachedInitially; + configuration.m_scaleSource = m_scaleSource; + return configuration; + } + + AZ::Transform EditorAttachmentComponent::GetTargetOffset() const + { + AZ::Transform offset = AZ::ConvertEulerDegreesToTransform(m_rotationOffset); + offset.SetTranslation(m_positionOffset); + offset.MultiplyByScale(m_scaleOffset); + return offset; + } + + AZStd::vector EditorAttachmentComponent::GetTargetBoneOptions() const + { + AZStd::vector names; + + // insert blank entry, so user may choose to bind to NO bone. + names.push_back(""); + + // track whether currently-set bone is found + bool currentTargetBoneFound = false; + + // Get character and iterate over bones + AZ::u32 jointCount = 0; + LmbrCentral::SkeletalHierarchyRequestBus::EventResult(jointCount, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointCount); + for (AZ::u32 jointIndex = 0; jointIndex < jointCount; ++jointIndex) + { + const char* name = nullptr; + LmbrCentral::SkeletalHierarchyRequestBus::EventResult(name, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointNameByIndex, jointIndex); + if (name) + { + names.push_back(name); + + if (!currentTargetBoneFound) + { + currentTargetBoneFound = (m_targetBoneName == names.back()); + } + } + } + + // If we never found currently-set bone name, + // stick it at top of list, just in case user wants to keep it anyway + if (!currentTargetBoneFound && !m_targetBoneName.empty()) + { + names.insert(names.begin(), m_targetBoneName); + } + + return names; + } + + AZ::u32 EditorAttachmentComponent::OnTargetIdChanged() + { + // Warn about bad setups (it won't crash, but it's nice to handle this early) + if (m_targetId == GetEntityId()) + { + AZ_Warning(GetEntity()->GetName().c_str(), false, "AttachmentComponent cannot target self.") m_targetId.SetInvalid(); + } + + // Warn about children attaching to a parent + AZ::EntityId parentOfTarget; + AZ::TransformBus::EventResult(parentOfTarget, m_targetId, &AZ::TransformBus::Events::GetParentId); + while (parentOfTarget.IsValid()) + { + if (parentOfTarget == GetEntityId()) + { + AZ_Warning( + GetEntity()->GetName().c_str(), parentOfTarget != GetEntityId(), "AttachmentComponent cannot target child entity"); + m_targetId.SetInvalid(); + break; + } + + AZ::EntityId currentParentId = parentOfTarget; + parentOfTarget.SetInvalid(); + AZ::TransformBus::EventResult(parentOfTarget, currentParentId, &AZ::TransformBus::Events::GetParentId); + } + + AttachOrDetachAsNecessary(); + + return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; // refresh bone options + } + + AZ::u32 EditorAttachmentComponent::OnTargetBoneChanged() + { + AttachOrDetachAsNecessary(); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorAttachmentComponent::OnTargetOffsetChanged() + { + EBUS_EVENT_ID(GetEntityId(), LmbrCentral::AttachmentComponentRequestBus, SetAttachmentOffset, GetTargetOffset()); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorAttachmentComponent::OnAttachedInitiallyChanged() + { + AttachOrDetachAsNecessary(); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorAttachmentComponent::OnScaleSourceChanged() + { + m_boneFollower.Deactivate(); + m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(), false); + return AZ::Edit::PropertyRefreshLevels::None; + } + + void EditorAttachmentComponent::AttachOrDetachAsNecessary() + { + if (m_attachedInitially && m_targetId.IsValid()) + { + EBUS_EVENT_ID( + GetEntityId(), LmbrCentral::AttachmentComponentRequestBus, Attach, m_targetId, m_targetBoneName.c_str(), GetTargetOffset()); + } + else + { + EBUS_EVENT_ID(GetEntityId(), LmbrCentral::AttachmentComponentRequestBus, Detach); + } + } + } // namespace Render + } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.h new file mode 100644 index 0000000000..cac8a71a94 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.h @@ -0,0 +1,104 @@ +/* +* 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 "AttachmentComponent.h" + +namespace AZ +{ + namespace Render + { + /*! + * In-editor attachment component. + * \ref AttachmentComponent + */ + class EditorAttachmentComponent + : public AzToolsFramework::Components::EditorComponentBase + { + private: + using Base = AzToolsFramework::Components::EditorComponentBase; + public: + AZ_COMPONENT(EditorAttachmentComponent, "{DA6072FD-E696-47D8-81D9-1F77D3464200}", Base); + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + AttachmentComponent::GetProvidedServices(provided); + } + + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + AttachmentComponent::GetIncompatibleServices(incompatible); + } + + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + AttachmentComponent::GetRequiredServices(required); + } + + ~EditorAttachmentComponent() override = default; + void BuildGameEntity(AZ::Entity* gameEntity) override; + + protected: + + ////////////////////////////////////////////////////////////////////////// + // AZ::Component interface implementation + void Activate() override; + void Deactivate() override; + ////////////////////////////////////////////////////////////////////////// + + AZ::u32 OnTargetIdChanged(); + AZ::u32 OnTargetBoneChanged(); + AZ::u32 OnTargetOffsetChanged(); + AZ::u32 OnAttachedInitiallyChanged(); + AZ::u32 OnScaleSourceChanged(); + + //! Invoked when an attachment property changes + void AttachOrDetachAsNecessary(); + + //! For populating ComboBox + AZStd::vector GetTargetBoneOptions() const; + + //! Create runtime configuration from editor configuration + AttachmentConfiguration CreateAttachmentConfiguration() const; + + //! Create AZ::Transform from position and rotation + AZ::Transform GetTargetOffset() const; + + //! Attach to this entity. + AZ::EntityId m_targetId; + + //! Attach to this bone on target entity. + AZStd::string m_targetBoneName; + + //! Offset from target bone's position. + AZ::Vector3 m_positionOffset = AZ::Vector3::CreateZero(); + + //! Offset from target bone's rotation. + AZ::Vector3 m_rotationOffset = AZ::Vector3::CreateZero(); + + //! Offset from target entity's scale. + AZ::Vector3 m_scaleOffset = AZ::Vector3::CreateOne(); + + //! Observe scale information from the specified source. + AttachmentConfiguration::ScaleSource m_scaleSource = AttachmentConfiguration::ScaleSource::WorldScale; + + //! Whether to attach to target upon activation. + //! If false, the entity remains detached until Attach() is called. + bool m_attachedInitially = true; + + //! Implements actual attachment functionality + AZ::Render::BoneFollower m_boneFollower; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp index b33dd7f165..2ef4e1e229 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef ATOMLYINTEGRATION_FEATURE_COMMON_EDITOR #include @@ -69,6 +70,7 @@ #include #include #include +#include #endif namespace AZ @@ -111,6 +113,7 @@ namespace AZ DiffuseProbeGridComponent::CreateDescriptor(), DeferredFogComponent::CreateDescriptor(), SurfaceData::SurfaceDataMeshComponent::CreateDescriptor(), + AttachmentComponent::CreateDescriptor(), #ifdef ATOMLYINTEGRATION_FEATURE_COMMON_EDITOR EditorAreaLightComponent::CreateDescriptor(), @@ -141,6 +144,7 @@ namespace AZ EditorDiffuseProbeGridComponent::CreateDescriptor(), EditorDeferredFogComponent::CreateDescriptor(), SurfaceData::EditorSurfaceDataMeshComponent::CreateDescriptor(), + EditorAttachmentComponent::CreateDescriptor(), #endif }); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake index ff8f33e06e..e58f72a121 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake @@ -11,6 +11,8 @@ set(FILES Source/Module.cpp + Source/Animation/EditorAttachmentComponent.h + Source/Animation/EditorAttachmentComponent.cpp Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h Include/AtomLyIntegration/CommonFeatures/ReflectionProbe/EditorReflectionProbeBus.h Source/EditorCommonFeaturesSystemComponent.h diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake index b26ebc60a6..e13d1d37d6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake @@ -10,6 +10,8 @@ # set(FILES + Source/Animation/AttachmentComponent.h + Source/Animation/AttachmentComponent.cpp Source/CoreLights/AreaLightComponent.h Source/CoreLights/AreaLightComponent.cpp Source/CoreLights/AreaLightComponentConfig.cpp diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h index b31091681e..1002fcbde1 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h @@ -18,7 +18,7 @@ #include -#include +#include #include #include diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp index e3de713b3c..8ef87af9a7 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -414,9 +413,6 @@ namespace EMotionFX CheckAttachToEntity(); - // Send general mesh creation notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event(entityId, &LmbrCentral::MeshComponentNotifications::OnMeshCreated, m_configuration.m_actorAsset); - Physics::RagdollConfiguration ragdollConfiguration; [[maybe_unused]] bool ragdollConfigValid = GetRagdollConfiguration(ragdollConfiguration); AZ_Assert(ragdollConfigValid, "Ragdoll Configuration is not valid"); @@ -460,11 +456,6 @@ namespace EMotionFX m_attachmentTargetActor = nullptr; - // Send general mesh destruction notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event( - GetEntityId(), - &LmbrCentral::MeshComponentNotifications::OnMeshDestroyed); - ActorComponentNotificationBus::Event( GetEntityId(), &ActorComponentNotificationBus::Events::OnActorInstanceDestroyed, diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/AnimAudioComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/AnimAudioComponent.cpp index 6958710b1a..eee9896dee 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/AnimAudioComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/AnimAudioComponent.cpp @@ -22,7 +22,7 @@ #include #include -#include // for SkeletalHierarchyRequestBus +#include #include diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp index bcb1e3f300..f45fe43f4e 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp @@ -26,8 +26,6 @@ #include #include -#include - #include #include #include @@ -255,11 +253,6 @@ namespace EMotionFX { if (m_actorInstance) { - // Send general mesh destruction notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event( - GetEntityId(), - &LmbrCentral::MeshComponentNotifications::OnMeshDestroyed); - ActorComponentNotificationBus::Event( GetEntityId(), &ActorComponentNotificationBus::Events::OnActorInstanceDestroyed, @@ -848,11 +841,6 @@ namespace EMotionFX if (m_actorInstance) { - // Send general mesh destruction notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event( - GetEntityId(), - &LmbrCentral::MeshComponentNotifications::OnMeshDestroyed); - ActorComponentNotificationBus::Event( GetEntityId(), &ActorComponentNotificationBus::Events::OnActorInstanceDestroyed, @@ -941,9 +929,6 @@ namespace EMotionFX { LmbrCentral::AttachmentComponentRequestBus::Event(attachment, &LmbrCentral::AttachmentComponentRequestBus::Events::Reattach, true); } - - // Send general mesh creation notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event(GetEntityId(), &LmbrCentral::MeshComponentNotifications::OnMeshCreated, m_actorAsset); } } //namespace Integration } // namespace EMotionFX diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.cpp b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.cpp index 770e1190be..7b15d6680d 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.cpp +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -518,18 +517,6 @@ namespace ImGui ImGui::EndChild(); // End the "Meshes in Scene" Child } } - - // Check to make sure the Tick Bus Connection status matches the debug enabled flag - if (m_meshDebugEnabled && !AZ::TickBus::Handler::BusIsConnected()) - { - // Connect to the Tick Bus - AZ::TickBus::Handler::BusConnect(); - } - else if (!m_meshDebugEnabled && AZ::TickBus::Handler::BusIsConnected()) - { - // Disconnect from the Tick Bus - AZ::TickBus::Handler::BusDisconnect(); - } } // Mesh Mouse Over Helper function @@ -597,81 +584,6 @@ namespace ImGui instanceOptions.m_mousedOverForDraw |= ImGui::IsItemHovered(); } - void ImGuiLYAssetExplorer::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) - { - // Search through all entities for Asset Components - OnTick_FindAssets(); - - // Check for all relevant pointers here. ( Actually requires checking all of these for different edge cases! :( - if (gEnv && gEnv->pRenderer && gEnv->pSystem && - gEnv->pSystem->GetIViewSystem() && gEnv->pSystem->GetIViewSystem()->GetActiveView() && - gEnv->pSystem->GetIViewSystem()->GetActiveView()->GetCurrentParams()) - { - // Get the Camera View Position from the view system. - const Vec3& cameraPosVec3 = gEnv->pSystem->GetIViewSystem()->GetActiveView()->GetCurrentParams()->position; - const AZ::Vector3 cameraPos(cameraPosVec3.x, cameraPosVec3.y, cameraPosVec3.z); - - // Loop through all Meshes to draw the appropriate ones! - for (const MeshInstanceDisplayList& meshInstanceList : m_meshInstanceDisplayList) - { - // bunch of different ways to filter results. First check for Mesh and Instance Name Filters... - bool displayMesh = true; - if (m_meshNameFilter) - { - displayMesh &= meshInstanceList.m_passesFilter; - } - if (m_entityNameFilter) - { - displayMesh &= meshInstanceList.m_childrenPassFilter; - } - - // ..Mouse Overs and Selection Filters should override other filters, so do it after.. Mouse Over THEN Selection Filter for precedence. - if (m_anyMousedOverForDraw) - { - displayMesh = meshInstanceList.m_mousedOverForDraw || meshInstanceList.m_childMousedOverForDraw; - } - else if (m_selectionFilter) - { - displayMesh = meshInstanceList.m_selectedForDraw; - for (const auto& meshInstance : meshInstanceList.m_instanceOptionMap) - { - displayMesh |= meshInstance.second.m_selectedForDraw; - } - } - - if (displayMesh) - { - for (const auto& meshInstance : meshInstanceList.m_instanceOptionMap) - { - AZ::Data::Asset meshAsset; - LmbrCentral::MeshComponentRequestBus::EventResult(meshAsset, meshInstance.first, &LmbrCentral::MeshComponentRequests::GetMeshAsset); - // See if we pass name filter first.. - bool displayEntity = true; - if (m_entityNameFilter) - { - displayEntity = meshInstance.second.m_passesFilter; - } - - // ..Mouse Overs and Selection Filters should override other filters, so do it after.. Mouse Over THEN Selection Filter for precedence. - if (m_anyMousedOverForDraw) - { - displayEntity = meshInstance.second.m_mousedOverForDraw || meshInstanceList.m_mousedOverForDraw; - } - else if (m_selectionFilter) - { - displayEntity = meshInstance.second.m_selectedForDraw | meshInstanceList.m_selectedForDraw; - } - - if (displayEntity) - { - OnTick_DrawEntity(meshInstance.first, meshAsset.GetId(), gEnv->pRenderer, cameraPos); - } - } - } - } - } - } - MeshInstanceDisplayList& ImGuiLYAssetExplorer::FindOrCreateMeshInstanceList(const char* meshName) { // Walk the list and see if an entry for this mesh exists already. If we find one, return it! @@ -696,250 +608,6 @@ namespace ImGui m_meshInstanceDisplayList.push_back(meshList); return m_meshInstanceDisplayList.back(); } - - // Scan the scene for Meshes! - void ImGuiLYAssetExplorer::OnTick_FindAssets() - { - // Retrieve Id map from game entity context (editor->runtime). - AzFramework::EntityContextId gameContextId = AzFramework::EntityContextId::CreateNull(); - AzFramework::GameEntityContextRequestBus::BroadcastResult(gameContextId, &AzFramework::GameEntityContextRequests::GetGameEntityContextId); - - // Get the Root Slice Component - AZ::SliceComponent* rootSliceComponent; - AzFramework::SliceEntityOwnershipServiceRequestBus::EventResult(rootSliceComponent, gameContextId, - &AzFramework::SliceEntityOwnershipServiceRequests::GetRootSlice); - - if (rootSliceComponent) - { - // Get an unordered_set of all EntityIds in the slice - AZ::SliceComponent::EntityIdSet entityIds; - rootSliceComponent->GetEntityIds(entityIds); - - // Loop through Mesh Map and "un-verify" them - for (MeshInstanceDisplayList& meshInstanceList : m_meshInstanceDisplayList) - { - for (auto& meshInstance : meshInstanceList.m_instanceOptionMap) - { - meshInstance.second.m_verifiedThisFrame = false; - } - } - - for (auto it = entityIds.begin(); it != entityIds.end(); it++) - { - AZ::Data::Asset meshAsset; - LmbrCentral::MeshComponentRequestBus::EventResult(meshAsset, *it, &LmbrCentral::MeshComponentRequests::GetMeshAsset); - - if (meshAsset.IsReady()) - { - // Get the Asset Info so we can get the mesh path - AZ::Data::AssetInfo assetInfo; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, meshAsset.GetId()); - - AZStd::string meshPath = assetInfo.m_relativePath; - AZStd::to_lower(meshPath.begin(), meshPath.end()); - // Save off this mesh instance into the instance map - MeshInstanceDisplayList& displayList = FindOrCreateMeshInstanceList(meshPath.c_str()); - if (!displayList.m_instanceOptionMap.count(*it)) - { - // Get the Entity Name, for easy searching later - AZStd::string entityName; - AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationBus::Events::GetEntityName, *it); - - // Init the instance entry and options - MeshInstanceOptions& meshOptions = displayList.m_instanceOptionMap[*it]; - meshOptions.m_verifiedThisFrame = true; - meshOptions.m_passesFilter = true; - meshOptions.m_selectedForDraw = false; - meshOptions.m_mousedOverForDraw = false; - meshOptions.m_instanceLabel = AZStd::string::format("%s%s", (*it).ToString().c_str(), entityName.c_str()); - AZStd::to_lower(meshOptions.m_instanceLabel.begin(), meshOptions.m_instanceLabel.end()); - } - else - { - displayList.m_instanceOptionMap[*it].m_verifiedThisFrame = true; - } - } - } - - // Loop through Mesh Map again and remove any "un-verify"-ed entries! - for (auto meshInstanceListIter = m_meshInstanceDisplayList.begin(); meshInstanceListIter != m_meshInstanceDisplayList.end();) - { - for (auto meshInstanceIter = (*meshInstanceListIter).m_instanceOptionMap.begin(); meshInstanceIter != (*meshInstanceListIter).m_instanceOptionMap.end();) - { - if (!(*meshInstanceIter).second.m_verifiedThisFrame) - { - // erase this instance from the map and set the iterator correctly. - meshInstanceIter = (*meshInstanceListIter).m_instanceOptionMap.erase(meshInstanceIter); - } - else - { - // increment the iterator - meshInstanceIter++; - } - } - - // Remove the Mesh Entry if there are no instances remaining - if ((*meshInstanceListIter).m_instanceOptionMap.empty()) - { - meshInstanceListIter = m_meshInstanceDisplayList.erase(meshInstanceListIter); - } - else - { - // increment the iterator - meshInstanceListIter++; - } - } - } - } - - // We know we want to draw this Entity/Mesh ( depending on distance from Cam ).. so draw! - void ImGuiLYAssetExplorer::OnTick_DrawEntity(const AZ::EntityId& entity, const AZ::Data::AssetId& assetId, IRenderer* renderer, const AZ::Vector3& cameraPos) - { - // Get the Entity Position so we can see how far from the camera we are. - AZ::Vector3 worldPos = AZ::Vector3::CreateZero(); - AZ::TransformBus::EventResult(worldPos, entity, &AZ::TransformBus::Events::GetWorldTranslation); - - // Get Our Distance From The Camera! ( Used just for draw alpha value ) - float distFromCamera = m_distanceFilter_far + 1.0f; // Default to just outside camera view ( i.e. Don't draw ) - if (m_anyMousedOverForDraw || m_selectionFilter || !m_distanceFilter) - { - // If we have either the Selection Filter or Mouse Over state on or the distance filter is off, and we made it this far, we are the lucky selected one! Draw ourselves by setting dist to 0.0f - distFromCamera = 0.0; - } - else if (m_distanceFilter) - { - // Distance filter is on and we aren't selected, so actually find the distance from the camera - distFromCamera = worldPos.GetDistance(cameraPos); - } - - // Only draw things within view distance ( cheese it to zero above to force drawing far things ) - if (distFromCamera <= m_distanceFilter_far) - { - // Find an interpolated Alpha.. 1.0f while inside near radius, interp 1.0 -> 0.0 while heading toward far radius - float alpha = (distFromCamera <= m_distanceFilter_near) ? 1.0f : (1.0f - ((distFromCamera - m_distanceFilter_near) / (m_distanceFilter_far - m_distanceFilter_near))); - - // The string to hold label text we will build. - AZStd::string entityLabel; - - // Grab the Asset Info to get the mesh path name. - AZ::Data::AssetInfo assetInfo; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, assetId); - - // Start the label with either the EntName and Mesh, or just Mesh - if (m_inWorld_label_entityName) - { - AZ::ComponentApplicationBus::BroadcastResult(entityLabel, &AZ::ComponentApplicationBus::Events::GetEntityName, entity); - entityLabel = AZStd::string::format("Entity: %s %s\nMesh: %s", entity.ToString().c_str(), entityLabel.c_str(), assetInfo.m_relativePath.c_str()); - } - else - { - entityLabel = AZStd::string::format("Mesh: %s", assetInfo.m_relativePath.c_str()); - } - - // See if we should add the Material! - if (m_inWorld_label_materialName) - { - _smart_ptr material; - LmbrCentral::MaterialOwnerRequestBus::EventResult(material, entity, &LmbrCentral::MaterialOwnerRequests::GetMaterial); - if (material) - { - entityLabel.append(AZStd::string::format("\nMaterial: %s", material->GetName())); - } - } - - // Get The Render Node for mesh debug draw and Lod Info - IRenderNode* renderNode = nullptr; - LmbrCentral::RenderNodeRequestBus::EventResult(renderNode, entity, &LmbrCentral::RenderNodeRequests::GetRenderNode); - - if (renderNode != nullptr && renderNode->GetEntityStatObj()) - { - // Debug Draw Mesh - if (m_inWorld_debugDrawMesh) - { - SGeometryDebugDrawInfo dd; - dd.color.Set(0.0f, 0.0f, 255.0f, 0.5f * alpha); - dd.lineColor.Set(255.0f, 0.0f, 0.0f, 0.75f * alpha); - renderNode->GetEntityStatObj()->DebugDraw(dd, 0.2f); - } - // Draw Total Lods info - if (m_inWorld_label_totalLods) - { - entityLabel.append(AZStd::string::format("\nTotal Lods: %d", renderNode->GetEntityStatObj()->GetLoadedLodsNum())); - } - // Draw Misc Lod Info - if (m_inWorld_label_miscLod) - { - entityLabel.append(AZStd::string::format("\nFirst Lod Distance: %f", renderNode->GetFirstLodDistance())); - float distances[SMeshLodInfo::s_nMaxLodCount]; - renderNode->GetLodDistances(gEnv->p3DEngine->GetFrameLodInfo(), distances); - for (int i = 0; i < SMeshLodInfo::s_nMaxLodCount; i++) - { - entityLabel.append(AZStd::string::format("\n frameLod: %d - %f", i, distances[i])); - } - } - } - - // Draw the label in the world - if (m_inWorld_drawLabel) - { - SDrawTextInfo ti; - ti.xscale = ti.yscale = m_inWorld_labelTextSize * alpha; - ti.flags = eDrawText_FixedSize | eDrawText_Center | eDrawText_800x600; - if (m_inWorld_label_framed) - { - ti.flags |= eDrawText_Framed; - } - if (m_inWorld_label_monoSpace) - { - ti.flags |= eDrawText_Monospace; - } - - { - ti.color[0] = m_inWorld_label_textColor.Value.x; - ti.color[1] = m_inWorld_label_textColor.Value.y; - ti.color[2] = m_inWorld_label_textColor.Value.z; - ti.color[3] = alpha; - } - Vec3 labelPos(worldPos.GetX(), worldPos.GetY(), worldPos.GetZ() - m_inWorld_originSphereRadius); - renderer->DrawTextQueued(labelPos, ti, entityLabel.c_str()); - } - - // Draw the sphere and/or AABB in the world - if (m_inWorld_drawOriginSphere || m_inWorld_drawAABB) - { - IRenderAuxGeom* pAuxGeom = renderer->GetIRenderAuxGeom(); - if (pAuxGeom) - { - const ColorF sphereColor(m_inWorld_label_textColor.Value.x, m_inWorld_label_textColor.Value.y, m_inWorld_label_textColor.Value.z, alpha); - Vec3 spherePos(worldPos.GetX(), worldPos.GetY(), worldPos.GetZ()); - - // draw a sample sphere - SAuxGeomRenderFlags oldFlags = pAuxGeom->GetRenderFlags(); - SAuxGeomRenderFlags flags = oldFlags; - flags.SetDepthWriteFlag(e_DepthWriteOff); - flags.SetDepthTestFlag(e_DepthTestOff); - flags.SetDrawInFrontMode(e_DrawInFrontOn); - flags.SetFillMode(e_FillModeSolid); - flags.SetCullMode(e_CullModeNone); - pAuxGeom->SetRenderFlags(flags); - - if ( m_inWorld_drawOriginSphere) - { - pAuxGeom->DrawSphere(spherePos, m_inWorld_originSphereRadius, sphereColor, false); - } - - if (m_inWorld_drawAABB && renderNode) - { - pAuxGeom->DrawAABB(renderNode->GetBBox(), false, sphereColor, EBoundingBoxDrawStyle::eBBD_Extremes_Color_Encoded); - } - - // Restore rendering state - pAuxGeom->SetRenderFlags(oldFlags); - } - } - } - } - -} // namespace ImGui + } // namespace ImGui #endif // IMGUI_ENABLED diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.h b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.h index 29584c84d3..b5f8ea576c 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.h +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.h @@ -43,7 +43,6 @@ namespace ImGui class ImGuiLYAssetExplorer : public ImGuiAssetExplorerRequestBus::Handler - , public AZ::TickBus::Handler { public: @@ -61,10 +60,6 @@ namespace ImGui void SetEnabled(bool enabled) override { m_enabled = enabled; m_meshDebugEnabled = enabled; } // -- ImGuiAssetExplorerRequestBus::Handler Interface ---------------------- - // -- AZ::TickBus::Handler Interface --------------------------------------- - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - // -- AZ::TickBus::Handler Interface --------------------------------------- - // Toggle the menu on and off void ToggleEnabled() { m_enabled = !m_enabled; } @@ -117,9 +112,6 @@ namespace ImGui void ImGuiUpdate_DrawMeshMouseOver(MeshInstanceDisplayList& meshDisplayList); void ImGuiUpdate_DrawEntityInstanceMouseOver(MeshInstanceDisplayList& meshDisplayList, AZ::EntityId& entityInstance, AZStd::string& entityName, MeshInstanceOptions& instanceOptions); - // Helper functions for the OnTick callback - void OnTick_DrawEntity(const AZ::EntityId& entity, const AZ::Data::AssetId& assetId, IRenderer* renderer, const AZ::Vector3& cameraPos); - void OnTick_FindAssets(); }; } #endif // IMGUI_ENABLED diff --git a/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.cpp b/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.cpp deleted file mode 100644 index 537585f48c..0000000000 --- a/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.cpp +++ /dev/null @@ -1,349 +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 "LmbrCentral_precompiled.h" -#include "AttachmentComponent.h" -#include -#include -#include -#include -#include -#include - -namespace LmbrCentral -{ - /// Behavior Context handler for AttachmentComponentNotificationBus - class BehaviorAttachmentComponentNotificationBusHandler : public AttachmentComponentNotificationBus::Handler, public AZ::BehaviorEBusHandler - { - public: - AZ_EBUS_BEHAVIOR_BINDER(BehaviorAttachmentComponentNotificationBusHandler, "{636B95A0-5C7D-4EE7-8645-955665315451}", AZ::SystemAllocator - , OnAttached, OnDetached); - - void OnAttached(AZ::EntityId id) override - { - Call(FN_OnAttached, id); - } - - void OnDetached(AZ::EntityId id) override - { - Call(FN_OnDetached, id); - } - }; - - void AttachmentConfiguration::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Target ID", &AttachmentConfiguration::m_targetId) - ->Field("Target Bone Name", &AttachmentConfiguration::m_targetBoneName) - ->Field("Target Offset", &AttachmentConfiguration::m_targetOffset) - ->Field("Attached Initially", &AttachmentConfiguration::m_attachedInitially) - ->Field("Scale Source", &AttachmentConfiguration::m_scaleSource) - ; - } - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->EBus("AttachmentComponentRequestBus") - ->Event("Attach", &AttachmentComponentRequestBus::Events::Attach) - ->Event("Detach", &AttachmentComponentRequestBus::Events::Detach) - ->Event("SetAttachmentOffset", &AttachmentComponentRequestBus::Events::SetAttachmentOffset); - - behaviorContext->EBus("AttachmentComponentNotificationBus") - ->Handler(); - } - } - - void AttachmentComponent::Reflect(AZ::ReflectContext* context) - { - AttachmentConfiguration::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Configuration", &AttachmentComponent::m_initialConfiguration) - ; - } - } - - //========================================================================= - // BoneFollower - //========================================================================= - - void BoneFollower::Activate(AZ::Entity* owner, const AttachmentConfiguration& configuration, bool targetCanAnimate) - { - AZ_Assert(owner, "owner is required"); - AZ_Assert(!m_ownerId.IsValid(), "BoneFollower is already Activated"); - - m_ownerId = owner->GetId(); - m_targetCanAnimate = targetCanAnimate; - m_isUpdatingOwnerTransform = false; - m_scaleSource = configuration.m_scaleSource; - - m_cachedOwnerTransform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(m_cachedOwnerTransform, m_ownerId, AZ::TransformBus, GetWorldTM); - - if (configuration.m_attachedInitially) - { - Attach(configuration.m_targetId, configuration.m_targetBoneName.c_str(), configuration.m_targetOffset); - } - - AttachmentComponentRequestBus::Handler::BusConnect(m_ownerId); - } - - void BoneFollower::Deactivate() - { - AZ_Assert(m_ownerId.IsValid(), "BoneFollower was never Activated"); - - AttachmentComponentRequestBus::Handler::BusDisconnect(); - Detach(); - m_ownerId.SetInvalid(); - } - - AZ::EntityId BoneFollower::GetTargetEntityId() - { - return m_targetId; - } - - AZ::Transform BoneFollower::GetOffset() - { - return m_targetOffset; - } - - void BoneFollower::Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) - { - AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use.") - - // safe to try and detach, even if we weren't attached - Detach(); - - if (!targetId.IsValid()) - { - return; - } - - if (targetId == m_ownerId) - { - AZ_Error("Attachment Component", false, "AttachmentComponent cannot target itself"); - return; - } - - // Note: the target entity may not be activated yet. That's ok. - // When mesh is ready we are notified via MeshComponentEvents::OnMeshCreated - // When transform is ready we are notified via TransformNotificationBus::OnTransformChanged - - m_targetId = targetId; - m_targetBoneName = targetBoneName; - m_targetOffset = offset; - - BindTargetBone(); - - m_targetBoneTransform = AZ::Transform::Identity(); - - m_isTargetEntityTransformKnown = false; // target's transform may not be available yet - - AZ::TransformBus::EventResult(m_cachedOwnerTransform, m_ownerId, &AZ::TransformBus::Events::GetWorldTM); // owner query will always succeed - - MeshComponentNotificationBus::Handler::BusConnect(m_targetId); // fires OnMeshCreated if asset is already ready - AZ::TransformNotificationBus::Handler::BusConnect(m_targetId); - if (m_targetCanAnimate) - { - // Only register for per-frame updates when target can animate - AZ::TickBus::Handler::BusConnect(); - } - - // update owner's transform - UpdateOwnerTransformIfNecessary(); - - // alert others that we've attached - AttachmentComponentNotificationBus::Event(m_targetId, &AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId); - } - - void BoneFollower::Detach() - { - AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use."); - - if (m_targetId.IsValid()) - { - // alert others that we're detaching - EBUS_EVENT_ID(m_targetId, AttachmentComponentNotificationBus, OnDetached, m_ownerId); - - MeshComponentNotificationBus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(m_targetId); - AZ::TickBus::Handler::BusDisconnect(); - - m_targetId.SetInvalid(); - } - } - - const char* BoneFollower::GetJointName() - { - return m_targetBoneName.c_str(); - } - - void BoneFollower::SetAttachmentOffset(const AZ::Transform& offset) - { - AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use."); - - if (m_targetId.IsValid()) - { - m_targetOffset = offset; - UpdateOwnerTransformIfNecessary(); - } - } - - void BoneFollower::OnMeshCreated(const AZ::Data::Asset& asset) - { - (void)asset; - - // reset character values - BindTargetBone(); - m_targetBoneTransform = QueryBoneTransform(); - - // move owner if necessary - UpdateOwnerTransformIfNecessary(); - } - - void BoneFollower::BindTargetBone() - { - m_targetBoneId = -1; - SkeletalHierarchyRequestBus::EventResult(m_targetBoneId, m_targetId, &SkeletalHierarchyRequests::GetJointIndexByName, m_targetBoneName.c_str()); - } - - void BoneFollower::UpdateOwnerTransformIfNecessary() - { - // Can't update until target entity's transform is known - if (!m_isTargetEntityTransformKnown) - { - if (AZ::TransformBus::GetNumOfEventHandlers(m_targetId) == 0) - { - return; - } - - AZ::TransformBus::EventResult(m_targetEntityTransform, m_targetId, &AZ::TransformBus::Events::GetWorldTM); - m_isTargetEntityTransformKnown = true; - } - - AZ::Transform finalTransform; - if (m_scaleSource == AttachmentConfiguration::ScaleSource::WorldScale) - { - // apply offset in world-space - finalTransform = m_targetEntityTransform * m_targetBoneTransform; - finalTransform.SetScale(AZ::Vector3::CreateOne()); - finalTransform *= m_targetOffset; - } - else if (m_scaleSource == AttachmentConfiguration::ScaleSource::TargetEntityScale) - { - // apply offset in target-entity-space (ignoring bone scale) - AZ::Transform boneNoScale = m_targetBoneTransform; - boneNoScale.SetScale(AZ::Vector3::CreateOne()); - - finalTransform = m_targetEntityTransform * boneNoScale * m_targetOffset; - } - else // AttachmentConfiguration::ScaleSource::TargetEntityScale - { - // apply offset in target-bone-space - finalTransform = m_targetEntityTransform * m_targetBoneTransform * m_targetOffset; - } - - if (m_cachedOwnerTransform != finalTransform) - { - AZ_Warning("Attachment Component", !m_isUpdatingOwnerTransform, "AttachmentComponent detected a cycle when updating transform, do not target child entities."); - if (!m_isUpdatingOwnerTransform) - { - m_cachedOwnerTransform = finalTransform; - m_isUpdatingOwnerTransform = true; - EBUS_EVENT_ID(m_ownerId, AZ::TransformBus, SetWorldTM, finalTransform); - m_isUpdatingOwnerTransform = false; - } - } - } - - AZ::Transform BoneFollower::QueryBoneTransform() const - { - AZ::Transform boneTransform = AZ::Transform::CreateIdentity(); - - if (m_targetBoneId >= 0) - { - SkeletalHierarchyRequestBus::EventResult(boneTransform, m_targetId, &SkeletalHierarchyRequests::GetJointTransformCharacterRelative, m_targetBoneId); - } - - return boneTransform; - } - - // fires when target's transform changes - void BoneFollower::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_targetEntityTransform = world; - m_isTargetEntityTransformKnown = true; - UpdateOwnerTransformIfNecessary(); - } - - void BoneFollower::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) - { - m_targetBoneTransform = QueryBoneTransform(); - UpdateOwnerTransformIfNecessary(); - } - - int BoneFollower::GetTickOrder() - { - return AZ::TICK_ATTACHMENT; - } - - void BoneFollower::Reattach(bool detachFirst) - { -#ifdef AZ_ENABLE_TRACING - AZ::Entity* ownerEntity = nullptr; - AZ::Entity* targetEntity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(ownerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_ownerId); - AZ::ComponentApplicationBus::BroadcastResult(targetEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_targetId); - AZ_TracePrintf("BoneFollower", "Reattaching entity '%s' to entity '%s'", ownerEntity ? ownerEntity->GetName().c_str() : "", - targetEntity ? targetEntity->GetName().c_str() : ""); -#endif - - if (m_targetId.IsValid() && detachFirst) - { - AttachmentComponentNotificationBus::Event(m_targetId, &AttachmentComponentNotificationBus::Events::OnDetached, m_ownerId); - } - - if (m_targetId != m_ownerId) - { - AttachmentComponentNotificationBus::Event(m_targetId, &AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId); - } - } - - //========================================================================= - // AttachmentComponent - //========================================================================= - - void AttachmentComponent::Activate() - { -#ifdef AZ_ENABLE_TRACING - bool isStaticTransform = false; - AZ::TransformBus::EventResult(isStaticTransform, GetEntityId(), &AZ::TransformBus::Events::IsStaticTransform); - AZ_Warning("Attachment Component", !isStaticTransform, - "Attachment needs to move, but entity '%s' %s has a static transform.", GetEntity()->GetName().c_str(), GetEntityId().ToString().c_str()); -#endif - - m_boneFollower.Activate(GetEntity(), m_initialConfiguration, true); - } - - - void AttachmentComponent::Deactivate() - { - m_boneFollower.Deactivate(); - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.h b/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.h deleted file mode 100644 index f2ef428ac2..0000000000 --- a/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.h +++ /dev/null @@ -1,186 +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. -* -*/ -#pragma once - -#include -#include -#include -#include -#include -#include - -struct ISkeletonPose; - -namespace LmbrCentral -{ - /*! - * Configuration data for AttachmentComponent. - */ - struct AttachmentConfiguration - { - AZ_TYPE_INFO(AttachmentConfiguration, "{74B5DC69-DE44-4640-836A-55339E116795}"); - - virtual ~AttachmentConfiguration() = default; - - static void Reflect(AZ::ReflectContext* context); - - //! Attach to this entity. - AZ::EntityId m_targetId; - - //! Attach to this bone on target entity. - AZStd::string m_targetBoneName; - - //! Offset from target. - AZ::Transform m_targetOffset = AZ::Transform::Identity(); - - //! Whether to attach to target upon activation. - //! If false, the entity remains detached until Attach() is called. - bool m_attachedInitially = true; - - //! Source from which to retrieve scale information. - enum class ScaleSource : AZ::u8 - { - WorldScale, // Scaled in world space. - TargetEntityScale, // Adopt scaling of attachment target entity. - TargetBoneScale, // Adopt scaling of attachment target entity/joint. - }; - ScaleSource m_scaleSource = ScaleSource::WorldScale; - }; - - /* - * Common functionality for game and editor attachment components. - * The BoneFollower tracks movement of the target's bone and - * updates the owning entity's TransformComponent to follow. - * This class should be a member within the attachment component - * and be activated/deactivated along with the component. - * \ref AttachmentComponent - */ - class BoneFollower - : public AttachmentComponentRequestBus::Handler - , public AZ::TransformNotificationBus::Handler - , public MeshComponentNotificationBus::Handler - , public AZ::Data::AssetBus::Handler - , public AZ::TickBus::Handler - { - public: - void Activate(AZ::Entity* owner, const AttachmentConfiguration& initialConfiguration, bool targetCanAnimate); - void Deactivate(); - - //////////////////////////////////////////////////////////////////////// - // AttachmentComponentRequests - void Reattach(bool detachFirst); - void Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) override; - void Detach() override; - void SetAttachmentOffset(const AZ::Transform& offset) override; - const char* GetJointName() override; - AZ::EntityId GetTargetEntityId() override; - AZ::Transform GetOffset() override; - //////////////////////////////////////////////////////////////////////// - - private: - - //////////////////////////////////////////////////////////////////////// - // AZ::TickBus - //! Check target bone transform every frame. - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - //! Make sure target bone transform updates after animation update. - int GetTickOrder() override; - //////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // AZ::TransformNotificationBus - //! When target's transform changes - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - //////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // MeshComponentEvents - //! When target's mesh changes - void OnMeshCreated(const AZ::Data::Asset& asset) override; - //////////////////////////////////////////////////////////////////////// - - void BindTargetBone(); - - AZ::Transform QueryBoneTransform() const; - - void UpdateOwnerTransformIfNecessary(); - - //! Entity which which is being attached. - AZ::EntityId m_ownerId; - - //! Whether to query bone position per-frame (false while in editor) - bool m_targetCanAnimate = false; - - AZ::EntityId m_targetId; - AZStd::string m_targetBoneName; - AZ::Transform m_targetOffset; //!< local transform - AZ::Transform m_targetBoneTransform; //!< local transform of bone - AZ::Transform m_targetEntityTransform; //!< world transform of target - bool m_isTargetEntityTransformKnown = false; - - //! Cached value, so we don't update owner's position unnecessarily. - AZ::Transform m_cachedOwnerTransform; - bool m_isUpdatingOwnerTransform = false; //!< detect infinite loops when updating owner's transform - - // Cached character values to avoid repeated lookup. - // These are set by calling ResetCharacter() - int m_targetBoneId; //!< negative when bone not found - - AttachmentConfiguration::ScaleSource m_scaleSource; - }; - - /*! - * The AttachmentComponent lets an entity stick to a particular bone on - * a target entity. This is achieved by tracking movement of the target's - * bone and updating the entity's TransformComponent accordingly. - */ - class AttachmentComponent - : public AZ::Component - { - public: - AZ_COMPONENT(AttachmentComponent, "{2D17A64A-7AC5-4C02-AC36-C5E8141FFDDF}"); - - friend class EditorAttachmentComponent; - - static void Reflect(AZ::ReflectContext* context); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63)); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - ~AttachmentComponent() override = default; - - private: - //////////////////////////////////////////////////////////////////////// - // AZ::Component - void Activate() override; - void Deactivate() override; - //////////////////////////////////////////////////////////////////////// - - //! Initial configuration for m_attachment - AttachmentConfiguration m_initialConfiguration; - - //! Implements actual attachment functionality - BoneFollower m_boneFollower; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.cpp b/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.cpp deleted file mode 100644 index 265f4ad864..0000000000 --- a/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.cpp +++ /dev/null @@ -1,238 +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 "LmbrCentral_precompiled.h" -#include "EditorAttachmentComponent.h" -#include -#include -#include -#include - -namespace LmbrCentral -{ - void EditorAttachmentComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Target ID", &EditorAttachmentComponent::m_targetId) - ->Field("Target Bone Name", &EditorAttachmentComponent::m_targetBoneName) - ->Field("Position Offset", &EditorAttachmentComponent::m_positionOffset) - ->Field("Rotation Offset", &EditorAttachmentComponent::m_rotationOffset) - ->Field("Scale Offset", &EditorAttachmentComponent::m_scaleOffset) - ->Field("Attached Initially", &EditorAttachmentComponent::m_attachedInitially) - ->Field("Scale Source", &EditorAttachmentComponent::m_scaleSource) - ; - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Attachment", "The Attachment component lets an entity attach to a bone on the skeleton of another entity") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Animation") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Attachment.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Attachment.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-attachment.html") - ->DataElement(0, &EditorAttachmentComponent::m_targetId, - "Target entity", "Attach to this entity.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetIdChanged) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_targetBoneName, - "Joint name", "Attach to this joint on target entity.") - ->Attribute(AZ::Edit::Attributes::StringList, &EditorAttachmentComponent::GetTargetBoneOptions) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetBoneChanged) - ->DataElement(0, &EditorAttachmentComponent::m_positionOffset, - "Position offset", "Local position offset from target bone") - ->Attribute(AZ::Edit::Attributes::Suffix, "m") - ->Attribute(AZ::Edit::Attributes::Step, 0.01f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) - ->DataElement(0, &EditorAttachmentComponent::m_rotationOffset, - "Rotation offset", "Local rotation offset from target bone") - ->Attribute(AZ::Edit::Attributes::Suffix, "deg") - ->Attribute(AZ::Edit::Attributes::Step, 0.01f) - ->Attribute(AZ::Edit::Attributes::Min, -AZ::RadToDeg(AZ::Constants::TwoPi)) - ->Attribute(AZ::Edit::Attributes::Max, AZ::RadToDeg(AZ::Constants::TwoPi)) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) - ->DataElement(0, &EditorAttachmentComponent::m_scaleOffset, - "Scale offset", "Local scale offset from target entity") - ->Attribute(AZ::Edit::Attributes::Step, 0.1f) - ->Attribute(AZ::Edit::Attributes::Min, 0.001f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) - ->DataElement(0, &EditorAttachmentComponent::m_attachedInitially, - "Attached initially", "Whether to attach to target upon activation.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnAttachedInitiallyChanged) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_scaleSource, - "Scaling", "How object scale should be determined. " - "Use world scale = Attached object is scaled in world space, Use target entity scale = Attached object adopts scale of target entity., Use target bone scale = Attached object adopts scale of target entity/joint.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnScaleSourceChanged) - ->EnumAttribute(AttachmentConfiguration::ScaleSource::WorldScale, "Use world scale") - ->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetEntityScale, "Use target entity scale") - ->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetBoneScale, "Use target bone scale") - ; - } - } - } - - void EditorAttachmentComponent::Activate() - { - Base::Activate(); - m_boneFollower.Activate(GetEntity(), - CreateAttachmentConfiguration(), - false); // Entity's don't animate in Editor - } - - void EditorAttachmentComponent::Deactivate() - { - m_boneFollower.Deactivate(); - Base::Deactivate(); - } - - void EditorAttachmentComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - AttachmentComponent* component = gameEntity->CreateComponent(); - if (component) - { - component->m_initialConfiguration = CreateAttachmentConfiguration(); - } - } - - AttachmentConfiguration EditorAttachmentComponent::CreateAttachmentConfiguration() const - { - AttachmentConfiguration configuration; - configuration.m_targetId = m_targetId; - configuration.m_targetBoneName = m_targetBoneName; - configuration.m_targetOffset = GetTargetOffset(); - configuration.m_attachedInitially = m_attachedInitially; - configuration.m_scaleSource = m_scaleSource; - return configuration; - } - - AZ::Transform EditorAttachmentComponent::GetTargetOffset() const - { - AZ::Transform offset = AZ::ConvertEulerDegreesToTransform(m_rotationOffset); - offset.SetTranslation(m_positionOffset); - offset.MultiplyByScale(m_scaleOffset); - return offset; - } - - AZStd::vector EditorAttachmentComponent::GetTargetBoneOptions() const - { - AZStd::vector names; - - // insert blank entry, so user may choose to bind to NO bone. - names.push_back(""); - - // track whether currently-set bone is found - bool currentTargetBoneFound = false; - - // Get character and iterate over bones - AZ::u32 jointCount = 0; - SkeletalHierarchyRequestBus::EventResult(jointCount, m_targetId, &SkeletalHierarchyRequests::GetJointCount); - for (AZ::u32 jointIndex = 0; jointIndex < jointCount; ++jointIndex) - { - const char* name = nullptr; - SkeletalHierarchyRequestBus::EventResult(name, m_targetId, &SkeletalHierarchyRequests::GetJointNameByIndex, jointIndex); - if (name) - { - names.push_back(name); - - if (!currentTargetBoneFound) - { - currentTargetBoneFound = (m_targetBoneName == names.back()); - } - } - } - - // If we never found currently-set bone name, - // stick it at top of list, just in case user wants to keep it anyway - if (!currentTargetBoneFound && !m_targetBoneName.empty()) - { - names.insert(names.begin(), m_targetBoneName); - } - - return names; - } - - AZ::u32 EditorAttachmentComponent::OnTargetIdChanged() - { - // Warn about bad setups (it won't crash, but it's nice to handle this early) - if (m_targetId == GetEntityId()) - { - AZ_Warning(GetEntity()->GetName().c_str(), false, "AttachmentComponent cannot target self.") - m_targetId.SetInvalid(); - } - - // Warn about children attaching to a parent - AZ::EntityId parentOfTarget; - AZ::TransformBus::EventResult(parentOfTarget, m_targetId, &AZ::TransformBus::Events::GetParentId); - while (parentOfTarget.IsValid()) - { - if (parentOfTarget == GetEntityId()) - { - AZ_Warning(GetEntity()->GetName().c_str(), parentOfTarget != GetEntityId(), "AttachmentComponent cannot target child entity"); - m_targetId.SetInvalid(); - break; - } - - AZ::EntityId currentParentId = parentOfTarget; - parentOfTarget.SetInvalid(); - AZ::TransformBus::EventResult(parentOfTarget, currentParentId, &AZ::TransformBus::Events::GetParentId); - } - - AttachOrDetachAsNecessary(); - - return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; // refresh bone options - } - - AZ::u32 EditorAttachmentComponent::OnTargetBoneChanged() - { - AttachOrDetachAsNecessary(); - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::u32 EditorAttachmentComponent::OnTargetOffsetChanged() - { - EBUS_EVENT_ID(GetEntityId(), AttachmentComponentRequestBus, SetAttachmentOffset, GetTargetOffset()); - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::u32 EditorAttachmentComponent::OnAttachedInitiallyChanged() - { - AttachOrDetachAsNecessary(); - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::u32 EditorAttachmentComponent::OnScaleSourceChanged() - { - m_boneFollower.Deactivate(); - m_boneFollower.Activate(GetEntity(), - CreateAttachmentConfiguration(), - false); - return AZ::Edit::PropertyRefreshLevels::None; - } - - void EditorAttachmentComponent::AttachOrDetachAsNecessary() - { - if (m_attachedInitially && m_targetId.IsValid()) - { - EBUS_EVENT_ID(GetEntityId(), AttachmentComponentRequestBus, Attach, m_targetId, m_targetBoneName.c_str(), GetTargetOffset()); - } - else - { - EBUS_EVENT_ID(GetEntityId(), AttachmentComponentRequestBus, Detach); - } - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.h b/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.h deleted file mode 100644 index 808ffd393e..0000000000 --- a/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.h +++ /dev/null @@ -1,101 +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. -* -*/ -#pragma once - -#include -#include "AttachmentComponent.h" - -namespace LmbrCentral -{ - /*! - * In-editor attachment component. - * \ref AttachmentComponent - */ - class EditorAttachmentComponent - : public AzToolsFramework::Components::EditorComponentBase - { - private: - using Base = AzToolsFramework::Components::EditorComponentBase; - public: - AZ_COMPONENT(EditorAttachmentComponent, "{DA6072FD-E696-47D8-81D9-1F77D3464200}", Base); - static void Reflect(AZ::ReflectContext* context); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - AttachmentComponent::GetProvidedServices(provided); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - AttachmentComponent::GetIncompatibleServices(incompatible); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - AttachmentComponent::GetRequiredServices(required); - } - - ~EditorAttachmentComponent() override = default; - void BuildGameEntity(AZ::Entity* gameEntity) override; - - protected: - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Activate() override; - void Deactivate() override; - ////////////////////////////////////////////////////////////////////////// - - AZ::u32 OnTargetIdChanged(); - AZ::u32 OnTargetBoneChanged(); - AZ::u32 OnTargetOffsetChanged(); - AZ::u32 OnAttachedInitiallyChanged(); - AZ::u32 OnScaleSourceChanged(); - - //! Invoked when an attachment property changes - void AttachOrDetachAsNecessary(); - - //! For populating ComboBox - AZStd::vector GetTargetBoneOptions() const; - - //! Create runtime configuration from editor configuration - AttachmentConfiguration CreateAttachmentConfiguration() const; - - //! Create AZ::Transform from position and rotation - AZ::Transform GetTargetOffset() const; - - //! Attach to this entity. - AZ::EntityId m_targetId; - - //! Attach to this bone on target entity. - AZStd::string m_targetBoneName; - - //! Offset from target bone's position. - AZ::Vector3 m_positionOffset = AZ::Vector3::CreateZero(); - - //! Offset from target bone's rotation. - AZ::Vector3 m_rotationOffset = AZ::Vector3::CreateZero(); - - //! Offset from target entity's scale. - AZ::Vector3 m_scaleOffset = AZ::Vector3::CreateOne(); - - //! Observe scale information from the specified source. - AttachmentConfiguration::ScaleSource m_scaleSource = AttachmentConfiguration::ScaleSource::WorldScale; - - //! Whether to attach to target upon activation. - //! If false, the entity remains detached until Attach() is called. - bool m_attachedInitially = true; - - //! Implements actual attachment functionality - LmbrCentral::BoneFollower m_boneFollower; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp index 974dddc6e0..ceac768e79 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp @@ -21,7 +21,6 @@ #include // Component descriptors -#include "Animation/AttachmentComponent.h" #include "Audio/AudioAreaEnvironmentComponent.h" #include "Audio/AudioEnvironmentComponent.h" #include "Audio/AudioListenerComponent.h" @@ -33,7 +32,6 @@ #include "Audio/AudioSystemComponent.h" #include "Audio/AudioTriggerComponent.h" #include "Bundling/BundlingSystemComponent.h" -#include "Rendering/MeshComponent.h" #include "Ai/NavigationComponent.h" #include "Scripting/TagComponent.h" #include "Scripting/SimpleStateComponent.h" @@ -74,9 +72,6 @@ #include #include -// Asset handlers -#include - // Scriptable Ebus Registration #include "Events/ReflectScriptableEvents.h" @@ -194,7 +189,6 @@ namespace LmbrCentral : AZ::Module() { m_descriptors.insert(m_descriptors.end(), { - AttachmentComponent::CreateDescriptor(), AudioAreaEnvironmentComponent::CreateDescriptor(), AudioEnvironmentComponent::CreateDescriptor(), AudioListenerComponent::CreateDescriptor(), @@ -209,7 +203,6 @@ namespace LmbrCentral LmbrCentralAllocatorComponent::CreateDescriptor(), LmbrCentralAssetBuilderAllocatorComponent::CreateDescriptor(), LmbrCentralSystemComponent::CreateDescriptor(), - MeshComponent::CreateDescriptor(), NavigationComponent::CreateDescriptor(), SimpleStateComponent::CreateDescriptor(), SpawnerComponent::CreateDescriptor(), @@ -329,13 +322,6 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) ; } - - MaterialHandle::Reflect(serializeContext); - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - MaterialHandle::Reflect(behaviorContext); } ReflectScriptableEvents::Reflect(context); @@ -379,10 +365,6 @@ namespace LmbrCentral // Register asset handlers. Requires "AssetDatabaseService" AZ_Assert(AZ::Data::AssetManager::IsReady(), "Asset manager isn't ready!"); - auto meshAssetHandler = aznew MeshAssetHandler(); - meshAssetHandler->Register(); // registers self with AssetManager - m_assetHandlers.emplace_back(meshAssetHandler); - // Add asset types and extensions to AssetCatalog. Uses "AssetCatalogService". auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); if (assetCatalog) @@ -518,8 +500,6 @@ namespace LmbrCentral gEnv = system.GetGlobalEnvironment(); #endif - REGISTER_INT(s_meshAssetHandler_AsyncCvar, 1, 0, "Enables asynchronous loading of legacy mesh formats"); - // Enable catalog now that application's asset root is set. if (system.GetGlobalEnvironment()->IsEditor()) { @@ -536,11 +516,6 @@ namespace LmbrCentral void LmbrCentralSystemComponent::OnCrySystemShutdown([[maybe_unused]] ISystem& system) { - if (gEnv->pConsole) - { - gEnv->pConsole->UnregisterVariable(s_meshAssetHandler_AsyncCvar, true); - } - EBUS_EVENT(AZ::Data::AssetCatalogRequestBus, StopMonitoringAssets); #if !defined(AZ_MONOLITHIC_BUILD) diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp index 14091a2e7a..8536733b01 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp @@ -16,7 +16,6 @@ #include "Ai/EditorNavigationAreaComponent.h" #include "Ai/EditorNavigationSeedComponent.h" -#include "Animation/EditorAttachmentComponent.h" #include "Audio/EditorAudioAreaEnvironmentComponent.h" #include "Audio/EditorAudioEnvironmentComponent.h" #include "Audio/EditorAudioListenerComponent.h" @@ -25,7 +24,6 @@ #include "Audio/EditorAudioRtpcComponent.h" #include "Audio/EditorAudioSwitchComponent.h" #include "Audio/EditorAudioTriggerComponent.h" -#include "Rendering/EditorMeshComponent.h" #include "Scripting/EditorLookAtComponent.h" #include "Scripting/EditorRandomTimedSpawnerComponent.h" #include "Scripting/EditorSpawnerComponent.h" @@ -61,7 +59,6 @@ namespace LmbrCentral : LmbrCentralModule() { m_descriptors.insert(m_descriptors.end(), { - EditorAttachmentComponent::CreateDescriptor(), EditorAudioAreaEnvironmentComponent::CreateDescriptor(), EditorAudioEnvironmentComponent::CreateDescriptor(), EditorAudioListenerComponent::CreateDescriptor(), @@ -70,7 +67,6 @@ namespace LmbrCentral EditorAudioRtpcComponent::CreateDescriptor(), EditorAudioSwitchComponent::CreateDescriptor(), EditorAudioTriggerComponent::CreateDescriptor(), - EditorMeshComponent::CreateDescriptor(), EditorTagComponent::CreateDescriptor(), EditorSphereShapeComponent::CreateDescriptor(), EditorDiskShapeComponent::CreateDescriptor(), @@ -107,8 +103,6 @@ namespace LmbrCentral typeIds.emplace_back(descriptor->GetUuid()); } EBUS_EVENT(AzFramework::MetricsPlainTextNameRegistrationBus, RegisterForNameSending, typeIds); - - EditorMeshBus::Handler::BusConnect(); } LmbrCentralEditorModule::~LmbrCentralEditorModule() @@ -123,11 +117,6 @@ namespace LmbrCentral return requiredComponents; } - - bool LmbrCentralEditorModule::AddMeshComponentWithAssetId(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId) - { - return AddMeshComponentWithMesh(targetEntity, meshAssetId); - } } // namespace LmbrCentral AZ_DECLARE_MODULE_CLASS(Gem_LmbrCentralEditor, LmbrCentral::LmbrCentralEditorModule) diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.h b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.h index f180c21d8d..7a9dbd01ba 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.h +++ b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.h @@ -13,13 +13,6 @@ #include "LmbrCentral.h" -#include - -namespace Water -{ - class WaterVolumeConverter; -} - namespace LmbrCentral { /** @@ -31,7 +24,6 @@ namespace LmbrCentral */ class LmbrCentralEditorModule : public LmbrCentralModule - , public EditorMeshBus::Handler { public: AZ_RTTI(LmbrCentralEditorModule, "{1BF648D7-3703-4B52-A688-67C253A059F2}", LmbrCentralModule); @@ -39,7 +31,5 @@ namespace LmbrCentral LmbrCentralEditorModule(); ~LmbrCentralEditorModule(); AZ::ComponentTypeList GetRequiredSystemComponents() const override; - - bool AddMeshComponentWithAssetId(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId) override; }; } // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.cpp deleted file mode 100644 index 64254ee8f0..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.cpp +++ /dev/null @@ -1,580 +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 "LmbrCentral_precompiled.h" - -#include "EditorMeshComponent.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include // For updating nav tiles on creation of editor physics. -#include // For basic physicalization at edit-time for object snapping. -#include -#include -#include - -#include -#include -#include - -namespace LmbrCentral -{ - AZ_CVAR(bool, cl_editorMeshIntersectionDebug, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Enable editor mesh intersection debugging"); - - void EditorMeshComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("Static Mesh Render Node", &EditorMeshComponent::m_mesh) - ; - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("Mesh", "The Mesh component is the primary method of adding visual geometry to entities") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/StaticMesh.svg") - ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/StaticMesh.png") - ->Attribute(AZ::Edit::Attributes::DynamicIconOverride, &EditorMeshComponent::GetMeshViewportIconPath) - ->Attribute(AZ::Edit::Attributes::PreferNoViewportIcon, true) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-static-mesh.html") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorMeshComponent::m_mesh) - ; - - editContext->Class( - "Render Options", "Rendering options for the mesh.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) - - ->ClassElement(AZ::Edit::ClassElements::Group, "Options") - ->Attribute(AZ::Edit::Attributes::AutoExpand, false) - - ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentRenderNode::MeshRenderOptions::m_opacity, "Opacity", "Opacity value") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, 1.f) - ->Attribute(AZ::Edit::Attributes::Step, 0.1f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_maxViewDist, "Max view distance", "Maximum view distance in meters.") - ->Attribute(AZ::Edit::Attributes::Suffix, " m") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, &MeshComponentRenderNode::GetDefaultMaxViewDist) - ->Attribute(AZ::Edit::Attributes::Step, 0.1f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_viewDistMultiplier, "View distance multiplier", "Adjusts max view distance. If 1.0 then default is used. 1.1 would be 10% further than default.") - ->Attribute(AZ::Edit::Attributes::Suffix, "x") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentRenderNode::MeshRenderOptions::m_lodRatio, "LOD distance ratio", "Controls LOD ratio over distance.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Min, 0) - ->Attribute(AZ::Edit::Attributes::Max, 255) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_castShadows, "Cast shadows", "Casts shadows.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_lodBoundingBoxBased, "LOD based on Bounding Boxes", "LOD based on Bounding Boxes.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_useVisAreas, "Use VisAreas", "Allow VisAreas to control this component's visibility.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - - ->ClassElement(AZ::Edit::ClassElements::Group, "Advanced") - ->Attribute(AZ::Edit::Attributes::AutoExpand, false) - - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_rainOccluder, "Rain occluder", "Occludes dynamic raindrops.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_affectDynamicWater, "Affect dynamic water", "Will generate ripples in dynamic water.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_receiveWind, "Receive wind", "Receives wind.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMajorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_acceptDecals, "Accept decals", "Can receive decals.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_affectNavmesh, "Affect navmesh", "Will affect navmesh generation.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_visibilityOccluder, "Visibility occluder", "Is appropriate for occluding visibility of other objects.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_dynamicMesh, "Deformable mesh", "Enables vertex deformation on mesh.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMajorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_affectGI, "Affects GI", "Affects the global illumination results.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ; - - editContext->Class( - "Mesh Rendering", "Attach geometry to the entity.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::m_visible, "Visible", "Is currently visible.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::RefreshRenderState) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::m_meshAsset, "Mesh asset", "Mesh asset reference") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::OnAssetPropertyChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::m_material, "Material override", "Optionally specify an override material.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::OnAssetPropertyChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::m_renderOptions, "Render options", "Render/draw options.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::RefreshRenderState) - ; - } - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class()->RequestBus("MeshComponentRequestBus"); - } - } - - void EditorMeshComponent::Activate() - { - EditorComponentBase::Activate(); - - m_mesh.AttachToEntity(m_entity->GetId()); - bool isStatic = false; - AZ::TransformBus::EventResult(isStatic, m_entity->GetId(), &AZ::TransformBus::Events::IsStaticTransform); - m_mesh.SetTransformStaticState(isStatic); - - bool visible = false; - AzToolsFramework::EditorEntityInfoRequestBus::EventResult( - visible, GetEntityId(), &AzToolsFramework::EditorEntityInfoRequestBus::Events::IsVisible); - m_mesh.UpdateAuxiliaryRenderFlags(!visible, ERF_HIDDEN); - - // Note we are purposely connecting to buses before calling m_mesh.CreateMesh(). - // m_mesh.CreateMesh() can result in events (eg: OnMeshCreated) that we want receive. - MaterialOwnerRequestBus::Handler::BusConnect(m_entity->GetId()); - AzFramework::BoundsRequestBus::Handler::BusConnect(m_entity->GetId()); - MeshComponentRequestBus::Handler::BusConnect(m_entity->GetId()); - MeshComponentNotificationBus::Handler::BusConnect(m_entity->GetId()); - LegacyMeshComponentRequestBus::Handler::BusConnect(m_entity->GetId()); - RenderNodeRequestBus::Handler::BusConnect(m_entity->GetId()); - AZ::TransformNotificationBus::Handler::BusConnect(m_entity->GetId()); - AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusConnect(GetEntityId()); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId()); - AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler::BusConnect(GetEntityId()); - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); - AzFramework::EntityIdContextQueryBus::EventResult(m_contextId, GetEntityId(), &AzFramework::EntityIdContextQueries::GetOwningContextId); - AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusConnect({ GetEntityId(), m_contextId }); - - m_mesh.m_renderOptions.m_changeCallback = - [this]() - { - m_mesh.RefreshRenderState(); - AffectNavmesh(); - }; - - m_mesh.CreateMesh(); - } - - void EditorMeshComponent::Deactivate() - { - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); - AZ::Data::AssetBus::Handler::BusDisconnect(); - MaterialOwnerRequestBus::Handler::BusDisconnect(); - AzFramework::BoundsRequestBus::Handler::BusDisconnect(); - MeshComponentRequestBus::Handler::BusDisconnect(); - MeshComponentNotificationBus::Handler::BusDisconnect(); - LegacyMeshComponentRequestBus::Handler::BusDisconnect(); - RenderNodeRequestBus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(); - AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusDisconnect(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); - AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler::BusDisconnect(); - - AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusDisconnect(); - - m_mesh.m_renderOptions.m_changeCallback = nullptr; - - m_mesh.DestroyMesh(); - m_mesh.AttachToEntity(AZ::EntityId()); - - EditorComponentBase::Deactivate(); - } - - - void EditorMeshComponent::OnMeshCreated(const AZ::Data::Asset& asset) - { - AZ::Data::AssetBus::Handler::BusDisconnect(); - AZ::Data::AssetBus::Handler::BusConnect(asset.GetId()); - - using namespace AzFramework::RenderGeometry; - IntersectionNotificationBus::Event(m_contextId, &IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void EditorMeshComponent::OnMeshDestroyed() - { - using namespace AzFramework::RenderGeometry; - IntersectionNotificationBus::Event(m_contextId, &IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - IRenderNode* EditorMeshComponent::GetRenderNode() - { - return &m_mesh; - } - - float EditorMeshComponent::GetRenderNodeRequestBusOrder() const - { - return s_renderNodeRequestBusOrder; - } - - void EditorMeshComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - AZ_UNUSED(world); - - using namespace AzFramework::RenderGeometry; - IntersectionNotificationBus::Event(m_contextId, &IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void EditorMeshComponent::OnStaticChanged(bool isStatic) - { - m_mesh.SetTransformStaticState(isStatic); - if (m_mesh.m_renderOptions.m_changeCallback) - { - m_mesh.m_renderOptions.m_changeCallback(); - } - AffectNavmesh(); - } - - AZ::Aabb EditorMeshComponent::GetWorldBounds() - { - return m_mesh.CalculateWorldAABB(); - } - - AZ::Aabb EditorMeshComponent::GetLocalBounds() - { - return m_mesh.CalculateLocalAABB(); - } - - AzFramework::RenderGeometry::RayResult EditorMeshComponent::RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) - { - AzFramework::RenderGeometry::RayResult result; - if (!GetVisibility() && ray.m_onlyVisible) - { - return result; - } - - if (IStatObj* geometry = GetStatObj()) - { - const AZ::Vector3 rayDirection = (ray.m_endWorldPosition - ray.m_startWorldPosition); - const AZ::Transform& transform = GetTransform()->GetWorldTM(); - const AZ::Transform inverseTransform = transform.GetInverse(); - - const AZ::Vector3 rayStartLocal = inverseTransform.TransformPoint(ray.m_startWorldPosition); - const AZ::Vector3 rayDistNormLocal = inverseTransform.TransformVector(rayDirection).GetNormalized(); - - SRayHitInfo hi; - hi.inReferencePoint = AZVec3ToLYVec3(rayStartLocal); - hi.inRay = Ray(hi.inReferencePoint, AZVec3ToLYVec3(rayDistNormLocal)); - hi.bInFirstHit = true; - hi.bGetVertColorAndTC = true; - - if (geometry->RayIntersection(hi)) - { - AZ::Matrix3x4 invTransformMatrix = AZ::Matrix3x4::CreateFromTransform(inverseTransform); - invTransformMatrix.Transpose(); - - result.m_uv = LYVec2ToAZVec2(hi.vHitTC); - result.m_worldPosition = transform.TransformPoint(LYVec3ToAZVec3(hi.vHitPos)); - result.m_worldNormal = invTransformMatrix.Multiply3x3(LYVec3ToAZVec3(hi.vHitNormal)).GetNormalized(); - result.m_distance = (result.m_worldPosition - ray.m_startWorldPosition).GetLength(); - result.m_entityAndComponent = { GetEntityId(), GetId() }; - if (cl_editorMeshIntersectionDebug) - { - m_debugPos = result.m_worldPosition; - m_debugNormal = result.m_worldNormal; - } - } - } - - return result; - } - - void EditorMeshComponent::SetMeshAsset(const AZ::Data::AssetId& id) - { - m_mesh.SetMeshAsset(id); - AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationRequests::AddDirtyEntity, - GetEntityId()); - } - - void EditorMeshComponent::SetMaterial(_smart_ptr material) - { - m_mesh.SetMaterial(material); - - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_AttributesAndValues); - } - - _smart_ptr EditorMeshComponent::GetMaterial() - { - return m_mesh.GetMaterial(); - } - - void EditorMeshComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId) - { - SetMeshAsset(assetId); - } - - void EditorMeshComponent::OnEntityVisibilityChanged(bool visibility) - { - m_mesh.UpdateAuxiliaryRenderFlags(!visibility, ERF_HIDDEN); - m_mesh.RefreshRenderState(); - } - - static void DecideColor( - const bool selected, const bool mouseHovered, const bool visible, - ColorB& triangleColor, ColorB& lineColor) - { - const ColorB translucentPurple = ColorB(250, 0, 250, 30); - - // default both colors to hidden - triangleColor = ColorB(AZ::u32(0)); - lineColor = ColorB(AZ::u32(0)); - - if (selected) - { - if (!visible) - { - lineColor = Col_Black; - - if (mouseHovered) - { - triangleColor = translucentPurple; - } - } - } - else - { - if (mouseHovered) - { - triangleColor = translucentPurple; - lineColor = AZColorToLYColorF(AzFramework::ViewportColors::HoverColor); - } - } - } - - void EditorMeshComponent::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - const bool mouseHovered = m_accentType == AzToolsFramework::EntityAccentType::Hover; - - IEditor* editor = nullptr; - AzToolsFramework::EditorRequests::Bus::BroadcastResult(editor, &AzToolsFramework::EditorRequests::GetEditor); - - const bool highlightGeometryOnMouseHover = editor->GetEditorSettings()->viewports.bHighlightMouseOverGeometry; - // if the mesh component is not visible, when selected we still draw the wireframe to indicate the shapes extent and position - const bool highlightGeometryWhenSelected = editor->GetEditorSettings()->viewports.bHighlightSelectedGeometry || !GetVisibility(); - - if ((!IsSelected() && mouseHovered && highlightGeometryOnMouseHover) || (IsSelected() && highlightGeometryWhenSelected)) - { - AZ::Transform transform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - - ColorB triangleColor, lineColor; - DecideColor(IsSelected(), mouseHovered, GetVisibility(), triangleColor, lineColor); - - SGeometryDebugDrawInfo dd; - dd.tm = AZTransformToLYTransform(transform); - dd.bExtrude = true; - dd.color = triangleColor; - dd.lineColor = lineColor; - - if (IStatObj* geometry = GetStatObj()) - { - geometry->DebugDraw(dd); - } - } - - if (cl_editorMeshIntersectionDebug) - { - debugDisplay.DrawArrow(m_debugPos, m_debugPos + (0.1f * m_debugNormal), 0.1f); - debugDisplay.DrawBall(m_debugPos, 0.03f); - debugDisplay.DrawWireBox(GetWorldBounds().GetMin(), GetWorldBounds().GetMax()); - } - } - - void EditorMeshComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - if (auto meshComponent = gameEntity->CreateComponent()) - { - m_mesh.CopyPropertiesTo(meshComponent->m_meshRenderNode); - // ensure we do not copy across the edit time entity id - meshComponent->m_meshRenderNode.m_renderOptions.m_attachedToEntityId = AZ::EntityId(); - } - } - - - IStatObj* EditorMeshComponent::GetStatObj() - { - return m_mesh.GetEntityStatObj(); - } - - bool EditorMeshComponent::GetVisibility() - { - return m_mesh.GetVisible(); - } - - void EditorMeshComponent::SetVisibility(bool visible) - { - m_mesh.SetVisible(visible); - } - - void EditorMeshComponent::AffectNavmesh() - { - // Refresh the nav tile when the flag changes. - INavigationSystem* pNavigationSystem = nullptr; // INavigationSystem will be converted to an AZInterface (LY-111343) - if (pNavigationSystem) - { - pNavigationSystem->WorldChanged(AZAabbToLyAABB(GetWorldBounds())); - } - } - - AZStd::string_view staticViewportIcon = "Icons/Components/Viewport/StaticMesh.png"; - AZStd::string_view dynamicViewportIcon = "Icons/Components/Viewport/DynamicMesh.png"; - AZStd::string EditorMeshComponent::GetMeshViewportIconPath() const - { - if (m_mesh.m_renderOptions.IsStatic()) - { - return staticViewportIcon; - } - - return dynamicViewportIcon; - } - - void EditorMeshComponent::OnAssetReloaded(AZ::Data::Asset /*asset*/) - { - using namespace AzFramework::RenderGeometry; - IntersectionNotificationBus::Event(m_contextId, &IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void EditorMeshComponent::OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& /*assetInfo*/) - { - if (m_mesh.m_meshAsset.GetId() != assetId) - { - return; - } - // If this editor mesh component is loaded and active in the level, it's referencing an asset that was just removed. - // Clearing this asset reference will help visualize this change. Note that this won't clear all references to this - // asset automatically, any levels that aren't loaded won't have the reference removed. - - // Set the mesh asset to invalid on the main thread. - AZ::TickBus::QueueFunction([this, assetId]() - { - // Emit a warning so users know this has occurred, it may not be intentional because the asset was removed before - // the references were cleared. Do this on the main thread. - AZ_Warning("EditorMeshComponent", false, "asset with ID %s referenced by entity named '%s' with ID %s was removed, this reference will be cleared on the associated component.", - assetId.ToString().c_str(), - GetEntity() ? GetEntity()->GetName().c_str() : "Invalid entity", - GetEntityId().ToString().c_str()); - - m_mesh.DestroyMesh(); - AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationRequests::AddDirtyEntity, - GetEntityId()); - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_AttributesAndValues); - }); - } - - AZ::Aabb EditorMeshComponent::GetEditorSelectionBoundsViewport( - const AzFramework::ViewportInfo& /*viewportInfo*/) - { - return GetWorldBounds(); - } - - bool EditorMeshComponent::EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& /*viewportInfo*/, - const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) - { - if (IStatObj* geometry = GetStatObj()) - { - AZ::Transform transform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - auto legacyTransform = AZTransformToLYTransform(transform); - const auto legacySrc = AZVec3ToLYVec3(src); - const auto legacyDir = AZVec3ToLYVec3(dir); - - const Matrix34 inverseTM = legacyTransform.GetInverted(); - const Vec3 raySrcLocal = inverseTM.TransformPoint(legacySrc); - const Vec3 rayDirLocal = inverseTM.TransformVector(legacyDir).GetNormalized(); - - SRayHitInfo hi; - hi.inReferencePoint = raySrcLocal; - hi.inRay = Ray(raySrcLocal, rayDirLocal); - if (geometry->RayIntersection(hi)) - { - const Vec3 worldHitPos = legacyTransform.TransformPoint(hi.vHitPos); - distance = legacySrc.GetDistance(worldHitPos); - return true; - } - } - - return false; - } - - void EditorMeshComponent::OnAccentTypeChanged(AzToolsFramework::EntityAccentType accent) - { - m_accentType = accent; - } - - bool AddMeshComponentWithMesh(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId) - { - // Error handling for failures should be done at the call site, this function can be invoked from Python. - if (!targetEntity.IsValid()) - { - return false; - } - AZ::ComponentTypeList componentsToAdd; - componentsToAdd.push_back(AZ::AzTypeInfo::Uuid()); - - AZStd::vector entityList; - entityList.push_back(targetEntity); - - AzToolsFramework::EntityCompositionRequests::AddComponentsOutcome outcome = - AZ::Failure(AZStd::string("Failed to call AddComponentsToEntities on EntityCompositionRequestBus")); - AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(outcome, &AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, entityList, componentsToAdd); - - if (!outcome.IsSuccess()) - { - return false; - } - - AZ::Data::AssetId meshAsset(meshAssetId); - - // If necessary, the call site can verify if the mesh was actually set. - LmbrCentral::MeshComponentRequestBus::Event( - targetEntity, - &LmbrCentral::MeshComponentRequestBus::Events::SetMeshAsset, - meshAsset); - return true; - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.h deleted file mode 100644 index 7617673e3b..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.h +++ /dev/null @@ -1,175 +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. -* -*/ -#pragma once - -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include "MeshComponent.h" - - -struct IPhysicalEntity; - -namespace LmbrCentral -{ - /** - * In-editor mesh component. - * Conducts some additional listening and operations to ensure immediate - * effects when changing fields in the editor. - */ - class EditorMeshComponent - : public AzToolsFramework::Components::EditorComponentBase - , public AZ::Data::AssetBus::Handler - , private AzFramework::AssetCatalogEventBus::Handler - , public AzFramework::BoundsRequestBus::Handler - , private AzFramework::RenderGeometry::IntersectionRequestBus::Handler - , private MeshComponentRequestBus::Handler - , private MaterialOwnerRequestBus::Handler - , private MeshComponentNotificationBus::Handler - , private RenderNodeRequestBus::Handler - , private AZ::TransformNotificationBus::Handler - , private AzToolsFramework::EntitySelectionEvents::Bus::Handler - , private AzToolsFramework::EditorVisibilityNotificationBus::Handler - , private AzFramework::EntityDebugDisplayEventBus::Handler - , private LegacyMeshComponentRequestBus::Handler - , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler - , private AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler - { - public: - AZ_COMPONENT(EditorMeshComponent, "{FC315B86-3280-4D03-B4F0-5553D7D08432}", AzToolsFramework::Components::EditorComponentBase) - - ~EditorMeshComponent() = default; - - const float s_renderNodeRequestBusOrder = 100.f; - - // AZ::Component overrides ... - void Activate() override; - void Deactivate() override; - - // BoundsRequestBus and MeshComponentRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - - // IntersectionRequestBus overrides ... - AzFramework::RenderGeometry::RayResult RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) override; - - // MeshComponentRequestBus overrides ... - void SetMeshAsset(const AZ::Data::AssetId& id) override; - AZ::Data::Asset GetMeshAsset() override { return m_mesh.GetMeshAsset(); } - void SetVisibility(bool visible) override; - bool GetVisibility() override; - - // MaterialOwnerRequestBus overrides ... - void SetMaterial(_smart_ptr) override; - _smart_ptr GetMaterial() override; - - // MeshComponentNotificationBus overrides ... - void OnMeshCreated(const AZ::Data::Asset& asset) override; - void OnMeshDestroyed() override; - - // RenderNodeRequestBus overrides ... - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - - // TransformNotificationBus overrides ... - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - void OnStaticChanged(bool isStatic) override; - - // EditorVisibilityNotificationBus overrides ... - void OnEntityVisibilityChanged(bool visibility) override; - - // AzFramework::EntityDebugDisplayEventBus overrides .... - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - //! Called when you want to change the game asset through code (like when creating components based on assets). - void SetPrimaryAsset(const AZ::Data::AssetId& assetId) override; - - // LegacyMeshComponentRequests overrides ... - IStatObj* GetStatObj() override; - - // EditorComponentBase overrides ... - void BuildGameEntity(AZ::Entity* gameEntity) override; - - // AZ::Data::AssetBus overrides ... - void OnAssetReloaded(AZ::Data::Asset asset) override; - - // AzFramework::AssetCatalogEventBus overrides ... - void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override; - - // EditorComponentSelectionRequestsBus overrides ... - AZ::Aabb GetEditorSelectionBoundsViewport( - const AzFramework::ViewportInfo& viewportInfo) override; - bool EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, - const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) override; - bool SupportsEditorRayIntersect() override { return true; } - - // EditorComponentSelectionNotificationsBus overrides ... - void OnAccentTypeChanged(AzToolsFramework::EntityAccentType accent) override; - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("MeshService", 0x71d8a455)); - provided.push_back(AZ_CRC("LegacyMeshService", 0xb462a299)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - dependent.push_back(AZ_CRC("EditorVisibilityService", 0x90888caf)); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("MeshService", 0x71d8a455)); - incompatible.push_back(AZ_CRC("LegacyMeshService", 0xb462a299)); - } - - static void Reflect(AZ::ReflectContext* context); - - protected: - - // Decides if this mesh affects the navmesh or not. - void AffectNavmesh(); - - AZStd::string GetMeshViewportIconPath() const; - - AzToolsFramework::EntityAccentType m_accentType = AzToolsFramework::EntityAccentType::None; ///< State of the entity selection in the viewport. - MeshComponentRenderNode m_mesh; ///< IRender node implementation. - - AzFramework::EntityContextId m_contextId; - AZ::Vector3 m_debugPos = AZ::Vector3(0); - AZ::Vector3 m_debugNormal = AZ::Vector3(0); - }; - - // Helper function useful for automation. - bool AddMeshComponentWithMesh(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId); -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MaterialHandle.cpp b/Gems/LmbrCentral/Code/Source/Rendering/MaterialHandle.cpp deleted file mode 100644 index 6171951398..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MaterialHandle.cpp +++ /dev/null @@ -1,399 +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 "LmbrCentral_precompiled.h" -#include -#include -#include -#include -#include -#include -#include - - -namespace LmbrCentral -{ - // Provides a set of reflected functions for operating on IMaterial through a MaterialHandle - // We keep these cpp-private instead of putting them in the header to align with the fact that - // MaterialHandle is not useful on the code side, and only exists to support reflection. If it - // were possible to reflect IMaterial directly, we'd still have this same set of functions here. - namespace MaterialHandleFunctions - { - void SetParamVector4(MaterialHandle* thisPtr, const AZStd::string& name, const AZ::Vector4& value) - { - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec4 vec4(value.GetX(), value.GetY(), value.GetZ(), value.GetW()); - thisPtr->m_material->SetGetMaterialParamVec4(name.c_str(), vec4, false, true); - } - else - { - AZ_Error("Material", false, "SetParamVector4 only accepts single Materials, not Material Groups"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to SetParamVector4"); - } - } - - void SetParamVector3(MaterialHandle* thisPtr, const AZStd::string& name, const AZ::Vector3& value) - { - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec3 vec3(value.GetX(), value.GetY(), value.GetZ()); - thisPtr->m_material->SetGetMaterialParamVec3(name.c_str(), vec3, false, true); - } - else - { - AZ_Error("Material", false, "SetParamVector3 only accepts single Materials, not Material Groups"); - } - - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to SetParamVector3"); - } - } - - void SetParamColor(MaterialHandle* thisPtr, const AZStd::string& name, const AZ::Color& value) - { - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - // When value had garbage data is was not only making the material render black, it also corrupted something - // on the GPU, making black boxes flicker over the sky. - // It was garbage due to a bug in the Color object node where all fields have to be set to some value manually; the default is not 0. - if ((value.GetR() < 0 || value.GetR() > 1) || - (value.GetG() < 0 || value.GetG() > 1) || - (value.GetB() < 0 || value.GetB() > 1) || - (value.GetA() < 0 || value.GetA() > 1)) - { - return; - } - - Vec4 vec4(value.GetR(), value.GetG(), value.GetB(), value.GetA()); - thisPtr->m_material->SetGetMaterialParamVec4(name.c_str(), vec4, false, true); - } - else - { - AZ_Error("Material", false, "SetParamColor only accepts single Materials, not Material Groups"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to SetParamColor"); - } - } - - void SetParamFloat(MaterialHandle* thisPtr, const AZStd::string& name, float value) - { - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - thisPtr->m_material->SetGetMaterialParamFloat(name.c_str(), value, false, true); - } - else - { - AZ_Error("Material", false, "SetParamFloat only accepts single Materials, not Material Groups"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to SetParamFloat"); - } - } - - AZ::Vector4 GetParamVector4(MaterialHandle* thisPtr, const AZStd::string& name) - { - AZ::Vector4 value = AZ::Vector4::CreateZero(); - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec4 vec4; - if (thisPtr->m_material->SetGetMaterialParamVec4(name.c_str(), vec4, true, true)) - { - value.Set(vec4.x, vec4.y, vec4.z, vec4.w); - } - } - else - { - AZ_Error("Material", false, "GetParamVector4 only accepts single Materials, not Material Groups"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to GetParamVector4"); - } - - return value; - } - - AZ::Vector3 GetParamVector3(MaterialHandle* thisPtr, const AZStd::string& name) - { - AZ::Vector3 value = AZ::Vector3::CreateZero(); - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec3 vec3; - if (thisPtr->m_material->SetGetMaterialParamVec3(name.c_str(), vec3, true, true)) - { - value.Set(vec3.x, vec3.y, vec3.z); - } - } - else - { - AZ_Error("Material", false, "GetParamVector3 only accepts single Materials, not Material Groups"); - } - - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to GetParamVector3"); - } - - return value; - } - - AZ::Color GetParamColor(MaterialHandle* thisPtr, const AZStd::string& name) - { - AZ::Color value = AZ::Color::CreateZero(); - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec4 vec4; - if (thisPtr->m_material->SetGetMaterialParamVec4(name.c_str(), vec4, true, true)) - { - value.Set(vec4.x, vec4.y, vec4.z, vec4.w); - } - } - else - { - AZ_Error("Material", false, "GetParamColor only accepts single Materials, not Material Groups"); - } - - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to GetParamColor"); - } - - return value; - } - - float GetParamFloat(MaterialHandle* thisPtr, const AZStd::string& name) - { - float value = 0.0f; - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - thisPtr->m_material->SetGetMaterialParamFloat(name.c_str(), value, true, true); - } - else - { - AZ_Error("Material", false, "GetParamFloat only accepts single Materials, not Material Groups"); - } - - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to GetParamFloat"); - } - - return value; - } - - MaterialHandle Clone(MaterialHandle* thisPtr) - { - MaterialHandle copy; - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsSubMaterial()) - { - copy.m_material = gEnv->p3DEngine->GetMaterialManager()->CloneMultiMaterial(thisPtr->m_material); - } - else - { - AZ_Error("Material", false, "Clone does not support Sub-Materials"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to Clone"); - } - - return copy; - } - - MaterialHandle FindByName(const AZStd::string& name) - { - MaterialHandle found; - found.m_material = gEnv->p3DEngine->GetMaterialManager()->FindMaterial(name.c_str()); - return found; - } - - MaterialHandle LoadByName(const AZStd::string& name) - { - LmbrCentral::MaterialHandle handle; - handle.m_material = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(name.c_str(), false, false, IMaterialManager::ELoadingFlagsPreviewMode); - - AZ_Error(nullptr, handle.m_material, "Material.LoadByName('%s') failed", name.c_str()); - - return handle; - } - - _smart_ptr GetSubMaterialHelper(_smart_ptr materialGroup, int materialId) - { - if (materialGroup) - { - if (materialGroup->IsMaterialGroup()) - { - int subMtlCount = materialGroup->GetSubMtlCount(); - if (materialId >= 1 && materialId <= subMtlCount) - { - return materialGroup->GetSubMtl(materialId-1); - } - else - { - AZ_Error("Material", false, "Invalid Material ID %d passed to FindSubMaterial. %d Materials are available.", materialId, subMtlCount); - } - } - else - { - AZ_Error("Material", false, "FindSubMaterial does not support single Material"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to FindSubMaterial."); - } - - return nullptr; - } - - - - MaterialHandle FindSubMaterial(const AZStd::string& name, int id, bool shouldLoad) - { - MaterialHandle found; - _smart_ptr materialGroup = gEnv->p3DEngine->GetMaterialManager()->FindMaterial(name.c_str()); - if (materialGroup) - { - found.m_material = GetSubMaterialHelper(materialGroup, id); - } - else - { - if (shouldLoad) - { - materialGroup = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(name.c_str(), false, false, IMaterialManager::ELoadingFlagsPreviewMode); - if (materialGroup) - { - found.m_material = GetSubMaterialHelper(materialGroup, id); - } - else - { - AZ_Error("Material", false, "Load Material '%s' failed", name.c_str()); - } - } - else - { - AZ_Warning("Material", false, "No Sub-Material is found since Material '%s' is not loaded", name.c_str()); - } - } - - return found; - } - - AZStd::string ToString(MaterialHandle* thisPtr) - { - if (!thisPtr || !thisPtr->m_material) - { - return "Invalid"; - } - else - { - return thisPtr->m_material->GetName(); - } - } - } - - void MaterialHandle::Reflect(AZ::SerializeContext* serializeContext) - { - // This is required in order to create a MaterialHandle variable in script canvas. - serializeContext->Class()->Version(0); - } - - void MaterialHandle::Reflect(AZ::BehaviorContext* behaviorContext) - { - const char* setMaterialParamTooltip = "Sets a Material param value"; - const char* getMaterialParamTooltip = "Returns a Material param value"; - AZ::BehaviorParameterOverrides setMaterialDetails = { "Material", "The Material to modify" }; - AZ::BehaviorParameterOverrides getMaterialDetails = { "Material", "The Material to inspect" }; - AZ::BehaviorParameterOverrides setParamNameDetails = { "ParamName", "The name of the Material param to set" }; - AZ::BehaviorParameterOverrides getParamNameDetails = { "ParamName", "The name of the Material param to return" }; - const AZStd::array getMaterialParamArgs = { { getMaterialDetails,getParamNameDetails } }; - const char* newValueTooltip = "The new value to apply"; - - behaviorContext->Class("Material") - ->Attribute(AZ::Script::Attributes::Category, "Rendering") - ->Method("ToString", &MaterialHandleFunctions::ToString) - ->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) // Hide this node because it doesn't really make sense for the user (GetName would be better), but we need "ToString" in order to provide nice output in Material Variable nodes in script canvas. - ->Method("FindByName", &MaterialHandleFunctions::FindByName, { { { "Name", "Full path name of the Material" } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Find a Material by name. Returns Invalid if the Material is not already loaded.") - ->Method("LoadByName", &MaterialHandleFunctions::LoadByName, { { { "Name", "Full path name of the Material" } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Find a Material by name, loading the asset if needed. Returns Invalid if the Material could not be found or loaded.") - ->Method("Clone", &MaterialHandleFunctions::Clone, { { { "Material", "The Material to clone" } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Creates a copy of the given Material.") - ->Method("FindSubMaterial", &MaterialHandleFunctions::FindSubMaterial, - { { { "Name", "Full path name of the Material Group to get a Sub-Material from" }, - { "MaterialID", "The ID of a Sub-Material to access. IDs start at 1.", behaviorContext->MakeDefaultValue(1) }, - { "ShouldLoad", "Whether to load the Material Group or not if it's not loaded", behaviorContext->MakeDefaultValue(true) } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Find a Sub-Material from a Material Group by specified Material ID. Returns Invalid if the Material Group could not be found or loaded or the Sub-Material could not be found.") - ->Method("SetParamVector4", &MaterialHandleFunctions::SetParamVector4, - { { setMaterialDetails,setParamNameDetails,{ "Vector4", newValueTooltip } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Method("SetParamVector3", &MaterialHandleFunctions::SetParamVector3, - { { setMaterialDetails,setParamNameDetails,{ "Vector3", newValueTooltip } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Method("SetParamColor", &MaterialHandleFunctions::SetParamColor, - { { setMaterialDetails,setParamNameDetails,{ "Color", newValueTooltip } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Method("SetParamNumber", &MaterialHandleFunctions::SetParamFloat, // Using "ParamNumber" instead of "ParamFloat" because in Script Canvas all primitives are just "numbers" - { { setMaterialDetails,setParamNameDetails,{ "Number", newValueTooltip } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Method("GetParamVector4", &MaterialHandleFunctions::GetParamVector4, getMaterialParamArgs) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Method("GetParamVector3", &MaterialHandleFunctions::GetParamVector3, getMaterialParamArgs) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Method("GetParamColor", &MaterialHandleFunctions::GetParamColor, getMaterialParamArgs) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Method("GetParamNumber", &MaterialHandleFunctions::GetParamFloat, getMaterialParamArgs) // Using "ParamNumber" instead of "ParamFloat" because in Script Canvas all primitives are just "numbers" - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ; - } -} diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.cpp b/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.cpp deleted file mode 100644 index 18b9003e4f..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.cpp +++ /dev/null @@ -1,265 +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 "LmbrCentral_precompiled.h" - -#include -#include -#include -#include -#include -#include - -#include -#include "MeshAssetHandler.h" - -#include -#include - -namespace LmbrCentral -{ - ////////////////////////////////////////////////////////////////////////// - const AZStd::string MeshAssetHandlerHelper::s_assetAliasToken = "@assets@/"; - - // what mesh do we use as a placeholder when its currently busy compiling? - static const char* g_meshCompilingSubstituteAsset = "engineassets/objects/default.cgf"; - - MeshAssetHandlerHelper::MeshAssetHandlerHelper() - : m_asyncLoadCvar(nullptr) - { - } - - void MeshAssetHandlerHelper::StripAssetAlias(const char*& assetPath) - { - const size_t assetAliasTokenLen = s_assetAliasToken.size() - 1; - if (0 == strncmp(assetPath, s_assetAliasToken.c_str(), assetAliasTokenLen)) - { - assetPath += assetAliasTokenLen; - } - } - - ICVar* MeshAssetHandlerHelper::GetAsyncLoadCVar() - { - if (!m_asyncLoadCvar) - { - m_asyncLoadCvar = gEnv->pConsole->GetCVar(s_meshAssetHandler_AsyncCvar); - } - - return m_asyncLoadCvar; - } - - ////////////////////////////////////////////////////////////////////////// - // Static Mesh Asset Handler - ////////////////////////////////////////////////////////////////////////// - - void AsyncStatObjLoadCallback(const AZ::Data::Asset& asset, _smart_ptr statObj) - { - if (statObj) - { - asset.Get()->m_statObj = statObj; - } - else - { -#if defined(AZ_ENABLE_TRACING) - AZStd::string assetDescription = asset.ToString(); - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetDescription, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetPathById, asset.GetId()); - AZ_Error("MeshAssetHandler", false, "Failed to load mesh asset %s", assetDescription.c_str()); -#endif // AZ_ENABLE_TRACING - } - } - - MeshAssetHandler::~MeshAssetHandler() - { - Unregister(); - } - - AZ::Data::AssetPtr MeshAssetHandler::CreateAsset([[maybe_unused]] const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) - { - (void)type; - - AZ_Assert(type == AZ::AzTypeInfo::Uuid(), "Invalid asset type! We handle only 'MeshAsset'"); - - return aznew MeshAsset(); - } - - AZ::Data::AssetId MeshAssetHandler::AssetMissingInCatalog([[maybe_unused]] const AZ::Data::Asset& asset) - { - // if tracing is disabled, we are likely in a situation where we specifically don't want any diagnostic information or "errors" to appear - // so in that case, don't load anything, don't substitute anything, don't escalate anything, just let the empty blank asset return. -#if defined(AZ_ENABLE_TRACING) - if (asset.GetId().IsValid()) - { - // find out whether its still compiling or it will never be available because its source file is missing. - // this also escalates it, if found, to the top of the build queue: - AzFramework::AssetSystem::AssetStatus statusResult = AzFramework::AssetSystem::AssetStatus_Unknown; - AzFramework::AssetSystemRequestBus::BroadcastResult(statusResult, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, asset.GetId()); - - if ((statusResult == AzFramework::AssetSystem::AssetStatus_Compiling) || (statusResult == AzFramework::AssetSystem::AssetStatus_Queued)) - { - // note that we can also check other codes and substitute other meshes if we want, here... - // its currently compiling and will finish soon. - // substitute a placeholder mesh: - - if (!m_missingMeshAssetId.IsValid()) - { - // substitute the missing mesh assetId so that there's at least something to render that indicates a problem - // in builds where there is no diagnostics or tracing, don't substitute anything, to prefer that there's no visual indication that - // something is wrong in shipped games. - AZ::Data::AssetCatalogRequestBus::BroadcastResult(m_missingMeshAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, g_meshCompilingSubstituteAsset, azrtti_typeid(), false); - AZ_Error("Mesh Asset Handler", m_missingMeshAssetId.IsValid(), "Attempted to substitute %s for a missing asset, but it is also missing!", g_meshCompilingSubstituteAsset); - } - - if (m_missingMeshAssetId.IsValid()) - { - AZ_TracePrintf("MeshAssetHandler", " - substituting with default asset ID %s\n", m_missingMeshAssetId.ToString().c_str()); - // substitute the missing mesh asset. - return m_missingMeshAssetId; - } - } - } -#endif // defined(AZ_ENABLE_TRACING) - - // otherwise, if we get here, it means that either it was truly missing, in which case let an error occur, or the missing default substitute asset - // is also itself missing! - return AZ::Data::AssetId(); - } - - - - void MeshAssetHandler::GetCustomAssetStreamInfoForLoad(AZ::Data::AssetStreamInfo& streamInfo) - { - // The StatObj system only takes in a file name for loading, not a memory buffer. - // If we set our stream data length to 0, the asset system will skip any file I/O for reading the data, and will instead - // go directly into the AssetHandler for processing. - streamInfo.m_dataLen = 0; - } - - AZ::Data::AssetHandler::LoadResult MeshAssetHandler::LoadAssetData( - const AZ::Data::Asset& asset, - AZStd::shared_ptr stream, - const AZ::Data::AssetFilterCB& /*assetLoadFilterCB*/) - { - const char* assetPath = stream->GetFilename(); - - AZ_Assert(asset.GetType() == AZ::AzTypeInfo::Uuid(), "Invalid asset type! We only load 'MeshAsset'"); - if (MeshAsset* meshAsset = asset.GetAs()) - { - AZ_Assert(!meshAsset->m_statObj.get(), "Attempting to create static mesh without cleaning up the old one."); - - // Strip the alias. StatObj instances are stored in a dictionary by their path, - // so to share instances with legacy cry entities, we need to use the same un-aliased format. - StripAssetAlias(assetPath); - - // Temporary cvar guard while async loading of legacy mesh formats is stabilized. - ICVar* cvar = GetAsyncLoadCVar(); - if (!cvar || cvar->GetIVal() == 0) - { - if (gEnv->mMainThreadId != CryGetCurrentThreadId()) - { - AZStd::binary_semaphore signaller; - - auto callback = [&asset, &signaller](IStatObj* obj) - { - AsyncStatObjLoadCallback(asset, obj); - signaller.release(); - }; - - gEnv->p3DEngine->LoadStatObjAsync(callback, assetPath); - signaller.acquire(); - } - else - { - AsyncStatObjLoadCallback(asset, gEnv->p3DEngine->LoadStatObjAutoRef(assetPath)); - } - } - else - { - _smart_ptr statObj = gEnv->p3DEngine->LoadStatObjAutoRef(assetPath); - - if (statObj) - { - meshAsset->m_statObj = statObj; - } - else - { -#if defined(AZ_ENABLE_TRACING) - AZStd::string assetDescription = asset.GetId().ToString(); - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetDescription, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetPathById, asset.GetId()); - AZ_Error("MeshAssetHandler", false, "Failed to load mesh asset \"%s\".", assetDescription.c_str()); -#endif // AZ_ENABLE_TRACING - } - } - - return AZ::Data::AssetHandler::LoadResult::LoadComplete; - } - return AZ::Data::AssetHandler::LoadResult::Error; - } - - void MeshAssetHandler::DestroyAsset(AZ::Data::AssetPtr ptr) - { - delete ptr; - } - - void MeshAssetHandler::GetHandledAssetTypes(AZStd::vector& assetTypes) - { - assetTypes.push_back(AZ::AzTypeInfo::Uuid()); - } - - void MeshAssetHandler::Register() - { - AZ_Assert(AZ::Data::AssetManager::IsReady(), "Asset manager isn't ready!"); - AZ::Data::AssetManager::Instance().RegisterHandler(this, AZ::AzTypeInfo::Uuid()); - - AZ::AssetTypeInfoBus::Handler::BusConnect(AZ::AzTypeInfo::Uuid()); - } - - void MeshAssetHandler::Unregister() - { - AZ::AssetTypeInfoBus::Handler::BusDisconnect(AZ::AzTypeInfo::Uuid()); - - if (AZ::Data::AssetManager::IsReady()) - { - AZ::Data::AssetManager::Instance().UnregisterHandler(this); - } - } - - AZ::Data::AssetType MeshAssetHandler::GetAssetType() const - { - return AZ::AzTypeInfo::Uuid(); - } - - const char* MeshAssetHandler::GetAssetTypeDisplayName() const - { - return "Static Mesh"; - } - - const char* MeshAssetHandler::GetGroup() const - { - return "Geometry"; - } - - const char* MeshAssetHandler::GetBrowserIcon() const - { - return "Icons/Components/StaticMesh.svg"; - } - - AZ::Uuid MeshAssetHandler::GetComponentTypeId() const - { - return AZ::Uuid("{FC315B86-3280-4D03-B4F0-5553D7D08432}"); - } - - void MeshAssetHandler::GetAssetTypeExtensions(AZStd::vector& extensions) - { - extensions.push_back(CRY_GEOMETRY_FILE_EXT); - } - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.h b/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.h deleted file mode 100644 index 00936316f5..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.h +++ /dev/null @@ -1,97 +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. -* -*/ -#pragma once - -#include -#include -#include -#include - -struct ICVar; - -namespace LmbrCentral -{ - static const char* s_meshAssetHandler_AsyncCvar = "az_Asset_EnableAsyncMeshLoading"; - - /** - * Base class for mesh asset handlers. Contains shared utilities and functionality. - */ - class MeshAssetHandlerHelper - { - public: - - MeshAssetHandlerHelper(); - - protected: - - /** - * Removes the asset alias from a string - * - * StatObjs, CharacterInstances and GeometryCaches are stored in - * dictionaries by their path which is not aliased like the new AZ systems. - * To look up mesh instances we need the un-aliased path. - * - * This method assumes that the alias will be at the beginning of the string. - * - * @param assetPath The asset path string to remove the alias from - */ - void StripAssetAlias(const char*& assetPath); - - static const AZStd::string s_assetAliasToken; //< The token used to strip the asset alias in StripAssetAlias - - ICVar* GetAsyncLoadCVar(); - ICVar* m_asyncLoadCvar; - }; - - /** - * Handler for static mesh assets (cgf). - */ - class MeshAssetHandler - : public AZ::Data::AssetHandler - , public AZ::AssetTypeInfoBus::Handler - , private MeshAssetHandlerHelper - { - public: - - AZ_CLASS_ALLOCATOR(MeshAssetHandler, AZ::SystemAllocator, 0); - - ~MeshAssetHandler() override; - - ////////////////////////////////////////////////////////////////////////////////////////////// - // AZ::Data::AssetHandler - AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override; - void GetCustomAssetStreamInfoForLoad(AZ::Data::AssetStreamInfo& streamInfo) override; - AZ::Data::AssetHandler::LoadResult LoadAssetData( - const AZ::Data::Asset& asset, - AZStd::shared_ptr stream, - const AZ::Data::AssetFilterCB& assetLoadFilterCB) override; - AZ::Data::AssetId AssetMissingInCatalog(const AZ::Data::Asset& asset) override; - void DestroyAsset(AZ::Data::AssetPtr ptr) override; - void GetHandledAssetTypes(AZStd::vector& assetTypes) override; - ////////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////////// - // AZ::AssetTypeInfoBus::Handler - AZ::Data::AssetType GetAssetType() const override; - const char* GetAssetTypeDisplayName() const override; - const char* GetGroup() const override; - const char* GetBrowserIcon() const override; - AZ::Uuid GetComponentTypeId() const override; - void GetAssetTypeExtensions(AZStd::vector& extensions) override; - ////////////////////////////////////////////////////////////////////////////////////////////// - - void Register(); - void Unregister(); - - AZ::Data::AssetId m_missingMeshAssetId; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.cpp deleted file mode 100644 index 0ee72b62cf..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.cpp +++ /dev/null @@ -1,1228 +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 "LmbrCentral_precompiled.h" -#include "MeshComponent.h" -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -namespace LmbrCentral -{ - ////////////////////////////////////////////////////////////////////////// - - //! Handler/binding code that is required for Behavior Context reflection of EBus Notifications. - class MaterialOwnerNotificationBusBehaviorHandler : public MaterialOwnerNotificationBus::Handler, public AZ::BehaviorEBusHandler - { - public: - AZ_EBUS_BEHAVIOR_BINDER(MaterialOwnerNotificationBusBehaviorHandler, "{77705C0E-5ADE-496C-85FF-9278565E278E}", AZ::SystemAllocator - , OnMaterialOwnerReady); - - void OnMaterialOwnerReady() override - { - Call(FN_OnMaterialOwnerReady); - } - }; - - ////////////////////////////////////////////////////////////////////////// - - AZ::BehaviorParameterOverrides CreateMaterialIdDetails(AZ::BehaviorContext* behaviorContext) - { - return{ "MaterialID", "The ID of a Material slot to access, if the Owner has multiple Materials. IDs start at 1.", behaviorContext->MakeDefaultValue(1) }; - } - - AZStd::array GetMaterialParamArgs(AZ::BehaviorContext* behaviorContext) - { - AZ::BehaviorParameterOverrides getParamNameDetails = { "ParamName", "The name of the Material param to return" }; - return{ { getParamNameDetails, CreateMaterialIdDetails(behaviorContext) } }; - } - - void MeshComponent::Reflect(AZ::ReflectContext* context) - { - MeshComponentRenderNode::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Static Mesh Render Node", &MeshComponent::m_meshRenderNode); - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("MeshComponentRequestBus") - ->Event("SetVisibility", &MeshComponentRequestBus::Events::SetVisibility) - ->Event("GetVisibility", &MeshComponentRequestBus::Events::GetVisibility) - ->VirtualProperty("Visibility", "GetVisibility", "SetVisibility"); - - const char* setMaterialParamTooltip = "Sets a Material param value for the given Entity. The Material will be cloned once before any changes are applied, so other instances are not affected."; - const char* getMaterialParamTooltip = "Returns a Material param value for the given Entity"; - AZ::BehaviorParameterOverrides setParamNameDetails = { "ParamName", "The name of the Material param to set" }; - const char* newValueTooltip = "The new value to apply"; - - behaviorContext->EBus("MaterialOwnerRequestBus", nullptr, "Includes functions for Components that have a Material such as Mesh Component, Decal Component, etc.") - ->Attribute(AZ::Script::Attributes::Category, "Rendering") - ->Event("IsMaterialOwnerReady", &MaterialOwnerRequestBus::Events::IsMaterialOwnerReady) - ->Attribute(AZ::Script::Attributes::ToolTip, "Indicates whether the Material Owner is fully initialized, and is ready for Material requests") - ->Event("SetMaterial", &MaterialOwnerRequestBus::Events::SetMaterialHandle) - ->Attribute(AZ::Script::Attributes::ToolTip, "Sets an Entity's Material") - ->Event("GetMaterial", &MaterialOwnerRequestBus::Events::GetMaterialHandle) - ->Attribute(AZ::Script::Attributes::ToolTip, "Returns an Entity's current Material") - ->Event("SetParamVector4", &MaterialOwnerRequestBus::Events::SetMaterialParamVector4, { { setParamNameDetails, { "Vector4", newValueTooltip }, CreateMaterialIdDetails(behaviorContext) } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Event("SetParamVector3", &MaterialOwnerRequestBus::Events::SetMaterialParamVector3, { { setParamNameDetails, { "Vector3", newValueTooltip }, CreateMaterialIdDetails(behaviorContext) } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Event("SetParamColor", &MaterialOwnerRequestBus::Events::SetMaterialParamColor, { { setParamNameDetails, { "Color" , newValueTooltip }, CreateMaterialIdDetails(behaviorContext) } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Event("SetParamNumber", &MaterialOwnerRequestBus::Events::SetMaterialParamFloat, { { setParamNameDetails, { "Number" , newValueTooltip }, CreateMaterialIdDetails(behaviorContext) } }) // Using ParamNumber instead of ParamFloat because in Script Canvas all primitives are just "numbers" - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Event("GetParamVector4", &MaterialOwnerRequestBus::Events::GetMaterialParamVector4, GetMaterialParamArgs(behaviorContext)) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Event("GetParamVector3", &MaterialOwnerRequestBus::Events::GetMaterialParamVector3, GetMaterialParamArgs(behaviorContext)) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Event("GetParamColor", &MaterialOwnerRequestBus::Events::GetMaterialParamColor, GetMaterialParamArgs(behaviorContext)) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Event("GetParamNumber", &MaterialOwnerRequestBus::Events::GetMaterialParamFloat, GetMaterialParamArgs(behaviorContext)) // Using ParamNumber instead of ParamFloat because in Script Canvas all primitives are just "numbers" - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip); - - behaviorContext->EBus("MaterialOwnerNotificationBus", nullptr, "Provides notifications from Components that have a Material such as Mesh Component, Decal Component, etc.") - ->Attribute(AZ::Script::Attributes::Category, "Rendering") - ->Handler() - ; - - behaviorContext->Class()->RequestBus("MeshComponentRequestBus"); - } - } - - - ////////////////////////////////////////////////////////////////////////// - - void MeshComponentRenderNode::MeshRenderOptions::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class() - ->Version(5, &VersionConverter) - ->Field("Opacity", &MeshComponentRenderNode::MeshRenderOptions::m_opacity) - ->Field("MaxViewDistance", &MeshComponentRenderNode::MeshRenderOptions::m_maxViewDist) - ->Field("ViewDistanceMultiplier", &MeshComponentRenderNode::MeshRenderOptions::m_viewDistMultiplier) - ->Field("LODRatio", &MeshComponentRenderNode::MeshRenderOptions::m_lodRatio) - ->Field("CastShadows", &MeshComponentRenderNode::MeshRenderOptions::m_castShadows) - ->Field("LODBBoxBased", &MeshComponentRenderNode::MeshRenderOptions::m_lodBoundingBoxBased) - ->Field("UseVisAreas", &MeshComponentRenderNode::MeshRenderOptions::m_useVisAreas) - ->Field("RainOccluder", &MeshComponentRenderNode::MeshRenderOptions::m_rainOccluder) - ->Field("AffectDynamicWater", &MeshComponentRenderNode::MeshRenderOptions::m_affectDynamicWater) - ->Field("ReceiveWind", &MeshComponentRenderNode::MeshRenderOptions::m_receiveWind) - ->Field("AcceptDecals", &MeshComponentRenderNode::MeshRenderOptions::m_acceptDecals) - ->Field("AffectNavmesh", &MeshComponentRenderNode::MeshRenderOptions::m_affectNavmesh) - ->Field("VisibilityOccluder", &MeshComponentRenderNode::MeshRenderOptions::m_visibilityOccluder) - ->Field("DynamicMesh", &MeshComponentRenderNode::MeshRenderOptions::m_dynamicMesh) - ->Field("AffectsGI", &MeshComponentRenderNode::MeshRenderOptions::m_affectGI) - ; - } - } - - bool MeshComponentRenderNode::MeshRenderOptions::VersionConverter(AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement) - { - // conversion from version 1: - // - Remove Bloom (m_allowBloom) - // - Remove MotionBlur (m_allowMotionBlur) - // - Remove DepthTest (m_depthTest) - if (classElement.GetVersion() <= 1) - { - classElement.RemoveElementByName(AZ_CRC("Bloom", 0xc6cd7d1b)); - classElement.RemoveElementByName(AZ_CRC("MotionBlur", 0x917cdb53)); - classElement.RemoveElementByName(AZ_CRC("DepthTest", 0x532f68b9)); - } - - // conversion from version 2: - // - Remove IndoorOnly (m_indoorOnly) - if (classElement.GetVersion() <= 2) - { - classElement.RemoveElementByName(AZ_CRC("IndoorOnly", 0xc8ab6ddb)); - } - - if (classElement.GetVersion() <= 3) - { - classElement.RemoveElementByName(AZ_CRC("CastLightmapShadows", 0x10ce0bf8)); - int index = classElement.FindElement(AZ_CRC("CastDynamicShadows", 0x55c75b43)); - AZ::SerializeContext::DataElementNode& shadowNode = classElement.GetSubElement(index); - shadowNode.SetName("CastShadows"); - } - - // conversion from version 4: - // - Set "CastShadows" to false if "Opacity" is less than 1.0f, in order to not break old assets. - // The new system ignores opacity for shadow casting and relies only on the "CastShadows" flag. - if (classElement.GetVersion() <= 4) - { - float opacity; - int opacityElementIndex = classElement.FindElement(AZ_CRC("Opacity", 0x43fd6d66)); - AZ::SerializeContext::DataElementNode& opacityNode = classElement.GetSubElement(opacityElementIndex); - opacityNode.GetData(opacity); - - if (opacity < 1.0f) - { - int castShadowsElementIndex = classElement.FindElement(AZ_CRC("CastShadows", 0xbe687463)); - AZ::SerializeContext::DataElementNode& castShadowsNode = classElement.GetSubElement(castShadowsElementIndex); - castShadowsNode.SetData(context, false); - } - } - - return true; - } - - bool MeshComponentRenderNode::MeshRenderOptions::IsStatic() const - { - return (m_hasStaticTransform && !m_dynamicMesh && !m_receiveWind); - } - - bool MeshComponentRenderNode::MeshRenderOptions::AffectsGi() const - { - return m_affectGI && IsStatic(); - } - - AZ::Crc32 MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility() const - { - return IsStatic() ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; - } - - void MeshComponentRenderNode::Reflect(AZ::ReflectContext* context) - { - MeshRenderOptions::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Visible", &MeshComponentRenderNode::m_visible) - ->Field("Static Mesh", &MeshComponentRenderNode::m_meshAsset) - ->Field("Material Override", &MeshComponentRenderNode::m_material) - ->Field("Render Options", &MeshComponentRenderNode::m_renderOptions) - ; - } - } - - float MeshComponentRenderNode::GetDefaultMaxViewDist() - { - if (gEnv && gEnv->p3DEngine) - { - return gEnv->p3DEngine->GetMaxViewDistance(false); - } - - // In the editor and the game, the dynamic lookup above should *always* hit. - // This case essentially means no renderer (not even the null renderer) is present. - return FLT_MAX; - } - - MeshComponentRenderNode::MeshRenderOptions::MeshRenderOptions() - : m_opacity(1.f) - , m_viewDistMultiplier(1.f) - , m_lodRatio(100) - , m_useVisAreas(true) - , m_castShadows(true) - , m_lodBoundingBoxBased(false) - , m_rainOccluder(true) - , m_affectNavmesh(true) - , m_affectDynamicWater(false) - , m_acceptDecals(true) - , m_receiveWind(false) - , m_visibilityOccluder(false) - , m_dynamicMesh(false) - , m_hasStaticTransform(false) - , m_affectGI(true) - { - m_maxViewDist = GetDefaultMaxViewDist(); - } - - MeshComponentRenderNode::MeshComponentRenderNode() - : m_statObj(nullptr) - , m_materialOverride(nullptr) - , m_auxiliaryRenderFlags(0) - , m_auxiliaryRenderFlagsHistory(0) - , m_lodDistance(0.f) - , m_lodDistanceScaled(FLT_MAX / (SMeshLodInfo::s_nMaxLodCount + 1)) // defualt overflow prevention - it is scaled by (SMeshLodInfo::s_nMaxLodCount + 1) - , m_lodDistanceScaleValue(1.0f) - , m_isRegisteredWithRenderer(false) - , m_objectMoved(false) - , m_meshAsset(AZ::Data::AssetLoadBehavior::QueueLoad) - , m_visible(true) - { - m_localBoundingBox.Reset(); - m_worldBoundingBox.Reset(); - m_worldTransform = AZ::Transform::CreateIdentity(); - m_renderTransform = Matrix34::CreateIdentity(); - } - - MeshComponentRenderNode::~MeshComponentRenderNode() - { - DestroyMesh(); - } - - void MeshComponentRenderNode::CopyPropertiesTo(MeshComponentRenderNode& rhs) const - { - rhs.m_visible = m_visible; - rhs.m_materialOverride = m_materialOverride; - rhs.m_meshAsset = m_meshAsset; - rhs.m_material = m_material; - rhs.m_renderOptions = m_renderOptions; - } - - void MeshComponentRenderNode::AttachToEntity(AZ::EntityId id) - { - if (AZ::TransformNotificationBus::Handler::BusIsConnectedId(m_renderOptions.m_attachedToEntityId)) - { - AZ::TransformNotificationBus::Handler::BusDisconnect(m_renderOptions.m_attachedToEntityId); - } - - if (m_modificationHelper.IsConnected()) - { - m_modificationHelper.Disconnect(); - } - - if (id.IsValid()) - { - if (!AZ::TransformNotificationBus::Handler::BusIsConnectedId(id)) - { - AZ::TransformNotificationBus::Handler::BusConnect(id); - } - - auto transformHandler = AZ::TransformBus::FindFirstHandler(id); - - UpdateWorldTransform(transformHandler->GetWorldTM()); - - AzFramework::EntityBoundsUnionRequestBus::Broadcast( - &AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId()); - - m_modificationHelper.Connect(id); - } - - m_renderOptions.m_attachedToEntityId = id; - } - - void MeshComponentRenderNode::OnAssetPropertyChanged() - { - if (HasMesh()) - { - DestroyMesh(); - } - - AZ::Data::AssetBus::Handler::BusDisconnect(); - - CreateMesh(); - AzFramework::RenderGeometry::IntersectionNotificationBus::Event(m_contextId, - &AzFramework::RenderGeometry::IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void MeshComponentRenderNode::RefreshRenderState() - { - if (gEnv->IsEditor()) - { - UpdateLocalBoundingBox(); - - AZ::Transform parentTransform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(parentTransform, m_renderOptions.m_attachedToEntityId, AZ::TransformBus, GetWorldTM); - OnTransformChanged(AZ::Transform::CreateIdentity(), parentTransform); - - if (HasMesh()) - { - // Re-register with the renderer, as some render settings/flags require it. - // Note that this is editor-only behavior (hence the guard above). - if (m_isRegisteredWithRenderer) - { - RegisterWithRenderer(false); - RegisterWithRenderer(true); - } - } - } - } - - void MeshComponentRenderNode::SetTransformStaticState(bool isStatic) - { - m_renderOptions.m_hasStaticTransform = isStatic; - } - - const AZ::Transform& MeshComponentRenderNode::GetTransform() const - { - return m_worldTransform; - } - - void MeshComponentRenderNode::SetAuxiliaryRenderFlags(uint32 flags) - { - m_auxiliaryRenderFlags = flags; - m_auxiliaryRenderFlagsHistory |= flags; - } - - void MeshComponentRenderNode::UpdateAuxiliaryRenderFlags(bool on, uint32 mask) - { - if (on) - { - m_auxiliaryRenderFlags |= mask; - } - else - { - m_auxiliaryRenderFlags &= ~mask; - } - - m_auxiliaryRenderFlagsHistory |= mask; - } - - bool MeshComponentRenderNode::IsReady() const - { - return HasMesh(); - } - - void MeshComponentRenderNode::CreateMesh() - { - if (m_meshAsset.GetId().IsValid()) - { - if (!AZ::Data::AssetBus::Handler::BusIsConnected()) - { - AZ::Data::AssetBus::Handler::BusConnect(m_meshAsset.GetId()); - } - - m_meshAsset.QueueLoad(); - } - } - - void MeshComponentRenderNode::DestroyMesh() - { - AZ::Data::AssetBus::Handler::BusDisconnect(); - - RegisterWithRenderer(false); - m_statObj = nullptr; - - EBUS_EVENT_ID(m_renderOptions.m_attachedToEntityId, MeshComponentNotificationBus, OnMeshDestroyed); - - m_meshAsset.Release(); - } - - bool MeshComponentRenderNode::HasMesh() const - { - return m_statObj != nullptr; - } - - void MeshComponentRenderNode::SetMeshAsset(const AZ::Data::AssetId& id) - { - AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().FindOrCreateAsset(id, m_meshAsset.GetAutoLoadBehavior()); - - if (asset) - { - m_meshAsset = asset; - OnAssetPropertyChanged(); - } - } - - void MeshComponentRenderNode::GetMemoryUsage(class ICrySizer* pSizer) const - { - pSizer->AddObjectSize(this); - } - - float MeshComponentRenderNode::GetUniformScale() - { - AZ::Vector3 scales = m_worldTransform.GetScale(); - AZ_Assert((scales.GetX() == scales.GetY()) && (scales.GetY() == scales.GetZ()), "Scales are not uniform"); - return scales.GetX(); - } - - float MeshComponentRenderNode::GetColumnScale(int column) - { - return m_worldTransform.GetScale().GetElement(column); - } - - void MeshComponentRenderNode::OnTransformChanged(const AZ::Transform&, const AZ::Transform& parentWorld) - { - // The entity to which we're attached has moved. - UpdateWorldTransform(parentWorld); - AzFramework::RenderGeometry::IntersectionNotificationBus::Event(m_contextId, - &AzFramework::RenderGeometry::IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void MeshComponentRenderNode::OnAssetReady(AZ::Data::Asset asset) - { - if (asset == m_meshAsset) - { - m_meshAsset = asset; - BuildRenderMesh(); - - if (HasMesh()) - { - const AZStd::string& materialOverridePath = m_material.GetAssetPath(); - if (!materialOverridePath.empty()) - { - m_materialOverride = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(materialOverridePath.c_str()); - - AZ_Warning("MeshComponent", m_materialOverride != gEnv->p3DEngine->GetMaterialManager()->GetDefaultMaterial(), - "Failed to load override Material \"%s\".", - materialOverridePath.c_str()); - } - else - { - m_materialOverride = nullptr; - } - - UpdateLocalBoundingBox(); - UpdateLodDistance(gEnv->p3DEngine->GetFrameLodInfo()); - RegisterWithRenderer(true); - - // Inform listeners that the mesh has been changed - LmbrCentral::MeshComponentNotificationBus::Event(m_renderOptions.m_attachedToEntityId, &LmbrCentral::MeshComponentNotifications::OnMeshCreated, asset); - AzFramework::RenderGeometry::IntersectionNotificationBus::Event(m_contextId, &AzFramework::RenderGeometry::IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - } - } - - void MeshComponentRenderNode::OnAssetReloaded(AZ::Data::Asset asset) - { - // note that this also corrects the assetId if it is incorrect - do not remove the following line - // even if you call OnAssetReady - OnAssetReady(asset); - } - - void MeshComponentRenderNode::UpdateWorldTransform(const AZ::Transform& entityTransform) - { - m_worldTransform = entityTransform; - - m_renderTransform = AZTransformToLYTransform(m_worldTransform); - - UpdateWorldBoundingBox(); - if (m_isRegisteredWithRenderer && m_renderOptions.AffectsGi()) - { - GiRegistrationBus::Broadcast(&GiRegistration::UpsertToGi, - m_renderOptions.m_attachedToEntityId, - m_worldTransform, - CalculateWorldAABB(), - m_meshAsset, - GetMaterial()); - } - - m_objectMoved = true; - } - - void MeshComponentRenderNode::UpdateLocalBoundingBox() - { - m_localBoundingBox.Reset(); - - if (HasMesh()) - { - m_localBoundingBox.Add(m_statObj->GetAABB()); - } - - AzFramework::EntityBoundsUnionRequestBus::Broadcast( - &AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId()); - - UpdateWorldBoundingBox(); - } - - void MeshComponentRenderNode::UpdateWorldBoundingBox() - { - m_worldBoundingBox.SetTransformedAABB(m_renderTransform, m_localBoundingBox); - - if (m_isRegisteredWithRenderer) - { - // Re-register with the renderer to update culling info - gEnv->p3DEngine->RegisterEntity(this); - } - } - - void MeshComponentRenderNode::SetVisible(bool isVisible) - { - if (m_visible != isVisible) - { - m_visible = isVisible; - RegisterWithRenderer(false); - RegisterWithRenderer(true); - } - } - - bool MeshComponentRenderNode::GetVisible() - { - return m_visible; - } - - void MeshComponentRenderNode::RegisterWithRenderer(bool registerWithRenderer) - { - if (gEnv && gEnv->p3DEngine) - { - if (registerWithRenderer) - { - if (!m_isRegisteredWithRenderer) - { - ApplyRenderOptions(); - - gEnv->p3DEngine->RegisterEntity(this); - - if (m_renderOptions.AffectsGi()) - { - GiRegistrationBus::Broadcast(&GiRegistration::UpsertToGi, - m_renderOptions.m_attachedToEntityId, - m_worldTransform, - CalculateWorldAABB(), - m_meshAsset, - GetMaterial()); - } - - m_isRegisteredWithRenderer = true; - } - } - else - { - if (m_isRegisteredWithRenderer) - { - gEnv->p3DEngine->FreeRenderNodeState(this); - - GiRegistrationBus::Broadcast(&GiRegistration::RemoveFromGi, - m_renderOptions.m_attachedToEntityId); - - m_isRegisteredWithRenderer = false; - } - } - } - } - - namespace MeshInternal - { - void UpdateRenderFlag(bool enable, int mask, unsigned int& flags) - { - if (enable) - { - flags |= mask; - } - else - { - flags &= ~mask; - } - } - } - - void MeshComponentRenderNode::ApplyRenderOptions() - { - using MeshInternal::UpdateRenderFlag; - unsigned int flags = GetRndFlags(); - flags |= ERF_COMPONENT_ENTITY; - - // Turn off any flag which has ever been set via auxiliary render flags - UpdateRenderFlag(false, m_auxiliaryRenderFlagsHistory, flags); - - // Update flags according to current render settings - UpdateRenderFlag(m_renderOptions.m_useVisAreas == false, ERF_OUTDOORONLY, flags); - UpdateRenderFlag(m_renderOptions.m_castShadows, ERF_CASTSHADOWMAPS | ERF_HAS_CASTSHADOWMAPS, flags); - UpdateRenderFlag(m_renderOptions.m_rainOccluder && m_renderOptions.IsStatic(), ERF_RAIN_OCCLUDER, flags); - UpdateRenderFlag(m_visible == false, ERF_HIDDEN, flags); - UpdateRenderFlag(m_renderOptions.m_receiveWind, ERF_RECVWIND, flags); - UpdateRenderFlag(m_renderOptions.m_visibilityOccluder && m_renderOptions.IsStatic(), ERF_GOOD_OCCLUDER, flags); - //Dynamic meshes shouldn't affect the navmeshes. If that decision is changed we should change this line to no longer require - //static and note that the flag is tied to the negation of the navemesh boolean. - //Also see the editormeshcomponent.cpp AffectNavemesh function. - UpdateRenderFlag(!(m_renderOptions.m_affectNavmesh && m_renderOptions.IsStatic()), ERF_EXCLUDE_FROM_TRIANGULATION, flags); - UpdateRenderFlag(false == m_renderOptions.m_affectDynamicWater && m_renderOptions.IsStatic(), ERF_NODYNWATER, flags); - UpdateRenderFlag(false == m_renderOptions.m_acceptDecals, ERF_NO_DECALNODE_DECALS, flags); - - UpdateRenderFlag(m_renderOptions.m_lodBoundingBoxBased, ERF_LOD_BBOX_BASED, flags); - - // Apply current auxiliary render flags - UpdateRenderFlag(true, m_auxiliaryRenderFlags, flags); - - m_fWSMaxViewDist = m_renderOptions.m_maxViewDist; - - SetViewDistanceMultiplier(m_renderOptions.m_viewDistMultiplier); - - SetLodRatio(static_cast(m_renderOptions.m_lodRatio)); - - SetRndFlags(flags); - } - - CLodValue MeshComponentRenderNode::ComputeLOD( int wantedLod, const SRenderingPassInfo& passInfo) - { - // Default values as per the CVar - default fade going between 2 and 8 meters with dissolve enabled - float dissolveDistMin = 2.0f; - float dissolveDistMax = 8.0f; - int dissolveEnabled = 1; - - if (gEnv && gEnv->pConsole) - { - static ICVar* dissolveDistMinCvar = gEnv->pConsole->GetCVar("e_DissolveDistMin"); - static ICVar* dissolveDistMaxCvar = gEnv->pConsole->GetCVar("e_DissolveDistMax"); - static ICVar* dissolveEnabledCvar = gEnv->pConsole->GetCVar("e_Dissolve"); - - dissolveDistMin = dissolveDistMinCvar->GetFVal(); - dissolveDistMax = dissolveDistMaxCvar->GetFVal(); - dissolveEnabled = dissolveEnabledCvar->GetIVal() ; - } - - const Vec3 cameraPos = passInfo.GetCamera().GetPosition(); - const float entityDistance = sqrt_tpl(Distance::Point_AABBSq(cameraPos, GetBBox())) * passInfo.GetZoomFactor(); - - wantedLod = CLAMP(wantedLod, m_statObj->GetMinUsableLod(), SMeshLodInfo::s_nMaxLodCount); - int currentLod = m_statObj->FindNearesLoadedLOD(wantedLod, true); - - if (dissolveEnabled && passInfo.IsGeneralPass()) - { - float invDissolveDist = 1.0f / CLAMP(0.1f * m_fWSMaxViewDist, dissolveDistMin, dissolveDistMax ); - int nextLod = m_statObj->FindNearesLoadedLOD(currentLod + 1, true); - - // If the user chose to base LOD switch on bounding boxes, then we do not use the geometric mean computed at init. - if (GetRndFlags() & ERF_LOD_BBOX_BASED) - { - const float lodRatio = GetLodRatioNormalized(); - if (lodRatio > 0.0f) - { - // We do not use a geometric mean per object but a global value for all objects. - static ICVar* lodBoundingBoxDistanceMultiplier = gEnv->pConsole->GetCVar("e_LodBoundingBoxDistanceMultiplier"); - - m_lodDistanceScaled = lodBoundingBoxDistanceMultiplier->GetFVal() * m_lodDistanceScaleValue; - } - } - else - { - m_lodDistanceScaled = m_lodDistance * m_lodDistanceScaleValue; - } - - float lodDistance = m_lodDistanceScaled * (currentLod + 1); - uint8 dissolveRatio255 = (uint8)SATURATEB((1.0f + (entityDistance - lodDistance) * invDissolveDist) * 255.f); - - if (dissolveRatio255 == 255) - { - return CLodValue(nextLod, 0, -1); - } - return CLodValue(currentLod, dissolveRatio255, nextLod); - } - - return CLodValue(currentLod); - } - - AZ::Aabb MeshComponentRenderNode::CalculateWorldAABB() const - { - AZ::Aabb aabb = AZ::Aabb::CreateNull(); - if (!m_worldBoundingBox.IsReset()) - { - aabb.AddPoint(LYVec3ToAZVec3(m_worldBoundingBox.min)); - aabb.AddPoint(LYVec3ToAZVec3(m_worldBoundingBox.max)); - } - return aabb; - } - - AZ::Aabb MeshComponentRenderNode::CalculateLocalAABB() const - { - AZ::Aabb aabb = AZ::Aabb::CreateNull(); - if (!m_localBoundingBox.IsReset()) - { - aabb.AddPoint(LYVec3ToAZVec3(m_localBoundingBox.min)); - aabb.AddPoint(LYVec3ToAZVec3(m_localBoundingBox.max)); - } - return aabb; - } - - /*IRenderNode*/ void MeshComponentRenderNode::Render(const struct SRendParams& inRenderParams, const struct SRenderingPassInfo& passInfo) - { - if (!HasMesh()) - { - return; - } - - if (!m_modificationHelper.GetMeshModified()) - { - IStatObj* obj = GetEntityStatObj(); - int subObjectCount = obj->GetSubObjectCount(); - - AZStd::function getSubObject; - if (subObjectCount == 0) - { - getSubObject = [obj](size_t index) - { - if (index > 0) - { - AZ_Warning("MeshComponentRenderNode", false, "Mesh indices out of range"); - return static_cast(nullptr); - } - return obj; - }; - } - else - { - getSubObject = [obj, subObjectCount](size_t index) - { - if (index >= subObjectCount) - { - AZ_Warning("MeshComponentRenderNode", false, "Mesh indices out of range"); - return static_cast(nullptr); - } - return obj->GetSubObject(index)->pStatObj; - }; - } - - for (const LmbrCentral::MeshModificationRequestHelper::MeshLODPrimIndex& meshIndices : m_modificationHelper.MeshesToEdit()) - { - if (meshIndices.lodIndex != 0) - { - continue; - } - - IStatObj* subObject = getSubObject(meshIndices.primitiveIndex); - if (!subObject) - { - continue; - } - - MeshModificationNotificationBus::Event( - GetEntityId(), - &MeshModificationNotificationBus::Events::ModifyMesh, - meshIndices.lodIndex, - meshIndices.primitiveIndex, - subObject->GetRenderMesh()); - } - - m_modificationHelper.SetMeshModified(true); - } - - SRendParams rParams(inRenderParams); - - // Assign a unique pInstance pointer, otherwise effects involving SRenderObjData will not work for this object. CEntityObject::Render does this for legacy entities. - rParams.pInstance = this; - - rParams.fAlpha = m_renderOptions.m_opacity; - - _smart_ptr previousMaterial = rParams.pMaterial; - const int previousObjectFlags = rParams.dwFObjFlags; - - if (m_materialOverride) - { - rParams.pMaterial = m_materialOverride; - } - - if (m_objectMoved) - { - rParams.dwFObjFlags |= FOB_DYNAMIC_OBJECT; - m_objectMoved = false; - } - - rParams.pMatrix = &m_renderTransform; - rParams.bForceDrawStatic = !m_renderOptions.m_dynamicMesh; - if (rParams.pMatrix->IsValid()) - { - rParams.lodValue = ComputeLOD(inRenderParams.lodValue.LodA(), passInfo); - m_statObj->Render(rParams, passInfo); - } - - rParams.pMaterial = previousMaterial; - rParams.dwFObjFlags = previousObjectFlags; - } - - /*IRenderNode*/ bool MeshComponentRenderNode::GetLodDistances(const SFrameLodInfo& frameLodInfo, float* distances) const - { - const float lodRatio = GetLodRatioNormalized(); - if (lodRatio > 0.0f) - { - const float distMultiplier = 1.f / (lodRatio * frameLodInfo.fTargetSize); - - for (int lodIndex = 0; lodIndex < SMeshLodInfo::s_nMaxLodCount; ++lodIndex) - { - distances[lodIndex] = m_lodDistance * (lodIndex + 1) * distMultiplier; - } - } - else - { - for (int lodIndex = 0; lodIndex < SMeshLodInfo::s_nMaxLodCount; ++lodIndex) - { - distances[lodIndex] = FLT_MAX; - } - } - return true; - } - - void MeshComponentRenderNode::UpdateLodDistance(const SFrameLodInfo& frameLodInfo) - { - SMeshLodInfo lodInfo; - - if (HasMesh()) - { - m_statObj->ComputeGeometricMean(lodInfo); - } - - m_lodDistance = sqrt(lodInfo.fGeometricMean); - - // The following computation need to stay in accordance with the 'GetLodDistances' formula. - const float lodRatio = GetLodRatioNormalized(); - if (lodRatio > 0.0f) - { - m_lodDistanceScaled = m_lodDistance / (lodRatio * frameLodInfo.fTargetSize); - m_lodDistanceScaleValue = 1.0f / (lodRatio * frameLodInfo.fTargetSize); - } - } - - /*IRenderNode*/ EERType MeshComponentRenderNode::GetRenderNodeType() - { - return m_renderOptions.IsStatic() ? eERType_StaticMeshRenderComponent : eERType_DynamicMeshRenderComponent; - } - - /*IRenderNode*/ bool MeshComponentRenderNode::CanExecuteRenderAsJob() - { - return !m_renderOptions.m_dynamicMesh - && !m_renderOptions.m_receiveWind - && m_modificationHelper.MeshesToEdit().empty(); - } - - /*IRenderNode*/ const char* MeshComponentRenderNode::GetName() const - { - return "MeshComponentRenderNode"; - } - - /*IRenderNode*/ const char* MeshComponentRenderNode::GetEntityClassName() const - { - return "MeshComponentRenderNode"; - } - - /*IRenderNode*/ Vec3 MeshComponentRenderNode::GetPos([[maybe_unused]] bool bWorldOnly /*= true*/) const - { - return m_renderTransform.GetTranslation(); - } - - /*IRenderNode*/ const AABB MeshComponentRenderNode::GetBBox() const - { - return m_worldBoundingBox; - } - - /*IRenderNode*/ void MeshComponentRenderNode::SetBBox(const AABB& WSBBox) - { - m_worldBoundingBox = WSBBox; - } - - /*IRenderNode*/ void MeshComponentRenderNode::OffsetPosition(const Vec3& delta) - { - // Recalculate local transform - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(localTransform, m_renderOptions.m_attachedToEntityId, AZ::TransformBus, GetLocalTM); - - localTransform.SetTranslation(localTransform.GetTranslation() + LYVec3ToAZVec3(delta)); - EBUS_EVENT_ID(m_renderOptions.m_attachedToEntityId, AZ::TransformBus, SetLocalTM, localTransform); - - m_objectMoved = true; - } - - /*IRenderNode*/ void MeshComponentRenderNode::SetMaterial(_smart_ptr pMat) - { - m_materialOverride = pMat; - - if (pMat) - { - m_material.SetAssetPath(pMat->GetName()); - } - else - { - // If no material is provided, we intend to reset to the original material so we treat - // it as an asset reset to recreate the mesh. - m_material.SetAssetPath(""); - OnAssetPropertyChanged(); - } - } - - /*IRenderNode*/ _smart_ptr MeshComponentRenderNode::GetMaterial([[maybe_unused]] Vec3* pHitPos /*= nullptr*/) - { - if (m_materialOverride) - { - return m_materialOverride; - } - - if (HasMesh()) - { - return m_statObj->GetMaterial(); - } - - return nullptr; - } - - /*IRenderNode*/ _smart_ptr MeshComponentRenderNode::GetMaterialOverride() - { - return m_materialOverride; - } - - /*IRenderNode*/ float MeshComponentRenderNode::GetMaxViewDist() - { - return(m_renderOptions.m_maxViewDist * 0.75f * GetViewDistanceMultiplier()); - } - - /*IRenderNode*/ IStatObj* MeshComponentRenderNode::GetEntityStatObj(unsigned int nPartId, [[maybe_unused]] unsigned int nSubPartId, Matrix34A* pMatrix, [[maybe_unused]] bool bReturnOnlyVisible) - { - if (0 == nPartId) - { - if (pMatrix) - { - *pMatrix = m_renderTransform; - } - - return m_statObj; - } - - return nullptr; - } - - /*IRenderNode*/ _smart_ptr MeshComponentRenderNode::GetEntitySlotMaterial(unsigned int nPartId, [[maybe_unused]] bool bReturnOnlyVisible, [[maybe_unused]] bool* pbDrawNear) - { - if (0 == nPartId) - { - return m_materialOverride; - } - - return nullptr; - } - - ////////////////////////////////////////////////////////////////////////// - // MeshComponent - const float MeshComponent::s_renderNodeRequestBusOrder = 100.f; - - MeshComponent::MeshComponent() - { - m_materialBusHandler = aznew MaterialOwnerRequestBusHandlerImpl(); - } - - MeshComponent::~MeshComponent() - { - delete m_materialBusHandler; - } - - void MeshComponent::Activate() - { - m_meshRenderNode.AttachToEntity(m_entity->GetId()); - m_materialBusHandler->Activate(&m_meshRenderNode, m_entity->GetId()); - bool isStatic = false; - AZ::TransformBus::EventResult(isStatic, m_entity->GetId(), &AZ::TransformBus::Events::IsStaticTransform); - m_meshRenderNode.SetTransformStaticState(isStatic); - // Note we are purposely connecting to buses before calling m_mesh.CreateMesh(). - // m_mesh.CreateMesh() can result in events (eg: OnMeshCreated) that we want receive. - MaterialOwnerRequestBus::Handler::BusConnect(m_entity->GetId()); - MeshComponentRequestBus::Handler::BusConnect(m_entity->GetId()); - AzFramework::BoundsRequestBus::Handler::BusConnect(m_entity->GetId()); - RenderNodeRequestBus::Handler::BusConnect(m_entity->GetId()); - AzFramework::EntityContextId contextId; - AzFramework::EntityIdContextQueryBus::EventResult(contextId, GetEntityId(), &AzFramework::EntityIdContextQueries::GetOwningContextId); - AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusConnect({ GetEntityId(), contextId }); - m_meshRenderNode.SetContextId(contextId); - m_meshRenderNode.CreateMesh(); - LegacyMeshComponentRequestBus::Handler::BusConnect(GetEntityId()); - } - - void MeshComponent::Deactivate() - { - AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusDisconnect(); - - MeshComponentRequestBus::Handler::BusDisconnect(); - AzFramework::BoundsRequestBus::Handler::BusDisconnect(); - MaterialOwnerRequestBus::Handler::BusDisconnect(); - LegacyMeshComponentRequestBus::Handler::BusDisconnect(); - RenderNodeRequestBus::Handler::BusDisconnect(); - - m_meshRenderNode.DestroyMesh(); - m_meshRenderNode.AttachToEntity(AZ::EntityId()); - m_materialBusHandler->Deactivate(); - } - - AZ::Aabb MeshComponent::GetWorldBounds() - { - return m_meshRenderNode.CalculateWorldAABB(); - } - - AZ::Aabb MeshComponent::GetLocalBounds() - { - return m_meshRenderNode.CalculateLocalAABB(); - } - - void MeshComponent::SetMeshAsset(const AZ::Data::AssetId& id) - { - m_meshRenderNode.SetMeshAsset(id); - } - - bool MeshComponent::IsMaterialOwnerReady() - { - return m_materialBusHandler->IsMaterialOwnerReady(); - } - - void MeshComponent::SetMaterial(_smart_ptr material) - { - m_materialBusHandler->SetMaterial(material); - } - - _smart_ptr MeshComponent::GetMaterial() - { - return m_materialBusHandler->GetMaterial(); - } - - void MeshComponent::SetMaterialHandle(const MaterialHandle& materialHandle) - { - m_materialBusHandler->SetMaterialHandle(materialHandle); - } - - MaterialHandle MeshComponent::GetMaterialHandle() - { - return m_materialBusHandler->GetMaterialHandle(); - } - - void MeshComponent::SetMaterialParamVector4(const AZStd::string& name, const AZ::Vector4& value, int materialId) - { - m_materialBusHandler->SetMaterialParamVector4(name, value, materialId); - } - - void MeshComponent::SetMaterialParamVector3(const AZStd::string& name, const AZ::Vector3& value, int materialId) - { - m_materialBusHandler->SetMaterialParamVector3(name, value, materialId); - } - - void MeshComponent::SetMaterialParamColor(const AZStd::string& name, const AZ::Color& value, int materialId) - { - m_materialBusHandler->SetMaterialParamColor(name, value, materialId); - } - - void MeshComponent::SetMaterialParamFloat(const AZStd::string& name, float value, int materialId) - { - m_materialBusHandler->SetMaterialParamFloat(name, value, materialId); - } - - AZ::Vector4 MeshComponent::GetMaterialParamVector4(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamVector4(name, materialId); - } - - AZ::Vector3 MeshComponent::GetMaterialParamVector3(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamVector3(name, materialId); - } - - AZ::Color MeshComponent::GetMaterialParamColor(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamColor(name, materialId); - } - - float MeshComponent::GetMaterialParamFloat(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamFloat(name, materialId); - } - - IRenderNode* MeshComponent::GetRenderNode() - { - return &m_meshRenderNode; - } - - float MeshComponent::GetRenderNodeRequestBusOrder() const - { - return s_renderNodeRequestBusOrder; - } - - IStatObj* MeshComponent::GetStatObj() - { - return m_meshRenderNode.GetEntityStatObj(); - } - - AzFramework::RenderGeometry::RayResult MeshComponent::RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) - { - AzFramework::RenderGeometry::RayResult result; - if (!GetVisibility() && ray.m_onlyVisible) - { - return result; - } - - if (IStatObj* geometry = GetStatObj()) - { - const AZ::Vector3 rayDirection = (ray.m_endWorldPosition - ray.m_startWorldPosition); - const AZ::Transform& transform = m_meshRenderNode.GetTransform(); - const AZ::Transform inverseTransform = transform.GetInverse(); - - const AZ::Vector3 rayStartLocal = inverseTransform.TransformPoint(ray.m_startWorldPosition); - const AZ::Vector3 rayDistNormLocal = inverseTransform.TransformVector(rayDirection).GetNormalized(); - - SRayHitInfo hi; - hi.inReferencePoint = AZVec3ToLYVec3(rayStartLocal); - hi.inRay = Ray(hi.inReferencePoint, AZVec3ToLYVec3(rayDistNormLocal)); - hi.bInFirstHit = true; - hi.bGetVertColorAndTC = true; - if (geometry->RayIntersection(hi)) - { - AZ::Matrix3x4 invTransformMatrix = AZ::Matrix3x4::CreateFromTransform(inverseTransform); - invTransformMatrix.Transpose(); - - result.m_uv = LYVec2ToAZVec2(hi.vHitTC); - result.m_worldPosition = transform.TransformPoint(LYVec3ToAZVec3(hi.vHitPos)); - result.m_worldNormal = invTransformMatrix.Multiply3x3(LYVec3ToAZVec3(hi.vHitNormal)).GetNormalized(); - result.m_distance = (result.m_worldPosition - ray.m_startWorldPosition).GetLength(); - result.m_entityAndComponent = { GetEntityId(), GetId() }; - } - } - return result; - } - - bool MeshComponent::GetVisibility() - { - return m_meshRenderNode.GetVisible(); - } - - void MeshComponent::SetVisibility(bool isVisible) - { - m_meshRenderNode.SetVisible(isVisible); - } - - void MeshComponentRenderNode::BuildRenderMesh() - { - m_statObj = nullptr; // Release smart pointer - - MeshAsset* data = m_meshAsset.Get(); - if (!data || !data->m_statObj) - { - return; - } - - // Populate m_statObj. If the mesh doesn't require to be unique, we reuse the render mesh from the asset. If the - // mesh requires to be unique, we create a copy of the asset's render mesh since it will be modified. - - bool hasClothData = !data->m_statObj->GetClothData().empty(); - const int subObjectCount = data->m_statObj->GetSubObjectCount(); - for (int i = 0; i < subObjectCount && !hasClothData; ++i) - { - IStatObj::SSubObject* subObject = data->m_statObj->GetSubObject(i); - if (subObject && - subObject->pStatObj && - !subObject->pStatObj->GetClothData().empty()) - { - hasClothData = true; - } - } - - bool useUniqueMesh = hasClothData; - - if (useUniqueMesh) - { - // Create a copy since each mesh can be deforming differently and we need to send different meshes to render - m_statObj = data->m_statObj->Clone( /*bCloneGeometry*/ true, /*bCloneChildren*/ true, /*bMeshesOnly*/ false); - } - else - { - // Reuse the same render mesh - m_statObj = data->m_statObj; - } - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.h deleted file mode 100644 index f7a7f5d861..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.h +++ /dev/null @@ -1,393 +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. -* -*/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace LmbrCentral -{ - class MaterialOwnerRequestBusHandlerImpl; - - /*! - * RenderNode implementation responsible for integrating with the renderer. - * The node owns render flags, the mesh instance, and the render transform. - */ - class MeshComponentRenderNode - : public IRenderNode - , public AZ::TransformNotificationBus::Handler - , public AZ::Data::AssetBus::Handler - { - friend class EditorMeshComponent; - public: - using MaterialPtr = _smart_ptr < IMaterial > ; - using MeshPtr = _smart_ptr < IStatObj > ; - - AZ_TYPE_INFO(MeshComponentRenderNode, "{46FF2BC4-BEF9-4CC4-9456-36C127C310D7}"); - - MeshComponentRenderNode(); - ~MeshComponentRenderNode() override; - - void CopyPropertiesTo(MeshComponentRenderNode& rhs) const; - - //! Notifies render node which entity owns it, for subscribing to transform - //! bus, etc. - void AttachToEntity(AZ::EntityId id); - - //! Returns true after all required assets are loaded - bool IsReady() const override; - - //! Instantiate mesh instance. - void CreateMesh(); - - //! Destroy mesh instance. - void DestroyMesh(); - - //! Returns true if the node has geometry assigned. - bool HasMesh() const; - - //! Assign a new mesh asset - void SetMeshAsset(const AZ::Data::AssetId& id); - - //! Get the mesh asset - AZ::Data::Asset GetMeshAsset() { return m_meshAsset; } - - //! Invoked in the editor when the user assigns a new asset. - void OnAssetPropertyChanged(); - - //! Render the mesh - void RenderMesh(const struct SRendParams& inRenderParams, const struct SRenderingPassInfo& passInfo); - - //! Updates the render node's world transform based on the entity's. - void UpdateWorldTransform(const AZ::Transform& entityTransform); - - //! Computes world-space AABB. - AZ::Aabb CalculateWorldAABB() const; - - //! Computes local-space AABB. - AZ::Aabb CalculateLocalAABB() const; - - ////////////////////////////////////////////////////////////////////////// - // AZ::Data::AssetBus::Handler - void OnAssetReady(AZ::Data::Asset asset) override; - void OnAssetReloaded(AZ::Data::Asset asset) override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // AZ::TransformNotificationBus::Handler interface implementation - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // IRenderNode interface implementation - void Render(const struct SRendParams& inRenderParams, const struct SRenderingPassInfo& passInfo) override; - bool GetLodDistances(const SFrameLodInfo& frameLodInfo, float* distances) const override; - float GetFirstLodDistance() const override { return m_lodDistance; } - EERType GetRenderNodeType() override; - bool CanExecuteRenderAsJob() override; - const char* GetName() const override; - const char* GetEntityClassName() const override; - Vec3 GetPos(bool bWorldOnly = true) const override; - const AABB GetBBox() const override; - void SetBBox(const AABB& WSBBox) override; - void OffsetPosition(const Vec3& delta) override; - void SetMaterial(_smart_ptr pMat) override; - _smart_ptr GetMaterial(Vec3* pHitPos = nullptr) override; - _smart_ptr GetMaterialOverride() override; - IStatObj* GetEntityStatObj(unsigned int nPartId = 0, unsigned int nSubPartId = 0, Matrix34A* pMatrix = nullptr, bool bReturnOnlyVisible = false) override; - _smart_ptr GetEntitySlotMaterial(unsigned int nPartId, bool bReturnOnlyVisible = false, bool* pbDrawNear = nullptr) override; - float GetMaxViewDist() override; - void GetMemoryUsage(class ICrySizer* pSizer) const override; - AZ::EntityId GetEntityId() override { return m_renderOptions.m_attachedToEntityId; } - float GetUniformScale() override; - float GetColumnScale(int column) override; - ////////////////////////////////////////////////////////////////////////// - - //! Invoked in the editor when a property requiring render state refresh - //! has changed. - void RefreshRenderState(); - - //! Set/get auxiliary render flags. - void SetAuxiliaryRenderFlags(uint32 flags); - uint32 GetAuxiliaryRenderFlags() const { return m_auxiliaryRenderFlags; } - void UpdateAuxiliaryRenderFlags(bool on, uint32 mask); - - void SetVisible(bool isVisible); - bool GetVisible(); - - static void Reflect(AZ::ReflectContext* context); - - static float GetDefaultMaxViewDist(); - static AZ::Uuid GetRenderOptionsUuid() { return AZ::AzTypeInfo::Uuid(); } - - //! Registers or unregisters our render node with the render. - void RegisterWithRenderer(bool registerWithRenderer); - bool IsRegisteredWithRenderer() const { return m_isRegisteredWithRenderer; } - - //! This function caches off the static flag stat of the transform; - void SetTransformStaticState(bool isStatic); - const AZ::Transform& GetTransform() const; - - void SetContextId(AzFramework::EntityContextId contextId) { m_contextId = contextId; } - - protected: - - //! Calculates base LOD distance based on mesh characteristics. - //! We do this each time the mesh resource changes. - void UpdateLodDistance(const SFrameLodInfo& frameLodInfo); - - //! Computes desired LOD level for the assigned mesh instance. - CLodValue ComputeLOD(int wantedLod, const SRenderingPassInfo& passInfo); - - //! Computes the entity-relative (local space) bounding box for - //! the assigned mesh. - virtual void UpdateLocalBoundingBox(); - - //! Updates the world-space bounding box and world space transform - //! for the assigned mesh. - void UpdateWorldBoundingBox(); - - //! Applies configured render options to the render node. - void ApplyRenderOptions(); - - //! Populates the render mesh from the mesh asset - void BuildRenderMesh(); - - class MeshRenderOptions - { - public: - - AZ_TYPE_INFO(MeshRenderOptions, "{EFF77BEB-CB99-44A3-8F15-111B0200F50D}") - - MeshRenderOptions(); - - float m_opacity; //!< Alpha/opacity value for rendering. - float m_maxViewDist; //!< Maximum draw distance. - float m_viewDistMultiplier; //!< Adjusts max view distance. If 1.0 then default max view distance is used. - AZ::u32 m_lodRatio; //!< Controls LOD distance ratio. - bool m_useVisAreas; //!< Allow VisAreas to control this component's visibility. - bool m_castShadows; //!< Casts shadows. - bool m_lodBoundingBoxBased; //!< LOD based on Bounding Boxes. - bool m_rainOccluder; //!< Occludes raindrops. - bool m_affectNavmesh; //!< Cuts out of the navmesh. - bool m_affectDynamicWater; //!< Affects dynamic water (ripples). - bool m_acceptDecals; //!< Accepts decals. - bool m_receiveWind; //!< Receives wind. - bool m_visibilityOccluder; //!< Appropriate for visibility occluding. - bool m_dynamicMesh; // Mesh can change or deform independent of transform - bool m_hasStaticTransform; - bool m_affectGI; //!< Mesh affects Global Illumination. - - //! The Id of the entity we're associated with, for bus subscription. - //Moved from render mesh to this struct for serialization/reflection utility - AZ::EntityId m_attachedToEntityId; - - AZStd::function m_changeCallback; - - // Minor property changes don't require refreshing/rebuilding the property tree since no other properties - // are shown/hidden as a result of a change. - AZ::u32 OnMinorChanged() - { - if (m_changeCallback) - { - m_changeCallback(); - } - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::u32 OnMajorChanged() - { - if (m_changeCallback) - { - m_changeCallback(); - } - return AZ::Edit::PropertyRefreshLevels::EntireTree; - } - - //Returns true if the transform is static and the mesh is not deformable. - bool IsStatic() const; - bool AffectsGi() const; - AZ::Crc32 StaticPropertyVisibility() const; - static void Reflect(AZ::ReflectContext* context); - - private: - static bool VersionConverter(AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement); - }; - - //! Should be visible. - bool m_visible; - - //! User-specified material override. - AzFramework::SimpleAssetReference m_material; - - //! Render flags/options. - MeshRenderOptions m_renderOptions; - - //! Currently-assigned material. Null if no material is manually assigned. - MaterialPtr m_materialOverride; - - //! World and render transforms. - //! These are equivalent, but for different math libraries. - AZ::Transform m_worldTransform; - Matrix34 m_renderTransform; - - //! Local and world bounding boxes. - AABB m_localBoundingBox; - AABB m_worldBoundingBox; - - //! Additional render flags -- for special editor behavior, etc. - uint32 m_auxiliaryRenderFlags; - - //! Remember which flags have ever been toggled externally so that we can shut them off - uint32 m_auxiliaryRenderFlagsHistory; - - //! Reference to current asset - AZ::Data::Asset m_meshAsset; - MeshPtr m_statObj; - - //! Computed LOD distance. - float m_lodDistance; - - //! Computed first LOD distance (the following are multiplies of the index) - float m_lodDistanceScaled; - - //! Scale we need to multiply the distance by. - float m_lodDistanceScaleValue; - - //! Identifies whether we've already registered our node with the renderer. - bool m_isRegisteredWithRenderer; - - //! Tracks if the object was moved so we can notify the renderer. - bool m_objectMoved; - - // Helper to store indices for meshes to be modified by other components. - MeshModificationRequestHelper m_modificationHelper; - - // EntityContext of the component - AzFramework::EntityContextId m_contextId; - }; - - - - class MeshComponent - : public AZ::Component - , public MeshComponentRequestBus::Handler - , public MaterialOwnerRequestBus::Handler - , public RenderNodeRequestBus::Handler - , public LegacyMeshComponentRequestBus::Handler - , public AzFramework::BoundsRequestBus::Handler - , public AzFramework::RenderGeometry::IntersectionRequestBus::Handler - { - public: - friend class EditorMeshComponent; - - AZ_COMPONENT(MeshComponent, "{2F4BAD46-C857-4DCB-A454-C412DE67852A}"); - - MeshComponent(); - ~MeshComponent() override; - - AZ_DISABLE_COPY_MOVE(MeshComponent); - - // AZ::Component overrides ... - void Activate() override; - void Deactivate() override; - - // BoundsRequestBus and MeshComponentRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - - // MeshComponentRequestBus overrides ... - void SetMeshAsset(const AZ::Data::AssetId& id) override; - AZ::Data::Asset GetMeshAsset() override { return m_meshRenderNode.GetMeshAsset(); } - void SetVisibility(bool newVisibility) override; - bool GetVisibility() override; - - // MaterialOwnerRequestBus overrides ... - bool IsMaterialOwnerReady() override; - void SetMaterial(_smart_ptr) override; - _smart_ptr GetMaterial() override; - void SetMaterialHandle(const MaterialHandle& materialHandle) override; - MaterialHandle GetMaterialHandle() override; - void SetMaterialParamVector4(const AZStd::string& /*name*/, const AZ::Vector4& /*value*/, int /*materialId = 1*/) override; - void SetMaterialParamVector3(const AZStd::string& /*name*/, const AZ::Vector3& /*value*/, int /*materialId = 1*/) override; - void SetMaterialParamColor(const AZStd::string& /*name*/, const AZ::Color& /*value*/, int /*materialId = 1*/) override; - void SetMaterialParamFloat(const AZStd::string& /*name*/, float /*value*/, int /*materialId = 1*/) override; - AZ::Vector4 GetMaterialParamVector4(const AZStd::string& /*name*/, int /*materialId = 1*/) override; - AZ::Vector3 GetMaterialParamVector3(const AZStd::string& /*name*/, int /*materialId = 1*/) override; - AZ::Color GetMaterialParamColor(const AZStd::string& /*name*/, int /*materialId = 1*/) override; - float GetMaterialParamFloat(const AZStd::string& /*name*/, int /*materialId = 1*/) override; - - // RenderNodeRequestBus overrides ... - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - static const float s_renderNodeRequestBusOrder; - - // MeshComponentRequestBus overrides ... - IStatObj* GetStatObj() override; - - // IntersectionRequestBus overrides ... - AzFramework::RenderGeometry::RayResult RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) override; - - protected: - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("MeshService", 0x71d8a455)); - provided.push_back(AZ_CRC("LegacyMeshService", 0xb462a299)); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("MeshService", 0x71d8a455)); - incompatible.push_back(AZ_CRC("LegacyMeshService", 0xb462a299)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - static void Reflect(AZ::ReflectContext* context); - - void RequireSendingRenderMeshForEditing(size_t lodIndex, size_t primitiveIndex); - void NoRenderMeshesForEditing(); - - ////////////////////////////////////////////////////////////////////////// - // Reflected Data - MeshComponentRenderNode m_meshRenderNode; - MaterialOwnerRequestBusHandlerImpl* m_materialBusHandler; - }; - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Tests/EditorMeshComponentTests.cpp b/Gems/LmbrCentral/Code/Tests/EditorMeshComponentTests.cpp deleted file mode 100644 index 8586955254..0000000000 --- a/Gems/LmbrCentral/Code/Tests/EditorMeshComponentTests.cpp +++ /dev/null @@ -1,293 +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 "LmbrCentral_precompiled.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "Source/Rendering/EditorMeshComponent.h" - -namespace UnitTest -{ - // base physical entity which can be derived from to detect other specific use-cases - struct PhysicalEntityPlaceHolder - : public IPhysicalEntity - { - pe_type GetType() const override { return PE_NONE; } - int AddRef() override { return 0; } - int Release() override { return 0; } - int SetParams([[maybe_unused]] const pe_params* params, [[maybe_unused]] int bThreadSafe = 0) override { return 0; } - int GetParams([[maybe_unused]] pe_params* params) const override { return 0; } - int GetStatus([[maybe_unused]] pe_status* status) const override { return 0; } - int Action(const pe_action*, [[maybe_unused]] int bThreadSafe = 0) override { return 0; } - int AddGeometry([[maybe_unused]] phys_geometry* pgeom, [[maybe_unused]] pe_geomparams* params, [[maybe_unused]] int id = -1, [[maybe_unused]] int bThreadSafe = 0) override { return 0; } - void RemoveGeometry([[maybe_unused]] int id, [[maybe_unused]] int bThreadSafe = 0) override {} - PhysicsForeignData GetForeignData([[maybe_unused]] int itype = 0) const override { return PhysicsForeignData{}; } - int GetiForeignData() const override { return 0; } - int GetStateSnapshot([[maybe_unused]] class CStream& stm, [[maybe_unused]] float time_back = 0, [[maybe_unused]] int flags = 0) override { return 0; } - int GetStateSnapshot([[maybe_unused]] TSerialize ser, [[maybe_unused]] float time_back = 0, [[maybe_unused]] int flags = 0) override { return 0; } - int SetStateFromSnapshot([[maybe_unused]] class CStream& stm, [[maybe_unused]] int flags = 0) override { return 0; } - int PostSetStateFromSnapshot() override { return 0; } - unsigned int GetStateChecksum() override { return 0; } - void SetNetworkAuthority([[maybe_unused]] int authoritive = -1, [[maybe_unused]] int paused = -1) override {} - int SetStateFromSnapshot([[maybe_unused]] TSerialize ser, [[maybe_unused]] int flags = 0) override { return 0; } - int SetStateFromTypedSnapshot([[maybe_unused]] TSerialize ser, [[maybe_unused]] int type, [[maybe_unused]] int flags = 0) override { return 0; } - int GetStateSnapshotTxt([[maybe_unused]] char* txtbuf, [[maybe_unused]] int szbuf, [[maybe_unused]] float time_back = 0) override { return 0; } - void SetStateFromSnapshotTxt([[maybe_unused]] const char* txtbuf, [[maybe_unused]] int szbuf) override {} - int DoStep([[maybe_unused]] float time_interval) override { return 0; } - int DoStep([[maybe_unused]] float time_interval, [[maybe_unused]] int iCaller) override { return 0; } - void StartStep([[maybe_unused]] float time_interval) override {} - void StepBack([[maybe_unused]] float time_interval) override {} - void GetMemoryStatistics([[maybe_unused]] ICrySizer* pSizer) const override {} - }; - - // special test fake to validate incoming pe_params - struct PhysicalEntitySetParamsCheck - : public PhysicalEntityPlaceHolder - { - int SetParams(const pe_params* params, [[maybe_unused]] int bThreadSafe = 0) override - { - if (params->type == pe_params_pos::type_id) - { - pe_params_pos* params_pos = (pe_params_pos*)params; - - Vec3 s; - if (Matrix34* m34 = params_pos->pMtx3x4) - { - s.Set(m34->GetColumn(0).len(), m34->GetColumn(1).len(), m34->GetColumn(2).len()); - Matrix33 m33(m34->GetColumn(0) / s.x, m34->GetColumn(1) / s.y, m34->GetColumn(2) / s.z); - // ensure passed in params_pos->pMtx3x4 is orthonormal - // ref - see Cry_Quat.h - explicit ILINE Quat_tpl(const Matrix33_tpl&m) - m_isOrthonormal = m33.IsOrthonormalRH(0.1f); - } - } - - return 0; - } - - bool m_isOrthonormal = false; - }; - - class TestEditorMeshComponent - : public LmbrCentral::EditorMeshComponent - { - public: - AZ_EDITOR_COMPONENT(TestEditorMeshComponent, "{6C6B593A-1946-4239-AE16-E8B96D9835E5}", LmbrCentral::EditorMeshComponent) - - static void Reflect(AZ::ReflectContext* context); - - TestEditorMeshComponent() = default; - - }; - - void TestEditorMeshComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(0); - } - } - - class EditorMeshComponentTestFixture - : public ToolsApplicationFixture - { - AZStd::unique_ptr m_testMeshComponentDescriptor; - - public: - void SetUpEditorFixtureImpl() override - { - AZ::SerializeContext* serializeContext = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); - - m_testMeshComponentDescriptor = - AZStd::unique_ptr(TestEditorMeshComponent::CreateDescriptor()); - m_testMeshComponentDescriptor->Reflect(serializeContext); - } - - void TearDownEditorFixtureImpl() override - { - m_testMeshComponentDescriptor.reset(); - } - }; - - struct MeshAssetHandlerFixture - : ScopedAllocatorSetupFixture - { - protected: - void SetUp() override - { - AZ::AllocatorInstance::Create(); - AZ::AllocatorInstance::Create(); - - AZ::Data::AssetManager::Create(AZ::Data::AssetManager::Descriptor()); - AZ::Data::AssetManager::Instance().SetAssetInfoUpgradingEnabled(false); - - m_handler.Register(); - } - - void TearDown() override - { - m_handler.Unregister(); - AZ::Data::AssetManager::Destroy(); - - AZ::AllocatorInstance::Destroy(); - AZ::AllocatorInstance::Destroy(); - } - - LmbrCentral::MeshAssetHandler m_handler; - }; - - struct MockAssetSystemRequestHandler - : AzFramework::AssetSystemRequestBus::Handler - { - MockAssetSystemRequestHandler() - { - BusConnect(); - } - - ~MockAssetSystemRequestHandler() - { - BusDisconnect(); - } - - AzFramework::AssetSystem::AssetStatus GetAssetStatusById([[maybe_unused]] const AZ::Data::AssetId& assetId) override - { - m_statusRequest = true; - - return AzFramework::AssetSystem::AssetStatus_Queued; - } - - MOCK_METHOD1(CompileAssetSync, AzFramework::AssetSystem::AssetStatus (const AZStd::string&)); - MOCK_METHOD1(CompileAssetSync_FlushIO, AzFramework::AssetSystem::AssetStatus (const AZStd::string&)); - MOCK_METHOD1(CompileAssetSyncById, AzFramework::AssetSystem::AssetStatus (const AZ::Data::AssetId&)); - MOCK_METHOD1(CompileAssetSyncById_FlushIO, AzFramework::AssetSystem::AssetStatus (const AZ::Data::AssetId&)); - MOCK_METHOD4(ConfigureSocketConnection, bool (const AZStd::string&, const AZStd::string&, const AZStd::string&, const AZStd::string&)); - MOCK_METHOD1(Connect, bool (const char*)); - MOCK_METHOD2(ConnectWithTimeout, bool (const char*, AZStd::chrono::duration)); - MOCK_METHOD0(Disconnect, bool ()); - MOCK_METHOD1(EscalateAssetBySearchTerm, bool (AZStd::string_view)); - MOCK_METHOD1(EscalateAssetByUuid, bool (const AZ::Uuid&)); - MOCK_METHOD0(GetAssetProcessorPingTimeMilliseconds, float ()); - MOCK_METHOD1(GetAssetStatus, AzFramework::AssetSystem::AssetStatus (const AZStd::string&)); - MOCK_METHOD1(GetAssetStatus_FlushIO, AzFramework::AssetSystem::AssetStatus (const AZStd::string&)); - MOCK_METHOD2(GetAssetStatusSearchType, AzFramework::AssetSystem::AssetStatus(const AZStd::string&, int)); - MOCK_METHOD2(GetAssetStatusSearchType_FlushIO, AzFramework::AssetSystem::AssetStatus(const AZStd::string&, int)); - MOCK_METHOD1(GetAssetStatusById_FlushIO, AzFramework::AssetSystem::AssetStatus (const AZ::Data::AssetId&)); - MOCK_METHOD3(GetUnresolvedProductReferences, void (AZ::Data::AssetId, AZ::u32&, AZ::u32&)); - MOCK_METHOD0(SaveCatalog, bool ()); - MOCK_METHOD1(SetAssetProcessorIP, void (const AZStd::string&)); - MOCK_METHOD1(SetAssetProcessorPort, void (AZ::u16)); - MOCK_METHOD1(SetBranchToken, void (const AZStd::string&)); - MOCK_METHOD1(SetProjectName, void (const AZStd::string&)); - MOCK_METHOD0(ShowAssetProcessor, void ()); - MOCK_METHOD1(ShowInAssetProcessor, void (const AZStd::string&)); - MOCK_METHOD1(WaitUntilAssetProcessorReady, bool(AZStd::chrono::duration)); - MOCK_METHOD1(WaitUntilAssetProcessorConnected, bool(AZStd::chrono::duration)); - MOCK_METHOD1(WaitUntilAssetProcessorDisconnected, bool(AZStd::chrono::duration)); - MOCK_METHOD0(AssetProcessorIsReady, bool()); - MOCK_METHOD0(ConnectedWithAssetProcessor, bool()); - MOCK_METHOD0(DisconnectedWithAssetProcessor, bool()); - MOCK_METHOD0(NegotiationWithAssetProcessorFailed, bool()); - MOCK_METHOD0(StartDisconnectingAssetProcessor, void()); - MOCK_METHOD1(EstablishAssetProcessorConnection, bool(const AzFramework::AssetSystem::ConnectionSettings&)); - MOCK_METHOD3(AppendAssetToPrioritySet, bool (const AZStd::string&, const AZ::Uuid&, uint32_t)); - MOCK_METHOD3(AppendAssetsToPrioritySet, bool (const AZStd::string&, const AZStd::vector&, uint32_t)); - MOCK_METHOD2(RemoveAssetFromPrioritySet, bool (const AZStd::string&, const AZ::Uuid&)); - MOCK_METHOD2(RemoveAssetsFromPrioritySet, bool (const AZStd::string&, const AZStd::vector&)); - bool m_statusRequest = false; - }; - - struct MockCatalog - : AZ::Data::AssetCatalogRequestBus::Handler - { - MockCatalog() - { - BusConnect(); - } - - ~MockCatalog() - { - BusDisconnect(); - } - - AZ::Data::AssetId GetAssetIdByPath(const char*, const AZ::Data::AssetType&, bool) override - { - m_generatedId = AZ::Data::AssetId(AZ::Uuid::CreateRandom(), 1234); - - return m_generatedId; - } - - MOCK_METHOD1(GetAssetInfoById, AZ::Data::AssetInfo (const AZ::Data::AssetId&)); - MOCK_METHOD1(AddAssetType, void (const AZ::Data::AssetType&)); - MOCK_METHOD1(AddDeltaCatalog, bool (AZStd::shared_ptr)); - MOCK_METHOD1(AddExtension, void (const char*)); - MOCK_METHOD0(ClearCatalog, void ()); - MOCK_METHOD5(CreateBundleManifest, bool (const AZStd::string&, const AZStd::vector&, const AZStd::string&, int, const AZStd::vector&)); - MOCK_METHOD2(CreateDeltaCatalog, bool (const AZStd::vector&, const AZStd::string&)); - MOCK_METHOD0(DisableCatalog, void ()); - MOCK_METHOD1(EnableCatalogForAsset, void (const AZ::Data::AssetType&)); - MOCK_METHOD3(EnumerateAssets, void (BeginAssetEnumerationCB, AssetEnumerationCB, EndAssetEnumerationCB)); - MOCK_METHOD1(GenerateAssetIdTEMP, AZ::Data::AssetId (const char*)); - MOCK_METHOD1(GetAllProductDependencies, AZ::Outcome, AZStd::string> (const AZ::Data::AssetId&)); - MOCK_METHOD3(GetAllProductDependenciesFilter, AZ::Outcome, AZStd::string> (const AZ::Data::AssetId&, const AZStd::unordered_set&, const AZStd::vector&)); - MOCK_METHOD1(GetAssetPathById, AZStd::string (const AZ::Data::AssetId&)); - MOCK_METHOD1(GetDirectProductDependencies, AZ::Outcome, AZStd::string> (const AZ::Data::AssetId&)); - MOCK_METHOD1(GetHandledAssetTypes, void (AZStd::vector&)); - MOCK_METHOD0(GetRegisteredAssetPaths, AZStd::vector ()); - MOCK_METHOD2(InsertDeltaCatalog, bool (AZStd::shared_ptr, size_t)); - MOCK_METHOD2(InsertDeltaCatalogBefore, bool (AZStd::shared_ptr, AZStd::shared_ptr)); - MOCK_METHOD1(LoadCatalog, bool (const char*)); - MOCK_METHOD2(RegisterAsset, void (const AZ::Data::AssetId&, AZ::Data::AssetInfo&)); - MOCK_METHOD1(RemoveDeltaCatalog, bool (AZStd::shared_ptr)); - MOCK_METHOD1(SaveCatalog, bool (const char*)); - MOCK_METHOD0(StartMonitoringAssets, void ()); - MOCK_METHOD0(StopMonitoringAssets, void ()); - MOCK_METHOD1(UnregisterAsset, void (const AZ::Data::AssetId&)); - - AZ::Data::AssetId m_generatedId{}; - }; - - struct MockAssetData - : LmbrCentral::MeshAsset - { - MockAssetData(AZ::Data::AssetId assetId) - { - m_assetId = assetId; - } - }; - - TEST_F(MeshAssetHandlerFixture, LoadAsset_StillInQueue_LoadsSubstituteAsset) - { - MockAssetSystemRequestHandler assetSystem; - MockCatalog catalog; - AZ::Data::AssetId assetId(AZ::Uuid::CreateRandom(), 0); - - AZ::Data::Asset asset(aznew MockAssetData(assetId), AZ::Data::AssetLoadBehavior::Default); - auto substituteAssetId = m_handler.AssetMissingInCatalog(asset); - - ASSERT_TRUE(assetSystem.m_statusRequest); - ASSERT_TRUE(catalog.m_generatedId.IsValid()); - ASSERT_EQ(substituteAssetId, catalog.m_generatedId); - } - - - -} // namespace UnitTest diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Animation/SkeletalHierarchyRequestBus.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Animation/SkeletalHierarchyRequestBus.h new file mode 100644 index 0000000000..b24ac2709b --- /dev/null +++ b/Gems/LmbrCentral/Code/include/LmbrCentral/Animation/SkeletalHierarchyRequestBus.h @@ -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. +* +*/ +#pragma once + +#include +#include + +namespace LmbrCentral +{ + /*! + * SkeletonHierarchyRequestBus + * Messages serviced by components to provide information about skeletal hierarchies. + */ + class SkeletalHierarchyRequests + : public AZ::ComponentBus + { + public: + + /** + * \return Number of joints in the skeleton joint hierarchy. + */ + virtual AZ::u32 GetJointCount() { return 0; } + + /** + * \param jointIndex Index of joint whose name should be returned. + * \return Name of the joint at the specified index. Null if joint index is not valid. + */ + virtual const char* GetJointNameByIndex(AZ::u32 /*jointIndex*/) { return nullptr; } + + /** + * \param jointName Name of joint whose index should be returned. + * \return Index of the joint with the specified name. -1 if the joint was not found. + */ + virtual AZ::s32 GetJointIndexByName(const char* /*jointName*/) { return 0; } + + /** + * \param jointIndex Index of joint whose local-space transform should be returned. + * \return Joint's character-space transform. Identify if joint index was not valid. + */ + virtual AZ::Transform GetJointTransformCharacterRelative(AZ::u32 /*jointIndex*/) { return AZ::Transform::CreateIdentity(); } + }; + + using SkeletalHierarchyRequestBus = AZ::EBus; + +} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/EditorMeshBus.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/EditorMeshBus.h deleted file mode 100644 index 19cad8cd29..0000000000 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/EditorMeshBus.h +++ /dev/null @@ -1,28 +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. -* -*/ -#pragma once - -#include - -namespace LmbrCentral -{ - class EditorMeshBusRequests : - public AZ::EBusTraits - { - public: - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - - virtual bool AddMeshComponentWithAssetId(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId) = 0; - }; - using EditorMeshBus = AZ::EBus; -} diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/MeshComponentBus.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/MeshComponentBus.h deleted file mode 100644 index 2f64bb084a..0000000000 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/MeshComponentBus.h +++ /dev/null @@ -1,164 +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. -* -*/ -#pragma once - -#include -#include -#include -#include - -struct IStatObj; -struct SRenderingPassInfo; -struct SRendParams; - -namespace LmbrCentral -{ - /*! - * MeshComponentRequestBus - * Messages serviced by the mesh component. - */ - class MeshComponentRequests - : public AZ::ComponentBus - { - public: - - /** - * Returns the axis aligned bounding box in world coordinates - */ - virtual AZ::Aabb GetWorldBounds() = 0; - - /** - * Returns the axis aligned bounding box in model coordinates - */ - virtual AZ::Aabb GetLocalBounds() = 0; - - /** - * Sets the mesh asset for this component - */ - virtual void SetMeshAsset(const AZ::Data::AssetId& id) = 0; - - /** - * Returns the asset used by the mesh - */ - virtual AZ::Data::Asset GetMeshAsset() = 0; - - /** - * Returns true if the mesh is currently visible - */ - virtual bool GetVisibility() { return true; } - - /** - * Sets the current visibility of the mesh - */ - virtual void SetVisibility([[maybe_unused]] bool isVisible) {} - }; - - using MeshComponentRequestBus = AZ::EBus; - - /*! - * SkeletonHierarchyRequestBus - * Messages serviced by components to provide information about skeletal hierarchies. - */ - class SkeletalHierarchyRequests - : public AZ::ComponentBus - { - public: - - /** - * \return Number of joints in the skeleton joint hierarchy. - */ - virtual AZ::u32 GetJointCount() { return 0; } - - /** - * \param jointIndex Index of joint whose name should be returned. - * \return Name of the joint at the specified index. Null if joint index is not valid. - */ - virtual const char* GetJointNameByIndex(AZ::u32 /*jointIndex*/) { return nullptr; } - - /** - * \param jointName Name of joint whose index should be returned. - * \return Index of the joint with the specified name. -1 if the joint was not found. - */ - virtual AZ::s32 GetJointIndexByName(const char* /*jointName*/) { return 0; } - - /** - * \param jointIndex Index of joint whose local-space transform should be returned. - * \return Joint's character-space transform. Identify if joint index was not valid. - */ - virtual AZ::Transform GetJointTransformCharacterRelative(AZ::u32 /*jointIndex*/) { return AZ::Transform::CreateIdentity(); } - }; - - using SkeletalHierarchyRequestBus = AZ::EBus; - - /*! - * LegacyMeshComponentRequestBus - * Messages serviced by the mesh component. - */ - class LegacyMeshComponentRequests - : public AZ::ComponentBus - { - public: - virtual IStatObj* GetStatObj() = 0; - }; - - using LegacyMeshComponentRequestBus = AZ::EBus; - - /*! - * MeshComponentNotificationBus - * Events dispatched by the mesh component. - */ - class MeshComponentNotifications - : public AZ::ComponentBus - { - public: - - /** - * Notifies listeners the mesh instance has been created. - * \param asset - The asset the mesh instance is based on. - */ - virtual void OnMeshCreated(const AZ::Data::Asset& asset) { (void)asset; } - - /** - * Notifies listeners that the mesh instance has been destroyed. - */ - virtual void OnMeshDestroyed() {} - - virtual void OnBoundsReset() {}; - - /* - * Notifies listeners prior to making the render call - */ - virtual void OnMeshPreRender([[maybe_unused]] const struct SRendParams& inOutRenderParams, [[maybe_unused]] const SRenderingPassInfo& passInfo) {}; - - /** - * When connecting to this bus if the asset is ready you will immediately get an OnMeshCreated event - **/ - template - struct ConnectionPolicy - : public AZ::EBusConnectionPolicy - { - static void Connect(typename Bus::BusPtr& busPtr, typename Bus::Context& context, typename Bus::HandlerNode& handler, typename Bus::Context::ConnectLockGuard& connectLock, const typename Bus::BusIdType& id = 0) - { - AZ::EBusConnectionPolicy::Connect(busPtr, context, handler, connectLock, id); - - AZ::Data::Asset asset; - EBUS_EVENT_ID_RESULT(asset, id, MeshComponentRequestBus, GetMeshAsset); - if (asset.GetStatus() == AZ::Data::AssetData::AssetStatus::Ready) - { - handler->OnMeshCreated(asset); - } - } - }; - }; - - using MeshComponentNotificationBus = AZ::EBus; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/Utils/MaterialOwnerRequestBusHandlerImpl.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/Utils/MaterialOwnerRequestBusHandlerImpl.h index 2779f68eb4..6fc0e85553 100644 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/Utils/MaterialOwnerRequestBusHandlerImpl.h +++ b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/Utils/MaterialOwnerRequestBusHandlerImpl.h @@ -12,7 +12,6 @@ #pragma once #include -#include #include #include @@ -28,8 +27,7 @@ namespace LmbrCentral //! This does not actually inherit the MaterialOwnerRequestBus::Handler interface because it is //! not intended to subscribe to that bus, but it does provide implementations for all the same functions. class MaterialOwnerRequestBusHandlerImpl - : public MeshComponentNotificationBus::Handler - , public AZ::TickBus::Handler + : public AZ::TickBus::Handler , public MaterialOwnerRequestBus::Handler { using MaterialPtr = _smart_ptr < IMaterial >; @@ -57,14 +55,7 @@ namespace LmbrCentral if (m_renderNode) { - if (!m_renderNode->IsReady()) - { - // Some material owners, in particular MeshComponents, may not be ready upon activation because the - // actual mesh data and default material haven't been loaded yet. Until the RenderNode is ready, - // it's material probably isn't valid. - MeshComponentNotificationBus::Handler::BusConnect(entityId); - } - else + if (m_renderNode->IsReady()) { // For some material owner types (like DecalComponent), the material is ready immediately. But we can't // send the event yet because components are still being Activated, so we delay until the first tick. @@ -81,7 +72,6 @@ namespace LmbrCentral void Deactivate() { m_notificationBus = nullptr; - MeshComponentNotificationBus::Handler::BusDisconnect(); MaterialOwnerRequestBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); } @@ -300,16 +290,6 @@ namespace LmbrCentral } ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // MeshComponentNotificationBus interface implementation - void OnMeshCreated([[maybe_unused]] const AZ::Data::Asset& asset) override - { - AZ_Assert(IsMaterialOwnerReady(), "Got OnMeshCreated but the RenderNode still isn't ready"); - SendReadyEvent(); - MeshComponentNotificationBus::Handler::BusDisconnect(); - } - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // TickBus interface implementation void OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) override diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake index 8d9e70478a..be62919093 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake @@ -12,14 +12,11 @@ set(FILES include/LmbrCentral/Rendering/EditorCameraCorrectionBus.h include/LmbrCentral/Rendering/EditorLightComponentBus.h - include/LmbrCentral/Rendering/EditorMeshBus.h include/LmbrCentral/Shape/EditorPolygonPrismShapeComponentBus.h include/LmbrCentral/Shape/EditorSplineComponentBus.h include/LmbrCentral/Shape/EditorTubeShapeComponentBus.h include/LmbrCentral/Component/EditorWrappedComponentBase.h include/LmbrCentral/Component/EditorWrappedComponentBase.inl - Source/Animation/EditorAttachmentComponent.h - Source/Animation/EditorAttachmentComponent.cpp Source/Audio/EditorAudioAreaEnvironmentComponent.h Source/Audio/EditorAudioAreaEnvironmentComponent.cpp Source/Audio/EditorAudioEnvironmentComponent.h @@ -40,8 +37,6 @@ set(FILES Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderComponent.cpp Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderWorker.h Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderWorker.cpp - Source/Rendering/EditorMeshComponent.h - Source/Rendering/EditorMeshComponent.cpp Source/Scripting/EditorLookAtComponent.h Source/Scripting/EditorLookAtComponent.cpp Source/Scripting/EditorRandomTimedSpawnerComponent.cpp diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake index a96f0ac4ab..b78ff769c2 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake @@ -19,7 +19,6 @@ set(FILES Tests/EditorCompoundShapeComponentTests.cpp Tests/EditorCylinderShapeComponentTests.cpp Tests/EditorPolygonPrismShapeComponentTests.cpp - Tests/EditorMeshComponentTests.cpp Tests/SpawnerComponentTest.cpp Tests/Builders/CopyDependencyBuilderTest.cpp Tests/Builders/SliceBuilderTests.cpp diff --git a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake index 99d1adda14..df6bafd499 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake @@ -17,6 +17,7 @@ set(FILES include/LmbrCentral/Ai/NavigationSystemBus.h include/LmbrCentral/Ai/NavigationSeedBus.h include/LmbrCentral/Animation/AttachmentComponentBus.h + include/LmbrCentral/Animation/SkeletalHierarchyRequestBus.h include/LmbrCentral/Audio/AudioEnvironmentComponentBus.h include/LmbrCentral/Audio/AudioListenerComponentBus.h include/LmbrCentral/Audio/AudioMultiPositionComponentBus.h @@ -40,7 +41,6 @@ set(FILES include/LmbrCentral/Rendering/MaterialHandle.h include/LmbrCentral/Rendering/MaterialOwnerBus.h include/LmbrCentral/Rendering/MeshAsset.h - include/LmbrCentral/Rendering/MeshComponentBus.h include/LmbrCentral/Rendering/MeshModificationBus.h include/LmbrCentral/Rendering/RenderNodeBus.h include/LmbrCentral/Rendering/GiRegistrationBus.h @@ -69,8 +69,6 @@ set(FILES include/LmbrCentral/Terrain/TerrainSystemRequestBus.h Source/Ai/NavigationSystemComponent.h Source/Ai/NavigationSystemComponent.cpp - Source/Animation/AttachmentComponent.h - Source/Animation/AttachmentComponent.cpp Source/Audio/AudioAreaEnvironmentComponent.h Source/Audio/AudioAreaEnvironmentComponent.cpp Source/Audio/AudioEnvironmentComponent.h @@ -99,11 +97,6 @@ set(FILES Source/Events/ReflectScriptableEvents.cpp Source/Geometry/GeometrySystemComponent.h Source/Geometry/GeometrySystemComponent.cpp - Source/Rendering/MaterialHandle.cpp - Source/Rendering/MeshAssetHandler.h - Source/Rendering/MeshAssetHandler.cpp - Source/Rendering/MeshComponent.h - Source/Rendering/MeshComponent.cpp Source/Rendering/EntityDebugDisplayComponent.h Source/Rendering/EntityDebugDisplayComponent.cpp Source/Scripting/LookAtComponent.h diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index e1ea3addec..2dc8fc97ec 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -345,7 +345,6 @@ namespace PhysX AzToolsFramework::BoxManipulatorRequestBus::Handler::BusConnect( AZ::EntityComponentIdPair(GetEntityId(), GetId())); ColliderShapeRequestBus::Handler::BusConnect(GetEntityId()); - LmbrCentral::MeshComponentNotificationBus::Handler::BusConnect(GetEntityId()); AZ::Render::MeshComponentNotificationBus::Handler::BusConnect(GetEntityId()); EditorColliderComponentRequestBus::Handler::BusConnect(AZ::EntityComponentIdPair(GetEntityId(), GetId())); m_nonUniformScaleChangedHandler = AZ::NonUniformScaleChangedEvent::Handler( @@ -394,7 +393,6 @@ namespace PhysX m_nonUniformScaleChangedHandler.Disconnect(); EditorColliderComponentRequestBus::Handler::BusDisconnect(); AZ::Render::MeshComponentNotificationBus::Handler::BusDisconnect(); - LmbrCentral::MeshComponentNotificationBus::Handler::BusDisconnect(); ColliderShapeRequestBus::Handler::BusDisconnect(); AzToolsFramework::BoxManipulatorRequestBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); @@ -1179,17 +1177,7 @@ namespace PhysX AZ::Render::MeshComponentRequestBus::EventResult(atomMeshAsset, GetEntityId(), &AZ::Render::MeshComponentRequestBus::Events::GetModelAsset); - if (atomMeshAsset.GetId().IsValid()) - { - return atomMeshAsset; - } - - // Try legacy render MeshComponent - AZ::Data::Asset legacyMeshAsset; - LmbrCentral::MeshComponentRequestBus::EventResult(legacyMeshAsset, - GetEntityId(), &LmbrCentral::MeshComponentRequests::GetMeshAsset); - - return legacyMeshAsset; + return atomMeshAsset; } void EditorColliderComponent::SetCollisionMeshFromRender() @@ -1264,14 +1252,6 @@ namespace PhysX renderMeshAsset.GetHint().c_str()); } } - - void EditorColliderComponent::OnMeshCreated([[maybe_unused]] const AZ::Data::Asset& asset) - { - if (ShouldUpdateCollisionMeshFromRender()) - { - SetCollisionMeshFromRender(); - } - } void EditorColliderComponent::OnModelReady([[maybe_unused]] const AZ::Data::Asset& modelAsset, [[maybe_unused]] const AZ::Data::Instance& model) diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.h b/Gems/PhysX/Code/Source/EditorColliderComponent.h index f179525802..e78be1b959 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.h +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.h @@ -32,8 +32,6 @@ #include #include -#include - #include #include #include @@ -105,7 +103,6 @@ namespace PhysX , private PhysX::MeshColliderComponentRequestsBus::Handler , private AZ::TransformNotificationBus::Handler , private PhysX::ColliderShapeRequestBus::Handler - , private LmbrCentral::MeshComponentNotificationBus::Handler , private AZ::Render::MeshComponentNotificationBus::Handler , private PhysX::EditorColliderComponentRequestBus::Handler , private Physics::WorldBodyRequestBus::Handler @@ -175,9 +172,6 @@ namespace PhysX AZ::Transform GetCurrentTransform() override; AZ::Vector3 GetBoxScale() override; - // LmbrCentral::MeshComponentNotificationBus - void OnMeshCreated(const AZ::Data::Asset& asset) override; - // AZ::Render::MeshComponentNotificationBus void OnModelReady(const AZ::Data::Asset& modelAsset, const AZ::Data::Instance& model) override;