AnimSequence.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  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. // Description : Implementation of IAnimSequence interface.
  9. #include <Maestro/Bus/EditorSequenceComponentBus.h>
  10. #include "AnimSequence.h"
  11. #include "AnimAZEntityNode.h"
  12. #include "AnimComponentNode.h"
  13. #include "CVarNode.h"
  14. #include "ScriptVarNode.h"
  15. #include "SceneNode.h"
  16. #include "StlUtils.h"
  17. #include "EventNode.h"
  18. #include "LayerNode.h"
  19. #include "CommentNode.h"
  20. #include "AnimPostFXNode.h"
  21. #include "AnimScreenFaderNode.h"
  22. #include "ShadowsSetupNode.h"
  23. #include "SequenceTrack.h"
  24. #include "AnimNodeGroup.h"
  25. #include <Maestro/Types/AnimNodeType.h>
  26. #include <Maestro/Types/SequenceType.h>
  27. #include <Maestro/Types/AnimParamType.h>
  28. #include <AzCore/Serialization/SerializeContext.h>
  29. //////////////////////////////////////////////////////////////////////////
  30. CAnimSequence::CAnimSequence(IMovieSystem* pMovieSystem, uint32 id, SequenceType sequenceType)
  31. : m_refCount(0)
  32. {
  33. m_nextGenId = 1;
  34. m_pMovieSystem = pMovieSystem;
  35. m_flags = 0;
  36. m_pParentSequence = nullptr;
  37. m_timeRange.Set(0, 10);
  38. m_bPaused = false;
  39. m_bActive = false;
  40. m_legacySequenceObject = nullptr;
  41. m_activeDirector = nullptr;
  42. m_activeDirectorNodeId = -1;
  43. m_precached = false;
  44. m_bResetting = false;
  45. m_sequenceType = sequenceType;
  46. m_time = -FLT_MAX;
  47. SetId(id);
  48. m_pEventStrings = aznew CAnimStringTable;
  49. m_expanded = true;
  50. }
  51. //////////////////////////////////////////////////////////////////////////
  52. CAnimSequence::CAnimSequence()
  53. : CAnimSequence((gEnv) ? gEnv->pMovieSystem : nullptr, 0, SequenceType::SequenceComponent)
  54. {
  55. }
  56. CAnimSequence::~CAnimSequence()
  57. {
  58. // clear reference to me from all my nodes
  59. for (int i = static_cast<int>(m_nodes.size()); --i >= 0;)
  60. {
  61. if (m_nodes[i])
  62. {
  63. m_nodes[i]->SetSequence(nullptr);
  64. }
  65. }
  66. }
  67. //////////////////////////////////////////////////////////////////////////
  68. void CAnimSequence::add_ref()
  69. {
  70. ++m_refCount;
  71. }
  72. //////////////////////////////////////////////////////////////////////////
  73. void CAnimSequence::release()
  74. {
  75. if (--m_refCount <= 0)
  76. {
  77. delete this;
  78. }
  79. }
  80. //////////////////////////////////////////////////////////////////////////
  81. void CAnimSequence::SetName(const char* name)
  82. {
  83. if (!m_pMovieSystem)
  84. {
  85. return; // should never happen, null pointer guard
  86. }
  87. AZStd::string originalName = GetName();
  88. m_name = name;
  89. m_pMovieSystem->OnSequenceRenamed(originalName.c_str(), m_name.c_str());
  90. }
  91. //////////////////////////////////////////////////////////////////////////
  92. const char* CAnimSequence::GetName() const
  93. {
  94. return m_name.c_str();
  95. }
  96. //////////////////////////////////////////////////////////////////////////
  97. void CAnimSequence::ResetId()
  98. {
  99. if (!m_pMovieSystem)
  100. {
  101. return; // should never happen, null pointer guard
  102. }
  103. SetId(m_pMovieSystem->GrabNextSequenceId());
  104. }
  105. //////////////////////////////////////////////////////////////////////////
  106. void CAnimSequence::SetFlags(int flags)
  107. {
  108. m_flags = flags;
  109. }
  110. //////////////////////////////////////////////////////////////////////////
  111. int CAnimSequence::GetFlags() const
  112. {
  113. return m_flags;
  114. }
  115. //////////////////////////////////////////////////////////////////////////
  116. int CAnimSequence::GetCutSceneFlags(const bool localFlags) const
  117. {
  118. int currentFlags = m_flags & (eSeqFlags_NoHUD | eSeqFlags_NoPlayer | eSeqFlags_NoGameSounds | eSeqFlags_NoAbort);
  119. if (m_pParentSequence != NULL)
  120. {
  121. if (localFlags == true)
  122. {
  123. currentFlags &= ~m_pParentSequence->GetCutSceneFlags();
  124. }
  125. else
  126. {
  127. currentFlags |= m_pParentSequence->GetCutSceneFlags();
  128. }
  129. }
  130. return currentFlags;
  131. }
  132. //////////////////////////////////////////////////////////////////////////
  133. void CAnimSequence::SetParentSequence(IAnimSequence* pParentSequence)
  134. {
  135. m_pParentSequence = pParentSequence;
  136. }
  137. //////////////////////////////////////////////////////////////////////////
  138. const IAnimSequence* CAnimSequence::GetParentSequence() const
  139. {
  140. return m_pParentSequence;
  141. }
  142. //////////////////////////////////////////////////////////////////////////
  143. int CAnimSequence::GetNodeCount() const
  144. {
  145. return static_cast<int>(m_nodes.size());
  146. }
  147. //////////////////////////////////////////////////////////////////////////
  148. IAnimNode* CAnimSequence::GetNode(int index) const
  149. {
  150. assert(index >= 0 && index < (int)m_nodes.size());
  151. return m_nodes[index].get();
  152. }
  153. //////////////////////////////////////////////////////////////////////////
  154. bool CAnimSequence::AddNode(IAnimNode* animNode)
  155. {
  156. AZ_Assert(animNode, "Expected valid animNode");
  157. if (!animNode)
  158. {
  159. return false;
  160. }
  161. animNode->SetSequence(this);
  162. animNode->SetTimeRange(m_timeRange);
  163. // Check if this node already in sequence. If found, don't add it again.
  164. bool found = false;
  165. for (int i = 0; i < (int)m_nodes.size(); i++)
  166. {
  167. if (animNode == m_nodes[i].get())
  168. {
  169. found = true;
  170. break;
  171. }
  172. }
  173. if (!found)
  174. {
  175. m_nodes.push_back(AZStd::intrusive_ptr<IAnimNode>(animNode));
  176. }
  177. const int nodeId = animNode->GetId();
  178. if (nodeId >= (int)m_nextGenId)
  179. {
  180. m_nextGenId = nodeId + 1;
  181. }
  182. // Make sure m_nextTrackId is bigger than the biggest existing track id.
  183. // m_nextTrackId is not serialized (track id's are) so this code will
  184. // exercise every time a sequence is loaded.
  185. int trackCount = animNode->GetTrackCount();
  186. for (int trackIndex = 0; trackIndex < trackCount; trackIndex++)
  187. {
  188. IAnimTrack* track = animNode->GetTrackByIndex(trackIndex);
  189. AZ_Assert(track, "Expected valid track");
  190. if (track->GetId() >= m_nextTrackId)
  191. {
  192. m_nextTrackId = track->GetId() + 1;
  193. }
  194. int subTrackCount = track->GetSubTrackCount();
  195. for (int subTrackIndex = 0; subTrackIndex < subTrackCount; subTrackIndex++)
  196. {
  197. IAnimTrack* subTrack = track->GetSubTrack(subTrackIndex);
  198. AZ_Assert(subTrack, "Expected valid subtrack.");
  199. if (subTrack->GetId() >= m_nextTrackId)
  200. {
  201. m_nextTrackId = subTrack->GetId() + 1;
  202. }
  203. }
  204. }
  205. if (animNode->NeedToRender())
  206. {
  207. AddNodeNeedToRender(animNode);
  208. }
  209. bool bNewDirectorNode = m_activeDirector == NULL && animNode->GetType() == AnimNodeType::Director;
  210. if (bNewDirectorNode)
  211. {
  212. m_activeDirector = animNode;
  213. }
  214. return true;
  215. }
  216. //////////////////////////////////////////////////////////////////////////
  217. IAnimNode* CAnimSequence::CreateNodeInternal(AnimNodeType nodeType, uint32 nNodeId)
  218. {
  219. if (!m_pMovieSystem)
  220. {
  221. return nullptr; // should never happen, null pointer guard
  222. }
  223. CAnimNode* animNode = nullptr;
  224. if (nNodeId == -1)
  225. {
  226. nNodeId = m_nextGenId;
  227. }
  228. switch (nodeType)
  229. {
  230. case AnimNodeType::AzEntity:
  231. animNode = aznew CAnimAzEntityNode(nNodeId);
  232. break;
  233. case AnimNodeType::Component:
  234. animNode = aznew CAnimComponentNode(nNodeId);
  235. break;
  236. case AnimNodeType::CVar:
  237. animNode = aznew CAnimCVarNode(nNodeId);
  238. break;
  239. case AnimNodeType::ScriptVar:
  240. animNode = aznew CAnimScriptVarNode(nNodeId);
  241. break;
  242. case AnimNodeType::Director:
  243. animNode = aznew CAnimSceneNode(nNodeId);
  244. break;
  245. case AnimNodeType::Event:
  246. animNode = aznew CAnimEventNode(nNodeId);
  247. break;
  248. case AnimNodeType::Group:
  249. animNode = aznew CAnimNodeGroup(nNodeId);
  250. break;
  251. case AnimNodeType::Layer:
  252. animNode = aznew CLayerNode(nNodeId);
  253. break;
  254. case AnimNodeType::Comment:
  255. animNode = aznew CCommentNode(nNodeId);
  256. break;
  257. case AnimNodeType::RadialBlur:
  258. case AnimNodeType::ColorCorrection:
  259. case AnimNodeType::DepthOfField:
  260. animNode = CAnimPostFXNode::CreateNode(nNodeId, nodeType);
  261. break;
  262. case AnimNodeType::ShadowSetup:
  263. animNode = aznew CShadowsSetupNode(nNodeId);
  264. break;
  265. case AnimNodeType::ScreenFader:
  266. animNode = aznew CAnimScreenFaderNode(nNodeId);
  267. break;
  268. default:
  269. m_pMovieSystem->LogUserNotificationMsg("AnimNode cannot be added because it is an unsupported object type.");
  270. break;
  271. }
  272. if (animNode)
  273. {
  274. if (AddNode(animNode))
  275. {
  276. // If there isn't an active director, set it now.
  277. if (m_activeDirector == nullptr && animNode->GetType() == AnimNodeType::Director)
  278. {
  279. SetActiveDirector(animNode);
  280. }
  281. }
  282. }
  283. return animNode;
  284. }
  285. //////////////////////////////////////////////////////////////////////////
  286. IAnimNode* CAnimSequence::CreateNode(AnimNodeType nodeType)
  287. {
  288. return CreateNodeInternal(nodeType);
  289. }
  290. //////////////////////////////////////////////////////////////////////////
  291. IAnimNode* CAnimSequence::CreateNode(XmlNodeRef node)
  292. {
  293. if (!GetMovieSystem())
  294. {
  295. return nullptr; // should never happen, null pointer guard
  296. }
  297. AnimNodeType type;
  298. GetMovieSystem()->SerializeNodeType(type, node, true, IAnimSequence::kSequenceVersion, 0);
  299. XmlString name;
  300. if (!node->getAttr("Name", name))
  301. {
  302. return nullptr;
  303. }
  304. IAnimNode* pNewNode = CreateNode(type);
  305. if (!pNewNode)
  306. {
  307. return nullptr;
  308. }
  309. pNewNode->SetName(name);
  310. pNewNode->Serialize(node, true, true);
  311. CAnimNode* newAnimNode = static_cast<CAnimNode*>(pNewNode);
  312. // Make sure de-serializing this node didn't just create an id conflict. This can happen sometimes
  313. // when copy/pasting nodes from a different sequence to this one.
  314. for (const auto& curNode : m_nodes)
  315. {
  316. CAnimNode* animNode = static_cast<CAnimNode*>(curNode.get());
  317. if (animNode->GetId() == newAnimNode->GetId() && animNode != newAnimNode)
  318. {
  319. // Conflict detected, resolve it by assigning a new id to the new node.
  320. newAnimNode->SetId(m_nextGenId++);
  321. }
  322. }
  323. return pNewNode;
  324. }
  325. //////////////////////////////////////////////////////////////////////////
  326. void CAnimSequence::RemoveNode(IAnimNode* node, bool removeChildRelationships)
  327. {
  328. assert(node != 0);
  329. node->Activate(false);
  330. node->OnReset();
  331. for (int i = 0; i < (int)m_nodes.size(); )
  332. {
  333. if (node == m_nodes[i].get())
  334. {
  335. m_nodes.erase(m_nodes.begin() + i);
  336. if (node->NeedToRender())
  337. {
  338. RemoveNodeNeedToRender(node);
  339. }
  340. continue;
  341. }
  342. if (removeChildRelationships && m_nodes[i]->GetParent() == node)
  343. {
  344. m_nodes[i]->SetParent(nullptr);
  345. }
  346. i++;
  347. }
  348. // The removed one was the active director node.
  349. if (m_activeDirector == node)
  350. {
  351. // Clear the active one.
  352. m_activeDirector = nullptr;
  353. m_activeDirectorNodeId = -1;
  354. // If there is another director node, set it as active.
  355. for (AnimNodes::const_iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  356. {
  357. IAnimNode* pNode = it->get();
  358. if (pNode->GetType() == AnimNodeType::Director)
  359. {
  360. SetActiveDirector(pNode);
  361. break;
  362. }
  363. }
  364. }
  365. }
  366. //////////////////////////////////////////////////////////////////////////
  367. void CAnimSequence::RemoveAll()
  368. {
  369. stl::free_container(m_nodes);
  370. stl::free_container(m_events);
  371. stl::free_container(m_nodesNeedToRender);
  372. m_activeDirector = nullptr;
  373. m_activeDirectorNodeId = -1;
  374. }
  375. //////////////////////////////////////////////////////////////////////////
  376. void CAnimSequence::Reset(bool bSeekToStart)
  377. {
  378. if (GetFlags() & eSeqFlags_LightAnimationSet)
  379. {
  380. return;
  381. }
  382. m_precached = false;
  383. m_bResetting = true;
  384. if (!bSeekToStart)
  385. {
  386. for (const auto& it :m_nodes)
  387. {
  388. IAnimNode* animNode = it.get();
  389. animNode->OnReset();
  390. }
  391. m_bResetting = false;
  392. return;
  393. }
  394. bool bWasActive = m_bActive;
  395. if (!bWasActive)
  396. {
  397. Activate();
  398. }
  399. SAnimContext ec;
  400. ec.singleFrame = true;
  401. ec.resetting = true;
  402. ec.sequence = this;
  403. ec.time = m_timeRange.start;
  404. Animate(ec);
  405. if (!bWasActive)
  406. {
  407. Deactivate();
  408. }
  409. else
  410. {
  411. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  412. {
  413. IAnimNode* animNode = it->get();
  414. animNode->OnReset();
  415. }
  416. }
  417. m_bResetting = false;
  418. }
  419. //////////////////////////////////////////////////////////////////////////
  420. void CAnimSequence::ResetHard()
  421. {
  422. if (GetFlags() & eSeqFlags_LightAnimationSet)
  423. {
  424. return;
  425. }
  426. m_bResetting = true;
  427. bool bWasActive = m_bActive;
  428. if (!bWasActive)
  429. {
  430. Activate();
  431. }
  432. SAnimContext ec;
  433. ec.singleFrame = true;
  434. ec.resetting = true;
  435. ec.sequence = this;
  436. ec.time = m_timeRange.start;
  437. Animate(ec);
  438. if (!bWasActive)
  439. {
  440. Deactivate();
  441. }
  442. else
  443. {
  444. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  445. {
  446. IAnimNode* animNode = it->get();
  447. static_cast<CAnimNode*>(animNode)->OnResetHard();
  448. }
  449. }
  450. m_bResetting = false;
  451. }
  452. //////////////////////////////////////////////////////////////////////////
  453. void CAnimSequence::Pause()
  454. {
  455. if (GetFlags() & eSeqFlags_LightAnimationSet || m_bPaused)
  456. {
  457. return;
  458. }
  459. m_bPaused = true;
  460. // Detach animation block from all nodes in this sequence.
  461. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  462. {
  463. IAnimNode* animNode = it->get();
  464. static_cast<CAnimNode*>(animNode)->OnPause();
  465. }
  466. // Notify EBus listeners
  467. Maestro::SequenceComponentNotificationBus::Event(GetSequenceEntityId(), &Maestro::SequenceComponentNotificationBus::Events::OnPause);
  468. }
  469. //////////////////////////////////////////////////////////////////////////
  470. void CAnimSequence::Resume()
  471. {
  472. if (GetFlags() & eSeqFlags_LightAnimationSet)
  473. {
  474. return;
  475. }
  476. if (m_bPaused)
  477. {
  478. m_bPaused = false;
  479. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  480. {
  481. IAnimNode* animNode = it->get();
  482. static_cast<CAnimNode*>(animNode)->OnResume();
  483. }
  484. // Notify EBus listeners
  485. Maestro::SequenceComponentNotificationBus::Event(GetSequenceEntityId(), &Maestro::SequenceComponentNotificationBus::Events::OnResume);
  486. }
  487. }
  488. //////////////////////////////////////////////////////////////////////////
  489. void CAnimSequence::OnLoop()
  490. {
  491. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  492. {
  493. IAnimNode* animNode = it->get();
  494. static_cast<CAnimNode*>(animNode)->OnLoop();
  495. }
  496. }
  497. //////////////////////////////////////////////////////////////////////////
  498. bool CAnimSequence::IsPaused() const
  499. {
  500. return m_bPaused;
  501. }
  502. //////////////////////////////////////////////////////////////////////////
  503. void CAnimSequence::OnStart()
  504. {
  505. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  506. {
  507. IAnimNode* animNode = it->get();
  508. static_cast<CAnimNode*>(animNode)->OnStart();
  509. }
  510. // notify listeners
  511. Maestro::SequenceComponentNotificationBus::Event(GetSequenceEntityId(), &Maestro::SequenceComponentNotificationBus::Events::OnStart, m_time);
  512. }
  513. //////////////////////////////////////////////////////////////////////////
  514. void CAnimSequence::OnStop()
  515. {
  516. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  517. {
  518. IAnimNode* animNode = it->get();
  519. static_cast<CAnimNode*>(animNode)->OnStop();
  520. }
  521. // notify listeners
  522. Maestro::SequenceComponentNotificationBus::Event(GetSequenceEntityId(), &Maestro::SequenceComponentNotificationBus::Events::OnStop, m_time);
  523. }
  524. void CAnimSequence::TimeChanged(float newTime)
  525. {
  526. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  527. {
  528. IAnimNode* animNode = it->get();
  529. animNode->TimeChanged(newTime);
  530. }
  531. }
  532. //////////////////////////////////////////////////////////////////////////
  533. void CAnimSequence::StillUpdate()
  534. {
  535. if (GetFlags() & eSeqFlags_LightAnimationSet)
  536. {
  537. return;
  538. }
  539. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  540. {
  541. IAnimNode* animNode = it->get();
  542. animNode->StillUpdate();
  543. }
  544. }
  545. //////////////////////////////////////////////////////////////////////////
  546. void CAnimSequence::Animate(const SAnimContext& ec)
  547. {
  548. assert(m_bActive);
  549. if (GetFlags() & eSeqFlags_LightAnimationSet)
  550. {
  551. return;
  552. }
  553. SAnimContext animContext = ec;
  554. animContext.sequence = this;
  555. m_time = animContext.time;
  556. // Evaluate all animation nodes in sequence.
  557. // The director first.
  558. if (m_activeDirector)
  559. {
  560. m_activeDirector->Animate(animContext);
  561. }
  562. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  563. {
  564. // Make sure correct animation block is binded to node.
  565. IAnimNode* animNode = it->get();
  566. // All other (inactive) director nodes are skipped.
  567. if (animNode->GetType() == AnimNodeType::Director)
  568. {
  569. continue;
  570. }
  571. // If this is a descendant of a director node and that director is currently not active, skip this one.
  572. IAnimNode* parentDirector = animNode->HasDirectorAsParent();
  573. if (parentDirector && parentDirector != m_activeDirector)
  574. {
  575. continue;
  576. }
  577. if (animNode->AreFlagsSetOnNodeOrAnyParent(eAnimNodeFlags_Disabled))
  578. {
  579. continue;
  580. }
  581. // Animate node.
  582. animNode->Animate(animContext);
  583. }
  584. }
  585. //////////////////////////////////////////////////////////////////////////
  586. void CAnimSequence::Render()
  587. {
  588. for (AnimNodes::iterator it = m_nodesNeedToRender.begin(); it != m_nodesNeedToRender.end(); ++it)
  589. {
  590. IAnimNode* animNode = it->get();
  591. animNode->Render();
  592. }
  593. }
  594. //////////////////////////////////////////////////////////////////////////
  595. void CAnimSequence::Activate()
  596. {
  597. if (m_bActive)
  598. {
  599. return;
  600. }
  601. m_bActive = true;
  602. // Assign animation block to all nodes in this sequence.
  603. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  604. {
  605. IAnimNode* animNode = it->get();
  606. static_cast<CAnimNode*>(animNode)->OnReset();
  607. static_cast<CAnimNode*>(animNode)->Activate(true);
  608. }
  609. }
  610. //////////////////////////////////////////////////////////////////////////
  611. void CAnimSequence::Deactivate()
  612. {
  613. if (!m_bActive)
  614. {
  615. return;
  616. }
  617. // Detach animation block from all nodes in this sequence.
  618. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  619. {
  620. IAnimNode* animNode = it->get();
  621. static_cast<CAnimNode*>(animNode)->Activate(false);
  622. static_cast<CAnimNode*>(animNode)->OnReset();
  623. }
  624. // Audio: Release precached sound
  625. m_bActive = false;
  626. m_precached = false;
  627. }
  628. //////////////////////////////////////////////////////////////////////////
  629. void CAnimSequence::PrecacheData(float startTime)
  630. {
  631. PrecacheStatic(startTime);
  632. }
  633. //////////////////////////////////////////////////////////////////////////
  634. void CAnimSequence::PrecacheStatic(const float startTime)
  635. {
  636. // pre-cache animation keys
  637. for (AnimNodes::const_iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  638. {
  639. IAnimNode* animNode = it->get();
  640. static_cast<CAnimNode*>(animNode)->PrecacheStatic(startTime);
  641. }
  642. PrecacheDynamic(startTime);
  643. if (m_precached)
  644. {
  645. return;
  646. }
  647. gEnv->pLog->Log("=== Precaching render data for cutscene: %s ===", GetName());
  648. m_precached = true;
  649. }
  650. //////////////////////////////////////////////////////////////////////////
  651. void CAnimSequence::PrecacheDynamic(float time)
  652. {
  653. // pre-cache animation keys
  654. for (AnimNodes::const_iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  655. {
  656. IAnimNode* animNode = it->get();
  657. static_cast<CAnimNode*>(animNode)->PrecacheDynamic(time);
  658. }
  659. }
  660. void CAnimSequence::SetId(uint32 newId)
  661. {
  662. // Notify movie system of new Id
  663. if (GetMovieSystem())
  664. {
  665. GetMovieSystem()->OnSetSequenceId(newId);
  666. }
  667. m_id = newId;
  668. }
  669. //////////////////////////////////////////////////////////////////////////
  670. static bool AnimSequenceVersionConverter(
  671. AZ::SerializeContext& serializeContext,
  672. AZ::SerializeContext::DataElementNode& rootElement)
  673. {
  674. if (rootElement.GetVersion() < 5)
  675. {
  676. rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimSequence>());
  677. }
  678. return true;
  679. }
  680. void CAnimSequence::Reflect(AZ::ReflectContext* context)
  681. {
  682. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  683. {
  684. serializeContext->Class<CAnimSequence, IAnimSequence>()
  685. ->Version(IAnimSequence::kSequenceVersion, &AnimSequenceVersionConverter)
  686. ->Field("Name", &CAnimSequence::m_name)
  687. ->Field("SequenceEntityId", &CAnimSequence::m_sequenceEntityId)
  688. ->Field("Flags", &CAnimSequence::m_flags)
  689. ->Field("TimeRange", &CAnimSequence::m_timeRange)
  690. ->Field("ID", &CAnimSequence::m_id)
  691. ->Field("Nodes", &CAnimSequence::m_nodes)
  692. ->Field("SequenceType", &CAnimSequence::m_sequenceType)
  693. ->Field("Events", &CAnimSequence::m_events)
  694. ->Field("Expanded", &CAnimSequence::m_expanded)
  695. ->Field("ActiveDirectorNodeId", &CAnimSequence::m_activeDirectorNodeId);
  696. }
  697. }
  698. //////////////////////////////////////////////////////////////////////////
  699. void CAnimSequence::InitPostLoad()
  700. {
  701. if (m_pMovieSystem)
  702. {
  703. // Notify the MovieSystem of the new sequence Id (updates the next available Id if needed)
  704. m_pMovieSystem->OnSetSequenceId(GetId());
  705. // check of sequence ID collision and resolve if needed
  706. if (m_pMovieSystem->FindSequenceById(GetId()))
  707. {
  708. // A collision found - resolve by resetting Id. TODO: resolve all references to previous Id
  709. ResetId();
  710. }
  711. }
  712. IAnimNode* firstDirectorFound = nullptr;
  713. int nodeCount = GetNodeCount();
  714. for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
  715. {
  716. IAnimNode* animNode = GetNode(nodeIndex);
  717. if (animNode)
  718. {
  719. AddNode(animNode);
  720. animNode->InitPostLoad(this);
  721. // store the first director found
  722. if (!firstDirectorFound && animNode->GetType() == AnimNodeType::Director)
  723. {
  724. firstDirectorFound = animNode;
  725. }
  726. // m_activeDirectorNodeId is serialized in the sequences, so set
  727. // this node as the active director if id's match.
  728. if (animNode->GetId() == m_activeDirectorNodeId)
  729. {
  730. SetActiveDirector(animNode);
  731. }
  732. }
  733. }
  734. // All nodes and track have been added and m_nextTrackId is set higher than any
  735. // existing track id. Go over the Tracks and make sure all of track id's are assigned.
  736. // Track Id's are serialized and should never be zero, unless this is track data from
  737. // before Track Ids were added.
  738. for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
  739. {
  740. IAnimNode* animNode = GetNode(nodeIndex);
  741. if (animNode)
  742. {
  743. int trackCount = animNode->GetTrackCount();
  744. for (int trackIndex = 0; trackIndex < trackCount; trackIndex++)
  745. {
  746. IAnimTrack* track = animNode->GetTrackByIndex(trackIndex);
  747. AZ_Assert(track, "Expected valid track.");
  748. if (track->GetId() == 0)
  749. {
  750. track->SetId(GetUniqueTrackIdAndGenerateNext());
  751. }
  752. int subTrackCount = track->GetSubTrackCount();
  753. for (int subTrackIndex = 0; subTrackIndex < subTrackCount; subTrackIndex++)
  754. {
  755. IAnimTrack* subTrack = track->GetSubTrack(subTrackIndex);
  756. AZ_Assert(subTrack, "Expected valid sub track.");
  757. if (subTrack->GetId() == 0)
  758. {
  759. subTrack->SetId(GetUniqueTrackIdAndGenerateNext());
  760. }
  761. }
  762. }
  763. }
  764. }
  765. // If the active director was not set, but there was a director found,
  766. // set it as the active director now. This can happen if the sequence
  767. // was serialized before the ActiveDirectorNodeId was added.
  768. if (!m_activeDirector && firstDirectorFound)
  769. {
  770. SetActiveDirector(firstDirectorFound);
  771. }
  772. }
  773. //////////////////////////////////////////////////////////////////////////
  774. void CAnimSequence::SetTimeRange(Range timeRange)
  775. {
  776. m_timeRange = timeRange;
  777. // Set this time range for every track in animation.
  778. // Set time range to be in range of largest animation track.
  779. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  780. {
  781. IAnimNode* anode = it->get();
  782. anode->SetTimeRange(timeRange);
  783. }
  784. }
  785. //////////////////////////////////////////////////////////////////////////
  786. void CAnimSequence::AdjustKeysToTimeRange(const Range& timeRange)
  787. {
  788. float offset = timeRange.start - m_timeRange.start;
  789. // Calculate scale ratio.
  790. float scale = timeRange.Length() / m_timeRange.Length();
  791. m_timeRange = timeRange;
  792. // Set time range to be in range of largest animation track.
  793. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  794. {
  795. IAnimNode* animNode = it->get();
  796. int trackCount = animNode->GetTrackCount();
  797. for (int paramIndex = 0; paramIndex < trackCount; paramIndex++)
  798. {
  799. IAnimTrack* pTrack = animNode->GetTrackByIndex(paramIndex);
  800. int nkey = pTrack->GetNumKeys();
  801. for (int k = 0; k < nkey; k++)
  802. {
  803. float keytime = pTrack->GetKeyTime(k);
  804. keytime = offset + keytime * scale;
  805. pTrack->SetKeyTime(k, keytime);
  806. }
  807. }
  808. }
  809. }
  810. //////////////////////////////////////////////////////////////////////////
  811. void CAnimSequence::ComputeTimeRange()
  812. {
  813. Range timeRange = m_timeRange;
  814. // Set time range to be in range of largest animation track.
  815. for (AnimNodes::iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  816. {
  817. IAnimNode* animNode = it->get();
  818. int trackCount = animNode->GetTrackCount();
  819. for (int paramIndex = 0; paramIndex < trackCount; paramIndex++)
  820. {
  821. IAnimTrack* pTrack = animNode->GetTrackByIndex(paramIndex);
  822. int nkey = pTrack->GetNumKeys();
  823. if (nkey > 0)
  824. {
  825. timeRange.start = std::min(timeRange.start, pTrack->GetKeyTime(0));
  826. timeRange.end = std::max(timeRange.end, pTrack->GetKeyTime(nkey - 1));
  827. }
  828. }
  829. }
  830. if (timeRange.start > 0)
  831. {
  832. timeRange.start = 0;
  833. }
  834. m_timeRange = timeRange;
  835. }
  836. //////////////////////////////////////////////////////////////////////////
  837. bool CAnimSequence::AddTrackEvent(const char* szEvent)
  838. {
  839. CRY_ASSERT(szEvent && szEvent[0]);
  840. if (stl::push_back_unique(m_events, szEvent))
  841. {
  842. NotifyTrackEvent(ITrackEventListener::eTrackEventReason_Added, szEvent);
  843. return true;
  844. }
  845. return false;
  846. }
  847. //////////////////////////////////////////////////////////////////////////
  848. bool CAnimSequence::RemoveTrackEvent(const char* szEvent)
  849. {
  850. CRY_ASSERT(szEvent && szEvent[0]);
  851. if (stl::find_and_erase(m_events, szEvent))
  852. {
  853. NotifyTrackEvent(ITrackEventListener::eTrackEventReason_Removed, szEvent);
  854. return true;
  855. }
  856. return false;
  857. }
  858. //////////////////////////////////////////////////////////////////////////
  859. bool CAnimSequence::RenameTrackEvent(const char* szEvent, const char* szNewEvent)
  860. {
  861. CRY_ASSERT(szEvent && szEvent[0]);
  862. CRY_ASSERT(szNewEvent && szNewEvent[0]);
  863. for (size_t i = 0; i < m_events.size(); ++i)
  864. {
  865. if (m_events[i] == szEvent)
  866. {
  867. m_events[i] = szNewEvent;
  868. NotifyTrackEvent(ITrackEventListener::eTrackEventReason_Renamed, szEvent, szNewEvent);
  869. return true;
  870. }
  871. }
  872. return false;
  873. }
  874. //////////////////////////////////////////////////////////////////////////
  875. bool CAnimSequence::MoveUpTrackEvent(const char* szEvent)
  876. {
  877. CRY_ASSERT(szEvent && szEvent[0]);
  878. for (size_t i = 0; i < m_events.size(); ++i)
  879. {
  880. if (m_events[i] == szEvent)
  881. {
  882. assert(i > 0);
  883. if (i > 0)
  884. {
  885. std::swap(m_events[i - 1], m_events[i]);
  886. NotifyTrackEvent(ITrackEventListener::eTrackEventReason_MovedUp, szEvent);
  887. }
  888. return true;
  889. }
  890. }
  891. return false;
  892. }
  893. //////////////////////////////////////////////////////////////////////////
  894. bool CAnimSequence::MoveDownTrackEvent(const char* szEvent)
  895. {
  896. CRY_ASSERT(szEvent && szEvent[0]);
  897. for (size_t i = 0; i < m_events.size(); ++i)
  898. {
  899. if (m_events[i] == szEvent)
  900. {
  901. assert(i < m_events.size() - 1);
  902. if (i < m_events.size() - 1)
  903. {
  904. std::swap(m_events[i], m_events[i + 1]);
  905. NotifyTrackEvent(ITrackEventListener::eTrackEventReason_MovedDown, szEvent);
  906. }
  907. return true;
  908. }
  909. }
  910. return false;
  911. }
  912. //////////////////////////////////////////////////////////////////////////
  913. void CAnimSequence::ClearTrackEvents()
  914. {
  915. m_events.clear();
  916. }
  917. //////////////////////////////////////////////////////////////////////////
  918. int CAnimSequence::GetTrackEventsCount() const
  919. {
  920. return (int)m_events.size();
  921. }
  922. //////////////////////////////////////////////////////////////////////////
  923. char const* CAnimSequence::GetTrackEvent(int iIndex) const
  924. {
  925. char const* szResult = nullptr;
  926. const bool bValid = (iIndex >= 0 && iIndex < GetTrackEventsCount());
  927. CRY_ASSERT(bValid);
  928. if (bValid)
  929. {
  930. szResult = m_events[iIndex].c_str();
  931. }
  932. return szResult;
  933. }
  934. //////////////////////////////////////////////////////////////////////////
  935. void CAnimSequence::NotifyTrackEvent(ITrackEventListener::ETrackEventReason reason,
  936. const char* event, const char* param)
  937. {
  938. // Notify listeners
  939. for (TTrackEventListeners::iterator j = m_listeners.begin(); j != m_listeners.end(); ++j)
  940. {
  941. (*j)->OnTrackEvent(this, reason, event, (void*)param);
  942. }
  943. // Notification via Event Bus
  944. Maestro::SequenceComponentNotificationBus::Event(GetSequenceEntityId(), &Maestro::SequenceComponentNotificationBus::Events::OnTrackEventTriggered, event, param);
  945. }
  946. //////////////////////////////////////////////////////////////////////////
  947. void CAnimSequence::TriggerTrackEvent(const char* event, const char* param)
  948. {
  949. NotifyTrackEvent(ITrackEventListener::eTrackEventReason_Triggered, event, param);
  950. }
  951. //////////////////////////////////////////////////////////////////////////
  952. void CAnimSequence::AddTrackEventListener(ITrackEventListener* pListener)
  953. {
  954. if (std::find(m_listeners.begin(), m_listeners.end(), pListener) == m_listeners.end())
  955. {
  956. m_listeners.push_back(pListener);
  957. }
  958. }
  959. //////////////////////////////////////////////////////////////////////////
  960. void CAnimSequence::RemoveTrackEventListener(ITrackEventListener* pListener)
  961. {
  962. TTrackEventListeners::iterator it = std::find(m_listeners.begin(), m_listeners.end(), pListener);
  963. if (it != m_listeners.end())
  964. {
  965. m_listeners.erase(it);
  966. }
  967. }
  968. //////////////////////////////////////////////////////////////////////////
  969. IAnimNode* CAnimSequence::FindNodeById(int nNodeId)
  970. {
  971. for (AnimNodes::const_iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  972. {
  973. IAnimNode* animNode = it->get();
  974. if (animNode->GetId() == nNodeId)
  975. {
  976. return animNode;
  977. }
  978. }
  979. return nullptr;
  980. }
  981. //////////////////////////////////////////////////////////////////////////
  982. IAnimNode* CAnimSequence::FindNodeByName(const char* sNodeName, const IAnimNode* pParentDirector)
  983. {
  984. for (AnimNodes::const_iterator it = m_nodes.begin(); it != m_nodes.end(); ++it)
  985. {
  986. IAnimNode* animNode = it->get();
  987. // Case insensitive name comparison.
  988. if (_stricmp(animNode->GetName(), sNodeName) == 0)
  989. {
  990. bool bParentDirectorCheck = animNode->HasDirectorAsParent() == pParentDirector;
  991. if (bParentDirectorCheck)
  992. {
  993. return animNode;
  994. }
  995. }
  996. }
  997. return nullptr;
  998. }
  999. //////////////////////////////////////////////////////////////////////////
  1000. void CAnimSequence::ReorderNode(IAnimNode* pNode, IAnimNode* pPivotNode, bool bNext)
  1001. {
  1002. if (pNode == pPivotNode || !pNode)
  1003. {
  1004. return;
  1005. }
  1006. AZStd::intrusive_ptr<IAnimNode> pTempHolder(pNode); // Keep reference to node so it is not deleted by erasing from list.
  1007. stl::find_and_erase_if(m_nodes, [pNode](const AZStd::intrusive_ptr<IAnimNode>& sp) { return sp.get() == pNode; });
  1008. AnimNodes::iterator it;
  1009. for (it = m_nodes.begin(); it != m_nodes.end(); ++it)
  1010. {
  1011. IAnimNode* animNode = it->get();
  1012. if (animNode == pPivotNode)
  1013. {
  1014. if (bNext)
  1015. {
  1016. m_nodes.insert(it + 1, AZStd::intrusive_ptr<IAnimNode>(pNode));
  1017. }
  1018. else
  1019. {
  1020. m_nodes.insert(it, AZStd::intrusive_ptr<IAnimNode>(pNode));
  1021. }
  1022. break;
  1023. }
  1024. }
  1025. if (it == m_nodes.end())
  1026. {
  1027. m_nodes.insert(m_nodes.begin(), AZStd::intrusive_ptr<IAnimNode>(pNode));
  1028. }
  1029. }
  1030. //////////////////////////////////////////////////////////////////////////
  1031. void CAnimSequence::CopyNodeChildren(XmlNodeRef& xmlNode, IAnimNode* animNode)
  1032. {
  1033. for (int k = 0; k < GetNodeCount(); ++k)
  1034. {
  1035. if (GetNode(k)->GetParent() == animNode)
  1036. {
  1037. XmlNodeRef childNode = xmlNode->newChild("Node");
  1038. GetNode(k)->Serialize(childNode, false, true);
  1039. if (GetNode(k)->GetType() == AnimNodeType::Group
  1040. || animNode->GetType() == AnimNodeType::Director)
  1041. {
  1042. CopyNodeChildren(xmlNode, GetNode(k));
  1043. }
  1044. }
  1045. }
  1046. }
  1047. //////////////////////////////////////////////////////////////////////////
  1048. void CAnimSequence::CopyNodes(XmlNodeRef& xmlNode, IAnimNode** pSelectedNodes, uint32 count)
  1049. {
  1050. for (uint32 i = 0; i < count; ++i)
  1051. {
  1052. IAnimNode* animNode = pSelectedNodes[i];
  1053. if (animNode)
  1054. {
  1055. XmlNodeRef xn = xmlNode->newChild("Node");
  1056. animNode->Serialize(xn, false, true);
  1057. // If it is a group node, copy its children also.
  1058. if (animNode->GetType() == AnimNodeType::Group || animNode->GetType() == AnimNodeType::Director)
  1059. {
  1060. CopyNodeChildren(xmlNode, animNode);
  1061. }
  1062. }
  1063. }
  1064. }
  1065. //////////////////////////////////////////////////////////////////////////
  1066. void CAnimSequence::PasteNodes(const XmlNodeRef& xmlNode, IAnimNode* pParent)
  1067. {
  1068. int type, id;
  1069. std::map<int, IAnimNode*> idToNode;
  1070. for (int i = 0; i < xmlNode->getChildCount(); i++)
  1071. {
  1072. XmlNodeRef xn = xmlNode->getChild(i);
  1073. if (!xn->getAttr("Type", type))
  1074. {
  1075. continue;
  1076. }
  1077. xn->getAttr("Id", id);
  1078. IAnimNode* node = CreateNode((AnimNodeType)type);
  1079. if (!node)
  1080. {
  1081. continue;
  1082. }
  1083. idToNode[id] = node;
  1084. xn->setAttr("Id", node->GetId());
  1085. node->Serialize(xn, true, true);
  1086. int parentId = 0;
  1087. if (xn->getAttr("ParentNode", parentId))
  1088. {
  1089. node->SetParent(idToNode[parentId]);
  1090. }
  1091. else
  1092. // This means a top-level node.
  1093. {
  1094. if (pParent)
  1095. {
  1096. node->SetParent(pParent);
  1097. }
  1098. }
  1099. }
  1100. }
  1101. //////////////////////////////////////////////////////////////////////////
  1102. bool CAnimSequence::AddNodeNeedToRender(IAnimNode* pNode)
  1103. {
  1104. assert(pNode != 0);
  1105. return stl::push_back_unique(m_nodesNeedToRender, AZStd::intrusive_ptr<IAnimNode>(pNode));
  1106. }
  1107. //////////////////////////////////////////////////////////////////////////
  1108. void CAnimSequence::RemoveNodeNeedToRender(IAnimNode* pNode)
  1109. {
  1110. assert(pNode != 0);
  1111. stl::find_and_erase_if(m_nodesNeedToRender, [pNode](const AZStd::intrusive_ptr<IAnimNode>& sp) { return sp.get() == pNode; });
  1112. }
  1113. //////////////////////////////////////////////////////////////////////////
  1114. void CAnimSequence::SetSequenceEntityId(const AZ::EntityId& sequenceEntityId)
  1115. {
  1116. m_sequenceEntityId = sequenceEntityId;
  1117. }
  1118. //////////////////////////////////////////////////////////////////////////
  1119. void CAnimSequence::SetActiveDirector(IAnimNode* pDirectorNode)
  1120. {
  1121. if (!pDirectorNode)
  1122. {
  1123. return;
  1124. }
  1125. assert(pDirectorNode->GetType() == AnimNodeType::Director);
  1126. if (pDirectorNode->GetType() != AnimNodeType::Director)
  1127. {
  1128. return; // It's not a director node.
  1129. }
  1130. if (pDirectorNode->GetSequence() != this)
  1131. {
  1132. return; // It's not a node belong to this sequence.
  1133. }
  1134. m_activeDirector = pDirectorNode;
  1135. m_activeDirectorNodeId = pDirectorNode->GetId();
  1136. }
  1137. //////////////////////////////////////////////////////////////////////////
  1138. IAnimNode* CAnimSequence::GetActiveDirector() const
  1139. {
  1140. return m_activeDirector;
  1141. }
  1142. //////////////////////////////////////////////////////////////////////////
  1143. bool CAnimSequence::IsAncestorOf(const IAnimSequence* sequence) const
  1144. {
  1145. assert(this != sequence);
  1146. if (this == sequence)
  1147. {
  1148. return true;
  1149. }
  1150. if (!GetMovieSystem())
  1151. {
  1152. return false; // should never happen, null pointer guard
  1153. }
  1154. for (const auto& it :m_nodes)
  1155. {
  1156. IAnimNode* pNode = it.get();
  1157. if (pNode->GetType() == AnimNodeType::Director)
  1158. {
  1159. IAnimTrack* pSequenceTrack = pNode->GetTrackForParameter(AnimParamType::Sequence);
  1160. if (pSequenceTrack)
  1161. {
  1162. PREFAST_ASSUME(sequence);
  1163. for (int i = 0; i < pSequenceTrack->GetNumKeys(); ++i)
  1164. {
  1165. ISequenceKey key;
  1166. pSequenceTrack->GetKey(i, &key);
  1167. if (_stricmp(key.szSelection.c_str(), sequence->GetName()) == 0)
  1168. {
  1169. return true;
  1170. }
  1171. IAnimSequence* pChild = CAnimSceneNode::GetSequenceFromSequenceKey(key);
  1172. if (pChild && pChild->IsAncestorOf(sequence))
  1173. {
  1174. return true;
  1175. }
  1176. }
  1177. }
  1178. }
  1179. }
  1180. return false;
  1181. }