def _makeRig(self, namer): jntCnt = self.options.getValue('numJnts') ikCtlCnt = self.options.getValue('numIkCtls') jntToks = self.__getToks(bndJnts=True) ctlToks = self.__getToks(ikCtls=True) bndJnts = [namer(t, r='bnd') for t in jntToks] MC.makeIdentity(bndJnts, apply=True, r=1, t=1, s=1) namer.setTokens(r='fk') fkCtls = [namer(t, r='fk') for t in jntToks[1:]] fkCtls = control.setupFkCtls(bndJnts[1:], fkCtls, jntToks[1:], namer) for ctl in fkCtls: control.setLockTag(ctl, uk=['rx', 'ry', 'rz']) for i, tok in enumerate(jntToks): self.setPlugNode(tok, bndJnts[i]) namer.setTokens(r='ik') ikJnts = utils.dupJntList(bndJnts[1:], jntToks[1:], namer) MC.setAttr('%s.v' % ikJnts[0], 0) ikCtls = [] for tok in ctlToks: n = namer(tok, r='ik') utils.insertNodeAbove(n) control.setLockTag(n, uk=['r', 't']) ikCtls.append(n) self.setPlugNode(tok, n) #doubling the cvs on the end allows us to build a curve with only 2 controls, #but causes popping otherwise. Only use if needed doubleEndPoints = False if ikCtlCnt == 1: doubleEndPoints = True crv = curveFromNodes(ikCtls, name=namer('ikspline_crv'), doubleEndPoints=doubleEndPoints ) srf = surfaceFromNodes(ikCtls, name=namer('ikspline_srf'), doubleEndPoints=doubleEndPoints) bindControlsToShape(ikCtls, crv, doubleEndPoints=doubleEndPoints) bindControlsToShape(ikCtls, srf, doubleEndPoints=doubleEndPoints) ikNode = setupSpineIkNode(ikCtls, ikJnts, nodeName='splinik', namer=namer, crv=crv, surf=srf) self.setNodeCateogry(ikNode, 'dnt') MC.setAttr("%s.v" % ikNode, 0) #parent the fk control to the ik control MC.parent(fkCtls[0], ikCtls[0]) utils.fixInverseScale(fkCtls[0]) #constrain the pelvis jnt to the first ik control MC.parentConstraint(ikCtls[0], bndJnts[0]) MC.scaleConstraint(ikCtls[0], bndJnts[0]) #tag this node so the master connect the uniform scale core.Root.tagInputScaleAttr(ikNode, 'inputScaleAmt') MC.addAttr(ikCtls[-1], ln='fkIk', dv=1, k=1, min=0, max=1) MC.addAttr(ikCtls[-1], ln='stretchAmt', dv=0, k=1, min=0, max=1) MC.addAttr(ikCtls[-1], ln='evenStretchAmt', dv=0, k=1, min=0, max=1) control.setLockTag(ikCtls[-1], uk=['fkIk', 'stretchAmt', 'evenStretchAmt']) MC.connectAttr('%s.stretchAmt' % ikCtls[-1], '%s.stretchAmt' % ikNode) MC.connectAttr('%s.evenStretchAmt' % ikCtls[-1], '%s.evenStretchAmt' % ikNode) #parent the ikCtls parentToFirst = [] parentToLast = [] numParentedCtlsPerSide = (ikCtlCnt/2)-1 parentToFirst = ikCtls[1:1+numParentedCtlsPerSide] parentToFirst = ikCtls[-1:-1-numParentedCtlsPerSide- ikCtlCnt % 2] _logger.debug('parentToFirst: %s' % parentToFirst) _logger.debug('parentToLast: %s' % parentToLast) for node in parentToFirst: zero = MC.listRelatives(node, parent=1)[0] MC.parent(zero, ikCtls[0]) for node in parentToLast: zero = MC.listRelatives(node, parent=1)[0] MC.parent(zero, ikCtls[-1]) ikReverse = utils.blendJointChains(fkCtls, ikJnts, bndJnts[1:], '%s.fkIk' % ikCtls[-1], namer) for ctl in fkCtls: MC.connectAttr('%s.outputX' % (ikReverse), '%s.v' % ctl) for ctl in ikCtls[1:-1]: MC.connectAttr('%s.fkIk' % (ikCtls[-1]), '%s.v' % ctl)
def setupSpineIkNode(ctlList, jntList, surf=None, crv=None, nodeName='beings_splineik', namer=None): """ Create an ik spline system using controls in the ctlList that will drive jnts in jntList """ if not namer: namer = utils.Namer('char', 'cn', 'spine') if not surf: surf = surfaceFromNodes(ctlList) surf = getShape(surf) if not crv: crv = curveFromNodes(ctlList) crv = getShape(crv) ikNode = MC.createNode('transform', name=namer(nodeName)) MC.parent(MC.listRelatives(surf, parent=1)[0], ikNode) MC.parent(MC.listRelatives(crv, parent=1)[0], ikNode) namer.setTokens(r='ik') names = ['stretch_%s' % ascii_lowercase[i] for i in range(len(jntList))] stretchJnts = utils.dupJntList(jntList, names, namer) #rebuild the curve so that we get more even parameterization for 'even stretch' #joints. Use a 7 degree curve so we can build with a single span evenStretchCrv = MC.rebuildCurve(MC.listRelatives(crv, parent=1)[0], ch=1, rpo=0, rt=0, end=1, kr=2, kcp=0, kep=1, kt=0, s=1, d=7, tol=0.01)[0] evenStretchCrv = MC.rename(evenStretchCrv, "%s_evenstretch" % crv) MC.parent(evenStretchCrv, ikNode) evenStretchCrv = getShape(evenStretchCrv) nodes = {'posi':[], 'cps': [], 'posiUp':[], 'xform':[], 'xformUp':[]} #for each joint, get the param at the rebuilt curve. Use this position to get #the closest point on the surface, then get the u and v values at that surface #point. for i, jnt in enumerate(stretchJnts): suff = ascii_lowercase[i] #get point on rebuild curve near each jnt poci = MC.createNode('pointOnCurveInfo', n='%s_%s_evenstretch_poci' % (ikNode, suff)) MC.connectAttr("%s.worldSpace[0]" % evenStretchCrv, '%s.ic' % poci) MC.setAttr('%s.pr' % poci, closestParamOnCurve(jnt, evenStretchCrv)) #get closest point on surface cps = MC.createNode("closestPointOnSurface", n='%s_%s_evenstretch_cps' % (ikNode, suff)) MC.connectAttr("%s.worldSpace[0]" % surf, '%s.is' % cps) MC.connectAttr("%s.p" % poci, "%s.ip" % cps) nodes['cps'].append(cps) MC.addAttr(ikNode, ln='evenStretchAmt', min=0, max=1, k=1) for i, jnt in enumerate(stretchJnts): #create a point on surface info node at each point suff = ascii_lowercase[i] posi = MC.createNode('pointOnSurfaceInfo', n='%s_%s_posi' % (ikNode, suff)) posiUp = MC.createNode('pointOnSurfaceInfo', n='%s_%s_up_posi' % (ikNode, suff)) MC.connectAttr('%s.worldSpace[0]' % surf, '%s.is' % posi) MC.connectAttr('%s.worldSpace[0]' % surf, '%s.is' % posiUp) u, v = closestParamOnSurface(jnt, surf) for node in [posi, posiUp]: blender = MC.createNode("blendColors", name='%s_%s_evenstretch_blc' % (ikNode, suff)) MC.connectAttr('%s.evenStretchAmt' % ikNode, '%s.blender' % blender) #as the evenStretchAmt increases, shift towards the u value of the even stretch crv MC.connectAttr("%s.u" % nodes['cps'][i], "%s.c1r" % blender) MC.setAttr("%s.c2r" % blender, u) MC.connectAttr("%s.opr" % blender, '%s.u' % node) MC.setAttr('%s.v' % posi, v) MC.setAttr('%s.v' % posiUp, v-.25) posXform = MC.createNode("transform", n='%s_%s_grp' % (ikNode, suff)) upXform = MC.createNode("transform", n='%s_%s_up_grp' % (ikNode, suff)) MC.parent(posXform, ikNode) MC.parent(upXform, ikNode) MC.connectAttr("%s.p" % posi, "%s.t" % posXform) MC.connectAttr("%s.p" % posiUp, "%s.t" % upXform) MC.pointConstraint(posXform, jnt) utils.fixJointConstraints(posXform) nodes['posi'].append(posi) nodes['posiUp'].append(posiUp) nodes['xform'].append(posXform) nodes['xformUp'].append(upXform) #now that all the xforms are created, aim them at each other and #measure the start stretch distance MC.addAttr(ikNode, ln='inputScaleAmt', dv=1, k=1) for i in range(len(stretchJnts)-1): suff = ascii_lowercase[i] nextSuff = ascii_lowercase[i+1] dst = MC.createNode('distanceBetween', n='%s_%s_to_%s_dist' % \ (ikNode,suff, nextSuff)) MC.connectAttr("%s.p" % nodes['posi'][i], '%s.p1' % dst) MC.connectAttr("%s.p" % nodes['posi'][i+1], '%s.p2' % dst) MC.addAttr(ikNode, ln = "origDistToNext_%s" % suff, h=False, dv=MC.getAttr("%s.d" % dst)) stretchMdn = MC.createNode("multiplyDivide", n='%s_%s_stretch_mdn' % (ikNode, suff)) MC.connectAttr('%s.d' % dst, '%s.input1X' % stretchMdn) MC.connectAttr('%s.origDistToNext_%s' % (ikNode, suff), '%s.input2X' % stretchMdn) MC.setAttr('%s.operation' % stretchMdn, 2) stretchSclMdn = MC.createNode("multiplyDivide", n='%s_%s_stretch_scl_mdn' % (ikNode, suff)) MC.setAttr('%s.operation' % stretchSclMdn, 2) MC.connectAttr('%s.outputX' % stretchMdn, '%s.input1X' % stretchSclMdn) MC.connectAttr('%s.inputScaleAmt' % ikNode, '%s.input2X' % stretchSclMdn) MC.addAttr(ikNode, ln = "stretchAmt_%s" % suff, k=1) MC.connectAttr('%s.outputX' % stretchSclMdn, '%s.stretchAmt_%s' \ % (ikNode, suff)) #connect stretch amount to joint scale MC.connectAttr('%s.stretchAmt_%s' % (ikNode, suff), '%s.sy' % stretchJnts[i]) #aim the xforms MC.aimConstraint(nodes['xform'][i+1], nodes['xform'][i], aimVector=[0,1,0], upVector=[1,0,0], worldUpType='object', worldUpObject=nodes['xformUp'][i]) MC.orientConstraint(nodes['xform'][i], stretchJnts[i]) utils.fixJointConstraints(stretchJnts[i]) utils.fixJointConstraints(nodes['xform'][i]) MC.orientConstraint(ctlList[-1], stretchJnts[-1]) utils.fixJointConstraints(stretchJnts[-1]) nsJnts, nsPosJnts, esUps = setupIkSplineJnts(jntList, crv, surf, ikNode, namer = namer, nodeName='%s_ns' % nodeName, tipCtl = ctlList[-1]) MC.addAttr(ikNode, ln='stretchAmt', min=0, max=1, dv=0, k=1) utils.blendJointChains(nsJnts, stretchJnts, jntList, '%s.stretchAmt' % ikNode, namer) MC.setAttr("%s.v" % nsJnts[0], 0) MC.setAttr("%s.v" % stretchJnts[0], 0) return ikNode
def setupIkSplineJnts(jntList, crv, surf, ikNode, nodeName='beings_splineik', namer=None, tipCtl=None): """ Setup a splineIk system, but use a nurbs surface to control orientation. This allows full twist control along the length of the chain @param jntList: the list of original joints; they will be duplicated @param crv: the curve to use for the spline ik system @param surf: the surface to use for the twist @param namer: the namer to use for naming; a generic will be assigned if none provided @param tipCtl: a control to use for orienting the last joint. If none provided, it will be oriented to the plane """ if not namer: namer = utils.Namer('char', 'cn', 'spine') namer.setTokens(r='ik') #use the splineik node to get joints to 'slip' alone the curve. These are intermediate #joints, we're just using their position to get us a point on the nurbs surface so we #can use the surface for orientation jntNames = ['%s_pos_jnt_%s' % (nodeName, ascii_lowercase[i]) for i in range(len(jntList))] splinePosJnts = utils.dupJntList(jntList, jntNames, namer) for jnt in splinePosJnts: control.setLockTag(jnt, uu=['t', 'r']) #these are the actual joints that will be oriented and positioned correctly jntNames = ['%s_jnt_%s' % (nodeName,ascii_lowercase[i]) for i in range(len(jntList))] splineJnts = utils.dupJntList(jntList, jntNames, namer) handle, ee = MC.ikHandle(solver='ikSplineSolver', sj=splinePosJnts[0], ee=splinePosJnts[-1], curve=crv, simplifyCurve=False, parentCurve=False, createCurve=False) MC.parent(handle, ikNode) xforms = [] ups = [] for i, jnt in enumerate(splinePosJnts): dcm = MC.createNode('decomposeMatrix', n=namer('%s_splinejnt_dcm' % nodeName, alphaSuf=i)) cps = MC.createNode('closestPointOnSurface', n=namer('%s_splinejnt_cps' % nodeName, alphaSuf=i)) posi = MC.createNode('pointOnSurfaceInfo', n=namer('%s_splinejnt_posi' % nodeName, alphaSuf=i)) xform = MC.createNode('transform', n=namer('%s_splinejnt_grp' % nodeName, alphaSuf=i)) xformUp = MC.createNode('transform', n=namer('%s_splinejnt_up_grp' % nodeName, alphaSuf=i)) MC.parent(xform, ikNode) MC.parent(xformUp, ikNode) MC.connectAttr('%s.worldMatrix' % jnt, '%s.inputMatrix' % dcm) MC.connectAttr("%s.worldSpace[0]" % surf, '%s.inputSurface' % cps) MC.connectAttr("%s.outputTranslate" % dcm, "%s.ip" % cps) MC.connectAttr("%s.p" % cps, "%s.t" % xform) MC.connectAttr("%s.worldSpace[0]" % surf, '%s.inputSurface' % posi) MC.connectAttr("%s.u" % cps, "%s.u" % posi) MC.setAttr("%s.v" % cps, MC.getAttr("%s.v" % cps) + .1) MC.connectAttr("%s.p" % posi, "%s.t" % xformUp) xforms.append(xform) ups.append(xformUp) MC.pointConstraint(splinePosJnts[i], splineJnts[i]) for i in range(len(splinePosJnts)-1): MC.aimConstraint(splinePosJnts[i+1], xforms[i], aimVector=[0,1,0], upVector=[1,0,0], worldUpType='object', worldUpObject=ups[i]) utils.fixJointConstraints(xforms[i]) MC.orientConstraint(xforms[i], splineJnts[i]) utils.fixJointConstraints(splineJnts[i]) if tipCtl: MC.orientConstraint(tipCtl, splineJnts[-1]) utils.fixJointConstraints(splineJnts[-1]) MC.setAttr("%s.v" % splinePosJnts[0], 0) MC.setAttr("%s.v" % handle, 0) return (splineJnts, splinePosJnts, ups)
def _makeRig(self, namer): #gather the bind joints and fk controls that were built bndJnts = [] fkCtls = [] for tok in self.__toks[:-1]: fkCtl = namer(tok, r='fk') if not MC.objExists(fkCtl): raise RuntimeError('%s does not exist' % fkCtl) fkCtls.append(fkCtl) for tok in self.__toks: jnt = namer(tok, r='bnd') if not MC.objExists(jnt): raise RuntimeError('%s does not exist' % jnt) bndJnts.append(jnt) if tok != 'hand_tip': self.setPlugNode('bnd_%s' % tok, jnt) MC.makeIdentity(bndJnts, apply=True, r=1, t=1, s=1) ikCtl = namer('ctl', r='ik') if not MC.objExists(ikCtl): raise RuntimeError("cannot find '%s'" % ikCtl) MC.makeIdentity(ikCtl, apply=True, r=1, s=1) # o = utils.Orientation() # side = self.options.getValue('side') # if side == 'rt': # o.setAxis('aim', 'negY') # o.reorientJoints(bndJnts) # MC.setAttr('%s.rx' % ikCtl, # (MC.getAttr('%s.rx' % ikCtl) * -1)) # MC.setAttr('%s.rz' % ikCtl, # (180 + MC.getAttr('%s.rz' % ikCtl) % 360)) side = self.options.getValue('side') if side == 'rt': o = utils.Orientation() otherO = utils.Orientation() otherO.setAxis('aim', 'posX') otherO.setAxis('up', 'posY') o.setAxis('aim', 'posX') o.setAxis('up', 'negY') origOrient = MC.getAttr('%s.jointOrient' % ikCtl)[0] newOrient = o.newAngle(origOrient, origOrient=otherO) MC.setAttr('%s.jointOrient' % ikCtl, *newOrient, type='double3') fkCtls = control.setupFkCtls(bndJnts[:-1], fkCtls, self.__toks[:-1], namer) for ctl in fkCtls: control.setLockTag(ctl, uk=['r']) namer.setTokens(r='ik') ikJnts = utils.dupJntList(bndJnts, self.__toks, namer) for jnt in ikJnts: control.setLockTag(jnt, uu=['r', 't', 's']) MC.setAttr('%s.v' % ikJnts[0], 0) #keep the ik hand control rotated par = MC.createNode('transform', n='%s_zero' % ikCtl) utils.snap(ikCtl, par, orient=False) MC.parent(ikCtl, par) self.setNodeCateogry(par, 'ik') MC.addAttr(ikCtl, ln='fkIk', min=0, max=1, dv=1, k=1) fkIkRev = utils.blendJointChains(fkCtls, ikJnts[:-1], bndJnts[:-1], '%s.fkIk' % ikCtl, namer) control.setLockTag(ikCtl, uk=['t', 'r', 'fkIk']) for ctl in fkCtls: MC.connectAttr('%s.outputX' % fkIkRev, '%s.v' % ctl) ikHandle, ikEff = MC.ikHandle(sj=ikJnts[0], ee=ikJnts[2], solver='ikRPsolver', n=namer.name('ikh')) MC.parent(ikHandle, ikCtl) MC.setAttr('%s.v' % ikHandle, 0) #setup pole vec for ik ctl pv = namer('polevec', r='ik') MC.setAttr('%s.r' % pv, 0, 0, 0, type='double3') control.setLockTag(ikCtl, uk=['t']) MC.poleVectorConstraint(pv, ikHandle) MC.parent(utils.insertNodeAbove(pv), ikCtl) #orient the hand to the ik control handOrientJnt = MC.duplicate(ikJnts[2], rc=1, po=1)[0] handOrientJnt = MC.rename(handOrientJnt, namer('handorient_space', r='ik')) MC.parent(handOrientJnt, ikCtl) MC.setAttr('%s.v' % handOrientJnt, 0) MC.orientConstraint(handOrientJnt, ikJnts[2])
def _makeRig(self, namer): #gather the bind joints and fk controls that were built bndJnts = [] fkCtls = [] for tok in self.__toks[:-1]: fkCtl = namer(tok, r='fk') if not MC.objExists(fkCtl): raise RuntimeError('%s does not exist' % fkCtl) fkCtls.append(fkCtl) for tok in self.__toks: jnt = namer(tok, r='bnd') if not MC.objExists(jnt): raise RuntimeError('%s does not exist' % jnt) bndJnts.append(jnt) MC.makeIdentity(bndJnts, apply=True, r=1, t=1, s=1) for jnt in bndJnts: control.setLockTag(jnt, uu=['t', 'r', 's']) for i, tok in enumerate(self.__toks[:3]): self.setPlugNode('bnd_%s' % tok, bndJnts[i]) o = utils.Orientation() side = self.options.getValue('side') if side == 'rt': o.setAxis('aim', 'negY') o.reorientJoints(bndJnts) fkCtls = control.setupFkCtls(bndJnts[:-1], fkCtls, self.__toks[:-1], namer) for ctl in fkCtls: control.setLockTag(ctl, uk=['r']) namer.setTokens(r='ik') ikJnts = utils.dupJntList(bndJnts, self.__toks, namer) MC.setAttr('%s.v' % ikJnts[0], 0) ikCtl = namer('heel_ctl', r='ik') if not MC.objExists(ikCtl): raise RuntimeError("Cannot find '%s'" % ikCtl) MC.addAttr(ikCtl, ln='fkIk', min=0, max=1, dv=1, k=1) fkIkRev = utils.blendJointChains(fkCtls, ikJnts[:-1], bndJnts[:-1], '%s.fkIk' % ikCtl, namer) for ctl in fkCtls: MC.connectAttr('%s.outputX' % fkIkRev, '%s.v' % ctl) ikHandle, ikEff = MC.ikHandle(sj=ikJnts[0], ee=ikJnts[2], solver='ikRPsolver', n=namer.name('ikh')) #use the no-flip setup xp = utils.getXProductFromNodes(ikJnts[1], ikJnts[0], ikJnts[2]) sp = MC.xform(ikJnts[0], q=1, ws=1, t=1) l = MC.spaceLocator()[0] MC.xform(l, t=[sp[0] + xp[0], sp[1]+xp[1], sp[2]+xp[2]], ws=1) MC.delete(MC.poleVectorConstraint(l, ikHandle)) MC.delete(l) MC.setAttr("%s.twist" % ikHandle, 90) MC.addAttr(ikCtl, ln='twist', dv=0, k=1) control.setLockTag(ikCtl, uk=['twist']) pma = MC.createNode('plusMinusAverage', n=namer('twist_pma')) MC.connectAttr("%s.twist" % ikCtl, "%s.input1D[0]" % pma) MC.setAttr("%s.input1D[1]" % pma, 90) MC.connectAttr("%s.output1D" % pma, "%s.twist" % ikHandle) del l, sp, xp ##set up the reverse foot #create the ik hanldes ikHandles = {} names = ['ankle', 'ball', 'toe', 'toetip'] for i in range(len(names)-1): startIndex = self.__toks.index(names[i]) endIndex = self.__toks.index(names[i+1]) start = names[i] end = names[i+1] name = namer.name(d='revfoot_%s_to_%s_ikh' % (start, end), r='ik') handle = MC.ikHandle(sj=ikJnts[startIndex], ee=ikJnts[endIndex], n=name, sol='ikSCsolver') ikHandles[names[i+1]] = handle[0] MC.rename(handle[1], name + '_eff') #setup the toe control to have an inverse pivot toeCtl = namer('toe_ctl', r='ik') MC.connectAttr("%s.fkIk" % ikCtl, "%s.v" % toeCtl) MC.parent(toeCtl, ikCtl) utils.insertNodeAbove(toeCtl) toeCtlInv = MC.createNode('transform', n = namer('toe_inv', r='ik')) MC.parent(toeCtlInv, toeCtl) toeCtlInvMdn = MC.createNode('multiplyDivide', n=namer('toe_inv_mdn', r='ik')) MC.connectAttr('%s.t' % toeCtl, '%s.input1' % toeCtlInvMdn) MC.setAttr('%s.input2' % toeCtlInvMdn, -1, -1, -1, type='double3') MC.connectAttr('%s.output' % toeCtlInvMdn, '%s.t' % toeCtlInv) #setup the rev foot joints revFootJnts = {} revFkToks = ['heel', 'toetip', 'toe', 'ball', 'ankle'] positions = [ikCtl, bndJnts[-1], bndJnts[-2], bndJnts[-3], bndJnts[-4]] MC.select(cl=1) for i in range(len(revFkToks)): tok = revFkToks[i] posNode = positions[i] pos = MC.xform(posNode, q=1, t=1, ws=1) if i == 1: pos[1] = MC.xform(positions[0], q=1, t=1, ws=1)[1] j = MC.joint(name=namer('%s_revfoot_jnt' % tok, r='ik'), p = pos ) revFootJnts[tok] = j if i == 0: MC.setAttr('%s.v' % j, 0) del i, j #orient the joints to aim down pos y and up axis along the plane formed by #the upper leg xp = utils.getXProductFromNodes(ikJnts[1], ikJnts[0], ikJnts[2]) for jnt in revFootJnts.values(): utils.orientJnt(jnt, aimVec=[0,1,0], upVec=[1,0,0], worldUpVec=[xp[0],0,xp[2]]) del jnt, xp MC.parent(revFootJnts['heel'], toeCtlInv) MC.parent(ikHandles['toetip'], revFootJnts['toetip']) MC.parent(ikHandles['toe'], revFootJnts['toe']) MC.parent(ikHandles['ball'], revFootJnts['ball']) MC.parent(ikHandle, revFootJnts['ankle']) #setup the foot roll self.__setupFootRoll(ikCtl, revFootJnts, namer) control.setLockTag(toeCtl, uk=['r', 't']) control.setLockTag(ikCtl, uk=['r', 't', 'fkIk']) self.setNodeCateogry(utils.insertNodeAbove(ikCtl, 'transform'), 'ik')
def _makeRig(self, namer): neckJntCnt = self.options.getValue('numNeckBones') + 1 ikCtlCnt = self.options.getValue('numIkCtls') toks = self.__getToks() bndJnts = [namer(t, r='bnd') for t in toks] MC.makeIdentity(bndJnts, apply=True, r=1, t=1, s=1) namer.setTokens(r='fk') #fkJnts = utils.dupJntList(bndJnts, toks, namer) fkCtls = [namer(t, r='fk') for t in toks[:-1]] fkCtls = control.setupFkCtls(bndJnts[:-1], fkCtls, toks[:-1], namer) for ctl in fkCtls: control.setLockTag(ctl, uk=['r']) for i, tok in enumerate(toks[:-1]): self.setPlugNode(tok, fkCtls[i]) namer.setTokens(r='ik') ikJnts = utils.dupJntList(bndJnts, toks, namer) MC.setAttr('%s.v' % ikJnts[0], 0) ikCtls = [] for i in range(ikCtlCnt): if i < (ikCtlCnt-1): n = namer('ctl', r='ik', alphaSuf=i) utils.insertNodeAbove(n) else: n = namer('head_ctl', r='ik') ikCtls.append(n) baseIkCtl = MC.createNode('transform', n=namer('base', r='ik')) utils.snap(bndJnts[0], baseIkCtl, orient=False) ikCtls.insert(0, baseIkCtl) for ctl in ikCtls: control.setLockTag(ctl, uk=['r', 't']) tmp = MC.createNode('transform', n="TMP") utils.parentShape(tmp, ikCtls[-1], deleteChildXform=False) utils.snap(bndJnts[-2], ikCtls[-1]) utils.parentShape(ikCtls[-1], tmp) utils.insertNodeAbove(ikCtls[-1]) #doubling the cvs on the end allows us to build a curve with only 2 controls, #but causes popping otherwise. Only use if needed doubleEndPoints = False if ikCtlCnt == 1: doubleEndPoints = True crv = curveFromNodes(ikCtls, name=namer('ikspline_crv'), doubleEndPoints=doubleEndPoints ) srf = surfaceFromNodes(ikCtls, name=namer('ikspline_srf'), doubleEndPoints=doubleEndPoints) bindControlsToShape(ikCtls, crv, doubleEndPoints=doubleEndPoints) bindControlsToShape(ikCtls, srf, doubleEndPoints=doubleEndPoints) ikNode, ikHandle = setupSpineIkNode(ikCtls, ikJnts[:-1], nodeName='splinik', namer=namer, crv=crv, surf=srf) self.setNodeCateogry(ikNode, 'dnt') MC.setAttr("%s.v" % ikNode, 0) #tag this node so the master connect the uniform scale core.Root.tagInputScaleAttr(ikNode, 'inputScaleAmt') MC.addAttr(ikCtls[-1], ln='fkIk', dv=0, k=1, min=0, max=1) MC.addAttr(ikCtls[-1], ln='stretchAmt', dv=0, k=1, min=0, max=1) MC.addAttr(ikCtls[-1], ln='evenStretchAmt', dv=0, k=1, min=0, max=1) control.setLockTag(ikCtls[-1], uk=['fkIk', 'stretchAmt', 'evenStretchAmt']) MC.connectAttr('%s.stretchAmt' % ikCtls[-1], '%s.stretchAmt' % ikNode) MC.connectAttr('%s.evenStretchAmt' % ikCtls[-1], '%s.evenStretchAmt' % ikNode) ikReverse = utils.blendJointChains(fkCtls, ikJnts[:-1], bndJnts[:-1], '%s.fkIk' % ikCtls[-1], namer) for ctl in fkCtls: MC.connectAttr('%s.outputX' % (ikReverse), '%s.v' % ctl) for ctl in ikCtls[1:-1]: MC.connectAttr('%s.fkIk' % (ikCtls[-1]), '%s.v' % ctl)