View Full Version : My StretchyIK script - help/advice needed

11 November 2011, 01:12 AM
Yeah, I'm reinventing the wheel here. This was meant to be a practice exercise for creating nodes and connecting their attributes, since I'd never done it with MEL. I thought I'd script something that I've done manually several times. It's my first time creating something like this, so I'm sure it's not as "streamlined" as it could be.

The problem is, it isn't working.
What's supposed to happen: Select hip, knee, ankle (or shoulder, elbow, wrist). Run script.
Tada! Stretchy leg (or arm)!
(note, this assumes you've got X pointing down the bone)

Everything works but the "stretchy" part. I don't know where I've gone wrong. I did this manually and it works fine, so obviously there's something with in my MEL. Would someone mind taking a look for me? Also, if there's anything that I could have done better/faster/more efficiently, I'd love to hear it. I'm here to learn and get better.


//StarScript - StretchyIK (v 0.5)

//Description - Creates a stretchy IK setup for bipedal

// arms and legs.


//Known Issue:




To Do
Bug Fixing
Add global scale option
Give user more options/control






global proc Stretchy(){

//list the selected joints

string $jntCol[] = `ls -sl -type joint`;

string $jnts;

string $jntCol[0];

string $jntCol[1];

string $jntCol[2];

//put each joint in its own string

string $topSJnt = $jntCol[0];

string $midSJnt = $jntCol[1];

string $botSJnt = $jntCol[2];

//for each joint create a locator and a null group and place it over the joint

for ($jnts in $jntCol){

select $jnts;

string $sLoc[] = `spaceLocator -n ($jnts + "_stretchLoc")`;

string $ptCnLoc[] = `pointConstraint $jnts $sLoc`;

string $orCnLoc[] = `orientConstraint $jnts $sLoc`;

string $sNull = `group -em -n($jnts + "_stretchNull")`;

string $ptCnNull[] = `pointConstraint $jnts $sNull`;

string $orCnNull[] = `pointConstraint $jnts $sNull`;

delete $ptCnNull $orCnNull;

delete $ptCnLoc $orCnLoc;


//create the IK between the hip and the ankle

string $sIK[];

$sIK = `ikHandle -solver ikRPsolver -startJoint $jntCol[0] -endEffector $jntCol[2] -n ($jntCol[0] + "_stretchHandle")`;

rename $sIK[1] "myEndEffector";

select -cl;

//select the locators that were created


($jntCol[0] + "_stretchLoc")

($jntCol[1] + "_stretchLoc")

($jntCol[2] + "_stretchLoc");

string $locCol[] = `ls -sl`;

string $locCol[0];

string $locCol[1];

string $locCol[2];

//put each locator in its own string

string $topSLoc = $locCol[0];

string $midSLoc = $locCol[1];

string $botSLoc = $locCol[2];

select -cl;

//duplicate the bottom locator so it can be used for the third distanceDimension object

select $botSLoc;

string $dupLoc[] = `duplicate`;

string $dupLoc[0];

string $bufferLoc = $dupLoc[0];

//select the null groups that were created


($jntCol[0] + "_stretchNull")

($jntCol[1] + "_stretchNull")

($jntCol[2] + "_stretchNull");

string $nullCol[] = `ls -sl`;

string $nullCol[0];

string $nullCol[1];

string $nullCol[2];

//puch each null group in its own string

string $topSNull = $nullCol[0];

string $midSNull = $nullCol[1];

string $botSNull = $nullCol[2];

select -cl;

//create IK Handle

string $ikCtrl[] = `circle -r 2 -s 8 -n IKCtrl`;

string $getCtrlCV = `select -r ($ikCtrl[0] + ".cv[0:7]")`;

string $rotCVs = `rotate -r -p 0cm 0cm 0cm -os 90 0 0`;

select -cl;

string $grpCtrl = `group -n stretchCtrlGrp $ikCtrl`;

string $ptCnGrp[] = `pointConstraint $botSJnt $grpCtrl`;

string $orCnGrp[] = `orientConstraint $botSJnt $grpCtrl`;

select -cl;

string $finTopPtCn[] = `pointConstraint $topSJnt $topSNull`;

string $finIKPtCn[] = `pointConstraint $sIK[0] $grpCtrl`;

delete $ptCnGrp;

delete $orCnGrp;

string $parCtrl[] = `parent $sIK[0] $ikCtrl`;

float $posOne[];

float $posTwo[];

float $posThree[];

//Query the translation information of the locators that have been created

float $posOne[] = `xform -ws -q -translation $topSLoc`;

float $posTwo[] = `xform -ws -q -translation $midSLoc`;

//float $posThree[] = `xform -ws -q -translation $botSLoc`;

float $posThree[] = `xform -ws -q -translation $grpCtrl`;

float $posBuffer[] = `xform -ws -q -translation $bufferLoc`;

//find the distance between the hip, the knee then the knee and the ankle, then the hip and the knee

string $setPosOne = `distanceDimension -sp $posOne[0] $posOne[1] $posOne[2] -ep $posTwo[0] $posTwo[1] $posTwo[2]`;

string $setPosTwo = `distanceDimension -sp $posTwo[0] $posTwo[1] $posTwo[2] -ep $posThree[0] $posThree[1] $posThree[2]`;

string $setPosRelax = `distanceDimension -sp $posOne[0] $posOne[1] $posOne[2] -ep $posBuffer[0] $posBuffer[1] $posBuffer[2]`;

//Get the full distance of the hip to the ankle. (My thinking is this distance = the distance of the leg when it's extended)

float $distOne = `getAttr $setPosOne.distance`;

float $distTwo = `getAttr $setPosTwo.distance`;

float $dist = $distOne + $distTwo;

//Get the "relaxed" distance; the default distance of the leg in it's resting state

float $distRelax = `getAttr $setPosRelax.distance`;

select -cl;

//set up stretchy IK

//create a multiplyDivide node, Condition node, and a distanceBetween node

string $multDivNode = `shadingNode -asUtility multiplyDivide`;

string $condNode = `shadingNode -asUtility condition`;

string $distBetNode = `shadingNode -asUtility distanceBetween`;

string $trToPt1X = `connectAttr -f ($topSNull + ".translateX") ($distBetNode + ".point1X")`;

string $trToPt1Y = `connectAttr -f ($topSNull + ".translateY") ($distBetNode + ".point1Y")`;

string $trToPt1Z = `connectAttr -f ($topSNull + ".translateZ") ($distBetNode + ".point1Z")`;

string $trToPt2X = `connectAttr -f ($botSNull + ".translateX") ($distBetNode + ".point2X")`;

string $trToPt2Y = `connectAttr -f ($botSNull + ".translateY") ($distBetNode + ".point2Y")`;

string $trToPt2Z = `connectAttr -f ($botSNull + ".translateZ") ($distBetNode + ".point2Z")`;

string $dsToCon = `connectAttr -f ($distBetNode + ".distance") ($condNode + ".firstTerm")`;

string $dsToMD = `connectAttr -f ($distBetNode + ".distance") ($multDivNode + ".input1X")`;

string $mdToCon = `connectAttr -f ($multDivNode + ".outputX") ($condNode + ".colorIfTrueR")`;

string $mdNodetoDiv = `setAttr ($multDivNode + ".operation") 2`; //2 is Divide

string $condNotetoGE = `setAttr ($condNode + ".operation") 3`; //3 is Greater than or Equal To

string $distCon = `setAttr ($condNode + ".secondTerm") $dist`;

string $distConRelax = `setAttr ($condNode + ".firstTerm") $distRelax`;

string $distMDRelax = `setAttr ($multDivNode + ".input2X") $dist`;

string $thighToCon = `connectAttr -f ($condNode + ".outColorR") ($topSJnt + ".scaleX")`;

string $legToCon = `connectAttr -f ($condNode + ".outColorR") ($midSJnt + ".scaleX")`;


select -cl;

//Delete the distance tools, locaters and unnecessary nulls from the scene

select $topSLoc









/*global proc globalScale(){

select -cl;

string $getTopNull[] = `select $topSNull`;

string $getBotNull[] = `select $botSNull`;

string $grpNulls[] = `group -n nullGrp $topSNull $botSNull`;





11 November 2011, 06:39 AM
I can't help you as far as getting the script to work, but you might think about a few things when asking people to read your code: try having not so many spaces in your script. Right now its at 376 lines of code, and you could easily squish that down by at least half with better spacing. All you need to do is have spaces between the logical steps that are taken as a visual separator. The next thing is that you don't need to declare variables (and not give them a value) only to use them in another variable, such as:

string $jntCol[0];

string $jntCol[1];

string $jntCol[2];

//put each joint in its own string

string $topSJnt = $jntCol[0];

string $midSJnt = $jntCol[1];

string $botSJnt = $jntCol[2];


string $topSJnt = $jntCol[0];

string $midSJnt = $jntCol[1];

string $botSJnt = $jntCol[2];

Still works fine by itself, as long as you're setting the values to the indexes of an already declared array variable, like you did.

Sorry I can't help you with the actual functionality. If I remembered how to successfully make a stretchy IK limb, I'd tear the code apart and squash the bug for ya. You might try going through step by step and printing the values as the commands are completed.

11 November 2011, 06:53 AM
Thanks for the fast reply

I don't know what's up with the spacing. When I look in my script editor, it's barely pushing 200 lines, but I see what you're saying. As for your second example, thanks. I wasn't aware that you could just go ahead and do that (yay, I'm learning already :)). That'll save me a lot of space as well, since I did it about 4 or 5 times here.

Thanks again!

11 November 2011, 10:28 AM
yeah the code gets spread out when you copy paste from you script editor to cgtalk I think.

CGTalk Moderation
11 November 2011, 10:28 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.