TrackViewTrack.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  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 "EditorDefs.h"
  9. #include "TrackViewTrack.h"
  10. // CryCommon
  11. #include <CryCommon/Maestro/Types/AnimParamType.h>
  12. // Editor
  13. #include "TrackViewSequence.h"
  14. #include "TrackViewNodeFactories.h"
  15. void CTrackViewTrackBundle::AppendTrack(CTrackViewTrack* pTrack)
  16. {
  17. // Check if newly added key has different type than existing ones
  18. if (m_bAllOfSameType && m_tracks.size() > 0)
  19. {
  20. const CTrackViewTrack* pLastTrack = m_tracks.back();
  21. if (pTrack->GetParameterType() != pLastTrack->GetParameterType()
  22. || pTrack->GetCurveType() != pLastTrack->GetCurveType()
  23. || pTrack->GetValueType() != pLastTrack->GetValueType())
  24. {
  25. m_bAllOfSameType = false;
  26. }
  27. }
  28. stl::push_back_unique(m_tracks, pTrack);
  29. }
  30. void CTrackViewTrackBundle::AppendTrackBundle(const CTrackViewTrackBundle& bundle)
  31. {
  32. for (auto iter = bundle.m_tracks.begin(); iter != bundle.m_tracks.end(); ++iter)
  33. {
  34. AppendTrack(*iter);
  35. }
  36. }
  37. bool CTrackViewTrackBundle::RemoveTrack(CTrackViewTrack* trackToRemove)
  38. {
  39. return stl::find_and_erase(m_tracks, trackToRemove);
  40. }
  41. CTrackViewTrack::CTrackViewTrack(IAnimTrack* pTrack, CTrackViewAnimNode* pTrackAnimNode,
  42. CTrackViewNode* pParentNode, bool bIsSubTrack, unsigned int subTrackIndex)
  43. : CTrackViewNode(pParentNode)
  44. , m_pAnimTrack(pTrack)
  45. , m_pTrackAnimNode(pTrackAnimNode)
  46. , m_bIsSubTrack(bIsSubTrack)
  47. , m_subTrackIndex(subTrackIndex)
  48. {
  49. // Search for child tracks
  50. const unsigned int subTrackCount = m_pAnimTrack->GetSubTrackCount();
  51. for (unsigned int subTrackI = 0; subTrackI < subTrackCount; ++subTrackI)
  52. {
  53. IAnimTrack* pSubTrack = m_pAnimTrack->GetSubTrack(subTrackI);
  54. CTrackViewTrackFactory trackFactory;
  55. CTrackViewTrack* pNewTVTrack = trackFactory.BuildTrack(pSubTrack, pTrackAnimNode, this, true, subTrackI);
  56. m_childNodes.push_back(AZStd::unique_ptr<CTrackViewNode>(pNewTVTrack));
  57. }
  58. m_bIsCompoundTrack = subTrackCount > 0;
  59. // Connect bus to listen for OnStart/StopPlayInEditor events
  60. AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
  61. }
  62. CTrackViewTrack::~CTrackViewTrack()
  63. {
  64. AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect();
  65. }
  66. CTrackViewAnimNode* CTrackViewTrack::GetAnimNode() const
  67. {
  68. return m_pTrackAnimNode;
  69. }
  70. bool CTrackViewTrack::SnapTimeToPrevKey(float& time) const
  71. {
  72. CTrackViewKeyHandle prevKey = const_cast<CTrackViewTrack*>(this)->GetPrevKey(time);
  73. if (prevKey.IsValid())
  74. {
  75. time = prevKey.GetTime();
  76. return true;
  77. }
  78. return false;
  79. }
  80. bool CTrackViewTrack::SnapTimeToNextKey(float& time) const
  81. {
  82. CTrackViewKeyHandle prevKey = const_cast<CTrackViewTrack*>(this)->GetNextKey(time);
  83. if (prevKey.IsValid())
  84. {
  85. time = prevKey.GetTime();
  86. return true;
  87. }
  88. return false;
  89. }
  90. void CTrackViewTrack::SetExpanded(bool expanded)
  91. {
  92. if (m_pAnimTrack)
  93. {
  94. CTrackViewSequence* sequence = GetSequence();
  95. if (nullptr != sequence)
  96. {
  97. if (GetExpanded() != expanded)
  98. {
  99. m_pAnimTrack->SetExpanded(expanded);
  100. if (expanded)
  101. {
  102. sequence->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Expanded);
  103. }
  104. else
  105. {
  106. sequence->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Collapsed);
  107. }
  108. }
  109. }
  110. }
  111. }
  112. bool CTrackViewTrack::GetExpanded() const
  113. {
  114. return (m_pAnimTrack) ? m_pAnimTrack->GetExpanded() : false;
  115. }
  116. CTrackViewKeyHandle CTrackViewTrack::GetPrevKey(const float time)
  117. {
  118. CTrackViewKeyHandle keyHandle;
  119. #ifdef max
  120. #undef max
  121. #endif
  122. const float startTime = time;
  123. float closestTime = -std::numeric_limits<float>::max();
  124. const int numKeys = m_pAnimTrack->GetNumKeys();
  125. for (int i = 0; i < numKeys; ++i)
  126. {
  127. const float keyTime = m_pAnimTrack->GetKeyTime(i);
  128. if (keyTime < startTime && keyTime > closestTime)
  129. {
  130. keyHandle = CTrackViewKeyHandle(this, i);
  131. closestTime = keyTime;
  132. }
  133. }
  134. return keyHandle;
  135. }
  136. CTrackViewKeyHandle CTrackViewTrack::GetNextKey(const float time)
  137. {
  138. CTrackViewKeyHandle keyHandle;
  139. const float startTime = time;
  140. float closestTime = std::numeric_limits<float>::max();
  141. const int numKeys = m_pAnimTrack->GetNumKeys();
  142. for (int i = 0; i < numKeys; ++i)
  143. {
  144. const float keyTime = m_pAnimTrack->GetKeyTime(i);
  145. if (keyTime > startTime && keyTime < closestTime)
  146. {
  147. keyHandle = CTrackViewKeyHandle(this, i);
  148. closestTime = keyTime;
  149. }
  150. }
  151. return keyHandle;
  152. }
  153. CTrackViewKeyBundle CTrackViewTrack::GetSelectedKeys()
  154. {
  155. CTrackViewKeyBundle bundle;
  156. if (m_bIsCompoundTrack)
  157. {
  158. for (auto iter = m_childNodes.begin(); iter != m_childNodes.end(); ++iter)
  159. {
  160. bundle.AppendKeyBundle((*iter)->GetSelectedKeys());
  161. }
  162. }
  163. else
  164. {
  165. bundle = GetKeys(true, -std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
  166. }
  167. return bundle;
  168. }
  169. CTrackViewKeyBundle CTrackViewTrack::GetAllKeys()
  170. {
  171. CTrackViewKeyBundle bundle;
  172. if (m_bIsCompoundTrack)
  173. {
  174. for (auto iter = m_childNodes.begin(); iter != m_childNodes.end(); ++iter)
  175. {
  176. bundle.AppendKeyBundle((*iter)->GetAllKeys());
  177. }
  178. }
  179. else
  180. {
  181. bundle = GetKeys(false, -std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
  182. }
  183. return bundle;
  184. }
  185. CTrackViewKeyBundle CTrackViewTrack::GetKeysInTimeRange(const float t0, const float t1)
  186. {
  187. CTrackViewKeyBundle bundle;
  188. if (m_bIsCompoundTrack)
  189. {
  190. for (auto iter = m_childNodes.begin(); iter != m_childNodes.end(); ++iter)
  191. {
  192. bundle.AppendKeyBundle((*iter)->GetKeysInTimeRange(t0, t1));
  193. }
  194. }
  195. else
  196. {
  197. bundle = GetKeys(false, t0, t1);
  198. }
  199. return bundle;
  200. }
  201. CTrackViewKeyBundle CTrackViewTrack::GetKeys(const bool bOnlySelected, const float t0, const float t1)
  202. {
  203. CTrackViewKeyBundle bundle;
  204. const int keyCount = m_pAnimTrack->GetNumKeys();
  205. for (int keyIndex = 0; keyIndex < keyCount; ++keyIndex)
  206. {
  207. const float keyTime = m_pAnimTrack->GetKeyTime(keyIndex);
  208. const bool timeRangeOk = (t0 <= keyTime && keyTime <= t1);
  209. if (timeRangeOk && (!bOnlySelected || IsKeySelected(keyIndex)))
  210. {
  211. CTrackViewKeyHandle keyHandle(this, keyIndex);
  212. bundle.AppendKey(keyHandle);
  213. }
  214. }
  215. return bundle;
  216. }
  217. CTrackViewKeyHandle CTrackViewTrack::CreateKey(const float time)
  218. {
  219. const int keyIndex = m_pAnimTrack->CreateKey(time);
  220. GetSequence()->OnKeysChanged();
  221. CTrackViewKeyHandle createdKeyHandle(this, keyIndex);
  222. GetSequence()->OnKeyAdded(createdKeyHandle);
  223. return createdKeyHandle;
  224. }
  225. void CTrackViewTrack::SlideKeys(const float time0, const float timeOffset)
  226. {
  227. for (int i = 0; i < m_pAnimTrack->GetNumKeys(); ++i)
  228. {
  229. float keyTime = m_pAnimTrack->GetKeyTime(i);
  230. if (keyTime >= time0)
  231. {
  232. m_pAnimTrack->SetKeyTime(i, keyTime + timeOffset);
  233. }
  234. }
  235. }
  236. void CTrackViewTrack::UpdateKeyDataAfterParentChanged(const AZ::Transform& oldParentWorldTM, const AZ::Transform& newParentWorldTM)
  237. {
  238. AZStd::unique_ptr<AzToolsFramework::ScopedUndoBatch> undoBatch;
  239. if (!AzToolsFramework::UndoRedoOperationInProgress())
  240. {
  241. undoBatch = AZStd::make_unique<AzToolsFramework::ScopedUndoBatch>("Update Key Data After Parent Changed");
  242. }
  243. m_pAnimTrack->UpdateKeyDataAfterParentChanged(oldParentWorldTM, newParentWorldTM);
  244. if (undoBatch.get())
  245. {
  246. undoBatch->MarkEntityDirty(GetSequence()->GetSequenceComponentEntityId());
  247. }
  248. }
  249. CTrackViewKeyHandle CTrackViewTrack::GetKey(unsigned int index)
  250. {
  251. if (index < GetKeyCount())
  252. {
  253. return CTrackViewKeyHandle(this, index);
  254. }
  255. return CTrackViewKeyHandle();
  256. }
  257. CTrackViewKeyConstHandle CTrackViewTrack::GetKey(unsigned int index) const
  258. {
  259. if (index < GetKeyCount())
  260. {
  261. return CTrackViewKeyConstHandle(this, index);
  262. }
  263. return CTrackViewKeyConstHandle();
  264. }
  265. CTrackViewKeyHandle CTrackViewTrack::GetKeyByTime(const float time)
  266. {
  267. if (m_bIsCompoundTrack)
  268. {
  269. // Search key in sub tracks
  270. unsigned int currentIndex = 0;
  271. unsigned int childCount = GetChildCount();
  272. for (unsigned int i = 0; i < childCount; ++i)
  273. {
  274. CTrackViewTrack* pChildTrack = static_cast<CTrackViewTrack*>(GetChild(i));
  275. int keyIndex = pChildTrack->m_pAnimTrack->FindKey(time);
  276. if (keyIndex >= 0)
  277. {
  278. return CTrackViewKeyHandle(this, currentIndex + keyIndex);
  279. }
  280. currentIndex += pChildTrack->GetKeyCount();
  281. }
  282. }
  283. int keyIndex = m_pAnimTrack->FindKey(time);
  284. if (keyIndex < 0)
  285. {
  286. return CTrackViewKeyHandle();
  287. }
  288. return CTrackViewKeyHandle(this, keyIndex);
  289. }
  290. CTrackViewKeyHandle CTrackViewTrack::GetNearestKeyByTime(const float time)
  291. {
  292. int minDelta = std::numeric_limits<int>::max();
  293. const unsigned int keyCount = GetKeyCount();
  294. for (unsigned int i = 0; i < keyCount; ++i)
  295. {
  296. CTrackViewKeyHandle keyHandle = GetKey(i);
  297. const int deltaT = abs((int)keyHandle.GetTime() - (int)time);
  298. // If deltaT got larger since last key, then the last key
  299. // was the key with minimum temporal distance to the given time
  300. if (deltaT > minDelta)
  301. {
  302. return CTrackViewKeyHandle(this, i - 1);
  303. }
  304. minDelta = AZStd::min(minDelta, deltaT);
  305. }
  306. // If we didn't return above and there are keys, then the
  307. // last key needs to be the one with minimum distance
  308. if (keyCount > 0)
  309. {
  310. return CTrackViewKeyHandle(this, keyCount - 1);
  311. }
  312. // No keys
  313. return CTrackViewKeyHandle();
  314. }
  315. void CTrackViewTrack::GetKeyValueRange(float& min, float& max) const
  316. {
  317. m_pAnimTrack->GetKeyValueRange(min, max);
  318. }
  319. ColorB CTrackViewTrack::GetCustomColor() const
  320. {
  321. return m_pAnimTrack->GetCustomColor();
  322. }
  323. void CTrackViewTrack::SetCustomColor(ColorB color)
  324. {
  325. m_pAnimTrack->SetCustomColor(color);
  326. }
  327. bool CTrackViewTrack::HasCustomColor() const
  328. {
  329. return m_pAnimTrack->HasCustomColor();
  330. }
  331. void CTrackViewTrack::ClearCustomColor()
  332. {
  333. m_pAnimTrack->ClearCustomColor();
  334. }
  335. IAnimTrack::EAnimTrackFlags CTrackViewTrack::GetFlags() const
  336. {
  337. return (IAnimTrack::EAnimTrackFlags)m_pAnimTrack->GetFlags();
  338. }
  339. CTrackViewTrackMemento CTrackViewTrack::GetMemento() const
  340. {
  341. CTrackViewTrackMemento memento;
  342. memento.m_serializedTrackState = XmlHelpers::CreateXmlNode("TrackState");
  343. m_pAnimTrack->Serialize(memento.m_serializedTrackState, false);
  344. return memento;
  345. }
  346. void CTrackViewTrack::RestoreFromMemento(const CTrackViewTrackMemento& memento)
  347. {
  348. // We're going to de-serialize, so this is const safe
  349. XmlNodeRef& xmlNode = const_cast<XmlNodeRef&>(memento.m_serializedTrackState);
  350. m_pAnimTrack->Serialize(xmlNode, true);
  351. }
  352. AZStd::string CTrackViewTrack::GetName() const
  353. {
  354. CTrackViewNode* pParentNode = GetParentNode();
  355. if (pParentNode->GetNodeType() == eTVNT_Track)
  356. {
  357. CTrackViewTrack* pParentTrack = static_cast<CTrackViewTrack*>(pParentNode);
  358. return pParentTrack->m_pAnimTrack->GetSubTrackName(m_subTrackIndex);
  359. }
  360. return GetAnimNode()->GetParamName(GetParameterType());
  361. }
  362. void CTrackViewTrack::SetDisabled(bool bDisabled)
  363. {
  364. if (bDisabled)
  365. {
  366. m_pAnimTrack->SetFlags(m_pAnimTrack->GetFlags() | IAnimTrack::eAnimTrackFlags_Disabled);
  367. GetSequence()->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Disabled);
  368. }
  369. else
  370. {
  371. m_pAnimTrack->SetFlags(m_pAnimTrack->GetFlags() & ~IAnimTrack::eAnimTrackFlags_Disabled);
  372. GetSequence()->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Enabled);
  373. }
  374. }
  375. bool CTrackViewTrack::IsDisabled() const
  376. {
  377. return m_pAnimTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Disabled;
  378. }
  379. void CTrackViewTrack::SetMuted(bool bMuted)
  380. {
  381. if (UsesMute())
  382. {
  383. if (bMuted)
  384. {
  385. m_pAnimTrack->SetFlags(m_pAnimTrack->GetFlags() | IAnimTrack::eAnimTrackFlags_Muted);
  386. GetSequence()->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Muted);
  387. }
  388. else
  389. {
  390. m_pAnimTrack->SetFlags(m_pAnimTrack->GetFlags() & ~IAnimTrack::eAnimTrackFlags_Muted);
  391. GetSequence()->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Unmuted);
  392. }
  393. }
  394. }
  395. // Returns whether the track is muted, or false if the track does not use muting
  396. bool CTrackViewTrack::IsMuted() const
  397. {
  398. return m_pAnimTrack->UsesMute() ? (m_pAnimTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Muted) : false;
  399. }
  400. void CTrackViewTrack::SetKey(unsigned int keyIndex, IKey* pKey)
  401. {
  402. m_pAnimTrack->SetKey(keyIndex, pKey);
  403. m_pTrackAnimNode->GetSequence()->OnKeysChanged();
  404. }
  405. void CTrackViewTrack::GetKey(unsigned int keyIndex, IKey* pKey) const
  406. {
  407. m_pAnimTrack->GetKey(keyIndex, pKey);
  408. }
  409. void CTrackViewTrack::SelectKey(unsigned int keyIndex, bool bSelect)
  410. {
  411. const bool bWasSelected = m_pAnimTrack->IsKeySelected(keyIndex);
  412. m_pAnimTrack->SelectKey(keyIndex, bSelect);
  413. if (bSelect != bWasSelected)
  414. {
  415. m_pTrackAnimNode->GetSequence()->OnKeySelectionChanged();
  416. }
  417. }
  418. void CTrackViewTrack::SetKeyTime(const int index, const float time, bool notifyListeners)
  419. {
  420. const float bOldTime = m_pAnimTrack->GetKeyTime(index);
  421. m_pAnimTrack->SetKeyTime(index, time);
  422. if (notifyListeners && (bOldTime != time))
  423. {
  424. // The keys were just make invalid by the above SetKeyTime(), so sort them now
  425. // to make sure they are ready to be used. Only do this when notifyListeners
  426. // is set so client callers can batch up a bunch of SetKeyTime calls if desired.
  427. m_pAnimTrack->SortKeys();
  428. m_pTrackAnimNode->GetSequence()->OnKeysChanged();
  429. }
  430. }
  431. float CTrackViewTrack::GetKeyTime(const int index) const
  432. {
  433. return m_pAnimTrack->GetKeyTime(index);
  434. }
  435. void CTrackViewTrack::RemoveKey(const int index)
  436. {
  437. m_pAnimTrack->RemoveKey(index);
  438. m_pTrackAnimNode->GetSequence()->OnKeysChanged();
  439. }
  440. int CTrackViewTrack::CloneKey(const int index)
  441. {
  442. int newIndex = m_pAnimTrack->CloneKey(index);
  443. m_pTrackAnimNode->GetSequence()->OnKeysChanged();
  444. return newIndex;
  445. }
  446. void CTrackViewTrack::SelectKeys(const bool bSelected)
  447. {
  448. m_pTrackAnimNode->GetSequence()->QueueNotifications();
  449. if (!m_bIsCompoundTrack)
  450. {
  451. unsigned int keyCount = GetKeyCount();
  452. for (unsigned int i = 0; i < keyCount; ++i)
  453. {
  454. m_pAnimTrack->SelectKey(i, bSelected);
  455. m_pTrackAnimNode->GetSequence()->OnKeySelectionChanged();
  456. }
  457. }
  458. else
  459. {
  460. // Affect sub tracks
  461. unsigned int childCount = GetChildCount();
  462. for (unsigned int childIndex = 0; childIndex < childCount; ++childIndex)
  463. {
  464. CTrackViewTrack* pChildTrack = static_cast<CTrackViewTrack*>(GetChild(childIndex));
  465. pChildTrack->SelectKeys(bSelected);
  466. m_pTrackAnimNode->GetSequence()->OnKeySelectionChanged();
  467. }
  468. }
  469. m_pTrackAnimNode->GetSequence()->SubmitPendingNotifications();
  470. }
  471. bool CTrackViewTrack::IsKeySelected(unsigned int keyIndex) const
  472. {
  473. if (m_pAnimTrack)
  474. {
  475. return m_pAnimTrack->IsKeySelected(keyIndex);
  476. }
  477. return false;
  478. }
  479. void CTrackViewTrack::SetSortMarkerKey(unsigned int keyIndex, bool enabled)
  480. {
  481. if (m_pAnimTrack)
  482. {
  483. return m_pAnimTrack->SetSortMarkerKey(keyIndex, enabled);
  484. }
  485. }
  486. bool CTrackViewTrack::IsSortMarkerKey(unsigned int keyIndex) const
  487. {
  488. if (m_pAnimTrack)
  489. {
  490. return m_pAnimTrack->IsSortMarkerKey(keyIndex);
  491. }
  492. return false;
  493. }
  494. CTrackViewKeyHandle CTrackViewTrack::GetSubTrackKeyHandle(unsigned int index) const
  495. {
  496. // Return handle to sub track key
  497. unsigned int childCount = GetChildCount();
  498. for (unsigned int childIndex = 0; childIndex < childCount; ++childIndex)
  499. {
  500. CTrackViewTrack* pChildTrack = static_cast<CTrackViewTrack*>(GetChild(childIndex));
  501. const unsigned int childKeyCount = pChildTrack->GetKeyCount();
  502. if (index < childKeyCount)
  503. {
  504. return pChildTrack->GetKey(index);
  505. }
  506. index -= childKeyCount;
  507. }
  508. return CTrackViewKeyHandle();
  509. }
  510. void CTrackViewTrack::SetAnimationLayerIndex(const int index)
  511. {
  512. if (m_pAnimTrack)
  513. {
  514. m_pAnimTrack->SetAnimationLayerIndex(index);
  515. }
  516. }
  517. int CTrackViewTrack::GetAnimationLayerIndex() const
  518. {
  519. return m_pAnimTrack->GetAnimationLayerIndex();
  520. }
  521. void CTrackViewTrack::OnStartPlayInEditor()
  522. {
  523. // remap any AZ::EntityId's used in tracks
  524. if (m_pAnimTrack)
  525. {
  526. // OnStopPlayInEditor clears this as well, but we clear it here in case OnStartPlayInEditor() is called multiple times before OnStopPlayInEditor()
  527. m_paramTypeToStashedEntityIdMap.clear();
  528. CAnimParamType trackParamType = m_pAnimTrack->GetParameterType();
  529. const AnimParamType paramType = trackParamType.GetType();
  530. if (paramType == AnimParamType::Camera || paramType == AnimParamType::Sequence)
  531. {
  532. ISelectKey selectKey;
  533. ISequenceKey sequenceKey;
  534. IKey* key = nullptr;
  535. for (int i = 0; i < m_pAnimTrack->GetNumKeys(); i++)
  536. {
  537. AZ::EntityId entityIdToRemap;
  538. if (paramType == AnimParamType::Camera)
  539. {
  540. m_pAnimTrack->GetKey(i, &selectKey);
  541. entityIdToRemap = selectKey.cameraAzEntityId;
  542. key = &selectKey;
  543. }
  544. else if (paramType == AnimParamType::Sequence)
  545. {
  546. m_pAnimTrack->GetKey(i, &sequenceKey);
  547. entityIdToRemap = sequenceKey.sequenceEntityId;
  548. key = &sequenceKey;
  549. }
  550. // stash the entity Id for restore in OnStopPlayInEditor
  551. m_paramTypeToStashedEntityIdMap[trackParamType].push_back(entityIdToRemap);
  552. if (entityIdToRemap.IsValid())
  553. {
  554. AZ::EntityId remappedId;
  555. AzToolsFramework::EditorEntityContextRequestBus::Broadcast(&AzToolsFramework::EditorEntityContextRequestBus::Events::MapEditorIdToRuntimeId, entityIdToRemap, remappedId);
  556. // remap
  557. if (paramType == AnimParamType::Camera)
  558. {
  559. selectKey.cameraAzEntityId = remappedId;
  560. }
  561. else if (paramType == AnimParamType::Sequence)
  562. {
  563. sequenceKey.sequenceEntityId = remappedId;
  564. }
  565. m_pAnimTrack->SetKey(i, key);
  566. }
  567. }
  568. }
  569. }
  570. }
  571. void CTrackViewTrack::OnStopPlayInEditor()
  572. {
  573. // restore any AZ::EntityId's remapped in OnStartPlayInEditor
  574. if (m_pAnimTrack && m_paramTypeToStashedEntityIdMap.size())
  575. {
  576. CAnimParamType trackParamType = m_pAnimTrack->GetParameterType();
  577. const AnimParamType paramType = trackParamType.GetType();
  578. if (paramType == AnimParamType::Camera || paramType == AnimParamType::Sequence)
  579. {
  580. for (int i = 0; i < m_pAnimTrack->GetNumKeys(); i++)
  581. {
  582. ISelectKey selectKey;
  583. ISequenceKey sequenceKey;
  584. IKey* key = nullptr;
  585. // restore entityIds
  586. if (paramType == AnimParamType::Camera)
  587. {
  588. m_pAnimTrack->GetKey(i, &selectKey);
  589. selectKey.cameraAzEntityId = m_paramTypeToStashedEntityIdMap[trackParamType][i];
  590. key = &selectKey;
  591. }
  592. else if (paramType == AnimParamType::Sequence)
  593. {
  594. m_pAnimTrack->GetKey(i, &sequenceKey);
  595. sequenceKey.sequenceEntityId = m_paramTypeToStashedEntityIdMap[trackParamType][i];
  596. key = &sequenceKey;
  597. }
  598. m_pAnimTrack->SetKey(i, key);
  599. }
  600. }
  601. // clear the StashedEntityIdMap now that we've consumed it
  602. m_paramTypeToStashedEntityIdMap.clear();
  603. }
  604. }
  605. void CTrackViewTrack::CopyKeysToClipboard(XmlNodeRef& xmlNode, const bool bOnlySelectedKeys, const bool bOnlyFromSelectedTracks)
  606. {
  607. if (bOnlyFromSelectedTracks && !IsSelected())
  608. {
  609. return;
  610. }
  611. if (GetKeyCount() == 0)
  612. {
  613. return;
  614. }
  615. if (bOnlySelectedKeys)
  616. {
  617. CTrackViewKeyBundle keyBundle = GetSelectedKeys();
  618. if (keyBundle.GetKeyCount() == 0)
  619. {
  620. return;
  621. }
  622. }
  623. XmlNodeRef childNode = xmlNode->newChild("Track");
  624. childNode->setAttr("name", GetName().c_str());
  625. GetParameterType().SaveToXml(childNode);
  626. childNode->setAttr("valueType", static_cast<int>(GetValueType()));
  627. m_pAnimTrack->SerializeSelection(childNode, false, bOnlySelectedKeys);
  628. }
  629. void CTrackViewTrack::PasteKeys(XmlNodeRef xmlNode, const float timeOffset)
  630. {
  631. CTrackViewSequence* sequence = GetSequence();
  632. AZ_Assert(sequence, "Expected sequence not to be null.");
  633. AzToolsFramework::ScopedUndoBatch undoBatch("Paste Keys");
  634. m_pAnimTrack->SerializeSelection(xmlNode, true, true, timeOffset);
  635. undoBatch.MarkEntityDirty(sequence->GetSequenceComponentEntityId());
  636. }