| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzCore/Math/Transform.h>
- #include "CompoundSplineTrack.h"
- #include "AnimSplineTrack.h"
- #include "Maestro/Types/AnimParamType.h"
- #include "Maestro/Types/AnimValueType.h"
- CCompoundSplineTrack::CCompoundSplineTrack(int nDims, AnimValueType inValueType, CAnimParamType subTrackParamTypes[MAX_SUBTRACKS], bool expanded)
- : m_refCount(0)
- , m_expanded(expanded)
- {
- assert(nDims > 0 && nDims <= MAX_SUBTRACKS);
- m_node = nullptr;
- m_nDimensions = nDims;
- m_valueType = inValueType;
- m_nParamType = AnimParamType::Invalid;
- m_flags = 0;
- m_subTracks.resize(MAX_SUBTRACKS);
- for (int i = 0; i < m_nDimensions; i++)
- {
- m_subTracks[i].reset(aznew C2DSplineTrack());
- m_subTracks[i]->SetParameterType(subTrackParamTypes[i]);
- if (inValueType == AnimValueType::RGB)
- {
- m_subTracks[i]->SetKeyValueRange(0.0f, 255.f);
- }
- }
- m_subTrackNames.resize(MAX_SUBTRACKS);
- m_subTrackNames[0] = "X";
- m_subTrackNames[1] = "Y";
- m_subTrackNames[2] = "Z";
- m_subTrackNames[3] = "W";
- #ifdef MOVIESYSTEM_SUPPORT_EDITING
- m_bCustomColorSet = false;
- #endif
- }
- //////////////////////////////////////////////////////////////////////////
- // Need default constructor for AZ Serialization
- CCompoundSplineTrack::CCompoundSplineTrack()
- : m_refCount(0)
- , m_nDimensions(0)
- , m_valueType(AnimValueType::Float)
- #ifdef MOVIESYSTEM_SUPPORT_EDITING
- , m_bCustomColorSet(false)
- #endif
- , m_expanded(false)
- {
- }
- void CCompoundSplineTrack::SetNode(IAnimNode* node)
- {
- m_node = node;
- for (int i = 0; i < m_nDimensions; i++)
- {
- m_subTracks[i]->SetNode(node);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::SetTimeRange(const Range& timeRange)
- {
- for (int i = 0; i < m_nDimensions; i++)
- {
- m_subTracks[i]->SetTimeRange(timeRange);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- /// @deprecated Serialization for Sequence data in Component Entity Sequences now occurs through AZ::SerializeContext and the Sequence Component
- bool CCompoundSplineTrack::Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks /*=true */)
- {
- #ifdef MOVIESYSTEM_SUPPORT_EDITING
- if (bLoading)
- {
- int flags = m_flags;
- xmlNode->getAttr("Flags", flags);
- SetFlags(flags);
- xmlNode->getAttr("HasCustomColor", m_bCustomColorSet);
- if (m_bCustomColorSet)
- {
- unsigned int abgr;
- xmlNode->getAttr("CustomColor", abgr);
- m_customColor = ColorB(abgr);
- }
- xmlNode->getAttr("Id", m_id);
- }
- else
- {
- int flags = GetFlags();
- xmlNode->setAttr("Flags", flags);
- xmlNode->setAttr("HasCustomColor", m_bCustomColorSet);
- if (m_bCustomColorSet)
- {
- xmlNode->setAttr("CustomColor", m_customColor.pack_abgr8888());
- }
- xmlNode->setAttr("Id", m_id);
- }
- #endif
- for (int i = 0; i < m_nDimensions; i++)
- {
- XmlNodeRef subTrackNode;
- if (bLoading)
- {
- subTrackNode = xmlNode->getChild(i);
- }
- else
- {
- subTrackNode = xmlNode->newChild("NewSubTrack");
- }
- m_subTracks[i]->Serialize(subTrackNode, bLoading, bLoadEmptyTracks);
- }
- return true;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CCompoundSplineTrack::SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected /*=false*/, float fTimeOffset /*=0*/)
- {
- for (int i = 0; i < m_nDimensions; i++)
- {
- XmlNodeRef subTrackNode;
- if (bLoading)
- {
- subTrackNode = xmlNode->getChild(i);
- }
- else
- {
- subTrackNode = xmlNode->newChild("NewSubTrack");
- }
- m_subTracks[i]->SerializeSelection(subTrackNode, bLoading, bCopySelected, fTimeOffset);
- }
- return true;
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::GetValue(float time, float& value, bool applyMultiplier)
- {
- for (int i = 0; i < 1 && i < m_nDimensions; i++)
- {
- m_subTracks[i]->GetValue(time, value, applyMultiplier);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::GetValue(float time, Vec3& value, bool applyMultiplier)
- {
- for (int i = 0; i < m_nDimensions; i++)
- {
- float v = value[i];
- m_subTracks[i]->GetValue(time, v, applyMultiplier);
- value[i] = v;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::GetValue(float time, Vec4& value, bool applyMultiplier)
- {
- for (int i = 0; i < m_nDimensions; i++)
- {
- float v = value[i];
- m_subTracks[i]->GetValue(time, v, applyMultiplier);
- value[i] = v;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::GetValue(float time, Quat& value)
- {
- if (m_nDimensions == 3)
- {
- // Assume Euler Angles XYZ
- float angles[3] = {0, 0, 0};
- for (int i = 0; i < m_nDimensions; i++)
- {
- m_subTracks[i]->GetValue(time, angles[i]);
- }
- value = Quat::CreateRotationZYX(Ang3(DEG2RAD(angles[0]), DEG2RAD(angles[1]), DEG2RAD(angles[2])));
- }
- else
- {
- assert(0);
- value.SetIdentity();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::SetValue(float time, const float& value, bool bDefault, bool applyMultiplier)
- {
- for (int i = 0; i < m_nDimensions; i++)
- {
- m_subTracks[i]->SetValue(time, value, bDefault, applyMultiplier);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::SetValue(float time, const Vec3& value, bool bDefault, bool applyMultiplier)
- {
- for (int i = 0; i < m_nDimensions; i++)
- {
- m_subTracks[i]->SetValue(time, value[i], bDefault, applyMultiplier);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::SetValue(float time, const Vec4& value, bool bDefault, bool applyMultiplier)
- {
- for (int i = 0; i < m_nDimensions; i++)
- {
- m_subTracks[i]->SetValue(time, value[i], bDefault, applyMultiplier);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::SetValue(float time, const Quat& value, bool bDefault)
- {
- if (m_nDimensions == 3)
- {
- // Assume Euler Angles XYZ
- Ang3 angles = Ang3::GetAnglesXYZ(value);
- for (int i = 0; i < 3; i++)
- {
- float degree = RAD2DEG(angles[i]);
- if (false == bDefault)
- {
- // Try to prefer the shortest path of rotation.
- float degree0 = 0.0f;
- m_subTracks[i]->GetValue(time, degree0);
- degree = PreferShortestRotPath(degree, degree0);
- }
- m_subTracks[i]->SetValue(time, degree, bDefault);
- }
- }
- else
- {
- assert(0);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::OffsetKeyPosition(const Vec3& offset)
- {
- if (m_nDimensions == 3)
- {
- for (int i = 0; i < 3; i++)
- {
- IAnimTrack* pSubTrack = m_subTracks[i].get();
- // Iterate over all keys.
- for (int k = 0, num = pSubTrack->GetNumKeys(); k < num; k++)
- {
- // Offset each key.
- float time = pSubTrack->GetKeyTime(k);
- float value = 0;
- pSubTrack->GetValue(time, value);
- value = value + offset[i];
- pSubTrack->SetValue(time, value);
- }
- }
- }
- else
- {
- assert(0);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::UpdateKeyDataAfterParentChanged(const AZ::Transform& oldParentWorldTM, const AZ::Transform& newParentWorldTM)
- {
- // Only update the position tracks
- if (m_nParamType.GetType() != AnimParamType::Position)
- {
- return;
- }
- AZ_Assert(m_nDimensions == 3, "Expected 3 dimensions, position, rotation or scale.");
- struct KeyValues
- {
- KeyValues(int i, float t, float v) : index(i), time(t), value(v) {};
- int index;
- float time;
- float value;
- };
- // Don't actually set the key data until we are done calculating all the new values.
- // In the case where not all 3 tracks have key data, data from other keys may be referenced
- // and used. So we don't want to muck with those other keys until we are done transforming all of
- // the key data.
- AZStd::vector<KeyValues> newKeyValues;
- // Collect all times that have key data on any track.
- for (int subTrackIndex = 0; subTrackIndex < 3; subTrackIndex++)
- {
- IAnimTrack* subTrack = m_subTracks[subTrackIndex].get();
- for (int k = 0, num = subTrack->GetNumKeys(); k < num; k++)
- {
- // If this key time is not already in the list, add it.
- float time = subTrack->GetKeyTime(k);
- // Create a 3 float vector with values from the 3 tracks.
- AZ::Vector3 vector;
- for (int i = 0; i < 3; i++)
- {
- float value = 0;
- m_subTracks[i]->GetValue(time, value);
- vector.SetElement(i, value);
- }
- // Use the old parent world transform to get the current key data into world space.
- AZ::Vector3 worldPosition = oldParentWorldTM.GetTranslation() + vector;
- // Get the world location into local space relative to the new parent.
- vector = worldPosition - newParentWorldTM.GetTranslation();
- // Store the new key data in a list to be set to keys later.
- newKeyValues.push_back(KeyValues(subTrackIndex, time, vector.GetElement(subTrackIndex)));
- }
- }
- // Set key data for each time gathered from the keys.
- for (auto valuePair : newKeyValues)
- {
- m_subTracks[valuePair.index]->SetValue(valuePair.time, valuePair.value);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- IAnimTrack* CCompoundSplineTrack::GetSubTrack(int nIndex) const
- {
- assert(nIndex >= 0 && nIndex < m_nDimensions);
- return m_subTracks[nIndex].get();
- }
- //////////////////////////////////////////////////////////////////////////
- AZStd::string CCompoundSplineTrack::GetSubTrackName(int nIndex) const
- {
- assert(nIndex >= 0 && nIndex < m_nDimensions);
- return m_subTrackNames[nIndex];
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::SetSubTrackName(int nIndex, const char* name)
- {
- assert(nIndex >= 0 && nIndex < m_nDimensions);
- assert(name);
- m_subTrackNames[nIndex] = name;
- }
- //////////////////////////////////////////////////////////////////////////
- int CCompoundSplineTrack::GetNumKeys() const
- {
- int nKeys = 0;
- for (int i = 0; i < m_nDimensions; i++)
- {
- nKeys += m_subTracks[i]->GetNumKeys();
- }
- return nKeys;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CCompoundSplineTrack::HasKeys() const
- {
- for (int i = 0; i < m_nDimensions; i++)
- {
- if (m_subTracks[i]->GetNumKeys())
- {
- return true;
- }
- }
- return false;
- }
- float CCompoundSplineTrack::PreferShortestRotPath(float degree, float degree0) const
- {
- // Assumes the degree is in (-PI, PI).
- assert(-181.0f < degree && degree < 181.0f);
- float degree00 = degree0;
- degree0 = fmod_tpl(degree0, 360.0f);
- float n = (degree00 - degree0) / 360.0f;
- float degreeAlt;
- if (degree >= 0)
- {
- degreeAlt = degree - 360.0f;
- }
- else
- {
- degreeAlt = degree + 360.0f;
- }
- if (fabs(degreeAlt - degree0) < fabs(degree - degree0))
- {
- return degreeAlt + n * 360.0f;
- }
- else
- {
- return degree + n * 360.0f;
- }
- }
- int CCompoundSplineTrack::GetSubTrackIndex(int& key) const
- {
- assert(key >= 0 && key < GetNumKeys());
- int count = 0;
- for (int i = 0; i < m_nDimensions; i++)
- {
- if (key < count + m_subTracks[i]->GetNumKeys())
- {
- key = key - count;
- return i;
- }
- count += m_subTracks[i]->GetNumKeys();
- }
- return -1;
- }
- void CCompoundSplineTrack::RemoveKey(int num)
- {
- assert(num >= 0 && num < GetNumKeys());
- int i = GetSubTrackIndex(num);
- assert(i >= 0);
- if (i < 0)
- {
- return;
- }
- m_subTracks[i]->RemoveKey(num);
- }
- void CCompoundSplineTrack::GetKeyInfo(int key, const char*& description, float& duration)
- {
- static char str[64];
- duration = 0;
- description = str;
- const char* subDesc = NULL;
- float time = GetKeyTime(key);
- int m = 0;
- /// Using the time obtained, combine descriptions from keys of the same time
- /// in sub-tracks if any into one compound description.
- str[0] = 0;
- // A head case
- for (m = 0; m < m_subTracks[0]->GetNumKeys(); ++m)
- {
- if (m_subTracks[0]->GetKeyTime(m) == time)
- {
- float dummy;
- m_subTracks[0]->GetKeyInfo(m, subDesc, dummy);
- azstrcat(str, AZ_ARRAY_SIZE(str), subDesc);
- break;
- }
- }
- if (m == m_subTracks[0]->GetNumKeys())
- {
- azstrcat(str, AZ_ARRAY_SIZE(str), m_subTrackNames[0].c_str());
- }
- // Tail cases
- for (int i = 1; i < GetSubTrackCount(); ++i)
- {
- azstrcat(str, AZ_ARRAY_SIZE(str), ",");
- for (m = 0; m < m_subTracks[i]->GetNumKeys(); ++m)
- {
- if (m_subTracks[i]->GetKeyTime(m) == time)
- {
- float dummy;
- m_subTracks[i]->GetKeyInfo(m, subDesc, dummy);
- azstrcat(str, AZ_ARRAY_SIZE(str), subDesc);
- break;
- }
- }
- if (m == m_subTracks[i]->GetNumKeys())
- {
- azstrcat(str, AZ_ARRAY_SIZE(str), m_subTrackNames[i].c_str());
- }
- }
- }
- float CCompoundSplineTrack::GetKeyTime(int index) const
- {
- assert(index >= 0 && index < GetNumKeys());
- int i = GetSubTrackIndex(index);
- assert(i >= 0);
- if (i < 0)
- {
- return 0;
- }
- return m_subTracks[i]->GetKeyTime(index);
- }
- void CCompoundSplineTrack::SetKeyTime(int index, float time)
- {
- assert(index >= 0 && index < GetNumKeys());
- int i = GetSubTrackIndex(index);
- assert(i >= 0);
- if (i < 0)
- {
- return;
- }
- m_subTracks[i]->SetKeyTime(index, time);
- }
- bool CCompoundSplineTrack::IsKeySelected(int key) const
- {
- assert(key >= 0 && key < GetNumKeys());
- int i = GetSubTrackIndex(key);
- assert(i >= 0);
- if (i < 0)
- {
- return false;
- }
- return m_subTracks[i]->IsKeySelected(key);
- }
- void CCompoundSplineTrack::SelectKey(int key, bool select)
- {
- assert(key >= 0 && key < GetNumKeys());
- int i = GetSubTrackIndex(key);
- assert(i >= 0);
- if (i < 0)
- {
- return;
- }
- float keyTime = m_subTracks[i]->GetKeyTime(key);
- // In the case of compound tracks, animators want to
- // select all keys of the same time in the sub-tracks together.
- const float timeEpsilon = 0.001f;
- for (int k = 0; k < m_nDimensions; ++k)
- {
- for (int m = 0; m < m_subTracks[k]->GetNumKeys(); ++m)
- {
- if (fabs(m_subTracks[k]->GetKeyTime(m) - keyTime) < timeEpsilon)
- {
- m_subTracks[k]->SelectKey(m, select);
- break;
- }
- }
- }
- }
- int CCompoundSplineTrack::NextKeyByTime(int key) const
- {
- assert(key >= 0 && key < GetNumKeys());
- float time = GetKeyTime(key);
- int count = 0, result = -1;
- float timeNext = FLT_MAX;
- for (int i = 0; i < GetSubTrackCount(); ++i)
- {
- for (int k = 0; k < m_subTracks[i]->GetNumKeys(); ++k)
- {
- float t = m_subTracks[i]->GetKeyTime(k);
- if (t > time)
- {
- if (t < timeNext)
- {
- timeNext = t;
- result = count + k;
- }
- break;
- }
- }
- count += m_subTracks[i]->GetNumKeys();
- }
- return result;
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::SetExpanded(bool expanded)
- {
- m_expanded = expanded;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CCompoundSplineTrack::GetExpanded() const
- {
- return m_expanded;
- }
-
- //////////////////////////////////////////////////////////////////////////
- unsigned int CCompoundSplineTrack::GetId() const
- {
- return m_id;
- }
- //////////////////////////////////////////////////////////////////////////
- void CCompoundSplineTrack::SetId(unsigned int id)
- {
- m_id = id;
- }
- //////////////////////////////////////////////////////////////////////////
- static bool CompoundSplineTrackVersionConverter(
- AZ::SerializeContext& serializeContext,
- AZ::SerializeContext::DataElementNode& rootElement)
- {
- if (rootElement.GetVersion() < 4)
- {
- rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>());
- }
- return true;
- }
- void CCompoundSplineTrack::Reflect(AZ::ReflectContext* context)
- {
- if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serializeContext->Class<CCompoundSplineTrack, IAnimTrack>()
- ->Version(4, &CompoundSplineTrackVersionConverter)
- ->Field("Flags", &CCompoundSplineTrack::m_flags)
- ->Field("ParamType", &CCompoundSplineTrack::m_nParamType)
- ->Field("NumSubTracks", &CCompoundSplineTrack::m_nDimensions)
- ->Field("SubTracks", &CCompoundSplineTrack::m_subTracks)
- ->Field("SubTrackNames", &CCompoundSplineTrack::m_subTrackNames)
- ->Field("ValueType", &CCompoundSplineTrack::m_valueType)
- ->Field("Expanded", &CCompoundSplineTrack::m_expanded)
- ->Field("Id", &CCompoundSplineTrack::m_id);
- }
- }
|