3
0

AnimNode.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237
  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/Serialization/SerializeContext.h>
  9. #include "AnimNode.h"
  10. #include "AnimTrack.h"
  11. #include "AnimSequence.h"
  12. #include <Maestro/Types/AssetBlendKey.h>
  13. #include "AssetBlendTrack.h"
  14. #include "CharacterTrack.h"
  15. #include "AnimSplineTrack.h"
  16. #include "BoolTrack.h"
  17. #include "SelectTrack.h"
  18. #include "EventTrack.h"
  19. #include "SoundTrack.h"
  20. #include "ConsoleTrack.h"
  21. #include "LookAtTrack.h"
  22. #include "TrackEventTrack.h"
  23. #include "SequenceTrack.h"
  24. #include "CompoundSplineTrack.h"
  25. #include "GotoTrack.h"
  26. #include "CaptureTrack.h"
  27. #include "CommentTrack.h"
  28. #include "ScreenFaderTrack.h"
  29. #include "TimeRangesTrack.h"
  30. #include "SoundTrack.h"
  31. #include <AzCore/std/sort.h>
  32. #include <AzCore/Math/MathUtils.h>
  33. #include <AzCore/Component/TickBus.h>
  34. #include <ctime>
  35. #include "Maestro/Types/AnimValueType.h"
  36. #include "Maestro/Types/AnimNodeType.h"
  37. #include "Maestro/Types/AnimParamType.h"
  38. //////////////////////////////////////////////////////////////////////////
  39. // Old deprecated IDs
  40. //////////////////////////////////////////////////////////////////////////
  41. #define APARAM_CHARACTER4 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x10)
  42. #define APARAM_CHARACTER5 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x11)
  43. #define APARAM_CHARACTER6 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x12)
  44. #define APARAM_CHARACTER7 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x13)
  45. #define APARAM_CHARACTER8 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x14)
  46. #define APARAM_CHARACTER9 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x15)
  47. #define APARAM_CHARACTER10 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x16)
  48. //////////////////////////////////////////////////////////////////////////
  49. static const EAnimCurveType DEFAULT_TRACK_TYPE = eAnimCurveType_BezierFloat;
  50. // Old serialization values that are no longer
  51. // defined in IMovieSystem.h, but needed for conversion:
  52. static const int OLD_ACURVE_GOTO = 21;
  53. static const int OLD_APARAM_PARTICLE_COUNT_SCALE = 95;
  54. static const int OLD_APARAM_PARTICLE_PULSE_PERIOD = 96;
  55. static const int OLD_APARAM_PARTICLE_SCALE = 97;
  56. static const int OLD_APARAM_PARTICLE_SPEED_SCALE = 98;
  57. static const int OLD_APARAM_PARTICLE_STRENGTH = 99;
  58. //////////////////////////////////////////////////////////////////////////
  59. // CAnimNode.
  60. //////////////////////////////////////////////////////////////////////////
  61. //////////////////////////////////////////////////////////////////////////
  62. void CAnimNode::Activate([[maybe_unused]] bool bActivate)
  63. {
  64. }
  65. //////////////////////////////////////////////////////////////////////////
  66. int CAnimNode::GetTrackCount() const
  67. {
  68. return static_cast<int>(m_tracks.size());
  69. }
  70. AZStd::string CAnimNode::GetParamName(const CAnimParamType& paramType) const
  71. {
  72. SParamInfo info;
  73. if (GetParamInfoFromType(paramType, info))
  74. {
  75. return info.name;
  76. }
  77. return "Unknown";
  78. }
  79. AnimValueType CAnimNode::GetParamValueType(const CAnimParamType& paramType) const
  80. {
  81. SParamInfo info;
  82. if (GetParamInfoFromType(paramType, info))
  83. {
  84. return info.valueType;
  85. }
  86. return AnimValueType::Unknown;
  87. }
  88. IAnimNode::ESupportedParamFlags CAnimNode::GetParamFlags(const CAnimParamType& paramType) const
  89. {
  90. SParamInfo info;
  91. if (GetParamInfoFromType(paramType, info))
  92. {
  93. return info.flags;
  94. }
  95. return IAnimNode::ESupportedParamFlags(0);
  96. }
  97. IAnimTrack* CAnimNode::GetTrackForParameter(const CAnimParamType& paramType) const
  98. {
  99. for (int i = 0, num = (int)m_tracks.size(); i < num; i++)
  100. {
  101. if (m_tracks[i]->GetParameterType() == paramType)
  102. {
  103. return m_tracks[i].get();
  104. }
  105. // Search the sub-tracks also if any.
  106. for (int k = 0; k < m_tracks[i]->GetSubTrackCount(); ++k)
  107. {
  108. if (m_tracks[i]->GetSubTrack(k)->GetParameterType() == paramType)
  109. {
  110. return m_tracks[i]->GetSubTrack(k);
  111. }
  112. }
  113. }
  114. return 0;
  115. }
  116. IAnimTrack* CAnimNode::GetTrackForParameter(const CAnimParamType& paramType, uint32 index) const
  117. {
  118. SParamInfo paramInfo;
  119. GetParamInfoFromType(paramType, paramInfo);
  120. if ((paramInfo.flags & IAnimNode::eSupportedParamFlags_MultipleTracks) == 0)
  121. {
  122. return GetTrackForParameter(paramType);
  123. }
  124. uint32 count = 0;
  125. for (int i = 0, num = (int)m_tracks.size(); i < num; i++)
  126. {
  127. if (m_tracks[i]->GetParameterType() == paramType && count++ == index)
  128. {
  129. return m_tracks[i].get();
  130. }
  131. // For this case, no subtracks are considered.
  132. }
  133. return 0;
  134. }
  135. uint32 CAnimNode::GetTrackParamIndex(const IAnimTrack* pTrack) const
  136. {
  137. assert(pTrack);
  138. uint32 index = 0;
  139. CAnimParamType paramType = pTrack->GetParameterType();
  140. SParamInfo paramInfo;
  141. GetParamInfoFromType(paramType, paramInfo);
  142. if ((paramInfo.flags & IAnimNode::eSupportedParamFlags_MultipleTracks) == 0)
  143. {
  144. return 0;
  145. }
  146. for (int i = 0, num = (int)m_tracks.size(); i < num; i++)
  147. {
  148. if (m_tracks[i].get() == pTrack)
  149. {
  150. return index;
  151. }
  152. if (m_tracks[i]->GetParameterType() == paramType)
  153. {
  154. ++index;
  155. }
  156. // For this case, no subtracks are considered.
  157. }
  158. assert(!"CAnimNode::GetTrackParamIndex() called with an invalid argument!");
  159. return 0;
  160. }
  161. IAnimTrack* CAnimNode::GetTrackByIndex(int nIndex) const
  162. {
  163. if (nIndex >= (int)m_tracks.size())
  164. {
  165. assert("nIndex>=m_tracks.size()" && false);
  166. return NULL;
  167. }
  168. return m_tracks[nIndex].get();
  169. }
  170. void CAnimNode::SetTrack(const CAnimParamType& paramType, IAnimTrack* pTrack)
  171. {
  172. if (pTrack)
  173. {
  174. for (unsigned int i = 0; i < m_tracks.size(); i++)
  175. {
  176. if (m_tracks[i]->GetParameterType() == paramType)
  177. {
  178. m_tracks[i].reset(pTrack);
  179. return;
  180. }
  181. }
  182. AddTrack(pTrack);
  183. }
  184. else
  185. {
  186. // Remove track at this id.
  187. for (unsigned int i = 0; i < m_tracks.size(); i++)
  188. {
  189. if (m_tracks[i]->GetParameterType() == paramType)
  190. {
  191. m_tracks.erase(m_tracks.begin() + i);
  192. }
  193. }
  194. }
  195. }
  196. //////////////////////////////////////////////////////////////////////////
  197. bool CAnimNode::TrackOrder(const AZStd::intrusive_ptr<IAnimTrack>& left, const AZStd::intrusive_ptr<IAnimTrack>& right)
  198. {
  199. return left->GetParameterType() < right->GetParameterType();
  200. }
  201. //////////////////////////////////////////////////////////////////////////
  202. void CAnimNode::AddTrack(IAnimTrack* pTrack)
  203. {
  204. RegisterTrack(pTrack);
  205. m_tracks.push_back(AZStd::intrusive_ptr<IAnimTrack>(pTrack));
  206. SortTracks();
  207. }
  208. //////////////////////////////////////////////////////////////////////////
  209. void CAnimNode::RegisterTrack(IAnimTrack* pTrack)
  210. {
  211. pTrack->SetTimeRange(GetSequence()->GetTimeRange());
  212. pTrack->SetNode(this);
  213. }
  214. void CAnimNode::SortTracks()
  215. {
  216. AZStd::insertion_sort(m_tracks.begin(), m_tracks.end(), TrackOrder);
  217. }
  218. //////////////////////////////////////////////////////////////////////////
  219. bool CAnimNode::RemoveTrack(IAnimTrack* pTrack)
  220. {
  221. for (unsigned int i = 0; i < m_tracks.size(); i++)
  222. {
  223. if (m_tracks[i].get() == pTrack)
  224. {
  225. m_tracks.erase(m_tracks.begin() + i);
  226. return true;
  227. }
  228. }
  229. return false;
  230. }
  231. //////////////////////////////////////////////////////////////////////////
  232. static bool AnimNodeVersionConverter(
  233. AZ::SerializeContext& serializeContext,
  234. AZ::SerializeContext::DataElementNode& rootElement)
  235. {
  236. if (rootElement.GetVersion() < 3)
  237. {
  238. rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimNode>());
  239. }
  240. if (rootElement.GetVersion() < 4)
  241. {
  242. // remove vector scale tracks from transform anim nodes
  243. AZStd::string name;
  244. if (rootElement.FindSubElementAndGetData<AZStd::string>(AZ_CRC_CE("Name"), name) && name == "Transform")
  245. {
  246. auto tracksElement = rootElement.FindSubElement(AZ_CRC_CE("Tracks"));
  247. if (tracksElement)
  248. {
  249. for (int trackIndex = tracksElement->GetNumSubElements() - 1; trackIndex >= 0; trackIndex--)
  250. {
  251. auto trackElement = tracksElement->GetSubElement(trackIndex);
  252. bool isScale = false;
  253. // trackElement should be an intrusive_ptr with one child
  254. if (trackElement.GetNumSubElements() == 1)
  255. {
  256. auto ptrElement = trackElement.GetSubElement(0);
  257. auto paramTypeElement = ptrElement.FindSubElement(AZ_CRC_CE("ParamType"));
  258. if (paramTypeElement)
  259. {
  260. AZStd::string paramName;
  261. if (paramTypeElement->FindSubElementAndGetData<AZStd::string>(AZ_CRC_CE("Name"), paramName) && paramName == "Scale")
  262. {
  263. isScale = true;
  264. }
  265. }
  266. }
  267. if (isScale)
  268. {
  269. tracksElement->RemoveElement(trackIndex);
  270. }
  271. }
  272. }
  273. }
  274. }
  275. return true;
  276. }
  277. void CAnimNode::Reflect(AZ::ReflectContext* context)
  278. {
  279. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  280. {
  281. serializeContext->Class<CAnimNode, IAnimNode>()
  282. ->Version(4, &AnimNodeVersionConverter)
  283. ->Field("ID", &CAnimNode::m_id)
  284. ->Field("Name", &CAnimNode::m_name)
  285. ->Field("Flags", &CAnimNode::m_flags)
  286. ->Field("Tracks", &CAnimNode::m_tracks)
  287. ->Field("Parent", &CAnimNode::m_parentNodeId)
  288. ->Field("Type", &CAnimNode::m_nodeType)
  289. ->Field("Expanded", &CAnimNode::m_expanded);
  290. }
  291. }
  292. //////////////////////////////////////////////////////////////////////////
  293. IAnimTrack* CAnimNode::CreateTrackInternal(const CAnimParamType& paramType, EAnimCurveType trackType, AnimValueType valueType)
  294. {
  295. if (valueType == AnimValueType::Unknown)
  296. {
  297. SParamInfo info;
  298. // Try to get info from paramType, else we can't determine the track data type
  299. if (!GetParamInfoFromType(paramType, info))
  300. {
  301. return 0;
  302. }
  303. valueType = info.valueType;
  304. }
  305. IAnimTrack* pTrack = NULL;
  306. switch (paramType.GetType())
  307. {
  308. // Create sub-classed tracks
  309. case AnimParamType::Event:
  310. pTrack = aznew CEventTrack(m_pSequence->GetTrackEventStringTable());
  311. break;
  312. case AnimParamType::Sound:
  313. pTrack = aznew CSoundTrack;
  314. break;
  315. case AnimParamType::Animation:
  316. pTrack = aznew CCharacterTrack;
  317. break;
  318. case AnimParamType::Console:
  319. pTrack = aznew CConsoleTrack;
  320. break;
  321. case AnimParamType::LookAt:
  322. pTrack = aznew CLookAtTrack;
  323. break;
  324. case AnimParamType::TrackEvent:
  325. pTrack = aznew CTrackEventTrack(m_pSequence->GetTrackEventStringTable());
  326. break;
  327. case AnimParamType::Sequence:
  328. pTrack = aznew CSequenceTrack;
  329. break;
  330. case AnimParamType::Capture:
  331. pTrack = aznew CCaptureTrack;
  332. break;
  333. case AnimParamType::CommentText:
  334. pTrack = aznew CCommentTrack;
  335. break;
  336. case AnimParamType::ScreenFader:
  337. pTrack = aznew CScreenFaderTrack;
  338. break;
  339. case AnimParamType::Goto:
  340. pTrack = aznew CGotoTrack;
  341. break;
  342. case AnimParamType::TimeRanges:
  343. pTrack = aznew CTimeRangesTrack;
  344. break;
  345. case AnimParamType::Float:
  346. pTrack = CreateTrackInternalFloat(trackType);
  347. break;
  348. default:
  349. // Create standard tracks
  350. switch (valueType)
  351. {
  352. case AnimValueType::Float:
  353. pTrack = CreateTrackInternalFloat(trackType);
  354. break;
  355. case AnimValueType::RGB:
  356. case AnimValueType::Vector:
  357. pTrack = CreateTrackInternalVector(trackType, paramType, valueType);
  358. break;
  359. case AnimValueType::Quat:
  360. pTrack = CreateTrackInternalQuat(trackType, paramType);
  361. break;
  362. case AnimValueType::Bool:
  363. pTrack = aznew CBoolTrack;
  364. break;
  365. case AnimValueType::Select:
  366. pTrack = aznew CSelectTrack;
  367. break;
  368. case AnimValueType::Vector4:
  369. pTrack = CreateTrackInternalVector4(paramType);
  370. break;
  371. case AnimValueType::CharacterAnim:
  372. pTrack = aznew CCharacterTrack;
  373. break;
  374. case AnimValueType::AssetBlend:
  375. pTrack = aznew CAssetBlendTrack;
  376. break;
  377. }
  378. }
  379. if (pTrack)
  380. {
  381. pTrack->SetParameterType(paramType);
  382. // Assign a unique id for every track.
  383. pTrack->SetId(m_pSequence->GetUniqueTrackIdAndGenerateNext());
  384. int subTrackCount = pTrack->GetSubTrackCount();
  385. for (int subTrackIndex = 0; subTrackIndex < subTrackCount; subTrackIndex++)
  386. {
  387. IAnimTrack* subTrack = pTrack->GetSubTrack(subTrackIndex);
  388. subTrack->SetId(m_pSequence->GetUniqueTrackIdAndGenerateNext());
  389. }
  390. AddTrack(pTrack);
  391. }
  392. return pTrack;
  393. }
  394. //////////////////////////////////////////////////////////////////////////
  395. IAnimTrack* CAnimNode::CreateTrack(const CAnimParamType& paramType)
  396. {
  397. IAnimTrack* pTrack = CreateTrackInternal(paramType, DEFAULT_TRACK_TYPE, AnimValueType::Unknown);
  398. InitializeTrackDefaultValue(pTrack, paramType);
  399. return pTrack;
  400. }
  401. //////////////////////////////////////////////////////////////////////////
  402. void CAnimNode::SerializeAnims(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks)
  403. {
  404. if (bLoading)
  405. {
  406. // Delete all tracks.
  407. stl::free_container(m_tracks);
  408. CAnimNode::SParamInfo info;
  409. // Loading.
  410. int paramTypeVersion = 0;
  411. xmlNode->getAttr("paramIdVersion", paramTypeVersion);
  412. CAnimParamType paramType;
  413. int num = xmlNode->getChildCount();
  414. for (int i = 0; i < num; i++)
  415. {
  416. XmlNodeRef trackNode = xmlNode->getChild(i);
  417. paramType.Serialize(trackNode, bLoading, paramTypeVersion);
  418. if (paramType.GetType() == AnimParamType::Music)
  419. {
  420. // skip loading AnimParamType::Music - it's deprecated
  421. continue;
  422. }
  423. if (paramTypeVersion == 0) // for old version with sound and animation param ids swapped
  424. {
  425. AnimParamType APARAM_ANIMATION_OLD = AnimParamType::Sound;
  426. AnimParamType APARAM_SOUND_OLD = AnimParamType::Animation;
  427. if (paramType.GetType() == APARAM_ANIMATION_OLD)
  428. {
  429. paramType = AnimParamType::Animation;
  430. }
  431. else if (paramType.GetType() == APARAM_SOUND_OLD)
  432. {
  433. paramType = AnimParamType::Sound;
  434. }
  435. }
  436. int curveType = eAnimCurveType_Unknown;
  437. trackNode->getAttr("Type", curveType);
  438. if (curveType == eAnimCurveType_Unknown)
  439. {
  440. if (paramTypeVersion == 0)
  441. {
  442. //////////////////////////////////////////////////////////////////////////
  443. // Backward compatibility code
  444. //////////////////////////////////////////////////////////////////////////
  445. // Legacy animation track.
  446. // Collapse parameter ID to the single type
  447. if (paramType.GetType() >= AnimParamType::Sound && paramType.GetType() <= static_cast<AnimParamType>(static_cast<int>(AnimParamType::Sound) + 2))
  448. {
  449. paramType = AnimParamType::Sound;
  450. }
  451. if (paramType.GetType() >= AnimParamType::Animation && paramType.GetType() <= static_cast<AnimParamType>(static_cast<int>(AnimParamType::Animation) + 2))
  452. {
  453. paramType = AnimParamType::Animation;
  454. }
  455. if (paramType.GetType() >= APARAM_CHARACTER4 && paramType.GetType() <= APARAM_CHARACTER10)
  456. {
  457. paramType = AnimParamType::Animation;
  458. }
  459. // Old tracks always used TCB tracks.
  460. // Backward compatibility to the CryEngine2 for track type (will make TCB controller)
  461. curveType = eAnimCurveType_TCBVector;
  462. }
  463. }
  464. if (paramTypeVersion <= 1)
  465. {
  466. // In old versions goto tracks were identified by a curve id
  467. if (curveType == OLD_ACURVE_GOTO)
  468. {
  469. paramType = AnimParamType::Goto;
  470. curveType = eAnimCurveType_Unknown;
  471. }
  472. }
  473. if (paramTypeVersion <= 3 && paramType.GetType() >= static_cast<AnimParamType>(OLD_APARAM_USER))
  474. {
  475. // APARAM_USER 100 => 100000
  476. paramType = static_cast<AnimParamType>(static_cast<int>(paramType.GetType()) + static_cast<int>(AnimParamType::User) - OLD_APARAM_USER);
  477. }
  478. if (paramTypeVersion <= 4)
  479. {
  480. // In old versions there was special code for particles
  481. // that is now handles by generic entity node code
  482. switch (paramType.GetType())
  483. {
  484. case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_COUNT_SCALE) :
  485. paramType = CAnimParamType("ScriptTable:Properties/CountScale");
  486. break;
  487. case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_PULSE_PERIOD) :
  488. paramType = CAnimParamType("ScriptTable:Properties/PulsePeriod");
  489. break;
  490. case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_SCALE) :
  491. paramType = CAnimParamType("ScriptTable:Properties/Scale");
  492. break;
  493. case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_SPEED_SCALE) :
  494. paramType = CAnimParamType("ScriptTable:Properties/SpeedScale");
  495. break;
  496. case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_STRENGTH):
  497. paramType = CAnimParamType("ScriptTable:Properties/Strength");
  498. break;
  499. }
  500. }
  501. if (paramTypeVersion <= 5 && !(GetSequence()->GetFlags() & IAnimSequence::eSeqFlags_LightAnimationSet))
  502. {
  503. // In old versions there was special code for lights that is now handled
  504. // by generic entity node code if this is not a light animation set sequence
  505. switch (paramType.GetType())
  506. {
  507. case AnimParamType::LightDiffuse:
  508. paramType = CAnimParamType("ScriptTable:Properties/Color/clrDiffuse");
  509. break;
  510. case AnimParamType::LightRadius:
  511. paramType = CAnimParamType("ScriptTable:Properties/Radius");
  512. break;
  513. case AnimParamType::LightDiffuseMult:
  514. paramType = CAnimParamType("ScriptTable:Properties/Color/fDiffuseMultiplier");
  515. break;
  516. case AnimParamType::LightHDRDynamic:
  517. paramType = CAnimParamType("ScriptTable:Properties/Color/fHDRDynamic");
  518. break;
  519. case AnimParamType::LightSpecularMult:
  520. paramType = CAnimParamType("ScriptTable:Properties/Color/fSpecularMultiplier");
  521. break;
  522. case AnimParamType::LightSpecPercentage:
  523. paramType = CAnimParamType("ScriptTable:Properties/Color/fSpecularPercentage");
  524. break;
  525. }
  526. }
  527. if (paramTypeVersion <= 7 && paramType.GetType() == AnimParamType::Physics)
  528. {
  529. paramType = AnimParamType::PhysicsDriven;
  530. }
  531. int valueType = static_cast<int>(AnimValueType::Unknown);
  532. trackNode->getAttr("ValueType", valueType);
  533. IAnimTrack* pTrack = CreateTrackInternal(paramType, (EAnimCurveType)curveType, static_cast<AnimValueType>(valueType));
  534. bool trackRemoved = false;
  535. if (pTrack)
  536. {
  537. if (!pTrack->Serialize(trackNode, bLoading, bLoadEmptyTracks))
  538. {
  539. // Boolean tracks must always be loaded even if empty.
  540. if (pTrack->GetValueType() != AnimValueType::Bool)
  541. {
  542. RemoveTrack(pTrack);
  543. trackRemoved = true;
  544. }
  545. }
  546. }
  547. if (!trackRemoved && gEnv->IsEditor())
  548. {
  549. InitializeTrackDefaultValue(pTrack, paramType);
  550. }
  551. }
  552. }
  553. else
  554. {
  555. // Saving.
  556. xmlNode->setAttr("paramIdVersion", CAnimParamType::kParamTypeVersion);
  557. for (unsigned int i = 0; i < m_tracks.size(); i++)
  558. {
  559. IAnimTrack* pTrack = m_tracks[i].get();
  560. if (pTrack)
  561. {
  562. CAnimParamType paramType = m_tracks[i]->GetParameterType();
  563. XmlNodeRef trackNode = xmlNode->newChild("Track");
  564. paramType.Serialize(trackNode, bLoading);
  565. int nTrackType = pTrack->GetCurveType();
  566. trackNode->setAttr("Type", nTrackType);
  567. pTrack->Serialize(trackNode, bLoading);
  568. int valueType = static_cast<int>(pTrack->GetValueType());
  569. trackNode->setAttr("ValueType", valueType);
  570. }
  571. }
  572. }
  573. }
  574. //////////////////////////////////////////////////////////////////////////
  575. void CAnimNode::SetTimeRange(Range timeRange)
  576. {
  577. for (unsigned int i = 0; i < m_tracks.size(); i++)
  578. {
  579. if (m_tracks[i])
  580. {
  581. m_tracks[i]->SetTimeRange(timeRange);
  582. }
  583. }
  584. }
  585. //////////////////////////////////////////////////////////////////////////
  586. // AZ::Serialization requires a default constructor
  587. CAnimNode::CAnimNode()
  588. : CAnimNode(0, AnimNodeType::Invalid)
  589. {
  590. }
  591. //////////////////////////////////////////////////////////////////////////
  592. // explicit copy constructor is required to prevent compiler's generated copy constructor
  593. // from calling AZStd::mutex's private copy constructor
  594. CAnimNode::CAnimNode(const CAnimNode& other)
  595. : m_refCount(0)
  596. , m_id(0) // don't copy id - these should be unique
  597. , m_parentNodeId(other.m_parentNodeId)
  598. , m_nodeType(other.m_nodeType)
  599. , m_pOwner(other.m_pOwner)
  600. , m_pSequence(other.m_pSequence)
  601. , m_flags(other.m_flags)
  602. , m_pParentNode(other.m_pParentNode)
  603. , m_nLoadedParentNodeId(other.m_nLoadedParentNodeId)
  604. , m_expanded(other.m_expanded)
  605. {
  606. // m_bIgnoreSetParam not copied
  607. }
  608. //////////////////////////////////////////////////////////////////////////
  609. CAnimNode::CAnimNode(const int id, AnimNodeType nodeType)
  610. : m_refCount(0)
  611. , m_id(id)
  612. , m_parentNodeId(0)
  613. , m_nodeType(nodeType)
  614. {
  615. m_pOwner = 0;
  616. m_pSequence = 0;
  617. m_flags = 0;
  618. m_bIgnoreSetParam = false;
  619. m_pParentNode = 0;
  620. m_nLoadedParentNodeId = 0;
  621. m_expanded = true;
  622. }
  623. //////////////////////////////////////////////////////////////////////////
  624. CAnimNode::~CAnimNode()
  625. {
  626. }
  627. //////////////////////////////////////////////////////////////////////////
  628. void CAnimNode::add_ref()
  629. {
  630. ++m_refCount;
  631. }
  632. //////////////////////////////////////////////////////////////////////////
  633. void CAnimNode::release()
  634. {
  635. if (--m_refCount <= 0)
  636. {
  637. delete this;
  638. }
  639. }
  640. //////////////////////////////////////////////////////////////////////////
  641. void CAnimNode::SetFlags(int flags)
  642. {
  643. m_flags = flags;
  644. }
  645. //////////////////////////////////////////////////////////////////////////
  646. int CAnimNode::GetFlags() const
  647. {
  648. return m_flags;
  649. }
  650. //////////////////////////////////////////////////////////////////////////
  651. bool CAnimNode::AreFlagsSetOnNodeOrAnyParent(EAnimNodeFlags flagsToCheck) const
  652. {
  653. if (m_pParentNode)
  654. {
  655. // recurse up parent chain until we find the flagsToCheck set or get to the top of the chain
  656. return ((GetFlags() & flagsToCheck) != 0) || m_pParentNode->AreFlagsSetOnNodeOrAnyParent(flagsToCheck);
  657. }
  658. // top of parent chain
  659. return ((GetFlags() & flagsToCheck) != 0);
  660. }
  661. //////////////////////////////////////////////////////////////////////////
  662. void CAnimNode::Animate([[maybe_unused]] SAnimContext& ec)
  663. {
  664. }
  665. //////////////////////////////////////////////////////////////////////////
  666. bool CAnimNode::IsParamValid(const CAnimParamType& paramType) const
  667. {
  668. SParamInfo info;
  669. if (GetParamInfoFromType(paramType, info))
  670. {
  671. return true;
  672. }
  673. return false;
  674. }
  675. //////////////////////////////////////////////////////////////////////////
  676. bool CAnimNode::SetParamValue(float time, CAnimParamType param, float value)
  677. {
  678. if (m_bIgnoreSetParam)
  679. {
  680. return true;
  681. }
  682. IAnimTrack* pTrack = GetTrackForParameter(param);
  683. if (pTrack && pTrack->GetValueType() == AnimValueType::Float)
  684. {
  685. // Float track.
  686. bool bDefault = !(gEnv->pMovieSystem->IsRecording() && (m_flags & eAnimNodeFlags_EntitySelected)); // Only selected nodes can be recorded
  687. pTrack->SetValue(time, value, bDefault);
  688. return true;
  689. }
  690. return false;
  691. }
  692. //////////////////////////////////////////////////////////////////////////
  693. bool CAnimNode::SetParamValue(float time, CAnimParamType param, const Vec3& value)
  694. {
  695. if (m_bIgnoreSetParam)
  696. {
  697. return true;
  698. }
  699. CCompoundSplineTrack* pTrack = static_cast<CCompoundSplineTrack*>(GetTrackForParameter(param));
  700. if (pTrack && pTrack->GetValueType() == AnimValueType::Vector)
  701. {
  702. // Vec3 track.
  703. bool bDefault = !(gEnv->pMovieSystem->IsRecording() && (m_flags & eAnimNodeFlags_EntitySelected)); // Only selected nodes can be recorded
  704. pTrack->SetValue(time, value, bDefault);
  705. return true;
  706. }
  707. return false;
  708. }
  709. //////////////////////////////////////////////////////////////////////////
  710. bool CAnimNode::SetParamValue(float time, CAnimParamType param, const Vec4& value)
  711. {
  712. if (m_bIgnoreSetParam)
  713. {
  714. return true;
  715. }
  716. CCompoundSplineTrack* pTrack = static_cast<CCompoundSplineTrack*>(GetTrackForParameter(param));
  717. if (pTrack && pTrack->GetValueType() == AnimValueType::Vector4)
  718. {
  719. // Vec4 track.
  720. bool bDefault = !(gEnv->pMovieSystem->IsRecording() && (m_flags & eAnimNodeFlags_EntitySelected)); // Only selected nodes can be recorded
  721. pTrack->SetValue(time, value, bDefault);
  722. return true;
  723. }
  724. return false;
  725. }
  726. //////////////////////////////////////////////////////////////////////////
  727. bool CAnimNode::GetParamValue(float time, CAnimParamType param, float& value)
  728. {
  729. IAnimTrack* pTrack = GetTrackForParameter(param);
  730. if (pTrack && pTrack->GetValueType() == AnimValueType::Float && pTrack->GetNumKeys() > 0)
  731. {
  732. // Float track.
  733. pTrack->GetValue(time, value);
  734. return true;
  735. }
  736. return false;
  737. }
  738. //////////////////////////////////////////////////////////////////////////
  739. bool CAnimNode::GetParamValue(float time, CAnimParamType param, Vec3& value)
  740. {
  741. CCompoundSplineTrack* pTrack = static_cast<CCompoundSplineTrack*>(GetTrackForParameter(param));
  742. if (pTrack && pTrack->GetValueType() == AnimValueType::Vector && pTrack->GetNumKeys() > 0)
  743. {
  744. // Vec3 track.
  745. pTrack->GetValue(time, value);
  746. return true;
  747. }
  748. return false;
  749. }
  750. //////////////////////////////////////////////////////////////////////////
  751. bool CAnimNode::GetParamValue(float time, CAnimParamType param, Vec4& value)
  752. {
  753. CCompoundSplineTrack* pTrack = static_cast<CCompoundSplineTrack*>(GetTrackForParameter(param));
  754. if (pTrack && pTrack->GetValueType() == AnimValueType::Vector4 && pTrack->GetNumKeys() > 0)
  755. {
  756. // Vec4 track.
  757. pTrack->GetValue(time, value);
  758. return true;
  759. }
  760. return false;
  761. }
  762. //////////////////////////////////////////////////////////////////////////
  763. /// @deprecated Serialization for Sequence data in Component Entity Sequences now occurs through AZ::SerializeContext and the Sequence Component
  764. void CAnimNode::Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks)
  765. {
  766. if (bLoading)
  767. {
  768. xmlNode->getAttr("Id", m_id);
  769. const char* name = xmlNode->getAttr("Name");
  770. int flags;
  771. if (xmlNode->getAttr("Flags", flags))
  772. {
  773. // Don't load expanded or selected flags
  774. flags = flags & ~(eAnimNodeFlags_Expanded | eAnimNodeFlags_EntitySelected);
  775. SetFlags(flags);
  776. }
  777. SetName(name);
  778. m_nLoadedParentNodeId = 0;
  779. xmlNode->getAttr("ParentNode", m_nLoadedParentNodeId);
  780. }
  781. else
  782. {
  783. m_nLoadedParentNodeId = 0;
  784. xmlNode->setAttr("Id", m_id);
  785. AnimNodeType nodeType = GetType();
  786. GetMovieSystem()->SerializeNodeType(nodeType, xmlNode, bLoading, IAnimSequence::kSequenceVersion, m_flags);
  787. xmlNode->setAttr("Name", GetName());
  788. // Don't store expanded or selected flags
  789. int flags = GetFlags() & ~(eAnimNodeFlags_Expanded | eAnimNodeFlags_EntitySelected);
  790. xmlNode->setAttr("Flags", flags);
  791. if (m_pParentNode)
  792. {
  793. xmlNode->setAttr("ParentNode", static_cast<CAnimNode*>(m_pParentNode)->GetId());
  794. }
  795. }
  796. SerializeAnims(xmlNode, bLoading, bLoadEmptyTracks);
  797. }
  798. //////////////////////////////////////////////////////////////////////////
  799. void CAnimNode::InitPostLoad(IAnimSequence* sequence)
  800. {
  801. m_pSequence = sequence;
  802. m_pParentNode = ((CAnimSequence*)m_pSequence)->FindNodeById(m_parentNodeId);
  803. // fix up animNode pointers and time ranges on tracks, then sort them
  804. for (unsigned int i = 0; i < m_tracks.size(); i++)
  805. {
  806. RegisterTrack(m_tracks[i].get());
  807. m_tracks[i].get()->InitPostLoad(sequence);
  808. }
  809. SortTracks();
  810. }
  811. //////////////////////////////////////////////////////////////////////////
  812. void CAnimNode::SetNodeOwner(IAnimNodeOwner* pOwner)
  813. {
  814. m_pOwner = pOwner;
  815. if (pOwner)
  816. {
  817. pOwner->OnNodeAnimated(this);
  818. }
  819. }
  820. //////////////////////////////////////////////////////////////////////////
  821. void CAnimNode::PostLoad()
  822. {
  823. if (m_nLoadedParentNodeId)
  824. {
  825. IAnimNode* pParentNode = ((CAnimSequence*)m_pSequence)->FindNodeById(m_nLoadedParentNodeId);
  826. m_pParentNode = pParentNode;
  827. m_parentNodeId = m_nLoadedParentNodeId; // adding as a temporary fix while we support both serialization methods
  828. m_nLoadedParentNodeId = 0;
  829. }
  830. }
  831. //////////////////////////////////////////////////////////////////////////
  832. Matrix34 CAnimNode::GetReferenceMatrix() const
  833. {
  834. static Matrix34 tm(IDENTITY);
  835. return tm;
  836. }
  837. IAnimTrack* CAnimNode::CreateTrackInternalFloat([[maybe_unused]] int trackType) const
  838. {
  839. return aznew C2DSplineTrack;
  840. }
  841. IAnimTrack* CAnimNode::CreateTrackInternalVector([[maybe_unused]] EAnimCurveType trackType, const CAnimParamType& paramType, const AnimValueType animValue) const
  842. {
  843. CAnimParamType subTrackParamTypes[MAX_SUBTRACKS];
  844. for (unsigned int i = 0; i < MAX_SUBTRACKS; ++i)
  845. {
  846. subTrackParamTypes[i] = AnimParamType::Float;
  847. }
  848. if (paramType == AnimParamType::Position)
  849. {
  850. subTrackParamTypes[0] = AnimParamType::PositionX;
  851. subTrackParamTypes[1] = AnimParamType::PositionY;
  852. subTrackParamTypes[2] = AnimParamType::PositionZ;
  853. }
  854. else if (paramType == AnimParamType::Scale)
  855. {
  856. subTrackParamTypes[0] = AnimParamType::ScaleX;
  857. subTrackParamTypes[1] = AnimParamType::ScaleY;
  858. subTrackParamTypes[2] = AnimParamType::ScaleZ;
  859. }
  860. else if (paramType == AnimParamType::Rotation)
  861. {
  862. subTrackParamTypes[0] = AnimParamType::RotationX;
  863. subTrackParamTypes[1] = AnimParamType::RotationY;
  864. subTrackParamTypes[2] = AnimParamType::RotationZ;
  865. IAnimTrack* pTrack = aznew CCompoundSplineTrack(3, AnimValueType::Quat, subTrackParamTypes, false);
  866. return pTrack;
  867. }
  868. else if (paramType == AnimParamType::DepthOfField)
  869. {
  870. subTrackParamTypes[0] = AnimParamType::FocusDistance;
  871. subTrackParamTypes[1] = AnimParamType::FocusRange;
  872. subTrackParamTypes[2] = AnimParamType::BlurAmount;
  873. IAnimTrack* pTrack = aznew CCompoundSplineTrack(3, AnimValueType::Vector, subTrackParamTypes, false);
  874. pTrack->SetSubTrackName(0, "FocusDist");
  875. pTrack->SetSubTrackName(1, "FocusRange");
  876. pTrack->SetSubTrackName(2, "BlurAmount");
  877. return pTrack;
  878. }
  879. else if (animValue == AnimValueType::RGB || paramType == AnimParamType::LightDiffuse ||
  880. paramType == AnimParamType::MaterialDiffuse || paramType == AnimParamType::MaterialSpecular
  881. || paramType == AnimParamType::MaterialEmissive)
  882. {
  883. subTrackParamTypes[0] = AnimParamType::ColorR;
  884. subTrackParamTypes[1] = AnimParamType::ColorG;
  885. subTrackParamTypes[2] = AnimParamType::ColorB;
  886. IAnimTrack* pTrack = aznew CCompoundSplineTrack(3, AnimValueType::RGB, subTrackParamTypes, false);
  887. pTrack->SetSubTrackName(0, "Red");
  888. pTrack->SetSubTrackName(1, "Green");
  889. pTrack->SetSubTrackName(2, "Blue");
  890. return pTrack;
  891. }
  892. return aznew CCompoundSplineTrack(3, AnimValueType::Vector, subTrackParamTypes, false);
  893. }
  894. IAnimTrack* CAnimNode::CreateTrackInternalQuat([[maybe_unused]] EAnimCurveType trackType, const CAnimParamType& paramType) const
  895. {
  896. CAnimParamType subTrackParamTypes[MAX_SUBTRACKS];
  897. if (paramType == AnimParamType::Rotation)
  898. {
  899. subTrackParamTypes[0] = AnimParamType::RotationX;
  900. subTrackParamTypes[1] = AnimParamType::RotationY;
  901. subTrackParamTypes[2] = AnimParamType::RotationZ;
  902. }
  903. else
  904. {
  905. // Unknown param type
  906. assert(0);
  907. }
  908. return aznew CCompoundSplineTrack(3, AnimValueType::Quat, subTrackParamTypes, false);
  909. }
  910. IAnimTrack* CAnimNode::CreateTrackInternalVector4(const CAnimParamType& paramType) const
  911. {
  912. IAnimTrack* pTrack;
  913. CAnimParamType subTrackParamTypes[MAX_SUBTRACKS];
  914. // set up track subtypes
  915. if (paramType == AnimParamType::TransformNoise
  916. || paramType == AnimParamType::ShakeMultiplier)
  917. {
  918. subTrackParamTypes[0] = AnimParamType::ShakeAmpAMult;
  919. subTrackParamTypes[1] = AnimParamType::ShakeAmpBMult;
  920. subTrackParamTypes[2] = AnimParamType::ShakeFreqAMult;
  921. subTrackParamTypes[3] = AnimParamType::ShakeFreqBMult;
  922. }
  923. else
  924. {
  925. // default to a Vector4 of floats
  926. for (unsigned int i = 0; i < MAX_SUBTRACKS; ++i)
  927. {
  928. subTrackParamTypes[i] = AnimParamType::Float;
  929. }
  930. }
  931. // create track
  932. pTrack = aznew CCompoundSplineTrack(4, AnimValueType::Vector4, subTrackParamTypes, true);
  933. // label subtypes
  934. if (paramType == AnimParamType::TransformNoise)
  935. {
  936. pTrack->SetSubTrackName(0, "Pos Noise Amp");
  937. pTrack->SetSubTrackName(1, "Pos Noise Freq");
  938. pTrack->SetSubTrackName(2, "Rot Noise Amp");
  939. pTrack->SetSubTrackName(3, "Rot Noise Freq");
  940. }
  941. else if (paramType == AnimParamType::ShakeMultiplier)
  942. {
  943. pTrack->SetSubTrackName(0, "Amplitude A");
  944. pTrack->SetSubTrackName(1, "Amplitude B");
  945. pTrack->SetSubTrackName(2, "Frequency A");
  946. pTrack->SetSubTrackName(3, "Frequency B");
  947. }
  948. return pTrack;
  949. }
  950. void CAnimNode::TimeChanged(float newTime)
  951. {
  952. // if the newTime is on a sound key, then reset sounds so sound will playback on next call to Animate()
  953. if (IsTimeOnSoundKey(newTime))
  954. {
  955. ResetSounds();
  956. }
  957. }
  958. bool CAnimNode::IsTimeOnSoundKey(float queryTime) const
  959. {
  960. bool retIsTimeOnSoundKey = false;
  961. const float tolerance = 0.0333f; // one frame at 30 fps
  962. int trackCount = NumTracks();
  963. for (int trackIndex = 0; trackIndex < trackCount; trackIndex++)
  964. {
  965. CAnimParamType paramType = m_tracks[trackIndex]->GetParameterType();
  966. IAnimTrack* pTrack = m_tracks[trackIndex].get();
  967. if ((paramType.GetType() != AnimParamType::Sound)
  968. || (pTrack->HasKeys() == false && pTrack->GetParameterType() != AnimParamType::Visibility)
  969. || (pTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Disabled))
  970. {
  971. continue;
  972. }
  973. // if we're here, pTrack points to a AnimParamType::Sound track
  974. ISoundKey oSoundKey;
  975. int const nSoundKey = static_cast<CSoundTrack*>(pTrack)->GetActiveKey(queryTime, &oSoundKey);
  976. if (nSoundKey >= 0)
  977. {
  978. retIsTimeOnSoundKey = AZ::IsClose(queryTime, oSoundKey.time, tolerance);
  979. if (retIsTimeOnSoundKey)
  980. {
  981. break; // no need to search further, we have a hit
  982. }
  983. }
  984. }
  985. return retIsTimeOnSoundKey;
  986. }
  987. //////////////////////////////////////////////////////////////////////////
  988. void CAnimNode::AnimateSound(std::vector<SSoundInfo>& nodeSoundInfo, SAnimContext& ec, IAnimTrack* pTrack, size_t numAudioTracks)
  989. {
  990. bool const bMute = gEnv->IsEditor() && (pTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Muted);
  991. if (!bMute && ec.time >= 0.0f)
  992. {
  993. ISoundKey oSoundKey;
  994. int const nSoundKey = static_cast<CSoundTrack*>(pTrack)->GetActiveKey(ec.time, &oSoundKey);
  995. SSoundInfo& rSoundInfo = nodeSoundInfo[numAudioTracks - 1];
  996. if (nSoundKey >= 0)
  997. {
  998. float const fSoundKeyTime = (ec.time - oSoundKey.time);
  999. if (rSoundInfo.nSoundKeyStart < nSoundKey && fSoundKeyTime < oSoundKey.fDuration)
  1000. {
  1001. ApplyAudioKey(oSoundKey.sStartTrigger.c_str());
  1002. }
  1003. if (rSoundInfo.nSoundKeyStart > nSoundKey)
  1004. {
  1005. rSoundInfo.nSoundKeyStop = nSoundKey;
  1006. }
  1007. rSoundInfo.nSoundKeyStart = nSoundKey;
  1008. if (fSoundKeyTime >= oSoundKey.fDuration)
  1009. {
  1010. if (rSoundInfo.nSoundKeyStop < nSoundKey)
  1011. {
  1012. rSoundInfo.nSoundKeyStop = nSoundKey;
  1013. if (oSoundKey.sStopTrigger.empty())
  1014. {
  1015. ApplyAudioKey(oSoundKey.sStartTrigger.c_str(), false);
  1016. }
  1017. else
  1018. {
  1019. ApplyAudioKey(oSoundKey.sStopTrigger.c_str());
  1020. }
  1021. }
  1022. }
  1023. else
  1024. {
  1025. rSoundInfo.nSoundKeyStop = -1;
  1026. }
  1027. }
  1028. else
  1029. {
  1030. rSoundInfo.Reset();
  1031. }
  1032. }
  1033. }
  1034. void CAnimNode::SetParent(IAnimNode* parent)
  1035. {
  1036. m_pParentNode = parent;
  1037. if (parent)
  1038. {
  1039. m_parentNodeId = static_cast<CAnimNode*>(m_pParentNode)->GetId();
  1040. }
  1041. else
  1042. {
  1043. m_parentNodeId = 0;
  1044. }
  1045. }
  1046. //////////////////////////////////////////////////////////////////////////
  1047. IAnimNode* CAnimNode::HasDirectorAsParent() const
  1048. {
  1049. IAnimNode* pParent = GetParent();
  1050. while (pParent)
  1051. {
  1052. if (pParent->GetType() == AnimNodeType::Director)
  1053. {
  1054. return pParent;
  1055. }
  1056. // There are some invalid data.
  1057. if (pParent->GetParent() == pParent)
  1058. {
  1059. pParent->SetParent(NULL);
  1060. return NULL;
  1061. }
  1062. pParent = pParent->GetParent();
  1063. }
  1064. return NULL;
  1065. }
  1066. void CAnimNode::UpdateDynamicParams()
  1067. {
  1068. if (gEnv->IsEditor())
  1069. {
  1070. // UpdateDynamicParams is called as the result of an editor event that is fired when a material is loaded,
  1071. // which could happen from multiple threads. Lock to avoid a crash iterating over the lua stack
  1072. AZStd::lock_guard<AZStd::mutex> lock(m_updateDynamicParamsLock);
  1073. // run this on the main thread to prevent further threading issues downstream in
  1074. // AnimNodes that may use EBuses that are not thread safe
  1075. if (gEnv && gEnv->mMainThreadId == CryGetCurrentThreadId())
  1076. {
  1077. UpdateDynamicParamsInternal();
  1078. }
  1079. else
  1080. {
  1081. AZ::TickBus::QueueFunction([this] {
  1082. UpdateDynamicParamsInternal();
  1083. });
  1084. }
  1085. }
  1086. else
  1087. {
  1088. UpdateDynamicParamsInternal();
  1089. }
  1090. }
  1091. //////////////////////////////////////////////////////////////////////////
  1092. void CAnimNode::SetExpanded(bool expanded)
  1093. {
  1094. m_expanded = expanded;
  1095. }
  1096. //////////////////////////////////////////////////////////////////////////
  1097. bool CAnimNode::GetExpanded() const
  1098. {
  1099. return m_expanded;
  1100. }