AnimTrack.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  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. #ifndef CRYINCLUDE_CRYMOVIE_ANIMTRACK_H
  9. #define CRYINCLUDE_CRYMOVIE_ANIMTRACK_H
  10. #pragma once
  11. //forward declarations.
  12. #include <IMovieSystem.h>
  13. /** General templated track for event type keys.
  14. KeyType class must be derived from IKey.
  15. */
  16. template <class KeyType>
  17. class TAnimTrack
  18. : public IAnimTrack
  19. {
  20. public:
  21. AZ_CLASS_ALLOCATOR(TAnimTrack, AZ::SystemAllocator);
  22. AZ_RTTI((TAnimTrack, "{D6E0F0E3-8843-46F0-8484-7B6E130409AE}", KeyType), IAnimTrack);
  23. TAnimTrack();
  24. EAnimCurveType GetCurveType() override { return eAnimCurveType_Unknown; };
  25. AnimValueType GetValueType() override { return kAnimValueUnknown; }
  26. void SetNode(IAnimNode* node) override { m_node = node; }
  27. // Return Animation Node that owns this Track.
  28. IAnimNode* GetNode() override { return m_node; }
  29. int GetSubTrackCount() const override { return 0; };
  30. IAnimTrack* GetSubTrack([[maybe_unused]] int nIndex) const override { return 0; };
  31. AZStd::string GetSubTrackName([[maybe_unused]] int nIndex) const override { return AZStd::string(); };
  32. void SetSubTrackName([[maybe_unused]] int nIndex, [[maybe_unused]] const char* name) override { assert(0); }
  33. const CAnimParamType& GetParameterType() const override { return m_nParamType; };
  34. void SetParameterType(CAnimParamType type) override { m_nParamType = type; };
  35. //////////////////////////////////////////////////////////////////////////
  36. // for intrusive_ptr support
  37. void add_ref() override;
  38. void release() override;
  39. //////////////////////////////////////////////////////////////////////////
  40. bool IsKeySelected(int key) const override
  41. {
  42. AZ_Assert(key >= 0 && key < (int)m_keys.size(), "Key index is out of range");
  43. if (m_keys[key].flags & AKEY_SELECTED)
  44. {
  45. return true;
  46. }
  47. return false;
  48. }
  49. void SelectKey(int key, bool select) override
  50. {
  51. AZ_Assert(key >= 0 && key < (int)m_keys.size(), "Key index is out of range");
  52. if (select)
  53. {
  54. m_keys[key].flags |= AKEY_SELECTED;
  55. }
  56. else
  57. {
  58. m_keys[key].flags &= ~AKEY_SELECTED;
  59. }
  60. }
  61. bool IsSortMarkerKey(unsigned int key) const override
  62. {
  63. AZ_Assert(key < m_keys.size(), "key index is out of range");
  64. if (m_keys[key].flags & AKEY_SORT_MARKER)
  65. {
  66. return true;
  67. }
  68. return false;
  69. }
  70. void SetSortMarkerKey(unsigned int key, bool enabled) override
  71. {
  72. AZ_Assert(key < m_keys.size(), "key index is out of range");
  73. if (enabled)
  74. {
  75. m_keys[key].flags |= AKEY_SORT_MARKER;
  76. }
  77. else
  78. {
  79. m_keys[key].flags &= ~AKEY_SORT_MARKER;
  80. }
  81. }
  82. //! Return number of keys in track.
  83. int GetNumKeys() const override { return static_cast<int>(m_keys.size()); };
  84. //! Return true if keys exists in this track
  85. bool HasKeys() const override { return !m_keys.empty(); }
  86. //! Set number of keys in track.
  87. //! If needed adds empty keys at end or remove keys from end.
  88. void SetNumKeys(int numKeys) override { m_keys.resize(numKeys); };
  89. //! Remove specified key.
  90. void RemoveKey(int num) override;
  91. int CreateKey(float time) override;
  92. int CloneKey(int fromKey) override;
  93. int CopyKey(IAnimTrack* pFromTrack, int nFromKey) override;
  94. //! Get key at specified location.
  95. //! @param key Must be valid pointer to compatible key structure, to be filled with specified key location.
  96. void GetKey(int index, IKey* key) const override;
  97. //! Get time of specified key.
  98. //! @return key time.
  99. float GetKeyTime(int index) const override;
  100. //! Find key at given time.
  101. //! @return Index of found key, or -1 if key with this time not found.
  102. int FindKey(float time) override;
  103. //! Get flags of specified key.
  104. //! @return key time.
  105. int GetKeyFlags(int index) override;
  106. //! Set key at specified location.
  107. //! @param key Must be valid pointer to compatible key structure.
  108. void SetKey(int index, IKey* key) override;
  109. //! Set time of specified key.
  110. void SetKeyTime(int index, float time) override;
  111. //! Set flags of specified key.
  112. void SetKeyFlags(int index, int flags) override;
  113. //! Sort keys in track (after time of keys was modified).
  114. void SortKeys() override;
  115. //! Get track flags.
  116. int GetFlags() override { return m_flags; };
  117. //! Check if track is masked
  118. bool IsMasked([[maybe_unused]] const uint32 mask) const override { return false; }
  119. //! Set track flags.
  120. void SetFlags(int flags) override
  121. {
  122. m_flags = flags;
  123. }
  124. //////////////////////////////////////////////////////////////////////////
  125. // Get track value at specified time.
  126. // Interpolates keys if needed.
  127. //////////////////////////////////////////////////////////////////////////
  128. void GetValue([[maybe_unused]] float time, [[maybe_unused]] float& value, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); };
  129. void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec3& value, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); };
  130. void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec4& value, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); };
  131. void GetValue([[maybe_unused]] float time, [[maybe_unused]] Quat& value) override { assert(0); };
  132. void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) override { assert(0); };
  133. void GetValue([[maybe_unused]] float time, [[maybe_unused]] Maestro::AssetBlends<AZ::Data::AssetData>& value) override { assert(0); }
  134. //////////////////////////////////////////////////////////////////////////
  135. // Set track value at specified time.
  136. // Adds new keys if required.
  137. //////////////////////////////////////////////////////////////////////////
  138. void SetValue([[maybe_unused]] float time, [[maybe_unused]] const float& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); };
  139. void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec3& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); };
  140. void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec4& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); };
  141. void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Quat& value, [[maybe_unused]] bool bDefault = false) override { assert(0); };
  142. void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) override { assert(0); };
  143. void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Maestro::AssetBlends<AZ::Data::AssetData>& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }
  144. void OffsetKeyPosition([[maybe_unused]] const AZ::Vector3& value) override { assert(0); };
  145. void UpdateKeyDataAfterParentChanged([[maybe_unused]] const AZ::Transform& oldParentWorldTM, [[maybe_unused]] const AZ::Transform& newParentWorldTM) override { assert(0); };
  146. /** Assign active time range for this track.
  147. */
  148. void SetTimeRange(const Range& timeRange) override { m_timeRange = timeRange; };
  149. /** Serialize this animation track to XML.
  150. Do not override this method, prefer to override SerializeKey.
  151. */
  152. bool Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true) override;
  153. bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected = false, float fTimeOffset = 0) override;
  154. /** Serialize single key of this track.
  155. Override this in derived classes.
  156. Do not save time attribute, it is already saved in Serialize of the track.
  157. */
  158. virtual void SerializeKey(KeyType& key, XmlNodeRef& keyNode, bool bLoading) = 0;
  159. //////////////////////////////////////////////////////////////////////////
  160. //////////////////////////////////////////////////////////////////////////
  161. /** Get last key before specified time.
  162. @return Index of key, or -1 if such key not exist.
  163. */
  164. int GetActiveKey(float time, KeyType* key);
  165. #ifdef MOVIESYSTEM_SUPPORT_EDITING
  166. ColorB GetCustomColor() const override
  167. { return m_customColor; }
  168. void SetCustomColor(ColorB color) override
  169. {
  170. m_customColor = color;
  171. m_bCustomColorSet = true;
  172. }
  173. bool HasCustomColor() const override
  174. { return m_bCustomColorSet; }
  175. void ClearCustomColor() override
  176. { m_bCustomColorSet = false; }
  177. #endif
  178. void GetKeyValueRange(float& fMin, float& fMax) const override { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; };
  179. void SetKeyValueRange(float fMin, float fMax) override{ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; };
  180. void SetMultiplier(float trackMultiplier) override
  181. {
  182. m_trackMultiplier = trackMultiplier;
  183. }
  184. void SetExpanded([[maybe_unused]] bool expanded) override
  185. {
  186. AZ_Assert(false, "Not expected to be used.");
  187. }
  188. bool GetExpanded() const override
  189. {
  190. return false;
  191. }
  192. unsigned int GetId() const override
  193. {
  194. return m_id;
  195. }
  196. void SetId(unsigned int id) override
  197. {
  198. m_id = id;
  199. }
  200. static void Reflect([[maybe_unused]] AZ::ReflectContext* context) {}
  201. protected:
  202. void CheckValid()
  203. {
  204. if (m_bModified)
  205. {
  206. SortKeys();
  207. }
  208. };
  209. void Invalidate() { m_bModified = -1; };
  210. int m_refCount;
  211. typedef AZStd::vector<KeyType> Keys;
  212. Keys m_keys;
  213. Range m_timeRange;
  214. CAnimParamType m_nParamType;
  215. int m_currKey : 31;
  216. int m_bModified : 1;
  217. float m_lastTime;
  218. int m_flags;
  219. #ifdef MOVIESYSTEM_SUPPORT_EDITING
  220. ColorB m_customColor;
  221. bool m_bCustomColorSet;
  222. #endif
  223. float m_fMinKeyValue;
  224. float m_fMaxKeyValue;
  225. IAnimNode* m_node;
  226. float m_trackMultiplier;
  227. unsigned int m_id = 0;
  228. };
  229. //////////////////////////////////////////////////////////////////////////
  230. template <class KeyType>
  231. inline void TAnimTrack<KeyType>::add_ref()
  232. {
  233. ++m_refCount;
  234. }
  235. //////////////////////////////////////////////////////////////////////////
  236. template <class KeyType>
  237. inline void TAnimTrack<KeyType>::release()
  238. {
  239. if (--m_refCount <= 0)
  240. {
  241. delete this;
  242. }
  243. }
  244. //////////////////////////////////////////////////////////////////////////
  245. template <class KeyType>
  246. inline TAnimTrack<KeyType>::TAnimTrack()
  247. : m_refCount(0)
  248. {
  249. m_currKey = 0;
  250. m_flags = 0;
  251. m_lastTime = -1;
  252. m_bModified = 0;
  253. m_node = nullptr;
  254. #ifdef MOVIESYSTEM_SUPPORT_EDITING
  255. m_bCustomColorSet = false;
  256. #endif
  257. }
  258. //////////////////////////////////////////////////////////////////////////
  259. template <class KeyType>
  260. inline void TAnimTrack<KeyType>::RemoveKey(int index)
  261. {
  262. AZ_Assert(index >= 0 && index < (int)m_keys.size(), "Key index is out of range");
  263. m_keys.erase(m_keys.begin() + index);
  264. Invalidate();
  265. }
  266. //////////////////////////////////////////////////////////////////////////
  267. template <class KeyType>
  268. inline void TAnimTrack<KeyType>::GetKey(int index, IKey* key) const
  269. {
  270. AZ_Assert(index >= 0 && index < (int)m_keys.size(), "Key index is out of range");
  271. AZ_Assert(key != 0, "Key cannot be null!");
  272. *(KeyType*)key = m_keys[index];
  273. }
  274. //////////////////////////////////////////////////////////////////////////
  275. template <class KeyType>
  276. inline void TAnimTrack<KeyType>::SetKey(int index, IKey* key)
  277. {
  278. AZ_Assert(index >= 0 && index < (int)m_keys.size(), "Key index is out of range");
  279. AZ_Assert(key != 0, "Key cannot be null!");
  280. m_keys[index] = *(KeyType*)key;
  281. Invalidate();
  282. }
  283. //////////////////////////////////////////////////////////////////////////
  284. template <class KeyType>
  285. inline float TAnimTrack<KeyType>::GetKeyTime(int index) const
  286. {
  287. AZ_Assert(index >= 0 && index < (int)m_keys.size(), "Key index is out of range");
  288. return m_keys[index].time;
  289. }
  290. //////////////////////////////////////////////////////////////////////////
  291. template <class KeyType>
  292. inline void TAnimTrack<KeyType>::SetKeyTime(int index, float time)
  293. {
  294. AZ_Assert(index >= 0 && index < (int)m_keys.size(), "Key index is out of range");
  295. m_keys[index].time = time;
  296. Invalidate();
  297. }
  298. //////////////////////////////////////////////////////////////////////////
  299. template <class KeyType>
  300. inline int TAnimTrack<KeyType>::FindKey(float time)
  301. {
  302. for (int i = 0; i < (int)m_keys.size(); i++)
  303. {
  304. if (m_keys[i].time == time)
  305. {
  306. return i;
  307. }
  308. }
  309. return -1;
  310. }
  311. //////////////////////////////////////////////////////////////////////////
  312. template <class KeyType>
  313. inline int TAnimTrack<KeyType>::GetKeyFlags(int index)
  314. {
  315. AZ_Assert(index >= 0 && index < (int)m_keys.size(), "Key index is out of range");
  316. return m_keys[index].flags;
  317. }
  318. //////////////////////////////////////////////////////////////////////////
  319. template <class KeyType>
  320. inline void TAnimTrack<KeyType>::SetKeyFlags(int index, int flags)
  321. {
  322. AZ_Assert(index >= 0 && index < (int)m_keys.size(), "Key index is out of range");
  323. m_keys[index].flags = flags;
  324. Invalidate();
  325. }
  326. //////////////////////////////////////////////////////////////////////////
  327. template <class KeyType>
  328. inline void TAnimTrack<KeyType>::SortKeys()
  329. {
  330. std::sort(m_keys.begin(), m_keys.end());
  331. m_bModified = 0;
  332. }
  333. //////////////////////////////////////////////////////////////////////////
  334. /// @deprecated Serialization for Sequence data in Component Entity Sequences now occurs through AZ::SerializeContext and the Sequence Component
  335. template <class KeyType>
  336. inline bool TAnimTrack<KeyType>::Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks)
  337. {
  338. if (bLoading)
  339. {
  340. int num = xmlNode->getChildCount();
  341. Range timeRange;
  342. int flags = m_flags;
  343. xmlNode->getAttr("Flags", flags);
  344. xmlNode->getAttr("StartTime", timeRange.start);
  345. xmlNode->getAttr("EndTime", timeRange.end);
  346. SetFlags(flags);
  347. SetTimeRange(timeRange);
  348. #ifdef MOVIESYSTEM_SUPPORT_EDITING
  349. xmlNode->getAttr("HasCustomColor", m_bCustomColorSet);
  350. if (m_bCustomColorSet)
  351. {
  352. unsigned int abgr;
  353. xmlNode->getAttr("CustomColor", abgr);
  354. m_customColor = ColorB(abgr);
  355. }
  356. #endif
  357. SetNumKeys(num);
  358. for (int i = 0; i < num; i++)
  359. {
  360. XmlNodeRef keyNode = xmlNode->getChild(i);
  361. keyNode->getAttr("time", m_keys[i].time);
  362. SerializeKey(m_keys[i], keyNode, bLoading);
  363. }
  364. xmlNode->getAttr("Id", m_id);
  365. if ((!num) && (!bLoadEmptyTracks))
  366. {
  367. return false;
  368. }
  369. }
  370. else
  371. {
  372. int num = GetNumKeys();
  373. CheckValid();
  374. xmlNode->setAttr("Flags", GetFlags());
  375. xmlNode->setAttr("StartTime", m_timeRange.start);
  376. xmlNode->setAttr("EndTime", m_timeRange.end);
  377. #ifdef MOVIESYSTEM_SUPPORT_EDITING
  378. xmlNode->setAttr("HasCustomColor", m_bCustomColorSet);
  379. if (m_bCustomColorSet)
  380. {
  381. xmlNode->setAttr("CustomColor", m_customColor.pack_abgr8888());
  382. }
  383. #endif
  384. for (int i = 0; i < num; i++)
  385. {
  386. XmlNodeRef keyNode = xmlNode->newChild("Key");
  387. keyNode->setAttr("time", m_keys[i].time);
  388. SerializeKey(m_keys[i], keyNode, bLoading);
  389. }
  390. xmlNode->setAttr("Id", m_id);
  391. }
  392. return true;
  393. }
  394. //////////////////////////////////////////////////////////////////////////
  395. template <class KeyType>
  396. inline bool TAnimTrack<KeyType>::SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected, float fTimeOffset)
  397. {
  398. if (bLoading)
  399. {
  400. int numCur = GetNumKeys();
  401. int num = xmlNode->getChildCount();
  402. unsigned int type;
  403. xmlNode->getAttr("TrackType", type);
  404. if (type != GetCurveType())
  405. {
  406. return false;
  407. }
  408. SetNumKeys(num + numCur);
  409. for (int i = 0; i < num; i++)
  410. {
  411. XmlNodeRef keyNode = xmlNode->getChild(i);
  412. keyNode->getAttr("time", m_keys[i + numCur].time);
  413. m_keys[i + numCur].time += fTimeOffset;
  414. SerializeKey(m_keys[i + numCur], keyNode, bLoading);
  415. if (bCopySelected)
  416. {
  417. m_keys[i + numCur].flags |= AKEY_SELECTED;
  418. }
  419. }
  420. SortKeys();
  421. }
  422. else
  423. {
  424. int num = GetNumKeys();
  425. xmlNode->setAttr("TrackType", GetCurveType());
  426. //CheckValid();
  427. for (int i = 0; i < num; i++)
  428. {
  429. if (!bCopySelected || GetKeyFlags(i) & AKEY_SELECTED)
  430. {
  431. XmlNodeRef keyNode = xmlNode->newChild("Key");
  432. keyNode->setAttr("time", m_keys[i].time);
  433. SerializeKey(m_keys[i], keyNode, bLoading);
  434. }
  435. }
  436. }
  437. return true;
  438. }
  439. //////////////////////////////////////////////////////////////////////////
  440. template <class KeyType>
  441. inline int TAnimTrack<KeyType>::CreateKey(float time)
  442. {
  443. KeyType key, akey;
  444. int nkey = GetNumKeys();
  445. SetNumKeys(nkey + 1);
  446. key.time = time;
  447. SetKey(nkey, &key);
  448. return nkey;
  449. }
  450. //////////////////////////////////////////////////////////////////////////
  451. template <class KeyType>
  452. inline int TAnimTrack<KeyType>::CloneKey(int fromKey)
  453. {
  454. KeyType key;
  455. GetKey(fromKey, &key);
  456. int nkey = GetNumKeys();
  457. SetNumKeys(nkey + 1);
  458. SetKey(nkey, &key);
  459. return nkey;
  460. }
  461. //////////////////////////////////////////////////////////////////////////
  462. template <class KeyType>
  463. inline int TAnimTrack<KeyType>::CopyKey(IAnimTrack* pFromTrack, int nFromKey)
  464. {
  465. KeyType key;
  466. pFromTrack->GetKey(nFromKey, &key);
  467. int nkey = GetNumKeys();
  468. SetNumKeys(nkey + 1);
  469. SetKey(nkey, &key);
  470. return nkey;
  471. }
  472. //////////////////////////////////////////////////////////////////////////
  473. template <class KeyType>
  474. inline int TAnimTrack<KeyType>::GetActiveKey(float time, KeyType* key)
  475. {
  476. CheckValid();
  477. if (key == NULL)
  478. {
  479. return -1;
  480. }
  481. int nkeys = static_cast<int>(m_keys.size());
  482. if (nkeys == 0)
  483. {
  484. m_lastTime = time;
  485. m_currKey = -1;
  486. return m_currKey;
  487. }
  488. bool bTimeWrap = false;
  489. if ((m_flags & eAnimTrackFlags_Cycle) || (m_flags & eAnimTrackFlags_Loop))
  490. {
  491. // Warp time.
  492. const char* desc = 0;
  493. float duration = 0;
  494. GetKeyInfo(nkeys - 1, desc, duration);
  495. float endtime = GetKeyTime(nkeys - 1) + duration;
  496. time = fmod_tpl(time, endtime);
  497. if (time < m_lastTime)
  498. {
  499. // Time is wrapped.
  500. bTimeWrap = true;
  501. }
  502. }
  503. m_lastTime = time;
  504. // Time is before first key.
  505. if (m_keys[0].time > time)
  506. {
  507. if (bTimeWrap)
  508. {
  509. // If time wrapped, active key is last key.
  510. m_currKey = nkeys - 1;
  511. *key = m_keys[m_currKey];
  512. }
  513. else
  514. {
  515. m_currKey = -1;
  516. }
  517. return m_currKey;
  518. }
  519. if (m_currKey < 0)
  520. {
  521. m_currKey = 0;
  522. }
  523. // Start from current key.
  524. int i;
  525. for (i = m_currKey; i < nkeys; i++)
  526. {
  527. if (time >= m_keys[i].time)
  528. {
  529. if ((i >= nkeys - 1) || (time < m_keys[i + 1].time))
  530. {
  531. m_currKey = i;
  532. *key = m_keys[m_currKey];
  533. return m_currKey;
  534. }
  535. }
  536. else
  537. {
  538. break;
  539. }
  540. }
  541. // Start from begining.
  542. for (i = 0; i < nkeys; i++)
  543. {
  544. if (time >= m_keys[i].time)
  545. {
  546. if ((i >= nkeys - 1) || (time < m_keys[i + 1].time))
  547. {
  548. m_currKey = i;
  549. *key = m_keys[m_currKey];
  550. return m_currKey;
  551. }
  552. }
  553. else
  554. {
  555. break;
  556. }
  557. }
  558. m_currKey = -1;
  559. return m_currKey;
  560. }
  561. #endif // CRYINCLUDE_CRYMOVIE_ANIMTRACK_H