3
0

SystemComponent.cpp 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  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/Component/ComponentApplication.h>
  9. #include <AzCore/Component/TransformBus.h>
  10. #include <AzCore/Serialization/SerializeContext.h>
  11. #include <AzCore/Serialization/EditContext.h>
  12. #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
  13. #include <AzCore/RTTI/BehaviorContext.h>
  14. #include <AzCore/Utils/Utils.h>
  15. #include <AzFramework/Physics/CharacterBus.h>
  16. #include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
  17. #include <EMotionFX/Source/Allocators.h>
  18. #include <EMotionFX/Source/SingleThreadScheduler.h>
  19. #include <EMotionFX/Source/EMotionFXManager.h>
  20. #include <EMotionFX/Source/AnimGraphManager.h>
  21. #include <EMotionFX/Source/AnimGraphObjectFactory.h>
  22. #include <EMotionFX/Source/MotionSet.h>
  23. #include <EMotionFX/Source/Recorder.h>
  24. #include <EMotionFX/Source/ConstraintTransformRotationAngles.h>
  25. #include <EMotionFX/Source/Parameter/ParameterFactory.h>
  26. #include <EMotionFX/Source/TwoStringEventData.h>
  27. #include <EMotionFX/Source/EventDataFootIK.h>
  28. #include <EMotionFX/Source/EventDataFloatArray.h>
  29. #include <EMotionFX/Source/MotionEvent.h>
  30. #include <EMotionFX/Source/AnimGraphNodeGroup.h>
  31. #include <EMotionFX/Source/MotionEventTable.h>
  32. #include <EMotionFX/Source/MotionEventTrack.h>
  33. #include <EMotionFX/Source/AnimGraphSyncTrack.h>
  34. #include <EMotionFX/Source/AnimGraph.h>
  35. #include <EMotionFX/Source/ActorManager.h>
  36. #include <EMotionFX/Source/ObjectId.h>
  37. #include <EMotionFX/Source/PhysicsSetup.h>
  38. #include <EMotionFX/Source/SimulatedObjectSetup.h>
  39. #include <MCore/Source/Command.h>
  40. #include <EMotionFX/CommandSystem/Source/MotionEventCommands.h>
  41. #include <EMotionFX/CommandSystem/Source/SimulatedObjectCommands.h>
  42. #include <EMotionFX/CommandSystem/Source/RagdollCommands.h>
  43. #include <EMotionFX/Source/PoseData.h>
  44. #include <EMotionFX/Source/PoseDataRagdoll.h>
  45. #include <Integration/AnimationBus.h>
  46. #include <Integration/EMotionFXBus.h>
  47. #include <Integration/Assets/ActorAsset.h>
  48. #include <Integration/Assets/MotionAsset.h>
  49. #include <Integration/Assets/MotionSetAsset.h>
  50. #include <Integration/Assets/AnimGraphAsset.h>
  51. #include <Integration/System/SystemComponent.h>
  52. #include <Integration/System/CVars.h>
  53. #include <AzFramework/Physics/PhysicsScene.h>
  54. #include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
  55. #include <AzFramework/Physics/Common/PhysicsTypes.h>
  56. #include <Integration/MotionExtractionBus.h>
  57. #if defined(EMOTIONFXANIMATION_EDITOR) // EMFX tools / editor includes
  58. // Qt
  59. #include <QtGui/QSurfaceFormat>
  60. // EMStudio tools and main window registration
  61. #include <LyViewPaneNames.h>
  62. #include <AzToolsFramework/ActionManager/Action/ActionManagerInterface.h>
  63. #include <AzToolsFramework/API/ViewPaneOptions.h>
  64. #include <AzQtComponents/Components/FancyDocking.h>
  65. #include <AzCore/std/string/wildcard.h>
  66. #include <AzCore/Component/ComponentApplicationBus.h>
  67. #include <QApplication>
  68. #include <EMotionStudio/EMStudioSDK/Source/MainWindow.h>
  69. #include <EMotionStudio/EMStudioSDK/Source/PluginManager.h>
  70. #include <Source/Editor/PropertyWidgets/PropertyTypes.h>
  71. #include <EMotionFX_Traits_Platform.h>
  72. #include <EMotionFX/Source/AnimGraphStateMachine.h>
  73. #include <EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h>
  74. #include <EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h>
  75. #include <EMotionStudio/Plugins/StandardPlugins/Source/MotionSetsWindow/MotionSetsWindowPlugin.h>
  76. #include <IEditor.h>
  77. #endif // EMOTIONFXANIMATION_EDITOR
  78. #include <IConsole.h>
  79. #include <ISystem.h>
  80. // include required AzCore headers
  81. #include <AzCore/IO/FileIO.h>
  82. #include <AzFramework/API/ApplicationAPI.h>
  83. namespace EMotionFX
  84. {
  85. namespace Integration
  86. {
  87. //////////////////////////////////////////////////////////////////////////
  88. class EMotionFXEventHandler
  89. : public EMotionFX::EventHandler
  90. {
  91. public:
  92. AZ_CLASS_ALLOCATOR(EMotionFXEventHandler, EMotionFXAllocator);
  93. const AZStd::vector<EventTypes> GetHandledEventTypes() const override
  94. {
  95. return {
  96. EVENT_TYPE_ON_EVENT,
  97. EVENT_TYPE_ON_HAS_LOOPED,
  98. EVENT_TYPE_ON_STATE_ENTERING,
  99. EVENT_TYPE_ON_STATE_ENTER,
  100. EVENT_TYPE_ON_STATE_END,
  101. EVENT_TYPE_ON_STATE_EXIT,
  102. EVENT_TYPE_ON_START_TRANSITION,
  103. EVENT_TYPE_ON_END_TRANSITION
  104. };
  105. }
  106. /// Dispatch motion events to listeners via ActorNotificationBus::OnMotionEvent.
  107. void OnEvent(const EMotionFX::EventInfo& emfxInfo) override
  108. {
  109. const ActorInstance* actorInstance = emfxInfo.m_actorInstance;
  110. if (actorInstance)
  111. {
  112. const AZ::EntityId owningEntityId = actorInstance->GetEntityId();
  113. // Fill engine-compatible structure to dispatch to game code.
  114. MotionEvent motionEvent;
  115. motionEvent.m_entityId = owningEntityId;
  116. motionEvent.m_actorInstance = emfxInfo.m_actorInstance;
  117. motionEvent.m_motionInstance = emfxInfo.m_motionInstance;
  118. motionEvent.m_time = emfxInfo.m_timeValue;
  119. // TODO
  120. for (const auto& eventData : emfxInfo.m_event->GetEventDatas())
  121. {
  122. if (const EMotionFX::TwoStringEventData* twoStringEventData = azrtti_cast<const EMotionFX::TwoStringEventData*>(eventData.get()))
  123. {
  124. motionEvent.m_eventTypeName = twoStringEventData->GetSubject().c_str();
  125. motionEvent.SetParameterString(twoStringEventData->GetParameters().c_str(), twoStringEventData->GetParameters().size());
  126. break;
  127. }
  128. if (const EMotionFX::EventDataFloatArray* floatArrayEventData =
  129. azrtti_cast<const EMotionFX::EventDataFloatArray*>(eventData.get()))
  130. {
  131. motionEvent.m_eventTypeName = floatArrayEventData->GetSubject().c_str();
  132. const AZStd::string parameterString = floatArrayEventData->DataToString();
  133. motionEvent.SetParameterString(parameterString.c_str(), parameterString.size());
  134. break;
  135. }
  136. }
  137. motionEvent.m_globalWeight = emfxInfo.m_globalWeight;
  138. motionEvent.m_localWeight = emfxInfo.m_localWeight;
  139. motionEvent.m_isEventStart = emfxInfo.IsEventStart();
  140. // Queue the event to flush on the main thread.
  141. ActorNotificationBus::QueueEvent(owningEntityId, &ActorNotificationBus::Events::OnMotionEvent, AZStd::move(motionEvent));
  142. }
  143. }
  144. void OnHasLooped(EMotionFX::MotionInstance* motionInstance) override
  145. {
  146. const ActorInstance* actorInstance = motionInstance->GetActorInstance();
  147. if (actorInstance)
  148. {
  149. const AZ::EntityId owningEntityId = actorInstance->GetEntityId();
  150. ActorNotificationBus::QueueEvent(owningEntityId, &ActorNotificationBus::Events::OnMotionLoop, motionInstance->GetMotion()->GetName());
  151. }
  152. }
  153. void OnStateEntering(EMotionFX::AnimGraphInstance* animGraphInstance, EMotionFX::AnimGraphNode* state) override
  154. {
  155. const ActorInstance* actorInstance = animGraphInstance->GetActorInstance();
  156. if (actorInstance && state)
  157. {
  158. const AZ::EntityId owningEntityId = actorInstance->GetEntityId();
  159. ActorNotificationBus::QueueEvent(owningEntityId, &ActorNotificationBus::Events::OnStateEntering, state->GetName());
  160. }
  161. }
  162. void OnStateEnter(EMotionFX::AnimGraphInstance* animGraphInstance, EMotionFX::AnimGraphNode* state) override
  163. {
  164. const ActorInstance* actorInstance = animGraphInstance->GetActorInstance();
  165. if (actorInstance && state)
  166. {
  167. const AZ::EntityId owningEntityId = actorInstance->GetEntityId();
  168. ActorNotificationBus::QueueEvent(owningEntityId, &ActorNotificationBus::Events::OnStateEntered, state->GetName());
  169. }
  170. }
  171. void OnStateEnd(EMotionFX::AnimGraphInstance* animGraphInstance, EMotionFX::AnimGraphNode* state) override
  172. {
  173. const ActorInstance* actorInstance = animGraphInstance->GetActorInstance();
  174. if (actorInstance && state)
  175. {
  176. const AZ::EntityId owningEntityId = actorInstance->GetEntityId();
  177. ActorNotificationBus::QueueEvent(owningEntityId, &ActorNotificationBus::Events::OnStateExiting, state->GetName());
  178. }
  179. }
  180. void OnStateExit(EMotionFX::AnimGraphInstance* animGraphInstance, EMotionFX::AnimGraphNode* state) override
  181. {
  182. const ActorInstance* actorInstance = animGraphInstance->GetActorInstance();
  183. if (actorInstance && state)
  184. {
  185. const AZ::EntityId owningEntityId = actorInstance->GetEntityId();
  186. ActorNotificationBus::QueueEvent(owningEntityId, &ActorNotificationBus::Events::OnStateExited, state->GetName());
  187. }
  188. }
  189. void OnStartTransition(EMotionFX::AnimGraphInstance* animGraphInstance, EMotionFX::AnimGraphStateTransition* transition) override
  190. {
  191. const ActorInstance* actorInstance = animGraphInstance->GetActorInstance();
  192. if (actorInstance)
  193. {
  194. const AZ::EntityId owningEntityId = actorInstance->GetEntityId();
  195. const char* sourceName = transition->GetSourceNode() ? transition->GetSourceNode()->GetName() : "";
  196. const char* targetName = transition->GetTargetNode() ? transition->GetTargetNode()->GetName() : "";
  197. ActorNotificationBus::QueueEvent(owningEntityId, &ActorNotificationBus::Events::OnStateTransitionStart, sourceName, targetName);
  198. }
  199. }
  200. void OnEndTransition(EMotionFX::AnimGraphInstance* animGraphInstance, EMotionFX::AnimGraphStateTransition* transition) override
  201. {
  202. const ActorInstance* actorInstance = animGraphInstance->GetActorInstance();
  203. if (actorInstance)
  204. {
  205. const AZ::EntityId owningEntityId = actorInstance->GetEntityId();
  206. const char* sourceName = transition->GetSourceNode() ? transition->GetSourceNode()->GetName() : "";
  207. const char* targetName = transition->GetTargetNode() ? transition->GetTargetNode()->GetName() : "";
  208. ActorNotificationBus::QueueEvent(owningEntityId, &ActorNotificationBus::Events::OnStateTransitionEnd, sourceName, targetName);
  209. }
  210. }
  211. };
  212. //////////////////////////////////////////////////////////////////////////
  213. class ActorNotificationBusHandler
  214. : public ActorNotificationBus::Handler
  215. , public AZ::BehaviorEBusHandler
  216. {
  217. public:
  218. AZ_EBUS_BEHAVIOR_BINDER(ActorNotificationBusHandler, "{D2CD62E7-5FCF-4DC2-85DF-C205D5AB1E8B}", AZ::SystemAllocator,
  219. OnMotionEvent,
  220. OnMotionLoop,
  221. OnStateEntering,
  222. OnStateEntered,
  223. OnStateExiting,
  224. OnStateExited,
  225. OnStateTransitionStart,
  226. OnStateTransitionEnd);
  227. void OnMotionEvent(MotionEvent motionEvent) override
  228. {
  229. Call(FN_OnMotionEvent, motionEvent);
  230. }
  231. void OnMotionLoop(const char* motionName) override
  232. {
  233. Call(FN_OnMotionLoop, motionName);
  234. }
  235. void OnStateEntering(const char* stateName) override
  236. {
  237. Call(FN_OnStateEntering, stateName);
  238. }
  239. void OnStateEntered(const char* stateName) override
  240. {
  241. Call(FN_OnStateEntered, stateName);
  242. }
  243. void OnStateExiting(const char* stateName) override
  244. {
  245. Call(FN_OnStateExiting, stateName);
  246. }
  247. void OnStateExited(const char* stateName) override
  248. {
  249. Call(FN_OnStateExited, stateName);
  250. }
  251. void OnStateTransitionStart(const char* fromState, const char* toState) override
  252. {
  253. Call(FN_OnStateTransitionStart, fromState, toState);
  254. }
  255. void OnStateTransitionEnd(const char* fromState, const char* toState) override
  256. {
  257. Call(FN_OnStateTransitionEnd, fromState, toState);
  258. }
  259. };
  260. SystemComponent::~SystemComponent() = default;
  261. void SystemComponent::ReflectEMotionFX(AZ::ReflectContext* context)
  262. {
  263. MCore::ReflectionSerializer::Reflect(context);
  264. MCore::StringIdPoolIndex::Reflect(context);
  265. EMotionFX::ConstraintTransformRotationAngles::Reflect(context);
  266. EMotionFX::ObjectId::Reflect(context);
  267. // Actor
  268. EMotionFX::PhysicsSetup::Reflect(context);
  269. EMotionFX::SimulatedObjectSetup::Reflect(context);
  270. EMotionFX::PoseData::Reflect(context);
  271. EMotionFX::PoseDataRagdoll::Reflect(context);
  272. // Motion set
  273. EMotionFX::MotionSet::Reflect(context);
  274. EMotionFX::MotionSet::MotionEntry::Reflect(context);
  275. // Base AnimGraph objects
  276. EMotionFX::AnimGraphObject::Reflect(context);
  277. EMotionFX::AnimGraph::Reflect(context);
  278. EMotionFX::AnimGraphNodeGroup::Reflect(context);
  279. // Anim graph objects
  280. EMotionFX::AnimGraphObjectFactory::ReflectTypes(context);
  281. // Anim graph's parameters
  282. EMotionFX::ParameterFactory::ReflectParameterTypes(context);
  283. EMotionFX::MotionEventTable::Reflect(context);
  284. EMotionFX::MotionEventTrack::Reflect(context);
  285. EMotionFX::AnimGraphSyncTrack::Reflect(context);
  286. EMotionFX::Event::Reflect(context);
  287. EMotionFX::MotionEvent::Reflect(context);
  288. EMotionFX::EventData::Reflect(context);
  289. EMotionFX::EventDataSyncable::Reflect(context);
  290. EMotionFX::TwoStringEventData::Reflect(context);
  291. EMotionFX::EventDataFootIK::Reflect(context);
  292. EMotionFX::EventDataFloatArray::Reflect(context);
  293. EMotionFX::Recorder::Reflect(context);
  294. EMotionFX::KeyTrackLinearDynamic<AZ::Vector3>::Reflect(context);
  295. EMotionFX::KeyTrackLinearDynamic<AZ::Quaternion>::Reflect(context);
  296. EMotionFX::KeyFrame<AZ::Vector3>::Reflect(context);
  297. EMotionFX::KeyFrame<AZ::Quaternion>::Reflect(context);
  298. MCore::Command::Reflect(context);
  299. CommandSystem::MotionIdCommandMixin::Reflect(context);
  300. CommandSystem::CommandAdjustMotion::Reflect(context);
  301. CommandSystem::CommandClearMotionEvents::Reflect(context);
  302. CommandSystem::CommandCreateMotionEventTrack::Reflect(context);
  303. CommandSystem::CommandAdjustMotionEventTrack::Reflect(context);
  304. CommandSystem::CommandCreateMotionEvent::Reflect(context);
  305. CommandSystem::CommandAdjustMotionEvent::Reflect(context);
  306. EMotionFX::CommandAdjustSimulatedObject::Reflect(context);
  307. EMotionFX::CommandAdjustSimulatedJoint::Reflect(context);
  308. EMotionFX::CommandAddRagdollJoint::Reflect(context);
  309. EMotionFX::CommandAdjustRagdollJoint::Reflect(context);
  310. EMotionFX::CommandRemoveRagdollJoint::Reflect(context);
  311. }
  312. //////////////////////////////////////////////////////////////////////////
  313. void SystemComponent::Reflect(AZ::ReflectContext* context)
  314. {
  315. ReflectEMotionFX(context);
  316. // Reflect component for serialization.
  317. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  318. if (serializeContext)
  319. {
  320. serializeContext->Class<SystemComponent, AZ::Component>()
  321. ->Version(1)
  322. ->Field("NumThreads", &SystemComponent::m_numThreads)
  323. ;
  324. serializeContext->Class<MotionEvent>()
  325. ->Version(1)
  326. ;
  327. if (AZ::EditContext* ec = serializeContext->GetEditContext())
  328. {
  329. ec->Class<SystemComponent>("EMotion FX Animation", "Enables the EMotion FX animation solution")
  330. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  331. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  332. ->DataElement(AZ::Edit::UIHandlers::Default, &SystemComponent::m_numThreads, "Number of threads", "Number of threads used internally by EMotion FX")
  333. ;
  334. }
  335. }
  336. // Reflect system-level types and EBuses to behavior context.
  337. AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
  338. if (behaviorContext)
  339. {
  340. behaviorContext->EBus<SystemRequestBus>("SystemRequestBus")
  341. ;
  342. behaviorContext->EBus<SystemNotificationBus>("SystemNotificationBus")
  343. ;
  344. // In order for a property to be displayed in ScriptCanvas.
  345. behaviorContext->Class<MotionEvent>("MotionEvent")
  346. ->Property("entityId", BehaviorValueGetter(&MotionEvent::m_entityId), nullptr)
  347. ->Property("parameter", BehaviorValueGetter(&MotionEvent::m_parameter), nullptr)
  348. ->Property("eventType", BehaviorValueGetter(&MotionEvent::m_eventType), nullptr)
  349. ->Property("eventTypeName", BehaviorValueGetter(&MotionEvent::m_eventTypeName), nullptr)
  350. ->Property("time", BehaviorValueGetter(&MotionEvent::m_time), nullptr)
  351. ->Property("globalWeight", BehaviorValueGetter(&MotionEvent::m_globalWeight), nullptr)
  352. ->Property("localWeight", BehaviorValueGetter(&MotionEvent::m_localWeight), nullptr)
  353. ->Property("isEventStart", BehaviorValueGetter(&MotionEvent::m_isEventStart), nullptr)
  354. ;
  355. behaviorContext->EBus<ActorNotificationBus>("ActorNotificationBus")
  356. ->Handler<ActorNotificationBusHandler>()
  357. ->Event("OnMotionEvent", &ActorNotificationBus::Events::OnMotionEvent)
  358. ->Event("OnMotionLoop", &ActorNotificationBus::Events::OnMotionLoop)
  359. ->Event("OnStateEntering", &ActorNotificationBus::Events::OnStateEntering)
  360. ->Event("OnStateEntered", &ActorNotificationBus::Events::OnStateEntered)
  361. ->Event("OnStateExiting", &ActorNotificationBus::Events::OnStateExiting)
  362. ->Event("OnStateExited", &ActorNotificationBus::Events::OnStateExited)
  363. ->Event("OnStateTransitionStart", &ActorNotificationBus::Events::OnStateTransitionStart)
  364. ->Event("OnStateTransitionEnd", &ActorNotificationBus::Events::OnStateTransitionEnd)
  365. ;
  366. }
  367. }
  368. //////////////////////////////////////////////////////////////////////////
  369. void SystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
  370. {
  371. provided.push_back(AZ_CRC("EMotionFXAnimationService", 0x3f8a6369));
  372. }
  373. //////////////////////////////////////////////////////////////////////////
  374. void SystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  375. {
  376. incompatible.push_back(AZ_CRC("EMotionFXAnimationService", 0x3f8a6369));
  377. }
  378. //////////////////////////////////////////////////////////////////////////
  379. void SystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  380. {
  381. required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601));
  382. }
  383. //////////////////////////////////////////////////////////////////////////
  384. void SystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
  385. {
  386. dependent.push_back(AZ_CRC("AssetCatalogService", 0xc68ffc57));
  387. dependent.push_back(AZ_CRC("JobsService", 0xd5ab5a50));
  388. }
  389. //////////////////////////////////////////////////////////////////////////
  390. SystemComponent::SystemComponent()
  391. : m_numThreads(1)
  392. {
  393. }
  394. //////////////////////////////////////////////////////////////////////////
  395. void SystemComponent::Init()
  396. {
  397. }
  398. //////////////////////////////////////////////////////////////////////////
  399. void SystemComponent::Activate()
  400. {
  401. // Initialize MCore, which is EMotionFX's standard library of containers and systems.
  402. MCore::Initializer::InitSettings coreSettings;
  403. coreSettings.m_memAllocFunction = &EMotionFXAlloc;
  404. coreSettings.m_memReallocFunction = &EMotionFXRealloc;
  405. coreSettings.m_memFreeFunction = &EMotionFXFree;
  406. if (!MCore::Initializer::Init(&coreSettings))
  407. {
  408. AZ_Error("EMotion FX Animation", false, "Failed to initialize EMotion FX SDK Core");
  409. return;
  410. }
  411. // Initialize EMotionFX runtime.
  412. EMotionFX::Initializer::InitSettings emfxSettings;
  413. emfxSettings.m_unitType = MCore::Distance::UNITTYPE_METERS;
  414. if (!EMotionFX::Initializer::Init(&emfxSettings))
  415. {
  416. AZ_Error("EMotion FX Animation", false, "Failed to initialize EMotion FX SDK Runtime");
  417. return;
  418. }
  419. SetMediaRoot("@products@");
  420. // \todo Right now we're pointing at the @projectroot@ location (source) and working from there, because .actor and .motion (motion) aren't yet processed through
  421. // the scene pipeline. Once they are, we'll need to update various segments of the Tool to always read from the @products@ cache, but write to the @projectroot@ data/metadata.
  422. EMotionFX::GetEMotionFX().InitAssetFolderPaths();
  423. // Register EMotionFX event handler
  424. m_eventHandler.reset(aznew EMotionFXEventHandler());
  425. EMotionFX::GetEventManager().AddEventHandler(m_eventHandler.get());
  426. // Setup asset types.
  427. RegisterAssetTypesAndHandlers();
  428. SystemRequestBus::Handler::BusConnect();
  429. AZ::TickBus::Handler::BusConnect();
  430. CrySystemEventBus::Handler::BusConnect();
  431. EMotionFXRequestBus::Handler::BusConnect();
  432. EnableRayRequests();
  433. m_renderBackendManager = AZStd::make_unique<RenderBackendManager>();
  434. #if defined (EMOTIONFXANIMATION_EDITOR)
  435. AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
  436. AzToolsFramework::EditorAnimationSystemRequestsBus::Handler::BusConnect();
  437. AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect();
  438. AzToolsFramework::ActionManagerRegistrationNotificationBus::Handler::BusConnect();
  439. // Register custom property handlers for the reflected property editor.
  440. m_propertyHandlers = RegisterPropertyTypes();
  441. #endif // EMOTIONFXANIMATION_EDITOR
  442. }
  443. //////////////////////////////////////////////////////////////////////////
  444. void SystemComponent::Deactivate()
  445. {
  446. #if defined(EMOTIONFXANIMATION_EDITOR)
  447. // Unregister custom property handlers for the reflected property editor.
  448. UnregisterPropertyTypes(m_propertyHandlers);
  449. m_propertyHandlers.clear();
  450. if (EMStudio::GetManager())
  451. {
  452. m_emstudioManager.reset();
  453. MysticQt::Initializer::Shutdown();
  454. }
  455. {
  456. using namespace AzToolsFramework;
  457. EditorRequests::Bus::Broadcast(&EditorRequests::UnregisterViewPane, EMStudio::MainWindow::GetEMotionFXPaneName());
  458. }
  459. AzToolsFramework::ActionManagerRegistrationNotificationBus::Handler::BusDisconnect();
  460. AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
  461. AzToolsFramework::EditorAnimationSystemRequestsBus::Handler::BusDisconnect();
  462. AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
  463. #endif // EMOTIONFXANIMATION_EDITOR
  464. m_renderBackendManager.reset();
  465. EMotionFX::GetEventManager().RemoveEventHandler(m_eventHandler.get());
  466. m_eventHandler.reset();
  467. AZ::TickBus::Handler::BusDisconnect();
  468. CrySystemEventBus::Handler::BusDisconnect();
  469. EMotionFXRequestBus::Handler::BusDisconnect();
  470. DisableRayRequests();
  471. if (SystemRequestBus::Handler::BusIsConnected())
  472. {
  473. SystemRequestBus::Handler::BusDisconnect();
  474. m_assetHandlers.resize(0);
  475. EMotionFX::Initializer::Shutdown();
  476. MCore::Initializer::Shutdown();
  477. }
  478. }
  479. //////////////////////////////////////////////////////////////////////////
  480. void SystemComponent::EnableRayRequests()
  481. {
  482. AZ::Interface<IRaycastRequests>::Unregister(this);
  483. AZ::Interface<IRaycastRequests>::Register(this);
  484. }
  485. void SystemComponent::DisableRayRequests()
  486. {
  487. AZ::Interface<IRaycastRequests>::Unregister(this);
  488. }
  489. //////////////////////////////////////////////////////////////////////////
  490. void SystemComponent::OnCrySystemInitialized([[maybe_unused]] ISystem& system, const SSystemInitParams&)
  491. {
  492. #if !defined(AZ_MONOLITHIC_BUILD)
  493. // When module is linked dynamically, we must set our gEnv pointer.
  494. // When module is linked statically, we'll share the application's gEnv pointer.
  495. gEnv = system.GetGlobalEnvironment();
  496. #endif
  497. REGISTER_CVAR2("emfx_updateEnabled", &CVars::emfx_updateEnabled, 1, VF_DEV_ONLY, "Enable main EMFX update");
  498. REGISTER_CVAR2(
  499. "emfx_ragdollManipulatorsEnabled", &CVars::emfx_ragdollManipulatorsEnabled, 1, VF_DEV_ONLY,
  500. "Feature flag for in development ragdoll manipulators");
  501. }
  502. //////////////////////////////////////////////////////////////////////////
  503. void SystemComponent::OnCrySystemShutdown(ISystem&)
  504. {
  505. gEnv->pConsole->UnregisterVariable("emfx_updateEnabled");
  506. gEnv->pConsole->UnregisterVariable("emfx_ragdollManipulatorsEnabled");
  507. #if !defined(AZ_MONOLITHIC_BUILD)
  508. gEnv = nullptr;
  509. #endif
  510. }
  511. //////////////////////////////////////////////////////////////////////////
  512. void SystemComponent::OnTick(float delta, [[maybe_unused]]AZ::ScriptTimePoint timePoint)
  513. {
  514. // Flush events prior to updating EMotion FX.
  515. ActorNotificationBus::ExecuteQueuedEvents();
  516. if (CVars::emfx_updateEnabled)
  517. {
  518. // Main EMotionFX runtime update.
  519. GetEMotionFX().Update(delta);
  520. bool inGameMode = true;
  521. #if defined (EMOTIONFXANIMATION_EDITOR)
  522. // Check if we are in game mode.
  523. IEditor* editor = nullptr;
  524. AzToolsFramework::EditorRequestBus::BroadcastResult(editor, &AzToolsFramework::EditorRequests::GetEditor);
  525. inGameMode = !editor || editor->IsInGameMode();
  526. #endif
  527. // Apply the motion extraction deltas to the character controller / entity transform for all entities.
  528. const ActorManager* actorManager = GetEMotionFX().GetActorManager();
  529. const size_t numActorInstances = actorManager->GetNumActorInstances();
  530. for (size_t i = 0; i < numActorInstances; ++i)
  531. {
  532. ActorInstance* actorInstance = actorManager->GetActorInstance(i);
  533. // Apply motion extraction only in game mode or in case the actor instance belongs to the Animation Editor.
  534. const bool applyMotionExtraction = inGameMode || !actorInstance->GetIsOwnedByRuntime();
  535. if (applyMotionExtraction)
  536. {
  537. actorInstance->SetMotionExtractionEnabled(true);
  538. ApplyMotionExtraction(actorInstance, delta);
  539. }
  540. else
  541. {
  542. actorInstance->SetMotionExtractionEnabled(false);
  543. }
  544. }
  545. }
  546. }
  547. void SystemComponent::ApplyMotionExtraction(const ActorInstance* actorInstance, float timeDelta)
  548. {
  549. AZ_Assert(actorInstance, "Cannot apply motion extraction. Actor instance is not valid.");
  550. AZ_Assert(actorInstance->GetActor(), "Cannot apply motion extraction. Actor instance is not linked to a valid actor.");
  551. AZ::Entity* entity = actorInstance->GetEntity();
  552. const Actor* actor = actorInstance->GetActor();
  553. if (!actorInstance->GetIsEnabled() ||
  554. !entity ||
  555. !actor->GetMotionExtractionNode())
  556. {
  557. return;
  558. }
  559. const AZ::EntityId entityId = entity->GetId();
  560. // Check if we have any physics character controllers.
  561. bool hasCustomMotionExtractionController = false;
  562. bool hasPhysicsController = false;
  563. Physics::CharacterRequestBus::EventResult(hasPhysicsController, entityId, &Physics::CharacterRequests::IsPresent);
  564. if (!hasPhysicsController)
  565. {
  566. hasCustomMotionExtractionController = MotionExtractionRequestBus::FindFirstHandler(entityId) != nullptr;
  567. }
  568. // If we have a physics controller.
  569. if (hasCustomMotionExtractionController || hasPhysicsController)
  570. {
  571. const float deltaTimeInv = (timeDelta > 0.0f) ? (1.0f / timeDelta) : 0.0f;
  572. AZ::Transform currentTransform = AZ::Transform::CreateIdentity();
  573. AZ::TransformBus::EventResult(currentTransform, entityId, &AZ::TransformBus::Events::GetWorldTM);
  574. const AZ::Vector3 actorInstancePosition = actorInstance->GetWorldSpaceTransform().m_position;
  575. const AZ::Vector3 positionDelta = actorInstancePosition - currentTransform.GetTranslation();
  576. if (hasPhysicsController)
  577. {
  578. Physics::CharacterRequestBus::Event(
  579. entityId, &Physics::CharacterRequests::AddVelocityForTick, positionDelta * deltaTimeInv);
  580. }
  581. else if (hasCustomMotionExtractionController)
  582. {
  583. MotionExtractionRequestBus::Event(entityId, &MotionExtractionRequestBus::Events::ExtractMotion, positionDelta, timeDelta);
  584. AZ::TransformBus::EventResult(currentTransform, entityId, &AZ::TransformBus::Events::GetWorldTM);
  585. }
  586. // Update the entity rotation.
  587. const AZ::Quaternion actorInstanceRotation = actorInstance->GetWorldSpaceTransform().m_rotation;
  588. const AZ::Quaternion currentRotation = currentTransform.GetRotation();
  589. if (!currentRotation.IsClose(actorInstanceRotation, AZ::Constants::FloatEpsilon))
  590. {
  591. AZ::Transform newTransform = currentTransform;
  592. newTransform.SetRotation(actorInstanceRotation);
  593. AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetWorldTM, newTransform);
  594. }
  595. }
  596. else // There is no physics controller, just use EMotion FX's actor instance transform directly.
  597. {
  598. const AZ::Transform newTransform = actorInstance->GetWorldSpaceTransform().ToAZTransform();
  599. AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetWorldTM, newTransform);
  600. }
  601. }
  602. int SystemComponent::GetTickOrder()
  603. {
  604. return AZ::TICK_ANIMATION;
  605. }
  606. //////////////////////////////////////////////////////////////////////////
  607. void SystemComponent::RegisterAnimGraphObjectType(EMotionFX::AnimGraphObject* objectTemplate)
  608. {
  609. EMotionFX::AnimGraphObjectFactory::GetUITypes().emplace(azrtti_typeid(objectTemplate));
  610. }
  611. //////////////////////////////////////////////////////////////////////////
  612. void SystemComponent::RegisterAssetTypesAndHandlers()
  613. {
  614. // Initialize asset handlers.
  615. m_assetHandlers.emplace_back(aznew ActorAssetHandler);
  616. m_assetHandlers.emplace_back(aznew MotionAssetHandler);
  617. m_assetHandlers.emplace_back(aznew MotionSetAssetHandler);
  618. m_assetHandlers.emplace_back(aznew AnimGraphAssetHandler);
  619. // Add asset types and extensions to AssetCatalog.
  620. auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler();
  621. if (assetCatalog)
  622. {
  623. assetCatalog->EnableCatalogForAsset(azrtti_typeid<ActorAsset>());
  624. assetCatalog->EnableCatalogForAsset(azrtti_typeid<MotionAsset>());
  625. assetCatalog->EnableCatalogForAsset(azrtti_typeid<MotionSetAsset>());
  626. assetCatalog->EnableCatalogForAsset(azrtti_typeid<AnimGraphAsset>());
  627. assetCatalog->AddExtension("actor"); // Actor
  628. assetCatalog->AddExtension("motion"); // Motion
  629. assetCatalog->AddExtension("motionset"); // Motion set
  630. assetCatalog->AddExtension("animgraph"); // Anim graph
  631. }
  632. }
  633. //////////////////////////////////////////////////////////////////////////
  634. void SystemComponent::SetMediaRoot(const char* alias)
  635. {
  636. const char* rootPath = AZ::IO::FileIOBase::GetInstance()->GetAlias(alias);
  637. if (rootPath)
  638. {
  639. AZStd::string mediaRootPath = rootPath;
  640. AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::Bus::Events::NormalizePathKeepCase, mediaRootPath);
  641. EMotionFX::GetEMotionFX().SetMediaRootFolder(mediaRootPath.c_str());
  642. }
  643. else
  644. {
  645. AZ_Warning("EMotionFX", false, "Failed to set media root because alias \"%s\" could not be resolved.", alias);
  646. }
  647. }
  648. //////////////////////////////////////////////////////////////////////////
  649. IRaycastRequests::RaycastResult SystemComponent::Raycast(
  650. [[maybe_unused]] AZ::EntityId entityId, const IRaycastRequests::RaycastRequest& rayRequest)
  651. {
  652. IRaycastRequests::RaycastResult rayResult;
  653. // Build the ray request in the physics system.
  654. AzPhysics::RayCastRequest physicsRayRequest;
  655. physicsRayRequest.m_start = rayRequest.m_start;
  656. physicsRayRequest.m_direction = rayRequest.m_direction;
  657. physicsRayRequest.m_distance = rayRequest.m_distance;
  658. physicsRayRequest.m_queryType = rayRequest.m_queryType;
  659. // Cast the ray in the physics system.
  660. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  661. {
  662. if (AzPhysics::SceneHandle sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  663. sceneHandle != AzPhysics::InvalidSceneHandle)
  664. {
  665. AzPhysics::SceneQueryHits result = sceneInterface->QueryScene(sceneHandle, &physicsRayRequest);
  666. if (result) // We intersected.
  667. {
  668. rayResult.m_position = result.m_hits[0].m_position;
  669. rayResult.m_normal = result.m_hits[0].m_normal;
  670. rayResult.m_intersected = true;
  671. }
  672. }
  673. }
  674. return rayResult;
  675. }
  676. #if defined (EMOTIONFXANIMATION_EDITOR)
  677. //////////////////////////////////////////////////////////////////////////
  678. void SystemComponent::NotifyRegisterViews()
  679. {
  680. using namespace AzToolsFramework;
  681. // Construct data folder that is used by the tool for loading assets (images etc.).
  682. using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
  683. auto settingsRegistry = AZ::SettingsRegistry::Get();
  684. AZ::IO::FixedMaxPath editorAssetsPath;
  685. if (settingsRegistry && settingsRegistry->Get(editorAssetsPath.Native(),
  686. FixedValueString::format("%s/EMotionFX/Path",AZ::SettingsRegistryMergeUtils::ManifestGemsRootKey)))
  687. {
  688. editorAssetsPath /= "Assets/Editor";
  689. editorAssetsPath = editorAssetsPath.LexicallyNormal();
  690. }
  691. // Re-initialize EMStudio.
  692. int argc = 0;
  693. char** argv = nullptr;
  694. MysticQt::Initializer::Init("", editorAssetsPath.c_str());
  695. m_emstudioManager = AZStd::make_unique<EMStudio::EMStudioManager>(qApp, argc, argv);
  696. // Register default plugins
  697. EMStudio::PluginManager* pluginManager = EMStudio::GetManager()->GetPluginManager();
  698. AZ_Assert(pluginManager, "The plugin manager should be initialized at the time the plugins get registered.");
  699. pluginManager->RegisterDefaultPlugins();
  700. // Let external gems register their plugins
  701. SystemNotificationBus::Broadcast(&SystemNotificationBus::Events::OnRegisterPlugin);
  702. // Get the MainWindow the first time so it is constructed
  703. EMStudio::GetManager()->GetMainWindow();
  704. EMStudio::GetManager()->ExecuteApp();
  705. AZStd::function<QWidget*(QWidget*)> windowCreationFunc = []([[maybe_unused]] QWidget* parent = nullptr)
  706. {
  707. return EMStudio::GetMainWindow();
  708. };
  709. // Register EMotionFX window with the main editor.
  710. AzToolsFramework::ViewPaneOptions emotionFXWindowOptions;
  711. emotionFXWindowOptions.isPreview = false;
  712. emotionFXWindowOptions.isDeletable = true;
  713. emotionFXWindowOptions.isDockable = false;
  714. #if AZ_TRAIT_EMOTIONFX_MAIN_WINDOW_DETACHED
  715. emotionFXWindowOptions.detachedWindow = true;
  716. #endif
  717. emotionFXWindowOptions.optionalMenuText = "Animation Editor";
  718. emotionFXWindowOptions.showOnToolsToolbar = true;
  719. emotionFXWindowOptions.toolbarIcon = ":/Menu/emfx_editor.svg";
  720. EditorRequests::Bus::Broadcast(&EditorRequests::RegisterViewPane, EMStudio::MainWindow::GetEMotionFXPaneName(), LyViewPane::CategoryTools, emotionFXWindowOptions, windowCreationFunc);
  721. }
  722. //////////////////////////////////////////////////////////////////////////
  723. bool SystemComponent::IsSystemActive(EditorAnimationSystemRequests::AnimationSystem systemType)
  724. {
  725. return (systemType == AnimationSystem::EMotionFX);
  726. }
  727. // AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
  728. AzToolsFramework::AssetBrowser::SourceFileDetails SystemComponent::GetSourceFileDetails(const char* fullSourceFileName)
  729. {
  730. using namespace AzToolsFramework::AssetBrowser;
  731. if (AZStd::wildcard_match("*.motionset", fullSourceFileName))
  732. {
  733. return SourceFileDetails("Editor/Images/AssetBrowser/MotionSet_80.svg");
  734. }
  735. else if (AZStd::wildcard_match("*.animgraph", fullSourceFileName))
  736. {
  737. return SourceFileDetails("Editor/Images/AssetBrowser/AnimGraph_80.svg");
  738. }
  739. return SourceFileDetails(); // no result
  740. }
  741. void SystemComponent::AddSourceFileOpeners(const char* fullSourceFileName, [[maybe_unused]] const AZ::Uuid& sourceUUID, [[maybe_unused]] AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers)
  742. {
  743. using namespace AzToolsFramework::AssetBrowser;
  744. if (HandlesSource(fullSourceFileName))
  745. {
  746. auto animationEditorCallback =
  747. []([[maybe_unused]] const char* fullSourceFileNameInCall, const AZ::Uuid& sourceUUIDInCall)
  748. {
  749. AZ::Outcome<int, AZStd::string> openOutcome = AZ::Failure(AZStd::string());
  750. const SourceAssetBrowserEntry* fullDetails = SourceAssetBrowserEntry::GetSourceByUuid(sourceUUIDInCall);
  751. if (fullDetails)
  752. {
  753. AzToolsFramework::OpenViewPane(LyViewPane::AnimationEditor);
  754. EMStudio::GetMainWindow()->ApplicationModeChanged("AnimGraph");
  755. if (AZStd::wildcard_match("*.motionset", fullSourceFileNameInCall))
  756. {
  757. EMStudio::EMStudioPlugin* plugin =
  758. EMStudio::GetPluginManager()->FindActivePlugin(EMStudio::MotionSetsWindowPlugin::CLASS_ID);
  759. EMStudio::MotionSetsWindowPlugin* motionSetPlugin = (EMStudio::MotionSetsWindowPlugin*)plugin;
  760. if (plugin)
  761. {
  762. // We need to wait for the end of frame otherwise setting the current widget fails
  763. QTimer::singleShot(
  764. 0,
  765. [motionSetPlugin, fullSourceFileNameInCall]()
  766. {
  767. motionSetPlugin->LoadMotionSet(AZStd::string(fullSourceFileNameInCall));
  768. QDockWidget* dockWidget = motionSetPlugin->GetDockWidget();
  769. AzQtComponents::DockTabWidget* tabWidget =
  770. AzQtComponents::DockTabWidget::ParentTabWidget(dockWidget);
  771. tabWidget->setCurrentWidget(dockWidget);
  772. });
  773. }
  774. }
  775. else
  776. {
  777. EMStudio::EMStudioPlugin* plugin =
  778. EMStudio::GetPluginManager()->FindActivePlugin(EMStudio::AnimGraphPlugin::CLASS_ID);
  779. EMStudio::AnimGraphPlugin* animGraphPlugin = (EMStudio::AnimGraphPlugin*)plugin;
  780. if (plugin)
  781. {
  782. animGraphPlugin->FileOpen(AZStd::string(fullSourceFileNameInCall));
  783. }
  784. }
  785. }
  786. };
  787. openers.push_back({ "Animation Editor", "Open In Animation Editor...",
  788. QIcon(), animationEditorCallback });
  789. }
  790. }
  791. void SystemComponent::AddSourceFileCreators(
  792. [[maybe_unused]] const char* fullSourceFolderName,
  793. [[maybe_unused]] const AZ::Uuid& sourceUUID,
  794. AzToolsFramework::AssetBrowser::SourceFileCreatorList& creators)
  795. {
  796. using namespace AzToolsFramework;
  797. creators.push_back(
  798. { "AnimGraph_Creator",
  799. "AnimGraph",
  800. QIcon(),
  801. [&]( const AZStd::string& fullSourceFolderNameInCallback, [[maybe_unused]] const AZ::Uuid& sourceUUID)
  802. {
  803. AZ::IO::FixedMaxPath outFilePath = AzFramework::StringFunc::Path::MakeUniqueFilenameWithSuffix(
  804. AZ::IO::PathView(fullSourceFolderNameInCallback + "/NewAnimGraph.animgraph"));
  805. EMotionFX::AnimGraph* animGraph = aznew EMotionFX::AnimGraph();
  806. // create the root state machine object
  807. EMotionFX::AnimGraphObject* rootSMObject =
  808. EMotionFX::AnimGraphObjectFactory::Create(azrtti_typeid<EMotionFX::AnimGraphStateMachine>(), animGraph);
  809. if (rootSMObject)
  810. {
  811. // type-cast the object to a state machine and set it as root state machine
  812. EMotionFX::AnimGraphStateMachine* rootSM = reinterpret_cast<EMotionFX::AnimGraphStateMachine*>(rootSMObject);
  813. animGraph->SetRootStateMachine(rootSM);
  814. animGraph->RecursiveReinit();
  815. animGraph->RecursiveInvalidateUniqueDatas();
  816. AZ::SerializeContext* serializeContext = nullptr;
  817. AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
  818. animGraph->SaveToFile(outFilePath.Native().c_str(), serializeContext);
  819. delete animGraph;
  820. }
  821. AzToolsFramework::AssetBrowser::AssetBrowserFileCreationNotificationBus::Event(
  822. AzToolsFramework::AssetBrowser::AssetBrowserFileCreationNotifications::FileCreationNotificationBusId,
  823. &AzToolsFramework::AssetBrowser::AssetBrowserFileCreationNotifications::HandleAssetCreatedInEditor,
  824. outFilePath.Native().c_str(),
  825. AZ::Crc32(),
  826. true);
  827. } });
  828. creators.push_back(
  829. { "MotionSet_Creator",
  830. "MotionSet",
  831. QIcon(),
  832. [&]( const AZStd::string& fullSourceFolderNameInCallback, [[maybe_unused]] const AZ::Uuid& sourceUUID)
  833. {
  834. AZ::IO::FixedMaxPath outFilePath = AzFramework::StringFunc::Path::MakeUniqueFilenameWithSuffix(
  835. AZ::IO::PathView(fullSourceFolderNameInCallback + "/NewMotionSet.motionset"));
  836. AZ::IO::PathView filePath = outFilePath.c_str();
  837. AZStd::string motionSetName = filePath.Stem().Native();
  838. EMotionFX::MotionSet* motionSet = aznew EMotionFX::MotionSet(motionSetName.c_str(), /*parentSet=*/nullptr);
  839. motionSet->SetFilename(outFilePath.c_str());
  840. AZ::SerializeContext* serializeContext = nullptr;
  841. AZ::ComponentApplicationBus::BroadcastResult(
  842. serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
  843. motionSet->SaveToFile(outFilePath.Native().c_str(), serializeContext);
  844. delete motionSet;
  845. AzToolsFramework::AssetBrowser::AssetBrowserFileCreationNotificationBus::Event(
  846. AzToolsFramework::AssetBrowser::AssetBrowserFileCreationNotifications::FileCreationNotificationBusId,
  847. &AzToolsFramework::AssetBrowser::AssetBrowserFileCreationNotifications::HandleAssetCreatedInEditor,
  848. outFilePath.Native().c_str(),
  849. AZ::Crc32(),
  850. true);
  851. } });
  852. }
  853. void SystemComponent::OnActionContextRegistrationHook()
  854. {
  855. constexpr AZStd::string_view AnimationEditorActionContextIdentifier = "o3de.context.animationEditor";
  856. constexpr AZStd::string_view AnimationEditorAnimGraphActionContextIdentifier = "o3de.context.animationEditor.animGraph";
  857. if(auto actionManagerInterface = AZ::Interface<AzToolsFramework::ActionManagerInterface>::Get())
  858. {
  859. // EMFX Main Window
  860. {
  861. AzToolsFramework::ActionContextProperties contextProperties;
  862. contextProperties.m_name = "O3DE Animation Editor";
  863. actionManagerInterface->RegisterActionContext(AnimationEditorActionContextIdentifier, contextProperties);
  864. }
  865. // AnimGraph
  866. {
  867. AzToolsFramework::ActionContextProperties contextProperties;
  868. contextProperties.m_name = "O3DE Animation Editor - Anim Graph";
  869. actionManagerInterface->RegisterActionContext(AnimationEditorAnimGraphActionContextIdentifier, contextProperties);
  870. }
  871. }
  872. }
  873. bool SystemComponent::HandlesSource(AZStd::string_view fileName) const
  874. {
  875. return AZStd::wildcard_match("*.animgraph", fileName.data()) || AZStd::wildcard_match("*.motionset", fileName.data());
  876. }
  877. #endif // EMOTIONFXANIMATION_EDITOR
  878. }
  879. } // namespace EMotionFX