// =========================================================================== // 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. // =========================================================================== // Compute the sum of elements in the integer array input argument proc int sum( int $vals[] ) { int $retval = 0; for ( $v in $vals ) $retval += $v; return $retval; } // Determine if a keys exist on the named character node attribute. Return a boolean // for each member of atts indicating whether or not keys exist for that attr. // proc int[] hasKeys( string $channel, string $attrs[] ) { int $exists[] = {}; for ( $a in $attrs ) { int $val = false; string $name = ($channel + $a); if (objExists($name) == false) $val = true; else { string $conns[] = `listConnections $name`; for ( $c in $conns ) if ( isAnimCurve( $c ) && `keyframe -q -keyframeCount $c` > 0 ) { $val = true; break; } } $exists[ size($exists) ] = $val; } return $exists; } // Description // Given a string representing a node in the scene, return its namespace prefix // // Examples // // getNamespacePrefix( "namespace:node" ); // // Result: namespace: // // // getNamespacePrefix( "namespace1:namespace2:node" ); // // Result: namespace1:namespace2: // // // size( getNamespacePrefix( "node" ) ); // // Result: 0 // // // size( getNamespacePrefix( "" ) ); // // Result: 0 // // proc string getNamespacePrefix( string $node ) { if ( size( $node ) > 0 ) { string $buf[]; int $n = tokenize( $node, ":", $buf ); if ( $n > 0 ) { $buf[ $n-1 ] = ""; return stringArrayToString( $buf, ":" ); } } return ""; } // Key the translation and rotation attributes of the offset object at the first frame of // the named clip only if no animCurves exist on the named attribute. // global proc keyClip( string $character, string $offset, string $clip ) { string $channel = ( $character + "." + $offset + "_" ); // Determine if keys exists on translation channels. int $keys[]; // Active the clip keys doActivateClipArgList 2 { "1", "1", $clip }; // Determine if keys exists on translation channels. $keys = hasKeys( $channel, { "translateX", "translateY", "translateZ" } ); int $keyTranslate = ( sum( $keys ) != 3 ) ? true : false ; // Determine if keys exists on rotation channels. $keys = hasKeys( $channel, { "rotateX", "rotateY", "rotateZ" } ); int $keyRotate = ( sum( $keys ) != 3 ) ? true : false ; // If either the translate or rotate channels need to be keyed ... if ( $keyTranslate || $keyRotate ) { // ... set the time to the clipSource start int $start = `getAttr ( $clip + ".sourceStart" )`; currentTime $start; // ... key appropriate channels if ( $keyTranslate ) setKeyframe -time $start -breakdown 0 -hierarchy none -controlPoints 0 -shape 0 ( $offset + ".translate" ); if ( $keyRotate ) setKeyframe -time $start -breakdown 0 -hierarchy none -controlPoints 0 -shape 0 ( $offset + ".rotate" ); } // Finally, deactivate the clips keys doActivateClipArgList 2 { "0", "1", $clip }; } // Check that all clips in the sequence meet preconditions for ghosting, offsetting, and clip matching. // If the clips do not meet needed preconditions, ask the user what to do and proceed accordingly. global proc int verifyClipsAreValid( string $character, string $offset ) { // Get the name of the scheduler for the current character. string $sched = `character -q -scheduler $character`; // If no scheduler exists, bail if ( size( $sched ) == 0 ) return true; // Get a list of all clips in the scene. string $clips[] = `clipSchedule -q -name $sched`; // If there are no clips, return true (i.e., consider the null set to be valid) if ( size( $clips ) == 0 ) return true; // Strip off the namespace prefix from the offset object { string $ncharacter = getNamespacePrefix( $character ); string $noffset = getNamespacePrefix( $offset ); if ( $ncharacter != $noffset ) { warning( (uiRes("m_verifyClipsAreValid.kNamespaceError")) ); return false; } $offset = stringRemovePrefix( $offset, $noffset ); } // Ensure that all clips are set to absolute int $notAbs[] = {}; for ( $c in $clips ) if ( getClipAbsState( $c ) != 1 ) $notAbs[ size($notAbs) ] = getClipIndex( $c, $sched ); // If some clips are relative if ( size( $notAbs ) ) { // Ask the user if we should convert clips string $yes = (uiRes("m_verifyClipsAreValid.kYes")); string $no = (uiRes("m_verifyClipsAreValid.kNo")); string $title = (uiRes("m_verifyClipsAreValid.kConvert")); string $prompt = (uiRes("m_verifyClipsAreValid.kPrompt")); string $msg = `format -s $no $prompt`; string $ans = `confirmDialog -title $title -message $msg -button $yes -button $no -defaultButton $yes -cancelButton $no -dismissString $no`; // If the user does not wish to proceed with the conversion, bail if ( $ans == $no ) return false; // Otherwise, set all clips to absolute clipSchedule -e -allAbsolute $sched; for ( $i in $notAbs ) clipSchedule -clipIndex $i -allAbsolute $sched; } // Lastly, ensure that the offset object is keyed in all clips for ( $clip in $clips ) keyClip $character $offset $clip; return true; }