Stretchy Leg Supports Weird Proportions!

Weird title, but big news! I got my stretchy leg script to work with different proportioned legs. That means it stretches them correctly and maintains their length correctly when not stretched.

What did I need to do this? A couple more attributes and 3 new nodes. I needed a condition node for each leg so that I could specify that the length had to be that limb’s particular length if it was false, and the “stretch factor” times the leg length if it is true.

Simple and scalable. I was able to put it into a UI which made it easy to first create the joints, move them where I want them, and then make all the controls. I have exactly what I need now!

Here’s the new Stretchy Limb script, and below is the UI that goes along with it.

import maya.cmds as cmds

class StretchyLeg():
    def __init__(self):
        print("# Leg Object Created")
    def makeJoints(self):
        self.upLimb= cmds.joint(n="upLimb#",p=(0,0,0),rad=.3)
        self.lowLimb = cmds.joint(n="lowLimb#",p=(0,-1,.001),rad=.3)
        self.endLimb = cmds.joint(n="endLimb#",p=(0,-2,0),rad=.3)

        self.foot = cmds.joint(n="foot#",p=(0,-2,.5),rad=.3)
        self.toe = cmds.joint(n="toe#",p=(0,-2,1),rad=.3)
        self.jointGrp = cmds.group(self.upLimb,n="jointGrp#")
        self.legJntGrp = cmds.group(self.upLimb,n="legJointGrp#")

    # Get location from methods instead of static attributes.
    def upLimbPos(self):
        return cmds.xform(self.upLimb,q=1,t=1,ws=1)
    def lowLimbPos(self):
        return cmds.xform(self.lowLimb,q=1,t=1,ws=1)
    def endLimbPos(self):
        return cmds.xform(self.endLimb,q=1,t=1,ws=1)
    def footPos(self):
        return cmds.xform(self.foot,q=1,t=1,ws=1)
    def toePos(self):
        return cmds.xform(self.toe,q=1,t=1,ws=1)

    def IKleg(self):
        cmds.select(self.upLimb)
        cmds.OrientJoint()
        self.legIK = cmds.ikHandle(sj=self.upLimb,ee=self.endLimb,sol="ikRPsolver")
        self.legIKgrp = cmds.group(self.legIK[0],n="legIK_GRP#")
        self.legIK[0] = cmds.rename(self.legIK[0],"legIK#")
        self.kneePoint = cmds.spaceLocator(n="kneePoint#")
        self.kneePointOrient = cmds.group(self.kneePoint,n="kneePoint_ORIENT#")
        cmds.xform(self.kneePointOrient,t=(0,-1,1))
        cmds.poleVectorConstraint(self.kneePoint,self.legIK[0])

        self.legGrp = cmds.group(self.jointGrp,self.legIKgrp,self.kneePointOrient,n="ikLeg_GRP#")

    def limbScale(self):
        return cmds.getAttr(self.legGrp + ".sx")
    def IKfoot(self):
        self.toeIK = cmds.ikHandle(sj=self.foot,ee=self.toe)
        self.toeIKgrp = cmds.group(self.toeIK[0],n="toeIK_GRP#")
        cmds.rename(self.toeIK[0],"toeIK#")
        self.footIK = cmds.ikHandle(sj=self.endLimb,ee=self.foot)
        self.footIKgrp = cmds.group(self.footIK[0],n="footIK_GRP#")
        cmds.rename(self.footIK[0],"footIK#")
        cmds.parent(self.footIKgrp,self.legGrp)
        cmds.parent(self.toeIKgrp,self.legGrp)
        self.ctrlGrp = cmds.group(self.footIKgrp,self.toeIKgrp,self.legIKgrp,self.kneePointOrient,n="contorlGrp#")

    def reverseFoot(self):
        cmds.select(self.legGrp)
        self.reverseHeel = cmds.joint(p=(self.endLimbPos()[0],self.toePos()[1],self.endLimbPos()[2]),n="reverseHeel#",rad=.5)
        self.reverseToe = cmds.joint(p=(self.toePos()[0],self.toePos()[1],self.toePos()[2]),n="reverseToe#",rad=.5)
        self.reverseFoot = cmds.joint(p=(self.footPos()[0],self.footPos()[1],self.footPos()[2]),n="reverseFoot#",rad=.5)
        self.reverseAnkle = cmds.joint(p=(self.endLimbPos()[0],self.endLimbPos()[1],self.endLimbPos()[2]),n="reverseAnkle#",rad=.5)

        self.reverseFootGrp = cmds.group(self.reverseHeel,n="reverseFootGrp#")

        cmds.select(self.reverseHeel)
        cmds.OrientJoint()

        cmds.parentConstraint(self.reverseToe,self.toeIKgrp,mo=1)
        cmds.parentConstraint(self.reverseToe,self.footIKgrp,mo=1)
        cmds.parentConstraint(self.reverseAnkle,self.legIKgrp,mo=1)

        cmds.parent(self.reverseFootGrp,self.jointGrp)
    def stretchyLeg(self):

        self.distDimStart = cmds.spaceLocator(n="distDimStart#")
        self.distDimEnd = cmds.spaceLocator(n="distDimEnd#")
        cmds.xform(self.distDimEnd,t=(self.endLimbPos()[0],self.endLimbPos()[1],self.endLimbPos()[2]))
        cmds.select(self.distDimStart,self.distDimEnd,add=1)
        self.distDim = cmds.distanceDimension()
        cmds.select(self.distDim)
        self.distDimShape = cmds.pickWalk(d="down")[0]
        self.upLimbLen = cmds.getAttr(self.lowLimb + ".tx")
        self.lowLimbLen = cmds.getAttr(self.endLimb + ".tx")
        self.stretchDist =  self.upLimbLen + self.lowLimbLen

        cmds.pointConstraint(self.reverseAnkle,self.distDimEnd,mo=1)
        cmds.pointConstraint(self.upLimb,self.distDimStart,mo=1)

        self.distGrp = cmds.group(self.distDimStart,self.distDimEnd,self.distDim,n="distGrp#")
        cmds.parent(self.distGrp, self.legGrp)

        self.distScaleComp = cmds.createNode("multiplyDivide",n="distScaleComp#")
        cmds.setAttr(self.distScaleComp + ".i1x",self.stretchDist)
        cmds.connectAttr(self.legGrp + ".sx",self.distScaleComp + ".i2x")

        self.currDist = cmds.createNode("multiplyDivide",n="currDist#")
        cmds.setAttr(self.currDist + ".op",2)
        cmds.connectAttr(self.distScaleComp + ".ox",self.currDist + ".i2x")
        cmds.connectAttr(self.distDimShape + ".distance",self.currDist + ".i1x")

        self.upLimbStretchLen = cmds.createNode("multiplyDivide",n="upLimbStretchLen#")
        cmds.connectAttr(self.currDist + ".ox", self.upLimbStretchLen + ".i1x")
        cmds.setAttr(self.upLimbStretchLen + ".i2x",self.upLimbLen)

        self.lowLimbStretchLen = cmds.createNode("multiplyDivide",n="lowLimbStretchLen#")
        cmds.connectAttr(self.currDist + ".ox", self.lowLimbStretchLen + ".i1x")
        cmds.setAttr(self.lowLimbStretchLen + ".i2x",self.lowLimbLen)

        self.upLimbStretchyCondition = cmds.createNode("condition",n="UpLimbstretchyCondition#")
        cmds.setAttr(self.upLimbStretchyCondition + ".op",2)
        cmds.setAttr(self.upLimbStretchyCondition + ".cfr",self.upLimbLen)
        cmds.connectAttr(self.upLimbStretchLen + ".ox",self.upLimbStretchyCondition + ".ctr")
        cmds.connectAttr(self.currDist + ".ox",self.upLimbStretchyCondition + ".ft")
        cmds.setAttr(self.upLimbStretchyCondition + ".st",1)

        self.lowLimbStretchyCondition = cmds.createNode("condition",n="LowLimbstretchyCondition#")
        cmds.setAttr(self.lowLimbStretchyCondition + ".op",2)
        cmds.setAttr(self.lowLimbStretchyCondition + ".cfr",self.lowLimbLen)
        cmds.connectAttr(self.lowLimbStretchLen + ".ox",self.lowLimbStretchyCondition + ".ctr")
        cmds.connectAttr(self.currDist + ".ox",self.lowLimbStretchyCondition + ".ft")
        cmds.setAttr(self.lowLimbStretchyCondition + ".st",1)

        cmds.connectAttr(self.upLimbStretchyCondition + ".ocr",self.lowLimb + ".tx")
        cmds.connectAttr(self.lowLimbStretchyCondition + ".ocr",self.endLimb + ".tx")

"""
myLeg = StretchyLeg()
myLeg.makeJoints()

myLeg.IKleg()
myLeg.IKfoot()
myLeg.reverseFoot()
myLeg.stretchyLeg()
"""

# next task is to make it so that the leg can have different proportions... Not too difficult. I've already done it before.
# All you do is make separate conditionals for each leg. The cfr for each leg is based on its particular length.
import maya.cmds as cmds
import bm_LegObj_03 as legObj
reload(legObj)

myLeg = legObj.StretchyLeg()

def legSetup():
    myLeg.IKleg()
    myLeg.IKfoot()
    myLeg.reverseFoot()
    myLeg.stretchyLeg()
    print ("# Leg Controls Created")

if cmds.window('stretchyLimb',exists=1):
    cmds.deleteUI('stretchyLimb')

cmds.window('stretchyLimb',t="bm_LimbGen",tlb=1)
cmds.columnLayout()

cmds.text("Stretchy Limb Generator")
cmds.button(l="Create Joints",c="myLeg.makeJoints()")
cmds.button(l="Setup Leg",c="legSetup()")

cmds.showWindow('stretchyLimb')
cmds.window('stretchyLimb',edit=1,wh=(125,75))
Advertisements
Image

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s