//James Parks //08-14-2004 //jpStretchIK.mel //*****REQUIREMENTS:***** //To make an IK chain stretchy you need to have a 2 bone IK chain //(well, any number of bones will work, but only the "Shoulder" //and the "Elbow" will be scaled, as is. You can manually connect //however many you want to) with some sort of controller at the //exact same position as the wrist. //*****TO USE:***** //Source this script //load the fields in the GUI with your existing IK chain // the wrist controller into the "Controller" spot // the bicep/upperArm joint into the "Shoulder" spot // the elbow/foreArm joint into the "Elbow" spot // the wrist joint into the "Wrist" spot //choose a maximum amount of stretch // Don't worry too much as this can be changed later // but I think 10 is a good max //choose which joint axes to stretch // choose the length axis of your joints, hopefully it'll be // the same on each joint and be oriented pointing straight // down the joint or just let all of them scale if you prefer //Hit the "Stretch" button //*****METHOD:***** //Then 3 attributes will be added to the controller // 1) Auto Stretchy -- an 0/1 integer that controls turns automatic stretchiness on or off // 2) Manual Stretchy -- a float value that lets you choose the stretch when Auto Stretchy is off // 3) Max Stretchy -- a float value that sets the maximum stretch amount //Then builds the network of nodes and connections that let the arm stretch // measures the original distance of the arm multiplied by the scale of the main controller. // sets up a distanceDimension node to measure the distance between the shoulder and the controller // divides the current distance by the original distance // multiplies the scale of the joints by that value //*****TO DO:***** //1) Maybe set up some sort of interactive switches for which axes to scale //2) Handle chains with many joints, including obscure forearm rigs //3) error checking global float $jpStretchVerNum = 1.31; global proc jpStretchIK() { global float $jpStretchVerNum; string $winName = "stretchIKWin"; if (`window -exists $winName`) deleteUI $winName; window -t ("Stretch IK v" + $jpStretchVerNum + " -- James Parks") -w 265 -h 285 -rtf 1 -mnb 1 -mxb 1 -menuBar 0 $winName; string $stretchForm = `formLayout -numberOfDivisions 100 stretchForm`; string $stretchTabs = `tabLayout -scr 1 -innerMarginWidth 5 -innerMarginHeight 5 stretchTabs`; setParent $stretchTabs; string $singleTab = `columnLayout singleColumn`; rowColumnLayout -nc 2 -cw 1 110 -cw 2 125; text -fn "boldLabelFont" -l " Controls"; text -l ""; button -l "Main Scale Control -->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` singleMainScaleGrp"); textFieldGrp -cal 1 "left" -cw 1 125 singleMainScaleGrp; button -l "End Controller ---->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` singleControllerGrp"); textFieldGrp -cal 1 "left" -cw 1 125 singleControllerGrp; text -fn "boldLabelFont" -l " Joints"; text -l ""; button -l "Root Joint --------->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` singleRootJointGrp"); textFieldButtonGrp -cal 1 "left" -cw 1 125 singleRootJointGrp; button -l "End Joint ----------->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` singleEndJointGrp"); textFieldGrp -cal 1 "left" -cw 1 125 singleEndJointGrp; setParent ..; floatFieldGrp -l "Max Stretch" -cal 1 "left" -cal 2 "left" -cw 1 75 -cw 2 50 -v1 10 -pre 1 singleMaxStretchGrp; checkBoxGrp -w 200 -h 15 -ncb 3 -label "Stretch Axes" -cal 1 "left" -l1 "X" -l2 "Y" -l3 "Z" -v1 1 -v2 1 -v3 1 -cw 1 75 -cw 2 33 -cw 3 33 -cw 4 33 singleStretchAxes; text -l ""; setParent $stretchTabs; string $ikTab = `columnLayout ikColumn`; rowColumnLayout -nc 2 -cw 1 110 -cw 2 125; text -fn "boldLabelFont" -l " Controls"; text -l ""; button -l "Main Scale Control -->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` mainScaleGrp"); textFieldGrp -cal 1 "left" -cw 1 125 mainScaleGrp; button -l "Wrist Controller ---->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` controllerGrp"); textFieldGrp -cal 1 "left" -cw 1 125 controllerGrp; text -fn "boldLabelFont" -l " Joints"; text -l ""; button -l "Shoulder ---------->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` shoulderGrp"); textFieldButtonGrp -cal 1 "left" -cw 1 125 shoulderGrp; button -l "Elbow -------------->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` elbowGrp"); textFieldGrp -cal 1 "left" -cw 1 125 elbowGrp; button -l "Wrist --------------->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` wristGrp"); textFieldGrp -cal 1 "left" -cw 1 125 wristGrp; setParent ..; floatFieldGrp -l "Max Stretch" -cal 1 "left" -cal 2 "left" -cw 1 75 -cw 2 50 -v1 10 -pre 1 maxStretchGrp; checkBoxGrp -w 200 -h 15 -ncb 3 -label "Stretch Axes" -cal 1 "left" -l1 "X" -l2 "Y" -l3 "Z" -v1 1 -v2 1 -v3 1 -cw 1 75 -cw 2 33 -cw 3 33 -cw 4 33 stretchAxes; text -l ""; setParent $stretchTabs; string $splineTab = `columnLayout stretchColumn`; rowColumnLayout -nc 2 -cw 1 110 -cw 2 125; text -fn "boldLabelFont" -l " Controls"; text -l ""; button -l "Main Scale Control -->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` splineMainScaleGrp"); textFieldGrp -cal 1 "left" -cw 1 125 splineMainScaleGrp; button -l "Spline Curve ----------->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` splineCurveGrp"); textFieldGrp -cal 1 "left" -cw 1 125 splineCurveGrp; text -fn "boldLabelFont" -l " Joints"; text -l ""; button -l "First Joint --------------->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` splineFirstJointGrp"); textFieldButtonGrp -cal 1 "left" -cw 1 125 splineFirstJointGrp; button -l "Last Joint --------------->" -width 110 -c ("textFieldGrp -e -tx `ls -sl` splineLastJointGrp"); textFieldGrp -cal 1 "left" -cw 1 125 splineLastJointGrp; setParent ..; floatFieldGrp -l "Max Stretch" -cal 1 "left" -cal 2 "left" -cw 1 75 -cw 2 50 -v1 10 -pre 1 splineMaxStretchGrp; checkBoxGrp -w 200 -h 15 -ncb 3 -label "Stretch Axes" -cal 1 "left" -l1 "X" -l2 "Y" -l3 "Z" -v1 1 -v2 1 -v3 1 -cw 1 75 -cw 2 33 -cw 3 33 -cw 4 33 splineStretchAxes; text -l ""; setParent $stretchForm; string $buttonsLayout = `rowColumnLayout -nc 2 -cw 1 130 -cw 2 130 buttonsLayout`; button -l "Stretch" -c ("jpDecideStretch(`tabLayout -q -sti stretchTabs`)"); button -l "Close" -c ("deleteUI " + $winName); tabLayout -edit -sti 2 -tabLabel $singleTab "Single Bone IK" -tabLabel $ikTab "Two Bone IK" -tabLabel $splineTab "Spline IK" $stretchTabs; formLayout -edit -attachForm $stretchTabs "top" 0 -attachForm $stretchTabs "left" 0 -attachForm $stretchTabs "bottom" 25 -attachForm $stretchTabs "right" 0 //-attachForm $buttonsLayout "top" 0 -attachForm $buttonsLayout "left" 0 -attachForm $buttonsLayout "bottom" 0 -attachForm $buttonsLayout "right" 0 $stretchForm ; //window -e -wh 245 245 $winName; showWindow $winName; }//end proc jpStretchIK global proc jpDecideStretch(int $type) { switch ($type) { case 1: //print "Still have to get this one working"; jpSingleStretch(`textFieldGrp -q -tx singleMainScaleGrp`, `textFieldGrp -q -tx singleControllerGrp`, `textFieldGrp -q -tx singleRootJointGrp`, `textFieldGrp -q -tx singleEndJointGrp`, `floatFieldGrp -q -v1 singleMaxStretchGrp`, `checkBoxGrp -q -v1 singleStretchAxes`, `checkBoxGrp -q -v2 singleStretchAxes`, `checkBoxGrp -q -v3 singleStretchAxes`); break; case 2: jpIKstretch(`textFieldGrp -q -tx mainScaleGrp`, `textFieldGrp -q -tx controllerGrp`, `textFieldGrp -q -tx shoulderGrp`, `textFieldGrp -q -tx elbowGrp`, `textFieldGrp -q -tx wristGrp`, `floatFieldGrp -q -v1 maxStretchGrp`, `checkBoxGrp -q -v1 stretchAxes`, `checkBoxGrp -q -v2 stretchAxes`, `checkBoxGrp -q -v3 stretchAxes`); break; case 3: jpSplineStretch(`textFieldGrp -q -tx splineMainScaleGrp`, `textFieldGrp -q -tx splineCurveGrp`, `textFieldGrp -q -tx splineFirstJointGrp`, `textFieldGrp -q -tx splineLastJointGrp`, `floatFieldGrp -q -v1 splineMaxStretchGrp`, `checkBoxGrp -q -v1 splineStretchAxes`, `checkBoxGrp -q -v2 splineStretchAxes`, `checkBoxGrp -q -v3 splineStretchAxes`); break; default: error "Something's F'd Up: jpDecideStretch"; break; }//end switch }//end proc jpDecideStretch global proc jpSingleStretch(string $mainControl, string $control, string $rootJoint, string $endJoint, float $maxStretch, int $x, int $y, int $z) { //prep the control to receive stretcy-ness select -cl; select $control; addAttr -ln autoStretchy -at long -min 0 -max 1 -dv 1 $control; setAttr -e -keyable true ($control + ".autoStretchy"); addAttr -ln manualStretchy -at "float" -min 1 -dv 1 $control; setAttr -e -keyable true ($control + ".manualStretchy"); addAttr -ln maxStretchy -at long -min 1 -dv $maxStretch $control; setAttr -e -keyable true ($control + ".maxStretchy"); float $rootTra[] = `xform -q -ws -t $rootJoint`; float $endTra[] = `xform -q -ws -t $endJoint`; //find the initial distance string $jointDistanceNode = `distanceDimension -sp $rootTra[0] $rootTra[1] $rootTra[2] -ep $endTra[0] $endTra[1] $endTra[2]`; float $initialDistance = `getAttr ($jointDistanceNode + ".distance")`; string $jointDistNodeEndLocShape = `connectionInfo -sfd ($jointDistanceNode + ".endPoint")`; string $jointDistNodeEndLocShape_Tok[]; tokenize $jointDistNodeEndLocShape "." $jointDistNodeEndLocShape_Tok; select $jointDistNodeEndLocShape_Tok[0]; string $endLoc[] = `pickWalk -d up`; ///////////////////////// //Do that stretchy thing -- make the stretchy nodes ///////////////////////// // make the dimension node and find out the names of the locators it made string $curDistNode = `distanceDimension -sp $rootTra[0] $rootTra[1] $rootTra[2] -ep $endTra[0] $endTra[1] $endTra[2]`; string $curDistStartLocShape = `connectionInfo -sfd ($curDistNode + ".startPoint")`; string $curDistEndLocShape = `connectionInfo -sfd ($curDistNode + ".endPoint")`; // because the connection info returns the shape node rather than the transform // we have to go through all this shite in order to find out the names of the // locators that the distance dimension node makes. Highly annoying. string $curDistStartLocShape_Tok[]; tokenize $curDistStartLocShape "." $curDistStartLocShape_Tok; string $curDistEndLocShape_Tok[]; tokenize $curDistEndLocShape "." $curDistEndLocShape_Tok; select $curDistStartLocShape_Tok[0]; string $startLoc[] = `pickWalk -d up`; select $curDistEndLocShape_Tok[0]; string $endLoc[] = `pickWalk -d up`; parent $startLoc[0] $rootJoint; parent $endLoc[0] $control; //make the utility nodes and connections // multiply initial distance by current scale string $mainScaleNode = `shadingNode -asUtility multiplyDivide -n ($mainControl + "_MD")`; setAttr ($mainScaleNode + ".input1X") $initialDistance; setAttr ($mainScaleNode + ".input1Y") $initialDistance; setAttr ($mainScaleNode + ".input1Z") $initialDistance; connectAttr ($mainControl + ".scaleX") ($mainScaleNode + ".input2X"); connectAttr ($mainControl + ".scaleY") ($mainScaleNode + ".input2Y"); connectAttr ($mainControl + ".scaleZ") ($mainScaleNode + ".input2Z"); // divide current distance by initial distance string $scaleNode = `shadingNode -asUtility multiplyDivide -n ($control + "_MD")`; setAttr ($scaleNode + ".operation") 2; connectAttr ($mainScaleNode + ".outputX") ($scaleNode + ".input2X"); connectAttr ($mainScaleNode + ".outputY") ($scaleNode + ".input2Y"); connectAttr ($mainScaleNode + ".outputZ") ($scaleNode + ".input2Z"); connectAttr ($curDistNode + ".distance") ($scaleNode + ".input1X"); connectAttr ($curDistNode + ".distance") ($scaleNode + ".input1Y"); connectAttr ($curDistNode + ".distance") ($scaleNode + ".input1Z"); // auto/manual stretch condition string $autoStretchConditionNode = `shadingNode -asUtility condition -n ($control + "_autoStretchCon")`; connectAttr ($control + ".autoStretchy") ($autoStretchConditionNode + ".firstTerm"); setAttr ($autoStretchConditionNode + ".secondTerm") .5; setAttr ($autoStretchConditionNode + ".operation") 2; connectAttr ($scaleNode + ".outputX") ($autoStretchConditionNode + ".colorIfTrueR"); connectAttr ($scaleNode + ".outputY") ($autoStretchConditionNode + ".colorIfTrueG"); connectAttr ($scaleNode + ".outputZ") ($autoStretchConditionNode + ".colorIfTrueB"); connectAttr ($control + ".manualStretchy") ($autoStretchConditionNode + ".colorIfFalseR"); connectAttr ($control + ".manualStretchy") ($autoStretchConditionNode + ".colorIfFalseG"); connectAttr ($control + ".manualStretchy") ($autoStretchConditionNode + ".colorIfFalseB"); // clamp scale between 1 and maxStretch string $clampNode = `shadingNode -asUtility clamp -n ($control + "_clamp")`; setAttr ($clampNode + ".minR") 1; setAttr ($clampNode + ".minG") 1; setAttr ($clampNode + ".minB") 1; connectAttr ($control + ".maxStretchy") ($clampNode + ".maxR"); connectAttr ($control + ".maxStretchy") ($clampNode + ".maxG"); connectAttr ($control + ".maxStretchy") ($clampNode + ".maxB"); connectAttr ($autoStretchConditionNode + ".outColor") ($clampNode + ".input"); // connect to the joints scale if($x == 1) { connectAttr ($clampNode + ".outputR") ($rootJoint + ".scaleX"); }//end if:X if($y == 1) { connectAttr ($clampNode + ".outputG") ($rootJoint + ".scaleY"); }//end if:Y if($z == 1) { connectAttr ($clampNode + ".outputB") ($rootJoint + ".scaleZ"); }//end if:Z //cleanup select $jointDistanceNode; pickWalk -d up; delete; //delete $endLoc[0]; }//end proc jpSingleStretch /////////////////////////////// //make the stretchy 2-bone IK network /////////////////////////////// global proc jpIKstretch(string $mainControl, string $control, string $shoulder, string $elbow, string $wrist, float $maxStretch, int $x, int $y, int $z) { //prep the control to receive stretcy-ness select -cl; select $control; addAttr -ln autoStretchy -at long -min 0 -max 1 -dv 1 $control; setAttr -e -keyable true ($control + ".autoStretchy"); addAttr -ln manualStretchy -at "float" -min 1 -dv 1 $control; setAttr -e -keyable true ($control + ".manualStretchy"); addAttr -ln maxStretchy -at long -min 1 -dv $maxStretch $control; setAttr -e -keyable true ($control + ".maxStretchy"); //find the initial distance of the arm float $bicepTra[] = `xform -q -ws -t $shoulder`; float $elbowTra[] = `xform -q -ws -t $elbow`; float $wristTra[] = `xform -q -ws -t $wrist`; string $bicepDistanceNode = `distanceDimension -sp $bicepTra[0] $bicepTra[1] $bicepTra[2] -ep $elbowTra[0] $elbowTra[1] $elbowTra[2]`; string $forearmDistanceNode = `distanceDimension -sp $elbowTra[0] $elbowTra[1] $elbowTra[2] -ep $wristTra[0] $wristTra[1] $wristTra[2]`; float $initialDistance = (`getAttr ($bicepDistanceNode + ".distance")`) + (`getAttr ($forearmDistanceNode + ".distance")`); string $bicepDistNodeEndLocShape = `connectionInfo -sfd ($bicepDistanceNode + ".endPoint")`; string $bicepDistNodeEndLocShape_Tok[]; tokenize $bicepDistNodeEndLocShape "." $bicepDistNodeEndLocShape_Tok; select $bicepDistNodeEndLocShape_Tok[0]; string $elbowLoc[] = `pickWalk -d up`; ///////////////////////// //Do that stretchy thing -- make the stretchy nodes ///////////////////////// // make the dimension node and find out the names of the locators it made string $curDistNode = `distanceDimension -sp $bicepTra[0] $bicepTra[1] $bicepTra[2] -ep $wristTra[0] $wristTra[1] $wristTra[2]`; string $curDistStartLocShape = `connectionInfo -sfd ($curDistNode + ".startPoint")`; string $curDistEndLocShape = `connectionInfo -sfd ($curDistNode + ".endPoint")`; // because the connection info returns the shape node rather than the transform // we have to go through all this shite in order to find out the names of the // locators that the distance dimension node makes. Highly annoying. string $curDistStartLocShape_Tok[]; tokenize $curDistStartLocShape "." $curDistStartLocShape_Tok; string $curDistEndLocShape_Tok[]; tokenize $curDistEndLocShape "." $curDistEndLocShape_Tok; select $curDistStartLocShape_Tok[0]; string $startLoc[] = `pickWalk -d up`; select $curDistEndLocShape_Tok[0]; string $endLoc[] = `pickWalk -d up`; catchQuiet(`parent $startLoc[0] $shoulder`); catchQuiet(`parent $endLoc[0] $control`); //make the utility nodes and connections // multiply initial distance by current scale string $mainScaleNode = `shadingNode -asUtility multiplyDivide -n ($mainControl + "_MD")`; setAttr ($mainScaleNode + ".input1X") $initialDistance; setAttr ($mainScaleNode + ".input1Y") $initialDistance; setAttr ($mainScaleNode + ".input1Z") $initialDistance; connectAttr ($mainControl + ".scaleX") ($mainScaleNode + ".input2X"); connectAttr ($mainControl + ".scaleY") ($mainScaleNode + ".input2Y"); connectAttr ($mainControl + ".scaleZ") ($mainScaleNode + ".input2Z"); // divide current distance by initial distance string $scaleNode = `shadingNode -asUtility multiplyDivide -n ($control + "_MD")`; setAttr ($scaleNode + ".operation") 2; connectAttr ($mainScaleNode + ".outputX") ($scaleNode + ".input2X"); connectAttr ($mainScaleNode + ".outputY") ($scaleNode + ".input2Y"); connectAttr ($mainScaleNode + ".outputZ") ($scaleNode + ".input2Z"); connectAttr ($curDistNode + ".distance") ($scaleNode + ".input1X"); connectAttr ($curDistNode + ".distance") ($scaleNode + ".input1Y"); connectAttr ($curDistNode + ".distance") ($scaleNode + ".input1Z"); // auto/manual stretch condition string $autoStretchConditionNode = `shadingNode -asUtility condition -n ($control + "_autoStretchCon")`; connectAttr ($control + ".autoStretchy") ($autoStretchConditionNode + ".firstTerm"); setAttr ($autoStretchConditionNode + ".secondTerm") .5; setAttr ($autoStretchConditionNode + ".operation") 2; connectAttr ($scaleNode + ".outputX") ($autoStretchConditionNode + ".colorIfTrueR"); connectAttr ($scaleNode + ".outputY") ($autoStretchConditionNode + ".colorIfTrueG"); connectAttr ($scaleNode + ".outputZ") ($autoStretchConditionNode + ".colorIfTrueB"); connectAttr ($control + ".manualStretchy") ($autoStretchConditionNode + ".colorIfFalseR"); connectAttr ($control + ".manualStretchy") ($autoStretchConditionNode + ".colorIfFalseG"); connectAttr ($control + ".manualStretchy") ($autoStretchConditionNode + ".colorIfFalseB"); // clamp scale between 1 and maxStretch string $clampNode = `shadingNode -asUtility clamp -n ($control + "_clamp")`; setAttr ($clampNode + ".minR") 1; setAttr ($clampNode + ".minG") 1; setAttr ($clampNode + ".minB") 1; connectAttr ($control + ".maxStretchy") ($clampNode + ".maxR"); connectAttr ($control + ".maxStretchy") ($clampNode + ".maxG"); connectAttr ($control + ".maxStretchy") ($clampNode + ".maxB"); connectAttr ($autoStretchConditionNode + ".outColor") ($clampNode + ".input"); // connect to the joints scale if($x == 1) { connectAttr ($clampNode + ".outputR") ($shoulder + ".scaleX"); connectAttr ($clampNode + ".outputR") ($elbow + ".scaleX"); }//end if:X if($y == 1) { connectAttr ($clampNode + ".outputG") ($shoulder + ".scaleY"); connectAttr ($clampNode + ".outputG") ($elbow + ".scaleY"); }//end if:Y if($z == 1) { connectAttr ($clampNode + ".outputB") ($shoulder + ".scaleZ"); connectAttr ($clampNode + ".outputB") ($elbow + ".scaleZ"); }//end if:Z //cleanup select $bicepDistanceNode; pickWalk -d up; delete; select $forearmDistanceNode; pickWalk -d up; delete; delete $elbowLoc[0]; }//end proc stretchMe //////////////////////// //Stretch proc for spline IK //////////////////////// global proc jpSplineStretch(string $mainControl, string $curve, string $firstBone, string $lastBone, float $maxStretch, int $x, int $y, int $z) { //prep the control to receive stretcy-ness select -cl; select $mainControl; if(!`attributeExists "autoStretchy" $mainControl`) { addAttr -ln autoStretchy -at long -min 0 -max 1 -dv 1 $mainControl; setAttr -e -keyable true ($mainControl + ".autoStretchy"); }//end if if(!`attributeExists "maxStretchy" $mainControl`) { addAttr -ln maxStretchy -at long -min 1 -dv $maxStretch $mainControl; setAttr -e -keyable true ($mainControl + ".maxStretchy"); }//end if // dupe the splineIKcurve for a reference length string $baselineCurve[] = `duplicate -n ($curve + "_baseline") $curve`; // make and connect the curveInfo nodes to find the lengths string $activeLength = `createNode curveInfo -n ($curve + "_CI")`; string $baselineLength = `createNode curveInfo -n ($baselineCurve[0] + "_CI")`; connectAttr ($curve + ".worldSpace[0]") ($activeLength + ".inputCurve"); connectAttr ($baselineCurve[0] + ".worldSpace[0]") ($baselineLength + ".inputCurve"); // compare the lengths string $multiplyDivide = `shadingNode -asUtility multiplyDivide -n ($curve + "_MD")`; setAttr ($multiplyDivide + ".operation") 2; setAttr ($multiplyDivide + ".input1Y") 1; setAttr ($multiplyDivide + ".input1Z") 1; connectAttr ($activeLength + ".arcLength") ($multiplyDivide + ".input1X"); connectAttr ($baselineLength + ".arcLength") ($multiplyDivide + ".input2X"); //clamp to greater than 1 string $clampNode = `shadingNode -asUtility clamp -n ($curve + "_clamp")`; connectAttr ($multiplyDivide + ".output") ($clampNode + ".input"); setAttr ($clampNode + ".minR") 1; setAttr ($clampNode + ".minG") 1; setAttr ($clampNode + ".minB") 1; connectAttr ($mainControl + ".maxStretchy") ($clampNode + ".maxR"); connectAttr ($mainControl + ".maxStretchy") ($clampNode + ".maxG"); connectAttr ($mainControl + ".maxStretchy") ($clampNode + ".maxB"); // auto/manual stretch condition string $autoStretchConditionNode = `shadingNode -asUtility condition -n ($mainControl + "_autoStretchCon")`; connectAttr ($mainControl + ".autoStretchy") ($autoStretchConditionNode + ".firstTerm"); setAttr ($autoStretchConditionNode + ".secondTerm") .5; setAttr ($autoStretchConditionNode + ".operation") 2; connectAttr ($clampNode + ".output") ($autoStretchConditionNode + ".colorIfTrue"); setAttr ($autoStretchConditionNode + ".colorIfFalseR") 1; setAttr ($autoStretchConditionNode + ".colorIfFalseG") 1; setAttr ($autoStretchConditionNode + ".colorIfFalseB") 1; //make an intermediate locator for scale string $scaleLoc[] = `spaceLocator -n ($curve + "_scale_loc")`; connectAttr ($autoStretchConditionNode + ".outColorR") ($scaleLoc[0] + ".scaleX"); connectAttr ($autoStretchConditionNode + ".outColorR") ($scaleLoc[0] + ".scaleY"); connectAttr ($autoStretchConditionNode + ".outColorR") ($scaleLoc[0] + ".scaleZ"); //find all the joints involved and connect them to the scale locator select -hi $firstBone; string $involvedJoints[] = `ls -sl`; print $involvedJoints; print "\n"; string $ikJoints[] = jpTypeFilterList($involvedJoints, "joint"); for($joint in $ikJoints) { print ($joint + "\n"); if($x == 1) connectAttr ($scaleLoc[0] + ".scaleX") ($joint + ".scaleX"); if($y == 1) connectAttr ($scaleLoc[0] + ".scaleY") ($joint + ".scaleY"); if($z == 1) connectAttr ($scaleLoc[0] + ".scaleZ") ($joint + ".scaleZ"); if($joint == $lastBone) break; }//end for }//end proc jpStretchSplineIK