AttachmentComponent.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <LmbrCentral/Animation/AttachmentComponentBus.h>
  10. #include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
  11. #include <AzCore/Component/Component.h>
  12. #include <AzCore/Component/TransformBus.h>
  13. #include <AzCore/Component/TickBus.h>
  14. #include <AzCore/Math/Transform.h>
  15. struct ISkeletonPose;
  16. namespace AZ
  17. {
  18. namespace Render
  19. {
  20. /*!
  21. * Configuration data for AttachmentComponent.
  22. */
  23. struct AttachmentConfiguration
  24. {
  25. AZ_TYPE_INFO(AttachmentConfiguration, "{74B5DC69-DE44-4640-836A-55339E116795}");
  26. virtual ~AttachmentConfiguration() = default;
  27. static void Reflect(AZ::ReflectContext* context);
  28. //! Attach to this entity.
  29. AZ::EntityId m_targetId;
  30. //! Attach to this bone on target entity.
  31. AZStd::string m_targetBoneName;
  32. //! Offset from target.
  33. AZ::Transform m_targetOffset = AZ::Transform::Identity();
  34. //! Whether to attach to target upon activation.
  35. //! If false, the entity remains detached until Attach() is called.
  36. bool m_attachedInitially = true;
  37. //! Source from which to retrieve scale information.
  38. enum class ScaleSource : AZ::u8
  39. {
  40. WorldScale, // Scaled in world space.
  41. TargetEntityScale, // Adopt scaling of attachment target entity.
  42. TargetBoneScale, // Adopt scaling of attachment target entity/joint.
  43. };
  44. ScaleSource m_scaleSource = ScaleSource::WorldScale;
  45. };
  46. /*
  47. * Common functionality for game and editor attachment components.
  48. * The BoneFollower tracks movement of the target's bone and
  49. * updates the owning entity's TransformComponent to follow.
  50. * This class should be a member within the attachment component
  51. * and be activated/deactivated along with the component.
  52. * \ref AttachmentComponent
  53. */
  54. class BoneFollower
  55. : public LmbrCentral::AttachmentComponentRequestBus::Handler
  56. , public AZ::TransformNotificationBus::Handler
  57. , public AZ::Render::MeshComponentNotificationBus::Handler
  58. , public AZ::Data::AssetBus::Handler
  59. , public AZ::TickBus::Handler
  60. {
  61. public:
  62. void Activate(AZ::Entity* owner, const AttachmentConfiguration& initialConfiguration, bool targetCanAnimate);
  63. void Deactivate();
  64. ////////////////////////////////////////////////////////////////////////
  65. // AttachmentComponentRequests
  66. void Reattach(bool detachFirst) override;
  67. void Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) override;
  68. void Detach() override;
  69. void SetAttachmentOffset(const AZ::Transform& offset) override;
  70. const char* GetJointName() override;
  71. AZ::EntityId GetTargetEntityId() override;
  72. AZ::Transform GetOffset() override;
  73. ////////////////////////////////////////////////////////////////////////
  74. private:
  75. ////////////////////////////////////////////////////////////////////////
  76. // AZ::TickBus
  77. //! Check target bone transform every frame.
  78. void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
  79. //! Make sure target bone transform updates after animation update.
  80. int GetTickOrder() override;
  81. ////////////////////////////////////////////////////////////////////////
  82. ////////////////////////////////////////////////////////////////////////
  83. // AZ::TransformNotificationBus
  84. //! When target's transform changes
  85. void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
  86. ////////////////////////////////////////////////////////////////////////
  87. ////////////////////////////////////////////////////////////////////////
  88. // MeshComponentEvents
  89. //! When target's mesh changes
  90. void OnModelReady(const AZ::Data::Asset<AZ::RPI::ModelAsset>& modelAsset, const AZ::Data::Instance<AZ::RPI::Model>& model) override;
  91. ////////////////////////////////////////////////////////////////////////
  92. void BindTargetBone();
  93. AZ::Transform QueryBoneTransform() const;
  94. void UpdateOwnerTransformIfNecessary();
  95. //! Entity which which is being attached.
  96. AZ::EntityId m_ownerId;
  97. //! Whether to query bone position per-frame (false while in editor)
  98. bool m_targetCanAnimate = false;
  99. AZ::EntityId m_targetId;
  100. AZStd::string m_targetBoneName;
  101. AZ::Transform m_targetOffset; //!< local transform
  102. AZ::Transform m_targetBoneTransform; //!< local transform of bone
  103. AZ::Transform m_targetEntityTransform; //!< world transform of target
  104. bool m_isTargetEntityTransformKnown = false;
  105. //! Cached value, so we don't update owner's position unnecessarily.
  106. AZ::Transform m_cachedOwnerTransform;
  107. bool m_isUpdatingOwnerTransform = false; //!< detect infinite loops when updating owner's transform
  108. // Cached character values to avoid repeated lookup.
  109. // These are set by calling ResetCharacter()
  110. int m_targetBoneId; //!< negative when bone not found
  111. AttachmentConfiguration::ScaleSource m_scaleSource;
  112. };
  113. /*!
  114. * The AttachmentComponent lets an entity stick to a particular bone on
  115. * a target entity. This is achieved by tracking movement of the target's
  116. * bone and updating the entity's TransformComponent accordingly.
  117. */
  118. class AttachmentComponent
  119. : public AZ::Component
  120. {
  121. public:
  122. AZ_COMPONENT(AttachmentComponent, "{2D17A64A-7AC5-4C02-AC36-C5E8141FFDDF}");
  123. friend class EditorAttachmentComponent;
  124. static void Reflect(AZ::ReflectContext* context);
  125. static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  126. {
  127. provided.push_back(AZ_CRC_CE("AttachmentService"));
  128. }
  129. static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  130. {
  131. incompatible.push_back(AZ_CRC_CE("AttachmentService"));
  132. incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
  133. }
  134. static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  135. {
  136. required.push_back(AZ_CRC_CE("TransformService"));
  137. }
  138. ~AttachmentComponent() override = default;
  139. private:
  140. ////////////////////////////////////////////////////////////////////////
  141. // AZ::Component
  142. void Activate() override;
  143. void Deactivate() override;
  144. ////////////////////////////////////////////////////////////////////////
  145. //! Initial configuration for m_attachment
  146. AttachmentConfiguration m_initialConfiguration;
  147. //! Implements actual attachment functionality
  148. BoneFollower m_boneFollower;
  149. };
  150. } // namespace Render
  151. } // namespace AZ