/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #include "StdAfx.h" #include "TrackViewPythonFuncs.h" #include "TrackViewNodes.h" #include "TrackViewAnimNode.h" #include "TrackViewSequenceManager.h" #include "AnimationContext.h" #include #include #include #include #include namespace { CTrackViewSequence* GetSequenceByEntityIdOrName(const CTrackViewSequenceManager* pSequenceManager, const char* entityIdOrName) { // the "name" string will be an AZ::EntityId in string form if this was called from // TrackView code. But for backward compatibility we also support a sequence name. bool isNameAValidU64 = false; QString entityIdString = entityIdOrName; AZ::u64 nameAsU64 = entityIdString.toULongLong(&isNameAValidU64); CTrackViewSequence* pSequence = nullptr; if (isNameAValidU64) { // "name" string was a valid u64 represented as a string. Use as an entity Id to search for sequence. pSequence = pSequenceManager->GetSequenceByEntityId(AZ::EntityId(nameAsU64)); } if (!pSequence) { // name passed in could not find a sequence by using it as an EntityId. Use it as a // sequence name for backward compatibility pSequence = pSequenceManager->GetSequenceByName(entityIdOrName); } return pSequence; } } namespace { ////////////////////////////////////////////////////////////////////////// // Misc ////////////////////////////////////////////////////////////////////////// void PyTrackViewSetRecording(bool bRecording) { CAnimationContext* pAnimationContext = GetIEditor()->GetAnimation(); if (pAnimationContext) { pAnimationContext->SetRecording(bRecording); } } ////////////////////////////////////////////////////////////////////////// // Sequences ////////////////////////////////////////////////////////////////////////// void PyTrackViewNewSequence(const char* name, int sequenceType) { CTrackViewSequenceManager* pSequenceManager = GetIEditor()->GetSequenceManager(); CTrackViewSequence* pSequence = pSequenceManager->GetSequenceByName(name); if (pSequence) { throw std::runtime_error("A sequence with this name already exists"); } CUndo undo("Create TrackView sequence"); pSequenceManager->CreateSequence(name, static_cast(sequenceType)); } void PyTrackViewDeleteSequence(const char* name) { CTrackViewSequenceManager* pSequenceManager = GetIEditor()->GetSequenceManager(); CTrackViewSequence* pSequence = GetSequenceByEntityIdOrName(pSequenceManager, name); if (pSequence) { pSequenceManager->DeleteSequence(pSequence); return; } throw std::runtime_error("Could not find sequence"); } void PyTrackViewSetCurrentSequence(const char* name) { const CTrackViewSequenceManager* sequenceManager = GetIEditor()->GetSequenceManager(); CTrackViewSequence* sequence = GetSequenceByEntityIdOrName(sequenceManager, name); CAnimationContext* animationContext = GetIEditor()->GetAnimation(); bool force = false; bool noNotify = false; bool user = true; animationContext->SetSequence(sequence, force, noNotify, user); } int PyTrackViewGetNumSequences() { const CTrackViewSequenceManager* pSequenceManager = GetIEditor()->GetSequenceManager(); AZ_TracePrintf("", "PyTrackViewGetNumSequences called") return pSequenceManager->GetCount(); } AZStd::string PyTrackViewGetSequenceName(unsigned int index) { if (index < PyTrackViewGetNumSequences()) { const CTrackViewSequenceManager* pSequenceManager = GetIEditor()->GetSequenceManager(); return pSequenceManager->GetSequenceByIndex(index)->GetName(); } throw std::runtime_error("Could not find sequence"); } Range PyTrackViewGetSequenceTimeRange(const char* name) { const CTrackViewSequenceManager* pSequenceManager = GetIEditor()->GetSequenceManager(); CTrackViewSequence* pSequence = GetSequenceByEntityIdOrName(pSequenceManager, name); if (!pSequence) { throw std::runtime_error("A sequence with this name doesn't exists"); } return pSequence->GetTimeRange(); } void PyTrackViewSetSequenceTimeRange(const char* name, float start, float end) { const CTrackViewSequenceManager* pSequenceManager = GetIEditor()->GetSequenceManager(); CTrackViewSequence* pSequence = GetSequenceByEntityIdOrName(pSequenceManager, name); if (!pSequence) { throw std::runtime_error("A sequence with this name doesn't exists"); } CUndo undo("Set sequence time range"); pSequence->SetTimeRange(Range(start, end)); pSequence->MarkAsModified(); } void PyTrackViewPlaySequence() { CAnimationContext* pAnimationContext = GetIEditor()->GetAnimation(); if (pAnimationContext->IsPlaying()) { throw std::runtime_error("A sequence is already playing"); } pAnimationContext->SetPlaying(true); } void PyTrackViewStopSequence() { CAnimationContext* pAnimationContext = GetIEditor()->GetAnimation(); if (!pAnimationContext->IsPlaying()) { throw std::runtime_error("No sequence is playing"); } pAnimationContext->SetPlaying(false); } void PyTrackViewSetSequenceTime(float time) { CAnimationContext* pAnimationContext = GetIEditor()->GetAnimation(); pAnimationContext->SetTime(time); } ////////////////////////////////////////////////////////////////////////// // Nodes ////////////////////////////////////////////////////////////////////////// void PyTrackViewAddNode(const char* nodeTypeString, const char* nodeName) { CTrackViewSequence* pSequence = GetIEditor()->GetAnimation()->GetSequence(); if (!pSequence) { throw std::runtime_error("No sequence is active"); } const AnimNodeType nodeType = GetIEditor()->GetMovieSystem()->GetNodeTypeFromString(nodeTypeString); if (nodeType == AnimNodeType::Invalid) { throw std::runtime_error("Invalid node type"); } CUndo undo("Create anim node"); pSequence->CreateSubNode(nodeName, nodeType); } void PyTrackViewAddSelectedEntities() { CAnimationContext* animationContext = GetIEditor()->GetAnimation(); CTrackViewSequence* sequence = animationContext->GetSequence(); if (!sequence) { throw std::runtime_error("No sequence is active"); } AZStd::vector tracks = { AnimParamType::Position, AnimParamType::Rotation }; AzToolsFramework::ScopedUndoBatch undoBatch("Add entities to Track View"); sequence->AddSelectedEntities(tracks); sequence->BindToEditorObjects(); undoBatch.MarkEntityDirty(sequence->GetSequenceComponentEntityId()); } void PyTrackViewAddLayerNode() { CAnimationContext* pAnimationContext = GetIEditor()->GetAnimation(); CTrackViewSequence* pSequence = pAnimationContext->GetSequence(); if (!pSequence) { throw std::runtime_error("No sequence is active"); } CUndo undo("Add current layer to TrackView"); pSequence->AddCurrentLayer(); } CTrackViewAnimNode* GetNodeFromName(const char* nodeName, const char* parentDirectorName) { CAnimationContext* pAnimationContext = GetIEditor()->GetAnimation(); CTrackViewSequence* pSequence = pAnimationContext->GetSequence(); if (!pSequence) { throw std::runtime_error("No sequence is active"); } CTrackViewAnimNode* pParentDirector = pSequence; if (strlen(parentDirectorName) > 0) { CTrackViewAnimNodeBundle foundNodes = pSequence->GetAnimNodesByName(parentDirectorName); if (foundNodes.GetCount() == 0 || foundNodes.GetNode(0)->GetType() != AnimNodeType::Director) { throw std::runtime_error("Director node not found"); } pParentDirector = foundNodes.GetNode(0); } CTrackViewAnimNodeBundle foundNodes = pParentDirector->GetAnimNodesByName(nodeName); return (foundNodes.GetCount() > 0) ? foundNodes.GetNode(0) : nullptr; } void PyTrackViewDeleteNode(AZStd::string_view nodeName, AZStd::string_view parentDirectorName) { CTrackViewAnimNode* pNode = GetNodeFromName(nodeName.data(), parentDirectorName.data()); if (pNode == nullptr) { throw std::runtime_error("Couldn't find node"); } CTrackViewAnimNode* pParentNode = static_cast(pNode->GetParentNode()); CUndo undo("Delete TrackView Node"); pParentNode->RemoveSubNode(pNode); } void PyTrackViewAddTrack(const char* paramName, const char* nodeName, const char* parentDirectorName) { CTrackViewAnimNode* pNode = GetNodeFromName(nodeName, parentDirectorName); if (!pNode) { throw std::runtime_error("Couldn't find node"); } // Add tracks to menu, that can be added to animation node. const int paramCount = pNode->GetParamCount(); for (int i = 0; i < paramCount; ++i) { CAnimParamType paramType = pNode->GetParamType(i); if (paramType == AnimParamType::Invalid) { continue; } IAnimNode::ESupportedParamFlags paramFlags = pNode->GetParamFlags(paramType); CTrackViewTrack* pTrack = pNode->GetTrackForParameter(paramType); if (!pTrack || (paramFlags & IAnimNode::eSupportedParamFlags_MultipleTracks)) { const char* name = pNode->GetParamName(paramType); if (_stricmp(name, paramName) == 0) { CUndo undo("Create track"); if (!pNode->CreateTrack(paramType)) { undo.Cancel(); throw std::runtime_error("Could not create track"); } pNode->SetSelected(true); return; } } } throw std::runtime_error("Could not create track"); } void PyTrackViewDeleteTrack(const char* paramName, uint32 index, const char* nodeName, const char* parentDirectorName) { CTrackViewAnimNode* pNode = GetNodeFromName(nodeName, parentDirectorName); if (!pNode) { throw std::runtime_error("Couldn't find node"); } const CAnimParamType paramType = GetIEditor()->GetMovieSystem()->GetParamTypeFromString(paramName); CTrackViewTrack* pTrack = pNode->GetTrackForParameter(paramType, index); if (!pTrack) { throw std::runtime_error("Could not find track"); } CUndo undo("Delete TrackView track"); pNode->RemoveTrack(pTrack); } int PyTrackViewGetNumNodes(AZStd::string_view parentDirectorName) { CAnimationContext* pAnimationContext = GetIEditor()->GetAnimation(); CTrackViewSequence* pSequence = pAnimationContext->GetSequence(); if (!pSequence) { throw std::runtime_error("No sequence is active"); } CTrackViewAnimNode* pParentDirector = pSequence; if (!parentDirectorName.empty()) { CTrackViewAnimNodeBundle foundNodes = pSequence->GetAnimNodesByName(parentDirectorName.data()); if (foundNodes.GetCount() == 0 || foundNodes.GetNode(0)->GetType() != AnimNodeType::Director) { throw std::runtime_error("Director node not found"); } pParentDirector = foundNodes.GetNode(0); } CTrackViewAnimNodeBundle foundNodes = pParentDirector->GetAllAnimNodes(); return foundNodes.GetCount(); } AZStd::string PyTrackViewGetNodeName(int index, AZStd::string_view parentDirectorName) { CAnimationContext* pAnimationContext = GetIEditor()->GetAnimation(); CTrackViewSequence* pSequence = pAnimationContext->GetSequence(); if (!pSequence) { throw std::runtime_error("No sequence is active"); } CTrackViewAnimNode* pParentDirector = pSequence; if (!parentDirectorName.empty()) { CTrackViewAnimNodeBundle foundNodes = pSequence->GetAnimNodesByName(parentDirectorName.data()); if (foundNodes.GetCount() == 0 || foundNodes.GetNode(0)->GetType() != AnimNodeType::Director) { throw std::runtime_error("Director node not found"); } pParentDirector = foundNodes.GetNode(0); } CTrackViewAnimNodeBundle foundNodes = pParentDirector->GetAllAnimNodes(); if (index < 0 || index >= foundNodes.GetCount()) { throw std::runtime_error("Invalid node index"); } return foundNodes.GetNode(index)->GetName(); } ////////////////////////////////////////////////////////////////////////// // Tracks ////////////////////////////////////////////////////////////////////////// CTrackViewTrack* GetTrack(const char* paramName, uint32 index, const char* nodeName, const char* parentDirectorName) { CTrackViewAnimNode* pNode = GetNodeFromName(nodeName, parentDirectorName); if (!pNode) { throw std::runtime_error("Couldn't find node"); } const CAnimParamType paramType = GetIEditor()->GetMovieSystem()->GetParamTypeFromString(paramName); CTrackViewTrack* pTrack = pNode->GetTrackForParameter(paramType, index); if (!pTrack) { throw std::runtime_error("Track doesn't exist"); } return pTrack; } std::set GetKeyTimeSet(CTrackViewTrack* pTrack) { std::set keyTimeSet; for (uint i = 0; i < pTrack->GetKeyCount(); ++i) { CTrackViewKeyHandle keyHandle = pTrack->GetKey(i); keyTimeSet.insert(keyHandle.GetTime()); } return keyTimeSet; } int PyTrackViewGetNumTrackKeys(const char* paramName, int trackIndex, const char* nodeName, const char* parentDirectorName) { CTrackViewTrack* pTrack = GetTrack(paramName, trackIndex, nodeName, parentDirectorName); return (int)GetKeyTimeSet(pTrack).size(); } AZStd::any PyTrackViewGetInterpolatedValue(const char* paramName, int trackIndex, float time, const char* nodeName, const char* parentDirectorName) { CTrackViewTrack* pTrack = GetTrack(paramName, trackIndex, nodeName, parentDirectorName); switch (pTrack->GetValueType()) { case AnimValueType::Float: case AnimValueType::DiscreteFloat: { float value; pTrack->GetValue(time, value); return AZStd::make_any(value); } break; case AnimValueType::Bool: { bool value; pTrack->GetValue(time, value); return AZStd::make_any(value); } break; case AnimValueType::Quat: { Quat value; pTrack->GetValue(time, value); Ang3 rotation(value); return AZStd::make_any(rotation.x, rotation.y, rotation.z); } case AnimValueType::Vector: { Vec3 value; pTrack->GetValue(time, value); return AZStd::make_any(value.x, value.y, value.z); } break; case AnimValueType::Vector4: { Vec4 value; pTrack->GetValue(time, value); return AZStd::make_any(value.x, value.y, value.z, value.w); } break; case AnimValueType::RGB: { Vec3 value; pTrack->GetValue(time, value); return AZStd::make_any(value.x, value.y, value.z, 0.0f); } break; default: throw std::runtime_error("Unsupported key type"); } return AZStd::any(); } AZStd::any PyTrackViewGetKeyValue(const char* paramName, int trackIndex, int keyIndex, const char* nodeName, const char* parentDirectorName) { CTrackViewTrack* pTrack = GetTrack(paramName, trackIndex, nodeName, parentDirectorName); std::set keyTimeSet = GetKeyTimeSet(pTrack); if (keyIndex < 0 || keyIndex >= keyTimeSet.size()) { throw std::runtime_error("Invalid key index"); } auto keyTimeIter = keyTimeSet.begin(); std::advance(keyTimeIter, keyIndex); const float keyTime = *keyTimeIter; return PyTrackViewGetInterpolatedValue(paramName, trackIndex, keyTime, nodeName, parentDirectorName); } } namespace AzToolsFramework { void TrackViewComponent::Reflect(AZ::ReflectContext* context) { if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { behaviorContext->EBus("EditorLayerTrackViewRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Module, "track_view") ->Event("AddNode", &EditorLayerTrackViewRequestBus::Events::AddNode) ->Event("AddTrack", &EditorLayerTrackViewRequestBus::Events::AddTrack) ->Event("AddLayerNode", &EditorLayerTrackViewRequestBus::Events::AddLayerNode) ->Event("AddSelectedEntities", &EditorLayerTrackViewRequestBus::Events::AddSelectedEntities) ->Event("DeleteNode", &EditorLayerTrackViewRequestBus::Events::DeleteNode) ->Event("DeleteTrack", &EditorLayerTrackViewRequestBus::Events::DeleteTrack) ->Event("DeleteSequence", &EditorLayerTrackViewRequestBus::Events::DeleteSequence) ->Event("GetInterpolatedValue", &EditorLayerTrackViewRequestBus::Events::GetInterpolatedValue) ->Event("GetKeyValue", &EditorLayerTrackViewRequestBus::Events::GetKeyValue) ->Event("GetNodeName", &EditorLayerTrackViewRequestBus::Events::GetNodeName) ->Event("GetNumNodes", &EditorLayerTrackViewRequestBus::Events::GetNumNodes) ->Event("GetNumSequences", &EditorLayerTrackViewRequestBus::Events::GetNumSequences) ->Event("GetNumTrackKeys", &EditorLayerTrackViewRequestBus::Events::GetNumTrackKeys) ->Event("GetSequenceName", &EditorLayerTrackViewRequestBus::Events::GetSequenceName) ->Event("GetSequenceTimeRange", &EditorLayerTrackViewRequestBus::Events::GetSequenceTimeRange) ->Event("NewSequence", &EditorLayerTrackViewRequestBus::Events::NewSequence) ->Event("PlaySequence", &EditorLayerTrackViewRequestBus::Events::PlaySequence) ->Event("SetCurrentSequence", &EditorLayerTrackViewRequestBus::Events::SetCurrentSequence) ->Event("SetRecording", &EditorLayerTrackViewRequestBus::Events::SetRecording) ->Event("SetSequenceTimeRange", &EditorLayerTrackViewRequestBus::Events::SetSequenceTimeRange) ->Event("SetTime", &EditorLayerTrackViewRequestBus::Events::SetSequenceTime) ->Event("StopSequence", &EditorLayerTrackViewRequestBus::Events::StopSequence) ; } } void TrackViewComponent::Activate() { EditorLayerTrackViewRequestBus::Handler::BusConnect(GetEntityId()); } void TrackViewComponent::Deactivate() { EditorLayerTrackViewRequestBus::Handler::BusDisconnect(); } int TrackViewComponent::GetNumSequences() { return PyTrackViewGetNumSequences(); } void TrackViewComponent::NewSequence(const char* name, int sequenceType) { return PyTrackViewNewSequence(name, sequenceType); } void TrackViewComponent::PlaySequence() { return PyTrackViewPlaySequence(); } void TrackViewComponent::StopSequence() { return PyTrackViewStopSequence(); } void TrackViewComponent::SetSequenceTime(float time) { return PyTrackViewSetSequenceTime(time); } void TrackViewComponent::AddSelectedEntities() { return PyTrackViewAddSelectedEntities(); } void TrackViewComponent::AddLayerNode() { return PyTrackViewAddLayerNode(); } void TrackViewComponent::AddTrack(const char* paramName, const char* nodeName, const char* parentDirectorName) { return PyTrackViewAddTrack(paramName, nodeName, parentDirectorName); } void TrackViewComponent::DeleteTrack(const char* paramName, uint32 index, const char* nodeName, const char* parentDirectorName) { return PyTrackViewDeleteTrack(paramName, index, nodeName, parentDirectorName); } int TrackViewComponent::GetNumTrackKeys(const char* paramName, int trackIndex, const char* nodeName, const char* parentDirectorName) { return PyTrackViewGetNumTrackKeys(paramName, trackIndex, nodeName, parentDirectorName); } void TrackViewComponent::SetRecording(bool bRecording) { return PyTrackViewSetRecording(bRecording); } void TrackViewComponent::DeleteSequence(const char* name) { return PyTrackViewDeleteSequence(name); } void TrackViewComponent::SetCurrentSequence(const char* name) { return PyTrackViewSetCurrentSequence(name); } AZStd::string TrackViewComponent::GetSequenceName(unsigned int index) { return PyTrackViewGetSequenceName(index); } Range TrackViewComponent::GetSequenceTimeRange(const char* name) { return PyTrackViewGetSequenceTimeRange(name); } void TrackViewComponent::AddNode(const char* nodeTypeString, const char* nodeName) { return PyTrackViewAddNode(nodeTypeString, nodeName); } void TrackViewComponent::DeleteNode(AZStd::string_view nodeName, AZStd::string_view parentDirectorName) { return PyTrackViewDeleteNode(nodeName, parentDirectorName); } int TrackViewComponent::GetNumNodes(AZStd::string_view parentDirectorName) { return PyTrackViewGetNumNodes(parentDirectorName); } AZStd::string TrackViewComponent::GetNodeName(int index, AZStd::string_view parentDirectorName) { return PyTrackViewGetNodeName(index, parentDirectorName); } AZStd::any TrackViewComponent::GetKeyValue(const char* paramName, int trackIndex, int keyIndex, const char* nodeName, const char* parentDirectorName) { return PyTrackViewGetKeyValue(paramName, trackIndex, keyIndex, nodeName, parentDirectorName); } AZStd::any TrackViewComponent::GetInterpolatedValue(const char* paramName, int trackIndex, float time, const char* nodeName, const char* parentDirectorName) { return PyTrackViewGetInterpolatedValue(paramName, trackIndex, time, nodeName, parentDirectorName); } void TrackViewComponent::SetSequenceTimeRange(const char* name, float start, float end) { return PyTrackViewSetSequenceTimeRange(name, start, end); } } namespace AzToolsFramework { void TrackViewFuncsHandler::Reflect(AZ::ReflectContext* context) { if (auto behaviorContext = azrtti_cast(context)) { behaviorContext->Class("CryRange") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Module, "legacy.trackview") ->Property("start", BehaviorValueProperty(&Range::start)) ->Property("end", BehaviorValueProperty(&Range::end)) ; // this will put these methods into the 'azlmbr.legacy.trackview' module auto addLegacyTrackview = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) { methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Legacy/TrackView") ->Attribute(AZ::Script::Attributes::Module, "legacy.trackview"); }; addLegacyTrackview(behaviorContext->Method("set_recording", PyTrackViewSetRecording, nullptr, "Activates/deactivates TrackView recording mode.")); addLegacyTrackview(behaviorContext->Method("new_sequence", PyTrackViewNewSequence, nullptr, "Creates a new sequence of the given type (0=Object Entity Sequence (Legacy), 1=Component Entity Sequence (PREVIEW)) with the given name.")); addLegacyTrackview(behaviorContext->Method("delete_sequence", PyTrackViewDeleteSequence, nullptr, "Deletes the specified sequence.")); addLegacyTrackview(behaviorContext->Method("set_current_sequence", PyTrackViewSetCurrentSequence, nullptr, "Sets the specified sequence as a current one in TrackView.")); addLegacyTrackview(behaviorContext->Method("get_num_sequences", PyTrackViewGetNumSequences, nullptr, "Gets the number of sequences.")); addLegacyTrackview(behaviorContext->Method("get_sequence_name", PyTrackViewGetSequenceName, nullptr, "Gets the name of a sequence by its index.")); addLegacyTrackview(behaviorContext->Method("get_sequence_time_range", PyTrackViewGetSequenceTimeRange, nullptr, "Gets the time range of a sequence as a pair.")); addLegacyTrackview(behaviorContext->Method("set_sequence_time_range", PyTrackViewSetSequenceTimeRange, nullptr, "Sets the time range of a sequence.")); addLegacyTrackview(behaviorContext->Method("play_sequence", PyTrackViewPlaySequence, nullptr, "Plays the current sequence in TrackView.")); addLegacyTrackview(behaviorContext->Method("stop_sequence", PyTrackViewStopSequence, nullptr, "Stops any sequence currently playing in TrackView.")); addLegacyTrackview(behaviorContext->Method("set_time", PyTrackViewSetSequenceTime, nullptr, "Sets the time of the sequence currently playing in TrackView.")); addLegacyTrackview(behaviorContext->Method("add_node", PyTrackViewAddNode, nullptr, "Adds a new node with the given type & name to the current sequence.")); addLegacyTrackview(behaviorContext->Method("add_selected_entities", PyTrackViewAddSelectedEntities, nullptr, "Adds an entity node(s) from viewport selection to the current sequence.")); addLegacyTrackview(behaviorContext->Method("add_layer_node", PyTrackViewAddLayerNode, nullptr, "Adds a layer node from the current layer to the current sequence.")); addLegacyTrackview(behaviorContext->Method("delete_node", PyTrackViewDeleteNode, nullptr, "Deletes the specified node from the current sequence.")); addLegacyTrackview(behaviorContext->Method("add_track", PyTrackViewAddTrack, nullptr, "Adds a track of the given parameter ID to the node.")); addLegacyTrackview(behaviorContext->Method("delete_track", PyTrackViewDeleteTrack, nullptr, "Deletes a track of the given parameter ID (in the given index in case of a multi-track) from the node.")); addLegacyTrackview(behaviorContext->Method("get_num_nodes", PyTrackViewGetNumNodes, nullptr, "Gets the number of nodes.")); addLegacyTrackview(behaviorContext->Method("get_node_name", PyTrackViewGetNodeName, nullptr, "Gets the name of a sequence by its index.")); addLegacyTrackview(behaviorContext->Method("get_num_track_keys", PyTrackViewGetNumTrackKeys, nullptr, "Gets number of keys of the specified track.")); addLegacyTrackview(behaviorContext->Method("get_key_value", PyTrackViewGetKeyValue, nullptr, "Gets the value of the specified key.")); addLegacyTrackview(behaviorContext->Method("get_interpolated_value", PyTrackViewGetInterpolatedValue, nullptr, "Gets the interpolated value of a track at the specified time.")); } } }