AnimSplineTrack_Vec2Specialization.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. // Description : 'Vec2' explicit specialization of the class template
  9. // TAnimSplineTrack
  10. // Notice : Should be included in AnimSplineTrack h only
  11. #include "AnimSplineTrack.h"
  12. #include "2DSpline.h"
  13. #include <AzCore/Serialization/EditContext.h>
  14. namespace spline
  15. {
  16. template<>
  17. void SplineKey<Vec2>::Reflect(AZ::ReflectContext* context);
  18. }
  19. template <>
  20. TAnimSplineTrack<Vec2>::TAnimSplineTrack()
  21. : m_refCount(0)
  22. {
  23. AllocSpline();
  24. m_flags = 0;
  25. m_defaultValue = Vec2(0, 0);
  26. m_fMinKeyValue = 0.0f;
  27. m_fMaxKeyValue = 0.0f;
  28. m_bCustomColorSet = false;
  29. m_node = nullptr;
  30. m_trackMultiplier = 1.0f;
  31. }
  32. template <>
  33. void TAnimSplineTrack<Vec2>::add_ref()
  34. {
  35. ++m_refCount;
  36. }
  37. //////////////////////////////////////////////////////////////////////////
  38. template <>
  39. void TAnimSplineTrack<Vec2>::release()
  40. {
  41. if (--m_refCount <= 0)
  42. {
  43. delete this;
  44. }
  45. }
  46. template <>
  47. void TAnimSplineTrack<Vec2>::GetValue(float time, float& value, bool applyMultiplier)
  48. {
  49. if (GetNumKeys() == 0)
  50. {
  51. value = m_defaultValue.y;
  52. }
  53. else
  54. {
  55. Spline::ValueType tmp;
  56. m_spline->Interpolate(time, tmp);
  57. value = tmp[0];
  58. }
  59. if (applyMultiplier && m_trackMultiplier != 1.0f)
  60. {
  61. value /= m_trackMultiplier;
  62. }
  63. }
  64. template <>
  65. EAnimCurveType TAnimSplineTrack<Vec2>::GetCurveType() { return eAnimCurveType_BezierFloat; }
  66. template <>
  67. AnimValueType TAnimSplineTrack<Vec2>::GetValueType() { return kAnimValueDefault; }
  68. template <>
  69. void TAnimSplineTrack<Vec2>::SetValue(float time, const float& value, bool bDefault, bool applyMultiplier)
  70. {
  71. if (!bDefault)
  72. {
  73. I2DBezierKey key;
  74. if (applyMultiplier && m_trackMultiplier != 1.0f)
  75. {
  76. key.value = Vec2(time, value * m_trackMultiplier);
  77. }
  78. else
  79. {
  80. key.value = Vec2(time, value);
  81. }
  82. SetKeyAtTime(time, &key);
  83. }
  84. else
  85. {
  86. if (applyMultiplier && m_trackMultiplier != 1.0f)
  87. {
  88. m_defaultValue = Vec2(time, value * m_trackMultiplier);
  89. }
  90. else
  91. {
  92. m_defaultValue = Vec2(time, value);
  93. }
  94. }
  95. }
  96. template <>
  97. void TAnimSplineTrack<Vec2>::GetKey(int index, IKey* key) const
  98. {
  99. assert(index >= 0 && index < GetNumKeys());
  100. assert(key != 0);
  101. Spline::key_type& k = m_spline->key(index);
  102. I2DBezierKey* bezierkey = (I2DBezierKey*)key;
  103. bezierkey->time = k.time;
  104. bezierkey->flags = k.flags;
  105. bezierkey->value = k.value;
  106. }
  107. template <>
  108. void TAnimSplineTrack<Vec2>::SetKey(int index, IKey* key)
  109. {
  110. assert(index >= 0 && index < GetNumKeys());
  111. assert(key != 0);
  112. Spline::key_type& k = m_spline->key(index);
  113. I2DBezierKey* bezierkey = (I2DBezierKey*)key;
  114. k.time = bezierkey->time;
  115. k.flags = bezierkey->flags;
  116. k.value = bezierkey->value;
  117. UpdateTrackValueRange(k.value.y);
  118. Invalidate();
  119. }
  120. //! Create key at given time, and return its index.
  121. template <>
  122. int TAnimSplineTrack<Vec2>::CreateKey(float time)
  123. {
  124. float value;
  125. int nkey = GetNumKeys();
  126. if (nkey > 0)
  127. {
  128. GetValue(time, value);
  129. }
  130. else
  131. {
  132. value = m_defaultValue.y;
  133. }
  134. UpdateTrackValueRange(value);
  135. Spline::ValueType tmp;
  136. tmp[0] = value;
  137. tmp[1] = 0;
  138. return m_spline->InsertKey(time, tmp);
  139. }
  140. template <>
  141. int TAnimSplineTrack<Vec2>::CopyKey(IAnimTrack* pFromTrack, int nFromKey)
  142. {
  143. // This small time offset is applied to prevent the generation of singular tangents.
  144. float timeOffset = 0.01f;
  145. I2DBezierKey key;
  146. pFromTrack->GetKey(nFromKey, &key);
  147. float t = key.time + timeOffset;
  148. int newIndex = CreateKey(t);
  149. key.time = key.value.x = t;
  150. SetKey(newIndex, &key);
  151. return newIndex;
  152. }
  153. /// @deprecated Serialization for Sequence data in Component Entity Sequences now occurs through AZ::SerializeContext and the Sequence Component
  154. template <>
  155. bool TAnimSplineTrack<Vec2>::Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks)
  156. {
  157. if (bLoading)
  158. {
  159. int num = xmlNode->getChildCount();
  160. int flags = m_flags;
  161. xmlNode->getAttr("Flags", flags);
  162. xmlNode->getAttr("defaultValue", m_defaultValue);
  163. SetFlags(flags);
  164. xmlNode->getAttr("HasCustomColor", m_bCustomColorSet);
  165. if (m_bCustomColorSet)
  166. {
  167. unsigned int abgr;
  168. xmlNode->getAttr("CustomColor", abgr);
  169. m_customColor = ColorB(abgr);
  170. }
  171. SetNumKeys(num);
  172. for (int i = 0; i < num; i++)
  173. {
  174. I2DBezierKey key; // Must be inside loop.
  175. XmlNodeRef keyNode = xmlNode->getChild(i);
  176. if (!keyNode->getAttr("time", key.time))
  177. {
  178. CryLog("[CRYMOVIE:TAnimSplineTrack<Vec2>::Serialize]Ill formed legacy track:missing time information.");
  179. return false;
  180. }
  181. if (!keyNode->getAttr("value", key.value))
  182. {
  183. CryLog("[CRYMOVIE:TAnimSplineTrack<Vec2>::Serialize]Ill formed legacy track:missing value information.");
  184. return false;
  185. }
  186. //assert(key.time == key.value.x);
  187. keyNode->getAttr("flags", key.flags);
  188. SetKey(i, &key);
  189. // In-/Out-tangent
  190. if (!keyNode->getAttr("ds", m_spline->key(i).ds))
  191. {
  192. CryLog("[CRYMOVIE:TAnimSplineTrack<Vec2>::Serialize]Ill formed legacy track:missing ds spline information.");
  193. return false;
  194. }
  195. if (!keyNode->getAttr("dd", m_spline->key(i).dd))
  196. {
  197. CryLog("[CRYMOVIE:TAnimSplineTrack<Vec2>::Serialize]Ill formed legacy track:dd spline information.");
  198. return false;
  199. }
  200. // now that tangents are loaded, compute the relative angle and size for later unified Tangent manipulations
  201. m_spline->key(i).ComputeThetaAndScale();
  202. }
  203. xmlNode->getAttr("Id", m_id);
  204. if ((!num) && (!bLoadEmptyTracks))
  205. {
  206. return false;
  207. }
  208. }
  209. else
  210. {
  211. int num = GetNumKeys();
  212. xmlNode->setAttr("Flags", GetFlags());
  213. xmlNode->setAttr("defaultValue", m_defaultValue);
  214. xmlNode->setAttr("HasCustomColor", m_bCustomColorSet);
  215. if (m_bCustomColorSet)
  216. {
  217. xmlNode->setAttr("CustomColor", m_customColor.pack_abgr8888());
  218. }
  219. I2DBezierKey key;
  220. for (int i = 0; i < num; i++)
  221. {
  222. GetKey(i, &key);
  223. XmlNodeRef keyNode = xmlNode->newChild("Key");
  224. assert(key.time == key.value.x);
  225. keyNode->setAttr("time", key.time);
  226. keyNode->setAttr("value", key.value);
  227. int flags = key.flags;
  228. // Just save the in/out/unify mask part. Others are for editing convenience.
  229. flags &= (SPLINE_KEY_TANGENT_IN_MASK | SPLINE_KEY_TANGENT_OUT_MASK | SPLINE_KEY_TANGENT_UNIFY_MASK);
  230. if (flags != 0)
  231. {
  232. keyNode->setAttr("flags", flags);
  233. }
  234. // We also have to save in-/out-tangents, because TCB infos are not used for custom tangent keys.
  235. keyNode->setAttr("ds", m_spline->key(i).ds);
  236. keyNode->setAttr("dd", m_spline->key(i).dd);
  237. }
  238. xmlNode->setAttr("Id", m_id);
  239. }
  240. return true;
  241. }
  242. template <>
  243. bool TAnimSplineTrack<Vec2>::SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected, float fTimeOffset)
  244. {
  245. if (bLoading)
  246. {
  247. int numCur = GetNumKeys();
  248. int num = xmlNode->getChildCount();
  249. unsigned int type;
  250. xmlNode->getAttr("TrackType", type);
  251. if (type != GetCurveType())
  252. {
  253. return false;
  254. }
  255. SetNumKeys(num + numCur);
  256. for (int i = 0; i < num; i++)
  257. {
  258. I2DBezierKey key; // Must be inside loop.
  259. XmlNodeRef keyNode = xmlNode->getChild(i);
  260. keyNode->getAttr("time", key.time);
  261. keyNode->getAttr("value", key.value);
  262. assert(key.time == key.value.x);
  263. key.time += fTimeOffset;
  264. key.value.x += fTimeOffset;
  265. keyNode->getAttr("flags", key.flags);
  266. SetKey(i + numCur, &key);
  267. if (bCopySelected)
  268. {
  269. SelectKey(i + numCur, true);
  270. }
  271. // In-/Out-tangent
  272. keyNode->getAttr("ds", m_spline->key(i + numCur).ds);
  273. keyNode->getAttr("dd", m_spline->key(i + numCur).dd);
  274. }
  275. SortKeys();
  276. }
  277. else
  278. {
  279. int num = GetNumKeys();
  280. xmlNode->setAttr("TrackType", GetCurveType());
  281. I2DBezierKey key;
  282. for (int i = 0; i < num; i++)
  283. {
  284. GetKey(i, &key);
  285. assert(key.time == key.value.x);
  286. if (!bCopySelected || IsKeySelected(i))
  287. {
  288. XmlNodeRef keyNode = xmlNode->newChild("Key");
  289. keyNode->setAttr("time", key.time);
  290. keyNode->setAttr("value", key.value);
  291. int flags = key.flags;
  292. // Just save the in/out mask part. Others are for editing convenience.
  293. flags &= (SPLINE_KEY_TANGENT_IN_MASK | SPLINE_KEY_TANGENT_OUT_MASK);
  294. if (flags != 0)
  295. {
  296. keyNode->setAttr("flags", flags);
  297. }
  298. // We also have to save in-/out-tangents, because TCB infos are not used for custom tangent keys.
  299. keyNode->setAttr("ds", m_spline->key(i).ds);
  300. keyNode->setAttr("dd", m_spline->key(i).dd);
  301. }
  302. }
  303. }
  304. return true;
  305. }
  306. //////////////////////////////////////////////////////////////////////////
  307. template<>
  308. void TAnimSplineTrack<Vec2>::GetKeyInfo(int index, const char*& description, float& duration)
  309. {
  310. duration = 0;
  311. static char str[64];
  312. description = str;
  313. assert(index >= 0 && index < GetNumKeys());
  314. Spline::key_type& k = m_spline->key(index);
  315. sprintf_s(str, "%.2f", k.value.y);
  316. }
  317. namespace spline
  318. {
  319. using BezierSplineVec2 = BezierSpline<Vec2, SplineKeyEx<Vec2>>;
  320. using TSplineBezierBasisVec2 = TSpline<SplineKeyEx<Vec2>, BezierBasis>;
  321. template <>
  322. void TSplineBezierBasisVec2::Reflect(AZ::ReflectContext* context);
  323. //////////////////////////////////////////////////////////////////////////
  324. template <>
  325. void BezierSplineVec2::Reflect(AZ::ReflectContext* context);
  326. AZ_TYPE_INFO_SPECIALIZE(TrackSplineInterpolator<Vec2>, "{173AC8F0-FD63-4583-8D38-F43FE59F2209}");
  327. AZ_TYPE_INFO_SPECIALIZE(SplineKeyEx<Vec2>, "{96BCA307-A4D5-43A0-9985-08A29BCCCB30}");
  328. AZ_TYPE_INFO_SPECIALIZE(BezierSplineVec2, "{EE318F13-A608-4047-85B3-3D40745A19C7}");
  329. AZ_TYPE_INFO_SPECIALIZE(TSplineBezierBasisVec2, "{B638C840-C1D7-483A-B04E-B22DA539DB8D}");
  330. template<>
  331. void SplineKey<Vec2>::Reflect(AZ::ReflectContext* context)
  332. {
  333. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr)
  334. {
  335. serializeContext->Class<SplineKey<Vec2> >()
  336. ->Version(1)
  337. ->Field("time", &SplineKey<Vec2>::time)
  338. ->Field("flags", &SplineKey<Vec2>::flags)
  339. ->Field("value", &SplineKey<Vec2>::value)
  340. ->Field("ds", &SplineKey<Vec2>::ds)
  341. ->Field("dd", &SplineKey<Vec2>::dd);
  342. }
  343. }
  344. template<>
  345. void SplineKeyEx<Vec2>::Reflect(AZ::ReflectContext* context)
  346. {
  347. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr)
  348. {
  349. serializeContext->Class<SplineKeyEx<Vec2>, SplineKey<Vec2> >()
  350. ->Version(1);
  351. }
  352. }
  353. void TrackSplineInterpolator<Vec2>::Reflect(AZ::ReflectContext* context)
  354. {
  355. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr)
  356. {
  357. serializeContext->Class<TrackSplineInterpolator<Vec2>, spline::BezierSpline<Vec2, spline::SplineKeyEx<Vec2> > >()
  358. ->Version(1);
  359. }
  360. }
  361. template <>
  362. void TSplineBezierBasisVec2::Reflect(AZ::ReflectContext* context)
  363. {
  364. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr)
  365. {
  366. serializeContext->Class<TSplineBezierBasisVec2>()
  367. ->Version(1)
  368. ->Field("Keys", &BezierSplineVec2::m_keys);
  369. }
  370. }
  371. //////////////////////////////////////////////////////////////////////////
  372. template <>
  373. void BezierSplineVec2::Reflect(AZ::ReflectContext* context)
  374. {
  375. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr)
  376. {
  377. TSplineBezierBasisVec2::Reflect(serializeContext);
  378. serializeContext->Class<BezierSplineVec2, TSplineBezierBasisVec2>()
  379. ->Version(1);
  380. }
  381. }
  382. } // namespace spline
  383. //////////////////////////////////////////////////////////////////////////
  384. // When TAnimSplineTrack<Vec2> is deserialized, a spline instance
  385. // is first created in the TUiAnimSplineTrack<Vec2> constructor (via AllocSpline()),
  386. // then the pointer is overwritten when "Spline" field is deserialized.
  387. // To prevent a memory leak, m_spline is now an intrusive pointer, so that if/when
  388. // the "Spline" field is deserialized, the old object will be deleted.
  389. static bool TAnimSplineTrackVec2VersionConverter(AZ::SerializeContext& context,
  390. AZ::SerializeContext::DataElementNode& classElement)
  391. {
  392. bool result = true;
  393. if (classElement.GetVersion() < 5)
  394. {
  395. classElement.AddElement(context, "BaseClass1", azrtti_typeid<IAnimTrack>());
  396. if (classElement.GetVersion() == 1)
  397. {
  398. bool converted = false;
  399. int splineElementIdx = classElement.FindElement(AZ_CRC("Spline", 0x35f655e9));
  400. if (splineElementIdx != -1)
  401. {
  402. // Find & copy the raw pointer node
  403. AZ::SerializeContext::DataElementNode& splinePtrNodeRef = classElement.GetSubElement(splineElementIdx);
  404. AZ::SerializeContext::DataElementNode splinePtrNodeCopy = splinePtrNodeRef;
  405. // Reset the node, then convert it to an intrusive pointer
  406. splinePtrNodeRef = AZ::SerializeContext::DataElementNode();
  407. if (splinePtrNodeRef.Convert<AZStd::intrusive_ptr<spline::TrackSplineInterpolator<Vec2>>>(context, "Spline"))
  408. {
  409. // Use the standard name used with the smart pointers serialization
  410. // (smart pointers are serialized as containers with one element);
  411. // Set the intrusive pointer to the raw pointer value
  412. splinePtrNodeCopy.SetName(AZ::SerializeContext::IDataContainer::GetDefaultElementName());
  413. splinePtrNodeRef.AddElement(splinePtrNodeCopy);
  414. converted = true;
  415. }
  416. }
  417. // Did not convert. Discard unknown versions if failed to convert, and hope for the best
  418. AZ_Assert(converted, "Failed to convert TUiAnimSplineTrack<Vec2> version %d to the current version", classElement.GetVersion());
  419. result = converted;
  420. }
  421. }
  422. return result;
  423. }
  424. //////////////////////////////////////////////////////////////////////////
  425. template<>
  426. void TAnimSplineTrack<Vec2>::Reflect(AZ::ReflectContext* context)
  427. {
  428. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  429. {
  430. spline::SplineKey<Vec2>::Reflect(serializeContext);
  431. spline::SplineKeyEx<Vec2>::Reflect(serializeContext);
  432. spline::TrackSplineInterpolator<Vec2>::Reflect(serializeContext);
  433. spline::BezierSplineVec2::Reflect(serializeContext);
  434. serializeContext->Class<TAnimSplineTrack<Vec2>, IAnimTrack>()
  435. ->Version(5, &TAnimSplineTrackVec2VersionConverter)
  436. ->Field("Flags", &TAnimSplineTrack<Vec2>::m_flags)
  437. ->Field("DefaultValue", &TAnimSplineTrack<Vec2>::m_defaultValue)
  438. ->Field("ParamType", &TAnimSplineTrack<Vec2>::m_nParamType)
  439. ->Field("Spline", &TAnimSplineTrack<Vec2>::m_spline)
  440. ->Field("Id", &TAnimSplineTrack<Vec2>::m_id);
  441. AZ::EditContext* ec = serializeContext->GetEditContext();
  442. // Preventing the default value from being pushed to slice to keep it from dirtying the slice when updated internally
  443. if (ec)
  444. {
  445. ec->Class<TAnimSplineTrack<Vec2>>("TAnimSplineTrack Vec2", "Specialization track for Vec2 AnimSpline")->
  446. DataElement(AZ::Edit::UIHandlers::Vector2, &TAnimSplineTrack<Vec2>::m_defaultValue, "DefaultValue", "")->
  447. Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Hide)->
  448. Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::NotPushable);
  449. }
  450. }
  451. }