12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603 |
- /*
- * 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
- *
- */
- // Description : TrackView's tree control.
- #include "EditorDefs.h"
- #include "TrackViewNodes.h"
- // Qt
- #include <QAction>
- #include <QCompleter>
- #include <QDropEvent>
- #include <QFileDialog>
- #include <QInputDialog>
- #include <QMenu>
- #include <QMessageBox>
- #include <QMimeData>
- #include <QScrollBar>
- #include <QStyledItemDelegate>
- // AzToolsFramework
- #include <AzToolsFramework/Entity/EditorEntitySearchBus.h>
- #include <AzToolsFramework/ToolsComponents/GenericComponentWrapper.h>
- // AzQtComponents
- #include <AzQtComponents/Components/InputDialog.h>
- #include <AzQtComponents/Components/Widgets/ColorPicker.h>
- #include <AzQtComponents/Components/Widgets/FileDialog.h>
- // CryCommon
- #include <CryCommon/Maestro/Bus/EditorSequenceComponentBus.h>
- #include <CryCommon/Maestro/Types/AnimValueType.h>
- #include <CryCommon/Maestro/Types/AnimNodeType.h>
- #include <CryCommon/Maestro/Types/AnimParamType.h>
- #include <CryCommon/Maestro/Types/SequenceType.h>
- // Editor
- #include "TrackView/TVEventsDialog.h"
- #include "TrackView/TrackViewDialog.h"
- #include "Util/AutoDirectoryRestoreFileDialog.h"
- #include "TrackViewFBXImportPreviewDialog.h"
- #include "AnimationContext.h"
- CTrackViewNodesCtrl::CRecord::CRecord(CTrackViewNode* pNode /*= nullptr*/)
- : m_pNode(pNode)
- , m_bVisible(false)
- {
- if (pNode)
- {
- QVariant v;
- v.setValue<CTrackViewNodePtr>(pNode);
- setData(0, Qt::UserRole, v);
- }
- }
- class CTrackViewNodesCtrlDelegate
- : public QStyledItemDelegate
- {
- public:
- CTrackViewNodesCtrlDelegate(QObject* parent = nullptr)
- : QStyledItemDelegate(parent)
- {}
- void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
- {
- bool enabled = index.data(CTrackViewNodesCtrl::CRecord::EnableRole).toBool();
- QStyleOptionViewItem opt = option;
- if (!enabled)
- {
- opt.state &= ~QStyle::State_Enabled;
- }
- QStyledItemDelegate::paint(painter, opt, index);
- }
- };
- class CTrackViewNodesTreeWidget
- : public QTreeWidget
- {
- public:
- CTrackViewNodesTreeWidget(QWidget* parent)
- : QTreeWidget(parent)
- , m_controller(nullptr)
- {
- setItemDelegate(new CTrackViewNodesCtrlDelegate(this));
- }
- void setController(CTrackViewNodesCtrl* p)
- {
- m_controller = p;
- }
- protected:
- // Allow both CopyActions and MoveActions to be valid drag and drop operations.
- Qt::DropActions supportedDropActions() const override
- {
- return Qt::CopyAction | Qt::MoveAction;
- }
- void dragMoveEvent(QDragMoveEvent* event) override
- {
- CTrackViewNodesCtrl::CRecord* record = (CTrackViewNodesCtrl::CRecord*) itemAt(event->pos());
- if (!record)
- {
- return;
- }
- CTrackViewNode* pTargetNode = record->GetNode();
- QTreeWidget::dragMoveEvent(event);
- if (!event->isAccepted())
- {
- return;
- }
- if (pTargetNode && pTargetNode->IsGroupNode() /*&& !m_draggedNodes.DoesContain(pTargetNode)*/)
- {
- CTrackViewAnimNode* pDragTarget = static_cast<CTrackViewAnimNode*>(pTargetNode);
- bool bAllValidReparenting = true;
- QList<CTrackViewAnimNode*> nodes = draggedNodes(event);
- Q_FOREACH(CTrackViewAnimNode * pDraggedNode, nodes)
- {
- if (!pDraggedNode->IsValidReparentingTo(pDragTarget))
- {
- bAllValidReparenting = false;
- break;
- }
- }
- if (!(bAllValidReparenting && !nodes.isEmpty()))
- {
- event->ignore();
- }
- return;
- }
- }
- void dropEvent(QDropEvent* event) override
- {
- CTrackViewNodesCtrl::CRecord* record = (CTrackViewNodesCtrl::CRecord*) itemAt(event->pos());
- if (!record)
- {
- return;
- }
- CTrackViewNode* targetNode = record->GetNode();
- if (targetNode && targetNode->IsGroupNode())
- {
- CTrackViewAnimNode* dragTarget = static_cast<CTrackViewAnimNode*>(targetNode);
- bool allValidReparenting = true;
- QList<CTrackViewAnimNode*> nodes = draggedNodes(event);
- Q_FOREACH(CTrackViewAnimNode * draggedNode, nodes)
- {
- if (!draggedNode->IsValidReparentingTo(dragTarget))
- {
- allValidReparenting = false;
- break;
- }
- }
- if (allValidReparenting && !nodes.isEmpty())
- {
- // By default here the drop action is a CopyAction. That is what we want in case
- // some other random control accepts this drop (and then does nothing with the data).
- // If that happens we will not receive any notifications. If the Action default was MoveAction,
- // the dragged items in the tree would be deleted out from under us causing a crash.
- // Since we are here, we know this drop is on the same control so we can
- // switch it to a MoveAction right now. The node parents will be fixed up below.
- event->setDropAction(Qt::MoveAction);
- QTreeWidget::dropEvent(event);
- if (!event->isAccepted())
- {
- return;
- }
- if (nodes.size() > 0)
- {
- // All nodes are from the same sequence
- CTrackViewSequence* sequence = nodes[0]->GetSequence();
- AZ_Assert(nullptr != sequence, "GetSequence() should never be null");
- AzToolsFramework::ScopedUndoBatch undoBatch("Drag and Drop Track View Nodes");
- Q_FOREACH(CTrackViewAnimNode * draggedNode, nodes)
- {
- draggedNode->SetNewParent(dragTarget);
- undoBatch.MarkEntityDirty(sequence->GetSequenceComponentEntityId());
- }
- }
- }
- }
- }
- void keyPressEvent(QKeyEvent* event) override
- {
- // HAVE TO INCLUDE CASES FOR THESE IN THE ShortcutOverride handler in ::event() below
- switch (event->key())
- {
- case Qt::Key_Tab:
- if (m_controller)
- {
- m_controller->ShowNextResult();
- event->accept();
- }
- return;
- default:
- break;
- }
- QTreeWidget::keyPressEvent(event);
- }
- bool event(QEvent* e) override
- {
- if (e->type() == QEvent::ShortcutOverride)
- {
- // since we respond to the following things, let Qt know so that shortcuts don't override us
- bool respondsToEvent = false;
- QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e);
- if (keyEvent->key() == Qt::Key_Tab)
- {
- respondsToEvent = true;
- }
- if (respondsToEvent)
- {
- e->accept();
- return true;
- }
- }
- return QTreeWidget::event(e);
- }
- bool focusNextPrevChild([[maybe_unused]] bool next) override
- {
- return false; // so we get the tab key
- }
- private:
- QList<CTrackViewAnimNode*> draggedNodes(QDropEvent* event)
- {
- QByteArray encoded = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
- QDataStream stream(&encoded, QIODevice::ReadOnly);
- QList<CTrackViewAnimNode*> nodes;
- while (!stream.atEnd())
- {
- int row, col;
- QMap<int, QVariant> roleDataMap;
- stream >> row >> col >> roleDataMap;
- QVariant v = roleDataMap[Qt::UserRole];
- if (v.isValid())
- {
- CTrackViewNode* pNode = v.value<CTrackViewNodePtr>();
- if (pNode && pNode->GetNodeType() == eTVNT_AnimNode)
- {
- nodes << (CTrackViewAnimNode*)pNode;
- }
- }
- }
- return nodes;
- }
- CTrackViewNodesCtrl* m_controller;
- };
- QDataStream& operator<<(QDataStream& out, const CTrackViewNodePtr& obj)
- {
- out.writeRawData((const char*) &obj, sizeof(obj));
- return out;
- }
- QDataStream& operator>>(QDataStream& in, CTrackViewNodePtr& obj)
- {
- in.readRawData((char*) &obj, sizeof(obj));
- return in;
- }
- enum EMenuItem
- {
- eMI_SelectInViewport = 603,
- eMI_CopyNodes = 605,
- eMI_CopySelectedNodes = 602,
- eMI_PasteNodes = 604,
- eMI_RemoveSelected = 10,
- eMI_CopyKeys = 599,
- eMI_CopySelectedKeys = 600,
- eMI_PasteKeys = 601,
- eMI_AddTrackBase = 1000,
- eMI_RemoveTrack = 299,
- eMI_ExpandAll = 650,
- eMI_CollapseAll = 659,
- eMI_ExpandFolders = 660,
- eMI_CollapseFolders = 661,
- eMI_ExpandEntities = 651,
- eMI_CollapseEntities = 652,
- eMI_ExpandCameras = 653,
- eMI_CollapseCameras = 654,
- eMI_ExpandEvents = 657,
- eMI_CollapseEvents = 658,
- eMI_Rename = 11,
- eMI_CreateFolder = 610,
- eMI_AddSelectedEntities = 500,
- eMI_AddDirectorNode = 501,
- eMI_AddConsoleVariable = 502,
- eMI_AddScriptVariable = 503,
- eMI_AddEvent = 505,
- eMI_AddCurrentLayer = 506,
- eMI_AddCommentNode = 507,
- eMI_AddRadialBlur = 508,
- eMI_AddColorCorrection = 509,
- eMI_AddDOF = 510,
- eMI_AddScreenfader = 511,
- eMI_AddShadowSetup = 513,
- eMI_EditEvents = 550,
- eMI_SaveToFBX = 12,
- eMI_ImportFromFBX = 14,
- eMI_SetAsViewCamera = 13,
- eMI_SetAsActiveDirector = 15,
- eMI_Disable = 17,
- eMI_Mute = 18,
- eMI_CustomizeTrackColor = 19,
- eMI_ClearCustomTrackColor = 20,
- eMI_ShowHideBase = 100,
- eMI_SelectSubmaterialBase = 2000,
- eMI_SetAnimationLayerBase = 3000,
- };
- // The 'MI' represents a Menu Item.
- AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
- #include <TrackView/ui_TrackViewNodes.h>
- AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNodesCtrl::CTrackViewNodesCtrl(QWidget* hParentWnd, CTrackViewDialog* parent /* = 0 */)
- : QWidget(hParentWnd)
- , m_bIgnoreNotifications(false)
- , m_bNeedReload(false)
- , m_bSelectionChanging(false)
- , ui(new Ui::CTrackViewNodesCtrl)
- , m_pTrackViewDialog(parent)
- {
- ui->setupUi(this);
- m_pDopeSheet = nullptr;
- m_currentMatchIndex = 0;
- m_matchCount = 0;
- qRegisterMetaType<CTrackViewNodePtr>("CTrackViewNodePtr");
- qRegisterMetaTypeStreamOperators<CTrackViewNodePtr>("CTrackViewNodePtr");
- ui->treeWidget->hide();
- ui->searchField->hide();
- ui->searchCount->hide();
- ui->searchField->installEventFilter(this);
- ui->treeWidget->setController(this);
- ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
- connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this, &CTrackViewNodesCtrl::OnNMRclick);
- connect(ui->treeWidget, &QTreeWidget::itemExpanded, this, &CTrackViewNodesCtrl::OnItemExpanded);
- connect(ui->treeWidget, &QTreeWidget::itemCollapsed, this, &CTrackViewNodesCtrl::OnItemExpanded);
- connect(ui->treeWidget, &QTreeWidget::itemSelectionChanged, this, &CTrackViewNodesCtrl::OnSelectionChanged);
- connect(ui->treeWidget, &QTreeWidget::itemDoubleClicked, this, &CTrackViewNodesCtrl::OnItemDblClick);
- connect(ui->searchField, &QLineEdit::textChanged, this, &CTrackViewNodesCtrl::OnFilterChange);
- m_bEditLock = false;
- m_arrowCursor = Qt::ArrowCursor;
- m_noIcon = Qt::ForbiddenCursor;
- ///////////////////////////////////////////////////////////////
- // Populate m_componentTypeToIconMap with all component icons
- AZ::SerializeContext* serializeContext = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
- AZ_Assert(serializeContext, "Failed to acquire serialize context.");
- serializeContext->EnumerateDerived<AZ::Component>([this](const AZ::SerializeContext::ClassData* classData, const AZ::Uuid&) -> bool
- {
- AZStd::string iconPath;
- AzToolsFramework::EditorRequestBus::BroadcastResult(iconPath, &AzToolsFramework::EditorRequests::GetComponentTypeEditorIcon, classData->m_typeId);
- if (!iconPath.empty())
- {
- m_componentTypeToIconMap[classData->m_typeId] = QIcon(iconPath.c_str());
- }
- return true; // continue enumerating
- });
- ///////////////////////////////////////////////////////////////
- GetIEditor()->GetSequenceManager()->AddListener(this);
- GetIEditor()->GetAnimation()->AddListener(this);
- GetIEditor()->GetUndoManager()->AddListener(this);
- };
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNodesCtrl::~CTrackViewNodesCtrl()
- {
- GetIEditor()->GetUndoManager()->RemoveListener(this);
- GetIEditor()->GetAnimation()->RemoveListener(this);
- GetIEditor()->GetSequenceManager()->RemoveListener(this);
- }
- bool CTrackViewNodesCtrl::eventFilter(QObject* o, QEvent* e)
- {
- if (o == ui->searchField && e->type() == QEvent::KeyPress)
- {
- QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e);
- if (keyEvent->key() == Qt::Key_Tab && keyEvent->modifiers() == Qt::NoModifier)
- {
- ShowNextResult();
- return true;
- }
- }
- return QWidget::eventFilter(o, e);
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnSequenceChanged()
- {
- assert(m_pTrackViewDialog);
- m_nodeToRecordMap.clear();
- ui->treeWidget->clear();
- FillAutoCompletionListForFilter();
- Reload();
- }
- // IAnimationContextListener
- void CTrackViewNodesCtrl::OnSequenceChanged([[maybe_unused]]CTrackViewSequence* pNewSequence)
- {
- OnSequenceChanged();
- }
- // ITrackViewSequenceManagerListener
- void CTrackViewNodesCtrl::OnSequenceRemoved([[maybe_unused]] CTrackViewSequence* pSequence)
- {
- OnSequenceChanged();
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::SetDopeSheet(CTrackViewDopeSheetBase* pDopeSheet)
- {
- m_pDopeSheet = pDopeSheet;
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNodesCtrl::CRecord* CTrackViewNodesCtrl::AddAnimNodeRecord(CRecord* pParentRecord, CTrackViewAnimNode* animNode)
- {
- CRecord* pNewRecord = new CRecord(animNode);
- pNewRecord->setText(0, QString::fromUtf8(animNode->GetName().c_str()));
- UpdateAnimNodeRecord(pNewRecord, animNode);
- pParentRecord->insertChild(GetInsertPosition(pParentRecord, animNode), pNewRecord);
- FillNodesRec(pNewRecord, animNode);
- return pNewRecord;
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNodesCtrl::CRecord* CTrackViewNodesCtrl::AddTrackRecord(CRecord* pParentRecord, CTrackViewTrack* pTrack)
- {
- CRecord* pNewTrackRecord = new CRecord(pTrack);
- pNewTrackRecord->setText(0, QString::fromUtf8(pTrack->GetName().c_str()));
- UpdateTrackRecord(pNewTrackRecord, pTrack);
- pParentRecord->insertChild(GetInsertPosition(pParentRecord, pTrack), pNewTrackRecord);
- FillNodesRec(pNewTrackRecord, pTrack);
- return pNewTrackRecord;
- }
- //////////////////////////////////////////////////////////////////////////
- int CTrackViewNodesCtrl::GetInsertPosition(CRecord* pParentRecord, CTrackViewNode* pNode)
- {
- // Search for insert position
- const int siblingCount = pParentRecord->childCount();
- for (int i = 0; i < siblingCount; ++i)
- {
- CRecord* record = static_cast<CRecord*>(pParentRecord->child(i));
- CTrackViewNode* pSiblingNode = record->GetNode();
- if (*pNode < *pSiblingNode)
- {
- return i;
- }
- }
- return siblingCount;
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::AddNodeRecord(CRecord* record, CTrackViewNode* pNode)
- {
- assert(m_nodeToRecordMap.find(pNode) == m_nodeToRecordMap.end());
- if (m_nodeToRecordMap.find(pNode) != m_nodeToRecordMap.end())
- {
- // For safety. Shouldn't happen
- return;
- }
- CRecord* pNewRecord = nullptr;
- if (pNode->IsHidden())
- {
- return;
- }
- switch (pNode->GetNodeType())
- {
- case eTVNT_AnimNode:
- pNewRecord = AddAnimNodeRecord(record, static_cast<CTrackViewAnimNode*>(pNode));
- break;
- case eTVNT_Track:
- pNewRecord = AddTrackRecord(record, static_cast<CTrackViewTrack*>(pNode));
- break;
- }
- if (pNewRecord)
- {
- if (!pNode->IsGroupNode() && pNode->GetChildCount() == 0) // groups and compound tracks are draggable
- {
- pNewRecord->setFlags(pNewRecord->flags() & ~Qt::ItemIsDragEnabled);
- }
- if (!pNode->IsGroupNode()) // only groups can be dropped into
- {
- pNewRecord->setFlags(pNewRecord->flags() & ~Qt::ItemIsDropEnabled);
- }
- if (pNode->GetExpanded())
- {
- pNewRecord->setExpanded(true);
- }
- if (pNode->IsSelected())
- {
- m_bIgnoreNotifications = true;
- SelectRow(pNode, false, false);
- m_bIgnoreNotifications = false;
- }
- m_nodeToRecordMap[pNode] = pNewRecord;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::FillNodesRec(CRecord* record, CTrackViewNode* pCurrentNode)
- {
- const unsigned int childCount = pCurrentNode->GetChildCount();
- for (unsigned int childIndex = 0; childIndex < childCount; ++childIndex)
- {
- CTrackViewNode* pNode = pCurrentNode->GetChild(childIndex);
- if (!pNode->IsHidden())
- {
- AddNodeRecord(record, pNode);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::UpdateNodeRecord(CRecord* record)
- {
- CTrackViewNode* pNode = record->GetNode();
- if (pNode)
- {
- switch (pNode->GetNodeType())
- {
- case eTVNT_AnimNode:
- UpdateAnimNodeRecord(record, static_cast<CTrackViewAnimNode*>(pNode));
- break;
- case eTVNT_Track:
- UpdateTrackRecord(record, static_cast<CTrackViewTrack*>(pNode));
- break;
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::UpdateTrackRecord(CRecord* record, CTrackViewTrack* pTrack)
- {
- record->setIcon(0, GetIconForTrack(pTrack));
- // Check if parameter is valid for non sub tracks
- CTrackViewAnimNode* animNode = pTrack->GetAnimNode();
- const bool isParamValid = pTrack->IsSubTrack() || animNode->IsParamValid(pTrack->GetParameterType());
- // Check if disabled or muted
- const bool bDisabledOrMuted = pTrack->IsDisabled() || pTrack->IsMuted();
- // If track is not valid and disabled/muted color node in grey
- record->setData(0, CRecord::EnableRole, !bDisabledOrMuted && isParamValid);
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::UpdateAnimNodeRecord(CRecord* record, CTrackViewAnimNode* animNode)
- {
- const QColor TextColorForMissingEntity(226, 52, 43); // LY palette for 'Error/Failure'
- const QColor BackColorForActiveDirector(243, 81, 29); // LY palette for 'Primary'
- const QColor BackColorForInactiveDirector(22, 23, 27); // LY palette for 'Background (In Focus)'
- const QColor BackColorForGroupNodes(42, 84, 244); // LY palette for 'Secondary'
- QFont f = font();
- f.setBold(true);
- record->setFont(0, f);
- AnimNodeType nodeType = animNode->GetType();
- if (nodeType == AnimNodeType::Component)
- {
- // get the component icon from cached component icons
- AZ::Entity* azEntity = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(azEntity, &AZ::ComponentApplicationBus::Events::FindEntity,
- static_cast<CTrackViewAnimNode*>(animNode->GetParentNode())->GetAzEntityId());
- if (azEntity)
- {
- const AZ::Component* component = azEntity->FindComponent(animNode->GetComponentId());
- if (component)
- {
- auto findIter = m_componentTypeToIconMap.find(AzToolsFramework::GetUnderlyingComponentType(*component));
- if (findIter != m_componentTypeToIconMap.end())
- {
- record->setIcon(0, findIter->second);
- }
- }
- }
- }
- else
- {
- record->setIcon(0, TrackViewNodeIcon(nodeType));
- }
- const bool disabled = animNode->IsDisabled();
- record->setData(0, CRecord::EnableRole, !disabled);
- if (nodeType == AnimNodeType::Group)
- {
- record->setBackground(0, BackColorForGroupNodes);
- record->setSizeHint(0, QSize(30, 20));
- }
- else if (nodeType == AnimNodeType::AzEntity)
- {
- AZ::Entity* entity = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(
- entity, &AZ::ComponentApplicationBus::Events::FindEntity, animNode->GetAzEntityId());
- if (!entity)
- {
- // In case of a missing entity, color it red.
- record->setForeground(0, TextColorForMissingEntity);
- }
- else
- {
- record->setData(0, Qt::ForegroundRole, QPalette::ColorRole::NoRole);
- }
- }
- // Mark the active director and other directors properly.
- if (animNode->IsActiveDirector())
- {
- record->setBackground(0, BackColorForActiveDirector);
- }
- else if (nodeType == AnimNodeType::Director)
- {
- record->setBackground(0, BackColorForInactiveDirector);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::Reload()
- {
- ui->treeWidget->clear();
- OnFillItems();
- }
- void CTrackViewNodesCtrl::OnFillItems()
- {
- CTrackViewSequence* sequence = GetIEditor()->GetAnimation()->GetSequence();
- if (sequence)
- {
- CTrackViewSequenceNotificationContext context(sequence);
- m_nodeToRecordMap.clear();
- CRecord* pRootGroupRec = new CRecord(sequence);
- pRootGroupRec->setText(0, QString::fromUtf8(sequence->GetName().c_str()));
- QFont f = font();
- f.setBold(true);
- pRootGroupRec->setData(0, Qt::FontRole, f);
- pRootGroupRec->setSizeHint(0, QSize(width(), 24));
- m_nodeToRecordMap[sequence] = pRootGroupRec;
- ui->treeWidget->addTopLevelItem(pRootGroupRec);
- FillNodesRec(pRootGroupRec, sequence);
- pRootGroupRec->setExpanded(sequence->GetExpanded());
- // Additional empty record like space for scrollbar in key control
- CRecord* pGroupRec = new CRecord();
- pGroupRec->setSizeHint(0, QSize(width(), 18));
- ui->treeWidget->addTopLevelItem(pRootGroupRec);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnItemExpanded(QTreeWidgetItem* item)
- {
- CRecord* record = (CRecord*) item;
- if (record && record->GetNode())
- {
- bool currentlyExpanded = record->GetNode()->GetExpanded();
- bool expanded = item->isExpanded();
- if (expanded != currentlyExpanded)
- {
- bool isDuringUndo = false;
- AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(isDuringUndo, &AzToolsFramework::ToolsApplicationRequests::Bus::Events::IsDuringUndoRedo);
- // Don't record another undo event if this OnItemExpanded callback is fired because we are Undoing or Redoing.
- if (isDuringUndo)
- {
- record->GetNode()->SetExpanded(expanded);
- }
- else
- {
- CTrackViewSequence* sequence = record->GetNode()->GetSequence();
- AZ_Assert(nullptr != sequence, "Expected valid sequence");
- AzToolsFramework::ScopedUndoBatch undoBatch("Set Node Expanded");
- record->GetNode()->SetExpanded(expanded);
- undoBatch.MarkEntityDirty(sequence->GetSequenceComponentEntityId());
- }
- }
- }
- UpdateDopeSheet();
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnSelectionChanged()
- {
- // Need to avoid the second call to this, because GetSelectedRows is broken
- // with multi selection
- if (m_bSelectionChanging)
- {
- return;
- }
- m_bSelectionChanging = true;
- CTrackViewSequence* sequence = GetIEditor()->GetAnimation()->GetSequence();
- if (sequence)
- {
- CTrackViewSequenceNotificationContext context(sequence);
- sequence->ClearSelection();
- QList<QTreeWidgetItem*> items = ui->treeWidget->selectedItems();
- int nCount = items.count();
- for (int i = 0; i < nCount; i++)
- {
- CRecord* record = (CRecord*)items.at(i);
- if (record && record->GetNode())
- {
- if (!record->GetNode()->IsSelected())
- {
- record->GetNode()->SetSelected(true);
- ui->treeWidget->setCurrentItem(record);
- }
- }
- }
- }
- m_bSelectionChanging = false;
- UpdateDopeSheet();
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnNMRclick(QPoint point)
- {
- CRecord* record = nullptr;
- bool isOnAzEntity = false;
- CTrackViewSequence* sequence = GetIEditor()->GetAnimation()->GetSequence();
- if (!sequence)
- {
- return;
- }
- CTrackViewSequenceNotificationContext context(sequence);
- // Find node under mouse.
- // Select the item that is at the point myPoint.
- record = static_cast<CRecord*>(ui->treeWidget->itemAt(point));
- CTrackViewAnimNode* groupNode = nullptr;
- CTrackViewNode* pNode = nullptr;
- CTrackViewAnimNode* animNode = nullptr;
- CTrackViewTrack* pTrack = nullptr;
- if (record && record->GetNode())
- {
- pNode = record->GetNode();
- if (pNode)
- {
- ETrackViewNodeType nodeType = pNode->GetNodeType();
- if (nodeType == eTVNT_AnimNode)
- {
- animNode = static_cast<CTrackViewAnimNode*>(pNode);
- isOnAzEntity = (animNode && animNode->GetType() == AnimNodeType::AzEntity);
- if (animNode->GetType() == AnimNodeType::Director || animNode->GetType() == AnimNodeType::Group || isOnAzEntity)
- {
- groupNode = animNode;
- }
- }
- else if (nodeType == eTVNT_Sequence)
- {
- groupNode = sequence;
- }
- else if (nodeType == eTVNT_Track)
- {
- pTrack = static_cast<CTrackViewTrack*>(pNode);
- animNode = pTrack->GetAnimNode();
- }
- }
- }
- else
- {
- pNode = sequence;
- groupNode = sequence;
- record = m_nodeToRecordMap[sequence];
- }
- int cmd = ShowPopupMenu(point, record);
- float scrollPos = SaveVerticalScrollPos();
- if (cmd == eMI_RemoveSelected)
- {
- // If we are about to delete the sequence, cancel the notification
- // context, otherwise it will notify on a stale sequence pointer.
- if (sequence->IsSelected())
- {
- context.Cancel();
- }
- // Let the AZ Undo system manage the nodes on the sequence entity
- AzToolsFramework::ScopedUndoBatch undoBatch("Delete Selected Nodes/Tracks");
- auto id = sequence->GetSequenceComponentEntityId();
- sequence->DeleteSelectedNodes();
- undoBatch.MarkEntityDirty(id);
- }
- if (groupNode)
- {
- // Group operations applicable to AZEntities and Group Nodes
- if (cmd == eMI_ExpandAll)
- {
- BeginUndoTransaction();
- groupNode->GetAllAnimNodes().ExpandAll();
- EndUndoTransaction();
- }
- else if (cmd == eMI_CollapseAll)
- {
- BeginUndoTransaction();
- groupNode->GetAllAnimNodes().CollapseAll();
- EndUndoTransaction();
- }
- if (!isOnAzEntity)
- {
- // Group operations not applicable to AZEntities
- if (cmd == eMI_AddSelectedEntities)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Entities to Track View");
- CTrackViewAnimNodeBundle addedNodes = groupNode->AddSelectedEntities(m_pTrackViewDialog->GetDefaultTracksForEntityNode());
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- int selectedEntitiesCount = 0;
- AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
- selectedEntitiesCount, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntitiesCount);
- // check to make sure all nodes were added and notify user if they weren't
- if (addedNodes.GetCount() != static_cast<unsigned int>(selectedEntitiesCount))
- {
- IMovieSystem* movieSystem = AZ::Interface<IMovieSystem>::Get();
- AZStd::string messages = movieSystem ? movieSystem->GetUserNotificationMsgs() : "";
- // Create a list of all lines
- AZStd::vector<AZStd::string> lines;
- AzFramework::StringFunc::Tokenize(messages.c_str(), lines, "\n");
- // Truncate very long messages. No information is lost because
- // all of these errors will have been logged to the console already.
- const int maxLines = 30;
- AZStd::string shortMessages;
- if (lines.size() > maxLines)
- {
- int numLines = 0;
- for (AZStd::string line : lines)
- {
- shortMessages += line + "\n";
- if (++numLines >= maxLines)
- {
- break;
- }
- }
- shortMessages += "Message truncated, please see console for a full list of warnings.\n";
- }
- else
- {
- shortMessages = messages;
- }
- QMessageBox::information(this, tr("Track View Warning"), tr(shortMessages.c_str()));
- // clear the notification log now that we've consumed and presented them.
- movieSystem->ClearUserNotificationMsgs();
- }
- groupNode->BindToEditorObjects();
- }
- else if (cmd == eMI_AddCurrentLayer)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Current Layer to Track View");
- groupNode->AddCurrentLayer();
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_AddScreenfader)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Screen Fader Node");
- groupNode->CreateSubNode("ScreenFader", AnimNodeType::ScreenFader);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_AddCommentNode)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Comment Node");
- QString commentNodeName = groupNode->GetAvailableNodeNameStartingWith("Comment");
- groupNode->CreateSubNode(commentNodeName, AnimNodeType::Comment);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_AddRadialBlur)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Radial Blur Node");
- groupNode->CreateSubNode("RadialBlur", AnimNodeType::RadialBlur);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_AddColorCorrection)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Color Correction Node");
- groupNode->CreateSubNode("ColorCorrection", AnimNodeType::ColorCorrection);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_AddDOF)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Depth of Field Node");
- groupNode->CreateSubNode("DepthOfField", AnimNodeType::DepthOfField);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_AddShadowSetup)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Shadow Setup Node");
- groupNode->CreateSubNode("ShadowsSetup", AnimNodeType::ShadowSetup);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_AddDirectorNode)
- {
- QString name = groupNode->GetAvailableNodeNameStartingWith("Director");
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Director Node");
- groupNode->CreateSubNode(name, AnimNodeType::Director);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_AddConsoleVariable)
- {
- QString stringValue = QInputDialog::getText(this, tr("Console Variable Name"), QString());
- if (!stringValue.isEmpty())
- {
- QString name = groupNode->GetAvailableNodeNameStartingWith(stringValue);
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Console (CVar) Node");
- groupNode->CreateSubNode(name, AnimNodeType::CVar);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- }
- else if (cmd == eMI_AddScriptVariable)
- {
- QString stringValue = QInputDialog::getText(this, tr("Script Variable Name"), QString());
- if (!stringValue.isEmpty())
- {
- QString name = groupNode->GetAvailableNodeNameStartingWith(stringValue);
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Script Variable Node");
- groupNode->CreateSubNode(name, AnimNodeType::ScriptVar);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- }
- else if (cmd == eMI_AddEvent)
- {
- QString stringValue = QInputDialog::getText(this, tr("Track Event Name"), QString());
- if (!stringValue.isEmpty())
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add Track View Event Node");
- groupNode->CreateSubNode(stringValue, AnimNodeType::Event);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- }
- else if (cmd == eMI_PasteNodes)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Paste Track View Nodes");
- groupNode->PasteNodesFromClipboard(this);
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_CreateFolder)
- {
- CreateFolder(groupNode);
- }
- else if (cmd == eMI_ExpandFolders)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Expand Track View folders");
- groupNode->GetAnimNodesByType(AnimNodeType::Group).ExpandAll();
- groupNode->GetAnimNodesByType(AnimNodeType::Director).ExpandAll();
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_CollapseFolders)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Collapse Track View folders");
- groupNode->GetAnimNodesByType(AnimNodeType::Group).CollapseAll();
- groupNode->GetAnimNodesByType(AnimNodeType::Director).CollapseAll();
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_ExpandEntities)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Expand Track View entities");
- groupNode->GetAnimNodesByType(AnimNodeType::AzEntity).ExpandAll();
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_CollapseEntities)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Collapse Track View entities");
- groupNode->GetAnimNodesByType(AnimNodeType::AzEntity).CollapseAll();
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_ExpandEvents)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Expand Track View events");
- groupNode->GetAnimNodesByType(AnimNodeType::Event).ExpandAll();
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- else if (cmd == eMI_CollapseEvents)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Collapse Track View events");
- groupNode->GetAnimNodesByType(AnimNodeType::Event).CollapseAll();
- undoBatch.MarkEntityDirty(groupNode->GetSequence()->GetSequenceComponentEntityId());
- }
- }
- }
- if (cmd == eMI_EditEvents)
- {
- EditEvents();
- }
- else if (cmd == eMI_Rename)
- {
- if (animNode || groupNode)
- {
- CTrackViewAnimNode* animNode2 = static_cast<CTrackViewAnimNode*>(pNode);
- QString oldName = QString::fromUtf8(animNode2->GetName().c_str());
- AzQtComponents::InputDialog inputDialog(this);
- inputDialog.setWindowTitle(tr("Rename Node"));
- inputDialog.setTextValue(oldName);
- inputDialog.setLabelText("");
- inputDialog.SetRegularExpressionValidator("[a-zA-Z0-9_\\-\\_]*");
- // Max name length is 512 for a sequence
- constexpr int MaxNameLength = 512;
- inputDialog.SetMaxLength(MaxNameLength);
- // add check for duplicate entity names if this is bound to an Object node
- bool checkForDuplicateName = animNode2->IsBoundToEditorObjects();
- bool retryRename = false;
- QString newName;
- do
- {
- const auto ret = inputDialog.exec();
- if (ret == QDialog::Accepted)
- {
- QString name = inputDialog.textValue();
- // Bail out early if user is trying to rename to the same name, can treat as a no-op
- if (name == oldName)
- {
- return;
- }
- if (checkForDuplicateName)
- {
- AzToolsFramework::EntitySearchFilter filter;
- const auto nameUtf8 = name.toUtf8();
- const AZStd::string searchName(nameUtf8.constData(), nameUtf8.length());
- filter.m_names.push_back(searchName);
- AzToolsFramework::EntityIdList matchingEntities;
- AzToolsFramework::EditorEntitySearchBus::BroadcastResult(matchingEntities, &AzToolsFramework::EditorEntitySearchRequests::SearchEntities, filter);
- if (!matchingEntities.empty())
- {
- QMessageBox::warning(this, tr("Entity already exists"), QString(tr("Entity named '%1' already exists.\n\nPlease choose another unique name.")).arg(name));
- retryRename = true;
- }
- else
- {
- newName = name;
- retryRename = false;
- }
- }
- else
- {
- newName = name;
- }
- }
- else
- {
- retryRename = false;
- }
- } while (retryRename);
- if(!GetNodeRecord(animNode2)) {
- QMessageBox::warning(
- this,
- tr("Entity does not exist"),
- tr("Entity has been deleted.\n\nUnable to rename entity"));
- }
- else if (!newName.isEmpty())
- {
- const CTrackViewSequenceManager* sequenceManager = GetIEditor()->GetSequenceManager();
- sequenceManager->RenameNode(animNode2, newName.toUtf8().data());
- UpdateNodeRecord(record);
- }
- }
- }
- else if (cmd == eMI_SetAsActiveDirector)
- {
- if (pNode && pNode->GetNodeType() == eTVNT_AnimNode)
- {
- CTrackViewAnimNode* animNode2 = static_cast<CTrackViewAnimNode*>(pNode);
- animNode2->SetAsActiveDirector();
- }
- }
- else if (cmd >= eMI_AddTrackBase && cmd < eMI_AddTrackBase + 1000)
- {
- if (animNode)
- {
- unsigned int menuId = cmd - eMI_AddTrackBase;
- if (animNode->GetType() != AnimNodeType::AzEntity)
- {
- // add track
- auto findIter = m_menuParamTypeMap.find(menuId);
- if (findIter != m_menuParamTypeMap.end())
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Add TrackView Track");
- animNode->CreateTrack(findIter->second);
- undoBatch.MarkEntityDirty(animNode->GetSequence()->GetSequenceComponentEntityId());
- }
- }
- }
- }
- else if (cmd == eMI_RemoveTrack)
- {
- if (pTrack)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Remove TrackView Track");
- pTrack->GetAnimNode()->RemoveTrack(pTrack);
- undoBatch.MarkEntityDirty(pTrack->GetSequence()->GetSequenceComponentEntityId());
- }
- }
- else if (cmd >= eMI_ShowHideBase && cmd < eMI_ShowHideBase + 100)
- {
- if (animNode)
- {
- unsigned int childIndex = cmd - eMI_ShowHideBase;
- if (childIndex < animNode->GetChildCount())
- {
- CTrackViewNode* pChild = animNode->GetChild(childIndex);
- pChild->SetHidden(!pChild->IsHidden());
- }
- }
- }
- else if (cmd == eMI_CopyKeys)
- {
- sequence->CopyKeysToClipboard(false, true);
- }
- else if (cmd == eMI_CopySelectedKeys)
- {
- sequence->CopyKeysToClipboard(true, true);
- }
- else if (cmd == eMI_PasteKeys)
- {
- CUndo undo("Paste TrackView Keys");
- sequence->PasteKeysFromClipboard(animNode, pTrack);
- }
- else if (cmd == eMI_CopyNodes)
- {
- if (animNode)
- {
- animNode->CopyNodesToClipboard(false, this);
- }
- else
- {
- sequence->CopyNodesToClipboard(false, this);
- }
- }
- else if (cmd == eMI_CopySelectedNodes)
- {
- sequence->CopyNodesToClipboard(true, this);
- }
- else if (cmd == eMI_SelectInViewport)
- {
- CUndo undo("Select TrackView Nodes in Viewport");
- sequence->SelectSelectedNodesInViewport();
- }
- else if (cmd >= eMI_SelectSubmaterialBase && cmd < eMI_SelectSubmaterialBase + 100)
- {
- if (animNode)
- {
- QString matName;
- GetMatNameAndSubMtlIndexFromName(matName, animNode->GetName().c_str());
- QString newMatName;
- newMatName = tr("%1.[%2]").arg(matName).arg(cmd - eMI_SelectSubmaterialBase + 1);
- CUndo undo("Rename TrackView node");
- animNode->SetName(newMatName.toUtf8().data());
- animNode->SetSelected(true);
- UpdateNodeRecord(record);
- }
- }
- else if (cmd >= eMI_SetAnimationLayerBase && cmd < eMI_SetAnimationLayerBase + 100)
- {
- if (pNode && pNode->GetNodeType() == eTVNT_Track)
- {
- CTrackViewTrack* pTrack2 = static_cast<CTrackViewTrack*>(pNode);
- pTrack2->SetAnimationLayerIndex(cmd - eMI_SetAnimationLayerBase);
- }
- }
- else if (cmd == eMI_Disable)
- {
- if (pNode)
- {
- CTrackViewSequence* sequence2 = pNode->GetSequence();
- AZ_Assert(nullptr != sequence2, "Expected valid sequence");
- AzToolsFramework::ScopedUndoBatch undoBatch("Node Set Disabled");
- pNode->SetDisabled(!pNode->IsDisabled());
- undoBatch.MarkEntityDirty(sequence2->GetSequenceComponentEntityId());
- }
- }
- else if (cmd == eMI_Mute)
- {
- if (pTrack)
- {
- pTrack->SetMuted(!pTrack->IsMuted());
- }
- }
- else if (cmd == eMI_CustomizeTrackColor)
- {
- CustomizeTrackColor(pTrack);
- }
- else if (cmd == eMI_ClearCustomTrackColor)
- {
- if (pTrack)
- {
- pTrack->ClearCustomColor();
- }
- }
- if (cmd)
- {
- RestoreVerticalScrollPos(scrollPos);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnItemDblClick(QTreeWidgetItem* item, int)
- {
- CRecord* record = (CRecord*)item;
- if (record && record->GetNode())
- {
- CTrackViewNode* pNode = record->GetNode();
- if (pNode->GetNodeType() == eTVNT_AnimNode)
- {
- CTrackViewAnimNode* animNode = static_cast<CTrackViewAnimNode*>(pNode);
- if (const AZ::EntityId entityId = animNode->GetAzEntityId();
- entityId.IsValid())
- {
- CUndo undo("Select Object");
- AzToolsFramework::ToolsApplicationRequestBus::Broadcast(
- &AzToolsFramework::ToolsApplicationRequests::SetSelectedEntities,
- AzToolsFramework::EntityIdList{animNode->GetAzEntityId()});
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::EditEvents()
- {
- CTVEventsDialog dlg;
- dlg.exec();
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::CreateFolder(CTrackViewAnimNode* groupNode)
- {
- // Change Group of the node.
- QString name = QInputDialog::getText(this, tr("Enter Folder Name"), QString());
- if (!name.isEmpty())
- {
- CUndo undo("Create folder");
- if (!groupNode->CreateSubNode(name, AnimNodeType::Group))
- {
- QMessageBox::critical(this, QString(), tr("The name already exists. Use another."));
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- struct STrackMenuTreeNode
- {
- QMenu menu;
- CAnimParamType paramType;
- std::map<QString, std::unique_ptr<STrackMenuTreeNode> > children;
- };
- //////////////////////////////////////////////////////////////////////////
- struct SContextMenu
- {
- QMenu main;
- QMenu expandSub;
- QMenu collapseSub;
- QMenu setLayerSub;
- STrackMenuTreeNode addTrackSub;
- QMenu addComponentSub;
- };
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::AddGroupNodeAddItems(SContextMenu& contextMenu, CTrackViewAnimNode* animNode)
- {
- contextMenu.main.addAction("Create Folder")->setData(eMI_CreateFolder);
- AzToolsFramework::EntityIdList entityIds;
- AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(
- entityIds, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
- if (!entityIds.empty())
- {
- const char* msg = entityIds.size() == 1 ? "Add Selected Entity" : "Add Selected Entities";
- contextMenu.main.addAction(msg)->setData(eMI_AddSelectedEntities);
- }
- const bool bIsDirectorOrSequence = (animNode->GetType() == AnimNodeType::Director || animNode->GetNodeType() == eTVNT_Sequence);
- CTrackViewAnimNode* pDirector = bIsDirectorOrSequence ? animNode : animNode->GetDirector();
- if (pDirector->GetAnimNodesByType(AnimNodeType::RadialBlur).GetCount() == 0)
- {
- contextMenu.main.addAction("Add Radial Blur Node")->setData(eMI_AddRadialBlur);
- }
- if (pDirector->GetAnimNodesByType(AnimNodeType::ColorCorrection).GetCount() == 0)
- {
- contextMenu.main.addAction("Add Color Correction Node")->setData(eMI_AddColorCorrection);
- }
- if (pDirector->GetAnimNodesByType(AnimNodeType::DepthOfField).GetCount() == 0)
- {
- contextMenu.main.addAction("Add Depth of Field Node")->setData(eMI_AddDOF);
- }
- if (pDirector->GetAnimNodesByType(AnimNodeType::ScreenFader).GetCount() == 0)
- {
- contextMenu.main.addAction("Add Screen Fader")->setData(eMI_AddScreenfader);
- }
- if (pDirector->GetAnimNodesByType(AnimNodeType::ShadowSetup).GetCount() == 0)
- {
- contextMenu.main.addAction("Add Shadows Setup Node")->setData(eMI_AddShadowSetup);
- }
- // A director node cannot have another director node as a child.
- if (animNode->GetType() != AnimNodeType::Director)
- {
- contextMenu.main.addAction("Add Director(Scene) Node")->setData(eMI_AddDirectorNode);
- }
- contextMenu.main.addAction("Add Comment Node")->setData(eMI_AddCommentNode);
- contextMenu.main.addAction("Add Console Variable Node")->setData(eMI_AddConsoleVariable);
- contextMenu.main.addAction("Add Script Variable Node")->setData(eMI_AddScriptVariable);
- contextMenu.main.addAction("Add Event Node")->setData(eMI_AddEvent);
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::AddMenuSeperatorConditional(QMenu& menu, bool& bAppended)
- {
- if (bAppended)
- {
- menu.addSeparator();
- }
- bAppended = false;
- }
- //////////////////////////////////////////////////////////////////////////
- int CTrackViewNodesCtrl::ShowPopupMenuSingleSelection(SContextMenu& contextMenu, CTrackViewSequence* sequence, CTrackViewNode* pNode)
- {
- bool bAppended = false;
- bool isOnComponentNode = false;
- bool isOnAzEntityNode = false;
- const bool bOnSequence = pNode->GetNodeType() == eTVNT_Sequence;
- const bool bOnNode = pNode->GetNodeType() == eTVNT_AnimNode;
- const bool bOnTrack = pNode->GetNodeType() == eTVNT_Track;
- const bool bIsLightAnimationSet = sequence->GetFlags() & IAnimSequence::eSeqFlags_LightAnimationSet;
- // Get track & anim node pointers
- CTrackViewTrack* pTrack = bOnTrack ? static_cast<CTrackViewTrack*>(pNode) : nullptr;
- const bool bOnTrackNotSub = bOnTrack && !pTrack->IsSubTrack();
- if (bOnNode)
- {
- AnimNodeType nodeType = static_cast<CTrackViewAnimNode*>(pNode)->GetType();
- if (nodeType == AnimNodeType::Component)
- {
- isOnComponentNode = true;
- }
- else if (nodeType == AnimNodeType::AzEntity)
- {
- isOnAzEntityNode = true;
- }
- }
- CTrackViewAnimNode* animNode = nullptr;
- if (bOnSequence || bOnNode)
- {
- animNode = static_cast<CTrackViewAnimNode*>(pNode);
- }
- else if (bOnTrack)
- {
- animNode = pTrack->GetAnimNode();
- }
- bool isOnDirector = (animNode && animNode->GetType() == AnimNodeType::Director);
- bool isOnAzEntity = (animNode && animNode->GetType() == AnimNodeType::AzEntity);
- bool isOnSequence = (animNode && animNode->GetNodeType() == eTVNT_Sequence);
- if (isOnSequence)
- {
- contextMenu.main.addAction("Select In Viewport")->setData(eMI_SelectInViewport);
- contextMenu.main.addSeparator();
- }
- // Entity
- if (bOnNode && !bIsLightAnimationSet && animNode->IsBoundToAzEntity())
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- contextMenu.main.addAction("Select In Viewport")->setData(eMI_SelectInViewport);
- bAppended = true;
- }
- {
- bool bCopyPasteRenameAppended = false;
- // Copy & paste nodes
- if ((bOnNode || bOnSequence) && !isOnComponentNode)
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- contextMenu.main.addAction("Copy")->setData(eMI_CopyNodes);
- bCopyPasteRenameAppended = true;
- }
- if (pNode->IsGroupNode() && !isOnAzEntity)
- {
- contextMenu.main.addAction("Paste")->setData(eMI_PasteNodes);
- bCopyPasteRenameAppended = true;
- }
- if ((bOnNode || bOnSequence || bOnTrackNotSub) && !isOnComponentNode)
- {
- contextMenu.main.addAction("Delete")->setData(bOnTrackNotSub ? eMI_RemoveTrack : eMI_RemoveSelected);
- bCopyPasteRenameAppended = true;
- }
- // Renaming
- if (pNode->CanBeRenamed())
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- contextMenu.main.addAction("Rename")->setData(eMI_Rename);
- bCopyPasteRenameAppended = true;
- }
- bAppended = bAppended || bCopyPasteRenameAppended;
- }
- if (bOnTrack)
- {
- // Copy & paste keys
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- contextMenu.main.addAction("Copy Keys")->setData(eMI_CopyKeys);
- contextMenu.main.addAction("Copy Selected Keys")->setData(eMI_CopySelectedKeys);
- contextMenu.main.addAction("Paste Keys")->setData(eMI_PasteKeys);
- bAppended = true;
- }
- // Flags
- {
- bool bFlagAppended = false;
- if (!bOnSequence)
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- QAction* a = contextMenu.main.addAction("Disabled");
- a->setData(eMI_Disable);
- a->setCheckable(true);
- a->setChecked(pNode->IsDisabled());
- // If the node is not currently allowed to be enabled, disable the check box.
- if (pNode->IsDisabled() && !pNode->CanBeEnabled())
- {
- a->setEnabled(false);
- }
- bFlagAppended = true;
- }
- if (bOnTrack)
- {
- if (pTrack->GetParameterType() == AnimParamType::Sound)
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- bool bMuted = pTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Muted;
- QAction* a = contextMenu.main.addAction("Muted");
- a->setData(eMI_Mute);
- a->setCheckable(true);
- a->setChecked(bMuted);
- bFlagAppended = true;
- }
- }
- // In case that it's a director node instead of a normal group node,
- if (bOnNode && animNode->GetType() == AnimNodeType::Director)
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- QAction* a = contextMenu.main.addAction("Active Director");
- a->setData(eMI_SetAsActiveDirector);
- a->setCheckable(true);
- a->setChecked(animNode->IsActiveDirector());
- bFlagAppended = true;
- }
- bAppended = bAppended || bFlagAppended;
- }
- // Expand / collapse
- if (bOnSequence || pNode->IsGroupNode())
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- contextMenu.expandSub.addAction("Expand all")->setData(eMI_ExpandAll);
- contextMenu.collapseSub.addAction("Collapse all")->setData(eMI_CollapseAll);
- if (!isOnAzEntity)
- {
- contextMenu.expandSub.addAction("Expand Folders")->setData(eMI_ExpandFolders);
- contextMenu.collapseSub.addAction("Collapse Folders")->setData(eMI_CollapseFolders);
- contextMenu.expandSub.addAction("Expand Entities")->setData(eMI_ExpandEntities);
- contextMenu.collapseSub.addAction("Collapse Entities")->setData(eMI_CollapseEntities);
- contextMenu.expandSub.addAction("Expand Events")->setData(eMI_ExpandEvents);
- contextMenu.collapseSub.addAction("Collapse Events")->setData(eMI_CollapseEvents);
- }
- contextMenu.expandSub.setTitle("Expand");
- contextMenu.main.addMenu(&contextMenu.expandSub);
- contextMenu.collapseSub.setTitle("Collapse");
- contextMenu.main.addMenu(&contextMenu.collapseSub);
- bAppended = true;
- }
- // Add/Remove
- {
- if (bOnSequence || (pNode->IsGroupNode() && !isOnAzEntity) )
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- AddGroupNodeAddItems(contextMenu, animNode);
- bAppended = true;
- }
- if (bOnNode)
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- if (!isOnAzEntity)
- {
- // Create 'Add Tracks' submenu
- m_menuParamTypeMap.clear();
- const QString addTracksMenuName = "Add Tracks";
- if (FillAddTrackMenu(contextMenu.addTrackSub, animNode))
- {
- // add script table properties -> tracks available for adding
- unsigned int currentId = 0;
- CreateAddTrackMenuRec(contextMenu.main, addTracksMenuName, animNode, contextMenu.addTrackSub, currentId);
- }
- else
- {
- // no tracks available for adding -> add empty disabled submenu for UI consistency
- contextMenu.main.addMenu(addTracksMenuName)->setEnabled(false);
- }
- }
- bAppended = true;
- }
- }
- bool isLegacySequence = (sequence && sequence->GetSequenceType() == SequenceType::Legacy);
- if (isLegacySequence && bOnNode && !bIsLightAnimationSet && !isOnDirector && !isOnComponentNode && !isOnAzEntityNode)
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- contextMenu.main.addAction("Import FBX File...")->setData(eMI_ImportFromFBX);
- contextMenu.main.addAction("Export FBX File...")->setData(eMI_SaveToFBX);
- bAppended = true;
- }
- // Events
- if (bOnSequence || pNode->IsGroupNode() && !bIsLightAnimationSet && !isOnAzEntity)
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- contextMenu.main.addAction("Edit Events...")->setData(eMI_EditEvents);
- bAppended = true;
- }
- // Delete track menu
- if (bOnTrackNotSub)
- {
- if (pTrack->GetParameterType() == AnimParamType::Animation || pTrack->GetParameterType() == AnimParamType::LookAt || pTrack->GetValueType() == AnimValueType::CharacterAnim)
- {
- // Add the set-animation-layer pop-up menu.
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- CreateSetAnimationLayerPopupMenu(contextMenu.setLayerSub, pTrack);
- contextMenu.setLayerSub.setTitle("Set Animation Layer");
- contextMenu.main.addMenu(&contextMenu.setLayerSub);
- bAppended = true;
- }
- }
- // Track color
- if (bOnTrack)
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- contextMenu.main.addAction("Customize Track Color...")->setData(eMI_CustomizeTrackColor);
- if (pTrack->HasCustomColor())
- {
- contextMenu.main.addAction("Clear Custom Track Color")->setData(eMI_ClearCustomTrackColor);
- }
- bAppended = true;
- }
- // Track hide/unhide flags
- if (bOnNode && !pNode->IsGroupNode())
- {
- AddMenuSeperatorConditional(contextMenu.main, bAppended);
- const QString manageTracksMenuName = "Toggle Tracks";
- auto manageTracksAction = contextMenu.main.addAction(manageTracksMenuName);
- bool bAppendedTrackFlag = false;
- const unsigned int numChildren = animNode->GetChildCount();
- for (unsigned int childIndex = 0; childIndex < numChildren; ++childIndex)
- {
- CTrackViewNode* pChild = animNode->GetChild(childIndex);
- if (pChild->GetNodeType() == eTVNT_Track)
- {
- CTrackViewTrack* pTrack2 = static_cast<CTrackViewTrack*>(pChild);
- if (pTrack2->IsSubTrack())
- {
- continue;
- }
- QAction* a = contextMenu.main.addAction(QString(" %1").arg(pTrack2->GetName().c_str()));
- a->setData(eMI_ShowHideBase + childIndex);
- a->setCheckable(true);
- a->setChecked(!pTrack2->IsHidden());
- bAppendedTrackFlag = true;
- }
- }
- manageTracksAction->setEnabled(bAppendedTrackFlag); // Disable this submenu if no tracks were added.
- bAppended = bAppendedTrackFlag || bAppended;
- }
- return 0;
- }
- //////////////////////////////////////////////////////////////////////////
- int CTrackViewNodesCtrl::ShowPopupMenuMultiSelection(SContextMenu& contextMenu)
- {
- QList<QTreeWidgetItem*> records = ui->treeWidget->selectedItems();
- bool bNodeSelected = false;
- for (int currentNode = 0; currentNode < records.size(); ++currentNode)
- {
- CRecord* pItemInfo = (CRecord*)records[currentNode];
- if (pItemInfo->GetNode()->GetNodeType() == eTVNT_AnimNode)
- {
- bNodeSelected = true;
- }
- }
- if (bNodeSelected)
- {
- contextMenu.main.addAction("Copy Selected Nodes")->setData(eMI_CopySelectedNodes);
- }
- contextMenu.main.addAction("Remove Selected Nodes/Tracks")->setData(eMI_RemoveSelected);
- if (bNodeSelected)
- {
- contextMenu.main.addSeparator();
- contextMenu.main.addAction("Select In Viewport")->setData(eMI_SelectInViewport);
- // Importing FBX is currently only supported on legacy entities. Legacy
- // sequences contain only legacy Cry entities and no AZ component entities.
- CAnimationContext* context = GetIEditor()->GetAnimation();
- AZ_Assert(context, "Expected valid GetIEditor()->GetAnimation()");
- if (context)
- {
- CTrackViewSequence* sequence = context->GetSequence();
- if (sequence && sequence->GetSequenceType() == SequenceType::Legacy)
- {
- contextMenu.main.addAction("Import From FBX File")->setData(eMI_ImportFromFBX);
- contextMenu.main.addAction("Save To FBX File")->setData(eMI_SaveToFBX);
- }
- }
- }
- return 0;
- }
- //////////////////////////////////////////////////////////////////////////
- int CTrackViewNodesCtrl::ShowPopupMenu([[maybe_unused]] QPoint point, const CRecord* record)
- {
- CTrackViewSequence* sequence = GetIEditor()->GetAnimation()->GetSequence();
- if (!sequence)
- {
- return 0;
- }
- SContextMenu contextMenu;
- CTrackViewNode* pNode = record ? record->GetNode() : nullptr;
- if (!pNode)
- {
- return 0;
- }
- if (ui->treeWidget->selectedItems().size() > 1)
- {
- ShowPopupMenuMultiSelection(contextMenu);
- }
- else if (pNode)
- {
- ShowPopupMenuSingleSelection(contextMenu, sequence, pNode);
- }
- if (m_bEditLock)
- {
- SetPopupMenuLock(&contextMenu.main);
- }
- QAction* action = contextMenu.main.exec(QCursor::pos());
- int ret = action ? action->data().toInt() : 0;
- return ret;
- }
- //////////////////////////////////////////////////////////////////////////
- // Add tracks that can be added to the given animation node to the
- // internal track menu tree data structure rooted at menuAddTrack
- bool CTrackViewNodesCtrl::FillAddTrackMenu(STrackMenuTreeNode& menuAddTrack, const CTrackViewAnimNode* animNode)
- {
- bool bTracksToAdd = false;
- const AnimNodeType nodeType = animNode->GetType();
- int paramCount = 0;
- IAnimNode::AnimParamInfos animatableProperties;
- CTrackViewNode* parentNode = animNode->GetParentNode();
- // all AZ::Entity entities are animated through components. Component nodes always have a parent - the containing AZ::Entity
- if (nodeType == AnimNodeType::Component && parentNode)
- {
- // component node - query all the animatable tracks via an EBus request
- // all AnimNodeType::Component are parented to AnimNodeType::AzEntityNodes - get the parent to get it's AZ::EntityId to use for the EBus request
- if (parentNode->GetNodeType() == eTVNT_AnimNode)
- {
- // this cast is safe because we check that the type is eTVNT_AnimNode
- const AZ::EntityId azEntityId = static_cast<CTrackViewAnimNode*>(parentNode)->GetAzEntityId();
- // query the animatable component properties from the Sequence Component
- Maestro::EditorSequenceComponentRequestBus::Event(const_cast<CTrackViewAnimNode*>(animNode)->GetSequence()->GetSequenceComponentEntityId(),
- &Maestro::EditorSequenceComponentRequestBus::Events::GetAllAnimatablePropertiesForComponent,
- animatableProperties, azEntityId, animNode->GetComponentId());
- paramCount = static_cast<int>(animatableProperties.size());
- }
- }
- else
- {
- // legacy Entity
- paramCount = animNode->GetParamCount();
- }
- for (int i = 0; i < paramCount; ++i)
- {
- CAnimParamType paramType;
- QString name;
- // get the animatable param name
- if (nodeType == AnimNodeType::Component)
- {
- // Skip over any hidden params
- if (animatableProperties[i].flags & IAnimNode::ESupportedParamFlags::eSupportedParamFlags_Hidden)
- {
- continue;
- }
- paramType = animatableProperties[i].paramType;
- }
- else
- {
- // legacy node
- paramType = animNode->GetParamType(i);
- if (paramType == AnimParamType::Invalid)
- {
- continue;
- }
- IAnimNode::ESupportedParamFlags paramFlags = animNode->GetParamFlags(paramType);
- CTrackViewTrack* pTrack = animNode->GetTrackForParameter(paramType);
- if (pTrack && !(paramFlags & IAnimNode::eSupportedParamFlags_MultipleTracks))
- {
- continue;
- }
- }
- name = QString::fromUtf8(animNode->GetParamName(paramType).c_str());
- QStringList splitName = name.split("/", Qt::SkipEmptyParts);
- STrackMenuTreeNode* pCurrentNode = &menuAddTrack;
- for (const QString& segment : splitName)
- {
- auto findIter = pCurrentNode->children.find(segment);
- if (findIter != pCurrentNode->children.end())
- {
- pCurrentNode = findIter->second.get();
- }
- //else {} - keep current node to avoid unnecessary nesting
- }
- // only add tracks to the that STrackMenuTreeNode tree that haven't already been added
- CTrackViewTrackBundle matchedTracks = animNode->GetTracksByParam(paramType);
- if (matchedTracks.GetCount() == 0 && !splitName.isEmpty())
- {
- STrackMenuTreeNode* pParamNode = new STrackMenuTreeNode;
- pCurrentNode->children[splitName.back()] = std::unique_ptr<STrackMenuTreeNode>(pParamNode);
- pParamNode->paramType = paramType;
- bTracksToAdd = true;
- }
- }
- return bTracksToAdd;
- }
- //////////////////////////////////////////////////////////////////////////
- //
- // FillAddTrackMenu fills the data structure for tracks to add (a STrackMenuTreeNode tree)
- // CreateAddTrackMenuRec actually creates the Qt submenu from this data structure
- //
- void CTrackViewNodesCtrl::CreateAddTrackMenuRec(QMenu& parent, const QString& name, CTrackViewAnimNode* animNode, struct STrackMenuTreeNode& node, unsigned int& currentId)
- {
- if (node.paramType.GetType() == AnimParamType::Invalid)
- {
- node.menu.setTitle(name);
- parent.addMenu(&node.menu);
- for (auto iter = node.children.begin(); iter != node.children.end(); ++iter)
- {
- CreateAddTrackMenuRec(node.menu, iter->first, animNode, *iter->second.get(), currentId);
- }
- }
- else
- {
- m_menuParamTypeMap[currentId] = node.paramType;
- QVariant paramTypeMenuID;
- paramTypeMenuID.setValue(eMI_AddTrackBase + currentId);
- parent.addAction(name)->setData(paramTypeMenuID);
- ++currentId;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::SetPopupMenuLock(QMenu* menu)
- {
- if (!m_bEditLock || !menu)
- {
- return;
- }
- UINT count = menu->actions().size();
- for (UINT i = 0; i < count; ++i)
- {
- QAction* a = menu->actions()[i];
- QString menuString = a->text();
- if (menuString != "Expand" && menuString != "Collapse")
- {
- a->setEnabled(false);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- float CTrackViewNodesCtrl::SaveVerticalScrollPos() const
- {
- int sbMin = ui->treeWidget->verticalScrollBar()->minimum();
- int sbMax = ui->treeWidget->verticalScrollBar()->maximum();
- return float(ui->treeWidget->verticalScrollBar()->value() - sbMin) / std::max(float(sbMax - sbMin), 1.0f);
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::RestoreVerticalScrollPos(float fScrollPos)
- {
- int sbMin = ui->treeWidget->verticalScrollBar()->minimum();
- int sbMax = ui->treeWidget->verticalScrollBar()->maximum();
- int newScrollPos = qRound(fScrollPos * (sbMax - sbMin)) + sbMin;
- ui->treeWidget->verticalScrollBar()->setValue(newScrollPos);
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::FillAutoCompletionListForFilter()
- {
- QStringList strings;
- CTrackViewSequence* sequence = GetIEditor()->GetAnimation()->GetSequence();
- if (sequence)
- {
- ui->noitems->hide();
- ui->treeWidget->show();
- ui->searchField->show();
- ui->searchCount->show();
- CTrackViewAnimNodeBundle animNodes = sequence->GetAllAnimNodes();
- const unsigned int animNodeCount = animNodes.GetCount();
- for (unsigned int i = 0; i < animNodeCount; ++i)
- {
- strings << QString::fromUtf8(animNodes.GetNode(i)->GetName().c_str());
- }
- }
- else
- {
- ui->noitems->show();
- ui->treeWidget->hide();
- ui->searchField->hide();
- ui->searchCount->hide();
- }
- QCompleter* c = new QCompleter(strings, this);
- c->setCaseSensitivity(Qt::CaseInsensitive);
- c->setCompletionMode(QCompleter::InlineCompletion);
- ui->searchField->setCompleter(c);
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnFilterChange(const QString& text)
- {
- CTrackViewSequence* sequence = GetIEditor()->GetAnimation()->GetSequence();
- if (sequence)
- {
- m_currentMatchIndex = 0; // Reset the match index
- m_matchCount = 0; // and the count.
- if (!text.isEmpty())
- {
- QList<QTreeWidgetItem*> items = ui->treeWidget->findItems(text, Qt::MatchContains | Qt::MatchRecursive);
- CTrackViewAnimNodeBundle animNodes = sequence->GetAllAnimNodes();
- m_matchCount = items.size(); // and the count.
- if (!items.empty())
- {
- ui->treeWidget->selectionModel()->clear();
- items.front()->setSelected(true);
- }
- }
- QString matchCountText = QString("%1/%2").arg(m_matchCount == 0 ? 0 : 1).arg(m_matchCount); // One-based indexing
- ui->searchCount->setText(matchCountText);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- int CTrackViewNodesCtrl::GetMatNameAndSubMtlIndexFromName(QString& matName, const char* nodeName)
- {
- if (const char* pCh = strstr(nodeName, ".["))
- {
- char matPath[MAX_PATH];
- azstrncpy(matPath, AZ_ARRAY_SIZE(matPath), nodeName, (size_t)(pCh - nodeName));
- matName = matPath;
- pCh += 2;
- if ((*pCh) != 0)
- {
- const int index = atoi(pCh) - 1;
- return index;
- }
- }
- else
- {
- matName = nodeName;
- }
- return -1;
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::ShowNextResult()
- {
- if (m_matchCount > 1)
- {
- CTrackViewSequence* sequence = GetIEditor()->GetAnimation()->GetSequence();
- if (sequence && !ui->searchField->text().isEmpty())
- {
- QList<QTreeWidgetItem*> items = ui->treeWidget->findItems(ui->searchField->text(), Qt::MatchContains | Qt::MatchRecursive);
- CTrackViewAnimNodeBundle animNodes = sequence->GetAllAnimNodes();
- m_matchCount = items.size(); // and the count.
- if (!items.empty())
- {
- ++m_currentMatchIndex;
- m_currentMatchIndex = m_currentMatchIndex % m_matchCount;
- ui->treeWidget->selectionModel()->clear();
- items[m_currentMatchIndex]->setSelected(true);
- }
- QString matchCountText = QString("%1/%2").arg(m_currentMatchIndex + 1).arg(m_matchCount); // One-based indexing
- ui->searchCount->setText(matchCountText);
- }
- }
- }
- void CTrackViewNodesCtrl::Update()
- {
- // Update the Track UI elements with the latest names of the Tracks.
- // In some cases the Track names (param names) may not be available at the time
- // of the Sequence activation because they come from the animated entities (which may not be active).
- // So just update them once a frame to make sure they are the latest.
- for (auto iter = m_nodeToRecordMap.begin(); iter != m_nodeToRecordMap.end(); ++iter)
- {
- const CTrackViewNode* node = iter->first;
- CTrackViewNodesCtrl::CRecord* record = iter->second;
- if (node && record)
- {
- if (node->GetNodeType() == eTVNT_Track)
- {
- const CTrackViewAnimNode* track = static_cast<const CTrackViewAnimNode*>(node);
- if (track)
- {
- record->setText(0, QString::fromUtf8(track->GetName().c_str()));
- }
- }
- }
- }
- }
- void CTrackViewNodesCtrl::keyPressEvent(QKeyEvent* event)
- {
- // HAVE TO INCLUDE CASES FOR THESE IN THE ShortcutOverride handler in ::event() below
- switch (event->key())
- {
- case Qt::Key_Z:
- if (event->modifiers() == Qt::ControlModifier)
- {
- GetIEditor()->Undo();
- event->accept();
- }
- break;
- default:
- break;
- }
- }
- bool CTrackViewNodesCtrl::event(QEvent* e)
- {
- if (e->type() == QEvent::ShortcutOverride)
- {
- // since we respond to the following things, let Qt know so that shortcuts don't override us
- bool respondsToEvent = false;
- QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e);
- if (keyEvent->key() == Qt::Key_Z && keyEvent->modifiers() == Qt::ControlModifier)
- {
- respondsToEvent = true;
- }
- if (respondsToEvent)
- {
- e->accept();
- return true;
- }
- }
- return QWidget::event(e);
- }
- void CTrackViewNodesCtrl::CreateSetAnimationLayerPopupMenu(QMenu& menuSetLayer, CTrackViewTrack* pTrack) const
- {
- // First collect layers already in use.
- std::vector<int> layersInUse;
- CTrackViewTrackBundle lookAtTracks = pTrack->GetAnimNode()->GetTracksByParam(AnimParamType::LookAt);
- assert(lookAtTracks.GetCount() <= 1);
- if (lookAtTracks.GetCount() > 0)
- {
- const int kDefaultLookIKLayer = 15;
- int lookIKLayerIndex = lookAtTracks.GetTrack(0)->GetAnimationLayerIndex();
- if (lookIKLayerIndex < 0) // Not set before, use the default instead.
- {
- lookIKLayerIndex = kDefaultLookIKLayer;
- }
- layersInUse.push_back(lookIKLayerIndex);
- }
- CTrackViewTrackBundle animationTracks = pTrack->GetAnimNode()->GetTracksByParam(AnimParamType::Animation);
- const unsigned int numAnimationTracks = animationTracks.GetCount();
- for (unsigned int i = 0; i < numAnimationTracks; ++i)
- {
- CTrackViewTrack* pAnimationTrack = animationTracks.GetTrack(i);
- if (pAnimationTrack)
- {
- const int kAdditiveLayerOffset = 6;
- int layerIndex = pAnimationTrack->GetAnimationLayerIndex();
- if (layerIndex < 0) // Not set before, use the default instead.
- {
- layerIndex = i == 0 ? 0 : kAdditiveLayerOffset + i;
- }
- layersInUse.push_back(layerIndex);
- }
- }
- // Add layer items.
- for (int i = 0; i < 16; ++i)
- {
- QString layerText = QString("Layer #%1").arg(i);
- QAction* a = menuSetLayer.addAction(layerText);
- a->setData(eMI_SetAnimationLayerBase + i);
- a->setCheckable(true);
- a->setChecked(pTrack->GetAnimationLayerIndex() == i);
- a->setEnabled(!stl::find(layersInUse, i));
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::CustomizeTrackColor(CTrackViewTrack* pTrack)
- {
- CTrackViewSequence* sequence = GetIEditor()->GetAnimation()->GetSequence();
- if (!sequence)
- {
- return;
- }
- AZ::Color defaultColor;
- if (pTrack->HasCustomColor())
- {
- ColorB customColor = pTrack->GetCustomColor();
- defaultColor = AZ::Color(customColor.r, customColor.g, customColor.b, customColor.a);
- }
- const AZ::Color color = AzQtComponents::ColorPicker::getColor(AzQtComponents::ColorPicker::Configuration::RGB, defaultColor, tr("Select Color"));
- if (color != defaultColor)
- {
- AzToolsFramework::ScopedUndoBatch undoBatch("Customize Track Color");
- pTrack->SetCustomColor(ColorB(color.GetR8(), color.GetG8(), color.GetB8()));
- undoBatch.MarkEntityDirty(sequence->GetSequenceComponentEntityId());
- UpdateDopeSheet();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::ClearCustomTrackColor(CTrackViewTrack* pTrack)
- {
- CTrackViewSequence* sequence = GetIEditor()->GetAnimation()->GetSequence();
- if (!sequence)
- {
- return;
- }
- AzToolsFramework::ScopedUndoBatch undoBatch("Clear Custom Track Color");
- pTrack->ClearCustomColor();
- undoBatch.MarkEntityDirty(sequence->GetSequenceComponentEntityId());
- UpdateDopeSheet();
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::paintEvent(QPaintEvent* event)
- {
- QWidget::paintEvent(event);
- UpdateDopeSheet();
- }
- //////////////////////////////////////////////////////////////////////////
- CTrackViewNodesCtrl::CRecord* CTrackViewNodesCtrl::GetNodeRecord(const CTrackViewNode* pNode) const
- {
- auto findIter = m_nodeToRecordMap.find(pNode);
- if (findIter == m_nodeToRecordMap.end())
- {
- return nullptr;
- }
- assert (findIter->second->GetNode() == pNode);
- return findIter->second;
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::UpdateDopeSheet()
- {
- UpdateRecordVisibility();
- if (m_pDopeSheet)
- {
- m_pDopeSheet->update();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // Workaround: CXTPReportRecord::IsVisible is
- // unreliable after the last visible element
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::UpdateRecordVisibility()
- {
- // Mark all records invisible
- for (auto iter = m_nodeToRecordMap.begin(); iter != m_nodeToRecordMap.end(); ++iter)
- {
- iter->second->m_bVisible = ui->treeWidget->visualItemRect(iter->second).isValid();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnNodeChanged(CTrackViewNode* pNode, ITrackViewSequenceListener::ENodeChangeType type)
- {
- if (pNode->GetSequence() != GetIEditor()->GetAnimation()->GetSequence())
- {
- return;
- }
- if (!m_bIgnoreNotifications)
- {
- CTrackViewNode* pParentNode = pNode->GetParentNode();
- CRecord* pNodeRecord = GetNodeRecord(pNode);
- CRecord* pParentNodeRecord = pParentNode ? GetNodeRecord(pParentNode) : nullptr;
- float storedScrollPosition = SaveVerticalScrollPos();
- switch (type)
- {
- case ITrackViewSequenceListener::eNodeChangeType_Added:
- case ITrackViewSequenceListener::eNodeChangeType_Unhidden:
- if (pParentNodeRecord)
- {
- AddNodeRecord(pParentNodeRecord, pNode);
- }
- break;
- case ITrackViewSequenceListener::eNodeChangeType_Removed:
- case ITrackViewSequenceListener::eNodeChangeType_Hidden:
- if (pNodeRecord)
- {
- EraseNodeRecordRec(pNode);
- delete pNodeRecord;
- }
- break;
- case ITrackViewSequenceListener::eNodeChangeType_Expanded:
- if (pNodeRecord)
- {
- pNodeRecord->setExpanded(true);
- }
- break;
- case ITrackViewSequenceListener::eNodeChangeType_Collapsed:
- if (pNodeRecord)
- {
- pNodeRecord->setExpanded(false);
- }
- break;
- case ITrackViewSequenceListener::eNodeChangeType_Disabled:
- case ITrackViewSequenceListener::eNodeChangeType_Enabled:
- case ITrackViewSequenceListener::eNodeChangeType_Muted:
- case ITrackViewSequenceListener::eNodeChangeType_Unmuted:
- case ITrackViewSequenceListener::eNodeChangeType_NodeOwnerChanged:
- if (pNodeRecord)
- {
- UpdateNodeRecord(pNodeRecord);
- }
- }
- switch (type)
- {
- case ITrackViewSequenceListener::eNodeChangeType_Added:
- case ITrackViewSequenceListener::eNodeChangeType_Unhidden:
- case ITrackViewSequenceListener::eNodeChangeType_Removed:
- case ITrackViewSequenceListener::eNodeChangeType_Hidden:
- case ITrackViewSequenceListener::eNodeChangeType_Expanded:
- case ITrackViewSequenceListener::eNodeChangeType_Collapsed:
- update();
- RestoreVerticalScrollPos(storedScrollPosition);
- break;
- case eNodeChangeType_SetAsActiveDirector:
- update();
- break;
- }
- }
- else
- {
- m_bNeedReload = true;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnNodeRenamed(CTrackViewNode* pNode, [[maybe_unused]] const char* pOldName)
- {
- if (!m_bIgnoreNotifications)
- {
- CRecord* pNodeRecord = GetNodeRecord(pNode);
- pNodeRecord->setText(0, QString::fromUtf8(pNode->GetName().c_str()));
- update();
- }
- else
- {
- m_bNeedReload = true;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::BeginUndoTransaction()
- {
- m_bNeedReload = false;
- m_bIgnoreNotifications = true;
- m_storedScrollPosition = SaveVerticalScrollPos();
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::EndUndoTransaction()
- {
- m_bIgnoreNotifications = false;
- if (m_bNeedReload)
- {
- Reload();
- RestoreVerticalScrollPos(m_storedScrollPosition);
- m_bNeedReload = false;
- }
- UpdateDopeSheet();
- }
- QIcon CTrackViewNodesCtrl::TrackViewIcon(const CTrackViewTrack* pTrack)
- {
- const QIcon defaultIcon(QStringLiteral(":/nodes/tvnodes-13.png"));
- if (!pTrack)
- {
- return defaultIcon;
- }
- const CAnimParamType paramType = pTrack->GetParameterType();
- const AnimValueType valueType = pTrack->GetValueType();
- const AnimNodeType nodeType = pTrack->GetAnimNode()->GetType();
- if (nodeType == AnimNodeType::RadialBlur || nodeType == AnimNodeType::ColorCorrection || nodeType == AnimNodeType::DepthOfField ||
- nodeType == AnimNodeType::ShadowSetup)
- {
- return defaultIcon;
- }
- switch (valueType)
- {
- case AnimValueType::CharacterAnim:
- case AnimValueType::AssetBlend:
- return QIcon(QStringLiteral(":/nodes/tvnodes-10.png"));
- }
- AnimParamType type = paramType.GetType();
- switch (type)
- {
- case AnimParamType::Position:
- return QIcon(QStringLiteral(":/nodes/tvnodes-03.png"));
- case AnimParamType::Rotation:
- return QIcon(QStringLiteral(":/nodes/tvnodes-04.png"));
- case AnimParamType::Scale:
- return QIcon(QStringLiteral(":/nodes/tvnodes-05.png"));
- case AnimParamType::Event:
- case AnimParamType::TrackEvent:
- return QIcon(QStringLiteral(":/nodes/tvnodes-06.png"));
- case AnimParamType::Visibility:
- return QIcon(QStringLiteral(":/nodes/tvnodes-07.png"));
- case AnimParamType::Camera:
- return QIcon(QStringLiteral(":/nodes/tvnodes-08.png"));
- case AnimParamType::Sound:
- return QIcon(QStringLiteral(":/nodes/tvnodes-09.png"));
- case AnimParamType::Animation:
- case AnimParamType::TimeRanges:
- return QIcon(QStringLiteral(":/nodes/tvnodes-10.png"));
- case AnimParamType::Sequence:
- return QIcon(QStringLiteral(":/nodes/tvnodes-11.png"));
- case AnimParamType::Capture:
- return QIcon(QStringLiteral(":/nodes/tvnodes-25.png"));
- case AnimParamType::Console:
- return QIcon(QStringLiteral(":/nodes/tvnodes-15.png"));
- case AnimParamType::LookAt:
- return QIcon(QStringLiteral(":/nodes/tvnodes-17.png"));
- case AnimParamType::TimeWarp:
- return QIcon(QStringLiteral(":/nodes/tvnodes-22.png"));
- case AnimParamType::CommentText:
- return QIcon(QStringLiteral(":/nodes/tvnodes-23.png"));
- case AnimParamType::ShakeMultiplier:
- [[fallthrough]];
- case AnimParamType::TransformNoise:
- return QIcon(QStringLiteral(":/nodes/tvnodes-28.png"));
- default:
- case AnimParamType::Float:
- break;
- }
- return defaultIcon;
- }
- QIcon CTrackViewNodesCtrl::TrackViewNodeIcon(AnimNodeType type)
- {
- switch (type)
- {
- case AnimNodeType::AzEntity:
- return QIcon(QStringLiteral(":/nodes/tvnodes-29.png"));
- case AnimNodeType::Director:
- return QIcon(QStringLiteral(":/nodes/tvnodes-27.png"));
- case AnimNodeType::CVar:
- return QIcon(QStringLiteral(":/nodes/tvnodes-15.png"));
- case AnimNodeType::ScriptVar:
- return QIcon(QStringLiteral(":/nodes/tvnodes-14.png"));
- case AnimNodeType::Material:
- return QIcon(QStringLiteral(":/nodes/tvnodes-16.png"));
- case AnimNodeType::Event:
- return QIcon(QStringLiteral(":/nodes/tvnodes-06.png"));
- case AnimNodeType::Group:
- return QIcon(QStringLiteral(":/nodes/tvnodes-01.png"));
- case AnimNodeType::Layer:
- return QIcon(QStringLiteral(":/nodes/tvnodes-20.png"));
- case AnimNodeType::Comment:
- return QIcon(QStringLiteral(":/nodes/tvnodes-23.png"));
- case AnimNodeType::Light:
- return QIcon(QStringLiteral(":/nodes/tvnodes-18.png"));
- case AnimNodeType::ShadowSetup:
- return QIcon(QStringLiteral(":/nodes/tvnodes-24.png"));
- }
- return QIcon(QStringLiteral(":/nodes/tvnodes-21.png"));
- }
- //////////////////////////////////////////////////////////////////////////
- QIcon CTrackViewNodesCtrl::GetIconForTrack(const CTrackViewTrack* pTrack)
- {
- return TrackViewIcon(pTrack);
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnKeysChanged(CTrackViewSequence* sequence)
- {
- if (!m_bIgnoreNotifications && sequence && sequence == GetIEditor()->GetAnimation()->GetSequence())
- {
- UpdateDopeSheet();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnKeySelectionChanged(CTrackViewSequence* sequence)
- {
- OnKeysChanged(sequence);
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::OnNodeSelectionChanged(CTrackViewSequence* sequence)
- {
- if (m_bSelectionChanging)
- {
- return;
- }
- if (!m_bIgnoreNotifications && sequence && sequence == GetIEditor()->GetAnimation()->GetSequence())
- {
- UpdateDopeSheet();
- CTrackViewAnimNodeBundle animNodes = sequence->GetAllAnimNodes();
- const uint numNodes = animNodes.GetCount();
- for (uint i = 0; i < numNodes; ++i)
- {
- CTrackViewAnimNode* pNode = animNodes.GetNode(i);
- if (pNode->IsSelected())
- {
- SelectRow(pNode, false, false);
- }
- else
- {
- DeselectRow(pNode);
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::SelectRow(CTrackViewNode* pNode, const bool bEnsureVisible, const bool bDeselectOtherRows)
- {
- std::unordered_map<const CTrackViewNode*, CRecord*>::const_iterator it = m_nodeToRecordMap.find(pNode);
- if (it != m_nodeToRecordMap.end())
- {
- if (bDeselectOtherRows)
- {
- ui->treeWidget->selectionModel()->clear();
- }
- (*it).second->setSelected(true);
- if (bEnsureVisible)
- {
- ui->treeWidget->scrollToItem((*it).second);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::DeselectRow(CTrackViewNode* pNode)
- {
- std::unordered_map<const CTrackViewNode*, CRecord*>::const_iterator it = m_nodeToRecordMap.find(pNode);
- if (it != m_nodeToRecordMap.end())
- {
- (*it).second->setSelected(false);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void CTrackViewNodesCtrl::EraseNodeRecordRec(CTrackViewNode* pNode)
- {
- m_nodeToRecordMap.erase(pNode);
- const unsigned int numChildren = pNode->GetChildCount();
- for (unsigned int i = 0; i < numChildren; ++i)
- {
- EraseNodeRecordRec(pNode->GetChild(i));
- }
- }
- #include <TrackView/moc_TrackViewNodes.cpp>
|