ColliderCapsuleManipulators.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. #include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
  9. #include <EMotionFX/CommandSystem/Source/ColliderCommands.h>
  10. #include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ViewportPluginBus.h>
  11. #include <EMotionStudio/EMStudioSDK/Source/EMStudioManager.h>
  12. #include <Editor/ColliderContainerWidget.h>
  13. #include <Editor/Plugins/Ragdoll/ColliderCapsuleManipulators.h>
  14. namespace EMotionFX
  15. {
  16. const Physics::CapsuleShapeConfiguration* GetCapsuleShapeConfiguration(const PhysicsSetupManipulatorData& physicsSetupManipulatorData)
  17. {
  18. if (!physicsSetupManipulatorData.HasCapsuleCollider())
  19. {
  20. return nullptr;
  21. }
  22. return azdynamic_cast<Physics::CapsuleShapeConfiguration*>(
  23. physicsSetupManipulatorData.m_colliderNodeConfiguration->m_shapes[0].second.get());
  24. }
  25. Physics::CapsuleShapeConfiguration* GetCapsuleShapeConfiguration(PhysicsSetupManipulatorData& physicsSetupManipulatorData)
  26. {
  27. return const_cast<Physics::CapsuleShapeConfiguration*>(
  28. GetCapsuleShapeConfiguration(const_cast<const PhysicsSetupManipulatorData&>(physicsSetupManipulatorData)));
  29. }
  30. void ColliderCapsuleManipulators::InstallCapsuleViewportEditFunctions()
  31. {
  32. if (!m_capsuleViewportEdit)
  33. {
  34. return;
  35. }
  36. m_capsuleViewportEdit->InstallGetManipulatorSpace(
  37. [this]()
  38. {
  39. return m_physicsSetupManipulatorData.m_nodeWorldTransform;
  40. });
  41. m_capsuleViewportEdit->InstallGetNonUniformScale(
  42. []()
  43. {
  44. return AZ::Vector3::CreateOne();
  45. });
  46. m_capsuleViewportEdit->InstallGetTranslationOffset(
  47. [this]()
  48. {
  49. if (!m_physicsSetupManipulatorData.HasCapsuleCollider())
  50. {
  51. return AZ::Vector3::CreateZero();
  52. }
  53. const Physics::ColliderConfiguration* colliderConfiguration =
  54. m_physicsSetupManipulatorData.m_colliderNodeConfiguration->m_shapes[0].first.get();
  55. return colliderConfiguration->m_position;
  56. });
  57. m_capsuleViewportEdit->InstallGetRotationOffset(
  58. [this]()
  59. {
  60. if (!m_physicsSetupManipulatorData.HasCapsuleCollider())
  61. {
  62. return AZ::Quaternion::CreateIdentity();
  63. }
  64. const Physics::ColliderConfiguration* colliderConfiguration =
  65. m_physicsSetupManipulatorData.m_colliderNodeConfiguration->m_shapes[0].first.get();
  66. return colliderConfiguration->m_rotation;
  67. });
  68. m_capsuleViewportEdit->InstallGetCapsuleRadius(
  69. [this]()
  70. {
  71. if (auto* capsuleShapeConfiguration = GetCapsuleShapeConfiguration(m_physicsSetupManipulatorData))
  72. {
  73. return capsuleShapeConfiguration->m_radius;
  74. }
  75. return Physics::ShapeConstants::DefaultCapsuleRadius;
  76. });
  77. m_capsuleViewportEdit->InstallGetCapsuleHeight(
  78. [this]()
  79. {
  80. if (const auto* capsuleShapeConfiguration = GetCapsuleShapeConfiguration(m_physicsSetupManipulatorData))
  81. {
  82. return capsuleShapeConfiguration->m_height;
  83. }
  84. return Physics::ShapeConstants::DefaultCapsuleHeight;
  85. });
  86. m_capsuleViewportEdit->InstallSetCapsuleRadius(
  87. [this](float radius)
  88. {
  89. if (auto* capsuleShapeConfiguration = GetCapsuleShapeConfiguration(m_physicsSetupManipulatorData))
  90. {
  91. capsuleShapeConfiguration->m_radius = radius;
  92. m_physicsSetupManipulatorData.m_collidersWidget->Update();
  93. }
  94. });
  95. m_capsuleViewportEdit->InstallSetCapsuleHeight(
  96. [this](float height)
  97. {
  98. if (auto* capsuleShapeConfiguration = GetCapsuleShapeConfiguration(m_physicsSetupManipulatorData))
  99. {
  100. capsuleShapeConfiguration->m_height = height;
  101. m_physicsSetupManipulatorData.m_collidersWidget->Update();
  102. }
  103. });
  104. m_capsuleViewportEdit->InstallSetTranslationOffset(
  105. [this](const AZ::Vector3& translationOffset)
  106. {
  107. if (m_physicsSetupManipulatorData.HasCapsuleCollider())
  108. {
  109. Physics::ColliderConfiguration* colliderConfiguration =
  110. m_physicsSetupManipulatorData.m_colliderNodeConfiguration->m_shapes[0].first.get();
  111. colliderConfiguration->m_position = translationOffset;
  112. }
  113. });
  114. m_capsuleViewportEdit->InstallBeginEditing(
  115. [this]()
  116. {
  117. BeginEditing();
  118. });
  119. m_capsuleViewportEdit->InstallEndEditing(
  120. [this]()
  121. {
  122. EndEditing();
  123. });
  124. }
  125. void ColliderCapsuleManipulators::Setup(const PhysicsSetupManipulatorData& physicsSetupManipulatorData)
  126. {
  127. m_physicsSetupManipulatorData = physicsSetupManipulatorData;
  128. if (!m_physicsSetupManipulatorData.HasCapsuleCollider())
  129. {
  130. return;
  131. }
  132. const bool allowAsymmetricalEditing = true;
  133. m_capsuleViewportEdit = AZStd::make_unique<AzToolsFramework::CapsuleViewportEdit>(allowAsymmetricalEditing);
  134. InstallCapsuleViewportEditFunctions();
  135. m_capsuleViewportEdit->Setup(EMStudio::g_animManipulatorManagerId);
  136. AZ::TickBus::Handler::BusConnect();
  137. PhysicsSetupManipulatorRequestBus::Handler::BusConnect();
  138. m_adjustColliderCallback = AZStd::make_unique<PhysicsSetupManipulatorCommandCallback>(this, false);
  139. EMStudio::GetCommandManager()->RegisterCommandCallback("AdjustCollider", m_adjustColliderCallback.get());
  140. }
  141. void ColliderCapsuleManipulators::Refresh()
  142. {
  143. if (m_capsuleViewportEdit)
  144. {
  145. m_capsuleViewportEdit->UpdateManipulators();
  146. }
  147. }
  148. void ColliderCapsuleManipulators::Teardown()
  149. {
  150. if (!m_physicsSetupManipulatorData.HasCapsuleCollider())
  151. {
  152. return;
  153. }
  154. EMStudio::GetCommandManager()->RemoveCommandCallback(m_adjustColliderCallback.get(), false);
  155. m_adjustColliderCallback.reset();
  156. PhysicsSetupManipulatorRequestBus::Handler::BusDisconnect();
  157. AZ::TickBus::Handler::BusDisconnect();
  158. if (m_capsuleViewportEdit)
  159. {
  160. m_capsuleViewportEdit->Teardown();
  161. }
  162. }
  163. void ColliderCapsuleManipulators::ResetValues()
  164. {
  165. if (m_capsuleViewportEdit)
  166. {
  167. m_capsuleViewportEdit->ResetValues();
  168. m_capsuleViewportEdit->UpdateManipulators();
  169. }
  170. }
  171. void ColliderCapsuleManipulators::BeginEditing()
  172. {
  173. if (!m_commandGroup.IsEmpty())
  174. {
  175. return;
  176. }
  177. m_commandGroup.SetGroupName("Adjust collider");
  178. const AZ::u32 actorId = m_physicsSetupManipulatorData.m_actor->GetID();
  179. const AZStd::string& nodeName = m_physicsSetupManipulatorData.m_node->GetNameString();
  180. const auto colliderType = PhysicsSetup::ColliderConfigType::Ragdoll;
  181. const size_t colliderIndex = 0;
  182. CommandAdjustCollider* command = aznew CommandAdjustCollider(actorId, nodeName, colliderType, colliderIndex);
  183. m_commandGroup.AddCommand(command);
  184. if (const auto* capsuleShapeConfiguration = GetCapsuleShapeConfiguration(m_physicsSetupManipulatorData))
  185. {
  186. command->SetOldHeight(capsuleShapeConfiguration->m_height);
  187. command->SetOldRadius(capsuleShapeConfiguration->m_radius);
  188. }
  189. }
  190. void ColliderCapsuleManipulators::EndEditing()
  191. {
  192. if (m_commandGroup.IsEmpty())
  193. {
  194. return;
  195. }
  196. if (CommandAdjustCollider* command = azdynamic_cast<CommandAdjustCollider*>(m_commandGroup.GetCommand(0)))
  197. {
  198. if (const auto* capsuleShapeConfiguration = GetCapsuleShapeConfiguration(m_physicsSetupManipulatorData))
  199. {
  200. command->SetHeight(capsuleShapeConfiguration->m_height);
  201. command->SetRadius(capsuleShapeConfiguration->m_radius);
  202. }
  203. }
  204. AZStd::string result;
  205. CommandSystem::GetCommandManager()->ExecuteCommandGroup(m_commandGroup, result);
  206. m_commandGroup.Clear();
  207. }
  208. void ColliderCapsuleManipulators::OnTick([[maybe_unused]] float delta, [[maybe_unused]] AZ::ScriptTimePoint timePoint)
  209. {
  210. if (m_capsuleViewportEdit)
  211. {
  212. const AzFramework::CameraState cameraState = AzToolsFramework::GetCameraState(m_viewportId);
  213. m_capsuleViewportEdit->OnCameraStateChanged(cameraState);
  214. }
  215. }
  216. void ColliderCapsuleManipulators::OnUnderlyingPropertiesChanged()
  217. {
  218. Refresh();
  219. }
  220. } // namespace EMotionFX