/*
makeJointsDynamic.mel v1.1
Author: Nate Lang
web: natelang3d.com
Install: Copy this file into your maya scripts folder
------Copy below code into a mel shelf button------
makeJointsDynamic();
------------------------------------------------------
Use:
Select all joints you wish to start a dynamic chain at and run script.
Script will make multiple joint chains at the same time.
Runs down enitre joint chain till reaches the end joint.
*/
proc groupNodes(string $follicle, string $ik, string $dynamicCurve)
{
//cleanup + orgaize created nodes
string $grpNum = `match "[0-9]+$" $follicle`;
group -name ("dynamicJoint_grp" + $grpNum);
parent $follicle ("dynamicJoint_grp" + $grpNum);
parent ("hairSystem" + $grpNum) ("dynamicJoint_grp" + $grpNum);
parent $dynamicCurve ("dynamicJoint_grp" + $grpNum);
delete ("hairSystem" + $grpNum + "OutputCurves");
delete ("hairSystem" + $grpNum + "Follicles");
}
proc string setPointLock(string $staticCurveName)
{
select $staticCurveName;
string $pickWalkCatcher[] = `pickWalk -direction up`;
string $follicleName = $pickWalkCatcher[0];
setAttr ($follicleName + ".pointLock") 1;
//return name of the follicle
return $follicleName;
}
proc string makeDynamicIK(string $top, string $end, string $curve)
{
//need top joint, bottom joint, and dynamic curve
select -r $top;
select -add $end;
select -add $curve;
string $ikName[] = `ikHandle -sol ikSplineSolver -ccv false`;
//return name of the ik
return $ikName[0];
}
proc string[] getJntChain(string $startJnt)
{
string $jntChain[];
string $currentName = $startJnt;
string $prevName = "temp";
int $jntCounter = 0;
//start at top of chain and add each joint name to a new array
while ($currentName != $prevName)
{
select $currentName;
stringArrayInsertAtIndex($jntCounter, $jntChain, $currentName);
$prevName = $currentName;
string $pickWalkCatcher[] = `pickWalk -direction down`;
$currentName = $pickWalkCatcher[0];
$jntCounter++;
}
//return array of all names in joint chain
return $jntChain;
}
proc string getLastJoint(string $startJnt)
{
string $currentName = $startJnt;
string $prevName = "temp";
int $jntCounter = 0;
//start at top of chain and add each joint name to a new array
while ($currentName != $prevName)
{
$prevName = $currentName;
string $pickWalkCatcher[] = `pickWalk -direction down`;
$currentName = $pickWalkCatcher[0];
$jntCounter++;
}
//return string with last name
return $currentName;
}
proc string makeCurve(string $jntChainTemp[])
{
float $locX[];
float $locY[];
float $locZ[];
int $index = 0;
//populate $locX[], $locY[], and $locZ[] with coordinates of each joint in selection
for ($jnt in $jntChainTemp)
{
float $jntWorldLocation[] = `xform -q -ws -translation $jnt`;
//get coordinates out of worldLocation array
float $xVal = $jntWorldLocation[0];
float $yVal = $jntWorldLocation[1];
float $zVal = $jntWorldLocation[2];
//populate new arrays with coordinates for each joint
floatArrayInsertAtIndex($index, $locX, $xVal);
floatArrayInsertAtIndex($index, $locY, $yVal);
floatArrayInsertAtIndex($index, $locZ, $zVal);
$index++;
}
//create curve and rebuild with correct # of spans
string $curveToDelete = `curve -degree 1 -point 0 0 0 -point 0 5 0 -point 0 10 0`;
string $newCurveName[] = `rebuildCurve -degree 3 -ch off -replaceOriginal false -spans ($index-3) -name ("jntCurve#") $curveToDelete`;
//move points into correct x,y,z coordinates taken from populated arrays
for ($i=0; $i<=$index; $i++)
{
setAttr ($newCurveName[0] + "Shape" + ".controlPoints[" + $i + "].xValue") $locX[$i];
setAttr ($newCurveName[0] + "Shape" + ".controlPoints[" + $i + "].yValue") $locY[$i];
setAttr ($newCurveName[0] + "Shape" + ".controlPoints[" + $i + "].zValue") $locZ[$i];
}
delete $curveToDelete;
return ($newCurveName[0]);
}
global proc makeJointsDynamic()
{
if(`objExists curve1`)
{
//maya script 'makeCurvesDynamic' needs to generate object named curve1
print "--------------------------------------------\n";
print "Cannot proceed object curve1 already exists\n";
print "Please rename object curve1 and try again\n";
print "--------------------------------------------\n";
}
else
{
string $topJoints[] = `ls -selection`;
for ($topJnt in $topJoints)
{
//get all joints in each chain
string $jntChain[] = getJntChain($topJnt);
//get end joint name
string $endJnt = getLastJoint($topJnt);
//make a curve starting at top of chain
string $newCurveName = makeCurve($jntChain);
select $newCurveName;
//make curve dynamic
makeCurvesDynamic 2 { "0", "0", "1", "1", "0"};
//rename new dynamic curve1
rename curve1 ($newCurveName + "_dynamic");
//set pointlock to the base of curve
string $follicleName = setPointLock($newCurveName);
//make ik spline. need first joint, last joint, and dynamic curve
string $ikHandle = makeDynamicIK(($jntChain[0]),$endJnt,($newCurveName + "_dynamic"));
//group and clean up all created nodes
groupNodes($follicleName, $ikHandle, ($newCurveName + "_dynamic"));
}
}
}