123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712 |
- /*
- * 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 "EditorDefs.h"
- #include "TrackViewNode.h"
- // CryCommon
- #include <CryCommon/Maestro/Types/AnimNodeType.h>
- // AzCore
- #include <AzCore/std/sort.h>
- // Editor
- #include "TrackView/TrackViewTrack.h"
- #include "TrackView/TrackViewSequence.h"
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyConstHandle::GetKey(IKey* pKey) const
- {
- m_pTrack->GetKey(m_keyIndex, pKey);
- }
- ////////////////////////////////////////////////////////////////////////////
- float CTrackViewKeyConstHandle::GetTime() const
- {
- return m_pTrack->GetKeyTime(m_keyIndex);
- }
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyHandle::SetKey(IKey* pKey)
- {
- assert(m_bIsValid);
- m_pTrack->SetKey(m_keyIndex, pKey);
- }
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyHandle::GetKey(IKey* pKey) const
- {
- assert(m_bIsValid);
- m_pTrack->GetKey(m_keyIndex, pKey);
- }
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyHandle::Select(bool bSelect)
- {
- assert(m_bIsValid);
- m_pTrack->SelectKey(m_keyIndex, bSelect);
- }
- ////////////////////////////////////////////////////////////////////////////
- bool CTrackViewKeyHandle::IsSelected() const
- {
- assert(m_bIsValid);
- return m_pTrack->IsKeySelected(m_keyIndex);
- }
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyHandle::SetTime(float time, bool notifyListeners)
- {
- AZ_Assert(m_bIsValid, "Expected a valid key handle.");
- // Flag the current key, because the key handle may become invalid
- // after the time is set and it is potentially sorted into a different
- // index.
- m_pTrack->SetSortMarkerKey(m_keyIndex, true);
- // set the new time, this may cause a sort that reorders the keys, making
- // m_keyIndex incorrect.
- m_pTrack->SetKeyTime(m_keyIndex, time, notifyListeners);
- // If the key at this index changed because of the key sort by time.
- // We need to search through the keys now and find the marker.
- if (!m_pTrack->IsSortMarkerKey(m_keyIndex))
- {
- CTrackViewKeyBundle allKeys = m_pTrack->GetAllKeys();
- for (unsigned int x = 0; x < allKeys.GetKeyCount(); x++)
- {
- unsigned int curIndex = allKeys.GetKey(x).GetIndex();
- if (m_pTrack->IsSortMarkerKey(curIndex))
- {
- m_keyIndex = curIndex;
- break;
- }
- }
- }
- // clear the sort marker
- m_pTrack->SetSortMarkerKey(m_keyIndex, false);
- }
- ////////////////////////////////////////////////////////////////////////////
- float CTrackViewKeyHandle::GetTime() const
- {
- assert(m_bIsValid);
- return m_pTrack->GetKeyTime(m_keyIndex);
- }
- ////////////////////////////////////////////////////////////////////////////
- float CTrackViewKeyHandle::GetDuration() const
- {
- assert(m_bIsValid);
- const char* desc = nullptr;
- float duration = 0;
- m_pTrack->m_pAnimTrack->GetKeyInfo(m_keyIndex, desc, duration);
- return duration;
- }
- ////////////////////////////////////////////////////////////////////////////
- const char* CTrackViewKeyHandle::GetDescription() const
- {
- assert(m_bIsValid);
- const char* desc = "";
- float duration = 0;
- m_pTrack->m_pAnimTrack->GetKeyInfo(m_keyIndex, desc, duration);
- return desc;
- }
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyHandle::Offset(float offset, bool notifyListeners)
- {
- AZ_Assert(m_bIsValid, "Expected key handle to be in a valid state.");
- float newTime = m_pTrack->GetKeyTime(m_keyIndex) + offset;
- m_pTrack->SetKeyTime(m_keyIndex, newTime, notifyListeners);
- }
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyHandle::Delete()
- {
- assert(m_bIsValid);
- m_pTrack->RemoveKey(m_keyIndex);
- m_bIsValid = false;
- }
- ////////////////////////////////////////////////////////////////////////////
- CTrackViewKeyHandle CTrackViewKeyHandle::Clone()
- {
- assert(m_bIsValid);
- unsigned int newKeyIndex = m_pTrack->CloneKey(m_keyIndex);
- return CTrackViewKeyHandle(m_pTrack, newKeyIndex);
- }
- ////////////////////////////////////////////////////////////////////////////
- CTrackViewKeyHandle CTrackViewKeyHandle::GetNextKey()
- {
- return m_pTrack->GetNextKey(GetTime());
- }
- ////////////////////////////////////////////////////////////////////////////
- CTrackViewKeyHandle CTrackViewKeyHandle::GetPrevKey()
- {
- return m_pTrack->GetPrevKey(GetTime());
- }
- ////////////////////////////////////////////////////////////////////////////
- CTrackViewKeyHandle CTrackViewKeyHandle::GetAboveKey() const
- {
- // Search for track above that has keys
- for (CTrackViewNode* pCurrentNode = m_pTrack->GetAboveNode(); pCurrentNode; pCurrentNode = pCurrentNode->GetAboveNode())
- {
- if (pCurrentNode->GetNodeType() == eTVNT_Track)
- {
- CTrackViewTrack* pCurrentTrack = static_cast<CTrackViewTrack*>(pCurrentNode);
- const unsigned int keyCount = pCurrentTrack->GetKeyCount();
- if (keyCount > 0)
- {
- // Return key with nearest time to this key
- return pCurrentTrack->GetNearestKeyByTime(GetTime());
- }
- }
- }
- return CTrackViewKeyHandle();
- }
- ////////////////////////////////////////////////////////////////////////////
- CTrackViewKeyHandle CTrackViewKeyHandle::GetBelowKey() const
- {
- // Search for track below that has keys
- for (CTrackViewNode* pCurrentNode = m_pTrack->GetBelowNode(); pCurrentNode; pCurrentNode = pCurrentNode->GetBelowNode())
- {
- if (pCurrentNode->GetNodeType() == eTVNT_Track)
- {
- CTrackViewTrack* pCurrentTrack = static_cast<CTrackViewTrack*>(pCurrentNode);
- const unsigned int keyCount = pCurrentTrack->GetKeyCount();
- if (keyCount > 0)
- {
- // Return key with nearest time to this key
- return pCurrentTrack->GetNearestKeyByTime(GetTime());
- }
- }
- }
- return CTrackViewKeyHandle();
- }
- ////////////////////////////////////////////////////////////////////////////
- bool CTrackViewKeyHandle::operator==(const CTrackViewKeyHandle& keyHandle) const
- {
- return m_pTrack == keyHandle.m_pTrack && m_keyIndex == keyHandle.m_keyIndex;
- }
- ////////////////////////////////////////////////////////////////////////////
- bool CTrackViewKeyHandle::operator!=(const CTrackViewKeyHandle& keyHandle) const
- {
- return !(*this == keyHandle);
- }
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyBundle::AppendKey(const CTrackViewKeyHandle& keyHandle)
- {
- // Check if newly added key has different type than existing ones
- if (m_bAllOfSameType && m_keys.size() > 0)
- {
- const CTrackViewKeyHandle& lastKey = m_keys.back();
- const CTrackViewTrack* pMyTrack = keyHandle.GetTrack();
- const CTrackViewTrack* pOtherTrack = lastKey.GetTrack();
- // Check if keys are from sub tracks, always compare types of parent track
- if (pMyTrack->IsSubTrack())
- {
- pMyTrack = static_cast<const CTrackViewTrack*>(pMyTrack->GetParentNode());
- }
- if (pOtherTrack->IsSubTrack())
- {
- pOtherTrack = static_cast<const CTrackViewTrack*>(pOtherTrack->GetParentNode());
- }
- // Do comparison
- if (pMyTrack->GetParameterType() != pOtherTrack->GetParameterType()
- || pMyTrack->GetCurveType() != pOtherTrack->GetCurveType()
- || pMyTrack->GetValueType() != pOtherTrack->GetValueType())
- {
- m_bAllOfSameType = false;
- }
- }
- m_keys.push_back(keyHandle);
- }
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyBundle::AppendKeyBundle(const CTrackViewKeyBundle& bundle)
- {
- for (auto iter = bundle.m_keys.begin(); iter != bundle.m_keys.end(); ++iter)
- {
- AppendKey(*iter);
- }
- }
- ////////////////////////////////////////////////////////////////////////////
- void CTrackViewKeyBundle::SelectKeys(const bool bSelected)
- {
- const unsigned int numKeys = GetKeyCount();
- for (unsigned int i = 0; i < numKeys; ++i)
- {
- GetKey(i).Select(bSelected);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewKeyHandle CTrackViewKeyBundle::GetSingleSelectedKey()
- {
- const unsigned int keyCount = GetKeyCount();
- if (keyCount == 1)
- {
- return m_keys[0];
- }
- else if (keyCount > 1 && keyCount <= 4)
- {
- // All keys must have same time & same parent track
- CTrackViewNode* pFirstParent = m_keys[0].GetTrack()->GetParentNode();
- const float firstTime = m_keys[0].GetTime();
- // Parent must be a track
- if (pFirstParent->GetNodeType() != eTVNT_Track)
- {
- return CTrackViewKeyHandle();
- }
- // Check other keys for equality
- for (unsigned int i = 0; i < keyCount; ++i)
- {
- if (m_keys[i].GetTrack()->GetParentNode() != pFirstParent || m_keys[i].GetTime() != firstTime)
- {
- return CTrackViewKeyHandle();
- }
- }
- return static_cast<CTrackViewTrack*>(pFirstParent)->GetKeyByTime(firstTime);
- }
- return CTrackViewKeyHandle();
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNode::CTrackViewNode(CTrackViewNode* pParent)
- : m_pParentNode(pParent)
- , m_bSelected(false)
- , m_bHidden(false)
- {
- }
- //////////////////////////////////////////////////////////////////////////
- bool CTrackViewNode::HasObsoleteTrack() const
- {
- return HasObsoleteTrackRec(this);
- }
- //////////////////////////////////////////////////////////////////////////
- bool CTrackViewNode::HasObsoleteTrackRec(const CTrackViewNode* pCurrentNode) const
- {
- if (pCurrentNode->GetNodeType() == eTVNT_Track)
- {
- const CTrackViewTrack* pTrack = static_cast<const CTrackViewTrack*>(pCurrentNode);
- EAnimCurveType trackType = pTrack->GetCurveType();
- if (trackType == eAnimCurveType_TCBFloat || trackType == eAnimCurveType_TCBQuat || trackType == eAnimCurveType_TCBVector)
- {
- return true;
- }
- }
- for (unsigned int i = 0; i < pCurrentNode->GetChildCount(); ++i)
- {
- CTrackViewNode* pNode = pCurrentNode->GetChild(i);
- if (HasObsoleteTrackRec(pNode))
- {
- return true;
- }
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNode::ClearSelection()
- {
- CTrackViewSequenceNotificationContext context(GetSequence());
- SetSelected(false);
- const unsigned int numChilds = GetChildCount();
- for (unsigned int childIndex = 0; childIndex < numChilds; ++childIndex)
- {
- GetChild(childIndex)->ClearSelection();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNode* CTrackViewNode::GetAboveNode() const
- {
- CTrackViewNode* pParent = GetParentNode();
- if (!pParent)
- {
- // The root does not have an above node
- return nullptr;
- }
- CTrackViewNode* pPrevSibling = GetPrevSibling();
- if (!pPrevSibling)
- {
- // First sibling -> parent is above node
- return pParent;
- }
- // Find last node in sibling tree
- CTrackViewNode* pCurrentNode = pPrevSibling;
- while (pCurrentNode && pCurrentNode->GetChildCount() > 0 && pCurrentNode->GetExpanded())
- {
- pCurrentNode = pCurrentNode->GetChild(pCurrentNode->GetChildCount() - 1);
- }
- return pCurrentNode;
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNode* CTrackViewNode::GetBelowNode() const
- {
- const unsigned int childCount = GetChildCount();
- if (childCount > 0 && GetExpanded())
- {
- return GetChild(0);
- }
- CTrackViewNode* pParent = GetParentNode();
- if (!pParent)
- {
- // Root without children
- return nullptr;
- }
- // If there is a next sibling return it
- CTrackViewNode* pNextSibling = GetNextSibling();
- if (pNextSibling)
- {
- return pNextSibling;
- }
- // Otherwise we need to go up the tree and check
- // the parent nodes for next siblings
- CTrackViewNode* pCurrentNode = pParent;
- while (pCurrentNode)
- {
- CTrackViewNode* pNextParentSibling = pCurrentNode->GetNextSibling();
- if (pNextParentSibling)
- {
- return pNextParentSibling;
- }
- pCurrentNode = pCurrentNode->GetParentNode();
- }
- return nullptr;
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNode* CTrackViewNode::GetPrevSibling() const
- {
- CTrackViewNode* pParent = GetParentNode();
- if (!pParent)
- {
- // The root does not have siblings
- return nullptr;
- }
- // Search for prev sibling
- unsigned int siblingCount = pParent->GetChildCount();
- assert(siblingCount > 0);
- for (unsigned int i = 1; i < siblingCount; ++i)
- {
- CTrackViewNode* pSibling = pParent->GetChild(i);
- if (pSibling == this)
- {
- return pParent->GetChild(i - 1);
- }
- }
- return nullptr;
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNode* CTrackViewNode::GetNextSibling() const
- {
- CTrackViewNode* pParent = GetParentNode();
- if (!pParent)
- {
- // The root does not have siblings
- return nullptr;
- }
- // Search for next sibling
- unsigned int siblingCount = pParent->GetChildCount();
- assert(siblingCount > 0);
- for (unsigned int i = 0; i < siblingCount - 1; ++i)
- {
- CTrackViewNode* pSibling = pParent->GetChild(i);
- if (pSibling == this)
- {
- return pParent->GetChild(i + 1);
- }
- }
- return nullptr;
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNode::SetSelected(bool bSelected)
- {
- if (bSelected != m_bSelected)
- {
- m_bSelected = bSelected;
- if (m_bSelected)
- {
- GetSequence()->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Selected);
- }
- else
- {
- GetSequence()->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Deselected);
- }
- GetSequence()->OnNodeSelectionChanged();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewSequence* CTrackViewNode::GetSequence()
- {
- for (CTrackViewNode* pCurrentNode = this; pCurrentNode; pCurrentNode = pCurrentNode->GetParentNode())
- {
- if (pCurrentNode->GetNodeType() == eTVNT_Sequence)
- {
- return static_cast<CTrackViewSequence*>(pCurrentNode);
- }
- }
- // Every node belongs to a sequence
- assert(false);
- return nullptr;
- }
- //////////////////////////////////////////////////////////////////////////
- const CTrackViewSequence* CTrackViewNode::GetSequenceConst() const
- {
- for (const CTrackViewNode* pCurrentNode = this; pCurrentNode; pCurrentNode = pCurrentNode->GetParentNode())
- {
- if (pCurrentNode->GetNodeType() == eTVNT_Sequence)
- {
- return static_cast<const CTrackViewSequence*>(pCurrentNode);
- }
- }
- AZ_Assert(false, "Every node belongs to a sequence");
- return nullptr;
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNode::AddNode(CTrackViewNode* pNode)
- {
- assert (pNode->GetNodeType() != eTVNT_Sequence);
- m_childNodes.push_back(std::unique_ptr<CTrackViewNode>(pNode));
- SortNodes();
- pNode->m_pParentNode = this;
- GetSequence()->OnNodeChanged(pNode, ITrackViewSequenceListener::eNodeChangeType_Added);
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNode::SortNodes()
- {
- // Sort with operator<
- AZStd::stable_sort(m_childNodes.begin(), m_childNodes.end(),
- [&](const std::unique_ptr<CTrackViewNode>& a, const std::unique_ptr<CTrackViewNode>& b) -> bool
- {
- const CTrackViewNode* pA = a.get();
- const CTrackViewNode* pB = b.get();
- return *pA < *pB;
- }
- );
- }
- namespace
- {
- static int GetNodeOrder(AnimNodeType nodeType)
- {
- AZ_Assert(nodeType < AnimNodeType::Num, "Expected nodeType to be less than AnimNodeType::Num");
- // note: this array gets over-allocated and is sparsely populated because the eAnimNodeType enums are not sequential in IMovieSystem.h
- // I wonder if the original authors intended this? Not a big deal, just some trivial memory wastage.
- static int nodeOrder[static_cast<int>(AnimNodeType::Num)];
- nodeOrder[static_cast<int>(AnimNodeType::Invalid)] = 0;
- nodeOrder[static_cast<int>(AnimNodeType::Director)] = 1;
- nodeOrder[static_cast<int>(AnimNodeType::Alembic)] = 4;
- nodeOrder[static_cast<int>(AnimNodeType::CVar)] = 6;
- nodeOrder[static_cast<int>(AnimNodeType::ScriptVar)] = 7;
- nodeOrder[static_cast<int>(AnimNodeType::Event)] = 9;
- nodeOrder[static_cast<int>(AnimNodeType::Layer)] = 10;
- nodeOrder[static_cast<int>(AnimNodeType::Comment)] = 11;
- nodeOrder[static_cast<int>(AnimNodeType::RadialBlur)] = 12;
- nodeOrder[static_cast<int>(AnimNodeType::ColorCorrection)] = 13;
- nodeOrder[static_cast<int>(AnimNodeType::DepthOfField)] = 14;
- nodeOrder[static_cast<int>(AnimNodeType::ScreenFader)] = 15;
- nodeOrder[static_cast<int>(AnimNodeType::Light)] = 16;
- nodeOrder[static_cast<int>(AnimNodeType::ShadowSetup)] = 17;
- nodeOrder[static_cast<int>(AnimNodeType::Group)] = 18;
- return nodeOrder[static_cast<int>(nodeType)];
- }
- }
- bool CTrackViewNode::operator<(const CTrackViewNode& otherNode) const
- {
- // Order nodes before tracks
- if (GetNodeType() < otherNode.GetNodeType())
- {
- return true;
- }
- else if (GetNodeType() > otherNode.GetNodeType())
- {
- return false;
- }
- // Same node type
- switch (GetNodeType())
- {
- case eTVNT_AnimNode:
- {
- const CTrackViewAnimNode& thisAnimNode = static_cast<const CTrackViewAnimNode&>(*this);
- const CTrackViewAnimNode& otherAnimNode = static_cast<const CTrackViewAnimNode&>(otherNode);
- const int thisTypeOrder = GetNodeOrder(thisAnimNode.GetType());
- const int otherTypeOrder = GetNodeOrder(otherAnimNode.GetType());
- if (thisTypeOrder == otherTypeOrder)
- {
- // Same node type, sort by name
- return thisAnimNode.GetName() < otherAnimNode.GetName();
- }
- return thisTypeOrder < otherTypeOrder;
- }
- case eTVNT_Track:
- const CTrackViewTrack& thisTrack = static_cast<const CTrackViewTrack&>(*this);
- const CTrackViewTrack& otherTrack = static_cast<const CTrackViewTrack&>(otherNode);
- if (thisTrack.GetParameterType() == otherTrack.GetParameterType())
- {
- // Same parameter type, sort by name
- return thisTrack.GetName() < otherTrack.GetName();
- }
- return thisTrack.GetParameterType() < otherTrack.GetParameterType();
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNode::SetHidden(bool bHidden)
- {
- bool bWasHidden = m_bHidden;
- m_bHidden = bHidden;
- if (bHidden && !bWasHidden)
- {
- GetSequence()->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Hidden);
- }
- else if (!bHidden && bWasHidden)
- {
- GetSequence()->OnNodeChanged(this, ITrackViewSequenceListener::eNodeChangeType_Unhidden);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- bool CTrackViewNode::IsHidden() const
- {
- return m_bHidden;
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNode* CTrackViewNode::GetFirstSelectedNode()
- {
- if (IsSelected())
- {
- return this;
- }
- const unsigned int numChilds = GetChildCount();
- for (unsigned int childIndex = 0; childIndex < numChilds; ++childIndex)
- {
- CTrackViewNode* pSelectedNode = GetChild(childIndex)->GetFirstSelectedNode();
- if (pSelectedNode)
- {
- return pSelectedNode;
- }
- }
- return nullptr;
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewAnimNode* CTrackViewNode::GetDirector()
- {
- for (CTrackViewNode* pCurrentNode = GetParentNode(); pCurrentNode; pCurrentNode = pCurrentNode->GetParentNode())
- {
- if (pCurrentNode->GetNodeType() == eTVNT_AnimNode)
- {
- CTrackViewAnimNode* pParentAnimNode = static_cast<CTrackViewAnimNode*>(pCurrentNode);
- if (pParentAnimNode->GetType() == AnimNodeType::Director)
- {
- return pParentAnimNode;
- }
- }
- else if (pCurrentNode->GetNodeType() == eTVNT_Sequence)
- {
- return static_cast<CTrackViewAnimNode*>(pCurrentNode);
- }
- }
- return nullptr;
- }
|