// =========================================================================== // 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. // =========================================================================== // // Creation Date: April 2009 // // Description: // A collection of utility functions used by sequencer and it's tools. // Always use these convenience routines in case the shot/sequence architecture changes // global proc string[] getSelectedShots() { string $shots[] = `ls -sl -type "shot"`; return $shots; } // Get the selected shot with the lowest sequence start frame global proc string getSelectedShotMin() { string $shots[] = getSelectedShots(); if (size ($shots) == 0 ) { return ""; } float $min = `getAttr ($shots[0] + ".sequenceStartFrame")`; string $shot = $shots[0]; for ($i = 1; $i < size ($shots); $i++) { float $smin = `getAttr ($shots[$i] + ".sequenceStartFrame")`; if ($smin < $min ) { $min = $smin; $shot = $shots[$i]; } } return $shot; } global proc string getSelectedShotMax() { string $shots[] = getSelectedShots(); if (size ($shots) == 0 ) { return ""; } float $max = `getAttr ($shots[0] + ".sequenceEndFrame")`; string $shot = $shots[0]; for ($i = 1; $i < size ($shots); $i++) { float $smax = `getAttr ($shots[$i] + ".sequenceEndFrame")`; if ($smax > $max ) { $max = $smax; $shot = $shots[$i]; } } return $shot; } global proc string getSequenceManager() { string $name = `sequenceManager -q -node`; return $name; } global proc float getSequenceTime() { float $time = `getAttr ( getSequenceManager() + ".outTime")`; return $time; } global proc string getShotsCamera( string $shot ) { string $camera = `shot -q -currentCamera $shot`; // Check to make sure the camera is a camera shape. If it is a transform, get the child // camera shape. if ($camera != "") { if (!`objectType -isAType "camera" $camera`) { if (`objectType -isAType "transform" $camera`) { string $s, $shapes[] = `listRelatives -children -f $camera`; $camera = ""; for ($s in $shapes) { if (`objectType -isAType "camera" $s`) { $camera = $s; break; } } } else { $camera = ""; } } } return $camera; } // // Returns the name of the camera used by this slot as this name // would appear in the listCameras() command, or the name of the // cameraSet if this camera uses a cameraSet. // global proc string getShotCurrentCamera( string $shot ) { string $currentCamera = `shot -q -cc $shot`; return $currentCamera; } // // Returns the list of all possible choices for cameras to be used // by shots, including stereo cameras and cameraSets. // global proc string[] getCameraChoicesForShots() { string $allCameras[] = listCameras(); if (`pluginInfo -q -loaded stereoCamera`) { string $stereoRigs[] = `ls -type stereoRigTransform`; appendStringArray($allCameras, $stereoRigs, size($stereoRigs)); } string $cameraSets[] = `ls -type cameraSet`; appendStringArray($allCameras, $cameraSets, size($cameraSets)); return $allCameras; } // // Returns the list of all possible choices for cameras to be used // by shots, except for the current camera of the given shot. // global proc string[] getCameraChoicesForShotsExceptCurrent( string $shot ) { $cameras = getCameraChoicesForShots(); if ( $shot != "" ) { string $currentCamera[]; $currentCamera[0] = getShotCurrentCamera( $shot ); $cameras = stringArrayRemove($currentCamera, $cameras); } return $cameras; } // // Get the image plane on the shot's camera // global proc string getShotsImagePlane( string $shot ) { string $camera = getShotsCamera( $shot ); if( $camera != "" ) { // The camera's image plane should match the clip pointed to by the shot. // If it is not found, return an empty string. string $clip = getShotsClip($shot); string $c, $ips[] = `listConnections -shapes 1 -d true ($camera + ".imagePlane")`; for ($c in $ips) { if ($c == $clip) return $clip; } } return ""; } // // The front plate is an attribute of the shot. It's connected as needed to the shot's camera // global proc string getShotsClip( string $shot ) { string $fp = ""; string $fps[] = `listConnections -shapes 1 ($shot + ".clip")`; if( size ($fps) > 0 ) $fp = $fps[0]; return $fp; } // // return the shot connected to the passed-in imagePlane // global proc string getClipsShot( string $imagePlane ) { string $shot = ""; if (size($imagePlane) > 0) { string $shots[] = `listConnections -type "shot" ($imagePlane+".message")`; if( size ($shots) > 0 ) $shot = $shots[0]; } return $shot; } global proc string[] getCamerasImagePlanes(string $camera ) { // Find the image planes which also point to a shot. There should just // be one, but older or corrupt files may contain more than one. string $retVal[]; string $ip, $ips[] = `listConnections -shapes 1 -type "imagePlane" ($camera + ".imagePlane")`; for ($ip in $ips) { string $shots[] = `listConnections -type "shot" ($ip + ".message")`; if (size($shots) > 0) $retVal[size($retVal)] = $ip; } return $retVal; } // // Disconnect the image plane, and reset the shot's info. Do not remove the movie // file from disk global proc removeImageplane( string $shot ) { // First delete the expressions that were built, then the IP itself string $ip = getShotsClip( $shot ); if ($ip == "") return; string $fe[] = `listConnections ( $ip + ".frameExtension")`; if ( size($fe) > 0 ) { delete $fe[0]; } string $de[] = `listConnections ( $ip + ".depth")`; if ( size($de) > 0 ) { delete $de[0]; } // Remove all of the connections from the image plane to any shots and cameras. // There should be only one connection to a shot and camera, but older or // corrupt files may contain more than one. string $c, $msgs[] = `listConnections -plugs true ($ip + ".message")`; for ($c in $msgs) { disconnectAttr ($ip + ".message") $c; } delete $ip; setAttr ( $shot + ".clipScale" ) 1; setAttr ( $shot + ".clipDuration" ) 0; setAttr ( $shot + ".clipZeroOffset") 0; setAttr ( $shot + ".clipPreHold") 0; setAttr ( $shot + ".clipPostHold") 0; } global proc buildFrameExtensionExpr( string $shot, string $newIP ) { string $feAttr = $newIP + ".frameExtension"; if( `connectionInfo -isDestination $feAttr` == false ) { // This expression calculates the correct frame number in the image plane // video clip for a given sequence time. The holds and scaling when the // clip was generated is taken into account. string $expr = ( "{\n" + " float $elS = sequenceManager1.outTime - " + $shot + ".sequenceStartFrame;\n" + " float $elE = " + $shot + ".sequenceEndFrame - sequenceManager1.outTime;\n" + " float $scl = " + $shot + ".clipScale / " + $shot + ".scale;\n" + " float $first = " + $shot + ".clipZeroOffset + 1;\n" + " if (" + $shot + ".clipPreHold > 0)\n" + " $first = " + $shot + ".clipPreHold;\n" + " if ($elS <= " + $shot + ".preHold)\n" + " " + $newIP + ".frameExtension = $first;\n" + " else if ($elE < " + $shot + ".postHold)\n" + " " + $newIP + ".frameExtension = $first + (\n" + " " + $shot + ".sequenceEndFrame -\n" + " " + $shot + ".sequenceStartFrame -\n" + " " + $shot + ".postHold -\n" + " " + $shot + ".preHold + 1) * $scl;\n" + " else \n" + " " + $newIP + ".frameExtension = $first + (\n" + " sequenceManager1.outTime -\n" + " " + $shot + ".sequenceStartFrame -\n" + " " + $shot + ".preHold) * $scl;\n" + "}" ); expression -s $expr -n ($newIP + "FrameExtensionExpresion"); } // Connect the IP time to the sequence time, this ensures they stay in sync string $exps[] = `listConnections ($feAttr)`; if( size ($exps) > 0 ) // Should be, as a result of the call to checkUseFrameExtension() { string $srcs[] = `listConnections -plugs true ($exps[0] + ".time")`; if (size($srcs) > 0) { disconnectAttr $srcs[0] ($exps[0] + ".time"); } connectAttr "sequenceManager1.outTime " ($exps[0] + ".time"); } } global proc buildDepthExpr( string $shot, string $newIP ) { // Link the image plane to the camera's near plane, put it just in front so nothing can come between the near clip and the IP string $expressionName = ($newIP + "depthExpression"); string $dAttr = $newIP + ".depth"; string $camera = getShotsCamera( $shot ); if ($camera != "") { // Offset just in front of the NCP string $exp = $dAttr + " = " + $camera + ".nearClipPlane + 0.0001;"; // Check for an existing expression for depth string $srcs[] = `listConnections -plugs true $dAttr`; // Edit the existing expression if (size($srcs) > 0) { string $editedExpression = `expression -e -s $exp -o $camera -ae 1 -uc all $expressionName`; if ( $editedExpression != $expressionName ) { error ((uiRes("m_sequencerUtils.kExpressionError"))); } } else { string $createdExpression = `expression -s $exp -o $camera -ae 1 -uc all -name $expressionName`; } } // Connect to sequence time, this ensures they stay in sync if (`isConnected "time1.outTime" ($expressionName +".time ")`) { disconnectAttr "time1.outTime" ($expressionName +".time "); } connectAttr "sequenceManager1.outTime " ($expressionName + ".time"); } global proc alignShotImagePlaneCamera(string $camera, string $ip) { float $coi[] = `camera -q -worldCenterOfInterest $camera`; setAttr ($ip+".center") -type "double3" $coi[0] $coi[1] $coi[2]; } global proc alignShotImagePlaneRatio(string $shot, string $ip) { // Get the ratio from the shot image resolution float $x = `getAttr ($shot + ".wResolution")`; float $y = `getAttr ($shot + ".hResolution")`; float $z = `getAttr ($ip + ".sizeX")`; if ($x != 0.0) { $z = $z * $y / $x; setAttr ($ip+".sizeY") $z; } } // Some convenience routines for icons/quick editing global proc sequencerTrimShotByOne() { string $shots[] = getSelectedShots(); float $ef = `getAttr ($shots[0] + ".endFrame")`; $ef -= 1; setAttr ($shots[0] + ".endFrame") $ef; } global proc sequencerShiftShotByOne( int $dir ) { string $shots[] = getSelectedShots(); float $sf = `getAttr ($shots[0] + ".sequenceStartFrame")`; float $ef = `getAttr ($shots[0] + ".sequenceEndFrame")`; $sf += $dir; $ef += $dir; setAttr ($shots[0] + ".sequenceStartFrame") $sf; setAttr ($shots[0] + ".sequenceEndFrame") $ef; } global proc string getLinkedShot( string $audio ) { string $conn[] = `listConnections -d true -s false ($audio + ".message")`; string $c; for ($c in $conn) { if (`objectType -isType "shot" $c`) return $c; } return ""; } global proc changeActiveShot( string $group, int $newActiveShotIndex ) { int $currentActiveShotIndex = getAttr($group+".shotGroup"); setAttr ($group + ".shotGroup ") $newActiveShotIndex; string $groupShots[] = `sets -q $group`; $groupShots = `sort $groupShots`; // The .shotGroup index always indexes alphabetically string $currentActiveShot = $groupShots[$currentActiveShotIndex]; string $newActiveShot = $groupShots[$newActiveShotIndex]; if(`optionVar -q "rippleEditModeEnabled"` == 1) { int $currShotStart, $currShotEnd, $newShotStart, $newShotEnd, $startDelta, $endDelta; $currShotStart = getAttr($currentActiveShot + ".sequenceStartFrame"); $currShotEnd = getAttr($currentActiveShot + ".sequenceEndFrame"); $newShotStart = getAttr($newActiveShot + ".sequenceStartFrame"); $newShotEnd = getAttr($newActiveShot + ".sequenceEndFrame"); $startDelta = $newShotStart - $currShotStart; $endDelta = $newShotEnd - $currShotEnd; if( ($startDelta != 0) || ($endDelta != 0) ) { shotRipple -startTime $currShotStart -startDelta $startDelta -endTime $currShotEnd -endDelta $endDelta $newActiveShot; } } else { // Move the shot to a new track if necessary to avoid collisions. // shot -e -dt $newActiveShot; } select -cl; redrawSequencer; sequenceManager -currentTime `sequenceManager -q -currentTime`; } global proc string getShotsGroup( string $shot ) { string $group = ""; // find out if the shot is connected to any object // sets. If so, make sure the set has a "shotGroup" // attribute // string $sets[] = `listSets -object $shot`; for ( $i = 0; $i < size( $sets ); $i++ ) { string $set = $sets[$i]; if ( `attributeExists "shotGroup" $set` ) { $group = $set; break; } } return $group; } global proc string getActiveShot( string $group ) // returns true if a shot is: // 1) Not in a shot group // 2) The active member of a shot group // Otherwise returns false { string $shot = ""; if("" != $group) { string $groupMembers[] = `sets -q $group`; $groupMembers = `sort $groupMembers`; // The .shotGroup index always indexes alphabetically int $activeIndex = getAttr ($group + ".shotGroup"); $shot = $groupMembers[$activeIndex]; } return $shot; } global proc string[] getGroupShots( string $group ) // returns the list of shots in the group { string $shots[]; if("" != $group) { string $m, $groupMembers[] = `sets -q $group`; for ($m in $groupMembers) $shots[size($shots)] = $m; } return $shots; } global proc int isShotActive( string $shot ) // returns true if a shot is: // 1) Not in a shot group // 2) The active member of a shot group // Otherwise returns false { string $group = getShotsGroup($shot); if("" == $group) { // Not in a group return true; } if($shot == getActiveShot($group)) return true; else return false; } global proc int isShotInactive( string $shot ) // returns true if a shot is: // 1) In a shot group // AND 2) Not the active member of the shot group // Otherwise returns false { string $group = getShotsGroup($shot); if("" == $group) { // Not in a group return false; } if($shot == getActiveShot($group)) return false; else return true; } global proc setShotActive( string $shot ) { string $group = getShotsGroup($shot); if("" == $group) // Not in a group return ; string $members[] = `sets -q $group`; $members = `sort $members`; // The .shotGroup index always indexes alphabetically for ( $i = 0; $i < size( $members ); $i++ ) { if ($members[$i] == $shot) { changeActiveShot $group $i; return; } } } global proc seqCreateGroupByName( string $shot ) // Description: // Creates a group based on the specified shot. The shot may not // already be in a group. // { // Check if the shot is already in a group. // int $i, $j; string $groups[] = `listSets -object $shot`; for ( $i = 0; $i < size( $groups ); $i++ ) { string $group = $groups[$i]; if ( `attributeExists "shotGroup" $group` ) { error( (uiRes("m_sequencerUtils.kCreateGroupAlready"))); return; } } // Not in a group so create the new group. // // MAYA-33470 - the shotGroup attr -must- be added to this object set // before adding any shot nodes to it, or the shot group cache fails string $group = `sets -n "shotGroup"`; select -cl; addAttr -ln "shotGroup" -at long $group; setAttr ( $group + ".shotGroup" ) 0; // add the shot to the new object set select -r $shot; sets -in $group; select -clear; } global proc seqCreateGroup() // Description: // Creates a new group containing any selected shot nodes. There must // be at least one shot node selected and these shot nodes may not already // be in a group. // { // Must have one or more shot nodes currently selected. // string $shots[] = `ls -sl -type shot`; if ( 0 == size( $shots ) ) { error( (uiRes("m_sequencerUtils.kCreateGroupNoShots"))); return; } // All selected shots must belong to the same sequencer node, // and they cannot already belong to a group. // string $sequencer = ""; int $i, $j; for ( $i = 0; $i < size( $shots ); $i++ ) { string $msg = ( $shots[$i] + ".msg" ); string $cnx[] = `listConnections $msg`; for ( $j = 0; $j < size( $cnx ); $j++ ) { string $node = $cnx[$j]; string $nodeType = `nodeType $node`; if ( "sequencer" == $nodeType ) { if ( $i == 0 ) { $sequencer = $node; } else if ( $sequencer != $node ) { error( (uiRes("m_sequencerUtils.kCreateGroupTooManySequencers"))); return; } } else if ( "objectSet" == $nodeType ) { if ( `attributeExists "shotGroup" $node` ) { error( (uiRes("m_sequencerUtils.kCreateGroupAlreadySel"))); return; } } } } // Create the group. We use a set to represent the group. // The connection between shot and group is performed via // set membership connection. To distinguish a shotGroup // from other sets, we add the attribute "shotGroup" which // also holds the index of the "active" shot. // // MAYA-33470 - the shotGroup attr -must- be added to this object set // before adding any shot nodes to it, or the shot group cache fails string $selection[] = `ls -sl`; select -cl; string $group = `sets -n "shotGroup"`; addAttr -ln "shotGroup" -at long $group; setAttr ( $group + ".shotGroup" ) 0; // add the shot to the new object set select -r $shots; sets -in $group; select -r $selection; // restore the selection // Shift all shots so they line up with the first shot, both // in time as well as on the same track. // if ( size( $shots ) > 1 ) { $shots = `sort $shots`; string $attr = ( $shots[0] + ".ssf" ); float $ssf = `getAttr $attr`; $attr = ( $shots[0] + ".track" ); int $track = `getAttr $attr`; for ( $i = 0; $i < size( $shots ); $i++ ) { $attr = ( $shots[$i] + ".ssf" ); setAttr $attr $ssf; $attr = ( $shots[$i] + ".track" ); setAttr $attr $track; } } select -clear; } proc addShotByName( string $shot, string $group ) { // Get the horizontal offset and track for shots in the group. // string $members[] = `sets -q $group`; string $attr = ( $members[0] + ".ssf" ); float $ssf = `getAttr $attr`; $attr = ( $members[0] + ".track" ); float $track = `getAttr $attr`; // If the shot is in a group remove it first. // removeShotByName( $shot ); // Add the shot to the new group. // sets -add $group $shot; // Move the shot to match the other shots in the group. // $attr = ( $shot + ".ssf" ); setAttr $attr $ssf; $attr = ( $shot + ".track" ); setAttr $attr $track; } global proc addShot() // Description: // Adds the selected shot to the selected group. If the shot is // already in a group, it gets moved (and if its old group becomes empty // that group is deleted). This function expects: // o Either one shot and one group to be selected (any order). // o Or the shot to move plus a shot in the group to move to (in order). // { // If the user selected a group, then there must be exactly one group // and one shot selected. Move the shot to the group and check if it // was already in a group, removing it prior to the move. // string $sets[] = `ls -sl -type objectSet`; if ( size( $sets ) > 0 ) { // Use the selected groups to specify the where to move the shot. // There must be exactly one selected group and one selected shot. // string $group = ""; if ( size( $sets ) == 1 ) { if ( `attributeExists "shotGroup" $sets[0]` ) { $group = $sets[0]; } } string $shots[] = `ls -sl -type shot`; if ( $group != "" && size( $shots ) == 1 ) { addShotByName( $shots[0], $group ); select -clear; return; } } else { // The user will specify which shot to move and where to move via // shots. There must be exactly two shots selected: // o The first selected shot specifies the shot to move. // o The second selected shot must be in the target group we want // to move the first shot to. // string $shots[] = `ls -sl -type shot`; if ( size( $shots ) == 2 ) { string $shot = $shots[0]; string $groupShot = $shots[1]; string $sets[] = `listSets -object $groupShot`; for ( $i = 0; $i < size( $sets ); $i++ ) { string $group = $sets[$i]; if ( `attributeExists "shotGroup" $group`) { addShotByName( $shot, $group ); select -clear; return; } } } } error( (uiRes("m_sequencerUtils.kAddShotBadGroup"))); } global proc removeShotByName( string $shot ) // Description: // Removes the specified shot from it's group if it belongs to a group. // { string $msg = ( $shot + ".msg" ); string $cnx[] = `listConnections $msg`; for ( $i = 0; $i < size( $cnx ); $i++ ) { string $group = $cnx[$i]; if ( "objectSet" == `nodeType $group` ) { if ( `attributeExists "shotGroup" $group` ) { // Remove the shot from the group. If the group is now // empty, delete it, otherwise reset which shot is // active to the first one. // sets -rm $group $shot; if ( 0 == `sets -s $group` ) { delete $group; } else { setAttr ( $group + ".shotGroup" ) 0; } } } } } global proc seqMuteGroup(string $group) { string $s, $shots[] = getGroupShots($group); for ($s in $shots) shot -e -mute true $s; } global proc seqUnmuteGroup(string $group) { string $s, $shots[] = getGroupShots($group); for ($s in $shots) shot -e -mute false $s; } global proc muteSelectedShots() { string $s, $shots[] = `ls -sl -type shot`; for ($s in $shots) shot -e -mute true $s; } global proc unmuteSelectedShots() { string $s, $shots[] = `ls -sl -type shot`; for ($s in $shots) shot -e -mute false $s; } global proc seqLockGroup(string $group) { string $s, $shots[] = getGroupShots($group); for ($s in $shots) shot -e -lock true $s; } global proc seqUnlockGroup(string $group) { string $s, $shots[] = getGroupShots($group); for ($s in $shots) shot -e -lock false $s; } global proc lockSelectedShots() { string $s, $shots[] = `ls -sl -type shot`; for ($s in $shots) shot -e -lock true $s; } global proc unlockSelectedShots() { string $s, $shots[] = `ls -sl -type shot`; for ($s in $shots) shot -e -lock false $s; } global proc favorSelectedShots() { string $s, $shots[] = `ls -sl -type shot`; for ($s in $shots) shot -e -favorite true $s; } global proc unfavorSelectedShots() { string $s, $shots[] = `ls -sl -type shot`; for ($s in $shots) shot -e -favorite false $s; } global proc removeShot() // Description: // Removes all selected shot nodes from their groups. If the groups // become empty, they are deleted. // { // Must have one or more shot nodes currently selected. // string $shots[] = `ls -sl -type shot`; if ( 0 == size( $shots ) ) { error( (uiRes("m_sequencerUtils.kRemoveGroupNoShots"))); return; } // For each shot, if it belongs to a group remove it from the group // and delete the group if it becomes empty. Since inactive shots in // groups are invisible, they may collide with other shots, so move // the shot to an open track to guarantee no collision. // int $i; for ( $i = 0; $i < size( $shots ); $i++ ) { string $shot = $shots[$i]; removeShotByName( $shot ); shot -e -dt $shot; } select -clear; } global proc seqUngroup( string $selected ) // Description: // Delete any groups that are selected. The shots become ungrouped. // If shots are selected, we also delete the groups they are contained in. // { // Delete any groups that are selected. Also create a unique track // for each shot that was in the group to avoid collisions. // string $groups[] = `ls -sl -type objectSet`; int $i, $j, $k, $n; for ( $i = $n = 0; $i < size( $groups ); $i++ ) { string $group = $groups[$i]; if ( `attributeExists "shotGroup" $group` ) { string $members[] = `sets -q $group`; sets -e -clear $group; delete $group; for ( $k = 0; $k < size( $members ); $k++ ) { shot -e -dt $members[$k]; } $n++; } } // Delete any groups that contain shots on the selection list. Also // create a unique track for each shot that was in the group to // avoid collisons. // string $shots[]; if ($selected == "") { $shots = `ls -sl -type shot`; } else { $shots[0] = $selected; } // If one of the selected shots is in a group, delete the // set (i.e. the group) // for ( $j = 0; $j < size( $shots ); $j++ ) { string $sets[] = `listSets -object $shots[$j]`; for ( $i = 0; $i < size( $sets ); $i++ ) { string $set = $sets[$i]; if ( `attributeExists "shotGroup" $set` ) { string $members[] = `sets -q $set`; sets -e -clear $set; delete $set; for ( $k = 0; $k < size( $members ); $k++ ) { shot -e -dt $members[$k]; } $n++; break; } } // end for $i } // end for $j if ( 0 == $n ) { error( (uiRes("m_sequencerUtils.kUngroupNoGroups"))); return; } select -clear; } global proc seqDeleteGroupAndContents( string $selected ) // Description: // Delete any groups that are selected. The shots contained in the // groups are deleted as well. For any shots on the selection list we also // delete their groups and any siblings. // { // Delete the shots within selected groups. This also deletes the // groups when they empty. // string $groups[] = `ls -sl -type objectSet`; int $i, $j, $k, $n; for ( $i = $n = 0; $i < size( $groups ); $i++ ) { string $group = $groups[$i]; if ( `attributeExists "shotGroup" $group` ) { string $members[] = `sets -q $group`; for ( $j = 0; $j < size( $members ); $j++ ) { delete $members[$j]; } $n++; } } // Delete any groups that contain shots on the selection list. // string $shots[]; if ($selected == "") { $shots = `ls -sl -type shot`; } else { $shots[0] = $selected; } // If one of the selected shots is part of a group, delete the // set (i.e the group) and contents // for ( $j = 0; $j < size( $shots ); $j++ ) { string $shot = $shots[$j]; if( !`objExists $shot` ) continue; string $sets[] = `listSets -object $shots`; for ( $i = 0; $i < size( $sets ); $i++ ) { string $set = $sets[$i]; if ( `attributeExists "shotGroup" $set` ) { string $members[] = `sets -q $set`; for ( $k = 0; $k < size( $members ); $k++ ) { delete $members[$k]; } $n++; break; } } // end for $i } // end for $j if ( 0 == $n ) { error( (uiRes("m_sequencerUtils.kDeleteGroupAndContentsNoGroups"))); return; } select -clear; } global proc redrawSequencer() // Description: // Utility method to force the sequencer editor to redraw. There are // some cases where an automatic redraw does not happen such as with // groups. We just read and write the "nodeState" attribute on each // sequencer node. // { string $seq[] = `ls -type sequencer`; int $i; for ( $i = 0; $i < size( $seq ); $i++ ) { string $attr = ( $seq[$i] + ".nodeState" ); int $state = `getAttr $attr`; setAttr $attr 0; setAttr $attr $state; } } global proc int[] isolateShot( string $inShot, string $shots[] ) // // Description: // Mute all the shots that are not the inShot shot. // Return each shot's original track state. // { string $shotName = `shot -q -sn $inShot`; string $shotOutName; int $shotState[]; int $shootOutTrack = `shot -q -track $inShot`; int $i; for ( $i = 0; $i < size($shots); $i++ ) { $shotState[$i] = `shot -q -selfmute $shots[$i]`; int $shotTrack = `shot -q -track $shots[$i]`; if( $shotTrack == $shootOutTrack ){ $shotOutName = `shot -q -sn $shots[$i]`; if (!($shotName == $shotOutName)){ shot -e -mute true $shots[$i]; // Mute }else{ shot -e -mute false $shots[$i]; // Unmute } }else shot -e -mute true $shots[$i]; } return $shotState; } global proc string legalizeShotName( string $shot, string $camera, string $template ) // // Description: // Modify illegal characters and replace the and template tokens // and return a name that can be used as a system filename. // { // Change any namespace delimiters into underscores, // since this will be used as a disk file name. string $buf[]; int $numTokens = `tokenize $shot ":" $buf`; string $shotName = ""; if ($numTokens > 1) { $shotName = ""; string $s; for ($s in $buf) { if ($shotName == "") $shotName = $s; else $shotName = $shotName + "_" + $s; } } else { if ($template != "") $shotName = $template; else $shotName = $shot; } // Replace all the tokens provided by template $shotName = `substitute "" $shotName $shot`; $shotName = `substitute "" $shotName $camera`; return $shotName; } global proc setShotTrackStates( string $shots[], int $trackStates[] ) // // Description: // Set the track state of the given list of shots to the given track states. // { for ( $i = 0; $i < size($shots); $i++ ) shot -e -mute $trackStates[$i] $shots[$i]; } global proc seqDisconnectImagePlane(string $imagePlane, string $camera) // // Description: // Cleanly disconnect the given image plane from the given camera. // { // Turn off the visibility, which will trigger the 3d to be drawn. // Sequencer has the feature where visibility=1 turns off the 3d, // and that could result in playblasting an empty scene. setAttr ($imagePlane + ".visibility") 0; // Disconnect all connections between this image plane and any cameras. string $c, $cams[] = `listConnections -type "camera" ($imagePlane + ".message ")`; for ($c in $cams) disconnectAttr -na ($imagePlane + ".message ") ($c + ".imagePlane"); // Needed in case the attribute editor is open, which will cause // the image to try read from the file on disk. setAttr ($imagePlane + ".imageName") -type "string" ""; } global proc seqRestoreImagePlane(string $oldIP, string $camera, string $oldImage, float $oldVisibility, int $oldType) // // Description: // Restore an old image plane. // { // Make the connection from the image plane to the camera if one doesn't // already exist. string $c, $cams[] = `listConnections -type "camera" ($oldIP + ".message ")`; int $alreadyConnected = false; for ($c in $cams) { if ($c == $camera) { $alreadyConnected = true; break; } } if (!$alreadyConnected) connectAttr -na ($oldIP + ".message " ) ($camera + ".imagePlane"); setAttr ($oldIP + ".visibility") $oldVisibility; setAttr ($oldIP + ".imageName") -type "string" $oldImage; setAttr ($oldIP + ".type") $oldType; } global proc setupShotImagePlane( string $shot, int $handles, float $start, float $end, string $image, float $opacity) // // Description: // Set the new image on the given shot node and setup some related attributes. // { // Reset the offset to the handle value. setAttr ($shot + ".clipZeroOffset") $handles; // Set the new image and its length float $duration = $end - $start + 1; shot -e -co $opacity -imagePlaneVisibility 1 -cl $image -cd $duration $shot; // Set the image attribute to the match the shot attributes. This will allow // the clip to stay in sync with the shot as it is scaled and held. float $scale = `getAttr ($shot + ".scale")`; float $preHold = `getAttr ($shot + ".preHold")`; float $postHold = `getAttr ($shot + ".postHold")`; setAttr ($shot + ".clipScale") $scale; setAttr ($shot + ".clipPreHold") $preHold; setAttr ($shot + ".clipPostHold") $postHold; setAttr ($shot + ".clipValid") 1; // New clip, so it's in sync with the 3d } // // Description: // Set the weight for the associated animation layer of the current shot (if // there is one) to 1.0, and set the weight for the layers associated with // all other shots to 0.0 . // global proc updateCustomAnimLayerWeights(string $currentShot) { // get list of all shots string $s, $shots[] = `ls -type shot`; // set them all to weight 0.0 for ($s in $shots) setAttr ($s+".customAnim") 0.0; // set the currentShot attr to weight 1.0 setAttr ($currentShot+".customAnim") 1.0; } global proc string createCustomAnimLayer(string $shot) { // Create the animLayer node. string $tmpAnimLayer = layerEditorCreateAnimLayer(false,false); // Rename the animLayer node to be based on the shotName attribute. // Make sure the name is a valid object name by converting illegal // characters into underscores and making sure the name starts with a letter. string $newAnimLayer = `shot -q -shotName $shot`; if (!isValidObjectName($newAnimLayer)) { string $buf[]; tokenize $newAnimLayer "`~!@#$%^&*()-=+[]\\{}|;':\",./<>? " $buf; $newAnimLayer = stringArrayToString($buf, "_"); string $start = startString($newAnimLayer, 1); string $lower = tolower($start); $start = `match "[a-z]" $lower`; if (size($start) == 0) $newAnimLayer = ("A" + $newAnimLayer); } $newAnimLayer = `rename $tmpAnimLayer ($newAnimLayer+"Layer")`; string $sequencerLayerName = "Sequencer_Layers"; if(! `objExists $sequencerLayerName`){ string $parentLayer = layerEditorCreateAnimLayer(false,false); rename $parentLayer $sequencerLayerName; } animLayer -e -parent $sequencerLayerName $newAnimLayer; connectAttr ($shot + ".customAnim") ($newAnimLayer+".weight"); // If the shot is the current shot, set its weight to 1. if (`sequenceManager -q -currentShot` == $shot) setAttr ($shot + ".customAnim") 1.0; return $newAnimLayer; } global proc deleteCustomAnimLayer(string $currentShot) { string $newAnimLayer; string $d[] = `listConnections ($currentShot+".customAnim")`; if (size($d) > 0) { string $customLayer = $d[0]; delete $customLayer; } string $sequencerLayerName = "Sequencer_Layers"; if( `objExists $sequencerLayerName`){ string $children[] = `animLayer -q -c $sequencerLayerName`; if (size($children) == 0){ delete $sequencerLayerName; } } } global proc string getDefaultPlayblastDirectory() // // Description: // Return the first directory in the "movie" file rule. // This will be the default directory where shot/sequence // playblasts will be written to. If no rules, return // user temp dir. // { // Note: on Mac/Linux the separator character is actually ":" string $separator = (`about -windows` ? ";" : ":"); string $dirs[]; string $rule = `workspace -q -fre "movie"`; tokenize $rule $separator $dirs; if( size($dirs) > 0 && size($dirs[0]) > 0 ) { return $dirs[0]; } return `internalVar -userTmpDir`; } // sortShotlist, sortShotSublist, and partitionShotlist make up an // in-place quicksort for a string array of shot node names. // Currently they are sorted according to sequenceStartFrame value // proc int partitionShotlist(string $shotlist[], int $left, int $right, int $pivotIndex) { string $pivotName = $shotlist[$pivotIndex]; int $pivotValue = getAttr($pivotName+".sequenceStartFrame"); //swap string $tmpName = $shotlist[$right]; $shotlist[$pivotIndex] = $tmpName; $shotlist[$right] = $pivotName; //storeIndex int $storeIndex = $left; int $i; for ($i = $left; $i <= $right-1; $i++) { int $iVal = `getAttr($shotlist[$i]+".sequenceStartFrame")`; if ($iVal <= $pivotValue) { //swap $tmpName = $shotlist[$i]; $shotlist[$i] = $shotlist[$storeIndex]; $shotlist[$storeIndex] = $tmpName; $storeIndex++; } } //swap $tmpName = $shotlist[$right]; $shotlist[$right] = $shotlist[$storeIndex]; $shotlist[$storeIndex] = $tmpName; return $storeIndex; } proc sortShotSublist(string $shotlist[], int $left, int $right) { if ($right > $left) { int $pivotIndex = $left; int $pivotNewIndex = partitionShotlist($shotlist,$left,$right,$pivotIndex); sortShotSublist($shotlist,$left,$pivotNewIndex-1); sortShotSublist($shotlist,$pivotNewIndex+1,$right); } return; } // modifies the original shot list to be sorted in order by sequenceStartFrame // TODO - enable sorting by some other attr value global proc sortShotlist(string $shotlist[]) { int $maxIndex = size($shotlist)-1; sortShotSublist($shotlist, 0, $maxIndex); }