// =========================================================================== // 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. // =========================================================================== // // Procedure Name: // validateClips // // Description: // Verifies that at least two clips are present and that all // of them share the same scheduler. // // Input Arguments: // clips - Clips to validate. // proc validateClips( string $clips[] ) { // Verify that we have at least two clips. // if ( size( $clips ) < 2 ) { error( (uiRes("m_doMatchClip.kMinClipsSelErr")) ); } // Verify that clips are connected to the same scheduler. // string $scheduler = getClipScheduler( $clips[ 0 ] ); for ( $i = 1; $i < size( $clips ); $i++ ) { string $tmp = getClipScheduler( $clips[ $i ] ); if ( $tmp == "" || $tmp != $scheduler ) { error( (uiRes("m_doMatchClip.kInvalidScheduler")) ); } } } // // Procedure Name: // getClipStartTime // // Description: // Fetches the start time of clips // // Input Arguments: // clips - Clips. // // Return Value: // Start time of clips. // proc float[] getClipStartTime( string $clips[] ) { float $time[]; for ( $clip in $clips ) { float $srcStart = `getAttr ( $clip + ".sourceStart" )`; float $srcEnd = `getAttr ( $clip + ".sourceEnd" )`; float $startFrame = `getAttr ( $clip + ".startFrame" )`; float $scale = `getAttr ( $clip + ".scale" )`; float $preCycle = `getAttr ( $clip + ".preCycle" )`; float $duration = $scale * ( $srcEnd - $srcStart ); $time[ size( $time ) ] = $startFrame - $preCycle * $duration; } return $time; } // // Procedure Name: // sortClipsByTime // // Description: // Sorts an array of clips based on their start time. // // NOTE: This function could be improve by creating a more // flexible sort command. // // Input Arguments: // clips - Clips to sort. // // Return Value: // Sorted clips // proc string[] sortClipsByTime( string $clips[] ) { int $count = size( $clips ); // Bail if no sorting is necessary. // if ( $count < 2 ) return $clips; // Compute time range. // float $time[] = getClipStartTime( $clips ); float $max = $time[ 0 ]; float $min = $time[ 0 ]; for ( $i = 1; $i < $count; $i++ ) { $max = max( $max, $time[ $i ] ); $min = min( $min, $time[ $i ] ); } float $range = $max - $min; // If time range is null this means all clips are starting at // at the same time. No sorting is necessary. // if ( $range == 0.0 ) return $clips; // Remap clip start time between 0 and 1 and create string tokens for sorting. // string $buffer[]; string $sortedClips[]; for ( $i = 0; $i < $count; $i++ ) { string $remap = ( $time[ $i ] - $min ) / $range; tokenize( $remap, ".", $buffer ); // Pad zeros after decimal point in order to sort correctly. // if ( size( $buffer ) > 1 ) { int $padding = 10 - size( $buffer[ 1 ] ); for ( $j = 0; $j < $padding; $j++ ) $remap += "0"; } else $remap += ".0000000000"; $sortedClips[ $i ] = ( $remap + "=" + $clips[ $i ] ); } $sortedClips = sort( $sortedClips ); for ( $i = 0; $i < $count; $i++ ) { // Tokenize to isolate sorted clip name. // tokenize( $sortedClips[ $i ], "=", $buffer ); $sortedClips[ $i ] = $buffer[ 1 ]; } return $sortedClips; } // // Procedure Name: // doMatchClip // // Description: // Calls clip matching command after validating selected clips and // character node. // // Input Arguments: // // matchT - Match translation type (see matchClip command) // // matchR - Match rotation type (see matchClip command) // // matchNode - Match node name. // If not specified the match node connected to the character // is used. // // Return Value: // None. // global proc doMatchClip( int $matchT, int $matchR, string $matchNode ) { string $clips[] = getSelectedClips( "noOptions" ); validateClips( $clips ); // Sort clips by start time. // $clips = sortClipsByTime( $clips ); // Get the character associated with these clips. // string $character = getClipCharacter( $clips[ 0 ] ); if ( $character == "" ) { error ( (uiRes("m_doMatchClip.kNoCharacterConnectedErr")) ); } // Get the match node from the character if none is specified. // if ( $matchNode == "" ) { string $matchNodes[] = `listConnections -s 1 -d 0 -p 0 ( $character + ".matchNode" )`; if ( size( $matchNodes ) == 0 ) { string $msg = (uiRes("m_doMatchClip.kNoMatchNodeForCharacterErr")); error( $msg + " " + $character ); } $matchNode = $matchNodes[ 0 ]; } for ( $i = 1; $i < size( $clips ); $i++ ) { clipMatching -matchTranslation $matchT -matchRotation $matchR -clipSrc $clips[ $i ] 0.0 -clipDst $clips[ $i - 1 ] 1.0 $character $matchNode; } }