3
0

ActorComponent.cpp 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  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 <AzCore/Asset/AssetSerializer.h>
  9. #include <AzCore/Component/Entity.h>
  10. #include <AzCore/Serialization/SerializeContext.h>
  11. #include <AzCore/Serialization/EditContext.h>
  12. #include <AzCore/RTTI/BehaviorContext.h>
  13. #include <AzCore/Math/Transform.h>
  14. #include <AzCore/Preprocessor/EnumReflectUtils.h>
  15. #include <AzFramework/Physics/Ragdoll.h>
  16. #include <AzFramework/Physics/RagdollPhysicsBus.h>
  17. #include <AzFramework/Physics/PhysicsScene.h>
  18. #include <AzFramework/Visibility/BoundsBus.h>
  19. #include <LmbrCentral/Animation/AttachmentComponentBus.h>
  20. #include <Integration/Components/ActorComponent.h>
  21. #include <Integration/Rendering/RenderBackendManager.h>
  22. #include <EMotionFX/Source/Transform.h>
  23. #include <EMotionFX/Source/RagdollInstance.h>
  24. #include <EMotionFX/Source/DebugDraw.h>
  25. #include <EMotionFX/Source/AttachmentSkin.h>
  26. #include <EMotionFX/Source/Node.h>
  27. #include <EMotionFX/Source/TransformData.h>
  28. #include <EMotionFX/Source/AttachmentNode.h>
  29. #include <MCore/Source/AzCoreConversions.h>
  30. #include <Atom/RPI.Reflect/Model/ModelAsset.h>
  31. namespace EMotionFX
  32. {
  33. namespace Integration
  34. {
  35. //////////////////////////////////////////////////////////////////////////
  36. class ActorComponentNotificationBehaviorHandler
  37. : public ActorComponentNotificationBus::Handler, public AZ::BehaviorEBusHandler
  38. {
  39. public:
  40. AZ_EBUS_BEHAVIOR_BINDER(ActorComponentNotificationBehaviorHandler, "{4631E2E1-62CB-451D-A6E3-CC40501879AE}", AZ::SystemAllocator,
  41. OnActorInstanceCreated, OnActorInstanceDestroyed);
  42. void OnActorInstanceCreated(EMotionFX::ActorInstance* actorInstance) override
  43. {
  44. Call(FN_OnActorInstanceCreated, actorInstance);
  45. }
  46. void OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) override
  47. {
  48. Call(FN_OnActorInstanceDestroyed, actorInstance);
  49. }
  50. };
  51. //////////////////////////////////////////////////////////////////////////
  52. void ActorComponent::BoundingBoxConfiguration::Set(ActorInstance* actorInstance) const
  53. {
  54. actorInstance->SetExpandBoundsBy(m_expandBy * 0.01f); // Normalize percentage for internal use. (1% == 0.01f)
  55. if (m_autoUpdateBounds)
  56. {
  57. actorInstance->SetupAutoBoundsUpdate(m_updateTimeFrequency, m_boundsType, m_updateItemFrequency);
  58. }
  59. else
  60. {
  61. actorInstance->SetBoundsUpdateType(m_boundsType);
  62. actorInstance->SetBoundsUpdateEnabled(false);
  63. }
  64. }
  65. void ActorComponent::BoundingBoxConfiguration::SetAndUpdate(ActorInstance* actorInstance) const
  66. {
  67. Set(actorInstance);
  68. const AZ::u32 updateFrequency = actorInstance->GetBoundsUpdateEnabled() ? actorInstance->GetBoundsUpdateItemFrequency() : 1;
  69. const ActorInstance::EBoundsType boundUpdateType = actorInstance->GetBoundsUpdateType();
  70. actorInstance->UpdateBounds(actorInstance->GetLODLevel(), boundUpdateType, updateFrequency);
  71. }
  72. void ActorComponent::BoundingBoxConfiguration::Reflect(AZ::ReflectContext* context)
  73. {
  74. if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  75. {
  76. serializeContext->Class<BoundingBoxConfiguration>()
  77. ->Version(2, [](AZ::SerializeContext& sc, AZ::SerializeContext::DataElementNode& node)
  78. {
  79. if (node.GetVersion() < 2)
  80. {
  81. // m_boundsType used to be an enum class with `int' underlying type, is now `u8'
  82. static const char* m_boundsType_name = "m_boundsType";
  83. static AZ::Crc32 m_boundsType_nameCrc(m_boundsType_name);
  84. int m_boundsType_as_int;
  85. if (!node.GetChildData(m_boundsType_nameCrc, m_boundsType_as_int))
  86. {
  87. return false;
  88. }
  89. if (!node.RemoveElementByName(m_boundsType_nameCrc)) return false;
  90. if (node.AddElementWithData(sc, m_boundsType_name, (AZ::u8)m_boundsType_as_int) == -1) return false;
  91. }
  92. return true;
  93. })
  94. ->Field("m_boundsType", &BoundingBoxConfiguration::m_boundsType)
  95. ->Field("m_autoUpdateBounds", &BoundingBoxConfiguration::m_autoUpdateBounds)
  96. ->Field("m_updateTimeFrequency", &BoundingBoxConfiguration::m_updateTimeFrequency)
  97. ->Field("m_updateItemFrequency", &BoundingBoxConfiguration::m_updateItemFrequency)
  98. ->Field("expandBy", &BoundingBoxConfiguration::m_expandBy)
  99. ;
  100. }
  101. }
  102. AZ::Crc32 ActorComponent::BoundingBoxConfiguration::GetVisibilityAutoUpdate() const
  103. {
  104. return m_boundsType != EMotionFX::ActorInstance::BOUNDS_STATIC_BASED ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
  105. }
  106. AZ::Crc32 ActorComponent::BoundingBoxConfiguration::GetVisibilityAutoUpdateSettings() const
  107. {
  108. if (m_boundsType == EMotionFX::ActorInstance::BOUNDS_STATIC_BASED || m_autoUpdateBounds == false)
  109. {
  110. return AZ::Edit::PropertyVisibility::Hide;
  111. }
  112. return AZ::Edit::PropertyVisibility::Show;
  113. }
  114. //////////////////////////////////////////////////////////////////////////
  115. AZ_ENUM_DEFINE_REFLECT_UTILITIES(ActorRenderFlags);
  116. void ActorComponent::Configuration::Reflect(AZ::ReflectContext* context)
  117. {
  118. BoundingBoxConfiguration::Reflect(context);
  119. auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  120. if (serializeContext)
  121. {
  122. ActorRenderFlagsReflect(*serializeContext);
  123. serializeContext->Class<Configuration>()
  124. ->Version(8)
  125. ->Field("ActorAsset", &Configuration::m_actorAsset)
  126. ->Field("AttachmentType", &Configuration::m_attachmentType)
  127. ->Field("AttachmentTarget", &Configuration::m_attachmentTarget)
  128. ->Field("SkinningMethod", &Configuration::m_skinningMethod)
  129. ->Field("LODLevel", &Configuration::m_lodLevel)
  130. ->Field("BoundingBoxConfig", &Configuration::m_bboxConfig)
  131. ->Field("ForceJointsUpdateOOV", &Configuration::m_forceUpdateJointsOOV)
  132. ->Field("RenderFlags", &Configuration::m_renderFlags)
  133. ->Field("ExcludeFromReflectionCubeMaps", &Configuration::m_excludeFromReflectionCubeMaps)
  134. ->Field("LightingChannelConfig", &Configuration::m_lightingChannelConfig)
  135. ->Field("RayTracingEnabled", &Configuration::m_rayTracingEnabled)
  136. ;
  137. }
  138. }
  139. //////////////////////////////////////////////////////////////////////////
  140. void ActorComponent::Reflect(AZ::ReflectContext* context)
  141. {
  142. auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  143. if (serializeContext)
  144. {
  145. Configuration::Reflect(context);
  146. serializeContext->Class<ActorComponent, AZ::Component>()
  147. ->Version(1)
  148. ->Field("Configuration", &ActorComponent::m_configuration)
  149. ;
  150. AZ::EditContext* editContext = serializeContext->GetEditContext();
  151. if (editContext)
  152. {
  153. editContext->Enum<EMotionFX::Integration::Space>("Space", "The transformation space.")
  154. ->Value("Local Space", Space::LocalSpace)
  155. ->Value("Model Space", Space::ModelSpace)
  156. ->Value("World Space", Space::WorldSpace);
  157. }
  158. }
  159. auto* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
  160. if (behaviorContext)
  161. {
  162. behaviorContext->EBus<ActorComponentRequestBus>("ActorComponentRequestBus")
  163. ->Event("GetJointIndexByName", &ActorComponentRequestBus::Events::GetJointIndexByName)
  164. ->Event("GetJointTransform", &ActorComponentRequestBus::Events::GetJointTransform)
  165. ->Event("AttachToEntity", &ActorComponentRequestBus::Events::AttachToEntity)
  166. ->Event("DetachFromEntity", &ActorComponentRequestBus::Events::DetachFromEntity)
  167. ->Event("GetRenderCharacter", &ActorComponentRequestBus::Events::GetRenderCharacter)
  168. ->Event("SetRenderCharacter", &ActorComponentRequestBus::Events::SetRenderCharacter)
  169. ->Event("GetRenderActorVisible", &ActorComponentRequestBus::Events::GetRenderActorVisible)
  170. ->Event("SetRayTracingEnabled", &ActorComponentRequestBus::Events::SetRayTracingEnabled)
  171. ->Event("EnableInstanceUpdate", &ActorComponentRequestBus::Events::EnableInstanceUpdate)
  172. ->VirtualProperty("RenderCharacter", "GetRenderCharacter", "SetRenderCharacter")
  173. ;
  174. behaviorContext->Class<ActorComponent>()->RequestBus("ActorComponentRequestBus");
  175. behaviorContext->EBus<ActorComponentNotificationBus>("ActorComponentNotificationBus")
  176. ->Handler<ActorComponentNotificationBehaviorHandler>()
  177. ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::List)
  178. ;
  179. }
  180. }
  181. void ActorComponent::SetActorAsset(AZ::Data::Asset<ActorAsset> actorAsset)
  182. {
  183. m_configuration.m_actorAsset = actorAsset;
  184. CheckActorCreation();
  185. }
  186. void ActorComponent::EnableInstanceUpdate(bool enable)
  187. {
  188. if (m_actorInstance)
  189. {
  190. m_actorInstance->SetIsEnabled(enable);
  191. }
  192. else
  193. {
  194. AZ_ErrorOnce("EMotionFX", false, "Cannot enable the actor instance update because actor instance haven't been created.");
  195. }
  196. }
  197. //////////////////////////////////////////////////////////////////////////
  198. ActorComponent::ActorComponent(const Configuration* configuration)
  199. : m_sceneFinishSimHandler([this]([[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  200. float fixedDeltatime)
  201. {
  202. if (m_actorInstance)
  203. {
  204. m_actorInstance->PostPhysicsUpdate(fixedDeltatime);
  205. }
  206. }, aznumeric_cast<int32_t>(AzPhysics::SceneEvents::PhysicsStartFinishSimulationPriority::Animation))
  207. {
  208. if (configuration)
  209. {
  210. m_configuration = *configuration;
  211. }
  212. }
  213. //////////////////////////////////////////////////////////////////////////
  214. ActorComponent::~ActorComponent()
  215. {
  216. }
  217. //////////////////////////////////////////////////////////////////////////
  218. void ActorComponent::Activate()
  219. {
  220. m_actorInstance.reset();
  221. auto& cfg = m_configuration;
  222. if (cfg.m_actorAsset.GetId().IsValid())
  223. {
  224. AZ::Data::AssetBus::Handler::BusDisconnect();
  225. AZ::Data::AssetBus::Handler::BusConnect(cfg.m_actorAsset.GetId());
  226. cfg.m_actorAsset.QueueLoad();
  227. }
  228. AZ::TickBus::Handler::BusConnect();
  229. const AZ::EntityId entityId = GetEntityId();
  230. ActorComponentRequestBus::Handler::BusConnect(entityId);
  231. LmbrCentral::AttachmentComponentNotificationBus::Handler::BusConnect(entityId);
  232. AzFramework::CharacterPhysicsDataRequestBus::Handler::BusConnect(entityId);
  233. AzFramework::RagdollPhysicsNotificationBus::Handler::BusConnect(entityId);
  234. AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(entityId);
  235. if (cfg.m_attachmentTarget.IsValid())
  236. {
  237. AttachToEntity(cfg.m_attachmentTarget, cfg.m_attachmentType);
  238. }
  239. }
  240. //////////////////////////////////////////////////////////////////////////
  241. void ActorComponent::Deactivate()
  242. {
  243. AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
  244. AzFramework::RagdollPhysicsNotificationBus::Handler::BusDisconnect();
  245. AzFramework::CharacterPhysicsDataRequestBus::Handler::BusDisconnect();
  246. m_sceneFinishSimHandler.Disconnect();
  247. ActorComponentRequestBus::Handler::BusDisconnect();
  248. AZ::TickBus::Handler::BusDisconnect();
  249. ActorComponentNotificationBus::Handler::BusDisconnect();
  250. LmbrCentral::AttachmentComponentNotificationBus::Handler::BusDisconnect();
  251. AZ::TransformNotificationBus::MultiHandler::BusDisconnect();
  252. AZ::Data::AssetBus::Handler::BusDisconnect();
  253. DestroyActor();
  254. m_configuration.m_actorAsset.Release();
  255. }
  256. //////////////////////////////////////////////////////////////////////////
  257. void ActorComponent::AttachToEntity(AZ::EntityId targetEntityId, [[maybe_unused]] AttachmentType attachmentType)
  258. {
  259. if (targetEntityId.IsValid() && targetEntityId != GetEntityId())
  260. {
  261. m_attachmentTargetEntityId = targetEntityId;
  262. ActorComponentNotificationBus::Handler::BusDisconnect();
  263. ActorComponentNotificationBus::Handler::BusConnect(targetEntityId);
  264. AZ::TransformNotificationBus::MultiHandler::BusConnect(targetEntityId);
  265. // There's no guarantee that we will receive a on transform change call for the target entity because of the entity activate order.
  266. // Enforce a transform query on target to get the correct initial transform.
  267. AZ::Transform transform;
  268. AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); // default to using our own TM
  269. AZ::TransformBus::EventResult(transform, targetEntityId, &AZ::TransformBus::Events::GetWorldTM); // attempt to get target's TM
  270. AZ::TransformBus::Event(GetEntityId(), &AZ::TransformBus::Events::SetWorldTM, transform); // set our TM
  271. }
  272. else
  273. {
  274. DetachFromEntity();
  275. }
  276. }
  277. //////////////////////////////////////////////////////////////////////////
  278. void ActorComponent::DetachFromEntity()
  279. {
  280. if (!m_actorInstance)
  281. {
  282. return;
  283. }
  284. ActorInstance* attachedTo = m_actorInstance->GetAttachedTo();
  285. if (attachedTo)
  286. {
  287. attachedTo->RemoveAttachment(m_actorInstance.get());
  288. AZ::TransformBus::Event(GetEntityId(), &AZ::TransformBus::Events::SetParent, m_attachmentPreviousParent);
  289. AZ::TransformBus::Event(GetEntityId(), &AZ::TransformBus::Events::SetLocalTM, AZ::Transform::CreateIdentity());
  290. AZ::TransformNotificationBus::MultiHandler::BusDisconnect(m_attachmentTargetEntityId);
  291. m_attachmentTargetEntityId.SetInvalid();
  292. }
  293. }
  294. //////////////////////////////////////////////////////////////////////////
  295. bool ActorComponent::GetRenderCharacter() const
  296. {
  297. return AZ::RHI::CheckBitsAny(m_configuration.m_renderFlags, ActorRenderFlags::Solid);
  298. }
  299. //////////////////////////////////////////////////////////////////////////
  300. void ActorComponent::SetRenderCharacter(bool enable)
  301. {
  302. if (enable)
  303. {
  304. m_configuration.m_renderFlags |= ActorRenderFlags::Solid;
  305. }
  306. else
  307. {
  308. m_configuration.m_renderFlags &= ~ActorRenderFlags::Solid;
  309. }
  310. if (m_renderActorInstance)
  311. {
  312. m_renderActorInstance->SetIsVisible(enable);
  313. }
  314. }
  315. //////////////////////////////////////////////////////////////////////////
  316. bool ActorComponent::GetRenderActorVisible() const
  317. {
  318. if (m_renderActorInstance)
  319. {
  320. return m_renderActorInstance->IsVisible();
  321. }
  322. return false;
  323. }
  324. //////////////////////////////////////////////////////////////////////////
  325. void ActorComponent::SetRayTracingEnabled(bool enabled)
  326. {
  327. if (m_renderActorInstance)
  328. {
  329. return m_renderActorInstance->SetRayTracingEnabled(enabled);
  330. }
  331. }
  332. //////////////////////////////////////////////////////////////////////////
  333. SkinningMethod ActorComponent::GetSkinningMethod() const
  334. {
  335. return m_configuration.m_skinningMethod;
  336. }
  337. //////////////////////////////////////////////////////////////////////////
  338. void ActorComponent::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
  339. {
  340. m_configuration.m_actorAsset = asset;
  341. AZ_Assert(m_configuration.m_actorAsset.IsReady() && m_configuration.m_actorAsset->GetActor(), "Actor asset should be loaded and actor valid.");
  342. // We'll defer actor creation until the next tick on the tick bus. This is because OnAssetReady() can sometimes get
  343. // triggered while in the middle of the render tick, since the rendering system sometimes contains blocking loads
  344. // which will still process any pending OnAssetReady() commands while waiting. If that occurs, the actor creation
  345. // would generate errors from trying to create a rendering actor while in the middle of processing the rendering data.
  346. // We can avoid the problem by just always waiting until the next tick to create the actor.
  347. m_processLoadedAsset = true;
  348. }
  349. void ActorComponent::OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset)
  350. {
  351. OnAssetReady(asset);
  352. }
  353. bool ActorComponent::IsPhysicsSceneSimulationFinishEventConnected() const
  354. {
  355. return m_sceneFinishSimHandler.IsConnected();
  356. }
  357. void ActorComponent::SetRenderFlag(ActorRenderFlags renderFlags)
  358. {
  359. m_configuration.m_renderFlags = renderFlags;
  360. }
  361. void ActorComponent::CheckActorCreation()
  362. {
  363. DestroyActor();
  364. // Create actor instance.
  365. auto* actorAsset = m_configuration.m_actorAsset.GetAs<ActorAsset>();
  366. AZ_Error("EMotionFX", actorAsset, "Actor asset is not valid.");
  367. if (!actorAsset)
  368. {
  369. return;
  370. }
  371. m_actorInstance = actorAsset->CreateInstance(GetEntity());
  372. if (!m_actorInstance)
  373. {
  374. AZ_Error("EMotionFX", actorAsset, "Failed to create actor instance.");
  375. return;
  376. }
  377. ActorComponentNotificationBus::Event(
  378. GetEntityId(),
  379. &ActorComponentNotificationBus::Events::OnActorInstanceCreated,
  380. m_actorInstance.get());
  381. m_actorInstance->SetLODLevel(m_configuration.m_lodLevel);
  382. m_actorInstance->SetLightingChannelMask(m_configuration.m_lightingChannelConfig.GetLightingChannelMask());
  383. // Setup initial transform and listen for transform changes.
  384. AZ::Transform transform = AZ::Transform::CreateIdentity();
  385. AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  386. OnTransformChanged(transform, transform);
  387. AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId());
  388. m_actorInstance->UpdateWorldTransform();
  389. // Set bounds update mode and compute bbox first time
  390. m_configuration.m_bboxConfig.SetAndUpdate(m_actorInstance.get());
  391. m_actorInstance->UpdateBounds(0, ActorInstance::EBoundsType::BOUNDS_STATIC_BASED);
  392. // Creating the render actor AFTER both actor asset and mesh asset loaded.
  393. RenderBackend* renderBackend = AZ::Interface<RenderBackendManager>::Get()->GetRenderBackend();
  394. if (renderBackend)
  395. {
  396. actorAsset->InitRenderActor();
  397. // If there is already a RenderActorInstance, destroy it before creating the new one so there are not two instances potentially handling events for the same entityId
  398. m_renderActorInstance.reset(nullptr);
  399. // Create the new RenderActorInstance
  400. m_renderActorInstance.reset(renderBackend->CreateActorInstance(GetEntityId(),
  401. m_actorInstance,
  402. m_configuration.m_actorAsset,
  403. m_configuration.m_skinningMethod,
  404. transform,
  405. m_configuration.m_rayTracingEnabled));
  406. if (m_renderActorInstance)
  407. {
  408. m_renderActorInstance->SetIsVisible(AZ::RHI::CheckBitsAny(m_configuration.m_renderFlags, ActorRenderFlags::Solid));
  409. m_renderActorInstance->SetExcludeFromReflectionCubeMaps(m_configuration.m_excludeFromReflectionCubeMaps);
  410. }
  411. }
  412. // Remember the parent entity before we re-parent (attach) it.
  413. AZ::TransformBus::EventResult(m_attachmentPreviousParent, GetEntityId(), &AZ::TransformBus::Events::GetParentId);
  414. // Reattach all attachments
  415. for (AZ::EntityId& attachment : m_attachments)
  416. {
  417. LmbrCentral::AttachmentComponentRequestBus::Event(attachment, &LmbrCentral::AttachmentComponentRequestBus::Events::Reattach, true);
  418. }
  419. const AZ::EntityId entityId = GetEntityId();
  420. LmbrCentral::AttachmentComponentRequestBus::Event(entityId, &LmbrCentral::AttachmentComponentRequestBus::Events::Reattach, true);
  421. CheckAttachToEntity();
  422. Physics::RagdollConfiguration ragdollConfiguration;
  423. [[maybe_unused]] bool ragdollConfigValid = GetRagdollConfiguration(ragdollConfiguration);
  424. AZ_Assert(ragdollConfigValid, "Ragdoll Configuration is not valid");
  425. AzFramework::CharacterPhysicsDataNotificationBus::Event(entityId, &AzFramework::CharacterPhysicsDataNotifications::OnRagdollConfigurationReady, ragdollConfiguration);
  426. }
  427. //////////////////////////////////////////////////////////////////////////
  428. void ActorComponent::CheckAttachToEntity()
  429. {
  430. // Attach to the target actor if we're both ready.
  431. if (m_actorInstance)
  432. {
  433. if (m_attachmentTargetEntityId.IsValid())
  434. {
  435. // Create the attachment if the target instance is already created.
  436. // Otherwise, listen to the actor instance creation event.
  437. ActorInstance* targetActorInstance = nullptr;
  438. ActorComponentRequestBus::EventResult(targetActorInstance, m_attachmentTargetEntityId, &ActorComponentRequestBus::Events::GetActorInstance);
  439. if (targetActorInstance)
  440. {
  441. DetachFromEntity();
  442. // Make sure we don't generate some circular loop by attaching to each other.
  443. if (!targetActorInstance->CheckIfCanHandleAttachment(m_actorInstance.get()))
  444. {
  445. AZ_Error("EMotionFX", false, "You cannot attach to yourself or create circular dependencies!\n");
  446. return;
  447. }
  448. // Remember the parent entity before we re-parent (attach) it.
  449. AZ::TransformBus::EventResult(m_attachmentPreviousParent, GetEntityId(), &AZ::TransformBus::Events::GetParentId);
  450. // Create the attachment.
  451. AZ_Assert(m_configuration.m_attachmentType == AttachmentType::SkinAttachment, "Expected a skin attachment.");
  452. Attachment* attachment = AttachmentSkin::Create(targetActorInstance, m_actorInstance.get());
  453. m_actorInstance->SetLocalSpaceTransform(Transform::CreateIdentity());
  454. targetActorInstance->AddAttachment(attachment);
  455. AZ::TransformBus::Event(GetEntityId(), &AZ::TransformBus::Events::SetParent, targetActorInstance->GetEntityId());
  456. AZ::TransformBus::Event(GetEntityId(), &AZ::TransformBus::Events::SetLocalTM, AZ::Transform::CreateIdentity());
  457. }
  458. }
  459. else
  460. {
  461. DetachFromEntity();
  462. }
  463. }
  464. }
  465. //////////////////////////////////////////////////////////////////////////
  466. void ActorComponent::DestroyActor()
  467. {
  468. DetachFromEntity();
  469. m_renderActorInstance.reset();
  470. if (m_actorInstance)
  471. {
  472. ActorComponentNotificationBus::Event(
  473. GetEntityId(),
  474. &ActorComponentNotificationBus::Events::OnActorInstanceDestroyed,
  475. m_actorInstance.get());
  476. m_actorInstance.reset();
  477. }
  478. }
  479. //////////////////////////////////////////////////////////////////////////
  480. void ActorComponent::OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world)
  481. {
  482. AZ_UNUSED(local);
  483. const AZ::EntityId* busIdPtr = AZ::TransformNotificationBus::GetCurrentBusId();
  484. if (!busIdPtr || *busIdPtr == GetEntityId()) // Our own entity has moved.
  485. {
  486. // If we're not attached to another actor, keep the EMFX root in sync with any external changes to the entity's transform.
  487. if (m_actorInstance)
  488. {
  489. const Transform localTransform = m_actorInstance->GetParentWorldSpaceTransform().Inversed() * Transform(world);
  490. m_actorInstance->SetLocalSpacePosition(localTransform.m_position);
  491. m_actorInstance->SetLocalSpaceRotation(localTransform.m_rotation);
  492. // Disable updating the scale to prevent feedback from adding up.
  493. // We need to find a better way to handle this or to prevent this feedback loop.
  494. EMFX_SCALECODE
  495. (
  496. m_actorInstance->SetLocalSpaceScale(localTransform.m_scale);
  497. )
  498. }
  499. }
  500. }
  501. //////////////////////////////////////////////////////////////////////////
  502. void ActorComponent::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
  503. {
  504. AZ_PROFILE_FUNCTION(Animation);
  505. // If we've got an asset that finished loading (denoted by an OnAssetReady() call), create the actor instance here.
  506. if (m_processLoadedAsset)
  507. {
  508. CheckActorCreation();
  509. m_processLoadedAsset = false;
  510. }
  511. if (!m_actorInstance || !m_actorInstance->GetIsEnabled())
  512. {
  513. return;
  514. }
  515. if (m_renderActorInstance)
  516. {
  517. m_renderActorInstance->OnTick(deltaTime);
  518. m_renderActorInstance->UpdateBounds();
  519. AZ::Interface<AzFramework::IEntityBoundsUnion>::Get()->RefreshEntityLocalBoundsUnion(GetEntityId());
  520. const bool isInCameraFrustum = m_renderActorInstance->IsInCameraFrustum();
  521. const bool renderActorSolid = AZ::RHI::CheckBitsAny(m_configuration.m_renderFlags, ActorRenderFlags::Solid);
  522. m_renderActorInstance->SetIsVisible(isInCameraFrustum && renderActorSolid);
  523. // Optimization: Set the actor instance invisible when character is out of camera view. This will stop the joint transforms update, except the root joint.
  524. // Calling it after the bounds on the render actor updated.
  525. if (!m_configuration.m_forceUpdateJointsOOV)
  526. {
  527. // Update the skeleton in case solid mesh rendering or any of the debug visualizations are enabled and the character is in the camera frustum.
  528. const bool updateTransforms = AZ::RHI::CheckBitsAny(m_configuration.m_renderFlags, s_requireUpdateTransforms);
  529. m_actorInstance->SetIsVisible(isInCameraFrustum && updateTransforms);
  530. }
  531. }
  532. }
  533. int ActorComponent::GetTickOrder()
  534. {
  535. return AZ::TICK_PRE_RENDER;
  536. }
  537. void ActorComponent::DisplayEntityViewport(
  538. [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo,
  539. [[maybe_unused]] AzFramework::DebugDisplayRequests& debugDisplay)
  540. {
  541. if (m_renderActorInstance)
  542. {
  543. m_renderActorInstance->DebugDraw(m_configuration.m_renderFlags);
  544. }
  545. }
  546. //////////////////////////////////////////////////////////////////////////
  547. void ActorComponent::OnActorInstanceCreated(ActorInstance* actorInstance)
  548. {
  549. auto it = AZStd::find(m_attachments.begin(), m_attachments.end(), actorInstance->GetEntityId());
  550. if (it != m_attachments.end())
  551. {
  552. if (m_actorInstance)
  553. {
  554. LmbrCentral::AttachmentComponentRequestBus::Event(actorInstance->GetEntityId(), &LmbrCentral::AttachmentComponentRequestBus::Events::Reattach, true);
  555. }
  556. }
  557. else
  558. {
  559. CheckAttachToEntity();
  560. }
  561. }
  562. void ActorComponent::OnActorInstanceDestroyed([[maybe_unused]] ActorInstance* actorInstance)
  563. {
  564. DetachFromEntity();
  565. }
  566. //////////////////////////////////////////////////////////////////////////
  567. bool ActorComponent::GetRagdollConfiguration(Physics::RagdollConfiguration& ragdollConfiguration) const
  568. {
  569. if (!m_actorInstance)
  570. {
  571. return false;
  572. }
  573. const AZStd::shared_ptr<PhysicsSetup>& physicsSetup = m_actorInstance->GetActor()->GetPhysicsSetup();
  574. ragdollConfiguration = physicsSetup->GetRagdollConfig();
  575. return true;
  576. }
  577. AZStd::string ActorComponent::GetParentNodeName(const AZStd::string& childName) const
  578. {
  579. if (!m_actorInstance)
  580. {
  581. return AZStd::string();
  582. }
  583. const Skeleton* skeleton = m_actorInstance->GetActor()->GetSkeleton();
  584. Node* childNode = skeleton->FindNodeByName(childName);
  585. if (childNode)
  586. {
  587. const Node* parentNode = childNode->GetParentNode();
  588. if (parentNode)
  589. {
  590. return parentNode->GetNameString();
  591. }
  592. }
  593. return AZStd::string();
  594. }
  595. //////////////////////////////////////////////////////////////////////////
  596. Physics::RagdollState ActorComponent::GetBindPose(const Physics::RagdollConfiguration& config) const
  597. {
  598. Physics::RagdollState physicsPose;
  599. if (!m_actorInstance)
  600. {
  601. return physicsPose;
  602. }
  603. const Actor* actor = m_actorInstance->GetActor();
  604. const Skeleton* skeleton = actor->GetSkeleton();
  605. const Pose* emfxPose = actor->GetBindPose();
  606. size_t numNodes = config.m_nodes.size();
  607. physicsPose.resize(numNodes);
  608. for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++)
  609. {
  610. const char* nodeName = config.m_nodes[nodeIndex].m_debugName.data();
  611. Node* emfxNode = skeleton->FindNodeByName(nodeName);
  612. AZ_Error("EMotionFX", emfxNode, "Could not find bind pose for node %s", nodeName);
  613. if (emfxNode)
  614. {
  615. const Transform& nodeTransform = emfxPose->GetModelSpaceTransform(emfxNode->GetNodeIndex());
  616. physicsPose[nodeIndex].m_position = nodeTransform.m_position;
  617. physicsPose[nodeIndex].m_orientation = nodeTransform.m_rotation;
  618. }
  619. }
  620. return physicsPose;
  621. }
  622. void ActorComponent::OnRagdollActivated()
  623. {
  624. Physics::Ragdoll* ragdoll;
  625. AzFramework::RagdollPhysicsRequestBus::EventResult(ragdoll, m_entity->GetId(), &AzFramework::RagdollPhysicsRequestBus::Events::GetRagdoll);
  626. if (ragdoll && m_actorInstance)
  627. {
  628. m_actorInstance->SetRagdoll(ragdoll);
  629. RagdollInstance* ragdollInstance = m_actorInstance->GetRagdollInstance();
  630. AZ_Assert(ragdollInstance, "As the ragdoll passed in ActorInstance::SetRagdoll() is valid, a valid ragdoll instance is expected to exist.");
  631. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  632. {
  633. sceneInterface->RegisterSceneSimulationFinishHandler(ragdollInstance->GetRagdollSceneHandle(), m_sceneFinishSimHandler);
  634. }
  635. }
  636. }
  637. void ActorComponent::OnRagdollDeactivated()
  638. {
  639. if (m_actorInstance)
  640. {
  641. m_sceneFinishSimHandler.Disconnect();
  642. m_actorInstance->SetRagdoll(nullptr);
  643. }
  644. }
  645. size_t ActorComponent::GetNumJoints() const
  646. {
  647. AZ_Assert(m_actorInstance, "The actor instance needs to be valid.");
  648. return m_actorInstance->GetActor()->GetNumNodes();
  649. }
  650. size_t ActorComponent::GetJointIndexByName(const char* name) const
  651. {
  652. AZ_Assert(m_actorInstance, "The actor instance needs to be valid.");
  653. Node* node = m_actorInstance->GetActor()->GetSkeleton()->FindNodeByNameNoCase(name);
  654. if (node)
  655. {
  656. return static_cast<size_t>(node->GetNodeIndex());
  657. }
  658. return ActorComponentRequests::s_invalidJointIndex;
  659. }
  660. AZ::Transform ActorComponent::GetJointTransform(size_t jointIndex, Space space) const
  661. {
  662. AZ_Assert(m_actorInstance, "The actor instance needs to be valid.");
  663. const size_t index = jointIndex;
  664. const size_t numNodes = m_actorInstance->GetActor()->GetNumNodes();
  665. AZ_Error("EMotionFX", index < numNodes, "GetJointTransform: The joint index %zu is out of bounds [0;%zu]. Entity: %s",
  666. index, numNodes, GetEntity()->GetName().c_str());
  667. if (index >= numNodes)
  668. {
  669. return AZ::Transform::CreateIdentity();
  670. }
  671. Pose* currentPose = m_actorInstance->GetTransformData()->GetCurrentPose();
  672. switch (space)
  673. {
  674. case Space::LocalSpace:
  675. {
  676. return MCore::EmfxTransformToAzTransform(currentPose->GetLocalSpaceTransform(index));
  677. }
  678. case Space::ModelSpace:
  679. {
  680. return MCore::EmfxTransformToAzTransform(currentPose->GetModelSpaceTransform(index));
  681. }
  682. case Space::WorldSpace:
  683. {
  684. return MCore::EmfxTransformToAzTransform(currentPose->GetWorldSpaceTransform(index));
  685. }
  686. default:
  687. AZ_Assert(false, "Unsupported space in GetJointTransform!");
  688. }
  689. return AZ::Transform::CreateIdentity();
  690. }
  691. void ActorComponent::GetJointTransformComponents(size_t jointIndex, Space space, AZ::Vector3& outPosition, AZ::Quaternion& outRotation, AZ::Vector3& outScale) const
  692. {
  693. AZ_Assert(m_actorInstance, "The actor instance needs to be valid.");
  694. const size_t index = jointIndex;
  695. const size_t numNodes = m_actorInstance->GetActor()->GetNumNodes();
  696. AZ_Error("EMotionFX", index < numNodes, "GetJointTransformComponents: The joint index %zu is out of bounds [0;%zu]. Entity: %s",
  697. index, numNodes, GetEntity()->GetName().c_str());
  698. if (index >= numNodes)
  699. {
  700. return;
  701. }
  702. Pose* currentPose = m_actorInstance->GetTransformData()->GetCurrentPose();
  703. switch (space)
  704. {
  705. case Space::LocalSpace:
  706. {
  707. const Transform& localTransform = currentPose->GetLocalSpaceTransform(index);
  708. outPosition = localTransform.m_position;
  709. outRotation = localTransform.m_rotation;
  710. EMFX_SCALECODE
  711. (
  712. outScale = localTransform.m_scale;
  713. )
  714. return;
  715. }
  716. case Space::ModelSpace:
  717. {
  718. const Transform& modelTransform = currentPose->GetModelSpaceTransform(index);
  719. outPosition = modelTransform.m_position;
  720. outRotation = modelTransform.m_rotation;
  721. EMFX_SCALECODE
  722. (
  723. outScale = modelTransform.m_scale;
  724. )
  725. return;
  726. }
  727. case Space::WorldSpace:
  728. {
  729. const Transform worldTransform = currentPose->GetWorldSpaceTransform(index);
  730. outPosition = worldTransform.m_position;
  731. outRotation = worldTransform.m_rotation;
  732. EMFX_SCALECODE
  733. (
  734. outScale = worldTransform.m_scale;
  735. )
  736. return;
  737. }
  738. default:
  739. {
  740. AZ_Assert(false, "Unsupported space in GetJointTransform!");
  741. outPosition = AZ::Vector3::CreateZero();
  742. outRotation = AZ::Quaternion::CreateIdentity();
  743. outScale = AZ::Vector3::CreateOne();
  744. }
  745. }
  746. }
  747. Physics::AnimationConfiguration* ActorComponent::GetPhysicsConfig() const
  748. {
  749. if (m_actorInstance)
  750. {
  751. Actor* actor = m_actorInstance->GetActor();
  752. const AZStd::shared_ptr<PhysicsSetup>& physicsSetup = actor->GetPhysicsSetup();
  753. if (physicsSetup)
  754. {
  755. return &physicsSetup->GetConfig();
  756. }
  757. }
  758. return nullptr;
  759. }
  760. // The entity has attached to the target.
  761. void ActorComponent::OnAttached(AZ::EntityId attachedEntityId)
  762. {
  763. const AZ::EntityId* busIdPtr = LmbrCentral::AttachmentComponentNotificationBus::GetCurrentBusId();
  764. if (busIdPtr)
  765. {
  766. const auto result = AZStd::find(m_attachments.begin(), m_attachments.end(), attachedEntityId);
  767. if (result == m_attachments.end())
  768. {
  769. m_attachments.emplace_back(attachedEntityId);
  770. }
  771. else
  772. {
  773. return;
  774. }
  775. }
  776. if (!m_actorInstance)
  777. {
  778. return;
  779. }
  780. ActorInstance* targetActorInstance = nullptr;
  781. ActorComponentRequestBus::EventResult(targetActorInstance, attachedEntityId, &ActorComponentRequestBus::Events::GetActorInstance);
  782. const char* jointName = nullptr;
  783. LmbrCentral::AttachmentComponentRequestBus::EventResult(jointName, attachedEntityId, &LmbrCentral::AttachmentComponentRequestBus::Events::GetJointName);
  784. if (targetActorInstance)
  785. {
  786. Node* node = jointName ? m_actorInstance->GetActor()->GetSkeleton()->FindNodeByName(jointName) : m_actorInstance->GetActor()->GetSkeleton()->GetNode(0);
  787. if (node)
  788. {
  789. const size_t jointIndex = node->GetNodeIndex();
  790. Attachment* attachment = AttachmentNode::Create(m_actorInstance.get(), jointIndex, targetActorInstance, true /* Managed externally, by this component. */);
  791. m_actorInstance->AddAttachment(attachment);
  792. }
  793. }
  794. }
  795. // The entity is detaching from the target.
  796. void ActorComponent::OnDetached(AZ::EntityId targetId)
  797. {
  798. // Remove the targetId from the attachment list
  799. const AZ::EntityId* busIdPtr = LmbrCentral::AttachmentComponentNotificationBus::GetCurrentBusId();
  800. if (busIdPtr)
  801. {
  802. m_attachments.erase(AZStd::remove(m_attachments.begin(), m_attachments.end(), targetId), m_attachments.end());
  803. }
  804. if (!m_actorInstance)
  805. {
  806. return;
  807. }
  808. ActorInstance* targetActorInstance = nullptr;
  809. ActorComponentRequestBus::EventResult(targetActorInstance, targetId, &ActorComponentRequestBus::Events::GetActorInstance);
  810. if (targetActorInstance)
  811. {
  812. m_actorInstance->RemoveAttachment(targetActorInstance);
  813. }
  814. }
  815. } // namespace Integration
  816. } // namespace EMotionFX