1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252 |
- /*
- * 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 "AnimNode.h"
- #include "AnimTrack.h"
- #include "AnimSequence.h"
- #include <Maestro/Types/AssetBlendKey.h>
- #include "AssetBlendTrack.h"
- #include "CharacterTrack.h"
- #include "AnimSplineTrack.h"
- #include "BoolTrack.h"
- #include "MathConversion.h"
- #include "SelectTrack.h"
- #include "EventTrack.h"
- #include "SoundTrack.h"
- #include "ConsoleTrack.h"
- #include "LookAtTrack.h"
- #include "TrackEventTrack.h"
- #include "SequenceTrack.h"
- #include "CompoundSplineTrack.h"
- #include "GotoTrack.h"
- #include "CaptureTrack.h"
- #include "CommentTrack.h"
- #include "ScreenFaderTrack.h"
- #include "TimeRangesTrack.h"
- #include "SoundTrack.h"
- #include <AzCore/std/sort.h>
- #include <AzCore/Math/MathUtils.h>
- #include <AzCore/Component/TickBus.h>
- #include <ctime>
- #include "Maestro/Types/AnimValueType.h"
- #include "Maestro/Types/AnimNodeType.h"
- #include "Maestro/Types/AnimParamType.h"
- //////////////////////////////////////////////////////////////////////////
- // Old deprecated IDs
- //////////////////////////////////////////////////////////////////////////
- #define APARAM_CHARACTER4 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x10)
- #define APARAM_CHARACTER5 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x11)
- #define APARAM_CHARACTER6 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x12)
- #define APARAM_CHARACTER7 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x13)
- #define APARAM_CHARACTER8 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x14)
- #define APARAM_CHARACTER9 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x15)
- #define APARAM_CHARACTER10 static_cast<AnimParamType>(static_cast<int>(AnimParamType::User) + 0x16)
- //////////////////////////////////////////////////////////////////////////
- static const EAnimCurveType DEFAULT_TRACK_TYPE = eAnimCurveType_BezierFloat;
- // Old serialization values that are no longer
- // defined in IMovieSystem.h, but needed for conversion:
- static const int OLD_ACURVE_GOTO = 21;
- static const int OLD_APARAM_PARTICLE_COUNT_SCALE = 95;
- static const int OLD_APARAM_PARTICLE_PULSE_PERIOD = 96;
- static const int OLD_APARAM_PARTICLE_SCALE = 97;
- static const int OLD_APARAM_PARTICLE_SPEED_SCALE = 98;
- static const int OLD_APARAM_PARTICLE_STRENGTH = 99;
- //////////////////////////////////////////////////////////////////////////
- // CAnimNode.
- //////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::Activate([[maybe_unused]] bool bActivate)
- {
- }
- //////////////////////////////////////////////////////////////////////////
- int CAnimNode::GetTrackCount() const
- {
- return static_cast<int>(m_tracks.size());
- }
- AZStd::string CAnimNode::GetParamName(const CAnimParamType& paramType) const
- {
- SParamInfo info;
- if (GetParamInfoFromType(paramType, info))
- {
- return info.name;
- }
- return "Unknown";
- }
- AnimValueType CAnimNode::GetParamValueType(const CAnimParamType& paramType) const
- {
- SParamInfo info;
- if (GetParamInfoFromType(paramType, info))
- {
- return info.valueType;
- }
- return AnimValueType::Unknown;
- }
- IAnimNode::ESupportedParamFlags CAnimNode::GetParamFlags(const CAnimParamType& paramType) const
- {
- SParamInfo info;
- if (GetParamInfoFromType(paramType, info))
- {
- return info.flags;
- }
- return IAnimNode::ESupportedParamFlags(0);
- }
- IAnimTrack* CAnimNode::GetTrackForParameter(const CAnimParamType& paramType) const
- {
- for (int i = 0, num = (int)m_tracks.size(); i < num; i++)
- {
- if (m_tracks[i]->GetParameterType() == paramType)
- {
- return m_tracks[i].get();
- }
- // Search the sub-tracks also if any.
- for (int k = 0; k < m_tracks[i]->GetSubTrackCount(); ++k)
- {
- if (m_tracks[i]->GetSubTrack(k)->GetParameterType() == paramType)
- {
- return m_tracks[i]->GetSubTrack(k);
- }
- }
- }
- return 0;
- }
- IAnimTrack* CAnimNode::GetTrackForParameter(const CAnimParamType& paramType, uint32 index) const
- {
- SParamInfo paramInfo;
- GetParamInfoFromType(paramType, paramInfo);
- if ((paramInfo.flags & IAnimNode::eSupportedParamFlags_MultipleTracks) == 0)
- {
- return GetTrackForParameter(paramType);
- }
- uint32 count = 0;
- for (int i = 0, num = (int)m_tracks.size(); i < num; i++)
- {
- if (m_tracks[i]->GetParameterType() == paramType && count++ == index)
- {
- return m_tracks[i].get();
- }
- // For this case, no subtracks are considered.
- }
- return 0;
- }
- uint32 CAnimNode::GetTrackParamIndex(const IAnimTrack* pTrack) const
- {
- assert(pTrack);
- uint32 index = 0;
- CAnimParamType paramType = pTrack->GetParameterType();
- SParamInfo paramInfo;
- GetParamInfoFromType(paramType, paramInfo);
- if ((paramInfo.flags & IAnimNode::eSupportedParamFlags_MultipleTracks) == 0)
- {
- return 0;
- }
- for (int i = 0, num = (int)m_tracks.size(); i < num; i++)
- {
- if (m_tracks[i].get() == pTrack)
- {
- return index;
- }
- if (m_tracks[i]->GetParameterType() == paramType)
- {
- ++index;
- }
- // For this case, no subtracks are considered.
- }
- assert(!"CAnimNode::GetTrackParamIndex() called with an invalid argument!");
- return 0;
- }
- IAnimTrack* CAnimNode::GetTrackByIndex(int nIndex) const
- {
- if (nIndex >= (int)m_tracks.size())
- {
- assert("nIndex>=m_tracks.size()" && false);
- return NULL;
- }
- return m_tracks[nIndex].get();
- }
- void CAnimNode::SetTrack(const CAnimParamType& paramType, IAnimTrack* pTrack)
- {
- if (pTrack)
- {
- for (unsigned int i = 0; i < m_tracks.size(); i++)
- {
- if (m_tracks[i]->GetParameterType() == paramType)
- {
- m_tracks[i].reset(pTrack);
- return;
- }
- }
- AddTrack(pTrack);
- }
- else
- {
- // Remove track at this id.
- for (unsigned int i = 0; i < m_tracks.size(); i++)
- {
- if (m_tracks[i]->GetParameterType() == paramType)
- {
- m_tracks.erase(m_tracks.begin() + i);
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::TrackOrder(const AZStd::intrusive_ptr<IAnimTrack>& left, const AZStd::intrusive_ptr<IAnimTrack>& right)
- {
- return left->GetParameterType() < right->GetParameterType();
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::AddTrack(IAnimTrack* pTrack)
- {
- RegisterTrack(pTrack);
- m_tracks.push_back(AZStd::intrusive_ptr<IAnimTrack>(pTrack));
- SortTracks();
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::RegisterTrack(IAnimTrack* pTrack)
- {
- pTrack->SetTimeRange(GetSequence()->GetTimeRange());
- pTrack->SetNode(this);
- }
- void CAnimNode::SortTracks()
- {
- AZStd::insertion_sort(m_tracks.begin(), m_tracks.end(), TrackOrder);
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::RemoveTrack(IAnimTrack* pTrack)
- {
- for (unsigned int i = 0; i < m_tracks.size(); i++)
- {
- if (m_tracks[i].get() == pTrack)
- {
- m_tracks.erase(m_tracks.begin() + i);
- return true;
- }
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- static bool AnimNodeVersionConverter(
- AZ::SerializeContext& serializeContext,
- AZ::SerializeContext::DataElementNode& rootElement)
- {
- if (rootElement.GetVersion() < 3)
- {
- rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimNode>());
- }
- if (rootElement.GetVersion() < 4)
- {
- // remove vector scale tracks from transform anim nodes
- AZStd::string name;
- if (rootElement.FindSubElementAndGetData<AZStd::string>(AZ_CRC_CE("Name"), name) && name == "Transform")
- {
- auto tracksElement = rootElement.FindSubElement(AZ_CRC_CE("Tracks"));
- if (tracksElement)
- {
- for (int trackIndex = tracksElement->GetNumSubElements() - 1; trackIndex >= 0; trackIndex--)
- {
- auto trackElement = tracksElement->GetSubElement(trackIndex);
- bool isScale = false;
- // trackElement should be an intrusive_ptr with one child
- if (trackElement.GetNumSubElements() == 1)
- {
- auto ptrElement = trackElement.GetSubElement(0);
- auto paramTypeElement = ptrElement.FindSubElement(AZ_CRC_CE("ParamType"));
- if (paramTypeElement)
- {
- AZStd::string paramName;
- if (paramTypeElement->FindSubElementAndGetData<AZStd::string>(AZ_CRC_CE("Name"), paramName) && paramName == "Scale")
- {
- isScale = true;
- }
- }
- }
- if (isScale)
- {
- tracksElement->RemoveElement(trackIndex);
- }
- }
- }
- }
- }
- return true;
- }
- void CAnimNode::Reflect(AZ::ReflectContext* context)
- {
- if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serializeContext->Class<CAnimNode, IAnimNode>()
- ->Version(4, &AnimNodeVersionConverter)
- ->Field("ID", &CAnimNode::m_id)
- ->Field("Name", &CAnimNode::m_name)
- ->Field("Flags", &CAnimNode::m_flags)
- ->Field("Tracks", &CAnimNode::m_tracks)
- ->Field("Parent", &CAnimNode::m_parentNodeId)
- ->Field("Type", &CAnimNode::m_nodeType)
- ->Field("Expanded", &CAnimNode::m_expanded);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- IAnimTrack* CAnimNode::CreateTrackInternal(const CAnimParamType& paramType, EAnimCurveType trackType, AnimValueType valueType)
- {
- if (valueType == AnimValueType::Unknown)
- {
- SParamInfo info;
- // Try to get info from paramType, else we can't determine the track data type
- if (!GetParamInfoFromType(paramType, info))
- {
- return 0;
- }
- valueType = info.valueType;
- }
- IAnimTrack* pTrack = NULL;
- switch (paramType.GetType())
- {
- // Create sub-classed tracks
- case AnimParamType::Event:
- pTrack = aznew CEventTrack(m_pSequence->GetTrackEventStringTable());
- break;
- case AnimParamType::Sound:
- pTrack = aznew CSoundTrack;
- break;
- case AnimParamType::Animation:
- pTrack = aznew CCharacterTrack;
- break;
- case AnimParamType::Console:
- pTrack = aznew CConsoleTrack;
- break;
- case AnimParamType::LookAt:
- pTrack = aznew CLookAtTrack;
- break;
- case AnimParamType::TrackEvent:
- pTrack = aznew CTrackEventTrack(m_pSequence->GetTrackEventStringTable());
- break;
- case AnimParamType::Sequence:
- pTrack = aznew CSequenceTrack;
- break;
- case AnimParamType::Capture:
- pTrack = aznew CCaptureTrack;
- break;
- case AnimParamType::CommentText:
- pTrack = aznew CCommentTrack;
- break;
- case AnimParamType::ScreenFader:
- pTrack = aznew CScreenFaderTrack;
- break;
- case AnimParamType::Goto:
- pTrack = aznew CGotoTrack;
- break;
- case AnimParamType::TimeRanges:
- pTrack = aznew CTimeRangesTrack;
- break;
- case AnimParamType::Float:
- pTrack = CreateTrackInternalFloat(trackType);
- break;
- default:
- // Create standard tracks
- switch (valueType)
- {
- case AnimValueType::Float:
- pTrack = CreateTrackInternalFloat(trackType);
- break;
- case AnimValueType::RGB:
- case AnimValueType::Vector:
- pTrack = CreateTrackInternalVector(trackType, paramType, valueType);
- break;
- case AnimValueType::Quat:
- pTrack = CreateTrackInternalQuat(trackType, paramType);
- break;
- case AnimValueType::Bool:
- pTrack = aznew CBoolTrack;
- break;
- case AnimValueType::Select:
- pTrack = aznew CSelectTrack;
- break;
- case AnimValueType::Vector4:
- pTrack = CreateTrackInternalVector4(paramType);
- break;
- case AnimValueType::CharacterAnim:
- pTrack = aznew CCharacterTrack;
- break;
- case AnimValueType::AssetBlend:
- pTrack = aznew CAssetBlendTrack;
- break;
- }
- }
- if (pTrack)
- {
- pTrack->SetParameterType(paramType);
- // Assign a unique id for every track.
- pTrack->SetId(m_pSequence->GetUniqueTrackIdAndGenerateNext());
- int subTrackCount = pTrack->GetSubTrackCount();
- for (int subTrackIndex = 0; subTrackIndex < subTrackCount; subTrackIndex++)
- {
- IAnimTrack* subTrack = pTrack->GetSubTrack(subTrackIndex);
- subTrack->SetId(m_pSequence->GetUniqueTrackIdAndGenerateNext());
- }
- AddTrack(pTrack);
- }
- return pTrack;
- }
- //////////////////////////////////////////////////////////////////////////
- IAnimTrack* CAnimNode::CreateTrack(const CAnimParamType& paramType)
- {
- IAnimTrack* pTrack = CreateTrackInternal(paramType, DEFAULT_TRACK_TYPE, AnimValueType::Unknown);
- InitializeTrackDefaultValue(pTrack, paramType);
- return pTrack;
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::SerializeAnims(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks)
- {
- if (bLoading)
- {
- // Delete all tracks.
- stl::free_container(m_tracks);
- CAnimNode::SParamInfo info;
- // Loading.
- int paramTypeVersion = 0;
- xmlNode->getAttr("paramIdVersion", paramTypeVersion);
- CAnimParamType paramType;
- int num = xmlNode->getChildCount();
- for (int i = 0; i < num; i++)
- {
- XmlNodeRef trackNode = xmlNode->getChild(i);
- paramType.Serialize(trackNode, bLoading, paramTypeVersion);
- if (paramType.GetType() == AnimParamType::Music)
- {
- // skip loading AnimParamType::Music - it's deprecated
- continue;
- }
- if (paramTypeVersion == 0) // for old version with sound and animation param ids swapped
- {
- AnimParamType APARAM_ANIMATION_OLD = AnimParamType::Sound;
- AnimParamType APARAM_SOUND_OLD = AnimParamType::Animation;
- if (paramType.GetType() == APARAM_ANIMATION_OLD)
- {
- paramType = AnimParamType::Animation;
- }
- else if (paramType.GetType() == APARAM_SOUND_OLD)
- {
- paramType = AnimParamType::Sound;
- }
- }
- int curveType = eAnimCurveType_Unknown;
- trackNode->getAttr("Type", curveType);
- if (curveType == eAnimCurveType_Unknown)
- {
- if (paramTypeVersion == 0)
- {
- //////////////////////////////////////////////////////////////////////////
- // Backward compatibility code
- //////////////////////////////////////////////////////////////////////////
- // Legacy animation track.
- // Collapse parameter ID to the single type
- if (paramType.GetType() >= AnimParamType::Sound && paramType.GetType() <= static_cast<AnimParamType>(static_cast<int>(AnimParamType::Sound) + 2))
- {
- paramType = AnimParamType::Sound;
- }
- if (paramType.GetType() >= AnimParamType::Animation && paramType.GetType() <= static_cast<AnimParamType>(static_cast<int>(AnimParamType::Animation) + 2))
- {
- paramType = AnimParamType::Animation;
- }
- if (paramType.GetType() >= APARAM_CHARACTER4 && paramType.GetType() <= APARAM_CHARACTER10)
- {
- paramType = AnimParamType::Animation;
- }
- // Old tracks always used TCB tracks.
- // Backward compatibility to the CryEngine2 for track type (will make TCB controller)
- curveType = eAnimCurveType_TCBVector;
- }
- }
- if (paramTypeVersion <= 1)
- {
- // In old versions goto tracks were identified by a curve id
- if (curveType == OLD_ACURVE_GOTO)
- {
- paramType = AnimParamType::Goto;
- curveType = eAnimCurveType_Unknown;
- }
- }
- if (paramTypeVersion <= 3 && paramType.GetType() >= static_cast<AnimParamType>(OLD_APARAM_USER))
- {
- // APARAM_USER 100 => 100000
- paramType = static_cast<AnimParamType>(static_cast<int>(paramType.GetType()) + static_cast<int>(AnimParamType::User) - OLD_APARAM_USER);
- }
- if (paramTypeVersion <= 4)
- {
- // In old versions there was special code for particles
- // that is now handles by generic entity node code
- switch (paramType.GetType())
- {
- case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_COUNT_SCALE) :
- paramType = CAnimParamType("ScriptTable:Properties/CountScale");
- break;
- case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_PULSE_PERIOD) :
- paramType = CAnimParamType("ScriptTable:Properties/PulsePeriod");
- break;
- case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_SCALE) :
- paramType = CAnimParamType("ScriptTable:Properties/Scale");
- break;
- case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_SPEED_SCALE) :
- paramType = CAnimParamType("ScriptTable:Properties/SpeedScale");
- break;
- case static_cast<AnimParamType>(OLD_APARAM_PARTICLE_STRENGTH):
- paramType = CAnimParamType("ScriptTable:Properties/Strength");
- break;
- }
- }
- if (paramTypeVersion <= 5 && !(GetSequence()->GetFlags() & IAnimSequence::eSeqFlags_LightAnimationSet))
- {
- // In old versions there was special code for lights that is now handled
- // by generic entity node code if this is not a light animation set sequence
- switch (paramType.GetType())
- {
- case AnimParamType::LightDiffuse:
- paramType = CAnimParamType("ScriptTable:Properties/Color/clrDiffuse");
- break;
- case AnimParamType::LightRadius:
- paramType = CAnimParamType("ScriptTable:Properties/Radius");
- break;
- case AnimParamType::LightDiffuseMult:
- paramType = CAnimParamType("ScriptTable:Properties/Color/fDiffuseMultiplier");
- break;
- case AnimParamType::LightHDRDynamic:
- paramType = CAnimParamType("ScriptTable:Properties/Color/fHDRDynamic");
- break;
- case AnimParamType::LightSpecularMult:
- paramType = CAnimParamType("ScriptTable:Properties/Color/fSpecularMultiplier");
- break;
- case AnimParamType::LightSpecPercentage:
- paramType = CAnimParamType("ScriptTable:Properties/Color/fSpecularPercentage");
- break;
- }
- }
- if (paramTypeVersion <= 7 && paramType.GetType() == AnimParamType::Physics)
- {
- paramType = AnimParamType::PhysicsDriven;
- }
- int valueType = static_cast<int>(AnimValueType::Unknown);
- trackNode->getAttr("ValueType", valueType);
- IAnimTrack* pTrack = CreateTrackInternal(paramType, (EAnimCurveType)curveType, static_cast<AnimValueType>(valueType));
- bool trackRemoved = false;
- if (pTrack)
- {
- if (!pTrack->Serialize(trackNode, bLoading, bLoadEmptyTracks))
- {
- // Boolean tracks must always be loaded even if empty.
- if (pTrack->GetValueType() != AnimValueType::Bool)
- {
- RemoveTrack(pTrack);
- trackRemoved = true;
- }
- }
- }
- if (!trackRemoved && gEnv->IsEditor())
- {
- InitializeTrackDefaultValue(pTrack, paramType);
- }
- }
- }
- else
- {
- // Saving.
- xmlNode->setAttr("paramIdVersion", CAnimParamType::kParamTypeVersion);
- for (unsigned int i = 0; i < m_tracks.size(); i++)
- {
- IAnimTrack* pTrack = m_tracks[i].get();
- if (pTrack)
- {
- CAnimParamType paramType = m_tracks[i]->GetParameterType();
- XmlNodeRef trackNode = xmlNode->newChild("Track");
- paramType.Serialize(trackNode, bLoading);
- int nTrackType = pTrack->GetCurveType();
- trackNode->setAttr("Type", nTrackType);
- pTrack->Serialize(trackNode, bLoading);
- int valueType = static_cast<int>(pTrack->GetValueType());
- trackNode->setAttr("ValueType", valueType);
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::SetTimeRange(Range timeRange)
- {
- for (unsigned int i = 0; i < m_tracks.size(); i++)
- {
- if (m_tracks[i])
- {
- m_tracks[i]->SetTimeRange(timeRange);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // AZ::Serialization requires a default constructor
- CAnimNode::CAnimNode()
- : CAnimNode(0, AnimNodeType::Invalid)
- {
- }
- //////////////////////////////////////////////////////////////////////////
- // explicit copy constructor is required to prevent compiler's generated copy constructor
- // from calling AZStd::mutex's private copy constructor
- CAnimNode::CAnimNode(const CAnimNode& other)
- : m_refCount(0)
- , m_id(0) // don't copy id - these should be unique
- , m_parentNodeId(other.m_parentNodeId)
- , m_nodeType(other.m_nodeType)
- , m_pOwner(other.m_pOwner)
- , m_pSequence(other.m_pSequence)
- , m_flags(other.m_flags)
- , m_pParentNode(other.m_pParentNode)
- , m_nLoadedParentNodeId(other.m_nLoadedParentNodeId)
- , m_expanded(other.m_expanded)
- , m_movieSystem(other.m_movieSystem)
- {
- // m_bIgnoreSetParam not copied
- }
- //////////////////////////////////////////////////////////////////////////
- CAnimNode::CAnimNode(const int id, AnimNodeType nodeType)
- : m_refCount(0)
- , m_id(id)
- , m_parentNodeId(0)
- , m_nodeType(nodeType)
- , m_movieSystem(AZ::Interface<IMovieSystem>::Get())
- {
- m_pOwner = 0;
- m_pSequence = 0;
- m_flags = 0;
- m_bIgnoreSetParam = false;
- m_pParentNode = 0;
- m_nLoadedParentNodeId = 0;
- m_expanded = true;
- AZ_Trace("CAnimNode", "CAnimNode type %i", static_cast<int>(nodeType));
- }
- //////////////////////////////////////////////////////////////////////////
- CAnimNode::~CAnimNode()
- {
- AZ_Trace("CAnimNode", "~CAnimNode %i", static_cast<int>(m_nodeType));
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::add_ref()
- {
- ++m_refCount;
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::release()
- {
- if (--m_refCount <= 0)
- {
- delete this;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::SetFlags(int flags)
- {
- m_flags = flags;
- }
- //////////////////////////////////////////////////////////////////////////
- int CAnimNode::GetFlags() const
- {
- return m_flags;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::AreFlagsSetOnNodeOrAnyParent(EAnimNodeFlags flagsToCheck) const
- {
- if (m_pParentNode)
- {
- // recurse up parent chain until we find the flagsToCheck set or get to the top of the chain
- return ((GetFlags() & flagsToCheck) != 0) || m_pParentNode->AreFlagsSetOnNodeOrAnyParent(flagsToCheck);
- }
- // top of parent chain
- return ((GetFlags() & flagsToCheck) != 0);
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::Animate([[maybe_unused]] SAnimContext& ec)
- {
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::IsParamValid(const CAnimParamType& paramType) const
- {
- SParamInfo info;
- if (GetParamInfoFromType(paramType, info))
- {
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::SetParamValue(float time, CAnimParamType param, float value)
- {
- if (m_bIgnoreSetParam)
- {
- return true;
- }
- IAnimTrack* pTrack = GetTrackForParameter(param);
- if (pTrack && pTrack->GetValueType() == AnimValueType::Float)
- {
- // Float track.
- bool bDefault = !(m_movieSystem->IsRecording() && (m_flags & eAnimNodeFlags_EntitySelected)); // Only selected nodes can be recorded
- pTrack->SetValue(time, value, bDefault);
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::SetParamValue(float time, CAnimParamType param, const AZ::Vector3& value)
- {
- if (m_bIgnoreSetParam)
- {
- return true;
- }
- CCompoundSplineTrack* pTrack = static_cast<CCompoundSplineTrack*>(GetTrackForParameter(param));
- if (pTrack && pTrack->GetValueType() == AnimValueType::Vector)
- {
- // Vec3 track.
- bool bDefault = !(m_movieSystem->IsRecording() && (m_flags & eAnimNodeFlags_EntitySelected)); // Only selected nodes can be recorded
- pTrack->SetValue(time, value, bDefault);
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::SetParamValue(float time, CAnimParamType param, const AZ::Vector4& value)
- {
- if (m_bIgnoreSetParam)
- {
- return true;
- }
- CCompoundSplineTrack* pTrack = static_cast<CCompoundSplineTrack*>(GetTrackForParameter(param));
- if (pTrack && pTrack->GetValueType() == AnimValueType::Vector4)
- {
- // Vec4 track.
- bool bDefault = !(m_movieSystem->IsRecording() && (m_flags & eAnimNodeFlags_EntitySelected)); // Only selected nodes can be recorded
- pTrack->SetValue(time, value, bDefault);
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::GetParamValue(float time, CAnimParamType param, float& value)
- {
- IAnimTrack* pTrack = GetTrackForParameter(param);
- if (pTrack && pTrack->GetValueType() == AnimValueType::Float && pTrack->GetNumKeys() > 0)
- {
- // Float track.
- pTrack->GetValue(time, value);
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::GetParamValue(float time, CAnimParamType param, AZ::Vector3& value)
- {
- CCompoundSplineTrack* pTrack = static_cast<CCompoundSplineTrack*>(GetTrackForParameter(param));
- if (pTrack && pTrack->GetValueType() == AnimValueType::Vector && pTrack->GetNumKeys() > 0)
- {
- // Vec3 track.
- pTrack->GetValue(time, value);
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::GetParamValue(float time, CAnimParamType param, AZ::Vector4& value)
- {
- CCompoundSplineTrack* pTrack = static_cast<CCompoundSplineTrack*>(GetTrackForParameter(param));
- if (pTrack && pTrack->GetValueType() == AnimValueType::Vector4 && pTrack->GetNumKeys() > 0)
- {
- // Vec4 track.
- pTrack->GetValue(time, value);
- return true;
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- /// @deprecated Serialization for Sequence data in Component Entity Sequences now occurs through AZ::SerializeContext and the Sequence Component
- void CAnimNode::Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks)
- {
- if (bLoading)
- {
- xmlNode->getAttr("Id", m_id);
- const char* name = xmlNode->getAttr("Name");
- int flags;
- if (xmlNode->getAttr("Flags", flags))
- {
- // Don't load expanded or selected flags
- flags = flags & ~(eAnimNodeFlags_Expanded | eAnimNodeFlags_EntitySelected);
- SetFlags(flags);
- }
- SetName(name);
- m_nLoadedParentNodeId = 0;
- xmlNode->getAttr("ParentNode", m_nLoadedParentNodeId);
- }
- else
- {
- m_nLoadedParentNodeId = 0;
- xmlNode->setAttr("Id", m_id);
- AnimNodeType nodeType = GetType();
- GetMovieSystem()->SerializeNodeType(nodeType, xmlNode, bLoading, IAnimSequence::kSequenceVersion, m_flags);
- xmlNode->setAttr("Name", GetName());
- // Don't store expanded or selected flags
- int flags = GetFlags() & ~(eAnimNodeFlags_Expanded | eAnimNodeFlags_EntitySelected);
- xmlNode->setAttr("Flags", flags);
- if (m_pParentNode)
- {
- xmlNode->setAttr("ParentNode", static_cast<CAnimNode*>(m_pParentNode)->GetId());
- }
- }
- SerializeAnims(xmlNode, bLoading, bLoadEmptyTracks);
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::InitPostLoad(IAnimSequence* sequence)
- {
- [[maybe_unused]] const AZ::EntityId& sequenceEntityId = sequence->GetSequenceEntityId();
- AZ_Trace("CAnimNode::InitPostLoad", "IAnimSequence is %s", sequenceEntityId.ToString().c_str());
- m_pSequence = sequence;
- m_pParentNode = ((CAnimSequence*)m_pSequence)->FindNodeById(m_parentNodeId);
- // fix up animNode pointers and time ranges on tracks, then sort them
- for (unsigned int i = 0; i < m_tracks.size(); i++)
- {
- RegisterTrack(m_tracks[i].get());
- m_tracks[i].get()->InitPostLoad(sequence);
- }
- SortTracks();
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::SetNodeOwner(IAnimNodeOwner* pOwner)
- {
- m_pOwner = pOwner;
- if (pOwner)
- {
- pOwner->OnNodeAnimated(this);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::PostLoad()
- {
- if (m_nLoadedParentNodeId)
- {
- IAnimNode* pParentNode = ((CAnimSequence*)m_pSequence)->FindNodeById(m_nLoadedParentNodeId);
- m_pParentNode = pParentNode;
- m_parentNodeId = m_nLoadedParentNodeId; // adding as a temporary fix while we support both serialization methods
- m_nLoadedParentNodeId = 0;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- Matrix34 CAnimNode::GetReferenceMatrix() const
- {
- static Matrix34 tm(IDENTITY);
- return tm;
- }
- IAnimTrack* CAnimNode::CreateTrackInternalFloat([[maybe_unused]] int trackType) const
- {
- return aznew C2DSplineTrack;
- }
- IAnimTrack* CAnimNode::CreateTrackInternalVector([[maybe_unused]] EAnimCurveType trackType, const CAnimParamType& paramType, const AnimValueType animValue) const
- {
- CAnimParamType subTrackParamTypes[MAX_SUBTRACKS];
- for (unsigned int i = 0; i < MAX_SUBTRACKS; ++i)
- {
- subTrackParamTypes[i] = AnimParamType::Float;
- }
- if (paramType == AnimParamType::Position)
- {
- subTrackParamTypes[0] = AnimParamType::PositionX;
- subTrackParamTypes[1] = AnimParamType::PositionY;
- subTrackParamTypes[2] = AnimParamType::PositionZ;
- }
- else if (paramType == AnimParamType::Scale)
- {
- subTrackParamTypes[0] = AnimParamType::ScaleX;
- subTrackParamTypes[1] = AnimParamType::ScaleY;
- subTrackParamTypes[2] = AnimParamType::ScaleZ;
- }
- else if (paramType == AnimParamType::Rotation)
- {
- subTrackParamTypes[0] = AnimParamType::RotationX;
- subTrackParamTypes[1] = AnimParamType::RotationY;
- subTrackParamTypes[2] = AnimParamType::RotationZ;
- IAnimTrack* pTrack = aznew CCompoundSplineTrack(3, AnimValueType::Quat, subTrackParamTypes, false);
- return pTrack;
- }
- else if (paramType == AnimParamType::DepthOfField)
- {
- subTrackParamTypes[0] = AnimParamType::FocusDistance;
- subTrackParamTypes[1] = AnimParamType::FocusRange;
- subTrackParamTypes[2] = AnimParamType::BlurAmount;
- IAnimTrack* pTrack = aznew CCompoundSplineTrack(3, AnimValueType::Vector, subTrackParamTypes, false);
- pTrack->SetSubTrackName(0, "FocusDist");
- pTrack->SetSubTrackName(1, "FocusRange");
- pTrack->SetSubTrackName(2, "BlurAmount");
- return pTrack;
- }
- else if (animValue == AnimValueType::RGB || paramType == AnimParamType::LightDiffuse ||
- paramType == AnimParamType::MaterialDiffuse || paramType == AnimParamType::MaterialSpecular
- || paramType == AnimParamType::MaterialEmissive)
- {
- subTrackParamTypes[0] = AnimParamType::ColorR;
- subTrackParamTypes[1] = AnimParamType::ColorG;
- subTrackParamTypes[2] = AnimParamType::ColorB;
- IAnimTrack* pTrack = aznew CCompoundSplineTrack(3, AnimValueType::RGB, subTrackParamTypes, false);
- pTrack->SetSubTrackName(0, "Red");
- pTrack->SetSubTrackName(1, "Green");
- pTrack->SetSubTrackName(2, "Blue");
- return pTrack;
- }
- return aznew CCompoundSplineTrack(3, AnimValueType::Vector, subTrackParamTypes, false);
- }
- IAnimTrack* CAnimNode::CreateTrackInternalQuat([[maybe_unused]] EAnimCurveType trackType, const CAnimParamType& paramType) const
- {
- CAnimParamType subTrackParamTypes[MAX_SUBTRACKS];
- if (paramType == AnimParamType::Rotation)
- {
- subTrackParamTypes[0] = AnimParamType::RotationX;
- subTrackParamTypes[1] = AnimParamType::RotationY;
- subTrackParamTypes[2] = AnimParamType::RotationZ;
- }
- else
- {
- // Unknown param type
- assert(0);
- }
- return aznew CCompoundSplineTrack(3, AnimValueType::Quat, subTrackParamTypes, false);
- }
- IAnimTrack* CAnimNode::CreateTrackInternalVector4(const CAnimParamType& paramType) const
- {
- IAnimTrack* pTrack;
- CAnimParamType subTrackParamTypes[MAX_SUBTRACKS];
- // set up track subtypes
- if (paramType == AnimParamType::TransformNoise
- || paramType == AnimParamType::ShakeMultiplier)
- {
- subTrackParamTypes[0] = AnimParamType::ShakeAmpAMult;
- subTrackParamTypes[1] = AnimParamType::ShakeAmpBMult;
- subTrackParamTypes[2] = AnimParamType::ShakeFreqAMult;
- subTrackParamTypes[3] = AnimParamType::ShakeFreqBMult;
- }
- else
- {
- // default to a Vector4 of floats
- for (unsigned int i = 0; i < MAX_SUBTRACKS; ++i)
- {
- subTrackParamTypes[i] = AnimParamType::Float;
- }
- }
- // create track
- pTrack = aznew CCompoundSplineTrack(4, AnimValueType::Vector4, subTrackParamTypes, true);
- // label subtypes
- if (paramType == AnimParamType::TransformNoise)
- {
- pTrack->SetSubTrackName(0, "Pos Noise Amp");
- pTrack->SetSubTrackName(1, "Pos Noise Freq");
- pTrack->SetSubTrackName(2, "Rot Noise Amp");
- pTrack->SetSubTrackName(3, "Rot Noise Freq");
- }
- else if (paramType == AnimParamType::ShakeMultiplier)
- {
- pTrack->SetSubTrackName(0, "Amplitude A");
- pTrack->SetSubTrackName(1, "Amplitude B");
- pTrack->SetSubTrackName(2, "Frequency A");
- pTrack->SetSubTrackName(3, "Frequency B");
- }
- return pTrack;
- }
- void CAnimNode::TimeChanged(float newTime)
- {
- // if the newTime is on a sound key, then reset sounds so sound will playback on next call to Animate()
- if (IsTimeOnSoundKey(newTime))
- {
- ResetSounds();
- }
- }
- bool CAnimNode::IsTimeOnSoundKey(float queryTime) const
- {
- bool retIsTimeOnSoundKey = false;
- const float tolerance = 0.0333f; // one frame at 30 fps
- int trackCount = NumTracks();
- for (int trackIndex = 0; trackIndex < trackCount; trackIndex++)
- {
- CAnimParamType paramType = m_tracks[trackIndex]->GetParameterType();
- IAnimTrack* pTrack = m_tracks[trackIndex].get();
- if ((paramType.GetType() != AnimParamType::Sound)
- || (pTrack->HasKeys() == false && pTrack->GetParameterType() != AnimParamType::Visibility)
- || (pTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Disabled))
- {
- continue;
- }
- // if we're here, pTrack points to a AnimParamType::Sound track
- ISoundKey oSoundKey;
- int const nSoundKey = static_cast<CSoundTrack*>(pTrack)->GetActiveKey(queryTime, &oSoundKey);
- if (nSoundKey >= 0)
- {
- retIsTimeOnSoundKey = AZ::IsClose(queryTime, oSoundKey.time, tolerance);
- if (retIsTimeOnSoundKey)
- {
- break; // no need to search further, we have a hit
- }
- }
- }
- return retIsTimeOnSoundKey;
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::AnimateSound(std::vector<SSoundInfo>& nodeSoundInfo, SAnimContext& ec, IAnimTrack* pTrack, size_t numAudioTracks)
- {
- bool const bMute = gEnv->IsEditor() && (pTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Muted);
- if (!bMute && ec.time >= 0.0f)
- {
- ISoundKey oSoundKey;
- int const nSoundKey = static_cast<CSoundTrack*>(pTrack)->GetActiveKey(ec.time, &oSoundKey);
- SSoundInfo& rSoundInfo = nodeSoundInfo[numAudioTracks - 1];
- if (nSoundKey >= 0)
- {
- float const fSoundKeyTime = (ec.time - oSoundKey.time);
- if (rSoundInfo.nSoundKeyStart < nSoundKey && fSoundKeyTime < oSoundKey.fDuration)
- {
- ApplyAudioKey(oSoundKey.sStartTrigger.c_str());
- }
- if (rSoundInfo.nSoundKeyStart > nSoundKey)
- {
- rSoundInfo.nSoundKeyStop = nSoundKey;
- }
- rSoundInfo.nSoundKeyStart = nSoundKey;
- if (fSoundKeyTime >= oSoundKey.fDuration)
- {
- if (rSoundInfo.nSoundKeyStop < nSoundKey)
- {
- rSoundInfo.nSoundKeyStop = nSoundKey;
- if (oSoundKey.sStopTrigger.empty())
- {
- ApplyAudioKey(oSoundKey.sStartTrigger.c_str(), false);
- }
- else
- {
- ApplyAudioKey(oSoundKey.sStopTrigger.c_str());
- }
- }
- }
- else
- {
- rSoundInfo.nSoundKeyStop = -1;
- }
- }
- else
- {
- rSoundInfo.Reset();
- }
- }
- }
- void CAnimNode::SetParent(IAnimNode* parent)
- {
- m_pParentNode = parent;
- if (parent)
- {
- m_parentNodeId = static_cast<CAnimNode*>(m_pParentNode)->GetId();
- }
- else
- {
- m_parentNodeId = 0;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- IAnimNode* CAnimNode::HasDirectorAsParent() const
- {
- IAnimNode* pParent = GetParent();
- while (pParent)
- {
- if (pParent->GetType() == AnimNodeType::Director)
- {
- return pParent;
- }
- // There are some invalid data.
- if (pParent->GetParent() == pParent)
- {
- pParent->SetParent(NULL);
- return NULL;
- }
- pParent = pParent->GetParent();
- }
- return NULL;
- }
- void CAnimNode::UpdateDynamicParams()
- {
- if (gEnv->IsEditor())
- {
- // UpdateDynamicParams is called as the result of an editor event that is fired when a material is loaded,
- // which could happen from multiple threads. Lock to avoid a crash iterating over the lua stack
- AZStd::lock_guard<AZStd::mutex> lock(m_updateDynamicParamsLock);
- // run this on the main thread to prevent further threading issues downstream in
- // AnimNodes that may use EBuses that are not thread safe
- if (gEnv && gEnv->mMainThreadId == CryGetCurrentThreadId())
- {
- UpdateDynamicParamsInternal();
- }
- else
- {
- AZ::TickBus::QueueFunction([this] {
- UpdateDynamicParamsInternal();
- });
- }
- }
- else
- {
- UpdateDynamicParamsInternal();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CAnimNode::SetExpanded(bool expanded)
- {
- m_expanded = expanded;
- }
- //////////////////////////////////////////////////////////////////////////
- bool CAnimNode::GetExpanded() const
- {
- return m_expanded;
- }
- IMovieSystem* CAnimNode::GetMovieSystem() const
- {
- return AZ::Interface<IMovieSystem>::Get();
- };
|