Monday, July 13, 2009

motion

////////////////////////////////
// //
// cMotionTrail. Cam 2006 //
// //
////////////////////////////////

// overview: creates updating motion trails with spacer objects.

// install: copy script into local scripts folder, source the script ( or restart maya ), type "cMotionTrailUI" to launch the script.

// Arguments: "cMotionTrail" int `start time` , int `end time`, float `spacer scale`, string `object to trail`, int `set template` ( 0 or 1 ).

// Written by Cameron Fielding : cameron.fielding@bvg.com

// Tested with Maya 7.0

// --------------------------------------------------------------------------------------------------------------------------------------------



// proc to create the UI //


global proc cMotionTrailUI()
{

if (`window -exists cMTrailWin`)
deleteUI -window cMTrailWin;

if (`windowPref -exists cMTrailWin`)
windowPref -remove cMTrailWin;

window -t "cMotionTrail" -w 562 -h 350 cMTrailWin;

formLayout cMtopForm;

rowColumnLayout -nc 3 -cw 1 65 -cw 2 150 -cw 3 100 cMrow1;

text -l "Time Range";
radioCollection cMraiod1;

$cMradio1_1 = `radioButton -label "Start/End"`;
$cMradio1_2 = `radioButton -label "Time Slider"`;

radioCollection -e -select $cMradio1_2 cMraiod1;

setParent cMtopForm;

rowColumnLayout -nc 2 -cw 1 55 -cw 2 80 cMrow2;

text -l "Start Time ";
textField -text "1" cMstart;
text -l " End Time ";
textField -text "30" cMend;

setParent cMtopForm;

frameLayout -bs "out" -h 2 cMSep1;

setParent cMtopForm;

floatSliderGrp -pre 2 -label "Spacer display size" -field true -minValue 0.01 -maxValue 10 -v 0.5 cMslide;

checkBox -l " Template the trail's group" -v 0 cMcbox;

colorIndexSliderGrp -label "Trail Colour" -min 0 -max 31 -value 14 -en true cMslide2;

checkBox -l " Use object's own colour for the trail" -v 0 cMcbox2;

checkBox -l " Connect trail to object's visibility" -v 0 cMcbox3;

checkBox -l " Use spheres as spacer objects" -v 1 cMcbox4;

colorIndexSliderGrp -label "Spacer Colour" -min 0 -max 31 -value 17 -en true cMslide3;


rowColumnLayout -nc 3 -cw 1 180 -cw 2 180 -cw 3 180 cMbutrow;

button -l "Create cMotion Trail" -c "getcMPrefs 1" -h 27 ;
button -l "Apply" -c "getcMPrefs 0";
button -l "Close" -c "deleteUI cMTrailWin";

setParent cMtopForm;

formLayout -e

-attachForm cMrow1 "left" 100
-attachForm cMrow1 "top" 3

-attachForm cMrow2 "left" 111
-attachForm cMrow2 "top" 20

-attachForm cMSep1 "left" 0
-attachForm cMSep1 "right" 0
-attachForm cMSep1 "top" 70

-attachForm cMslide "left" 25
-attachForm cMslide "top" 78

-attachForm cMslide2 "left" 25
-attachForm cMslide2 "top" 104
-attachForm cMslide2 "right" 140

-attachForm cMslide3 "left" 25
-attachForm cMslide3 "top" 131

-attachForm cMcbox "left" 164
-attachForm cMcbox "top" 177

-attachForm cMcbox2 "left" 164
-attachForm cMcbox2 "top" 159

-attachForm cMcbox3 "left" 164
-attachForm cMcbox3 "top" 196

-attachForm cMcbox4 "left" 164
-attachForm cMcbox4 "top" 215

-attachForm cMbutrow "left" 5
-attachForm cMbutrow "bottom" 5

cMtopForm;

showWindow;

window -e -h 290 cMTrailWin;

}


// proc to launch the main function with flags from the UI //


global proc getcMPrefs( int $closecMwin )
{

int $startTime, $endTime, $template;
float $scale;
string $trailObjects[];



if ( `radioCollection -q -sl cMraiod1` == "radioButton1" )
{
$startTime = `textField -q -text cMstart`;
$endTime = `textField -q -text cMend`;
}
else
{
$startTime = `playbackOptions -q -min`;
$endTime = `playbackOptions -q -max`;
}

$template = `checkBox -q -v cMcbox`;

$scale = `floatSliderGrp -q -v cMslide`;

$trailObjects = `ls -sl -fl`;


for ( $trailObject in $trailObjects )
{

if ( `objExists ( $trailObject + "_extraNode_t" + $startTime + $endTime )` == 0 )
{
cMotionTrail $startTime $endTime $scale $trailObject $template;
}
else
{
catch ( error ( "a trail already exists for " + $trailObject + " from frames " + $startTime + " to " + $endTime ));
}
}

if ( $closecMwin == 1 )
{
deleteUI cMTrailWin;
}

}

// main trail creating proc //


global proc cMotionTrail ( int $startTime, int $endTime, float $scale, string $trailObject, int $template )
{


// get the name of the object thats going to be trailed, and the trail length //


string $originalName = $trailObject;

int $totalTime = $endTime - $startTime;

$totalTime ++;


// clear the array that will be used to group everything together, and create its index clock that will manage its members //

string $groupArray[];
clear $groupArray;
int $gAClock = 0;


// create the extra node needed ( I'm not sure why this node is needed - but it seems that the `getAttr -t` function needs it to successfully evaluate the
// position of the hiddenTrailObject, when the object being trailed is not a direct child of the world )


group -w -em -n ( $trailObject + "_extraNode_t" + $startTime + $endTime );

pointConstraint -offset 0 0 0 -weight 1 $trailObject ( $trailObject + "_extraNode_t" + $startTime + $endTime );

$groupArray[$gAClock] = ( $trailObject + "_extraNode_t" + $startTime + $endTime );
$gAClock ++;

$trailObject = ( $trailObject + "_extraNode_t" + $startTime + $endTime );


// create the hidden trail object that will be sampled //
// note: this is the actual object that the script uses to generate and alter the shape of the cMotion trail. NOT the object the user selected.


group -w -em -n ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime );

connectAttr ( $originalName + "_extraNode_t" + $startTime + $endTime + ".translateX" ) ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translateX" );
connectAttr ( $originalName + "_extraNode_t" + $startTime + $endTime + ".translateY" ) ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translateY" );
connectAttr ( $originalName + "_extraNode_t" + $startTime + $endTime + ".translateZ" ) ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translateZ" );

$groupArray[$gAClock] = ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime );

$gAClock ++;


// prepare the curve data //


float $tPosX[], $tPosY[], $tPosZ[];

clear $tPosX $tPosY $tPosZ;

int $cMclock = $startTime;

for ( $i = 0; $i < $totalTime; $i ++ )
{
$tPosX[$i] = `getAttr -t $cMclock ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translateX" )`;
$tPosY[$i] = `getAttr -t $cMclock ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translateY" )`;
$tPosZ[$i] = `getAttr -t $cMclock ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translateZ" )`;

$cMclock ++;
}


// create the eval string, and evaluate it to generate the curve //


string $evalMe = "curve -d 1 ";

int $cMclock = $startTime;

for ( $i = 0; $i < `size $tPosX`; $i ++ )
{

$evalMe = ( $evalMe + "-p " + $tPosX[$i] + " " + $tPosY[$i] + " " + $tPosZ[$i] + " " );

}

$evalMe = ( $evalMe + "-n " + $trailObject + "_cMotionTrail_curve" );

eval $evalMe;

$groupArray[$gAClock] = ( $trailObject + "_cMotionTrail_curve" );
$gAClock ++;

// lock the curve so it cant be accidently moved ( only the group as a whole can be user manipulated );

setAttr -lock true ( $trailObject + "_cMotionTrail_curve.tx" );
setAttr -lock true ( $trailObject + "_cMotionTrail_curve.ty" );
setAttr -lock true ( $trailObject + "_cMotionTrail_curve.tz" );

setAttr -lock true ( $trailObject + "_cMotionTrail_curve.rx" );
setAttr -lock true ( $trailObject + "_cMotionTrail_curve.ry" );
setAttr -lock true ( $trailObject + "_cMotionTrail_curve.rz" );

setAttr -lock true ( $trailObject + "_cMotionTrail_curve.sx" );
setAttr -lock true ( $trailObject + "_cMotionTrail_curve.sy" );
setAttr -lock true ( $trailObject + "_cMotionTrail_curve.sz" );

// set the user colours of the curve

setAttr ( $trailObject + "_cMotionTrail_curve.overrideEnabled" ) 1;
setAttr ( $trailObject + "_cMotionTrail_curve.overrideColor" ) ( (`colorIndexSliderGrp -q -value cMslide2`) - 1 );



// if the user chose `use object colour` and object has override enabled - set its colour //

if ( `checkBox -q -v cMcbox2` == 1 || ($originalName + ".overrideEnabled") == 1 )
{
setAttr ( $trailObject + "_cMotionTrail_curve.overrideColor" ) ( `getAttr ( $originalName + ".overrideColor" )`);
}


// rename the curve's shape node for easy access //


string $findShape[];

$findShape = `listRelatives ( $trailObject + "_cMotionTrail_curve" )`;

rename $findShape[0] ( $trailObject + "_cMotionTrailShape" );


// create the eval string to make the scriptjob that will update each CV position on the curve //


string $evalMeExpr = "";

int $cMclock = $startTime;

for ( $i = 0; $i < `size $tPosX `; $i ++ )
{

$evalMeExpr = ( $evalMeExpr + "setAttr \\\"" + $trailObject + "_cMotionTrailShape" + ".controlPoints[" + $i + "].xValue\\\" ( `getAttr -t " + $cMclock + " " + $trailObject + ".tx`);" );
$evalMeExpr = ( $evalMeExpr + "setAttr \\\"" + $trailObject + "_cMotionTrailShape" + ".controlPoints[" + $i + "].yValue\\\" ( `getAttr -t " + $cMclock + " " + $trailObject + ".ty`);" );
$evalMeExpr = ( $evalMeExpr + "setAttr \\\"" + $trailObject + "_cMotionTrailShape" + ".controlPoints[" + $i + "].zValue\\\" ( `getAttr -t " + $cMclock + " " + $trailObject + ".tz`);" );

$cMclock ++;
}


// create the scriptJob to connect the update to a change in the trail null's translate attributes //

// note: for efficiency this scriptjob checks the current frame number and compares it with a previous stored frame number ( from a dynamically generated
// global variable ). The scriptjob will only run if these 2 values are the same ( so the scriptJob will ONLY evaluate when the user physically makes a
// change in the scene, rather than evaluating each time the user scrubs the timeslider, or steps through the timeSlider. )

int $randTag = `rand 999999`;

$evalMeExpr = ( "$cmtsc" + $randTag + "_sJob1 = `scriptJob -kws -cu true -ac \"" + $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translate\" \"" +

"global int $cmtscDG" + $randTag + "_hiddenTrailObject_t" + $startTime + $endTime + "r2; $r1 = `currentTime -q`; if ( $r1 == $cmtscDG" + $randTag + "_hiddenTrailObject_t" + $startTime + $endTime + "r2 ) {" + $evalMeExpr);

$evalMeExpr = ( $evalMeExpr + " print \\\"\\\"; }else{ $cmtscDG" + $randTag + "_hiddenTrailObject_t" + $startTime + $endTime + "r2 = `currentTime -q`; } \"`" );

eval $evalMeExpr;



// create the spacing locators and connect them to each point on the curve //

// note: for efficiency, the spacing locators are connected directly to each CV in the curve, much faster than depending on the scriptJob
// to also update all their positions.


int $cMclock = $startTime;

for ( $i = 0; $i < `size $tPosX `; $i ++ )
{

$tPosX[$i] = `getAttr -t $startTime ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translateX" )`;
$tPosY[$i] = `getAttr -t $startTime ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translateY" )`;
$tPosZ[$i] = `getAttr -t $startTime ( $originalName + "_hiddenTrailObject_t" + $startTime + $endTime + ".translateX" )`;


if ( `checkBox -q -v cMcbox4` == 0 )
{
spaceLocator -n ( $trailObject + "_spacingLocator_" + $i );
}
else
{
sphere -p 0 0 0 -ax 0 1 0 -ssw 0 -esw 360 -r 1 -d 3 -ut 0 -tol 0.01 -s 4 -nsp 2 -ch 1 -n ( $trailObject + "_spacingLocator_" + $i );
setAttr ( $trailObject + "_spacingLocator_" + $i + ".overrideShading" ) 0 ;
}

scale -r $scale $scale $scale;

xform -ws -t $tPosX[$i] $tPosY[$i] $tPosZ[$i];

connectAttr ( $trailObject + "_cMotionTrailShape" + ".controlPoints[" + $i + "].xValue" ) ( $trailObject + "_spacingLocator_" + $i + ".tx" );
connectAttr ( $trailObject + "_cMotionTrailShape" + ".controlPoints[" + $i + "].yValue" ) ( $trailObject + "_spacingLocator_" + $i + ".ty" );
connectAttr ( $trailObject + "_cMotionTrailShape" + ".controlPoints[" + $i + "].zValue" ) ( $trailObject + "_spacingLocator_" + $i + ".tz" );

$groupArray[$gAClock] = ( $trailObject + "_spacingLocator_" + $i );
$gAClock ++;

$cMclock ++;

setAttr ( $trailObject + "_spacingLocator_" + $i + ".overrideEnabled" ) 1;
setAttr ( $trailObject + "_spacingLocator_" + $i + ".overrideColor" ) ( (`colorIndexSliderGrp -q -value cMslide3`) - 1 );
}


// create the final group of everything that was created, and set its user template value //


select -r $groupArray;
group -n ( $originalName + "_cMotionTrail_" + $startTime + "to" + $endTime );

setAttr ( $originalName + "_cMotionTrail_" + $startTime + "to" + $endTime + ".template") $template;
select -cl;

if ( `checkBox -q -v cMcbox3` == 1 )
{
catch ( `connectAttr ( $originalName + ".visibility" ) ( $originalName + "_cMotionTrail_" + $startTime + "to" + $endTime + ".visibility ") `);
}

}

scr

global string $aTan_version = "";
global proc dq_smooth_tan()
{
global string $aTan_version ;

if (`window -q -ex autoTangentWin`)
{
showWindow autoTangentWin ;
return ;
}
float $soft = 0.0 ;
int $bFlatten = 1 ;
if(`optionVar -ex "aTan_softness"`)
$soft = `optionVar -q "aTan_softness"` * 100.0 ;
if(`optionVar -ex "aTan_flatten"`)
$bFlatten = `optionVar -q "aTan_flatten"` ;
window -w 200 -h 125 -s 0 -t ("Smooth Tangent "+$aTan_version) -in "autoTangent" autoTangentWin;
columnLayout -adj true;
separator -style "in" -w 200 -h 5 ;
checkBox -vis 0 -l "Flatten Start/End Keys" -v $bFlatten cbFlatten ;
floatSliderGrp -label "Smooth Value:" -field true -min 0.0 -max 10 -v $soft -adj 3 -cw3 80 40 90 -cc ("aTan_start();") fsgSoft;
button -l ("Apply Selected Keys") -al "center" -w 180 -c ("aTan_start();") btnTan;
separator -style "in" -w 200 -h 5 ;
window -e -wh 210 80 autoTangentWin;
showWindow;
}
global proc aTan_start()
{
float $soft = `floatSliderGrp -q -v fsgSoft` / 100.0 ;
int $bFlatten = `checkBox -q -v cbFlatten` ;
optionVar -fv "aTan_softness" $soft ;
optionVar -iv "aTan_flatten" $bFlatten ;
aTan_smoothKeys($soft, $bFlatten) ;
}
global proc aTan_smoothKeys(float $softness, int $bFlatten)
{
string $curves[] = `keyframe -q -name -sl` ;
string $crv ;
waitCursor -state on ;
for ($crv in $curves)
{
int $idxs[] = `keyframe -q -indexValue -sl $crv` ;
int $idx ;
for ($idx in $idxs)
{
int $total = `keyframe -q -keyframeCount $crv` ;
float $valCs[] = `keyframe -index $idx -q -valueChange $crv` ;
float $timeCs[] = `keyframe -index $idx -q -timeChange $crv` ;

float $valPs[] = $valCs ;
float $valNs[] = $valCs ;
float $timePs[] = $timeCs ;
float $timeNs[] = $timeCs ;
if ($idx > 0)
{
$valPs = `keyframe -index ($idx-1) -q -valueChange $crv` ;
$timePs = `keyframe -index ($idx-1) -q -timeChange $crv` ;
}
if ($idx < $total-1)
{
$valNs = `keyframe -index ($idx+1) -q -valueChange $crv` ;
$timeNs = `keyframe -index ($idx+1) -q -timeChange $crv` ;
}
float $valC = $valCs[0] ;
float $valP = $valPs[0] ;
float $valN = $valNs[0] ;
float $timeC = $timeCs[0] ;
float $timeP = $timePs[0] ;
float $timeN = $timeNs[0] ;
if ($idx == 0 && !$bFlatten)
{
$timeP = $timeC - ($timeN - $timeC) ;
$valP = $valC - ($valN - $valC) ;
}
else if ($idx == ($total-1) && !$bFlatten)
{
$timeN = $timeC + ($timeC - $timeP) ;
$valN = $valC + ($valC - $valP) ;
}
float $valIn = $valC - $valP ;
float $valOut = $valN - $valC ;
float $timeIn = $timeC - $timeP ;
float $timeOut = $timeN - $timeC ;
float $slopeIn = 0 ;
float $slopeOut = 0 ;
if ($timeIn != 0)
$slopeIn = $valIn / $timeIn ;
if ($timeOut != 0)
$slopeOut = $valOut / $timeOut ;
float $powIn = 0.5, $powOut = 0.5;

if ($slopeIn + $slopeOut != 0)
$powIn = 1.0 - ( abs($slopeIn) / ( abs($slopeIn) + abs($slopeOut) ) ) ;
$powOut = 1.0 - $powIn ;
$powIn = ((1.0 - $softness) * $powIn ) + ($softness * 0.5) ;
$powOut = ((1.0 - $softness) * $powOut ) + ($softness * 0.5) ;
float $newSlope = ( $powIn * $slopeIn ) + ( $powOut * $slopeOut ) ;
float $ang = atan( $newSlope ) * 180.0 / 3.14159 ;
keyTangent -itt spline -ott spline -time $timeC $crv ;
keyTangent -ia $ang -oa $ang -time $timeC $crv ;
int $wts[] = `keyTangent -q -wt $crv` ;
if ($wts[0] == 1)
{
float $inWt = abs($timeIn) / 3.0 ;
float $outWt = abs($timeOut) / 3.0 ;
keyTangent -iw $inWt -ow $outWt -time $timeC $crv ;
}
}

}
waitCursor -state off ;
}
dq_smooth_tan;