// =========================================================================== // 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: July 30, 1997 // // // // // // advanceToNextDrivenKey (string $advanceFlag, string $attribute) // // // None // // // Script for going to the next, previous, first or last // driven keyframe. Driven keyframes are set using Set Driven Key. // // // string $advanceFlag if true, go to next key, else go to previous key // // string $attribute the driven attribute or "" to use selected item // // // // Say you have a lattice point keyed against a joint's rotation. // // Select the lattice point and to go to the previous key enter: // advanceNextDrivenKey -previous ""; // // // To go to the next driven key enter: // advanceToNextDrivenKey -next ""; // // // To go to the first driven key enter: // advanceToNextDrivenKey -first ""; // // // To go to the last driven key enter: // advanceToNextDrivenKey -last ""; // // // If the object has more than one driven-key relationship defined, and // // the "" argument is used, we advance ALL the drivers that // // affect that object. // // // Therefore, if you have many driven attributes on a node, you may want // // to specify the attribute directly, for example: // advanceToNextDrivenKey -previous nurbSphere1.tx; // // // Via the UI, you can specify an attribute to be advanced using the // // setDrivenKey window menu item: Key->Go To Next, Key->Go To Previous. // // ///////////////////////////////////////////////////////////////////////// // Method: getAnimCurve // // Description: // Return the animCurve that connects $driver to $driven. // If such an animCurve cannot be found, returns an empty string. // global proc string getAnimCurve(string $driver, string $driven) { int $ii; string $result = ""; // First we will do the most simple thing ... look for a single // animCurve connected out of the driver. // string $conns[] = `listConnections -scn true -s false $driver`; int $count = size($conns); string $errMsg; if (0 == $count) { $errMsg = (uiRes("m_advanceToNextDrivenKey.kCouldNotLocateDownstream")); error(`format -s $driven $errMsg`); return $result; } int $animCurveCount = 0; for ($ii = 0; $ii < $count; $ii++) { string $isAnimCurve[] = `ls -type animCurve $conns[$ii]`; if (size($isAnimCurve)) { $result = $conns[$ii]; $animCurveCount++; } } if (1 == $animCurveCount ) { return $result; } // If the simple test done first does not work we need to try to // find the proper animCurve in a more complicated way: look in the // upstream history of the driven item for animCurves, and then // for each animCurve determine if its driver is $driver. // // First convert the driven item into an attribute name. // This is necessary for selection items such as CVs, where // the node name to plug name conversion is non-trivial. // string $drivenItems[] = `setDrivenKeyframe -q -dn $driven`; if (0 == size($drivenItems)) { $errMsg = (uiRes("m_advanceToNextDrivenKey.kCouldNotLocateUpstream")); error(`format -s $driven $errMsg`); return $result; } string $hist[] = `listHistory -lf false $drivenItems[0]`; $count = size($hist); for ($ii = 0 ; $ii < $count; $ii++) { string $isAnimCurve[] = `ls -type animCurve $hist[$ii]`; if (size($isAnimCurve)) { $conns = `listConnections -d false -p true -scn true ($hist[$ii]+".i")`; if (1 == size($conns)) { if ($conns[0] == $driver) { $result = $hist[$ii]; break; } } } } return $result; } // // Method: nextDrivenAdvance // // Description: // Given an animCurve with a non-time input, determine and perform // the setAttr command that will cause the input to move to the next // keyed value. // // Returns: // nothing // global proc nextDrivenAdvance(string $advanceFlag, string $animCrv) { float $tolerance = 0.0000005; string $conns[] = `listConnections -d false -p true -scn true ($animCrv+".i")`; if (1 != size($conns)) { error((uiRes("m_advanceToNextDrivenKey.kNextDrivenAdvance"))); return; } $attrToSet = $conns[0]; float $currentValue = `getAttr $attrToSet`; // tolerance is used to prevent the advance from getting stopped // up by precision errors // if ($advanceFlag == "-next" || $advanceFlag == "-n") { $currentValue += $tolerance; } else { $currentValue -= $tolerance; } // get current keys // float $values[] = `keyframe -q -fc $animCrv`; int $valueCount = size($values); if (0 == $valueCount) { string $errMsg = (uiRes("m_advanceToNextDrivenKey.kNoKeyframesFound")); error(`format -s $attrToSet $errMsg`); return; } // find the next keyframe and advance to it using setAttr // string $cmd; if ($advanceFlag == "-next" || $advanceFlag == "-n") { for ($jj = 0; $jj < $valueCount; $jj++) { if ($currentValue < $values[$jj]) { $cmd = "setAttr "+$attrToSet+" "+$values[$jj]; break; } $cmd = "setAttr "+$attrToSet+" "+$values[0]; } } else if ($advanceFlag == "-previous" || $advanceFlag == "-p") { for ($jj = $valueCount-1; $jj >= 0; $jj--) { if ($currentValue > $values[$jj]) { $cmd = "setAttr "+$attrToSet+" "+$values[$jj]; break; } $cmd = "setAttr "+$attrToSet+" "+$values[$valueCount-1]; } } else if ($advanceFlag == "-first" || $advanceFlag == "-f") { $cmd = "setAttr "+$attrToSet+" "+$values[0]; } else if ($advanceFlag == "-last" || $advanceFlag == "-l") { $cmd = "setAttr "+$attrToSet+" "+$values[$valueCount-1]; } evalEcho $cmd; } // // Procedure Name: // advanceToNextDrivenKey // // Description: // Go to the next or previous driven key. // // Advance the driver of $attribute to its next or prior setDrivenKey // position. If $attribute == "", look at the selection list and // use the selected object as $attribute. If $attribute is not // a driven object, the command will give an error message and do // nothing. // // Input Arguments: // $advanceFlag: if true, go to next key, else go to previous key // $attribute: the driven attribute or "" to use selected item // // Return Value: // none // global proc advanceToNextDrivenKey(string $advanceFlag, string $attribute) { if ($attribute == "") { // if no attribute was specified, then try to use the // selection list // string $sel[] = `ls -sl`; if (1 != size($sel)) { error (uiRes("m_advanceToNextDrivenKey.kMustSelect")); return; } $attribute = $sel[0]; } string $errMsg; if ($advanceFlag != "-next" && $advanceFlag != "-n" && $advanceFlag != "-previous" && $advanceFlag != "-p" && $advanceFlag != "-last" && $advanceFlag != "-l" && $advanceFlag != "-first" && $advanceFlag != "-f") { $errMsg = (uiRes("m_advanceToNextDrivenKey.kInvalidFlag")); error(`format -s $advanceFlag $errMsg`); } // find the driver(s) // string $drivers[] = `setDrivenKeyframe -q -dr $attribute`; if ($drivers[0] == "No drivers.") { $errMsg = (uiRes("m_advanceToNextDrivenKey.kNoDriverFound")); error(`format -s $attribute $errMsg`); return; } string $cmd; int $ii; int $driverCount = size($drivers); for ($ii = 0; $ii < $driverCount; $ii++) { string $animCurve = getAnimCurve($drivers[$ii],$attribute); if ("" != $animCurve) { nextDrivenAdvance($advanceFlag,$animCurve); } } }