EditorColliderComponent.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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 <AzCore/Component/TickBus.h>
  10. #include <AzCore/Component/TransformBus.h>
  11. #include <AzCore/Component/NonUniformScaleBus.h>
  12. #include <AzCore/Math/Quaternion.h>
  13. #include <AzFramework/Entity/EntityDebugDisplayBus.h>
  14. #include <AzFramework/Physics/Common/PhysicsEvents.h>
  15. #include <AzFramework/Physics/Common/PhysicsTypes.h>
  16. #include <AzFramework/Physics/Components/SimulatedBodyComponentBus.h>
  17. #include <AzFramework/Physics/Shape.h>
  18. #include <AzFramework/Physics/ShapeConfiguration.h>
  19. #include <AzFramework/Visibility/BoundsBus.h>
  20. #include <AzToolsFramework/API/ToolsApplicationAPI.h>
  21. #include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
  22. #include <AzToolsFramework/Manipulators/BoxManipulatorRequestBus.h>
  23. #include <AzToolsFramework/Manipulators/ShapeManipulatorRequestBus.h>
  24. #include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
  25. #include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
  26. #include <AzToolsFramework/UI/PropertyEditor/ComponentEditor.hxx>
  27. #include <PhysX/ColliderShapeBus.h>
  28. #include <PhysX/EditorColliderComponentRequestBus.h>
  29. #include <PhysX/MeshAsset.h>
  30. #include <PhysX/MeshColliderComponentBus.h>
  31. #include <System/PhysXSystem.h>
  32. #include <Editor/DebugDraw.h>
  33. namespace AzPhysics
  34. {
  35. class SceneInterface;
  36. struct SimulatedBody;
  37. }
  38. namespace PhysX
  39. {
  40. //! Edit context wrapper for the physics asset and asset specific parameters in the shape configuration.
  41. struct EditorProxyAssetShapeConfig
  42. {
  43. AZ_CLASS_ALLOCATOR(EditorProxyAssetShapeConfig, AZ::SystemAllocator, 0);
  44. AZ_TYPE_INFO(EditorProxyAssetShapeConfig, "{C1B46450-C2A3-4115-A2FB-E5FF3BAAAD15}");
  45. static void Reflect(AZ::ReflectContext* context);
  46. AZ::Data::Asset<Pipeline::MeshAsset> m_pxAsset{ AZ::Data::AssetLoadBehavior::QueueLoad };
  47. Physics::PhysicsAssetShapeConfiguration m_configuration;
  48. };
  49. //! Edit context wrapper for cylinder specific parameters and cached geometry.
  50. struct EditorProxyCylinderShapeConfig
  51. {
  52. AZ_CLASS_ALLOCATOR(EditorProxyCylinderShapeConfig, AZ::SystemAllocator, 0);
  53. AZ_TYPE_INFO(EditorProxyCylinderShapeConfig, "{2394B3D0-E7A1-4B66-8C42-0FFDC1FCAA26}");
  54. static void Reflect(AZ::ReflectContext* context);
  55. //! Cylinder specific parameters.
  56. AZ::u8 m_subdivisionCount = 16;
  57. float m_height = 1.0f;
  58. float m_radius = 1.0f;
  59. //! Configuration stores the convex geometry for the cylinder and shape scale.
  60. Physics::CookedMeshShapeConfiguration m_configuration;
  61. };
  62. //! Proxy container for only displaying a specific shape configuration depending on the shapeType selected.
  63. struct EditorProxyShapeConfig
  64. {
  65. AZ_CLASS_ALLOCATOR(EditorProxyShapeConfig, AZ::SystemAllocator, 0);
  66. AZ_TYPE_INFO(EditorProxyShapeConfig, "{531FB42A-42A9-4234-89BA-FD349EF83D0C}");
  67. static void Reflect(AZ::ReflectContext* context);
  68. EditorProxyShapeConfig() = default;
  69. EditorProxyShapeConfig(const Physics::ShapeConfiguration& shapeConfiguration);
  70. Physics::ShapeType m_shapeType = Physics::ShapeType::PhysicsAsset;
  71. Physics::SphereShapeConfiguration m_sphere;
  72. Physics::BoxShapeConfiguration m_box;
  73. Physics::CapsuleShapeConfiguration m_capsule;
  74. EditorProxyCylinderShapeConfig m_cylinder;
  75. EditorProxyAssetShapeConfig m_physicsAsset;
  76. bool m_hasNonUniformScale = false; //!< Whether there is a non-uniform scale component on this entity.
  77. AZ::u8 m_subdivisionLevel = 4; //!< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling.
  78. Physics::CookedMeshShapeConfiguration m_cookedMesh;
  79. bool IsSphereConfig() const;
  80. bool IsBoxConfig() const;
  81. bool IsCapsuleConfig() const;
  82. bool IsCylinderConfig() const;
  83. bool IsAssetConfig() const;
  84. Physics::ShapeConfiguration& GetCurrent();
  85. const Physics::ShapeConfiguration& GetCurrent() const;
  86. AZStd::shared_ptr<Physics::ShapeConfiguration> CloneCurrent() const;
  87. private:
  88. bool ShowingSubdivisionLevel() const;
  89. AZ::u32 OnShapeTypeChanged();
  90. AZ::u32 OnConfigurationChanged();
  91. Physics::ShapeType m_lastShapeType = Physics::ShapeType::PhysicsAsset;
  92. };
  93. class EditorColliderComponentDescriptor;
  94. //! Editor PhysX Collider Component.
  95. //!
  96. class EditorColliderComponent
  97. : public AzToolsFramework::Components::EditorComponentBase
  98. , protected DebugDraw::DisplayCallback
  99. , protected AzToolsFramework::EntitySelectionEvents::Bus::Handler
  100. , private AzToolsFramework::BoxManipulatorRequestBus::Handler
  101. , private AzToolsFramework::ShapeManipulatorRequestBus::Handler
  102. , private AZ::Data::AssetBus::Handler
  103. , private PhysX::MeshColliderComponentRequestsBus::Handler
  104. , private AZ::TransformNotificationBus::Handler
  105. , private PhysX::ColliderShapeRequestBus::Handler
  106. , private AZ::Render::MeshComponentNotificationBus::Handler
  107. , private PhysX::EditorColliderComponentRequestBus::Handler
  108. , private PhysX::EditorColliderValidationRequestBus::Handler
  109. , private AzPhysics::SimulatedBodyComponentRequestsBus::Handler
  110. , public AzFramework::BoundsRequestBus::Handler
  111. {
  112. public:
  113. AZ_RTTI(EditorColliderComponent, "{FD429282-A075-4966-857F-D0BBF186CFE6}", AzToolsFramework::Components::EditorComponentBase);
  114. AZ_EDITOR_COMPONENT_INTRUSIVE_DESCRIPTOR_TYPE(EditorColliderComponent);
  115. AZ_CLASS_ALLOCATOR(EditorColliderComponent, AZ::SystemAllocator, 0);
  116. friend class EditorColliderComponentDescriptor;
  117. static void Reflect(AZ::ReflectContext* context);
  118. static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
  119. static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
  120. static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
  121. static AZ::ComponentDescriptor* CreateDescriptor();
  122. EditorColliderComponent() = default;
  123. EditorColliderComponent(
  124. const Physics::ColliderConfiguration& colliderConfiguration,
  125. const Physics::ShapeConfiguration& shapeConfiguration);
  126. // these functions are made virtual because we call them from other modules
  127. virtual const EditorProxyShapeConfig& GetShapeConfiguration() const;
  128. virtual const Physics::ColliderConfiguration& GetColliderConfiguration() const;
  129. virtual Physics::ColliderConfiguration GetColliderConfigurationScaled() const;
  130. Physics::ColliderConfiguration GetColliderConfigurationNoOffset() const;
  131. // BoundsRequestBus overrides ...
  132. AZ::Aabb GetWorldBounds() override;
  133. AZ::Aabb GetLocalBounds() override;
  134. void BuildGameEntity(AZ::Entity* gameEntity) override;
  135. private:
  136. AZ_DISABLE_COPY_MOVE(EditorColliderComponent)
  137. // AZ::Component
  138. void Activate() override;
  139. void UpdateShapeConfiguration();
  140. void Deactivate() override;
  141. //! AzToolsFramework::EntitySelectionEvents
  142. void OnSelected() override;
  143. void OnDeselected() override;
  144. // DisplayCallback overrides ...
  145. void Display(const AzFramework::ViewportInfo& viewportInfo,
  146. AzFramework::DebugDisplayRequests& debugDisplay) const override;
  147. void DisplayCylinderCollider(AzFramework::DebugDisplayRequests& debugDisplay) const;
  148. void DisplayMeshCollider(AzFramework::DebugDisplayRequests& debugDisplay) const;
  149. void DisplayUnscaledPrimitiveCollider(AzFramework::DebugDisplayRequests& debugDisplay) const;
  150. void DisplayScaledPrimitiveCollider(AzFramework::DebugDisplayRequests& debugDisplay) const;
  151. // AZ::Data::AssetBus::Handler
  152. void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
  153. void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
  154. // PhysXMeshColliderComponentRequestBus
  155. AZ::Data::Asset<Pipeline::MeshAsset> GetMeshAsset() const override;
  156. void SetMeshAsset(const AZ::Data::AssetId& id) override;
  157. void UpdateMaterialSlotsFromMeshAsset();
  158. // TransformBus
  159. void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
  160. // non-uniform scale handling
  161. void OnNonUniformScaleChanged(const AZ::Vector3& nonUniformScale);
  162. // AzToolsFramework::BoxManipulatorRequestBus
  163. AZ::Vector3 GetDimensions() const override;
  164. void SetDimensions(const AZ::Vector3& dimensions) override;
  165. AZ::Transform GetCurrentLocalTransform() const override;
  166. // AzToolsFramework::ShapeManipulatorRequestBus overrides ...
  167. AZ::Vector3 GetTranslationOffset() const override;
  168. void SetTranslationOffset(const AZ::Vector3& translationOffset) override;
  169. AZ::Transform GetManipulatorSpace() const override;
  170. // AZ::Render::MeshComponentNotificationBus
  171. void OnModelReady(const AZ::Data::Asset<AZ::RPI::ModelAsset>& modelAsset,
  172. const AZ::Data::Instance<AZ::RPI::Model>& model) override;
  173. // PhysX::ColliderShapeBus
  174. AZ::Aabb GetColliderShapeAabb() override;
  175. bool IsTrigger() override;
  176. // PhysX::EditorColliderComponentRequestBus
  177. void SetColliderOffset(const AZ::Vector3& offset) override;
  178. AZ::Vector3 GetColliderOffset() const override;
  179. void SetColliderRotation(const AZ::Quaternion& rotation) override;
  180. AZ::Quaternion GetColliderRotation() const override;
  181. AZ::Transform GetColliderWorldTransform() const override;
  182. void SetShapeType(Physics::ShapeType shapeType) override;
  183. Physics::ShapeType GetShapeType() const override;
  184. void SetSphereRadius(float radius) override;
  185. float GetSphereRadius() const override;
  186. void SetCapsuleRadius(float radius) override;
  187. float GetCapsuleRadius() const override;
  188. void SetCapsuleHeight(float height) override;
  189. float GetCapsuleHeight() const override;
  190. void SetCylinderRadius(float radius) override;
  191. float GetCylinderRadius() const override;
  192. void SetCylinderHeight(float height) override;
  193. float GetCylinderHeight() const override;
  194. void SetCylinderSubdivisionCount(AZ::u8 subdivisionCount) override;
  195. AZ::u8 GetCylinderSubdivisionCount() const override;
  196. void SetAssetScale(const AZ::Vector3& scale) override;
  197. AZ::Vector3 GetAssetScale() const override;
  198. // PhysX::EditorColliderValidationRequestBus overrides ...
  199. void ValidateRigidBodyMeshGeometryType() override;
  200. AZ::Transform GetColliderLocalTransform() const;
  201. EditorProxyShapeConfig m_shapeConfiguration;
  202. Physics::ColliderConfiguration m_configuration;
  203. AZ::u32 OnConfigurationChanged();
  204. void UpdateShapeConfigurationScale();
  205. // AzPhysics::SimulatedBodyComponentRequestsBus::Handler overrides ...
  206. void EnablePhysics() override;
  207. void DisablePhysics() override;
  208. bool IsPhysicsEnabled() const override;
  209. AZ::Aabb GetAabb() const override;
  210. AzPhysics::SimulatedBody* GetSimulatedBody() override;
  211. AzPhysics::SimulatedBodyHandle GetSimulatedBodyHandle() const override;
  212. AzPhysics::SceneQueryHit RayCast(const AzPhysics::RayCastRequest& request) override;
  213. // Mesh collider
  214. void UpdateMeshAsset();
  215. bool IsAssetConfig() const;
  216. // Cylinder collider
  217. void UpdateCylinderCookedMesh();
  218. void CreateStaticEditorCollider();
  219. void ClearStaticEditorCollider();
  220. void BuildDebugDrawMesh() const;
  221. AZ::ComponentDescriptor::StringWarningArray GetComponentWarnings() const { return m_componentWarnings; };
  222. using ComponentModeDelegate = AzToolsFramework::ComponentModeFramework::ComponentModeDelegate;
  223. ComponentModeDelegate m_componentModeDelegate; //!< Responsible for detecting ComponentMode activation
  224. //!< and creating a concrete ComponentMode.
  225. AzPhysics::SceneInterface* m_sceneInterface = nullptr;
  226. AzPhysics::SceneHandle m_editorSceneHandle = AzPhysics::InvalidSceneHandle;
  227. AzPhysics::SimulatedBodyHandle m_editorBodyHandle = AzPhysics::InvalidSimulatedBodyHandle;
  228. // Auto-assigning collision mesh utility functions
  229. bool ShouldUpdateCollisionMeshFromRender() const;
  230. void SetCollisionMeshFromRender();
  231. AZ::Data::Asset<AZ::Data::AssetData> GetRenderMeshAsset() const;
  232. AZ::Data::AssetId FindMatchingPhysicsAsset(const AZ::Data::Asset<AZ::Data::AssetData>& renderMeshAsset,
  233. const AZStd::vector<AZ::Data::AssetId>& physicsAssets);
  234. void ValidateAssetMaterials();
  235. void InitEventHandlers();
  236. DebugDraw::Collider m_colliderDebugDraw;
  237. AzPhysics::SystemEvents::OnConfigurationChangedEvent::Handler m_physXConfigChangedHandler;
  238. AZ::Transform m_cachedWorldTransform;
  239. AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler; //!< Responds to changes in non-uniform scale.
  240. bool m_hasNonUniformScale = false; //!< Whether there is a non-uniform scale component on this entity.
  241. AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne(); //!< Caches the current non-uniform scale.
  242. mutable AZStd::optional<Physics::CookedMeshShapeConfiguration> m_scaledPrimitive; //!< Approximation for non-uniformly scaled primitive.
  243. AZ::Aabb m_cachedAabb = AZ::Aabb::CreateNull(); //!< Cache the Aabb to avoid recalculating it.
  244. bool m_cachedAabbDirty = true; //!< Track whether the cached Aabb needs to be recomputed.
  245. AZ::ComponentDescriptor::StringWarningArray m_componentWarnings;
  246. };
  247. class EditorColliderComponentDescriptor :
  248. public AZ::ComponentDescriptorHelper<EditorColliderComponent>
  249. {
  250. public:
  251. AZ_CLASS_ALLOCATOR(EditorColliderComponentDescriptor, AZ::SystemAllocator, 0);
  252. AZ_TYPE_INFO(EditorColliderComponentDescriptor, "{E099B5D6-B03F-436C-AB8E-7ADE4DAD74A0}");
  253. EditorColliderComponentDescriptor() = default;
  254. void Reflect(AZ::ReflectContext* reflection) const override;
  255. void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided, const AZ::Component* instance) const override;
  256. void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent, const AZ::Component* instance) const override;
  257. void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required, const AZ::Component* instance) const override;
  258. void GetWarnings(AZ::ComponentDescriptor::StringWarningArray& warnings, const AZ::Component* instance) const override;
  259. };
  260. } // namespace PhysX