NamedPosesManager.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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 <Clients/NamedPosesManager.h>
  9. #include "CommonUtilities.h"
  10. #include <AzCore/Component/EntityId.h>
  11. #include <AzCore/Component/TransformBus.h>
  12. #include <AzCore/Math/Transform.h>
  13. #include <AzCore/Outcome/Outcome.h>
  14. #include <AzCore/Serialization/SerializeContext.h>
  15. #include <AzCore/std/containers/unordered_set.h>
  16. #include <AzCore/std/string/string.h>
  17. #include <AzFramework/Components/TransformComponent.h>
  18. #include <AzFramework/Entity/GameEntityContextBus.h>
  19. #include <Components/NamedPoseComponent.h>
  20. #include <SimulationInterfaces/Bounds.h>
  21. #include <SimulationInterfaces/NamedPoseManagerRequestBus.h>
  22. #include <SimulationInterfaces/Result.h>
  23. #include <SimulationInterfaces/SimulationFeaturesAggregatorRequestBus.h>
  24. #include <AzFramework/Physics/Shape.h>
  25. #include <AzFramework/Physics/ShapeConfiguration.h>
  26. #include <AzFramework/Physics/SimulatedBodies/StaticRigidBody.h>
  27. #include <LmbrCentral/Scripting/TagComponentBus.h>
  28. #include <SimulationInterfaces/SimulationInterfacesTypeIds.h>
  29. #include <simulation_interfaces/msg/result.hpp>
  30. #include <simulation_interfaces/msg/simulator_features.hpp>
  31. #include <simulation_interfaces/srv/spawn_entity.hpp>
  32. namespace SimulationInterfaces
  33. {
  34. AZ_COMPONENT_IMPL(NamedPoseManager, "NamedPoseManager", NamedPoseManagerTypeId);
  35. void NamedPoseManager::Reflect(AZ::ReflectContext* context)
  36. {
  37. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  38. {
  39. serializeContext->Class<NamedPoseManager, AZ::Component>()->Version(0);
  40. }
  41. }
  42. void NamedPoseManager::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  43. {
  44. provided.push_back(AZ_CRC_CE("NamedPoseManagerService"));
  45. }
  46. void NamedPoseManager::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  47. {
  48. incompatible.push_back(AZ_CRC_CE("NamedPoseManagerService"));
  49. }
  50. void NamedPoseManager::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
  51. {
  52. required.push_back(AZ_CRC_CE("SimulationFeaturesAggregator"));
  53. }
  54. void NamedPoseManager::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
  55. {
  56. dependent.push_back(AZ_CRC_CE("PhysicsService"));
  57. dependent.push_back(AZ_CRC_CE("SimulationFeaturesAggregator"));
  58. }
  59. NamedPoseManager::NamedPoseManager()
  60. {
  61. if (NamedPoseManagerRequestBusInterface::Get() == nullptr)
  62. {
  63. NamedPoseManagerRequestBusInterface::Register(this);
  64. }
  65. }
  66. NamedPoseManager::~NamedPoseManager()
  67. {
  68. if (NamedPoseManagerRequestBusInterface::Get() == this)
  69. {
  70. NamedPoseManagerRequestBusInterface::Unregister(this);
  71. }
  72. }
  73. void NamedPoseManager::Init()
  74. {
  75. }
  76. void NamedPoseManager::Activate()
  77. {
  78. SimulationFeaturesAggregatorRequestBus::Broadcast(
  79. &SimulationFeaturesAggregatorRequests::AddSimulationFeatures,
  80. AZStd::unordered_set<SimulationFeatureType>{
  81. simulation_interfaces::msg::SimulatorFeatures::NAMED_POSES,
  82. simulation_interfaces::msg::SimulatorFeatures::POSE_BOUNDS,
  83. });
  84. NamedPoseManagerRequestBus::Handler::BusConnect();
  85. }
  86. void NamedPoseManager::Deactivate()
  87. {
  88. NamedPoseManagerRequestBus::Handler::BusDisconnect();
  89. }
  90. AZ::Outcome<void, FailedResult> NamedPoseManager::RegisterNamedPose(AZ::EntityId& namedPoseEntityId)
  91. {
  92. // check if given entity has named pose component
  93. AZ::Entity* entity = nullptr;
  94. AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, namedPoseEntityId);
  95. if (!entity)
  96. {
  97. return AZ::Failure(
  98. FailedResult(simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED, "Failed to gather entity with given id"));
  99. }
  100. auto namedPoseComponent = entity->FindComponent<NamedPoseComponent>();
  101. if (!namedPoseComponent)
  102. {
  103. return AZ::Failure(FailedResult(
  104. simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED,
  105. "Entity with given Id doesn't have NamedPoseComponent, use CreateNamedPose method to create new pose"));
  106. }
  107. NamedPose configuration;
  108. NamedPoseComponentRequestBus::EventResult(configuration, namedPoseEntityId, &NamedPoseComponentRequests::GetConfiguration);
  109. if (m_namedPoseToEntityId.contains(configuration.m_name))
  110. {
  111. return AZ::Failure(FailedResult(
  112. simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED,
  113. "Named pose with given name already exists in the record. Change name of your entity with NamedPoseComponent"));
  114. }
  115. m_namedPoseToEntityId[configuration.m_name] = namedPoseEntityId;
  116. return AZ::Success();
  117. }
  118. AZ::Outcome<void, FailedResult> NamedPoseManager::UnregisterNamedPose(AZ::EntityId& namedPoseEntityId)
  119. {
  120. if (!namedPoseEntityId.IsValid())
  121. {
  122. return AZ::Failure(FailedResult(simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED, "Given ID is invalid"));
  123. }
  124. AZStd::string name;
  125. AZ::ComponentApplicationBus::BroadcastResult(name, &AZ::ComponentApplicationRequests::GetEntityName, namedPoseEntityId);
  126. if (m_namedPoseToEntityId.contains(name))
  127. {
  128. m_namedPoseToEntityId.erase(name);
  129. return AZ::Success();
  130. }
  131. return AZ::Failure(
  132. FailedResult(simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED, "Named pose with given id is not registered"));
  133. }
  134. AZ::Outcome<NamedPoseList, FailedResult> NamedPoseManager::GetNamedPoses(const TagFilter& tags)
  135. {
  136. auto filteredEntities = Utils::FilterNamedPosesByTag(m_namedPoseToEntityId, tags);
  137. NamedPoseList namedPoseList;
  138. namedPoseList.reserve(filteredEntities.size());
  139. for (auto& [name, entityId] : filteredEntities)
  140. {
  141. NamedPose configuration;
  142. NamedPoseComponentRequestBus::EventResult(configuration, entityId, &NamedPoseComponentRequests::GetConfiguration);
  143. namedPoseList.push_back(configuration);
  144. }
  145. return AZ::Success(namedPoseList);
  146. }
  147. AZ::Outcome<Bounds, FailedResult> NamedPoseManager::GetNamedPoseBounds(const AZStd::string& name)
  148. {
  149. if (!m_namedPoseToEntityId.contains(name))
  150. {
  151. return AZ::Failure(
  152. FailedResult(simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED, "Named pose with given name is not registered"));
  153. }
  154. AZ::EntityId namedPoseEntityId = m_namedPoseToEntityId.at(name);
  155. if (!namedPoseEntityId.IsValid())
  156. {
  157. return AZ::Failure(FailedResult(
  158. simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED,
  159. AZStd::string::format("Named pose with given name %s has invalid entity ID", name.c_str())));
  160. }
  161. // get simulated body
  162. auto simulatedBody = Utils::GetSimulatedBody(namedPoseEntityId);
  163. if (!simulatedBody.IsSuccess())
  164. {
  165. Bounds emptyBounds;
  166. emptyBounds.m_boundsType = simulation_interfaces::msg::Bounds::TYPE_EMPTY;
  167. return emptyBounds;
  168. }
  169. // only static rigid body makes sense to be named pose bounds.
  170. auto staticRigidBody = azdynamic_cast<AzPhysics::StaticRigidBody*>(simulatedBody.GetValue());
  171. if (!staticRigidBody)
  172. {
  173. return AZ::Failure(FailedResult(
  174. simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED,
  175. "Named Pose in simulation interfaces supports bounds defined by the static rigid body"));
  176. }
  177. const AZ::u32 shapesCount = staticRigidBody->GetShapeCount();
  178. if (shapesCount == 0)
  179. {
  180. Bounds emptyBounds;
  181. emptyBounds.m_boundsType = simulation_interfaces::msg::Bounds::TYPE_EMPTY;
  182. return emptyBounds;
  183. }
  184. if (shapesCount > 1)
  185. {
  186. return AZ::Failure(FailedResult(
  187. simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED,
  188. "Named Pose in simulation interfaces doesn't support multiple shapes"));
  189. }
  190. AZStd::shared_ptr<Physics::Shape> shape = staticRigidBody->GetShape(0);
  191. auto boundsOutput = Utils::ConvertPhysicalShapeToBounds(shape, namedPoseEntityId);
  192. if (boundsOutput.IsSuccess())
  193. {
  194. return AZ::Success(boundsOutput.GetValue());
  195. }
  196. return AZ::Failure(FailedResult(simulation_interfaces::msg::Result::RESULT_OPERATION_FAILED, boundsOutput.GetError()));
  197. }
  198. } // namespace SimulationInterfaces