// =========================================================================== // Copyright 2018 Autodesk, Inc. All rights reserved. // // Use of this software is subject to the terms of the Autodesk license // agreement provided at the time of installation or download, or which // otherwise accompanies this software in either electronic or hard copy form. // =========================================================================== global proc string[] teGetTrackSelection(string $trackNodeName, int $trackIndex, int $warn) // // Description: // Determines which track(s) should an operation be executed on. // This should be used by track functions that allow an operation to be executed on multiple tracks. // // This is described in the following scenario( TrackInfo here means a string of ":" ): // 1. User select a track and right click on it. Return value: TrackInfo selected track. // 2. User select a track and right click on another track. Return Value: TrackInfo of the track under the mouse cursor. // 3. User select more than one track and right click on any of the tracks. Return Value: Array of TrackInfo of all the selected tracks. // 4. User select more than one track and right click on a track that is not selected. Return Value: TrackInfo of the track under the mouse cursor. // 5. $trackNodeName == "" || $trackIndex == -1. Return Value: Array of TrackInfo of the current selected track(s), if any. // // Input: // $trackNodeName - Track node name of the current track under mouse cursor. // $trackIndex - Track index of the current track under mouse cursor. // $warn - Should a warning be prompted if a valid clip id cannot be found. // // Return: // Array of TrackInfos. // { string $allSelectedTracks[] = `timeEditorTracks -q -selectedTracks`; // verify if the given input param is valid if($trackNodeName == "" || $trackIndex < 0) { // if there are no selected tracks & given track data is invalid, prompt warning if needed. if(size($allSelectedTracks) == 0 && $warn) { warning( (uiRes("m_teTrackFunctions.kNoTracksSelected")) ); } } else { // if there are selecte tracks in the scene, we check if the given track is part of the selection // first, we make sure the given track data is refering to a valid track node and index // by ensuring a valid plug index. int $plugIndex = -1; int $retVal = catchQuiet( $plugIndex = `timeEditorTracks -q -trackIndex $trackIndex -plugIndex $trackNodeName` ); if( $retVal == 0 && $plugIndex > -1) { string $searchKey = $trackNodeName+":"+$trackIndex; if(stringArrayFind($searchKey, 0, $allSelectedTracks) == -1) { // if given track is not part of the selected // we return only the given track clear($allSelectedTracks); $allSelectedTracks[0] = $trackNodeName + ":" + $trackIndex; } } } return $allSelectedTracks; } global proc string teParseTrackNode(string $trackString) { string $tmp[]; int $n = tokenize($trackString, ":", $tmp); if ($n < 2) return $trackString; stringArrayRemoveAtIndex($n-1, $tmp); // remove index from path return stringArrayToString($tmp, ":"); } global proc int teParseTrackIndex(string $trackString) { string $tmp[]; int $n = tokenize($trackString, ":", $tmp); if ($n < 2) return -1; return (int)$tmp[$n-1]; } global proc string teGetFirstTrackInSelection(string $trackNodeName, int $trackIndex, int $warn) // // Description: // Helper function to teGetTrackSelection(). // Returns only the first TrackInfo in a list of selected tracks determined by teGetTrackSelection(), if the given track is invalid. // This should be used by track functions that only an operation to be executed on a single track at any one time. // // Input: // $trackNodeName - Track node name of the current track under mouse cursor. Empty string is node name is unknown // $trackIndex - Track index of the current track under mouse cursor. -1 if index is unknown. // $warn - Should a warning be prompted if a valid clip id cannot be found. // // Return: // TrackInfo string. Empty string if a valid TrackInfo cannot be found. // { int $plugIndex = -1; int $retVal = catchQuiet( $plugIndex = `timeEditorTracks -q -trackIndex $trackIndex -plugIndex $trackNodeName` ); string $ret = ""; if( $retVal == 0 && $plugIndex > -1) { $ret = $trackNodeName+":"+$trackIndex; } else { string $selectedTracks[] = teGetTrackSelection($trackNodeName, $trackIndex, $warn); if(size($selectedTracks) > 0) { $ret = $selectedTracks[0]; } } return $ret; } global proc string teGetActiveTabViewTrackNode() // // Description: // Returns the track node name of the current active tab in Time Editor. // If the editor is not open, it will return the track node of the current active composition. // If an active composition cannot be found, it will return an empty string. // // Return: // Track Node Name of the current active tab. // { string $tracksNodeName = ""; string $timeEd = "timeEditorPanel1TimeEd"; if(`timeEditorPanel -exists $timeEd`) { // get the track node of the active view from the Time Editor Window int $activeTab = `timeEditorPanel -q -activeTabView $timeEd`; int $groupId = `timeEditorPanel -groupIdForTabView $activeTab -q $timeEd`; if($groupId != 0) { $tracksNodeName = `timeEditorClip -q -tracksNode -clipId $groupId`; } } // Fetch the global tracks node if no group tab view or time editor is not opened if($tracksNodeName == "") { string $activeComp = ""; // Prevent the warning from MEL command from interrupting. catchQuiet($activeComp = `timeEditorComposition -q -active`); $tracksNodeName= `timeEditorComposition -q -tracksNode $activeComp`; } return $tracksNodeName; } global proc string teGetActiveTabNewTrackIdString() { return teGetActiveTabViewTrackNode() + ":-1"; } global proc int teIsTrackSelected(string $trackNodeName, int $trackIndex) // // Determines if the given track is selected // // Input: // $trackNodeName - Track node name. // $trackIndex - Track index. // // Return: // 1 or 0 depending on whether track is selected. // { int $selectedTracks[] = `timeEditorTracks -q -selectedTracks $trackNodeName`; // if nothing is selected if(size($selectedTracks) == 0) return 0; return (intArrayFind($trackIndex, 0, $selectedTracks) != -1); } global proc int teIsSelectedTracksMuted(string $trackNodeName, int $trackIndex) // // Determines if the given track is Muted, will return 1 if one track is muted. // // Input: // $trackNodeName - Track node name. // $trackIndex - Track index. // // Return: // 1 or 0 depending on whether track is muted. // { string $selected[] = teGetTrackSelection($trackNodeName, $trackIndex, 1); if(size($selected) == 0) return 0; for ($track in $selected) { int $ti = teParseTrackIndex($track); string $t = teParseTrackNode($track); int $muted = `timeEditorTracks -q -trackIndex $ti -trackMuted $t`; if($muted) return 1; } return 0; } global proc teMuteUnmuteSelectedTracks(int $mute, string $trackNodeName, int $trackIndex) // // Description: // Mute/Unmute tracks // // Input: // mute : mute or unmute the selected tracks // trackNodeName : track node name under mouse cursor // trackIndex : track index // { string $selected[] = teGetTrackSelection($trackNodeName, $trackIndex, 1); if(size($selected) == 0) return; string $cmd_to_run = ""; for ($track in $selected) { string $cmd = "timeEditorTracks -e -trackIndex " + teParseTrackIndex($track) + " -trackMuted " + ($mute == 0 ? false : true) + " " + teParseTrackNode($track) + ";"; $cmd_to_run = $cmd_to_run + $cmd; } evalEcho($cmd_to_run); } global proc int teIsSelectedTracksSoloed(string $trackNodeName, int $trackIndex) // // Determines if the given track is Soloed, will return 1 if one track is Soloed. // // Input: // $trackNodeName - Track node name. // $trackIndex - Track index. // // Return: // 1 or 0 depending on whether track is Soloed. // { string $selected[] = teGetTrackSelection($trackNodeName, $trackIndex, 1); if(size($selected) == 0) return 0; for ($track in $selected) { int $ti = teParseTrackIndex($track); string $t = teParseTrackNode($track); int $soloed = `timeEditorTracks -q -trackIndex $ti -trackSolo $t`; if($soloed) return $soloed; } return 0; } global proc teSoloUnsoloSelectedTracks(int $add, int $solo, string $trackNodeName, int $trackIndex) // // Description: // Solo/Unsolo tracks // // Input: // add : specify whether we add selected tracks to solo or do we reset // solo : solo or unsolo the selected tracks // trackNodeName : track node name under mouse cursor // trackIndex : track index // { string $selected[] = teGetTrackSelection($trackNodeName, $trackIndex, 1); if(size($selected) == 0) return; string $cmd_to_run; if(!$add) { // we are not adding selected track to the current set of solo tracks // so we need to reset the current solo tracks $cmd_to_run = "timeEditorTracks -resetSolo;"; } for ($track in $selected) { string $cmd = "timeEditorTracks -e -trackIndex " + teParseTrackIndex($track) + " -trackSolo " + ($solo == 0 ? false : true) + " " + teParseTrackNode($track) + ";"; $cmd_to_run = $cmd_to_run + $cmd; } evalEcho($cmd_to_run); } global proc teDeleteSelectedTracks(string $trackNodeName, int $trackIndex) // // Description: // selected tracks is a string array, for example: // TimeEditor_Tracks_Composition1:0 Group_B_Tracks:0 Group_B_Tracks:1 // Please note that tracksNode may be more than one. // We need to form a remove command such that track indices under // the same tracksNode should form one track remove list, the final command // of above example should be: // timeEditorTracks -e -rt 0 TimeEditor_Tracks_Composition1; timeEditorTracks -e -rt 0 -rt 1 Group_B_Tracks; // // Input: // trackNodeName : track node name under mouse cursor // trackIndex : track index // { string $selected[] = teGetTrackSelection($trackNodeName, $trackIndex, 1); if(size($selected) == 0) return; string $cmds[]; string $tracksNodeList[]; for ($track in $selected) { // track name should be in this format: "trackNode:trackNumber" int $index = (int)teParseTrackIndex($track); string $tracksNode = teParseTrackNode($track); if (!stringArrayContains($tracksNode, $tracksNodeList)) { $tracksNodeList[size($tracksNodeList)] = $tracksNode; $cmds[size($cmds)] = "timeEditorTracks -e -removeTrack " + $index; } else { int $pos = stringArrayFind($tracksNode, 0, $tracksNodeList); $cmds[$pos] = $cmds[$pos] + " -removeTrack " + $index; } } string $finalCmd; int $i; for ($i = 0; $i < size($tracksNodeList) ; $i ++) { $finalCmd = $finalCmd + $cmds[$i] + " " + $tracksNodeList[$i] + "; "; } evalEcho($finalCmd); } global proc int teGetTrackIndex(string $trackInfo) // // Description: // Returns the track index in the given TrackInfo string. // // Input: // $trackInfo : TrackInfo string in the format ":"; // // Return: // Int track index. -1 if not valid. // { return teParseTrackIndex($trackInfo); } global proc string teCreateNewTrack(int $trackType) // // Description: // Returns a valid TrackInfo string of the newly created track (Tab-awareness) // // Input: // $trackType : What type of track should be created // // Return: // TrackInfo string // { string $activeTracksNode = teGetActiveTabViewTrackNode(); int $newTrackIndex = `timeEditorTracks -e -addTrack -1 -trackType $trackType $activeTracksNode`; return ($activeTracksNode + ":" + $newTrackIndex); } global proc string teGetTrackForClipCreation(int $autoCreate, int $trackType) // // Description: // Returns a valid TrackInfo string for use by clip creation function. //// - If there is a track selected, choose it as target track // - Otherwise, create new one(Tab-awareness) as required // // Input: // $autoCreate : If we should create a valid track if one cannot be found // $trackType : What type of track should be created // // Return: // TrackInfo string // { int $createNewTrack = $autoCreate; string $trackName = teGetFirstTrackInSelection("", -1, 0); if($trackName != "") { int $trackIndex = teGetTrackIndex($trackName); string $tracksNode = teParseTrackNode($trackName); if(`timeEditorTracks -q -trackType -trackIndex $trackIndex $tracksNode` == $trackType) { // it is the correct type - no need to create a new track $createNewTrack = 0; } else { warning( (uiRes("m_teTrackFunctions.kNoCorrectTrackType")) ); } } else { // try to use first empty track $trackName = teLastEmptyAnimationTrack($trackType); if ($trackName == "" && $createNewTrack) { $trackName = teCreateNewTrack($trackType); } } return $trackName; } global proc teCreateTrackAtEnd(int $trackType) // // Description: // Create new Track // If there is a track selected, add new track before it // Otherwise, create new one at the end of the active tab(Tab-awareness) // // Input Argument: // trackType: the type of track to create // // Return:R // None // { // add new or use selected track string $selectedTrack[] = `timeEditorTracks -q -selectedTracks`; int $insertAtTrackIndex = -1; string $tracksNode = ""; // No track selected or more than 1 selected - create a new track regardless if (size($selectedTrack) == 1) { string $trackName = $selectedTrack[0]; $insertAtTrackIndex = teGetTrackIndex($trackName); $tracksNode = teParseTrackNode($trackName); } if($tracksNode == "") { $tracksNode = teGetActiveTabViewTrackNode(); $insertAtTrackIndex = -1; } evalEcho("timeEditorTracks -e -addTrack " + $insertAtTrackIndex + " -trackType " + $trackType + " " + $tracksNode); } global proc teMoveSelectedTracks(int $dir) // // Description: // Move selected tracks up or down // // Input: // direction : move selected tracks up (-1) or down (1) // { // get list of tracks sorted by the tracks node they belong to and subsequently by track index string $selectedTracks[] = sort(`timeEditorTracks -q -selectedTracks`); int $num = size($selectedTracks); int $i = 0; string $node = ""; // tracks node of the currently processed track int $index = 0; // track index string $currentNode = ""; string $cmd = ""; // final command to execute int $lower = 0, $upper = 0; // boundaries that tracks can be moved within while($i < $num) { int $k = $dir == -1 ? $i : $num-1-$i; // if moving down, process list in reverse order $node = teParseTrackNode($selectedTracks[$k]); $index = teParseTrackIndex($selectedTracks[$k]); $i++; if ($node != $currentNode) { int $num = size(`timeEditorTracks -q -allTracks $node`); $lower = 0; $upper = $num-1; $currentNode = $node; } // validate if track can be moved in the desired direction if ($dir == -1) { if ($index - 1 < $lower) { $lower++; continue; } } else { if ($index + 1 > $upper) { $upper--; continue; } } // add command to move this track $cmd += "timeEditorTracks -e -reorderTrack " + $index + " " + $dir + " " + $node + ";"; } if (size($cmd) > 0) evalEcho($cmd); }