Ejemplo n.º 1
0
    def build(self):
        self.tangentCrv = rt_curve.TangentCurve(points=cmds.ls(sl=1), name=self.name)
        self.main_grp = cmds.group(empty=1, name='%s_grp' % self.name)
        cmds.parent(self.tangentCrv.dnt_grp, self.main_grp)

        # Ctrls
        self.ctrls = []
        for loc in self.tangentCrv.cv_locs:
            ctrl = rt_controls.circleBumpCtrl(radius=10, name=loc.replace('loc', 'ctrl'), axis='y')
            common.align(ctrl, loc, orient=0)
            cmds.parent(loc, ctrl)
            cmds.parent(ctrl, self.main_grp)
            common.insertGroup(ctrl)
            cmds.addAttr(ctrl, ln='tangentWeight', at="float", minValue=0.0, maxValue=1.0, keyable=1, hidden=0, defaultValue=0.25 )
            cmds.connectAttr('%s.tangentWeight' % ctrl, '%s.tangentWeight' % loc)
            self.ctrls.append(ctrl)

        # set up stretch blending
        cmds.addAttr(self.ctrls[-1], ln='stretch', at="float", minValue=0.0, maxValue=1.0, keyable=1, hidden=0, defaultValue=1.0 )
        cmds.addAttr(self.ctrls[-1], ln='stretchValue', at="float", keyable=0, hidden=0)
        info = cmds.createNode('curveInfo', name='%s_crvInfo' % self.name)
        cmds.connectAttr('%s.worldSpace[0]' % self.tangentCrv.crv, '%s.inputCurve' % info)
        stretch_md = cmds.createNode('multiplyDivide', name='%s_stretch_md' % self.name)
        cmds.connectAttr('%s.arcLength' % info, '%s.input2X' % stretch_md)
        cmds.setAttr('%s.input1X' % stretch_md, cmds.getAttr('%s.input2X' % stretch_md))
        cmds.setAttr('%s.operation' % stretch_md, 2)
        cmds.connectAttr('%s.outputX' % stretch_md, '%s.stretchValue' % self.ctrls[-1])



        # Nodes along curve
        self.pathNodes = rt_curve.nodesAlongCurve(crv=self.tangentCrv.crv, numNodes=self.numCtrls, name=self.name)
        for i in range(len(self.pathNodes['mpNodes'])):
            mp = self.pathNodes['mpNodes'][i]
            if i == 0:
                cmds.pathAnimation(mp, e=1, wut='objectrotation', wuo=self.ctrls[0])
            else:
                cmds.pathAnimation(mp, e=1, wut='objectrotation', wuo=self.pathNodes['grps'][i-1])

                # Add stretching functionality
                blend = cmds.createNode('blendTwoAttr', name=mp.replace('mp', 'stretch_blend'))
                cmds.connectAttr('%s.stretch' % self.ctrls[-1], '%s.attributesBlender' % blend)
                uc = cmds.createNode('unitConversion', name=mp.replace('mp', 'stretch_uc'))
                cmds.connectAttr('%s.stretchValue' % self.ctrls[-1], '%s.input' % uc)
                cmds.setAttr('%s.conversionFactor' % uc, cmds.getAttr('%s.uValue' % mp))
                cmds.connectAttr('%s.output' % uc, '%s.input[0]' % blend)
                cmds.setAttr('%s.input[1]' % blend, cmds.getAttr('%s.uValue' % mp))
                cmds.connectAttr('%s.output' % blend, '%s.uValue' % mp)
            cmds.parent(self.pathNodes['grps'][i], self.tangentCrv.dnt_grp)
Ejemplo n.º 2
0
def buildSpine(start, end, numJoints=10, name=''):
    # base groups
    main_grp = pmc.group(empty=1, name='%s_grp' % name)
    const_grp = pmc.group(empty=1, name='%s_const_grp' % name)
    common.align(const_grp.nodeName(), start, orient=0)

    # Create curve
    crv = curve.curveBetweenNodes(start, end, name=name)
    crvJoints = curve.bindCurve(crv)

    # controls
    # hips
    hip_ctrl = controls.circleBumpCtrl(name='%s_hips_ctrl' % name, axis='y')
    common.align(hip_ctrl.nodeName(), crvJoints[1])
    hip_ctrl.setParent(const_grp)
    pmc.parent(crvJoints[0], hip_ctrl)
    hip_tan_grp = common.insertGroup(crvJoints[0])
    hip_tan_grp = pmc.rename(hip_tan_grp, '%s_hips_tangent_grp' % name)
    pmc.parent(crvJoints[1], hip_tan_grp)
    pmc.parent(hip_tan_grp, hip_ctrl)
    common.insertGroup(hip_ctrl.nodeName())

    # chest
    chest_ctrl = controls.circleBumpCtrl(name='%s_chest_ctrl' % name, axis='y')
    common.align(chest_ctrl.nodeName(), crvJoints[2])
    chest_ctrl.setParent(const_grp)
    pmc.parent(crvJoints[3], chest_ctrl)
    chest_tan_grp = common.insertGroup(crvJoints[3])
    chest_tan_grp = pmc.rename(chest_tan_grp, '%s_chest_tangent_grp' % name)
    pmc.parent(crvJoints[2], chest_tan_grp)
    pmc.parent(chest_tan_grp, chest_ctrl)
    common.insertGroup(chest_ctrl.nodeName())

    # curve tangent stuff
    # crvInfo
    crvInfo = pmc.createNode('curveInfo', name='%s_crvInfo' % name)
    crvShape = common.getShape(crv)
    crvShape.worldSpace[0].connect(crvInfo.inputCurve)

    # distance
    ctrlDist = common.distanceBetweenNodes(hip_ctrl, chest_ctrl, name='%s_dist' % name)
    distMD = common.divide(ctrlDist.distance, ctrlDist.distance.get(), name='%s_ctrlDist_md')
    ctrlDistMult = common.pow(distMD.outputX, 0.5, name='%s_ctrlDistMult_md')

    # angle
    hipVp = pmc.createNode('vectorProduct', name='%s_hipAngle_vp' % name)
    hipVp.operation.set(3)
    hip_ctrl.worldMatrix[0].connect(hipVp.matrix)
    hipVp.input1X.set(0.0)
    hipVp.input1Y.set(1.0)
    hipVp.input1Z.set(0.0)

    chestVp = pmc.createNode('vectorProduct', name='%s_chestAngle_vp' % name)
    chestVp.operation.set(3)
    chest_ctrl.worldMatrix[0].connect(chestVp.matrix)
    chestVp.input1X.set(0.0)
    chestVp.input1Y.set(1.0)
    chestVp.input1Z.set(0.0)

    dotVp = pmc.createNode('vectorProduct', name='%s_angle' % name)
    hipVp.output.connect(dotVp.input1)
    chestVp.output.connect(dotVp.input2)
    dotVp.normalizeOutput.set(1)

    dotPMA = common.add([dotVp.outputX, 1.0], name='%_dotPlusOne_pma')
    dotMult = common.multiply(dotPMA.output1D, 0.25, name='%s_dot_md')
    dotRev = pmc.createNode('reverse', name='%s_dot_rev' % name)
    dotMult.outputX.connect(dotRev.inputX)

    tanPMA = common.add([dotRev.outputX, ctrlDistMult.outputX], name='%s_tangent_pma')

    tanPMA.output1D.connect('%s.sx' % hip_tan_grp)
    tanPMA.output1D.connect('%s.sy' % hip_tan_grp)
    tanPMA.output1D.connect('%s.sz' % hip_tan_grp)
    tanPMA.output1D.connect('%s.sx' % chest_tan_grp)
    tanPMA.output1D.connect('%s.sy' % chest_tan_grp)
    tanPMA.output1D.connect('%s.sz' % chest_tan_grp)


    # stretch
    stretchMD = common.divide(crvInfo.arcLength, crvInfo.arcLength.get(), name='%s_stretch_md' % name)

    # pathNodes
    mps = curve.nodesAlongCurve(crv=crv, numNodes=numJoints, name=name, followAxis='y', upAxis='z', upNode=hip_ctrl.nodeName(), upVec='z')
Ejemplo n.º 3
0
def tripleChain(top=None, mid=None, bot=None, end=None, prefix='', settingsCtrl=None, globalScaleAttr=None, nameList=legNames):
    '''
    makes an fk, ik and result chain based on the supplied 4 joint hierarchy
    '''

    #Validation
    if not top or not mid or not bot or not end:
        if len(pmc.selected()) == 4:
            top = pmc.selected()[0]
            mid = pmc.selected()[1]
            bot = pmc.selected()[2]
            end = pmc.selected()[3]
        else:
            return common.showDialog('Argument Error', 'Please supply 4 hierarchical joints')

    ##################################################################################################################################################
    # Base groups
    ##################################################################################################################################################
    # Root group
    root = pmc.group(empty=1, name='%s_grp' % prefix)
    if not globalScaleAttr:
        globalScaleAttr = root.sx

    #Constrain group which is aligned to the first joint and can be used to attach the limb to a shoulder or hip
    const = pmc.group(empty=1, name='%s_const_grp' % prefix)
    common.align(const.nodeName(), top.nodeName())
    const.setParent(root)

    def _duplicateChain(chainType):
        dupes = cmds.duplicate(top.nodeName(), rc=1)
        print dupes
        dupes = pmc.ls(dupes)
        for d in range(4):
            dupes[d].rename('%s_%s_%s_jnt' % (prefix, nameList[d], chainType))
        return dupes

    resultChain = _duplicateChain('result')
    resultChain[0].setParent(const)
    fkChain = _duplicateChain('fk')
    fkChain[0].setParent(const)
    ikChain = _duplicateChain('ik')
    ikChain[0].setParent(const)

    ##################################################################################################################################################
    # SETTINGS & ATTRS
    ##################################################################################################################################################
    if not settingsCtrl:
        settingsCtrl = controls.crossCtrl(name='%s_settings_ctrl' % prefix)
        common.align(settingsCtrl.nodeName(), const.nodeName())
        settingsCtrl.setParent(root)
        # ik / fk attr
        pmc.addAttr(settingsCtrl, longName='state', at='float', minValue=0.0, maxValue=1.0, keyable=True, hidden=0)
        stateRev = pmc.createNode('reverse', name='%s_state_rev' % prefix)
        settingsCtrl.state.connect(stateRev.inputX)
        # bendy ctrls switch
        pmc.addAttr( settingsCtrl, longName='bendy_ctrls', at='enum', enumName='hide:show', keyable=True )
        pmc.parentConstraint(resultChain[2], settingsCtrl)


    ##################################################################################################################################################
    # FK CTRLS
    ##################################################################################################################################################
    fkGrp = pmc.group(empty=1, name='%s_fk_grp' % prefix)
    fkGrp.setParent(const)
    settingsCtrl.state.connect(fkGrp.visibility)

    # fk top ctrl
    fkTopCtrl = controls.circleBumpCtrl(name='%s_%s_fk_ctrl' % (prefix, nameList[0]), axis='x', radius=10)
    common.align(fkTopCtrl.nodeName(), fkChain[0].nodeName())
    fkTopCtrl.setParent(fkGrp)
    common.insertGroup(fkTopCtrl.nodeName())

    # fk mid ctrl
    fkMidCtrl = controls.circleBumpCtrl(name='%s_%s_fk_ctrl' % (prefix, nameList[1]), axis='x', radius=10)
    common.align(fkMidCtrl.nodeName(), fkChain[1].nodeName())
    fkMidCtrl.setParent(fkTopCtrl)
    common.insertGroup(fkMidCtrl.nodeName())

    # fk bot ctrl
    fkBotCtrl = controls.circleBumpCtrl(name='%s_%s_fk_ctrl' % (prefix, nameList[2]), axis='x', radius=10)
    common.align(fkBotCtrl.nodeName(), fkChain[2].nodeName())
    fkBotCtrl.setParent(fkMidCtrl)
    common.insertGroup(fkBotCtrl.nodeName())

    pmc.parentConstraint(fkTopCtrl, fkChain[0])
    pmc.parentConstraint(fkMidCtrl, fkChain[1])
    pmc.parentConstraint(fkBotCtrl, fkChain[2])

    # add extend attrs
    for ctrl in [fkMidCtrl, fkBotCtrl]:
        pmc.addAttr( ctrl, longName='extend', at='double', keyable=True )
        boneLen = ctrl.getParent().tx.get()
        if boneLen > 0.0:
            extend_pma = common.add([boneLen, ctrl.extend], name='%s_extend_pma' % ctrl.nodeName())
        else:
            extend_pma = common.minus([boneLen, ctrl.extend], name='%s_extend_pma' % ctrl.nodeName())
        extend_pma.output1D.connect(ctrl.getParent().tx)

    ##################################################################################################################################################
    # IK BUSINESS
    ##################################################################################################################################################
    ikGrp = pmc.group(empty=1, name='%s_ik_grp' % prefix)
    ikGrp.setParent(root)
    stateRev.outputX.connect(ikGrp.visibility)

    # IK ctrl
    ikCtrl = controls.boxCtrl(name='%s_ik_ctrl' % prefix, size=10)
    common.align(ikCtrl.nodeName(), resultChain[2].nodeName(), orient=0)
    ikCtrl.setParent(ikGrp)
    common.insertGroup(ikCtrl.nodeName())

    pmc.addAttr( ikCtrl, longName='stretch', at='double', minValue=0, maxValue=1, defaultValue=0, keyable=True )
    pmc.addAttr( ikCtrl, longName='extend', at='double', keyable=True )
    pmc.addAttr( ikCtrl, longName='soft', at='double', minValue=0, defaultValue=0, keyable=True )

    # Set up ik / fk blending
    for i in range(4):
        common.blendAttrs(targ1=ikChain[i].nodeName(), targ2=fkChain[i].nodeName(), driven=resultChain[i].nodeName(), blendAttr='%s.state' % settingsCtrl.nodeName())

    # Soft non-stretchy IK stuff
    softBlendLoc = pmc.spaceLocator(name='%s_softBlendLoc' % prefix)
    common.align(softBlendLoc.nodeName(), ikCtrl.nodeName())
    softBlendLoc.setParent(ikGrp)

    aimLoc = pmc.spaceLocator(name='%s_softIkAimLoc' % prefix)
    common.align(aimLoc.nodeName(), const.nodeName())
    aimLoc.setParent(const)
    pmc.aimConstraint(ikCtrl, aimLoc)

    wristLoc = pmc.spaceLocator(name='%s_wristLoc' % prefix)
    common.align(wristLoc.nodeName(), ikCtrl.nodeName())
    wristLoc.setParent(aimLoc)

    ctrlLoc = pmc.spaceLocator(name='%s_ctrlLoc' % prefix)
    common.align(ctrlLoc.nodeName(), ikCtrl.nodeName())
    ctrlLoc.setParent(ikCtrl)

    ctrlDist = common.distanceBetweenNodes(aimLoc, ctrlLoc, name='%s_ctrlDist' % prefix)
    softDist = common.distanceBetweenNodes(wristLoc, softBlendLoc, name='%s_softDist' % prefix)
    stretchDist = common.distanceBetweenNodes(aimLoc, softBlendLoc, name='%s_stretchDist' % prefix)

    chainLen = abs(ikChain[1].tx.get() + ikChain[2].tx.get())

    chainLenMinusSoft = common.minus([chainLen, ikCtrl.soft], name='%s_chainLenMinusSoft_pma' % prefix)
    print(chainLenMinusSoft)

    isStretchedCond = pmc.createNode('condition', name='%s_isStretched_cond' % prefix)
    isStretchedCond.operation.set(2)
    ctrlDist.distance.connect(isStretchedCond.firstTerm)
    chainLenMinusSoft.output1D.connect(isStretchedCond.secondTerm)
    ctrlDist.distance.connect(isStretchedCond.colorIfFalseR)

    isSoftCond = pmc.createNode('condition', name='%s_isSoft_cond' % prefix)
    isSoftCond.operation.set(2)
    ikCtrl.soft.connect(isSoftCond.firstTerm)
    isSoftCond.colorIfFalseR.set(chainLen)

    ctrlDistMinusSoftChain = common.minus([ctrlDist.distance, chainLenMinusSoft.output1D], name='%s_ctrlDistMinusSoftChain_pma' % prefix)

    divideBySoft = common.divide(ctrlDistMinusSoftChain.output1D, ikCtrl.soft, name='%s_divideBySoft_md' % prefix)

    invert = common.multiply(divideBySoft.outputX, -1, name='%s_invertSoft_md' % prefix)

    exp = common.pow(2.718282, invert.outputX, name='%s_exponential_md' % prefix)

    multiplyBySoft = common.multiply(exp.outputX, ikCtrl.soft, name='%s_multiplyBySoft_md' % prefix)

    minusFromChainLen = common.minus([chainLen, multiplyBySoft.outputX], name='%s_minusFromChainLen_md' % prefix)

    minusFromChainLen.output1D.connect(isSoftCond.colorIfTrueR)

    isSoftCond.outColorR.connect(isStretchedCond.colorIfTrueR)

    isStretchedCond.outColorR.connect(wristLoc.tx)

    # stretchy soft IK stuff
    pc = pmc.pointConstraint(wristLoc, ctrlLoc, softBlendLoc)
    stretchRev = pmc.createNode('reverse', name='%s_stretch_rev' % prefix)
    ikCtrl.stretch.connect(stretchRev.inputX)
    stretchRev.outputX.connect('%s.%sW0' % (pc.nodeName(), wristLoc.nodeName()))
    ikCtrl.stretch.connect('%s.%sW1' % (pc.nodeName(), ctrlLoc.nodeName()))

    globalScaleDiv = common.divide(1.0, globalScaleAttr, name='%s_globalScaleDiv_md' % prefix)

    scaledSoftDist = common.multiply(globalScaleDiv.outputX, softDist.distance, name='%s_scaledSoftDist_md' % prefix)

    # Stretchy Mid
    midLen = common.multiply((mid.tx.get() / chainLen), scaledSoftDist.outputX, name='%s_midLen_md' % prefix)

    stretchMidLen = common.multiply(ikCtrl.stretch, midLen.outputX, name='%s_stretchMidLen_md' % prefix)

    stretchMidLenPlusBoneLen = common.add([mid.tx.get(), stretchMidLen.outputX], name='%s_stretchMidLenPlusBoneLen_pma' % prefix)

    stretchMidLenPlusBoneLen.output1D.connect(ikChain[1].tx)

    # Stretchy Bot
    botLen = common.multiply((bot.tx.get() / chainLen), scaledSoftDist.outputX, name='%s_botLen_md' % prefix)

    stretchBotLen = common.multiply(ikCtrl.stretch, botLen.outputX, name='%s_stretchBotLen_md' % prefix)

    stretchBotLenPlusBoneLen = common.add([bot.tx.get(), stretchBotLen.outputX], name='%s_stretchBotLenPlusBoneLen_pma' % prefix)

    stretchBotLenPlusBoneLen.output1D.connect(ikChain[2].tx)


    # IK Solvers
    ikHandleGrp = pmc.group(empty=1, name='%s_ikHandle_grp' % prefix)
    common.align(ikHandleGrp.nodeName(), ikCtrl.nodeName())
    ikHandleGrp.setParent(softBlendLoc)
    pmc.orientConstraint(ikCtrl, ikHandleGrp, mo=1)

    ikHandle = pmc.ikHandle(solver='ikRPsolver', name='%s_ikHandle' % prefix, startJoint=ikChain[0], endEffector=ikChain[2])[0]
    common.align(ikHandle.nodeName(), resultChain[2].nodeName())
    ikHandle.setParent(ikHandleGrp)

    endIkHandle = pmc.ikHandle(solver='ikSCsolver', name='%s_end_ikHandle' % prefix, startJoint=ikChain[2], endEffector=ikChain[3])[0]
    common.align(endIkHandle.nodeName(), resultChain[3].nodeName())
    endIkHandle.rx.set(0)
    endIkHandle.setParent(ikHandleGrp)

    ##################################################################################################################################################
    # NON ROLLS
    ##################################################################################################################################################
    topNonRoll = nonRoll.build(joint=resultChain[0].nodeName(), name='%s_top' % prefix)
    cmds.parent(topNonRoll['main_grp'], const.nodeName())

    midNonRoll = nonRoll.build(joint=resultChain[1].nodeName(), name='%s_mid' % prefix)
    cmds.parent(midNonRoll['main_grp'], topNonRoll['nonRoll'])

    botNonRoll = nonRoll.build(joint=resultChain[2].nodeName(), name='%s_bot' % prefix)
    cmds.parent(botNonRoll['main_grp'], resultChain[1].nodeName())
Ejemplo n.º 4
0
def build(upLeg=None, lowLeg=None, ankle=None, end=None, side='lf', twistJoints=5, globalScaleAttr=None, cleanup=0):
    '''
    makes a triple chain leg using a set of 4 existing hierarchical joints
    
    '''
    #Validation
    if not upLeg or not lowLeg or not ankle or not end:
        if len(cmds.ls(sl=1)) == 4:
            upLeg = cmds.ls(sl=1)[0]
            lowLeg = cmds.ls(sl=1)[1]
            ankle = cmds.ls(sl=1)[2]
            end = cmds.ls(sl=1)[3]
        else:
            return common.showDialog( 'Argument Error', 'Please supply 4 hierarchical joints' )
    
    # Root group
    root = cmds.group(empty=1, name='%s_leg_grp' % side)
    
    #Constrain group which is aligned to the first joint and can be used to attach the leg to a shoulder
    const = cmds.group(empty=1, name='%s_leg_const_grp' % side)
    common.align(const, upLeg)
    cmds.parent(const, root)
    
    # result chainw
    dupes = cmds.duplicate(upLeg, rc=1)
    resultChain = []
    for i in range(4):
        jnt = cmds.rename(dupes[i], '%s_%s_result_jnt' %(side, ['upLeg', 'lowLeg', 'ankle', 'end'][i]) )
        resultChain.append(jnt)
        
    cmds.parent(resultChain[0], const)
    
    # fk chain
    dupes = cmds.duplicate(resultChain[0], rc=1)
    fkChain = []
    for i in range(4):
        jnt = cmds.rename(dupes[i], '%s_%s_fk_jnt' %(side, ['upLeg', 'lowLeg', 'ankle', 'end'][i]) )
        fkChain.append(jnt)
        
    
    # ik chain
    dupes = cmds.duplicate(resultChain[0], rc=1)
    ikChain = []
    for i in range(4):
        jnt = cmds.rename(dupes[i], '%s_%s_ik_jnt' %(side, ['upLeg', 'lowLeg', 'ankle', 'end'][i]) )
        ikChain.append(jnt)
        
    # Settings ctrl
    settingsCtrl = controls.crossCtrl(name='%s_leg_settings_ctrl' % side)
    settingsShape = common.getShape(settingsCtrl)
    common.align(settingsCtrl, const)
    cmds.parent(settingsCtrl, root)
    # ik / fk attr
    cmds.addAttr( settingsCtrl, longName='state', at='enum', enumName='ik:fk', keyable=True )
    stateRev = cmds.createNode('reverse', name='%s_leg_state_rev' % side)
    cmds.connectAttr('%s.state' % settingsCtrl, '%s.inputX' % stateRev)
    # bendy ctrls switch
    cmds.addAttr( settingsCtrl, longName='bendy_ctrls', at='enum', enumName='hide:show', keyable=True )
    
    ##################################################################################################################################### FK Ctrls
    fkGrp = cmds.group(empty=1, name='%s_leg_fk_grp' % side)
    cmds.parent(fkGrp, root)
    cmds.connectAttr('%s.state' % settingsCtrl, '%s.visibility' % fkGrp)
    
    # fk up leg
    fkUpLegCtrl = controls.circleBumpCtrl(name='%s_upLeg_fk_ctrl' % side, axis='x', radius=10)[0]
    common.align(fkUpLegCtrl, fkChain[0])
    cmds.parent(fkUpLegCtrl, fkGrp)
    common.insertGroup(fkUpLegCtrl)
    
    # fk low leg
    fkLowLegCtrl = controls.circleBumpCtrl(name='%s_lowLeg_fk_ctrl' % side, axis='x', radius=10)[0]
    common.align(fkLowLegCtrl, fkChain[1])
    cmds.parent(fkLowLegCtrl, fkUpLegCtrl)
    
    # fk foot
    fkFootCtrl = controls.circleBumpCtrl(name='%s_foot_fk_ctrl' % side, axis='x', radius=10)[0]
    common.align(fkFootCtrl, fkChain[2])
    cmds.parent(fkFootCtrl, fkLowLegCtrl)
    
    cmds.parentConstraint(fkUpLegCtrl, fkChain[0])
    cmds.parentConstraint(fkLowLegCtrl, fkChain[1])
    cmds.parentConstraint(fkFootCtrl, fkChain[2])
    
    # add extend attrs
    for ctrl in [fkLowLegCtrl, fkFootCtrl]:
        cmds.addAttr( ctrl, longName='extend', at='double', keyable=True )
        extend_pma = cmds.createNode('plusMinusAverage', name='%s_extend_pma' % ctrl)
        cmds.setAttr('%s.input1D[0]' % extend_pma, cmds.getAttr('%s.tx' % ctrl))
        if side == 'lf':
            cmds.setAttr('%s.operation' % extend_pma, 2)
        cmds.connectAttr('%s.extend' % ctrl, '%s.input1D[1]' % extend_pma)
        cmds.connectAttr('%s.output1D' % extend_pma, '%s.tx' % ctrl)
    
    ##################################################################################################################################### IK ctrls ####
    ikGrp = cmds.group(empty=1, name='%s_leg_ik_grp' % side)
    cmds.parent(ikGrp, root)
    cmds.connectAttr('%s.outputX' % stateRev, '%s.visibility' % ikGrp)
    
    # IK foot
    ikFootCtrl = controls.boxCtrl(name='%s_foot_ik_ctrl' % side, size=10)
    common.align(ikFootCtrl, resultChain[2], orient=0)
    cmds.parent(ikFootCtrl, ikGrp)
    common.insertGroup(ikFootCtrl)
    
    cmds.addAttr( ikFootCtrl, longName='stretch', at='double', minValue=0, maxValue=1, defaultValue=0, keyable=True )
    cmds.addAttr( ikFootCtrl, longName='extend', at='double', keyable=True )
    cmds.addAttr( ikFootCtrl, longName='pin', at='double', minValue=0, maxValue=1, defaultValue=0, keyable=True )
    
    # IK Knee
    ikKneeCtrl = controls.crossCtrl(name='%s_knee_ik_ctrl' % side, size=10)
    
    pvAxis = '-z'
    if side == 'rt':
        pvAxis='z'
    pv = common.placePoleVector(node1=resultChain[0], node2=resultChain[1], node3=resultChain[2], axis=pvAxis)
    cmds.setAttr('%s.t' % ikKneeCtrl, pv[0], pv[1], pv[2])
    cmds.parent(ikKneeCtrl, ikGrp)
    common.insertGroup(ikKneeCtrl)
    
    # IK Solvers
    ikHandle = cmds.ikHandle( solver='ikRPsolver', name='%s_leg_ikHandle' % side, startJoint=ikChain[ 0 ], endEffector=ikChain[ 2 ] )[ 0 ]
    common.align(ikHandle, resultChain[2])
    cmds.poleVectorConstraint(ikKneeCtrl, ikHandle)
    cmds.parent(ikHandle, ikFootCtrl)
    
    endIkFootle = cmds.ikHandle( solver='ikSCsolver', name='%s_leg_end_ikHandle' % side, startJoint=ikChain[ 2 ], endEffector=ikChain[ 3 ] )[ 0 ]
    common.align(endIkFootle, resultChain[3])
    cmds.parent(endIkFootle, ikFootCtrl)
    cmds.setAttr('%s.rotateX' % endIkFootle, 0)
    
    #if side == 'lf':
        #cmds.setAttr('%s.preferredAngleY' % ikChain[1], -90)
    
    # Set up ik / fk blending
    for i in range(4):
        common.blendAttrs(targ1=ikChain[i], targ2=fkChain[i], driven=resultChain[i], blendAttr='%s.state' % settingsCtrl)
    
    ############################################################################################################################## Stretchy IK
    # upLeg to ankle measure
    legDist = measure.build(start=resultChain[0], end=resultChain[2], name='%s_legDist' % side)
    cmds.parent(legDist['start'], const)
    cmds.parent(legDist['xform'], const)
    cmds.parent(legDist['end'], ikFootCtrl)
    
    # upLeg to knee measure
    upLegDist = measure.build(start=resultChain[0], end=ikKneeCtrl, startLoc=legDist['start'], name='%s_upLegDist' % side)
    cmds.parent(upLegDist['xform'], const)
    cmds.parent(upLegDist['end'], ikKneeCtrl)
    
    # knee to ankle measure
    lowLegDist = measure.build(start=ikKneeCtrl, end=ikFootCtrl, startLoc=upLegDist['end'], endLoc=legDist['end'], name='%s_lowLegDist' % side)
    cmds.parent(lowLegDist['xform'], const)
    
    # Utility node creation
    stretch_md = cmds.createNode('multiplyDivide', name='%s_leg_stretchFactor_md' % side)
    squash_md = cmds.createNode('multiplyDivide', name='%s_leg_squashFactor_md' % side)
    stretch_cond = cmds.createNode('condition', name='%s_leg_stretchFactor_cond' % side)
    extend_pma = cmds.createNode('plusMinusAverage', name='%s_leg_extend_pma' % side)
    
    upLegStretch_md = cmds.createNode('multiplyDivide', name='%s_upLeg_stretch_md' % side)
    upLegStretchAmount_bc = cmds.createNode('blendColors', name='%s_upLeg_stretchAmount_bc' % side)
    upLegPinAmount_bc = cmds.createNode('blendColors', name='%s_upLeg_pinAmount_bc' % side)
    
    lowLegStretch_md = cmds.createNode('multiplyDivide', name='%s_lowLeg_stretch_md' % side)
    lowLegStretchAmount_bc = cmds.createNode('blendColors', name='%s_lowLeg_stretchAmount_bc' % side)
    lowLegPinAmount_bc = cmds.createNode('blendColors', name='%s_lowLeg_pinAmount_bc' % side)
    
    extendGlobalScale_md = cmds.createNode('multiplyDivide', name='%s_leg_extendGlobalScale_md' % side)
    legDistGlobalScale_md = cmds.createNode('multiplyDivide', name='%s_legDist_globalScale_md' % side)
    upLegDistGlobalScale_md = cmds.createNode('multiplyDivide', name='%s_upLegDistGlobalScale_md' % side)
    lowLegDistGlobalScale_md = cmds.createNode('multiplyDivide', name='%s_lowLegDistGlobalScale_md' % side)
    
    # Connect up graph
    cmds.connectAttr('%s.extend' % ikFootCtrl, '%s.input1X' % extendGlobalScale_md)
    
    cmds.connectAttr('%s.distance' % legDist['shape'], '%s.input1X' % legDistGlobalScale_md)
    cmds.setAttr('%s.operation' % legDistGlobalScale_md, 2)
    
    cmds.connectAttr('%s.distance' % upLegDist['shape'], '%s.input1X' % upLegDistGlobalScale_md)
    cmds.setAttr('%s.operation' % upLegDistGlobalScale_md, 2)
    
    cmds.connectAttr('%s.distance' % lowLegDist['shape'], '%s.input1X' % lowLegDistGlobalScale_md)
    cmds.setAttr('%s.operation' % lowLegDistGlobalScale_md, 2)
    
    if globalScaleAttr:
        cmds.connectAttr(globalScaleAttr, '%s.input2X' % legDistGlobalScale_md )
        cmds.connectAttr(globalScaleAttr, '%s.input2X' % upLegDistGlobalScale_md )
        cmds.connectAttr(globalScaleAttr, '%s.input2X' % lowLegDistGlobalScale_md )
    else:
        cmds.setAttr('%s.input2X' % legDistGlobalScale_md, 1)
        cmds.setAttr('%s.input2X' % upLegDistGlobalScale_md, 1)
        cmds.setAttr('%s.input2X' % lowLegDistGlobalScale_md, 1)
        
    upLegLength = math.fabs(cmds.getAttr('%s.tx' % resultChain[1]))
    lowLegLength = math.fabs(cmds.getAttr('%s.tx' % resultChain[2]))
    
    cmds.connectAttr('%s.outputX' % extendGlobalScale_md, '%s.input1D[0]' % extend_pma)
    cmds.setAttr('%s.input1D[1]' % extend_pma, upLegLength + lowLegLength)
    
    cmds.connectAttr('%s.output1D' % extend_pma, '%s.input1X' % squash_md)
    cmds.setAttr('%s.input2X' % squash_md, upLegLength + lowLegLength)
    cmds.setAttr('%s.operation' % squash_md, 2)
    
    cmds.connectAttr('%s.outputX' % legDistGlobalScale_md, '%s.input1X' % stretch_md)
    cmds.setAttr('%s.input2X' % stretch_md, upLegLength + lowLegLength)
    cmds.setAttr('%s.operation' % stretch_md, 2)
    
    cmds.connectAttr('%s.outputX' % legDistGlobalScale_md, '%s.firstTerm' % stretch_cond)
    cmds.connectAttr('%s.output1D' % extend_pma, '%s.secondTerm' % stretch_cond)
    cmds.connectAttr('%s.outputX' % stretch_md, '%s.colorIfTrueR' % stretch_cond)
    cmds.connectAttr('%s.outputX' % squash_md, '%s.colorIfFalseR' % stretch_cond)
    cmds.setAttr('%s.operation' % stretch_cond, 2)
    
    cmds.connectAttr('%s.outColorR' % stretch_cond, '%s.input1X' % upLegStretch_md)
    cmds.setAttr('%s.input2X' % upLegStretch_md, upLegLength)
    
    cmds.connectAttr('%s.outColorR' % stretch_cond, '%s.input1X' % lowLegStretch_md)
    cmds.setAttr('%s.input2X' % lowLegStretch_md, lowLegLength)
    
    cmds.connectAttr('%s.stretch' % ikFootCtrl, '%s.blender' % upLegStretchAmount_bc)
    cmds.connectAttr('%s.outputX' % upLegStretch_md, '%s.color1R' % upLegStretchAmount_bc)
    cmds.setAttr('%s.color2R' % upLegStretchAmount_bc, upLegLength)
    
    cmds.connectAttr('%s.stretch' % ikFootCtrl, '%s.blender' % lowLegStretchAmount_bc)
    cmds.connectAttr('%s.outputX' % lowLegStretch_md, '%s.color1R' % lowLegStretchAmount_bc)
    cmds.setAttr('%s.color2R' % lowLegStretchAmount_bc, lowLegLength)
    
    cmds.connectAttr('%s.pin' % ikFootCtrl, '%s.blender' % upLegPinAmount_bc)
    cmds.connectAttr('%s.outputX' % upLegDistGlobalScale_md, '%s.color1R' % upLegPinAmount_bc)
    cmds.connectAttr('%s.outputR' % upLegStretchAmount_bc, '%s.color2R' % upLegPinAmount_bc)
    
    cmds.connectAttr('%s.pin' % ikFootCtrl, '%s.blender' % lowLegPinAmount_bc)
    cmds.connectAttr('%s.outputX' % lowLegDistGlobalScale_md, '%s.color1R' % lowLegPinAmount_bc)
    cmds.connectAttr('%s.outputR' % lowLegStretchAmount_bc, '%s.color2R' % lowLegPinAmount_bc)
    
    if side == 'lf':
        upLegPinAmount_uc = cmds.createNode('unitConversion', name='%s_upLegPinAmount_uc')
        cmds.setAttr('%s.conversionFactor' % upLegPinAmount_uc, -1)
        cmds.connectAttr('%s.outputR' % upLegPinAmount_bc, '%s.input' % upLegPinAmount_uc)
        cmds.connectAttr('%s.output' % upLegPinAmount_uc, '%s.tx' % ikChain[1])
        
        lowLegPinAmount_uc = cmds.createNode('unitConversion', name='%s_lowLegPinAmount_uc')
        cmds.setAttr('%s.conversionFactor' % lowLegPinAmount_uc, -1)
        cmds.connectAttr('%s.outputR' % lowLegPinAmount_bc, '%s.input' % lowLegPinAmount_uc)
        cmds.connectAttr('%s.output' % lowLegPinAmount_uc, '%s.tx' % ikChain[2])
    else:  
        cmds.connectAttr('%s.outputR' % upLegPinAmount_bc, '%s.tx' % ikChain[1])
        cmds.connectAttr('%s.outputR' % lowLegPinAmount_bc, '%s.tx' % ikChain[2])
    
    
    ############################################################################################################################# Twist extration
    upLegNonRoll = nonRoll.build(joint=resultChain[0], name='%s_upLeg' % side)
    cmds.parent(upLegNonRoll['main_grp'], const)
    
    lowLegNonRoll = nonRoll.build(joint=resultChain[1], name='%s_lowLeg' % side)
    cmds.parent(lowLegNonRoll['main_grp'], upLegNonRoll['nonRoll'])
    
    ankleNonRoll = nonRoll.build(joint=resultChain[2], name='%s_ankle' % side)
    cmds.parent(ankleNonRoll['main_grp'], resultChain[1])
    
    
    ############################################################################################################################# Bendy leg
    bendGrp = cmds.group(empty=1, name='%s_leg_bend_grp' % side)
    cmds.parent(bendGrp, root)
    cmds.connectAttr('%s.bendy_ctrls' % settingsCtrl, '%s.visibility' % bendGrp)
    
    # Knee ctrl
    bendyKneeCtrl = controls.squareCtrl(name='%s_knee_bend_ctrl' % side, axis='x', size=10)
    cmds.parent(bendyKneeCtrl, bendGrp)
    bendyKneeGrp = common.insertGroup(bendyKneeCtrl)
    bendyKneeGrp = cmds.rename(bendyKneeGrp, '%s_knee_bend_grp' % side)
    orientConstraint = cmds.orientConstraint(resultChain[0], resultChain[1], bendyKneeGrp)[0]
    cmds.setAttr('%s.interpType' % orientConstraint, 2)
    cmds.pointConstraint(resultChain[1], bendyKneeGrp)
    cmds.addAttr(settingsCtrl, longName='auto_bend', at='double', minValue=0, maxValue=1, defaultValue=0, keyable=1)
    
    # Auto / Manual knee bend
    # In
    bendyKneeInConstGrp = cmds.group(empty=1, name='%s_knee_bend_in_const_grp' % side)
    common.align(bendyKneeInConstGrp, resultChain[0])
    upLegPoints = common.pointsAlongVector(resultChain[0], resultChain[1], divisions=3)
    cmds.setAttr('%s.t' % bendyKneeInConstGrp, upLegPoints[2][0], upLegPoints[2][1], upLegPoints[2][2])
    cmds.parent(bendyKneeInConstGrp, bendGrp)
    
    bendyKneeInCtrl = controls.squareCtrl(name='%s_knee_bend_in_ctrl' % side, axis='x', size=7.5)
    common.align(bendyKneeInCtrl, bendyKneeInConstGrp)
    cmds.parent(bendyKneeInCtrl, bendyKneeInConstGrp)
    
    bendyKneeInManual = cmds.group(empty=1, name='%s_knee_bend_in_manual_targ' % side)
    common.align(bendyKneeInManual, bendyKneeInConstGrp)
    cmds.parent(bendyKneeInManual, resultChain[0])
    cmds.pointConstraint(bendyKneeCtrl, resultChain[0], bendyKneeInManual)
    cmds.pointConstraint(bendyKneeCtrl, bendyKneeInManual, e=1, w=2.0)
    
    bendyKneeInAuto = cmds.group(empty=1, name='%s_knee_bend_in_auto_targ' % side)
    common.align(bendyKneeInAuto, bendyKneeInConstGrp)
    cmds.parent(bendyKneeInAuto, bendyKneeCtrl)
    
    parentConstraint = cmds.parentConstraint(bendyKneeInManual, bendyKneeInAuto, bendyKneeInConstGrp)[0]
    cmds.connectAttr('%s.auto_bend' % settingsCtrl, '%s.%sW1' % (parentConstraint, bendyKneeInAuto))
    rev = cmds.createNode('reverse', name='%s_knee_bend_auto_rev')
    cmds.connectAttr('%s.auto_bend' % settingsCtrl, '%s.inputX' % rev)
    cmds.connectAttr('%s.outputX' % rev, '%s.%sW0' % (parentConstraint, bendyKneeInManual))
    
    # out
    bendyKneeOutConstGrp = cmds.group(empty=1, name='%s_knee_bend_out_const_grp' % side)
    common.align(bendyKneeOutConstGrp, resultChain[1])
    lowLegPoints = common.pointsAlongVector(resultChain[1], resultChain[2], divisions=3)
    cmds.setAttr('%s.t' % bendyKneeOutConstGrp, lowLegPoints[1][0], lowLegPoints[1][1], lowLegPoints[1][2])
    cmds.parent(bendyKneeOutConstGrp, bendGrp)
    
    bendyKneeOutCtrl = controls.squareCtrl(name='%s_knee_bend_out_ctrl' % side, axis='x', size=7.5)
    common.align(bendyKneeOutCtrl, bendyKneeOutConstGrp)
    cmds.parent(bendyKneeOutCtrl, bendyKneeOutConstGrp)
    
    bendyKneeOutManual = cmds.group(empty=1, name='%s_knee_bend_out_manual_targ' % side)
    common.align(bendyKneeOutManual, bendyKneeOutConstGrp)
    cmds.parent(bendyKneeOutManual, resultChain[1])
    cmds.pointConstraint(bendyKneeCtrl, resultChain[2], bendyKneeOutManual)
    cmds.pointConstraint(bendyKneeCtrl, bendyKneeOutManual, e=1, w=2.0)
    
    bendyKneeOutAuto = cmds.group(empty=1, name='%s_knee_bend_out_auto_targ' % side)
    common.align(bendyKneeOutAuto, bendyKneeOutConstGrp)
    cmds.parent(bendyKneeOutAuto, bendyKneeCtrl)
    
    parentConstraint = cmds.parentConstraint(bendyKneeOutManual, bendyKneeOutAuto, bendyKneeOutConstGrp)[0]
    cmds.connectAttr('%s.auto_bend' % settingsCtrl, '%s.%sW1' % (parentConstraint, bendyKneeOutAuto))
    rev = cmds.createNode('reverse', name='%s_knee_bend_auto_rev')
    cmds.connectAttr('%s.auto_bend' % settingsCtrl, '%s.inputX' % rev)
    cmds.connectAttr('%s.outputX' % rev, '%s.%sW0' % (parentConstraint, bendyKneeOutManual))
    
    # Hip out
    bendyHipConstGrp = cmds.group(empty=1, name='%s_hip_bend_const_grp' % side)
    common.align(bendyHipConstGrp, resultChain[0])
    cmds.parent(bendyHipConstGrp, bendGrp)
    
    bendyHipCtrl = controls.squareCtrl(name='%s_hip_bend_ctrl' % side, axis='x', size=7.5)
    common.align(bendyHipCtrl, bendyHipConstGrp)
    cmds.parent(bendyHipCtrl, bendyHipConstGrp)
    cmds.pointConstraint(bendyKneeCtrl, resultChain[0], bendyHipConstGrp)
    cmds.pointConstraint(bendyKneeCtrl, bendyHipConstGrp, e=1, w=0.5)
    cmds.orientConstraint(resultChain[0], bendyHipConstGrp)
    
    # Ankle in
    bendyAnkleConstGrp = cmds.group(empty=1, name='%s_ankle_bend_const_grp' % side)
    common.align(bendyAnkleConstGrp, resultChain[1])
    cmds.parent(bendyAnkleConstGrp, bendGrp)
    
    bendyAnkleCtrl = controls.squareCtrl(name='%s_ankle_bend_ctrl' % side, axis='x', size=7.5)
    common.align(bendyAnkleCtrl, bendyAnkleConstGrp)
    cmds.parent(bendyAnkleCtrl, bendyAnkleConstGrp)
    cmds.pointConstraint(bendyKneeCtrl, resultChain[2], bendyAnkleConstGrp)
    cmds.pointConstraint(bendyKneeCtrl, bendyAnkleConstGrp, e=1, w=0.5)
    cmds.orientConstraint(resultChain[1], bendyAnkleConstGrp)
    
        
    ############################################################################################################################# Curve segments
    defJnts_grp = cmds.group(empty=1, name='%s_leg_defJnts_grp' % side)
    cmds.parent(defJnts_grp, root)
    
    # up leg
    upLegSeg = cmds.group(empty=1, name='%s_upLeg_segment_grp' % side)
    cmds.parent(upLegSeg, defJnts_grp)
    cmds.setAttr('%s.inheritsTransform' % upLegSeg, 0)
    
    crv = curve.curveBetweenNodes(start=upLeg, end=lowLeg, name='%s_upLeg' % side)
    cmds.parent(crv, const)
    
    mpNodes = curve.nodesAlongCurve(crv=crv, numNodes=twistJoints, name='%s_upLeg' % side, upNode=upLegNonRoll['nonRoll'])
    cmds.parent(mpNodes['grps'], upLegSeg)
    
    roll_uc = cmds.createNode('unitConversion', name='%s_upLeg_roll_uc' % side)
    cmds.setAttr('%s.conversionFactor' % roll_uc, 1.0)
    cmds.connectAttr('%s.rotateX' % lowLegNonRoll['info'], '%s.input' % roll_uc)
    
    kneeRoll_uc = cmds.createNode('unitConversion', name='%s_upLeg_kneeRoll_uc' % side)
    cmds.setAttr('%s.conversionFactor' % kneeRoll_uc, 1.0)
    cmds.connectAttr('%s.rotateX' % bendyKneeCtrl, '%s.input' % kneeRoll_uc)
    
    roll_pma = cmds.createNode('plusMinusAverage', name='%s_upLeg_roll_pma' % side)
    cmds.connectAttr('%s.output' % roll_uc, '%s.input1D[0]' % roll_pma)
    cmds.connectAttr('%s.output' % kneeRoll_uc, '%s.input1D[1]' % roll_pma)
    
    for i in range(len(mpNodes['mpNodes'])):
        # Create child Joint
        cmds.select(clear=1)
        j = cmds.joint(name='%s_upLeg_%s_defJnt' % (side, i))
        common.align(j, mpNodes['grps'][i])
        cmds.parent(j, mpNodes['grps'][i])
        
        totalRoll_uc = cmds.createNode('unitConversion', name='%s_upLeg_totalRoll_%s_uc' % (side, i+1))
        if side == 'lf':
            cmds.setAttr('%s.conversionFactor' % totalRoll_uc,  (1.0 / (twistJoints-1) * i)*-1)
        else:
            cmds.setAttr('%s.conversionFactor' % totalRoll_uc,  1.0 / (twistJoints-1) * i)
        cmds.connectAttr('%s.output1D' % roll_pma, '%s.input' % totalRoll_uc)
        cmds.connectAttr('%s.output' % totalRoll_uc, '%s.frontTwist' % mpNodes['mpNodes'][i])
    
    upLegCrvJnts = curve.bindCurve(crv=crv)
    cmds.parent(upLegCrvJnts[0], resultChain[0])
    cmds.parent(upLegCrvJnts[1], bendyHipCtrl)
    cmds.parent(upLegCrvJnts[2], bendyKneeInCtrl)
    cmds.parent(upLegCrvJnts[3], bendyKneeCtrl)
    
    # low leg
    lowLegSeg = cmds.group(empty=1, name='%s_lowLeg_segment_grp' % side)
    cmds.parent(lowLegSeg, defJnts_grp)
    cmds.setAttr('%s.inheritsTransform' % lowLegSeg, 0)
    
    crv = curve.curveBetweenNodes(start=lowLeg, end=ankle, name='%s_lowLeg' % side)
    cmds.parent(crv, const)
    
    mpNodes = curve.nodesAlongCurve(crv=crv, numNodes=twistJoints, name='%s_lowLeg' % side, upNode=resultChain[1])
    cmds.parent(mpNodes['grps'], lowLegSeg)
    
    for i in range(len(mpNodes['mpNodes'])):
        # Create child Joint
        cmds.select(clear=1)
        j = cmds.joint(name='%s_lowLeg_%s_defJnt' % (side, i))
        common.align(j, mpNodes['grps'][i])
        cmds.parent(j, mpNodes['grps'][i])
        
        roll_uc = cmds.createNode('unitConversion', name='%s_lowLeg_roll_%s_uc' % (side, i+1))
        cmds.setAttr('%s.conversionFactor' % roll_uc, 1.0 / (twistJoints-1) * i)
        cmds.connectAttr('%s.rotateX' % ankleNonRoll['info'], '%s.input' % roll_uc)
        
        kneeRoll_uc = cmds.createNode('unitConversion', name='%s_lowLeg_kneeRoll_%s_uc' % (side, i+1))
        cmds.setAttr('%s.conversionFactor' % kneeRoll_uc, 1.0 - (1.0 / (twistJoints-1) * i))
        cmds.connectAttr('%s.rotateX' % bendyKneeCtrl, '%s.input' % kneeRoll_uc)
        
        roll_pma = cmds.createNode('plusMinusAverage', name='%s_lowLeg_roll_%s_pma' % (side, i+1))
        cmds.connectAttr('%s.output' % roll_uc, '%s.input1D[0]' % roll_pma)
        cmds.connectAttr('%s.output' % kneeRoll_uc, '%s.input1D[1]' % roll_pma)
        
        totalRoll_uc = cmds.createNode('unitConversion', name='%s_lowLeg_totalRoll_%s_uc' % (side, i+1))
        if side == 'lf':
            cmds.setAttr('%s.conversionFactor' % totalRoll_uc, -1.0)
        else:
            cmds.setAttr('%s.conversionFactor' % totalRoll_uc, 1.0)
        cmds.connectAttr('%s.output1D' % roll_pma, '%s.input' % totalRoll_uc)
        cmds.connectAttr('%s.output' % totalRoll_uc, '%s.frontTwist' % mpNodes['mpNodes'][i])
    
    lowLegCrvJnts = curve.bindCurve(crv=crv)
    cmds.parent(lowLegCrvJnts[0], bendyKneeCtrl)
    cmds.parent(lowLegCrvJnts[1], bendyKneeOutCtrl)
    cmds.parent(lowLegCrvJnts[2], bendyAnkleCtrl)
    cmds.parent(lowLegCrvJnts[3], resultChain[2])
    
    ############################################################################################################################################## CLEANUP
    if cleanup:
        cmds.setAttr('%s.visibility' % const, 0)
        common.attrCtrl(lock=True, keyable=False, channelBox=False, nodeList=[const, bendyKneeCtrl], attrList=['visibility'])
        
        common.attrCtrl(lock=True, keyable=False, channelBox=False,
                        nodeList=[fkUpLegCtrl, fkLowLegCtrl, fkFootCtrl],
                        attrList=['visibility', 'tx', 'ty', 'tz', 'sx', 'sy', 'sz'])
        
        common.attrCtrl(lock=True, keyable=False, channelBox=False,
                        nodeList=[ikFootCtrl,],
                        attrList=['visibility', 'sx', 'sy', 'sz'])
        
        common.attrCtrl(lock=True, keyable=False, channelBox=False,
                        nodeList=[ikKneeCtrl, bendyHipCtrl, bendyKneeInCtrl, bendyKneeOutCtrl, bendyAnkleCtrl],
                        attrList=['visibility', 'sx', 'sy', 'sz'])
        
    ############################################################################################################################################## RETURN
    returnDict={
                'upLeg_fk_ctrl':fkUpLegCtrl,
                'lowLeg_fk_ctrl':fkLowLegCtrl,
                'foot_fk_ctrl':fkFootCtrl,
                'foot_ik_ctrl':ikFootCtrl,
                'knee_ik_ctrl': ikKneeCtrl,
                'settings':settingsCtrl,
                'knee_bend_ctrl':bendyKneeCtrl,
                'hip_bend_ctrl':bendyHipCtrl,
                'knee_in_bend_ctrl':bendyKneeInCtrl,
                'knee_out_bend_ctrl':bendyKneeInCtrl,
                'root':root,
                'const':const
                }
    
    return returnDict
        
        
        
        
        
        
        
        
        
        
Ejemplo n.º 5
0
def buildFoot(name='', numJoints=5, side='rt', blendAttr=None, cleanup=1):
    
    # main ik group
    grp = cmds.group(empty=1, name=(name+'_ik_grp'))
    noTouch_grp = cmds.group(empty=1, name=(name+'_ik_noTouch_grp'))
    cmds.parent(noTouch_grp, grp)
    
    # Create ik nurbsPlane
    ikPlane = cmds.nurbsPlane(u=7, v=7, name=(name+'_ikPlane'), axis=[0,1,0])[0]
    cmds.parent(ikPlane, noTouch_grp)
    
    # Create ik follicles
    ikFollicles=[]
    for i in range(numJoints):
        f = rivet.build(mesh=ikPlane, paramV=(1.0/(numJoints-1) * i), paramU=0.5, name=(name + '_ik_' + str(i+1)))
        ikFollicles.append(f)
        cmds.parent(f, noTouch_grp)
        
    # Create IK Control
    ##ikCtrl = cmds.circle(name=(name + '_ik_bend_ctrl'))[0]
    ikCtrl = controls.circleBumpCtrl(radius=5.0, name=(name + '_ik_bend_ctrl'), axis='x')[0]
    cmds.parent(ikCtrl, grp)
    common.insertGroup(ikCtrl)
    cmds.addAttr(ikCtrl, ln='falloff', at='double', keyable=1, minValue=0.01)
        
    # Create deformers
    ikBend1 = cmds.nonLinear(ikPlane, type='bend')
    ikBend1_bend = cmds.rename(ikBend1[0], name+'_ikBend_1')
    ikBend1_handle = cmds.rename(ikBend1[1], name+'_ikBend_1_handle')
    handle_grp = common.insertGroup(ikBend1_handle)
    driven_grp = common.insertGroup(ikBend1_handle, 'driven')
    cmds.xform(ikBend1_handle, ws=0, rotation=(90, 0, 90))
    cmds.parent(handle_grp, noTouch_grp)
    
    uc = cmds.createNode('unitConversion', name=(name + '_ikBend_1_falloff_uc'))
    cmds.connectAttr(ikCtrl+'.falloff', uc+'.input')
    cmds.setAttr(uc+'.conversionFactor', -1.0)
    
    md = cmds.createNode('multiplyDivide', name=(name+'_ikBend_1_curvature_md'))
    cmds.setAttr(md+'.operation', 2)
    cmds.connectAttr(ikCtrl+'.rx', md+'.input1X')
    cmds.connectAttr(ikCtrl+'.falloff', md+'.input2X')
    
    cmds.connectAttr(md+'.outputX', ikBend1_bend+'.curvature')
    cmds.connectAttr(uc+'.output', ikBend1_bend+'.lowBound')
    cmds.setAttr(ikBend1_bend+'.highBound', 0.0)
    cmds.connectAttr(ikCtrl+'.tx', driven_grp+'.tx')
    cmds.connectAttr(ikCtrl+'.tz', driven_grp+'.tz')
    cmds.connectAttr(ikCtrl+'.ry', driven_grp+'.ry')
    
    # Create IK toe Control
    ##ikToeCtrl = cmds.circle(name=(name + '_ik_toe_ctrl'))[0]
    ikToeCtrl = controls.circleBumpCtrl(radius=3.0, name=(name + '_ik_toe_ctrl'), axis='x')[0]
    cmds.parent(ikToeCtrl, ikCtrl)
    common.insertGroup(ikToeCtrl)
        
    # Create deformers
    ikToeBend1 = cmds.nonLinear(ikPlane, type='bend')
    ikToeBend1_bend = cmds.rename(ikToeBend1[0], name+'_ikToeBend_1')
    ikToeBend1_handle = cmds.rename(ikToeBend1[1], name+'_ikToeBend_1_handle')
    cmds.parent(ikToeBend1_handle, driven_grp)
    cmds.xform(ikToeBend1_handle, ws=0, rotation=(90, 0, 90))
    
    uc = cmds.createNode('unitConversion', name=(name + '_ikToeBend_1_curvature_uc'))
    cmds.connectAttr(ikToeCtrl+'.rx', uc+'.input')
    cmds.setAttr(uc+'.conversionFactor', -57.296)
    
    md = cmds.createNode('multiplyDivide', name=(name+'_ikToeBend_1_curvature_md'))
    cmds.setAttr(md+'.operation', 2)
    cmds.connectAttr(uc+'.output', md+'.input1X')
    cmds.connectAttr(ikCtrl+'.falloff', md+'.input2X')
    
    cmds.connectAttr(md+'.outputX', ikToeBend1_bend+'.curvature')
    cmds.connectAttr(ikCtrl+'.falloff', ikToeBend1_bend+'.highBound')
    cmds.setAttr(ikToeBend1_bend+'.lowBound', 0.0)
    
    # main fk group
    fk_grp = cmds.group(empty=1, name=(name+'_fk_grp'))
    fk_noTouch_grp = cmds.group(empty=1, name=(name+'_fk_noTouch_grp'))
    cmds.parent(fk_noTouch_grp, fk_grp)
    
    # fk nurbsPlane
    fkPlane = cmds.nurbsPlane(u=7, v=7, name=(name+'_fkPlane'), axis=[0,1,0])[0]
    cmds.parent(fkPlane, fk_noTouch_grp)
    
    # Create fk follicles
    fkFollicles=[]
    for i in range(numJoints):
        f = rivet.build(mesh=fkPlane, paramV=(1.0/(numJoints-1) * i), paramU=0.5, name=(name + '_fk_' + str(i+1)))
        fkFollicles.append(f)
        cmds.parent(f, fk_noTouch_grp)
    
    # Create FK Control
    ##fkCtrl = cmds.circle(name=(name + '_fk_bend_ctrl'))[0]
    fkCtrl = controls.circleBumpCtrl(radius=4.0, name=(name + '_fk_bend_ctrl'), axis='x')[0]
    cmds.parent(fkCtrl, fk_grp)
    common.insertGroup(fkCtrl)
    cmds.addAttr(fkCtrl, ln='falloff', at='double', keyable=1, minValue=0.01)
        
    # Create fk deformers
    fkBend1 = cmds.nonLinear(fkPlane, type='bend')
    fkBend1_bend = cmds.rename(fkBend1[0], name+'_fkBend_1')
    fkBend1_handle = cmds.rename(fkBend1[1], name+'_fkBend_1_handle')
    handle_grp = common.insertGroup(fkBend1_handle)
    driven_grp = common.insertGroup(fkBend1_handle, 'driven')
    cmds.xform(fkBend1_handle, ws=0, rotation=(90, 0, 90))
    cmds.parent(handle_grp, fk_noTouch_grp)
    
    uc = cmds.createNode('unitConversion', name=(name + '_fkBend_1_curvature_uc'))
    cmds.connectAttr(fkCtrl+'.rx', uc+'.input')
    cmds.setAttr(uc+'.conversionFactor', -57.296)
    
    md = cmds.createNode('multiplyDivide', name=(name+'_fkBend_1_curvature_md'))
    cmds.setAttr(md+'.operation', 2)
    cmds.connectAttr(uc+'.output', md+'.input1X')
    cmds.connectAttr(fkCtrl+'.falloff', md+'.input2X')
    
    cmds.connectAttr(md+'.outputX', fkBend1_bend+'.curvature')
    cmds.connectAttr(fkCtrl+'.falloff', fkBend1_bend+'.highBound')
    cmds.setAttr(fkBend1_bend+'.lowBound', 0.0)
    cmds.connectAttr(fkCtrl+'.tx', driven_grp+'.tx')
    cmds.connectAttr(fkCtrl+'.tz', driven_grp+'.tz')
    cmds.connectAttr(fkCtrl+'.ry', driven_grp+'.ry')
    
    # Set up blending attribute
    ikAttr=None
    fkAttr=None
    if not blendAttr:
        cmds.addAttr(grp, longName='state', at='enum', enumName='ik:fk', keyable=True )
        stateRev = cmds.createNode('reverse', name=(name+'_state_rev'))
        cmds.connectAttr(grp+'.state', stateRev+'.inputX')
        fkAttr=(grp+'.state')
        ikAttr=(stateRev+'.outputX')
    else:
        fkAttr=blendAttr
        # Check whether a reverse node is connected to blendAttr
        revCheck = cmds.listConnections(fkAttr, type='reverse')
        if revCheck:
            ikAttr = revCheck[0]+'.outputX'
        else:
            stateRev = cmds.createNode('reverse', name=(name+'_state_rev'))
            cmds.connectAttr(fkAttr, stateRev+'.inputX') 
            ikAttr=(stateRev+'.outputX')
    
    joints_grp = cmds.group(empty=1, name=(name+'_joints_grp'))
    cmds.parent(joints_grp, grp)
    
    # Build joints
    for i in range(numJoints):
        cmds.select(joints_grp)
        pos = cmds.xform(ikFollicles[i], q=1, t=1, ws=1)
        j = cmds.joint(name=(name+'_'+str(i+1)+'_jnt'), p=pos)
        #Constrain between follicles
        pc = cmds.parentConstraint([ikFollicles[i], fkFollicles[i]], j)[0]
        weightAliasList = [str(w) for w in cmds.parentConstraint(j, q=1, weightAliasList=1)]
        cmds.connectAttr(ikAttr, pc+'.'+weightAliasList[0])
        cmds.connectAttr(fkAttr, pc+'.'+weightAliasList[1])
        
    if cleanup:
        common.attrCtrl(lock=True, keyable=False, channelBox=False, nodeList=[ikCtrl, fkCtrl], attrList=['ty', 'rz', 'sx', 'sy', 'sz', 'visibility'])
        common.attrCtrl(lock=True, keyable=False, channelBox=False, nodeList=[ikToeCtrl], attrList=['tx', 'ty', 'tz', 'ry', 'rz', 'sx', 'sy', 'sz', 'visibility'])
        
        

        
#buildFoot()