def fkChainBetweenPoints(start, end, name, bias, numCtrls=3, ctrlInterval=3): ''' Creates an fk chain aligned to start finishing at end. :param start: beginning of the chain :param end: end of the chain :param name: prefix for newly created nodes :param numCtrls: number of fk ctrls to distribute along the chain :param bias: weight of control distribution towards start or end. Positive values favour end, negative favour start :param ctrlInterval: number of intermediate transforms between controls :return: list of ctrls ''' ctrls = [] points = coreUtils.pointsAlongVector(start, end, (numCtrls * ctrlInterval), bias) ctrlSize = coreUtils.getDistance(start, end) # get axis for control alignment axis = coreUtils.getDominantAxis(start, end) # Base baseCtrl = controls.circleBumpCtrl(radius=ctrlSize * .2, name='%s_base_ctrl' % name, axis=axis) baseBuffer = coreUtils.addParent(baseCtrl, 'group', name='%s_base_buffer_srt' % name) coreUtils.align(baseBuffer, start) ctrls.append(baseCtrl) #FK for i in range(len(points)): num = str(i + 1).zfill(2) ctrlNum = str((i / ctrlInterval) + 1).zfill(2) c = None if i % ctrlInterval == 0 and i != len(points) - 1: c = controls.circleBumpCtrl(name='%s_%s_ctrl' % (name, ctrlNum), axis=axis, radius=ctrlSize * .1) else: c = coreUtils.pmc.group(empty=1, name='%s_%s_srt' % (name, num)) ctrls[-1].t.connect(c.t) ctrls[-1].r.connect(c.r) ctrls[-1].s.connect(c.s) b = coreUtils.addParent(c, 'group', name='%s_%s_buffer_srt' % (name, num)) if i == 0: coreUtils.align(b, start) b.setParent(baseCtrl) else: b.t.set(points[i]) coreUtils.align(b, start, translate=0) b.setParent(ctrls[-1]) ctrls.append(c)
def addCtrl(anchor, target, name, ctrlSize=1): ''' adds an ik control to anchor's component The control will be aligned to target and attached to anchor :param name: name for new control e.g. 'shldr_R' :return: new control ''' if anchor in pmc.listRelatives(getComponentGroup(anchor, 'interface'), ad=1): print 'anchor is is interface' c = controls.boxCtrl(size=ctrlSize, name='%s_%s_ctrl' % (getComponentFromName(anchor), name)) b = coreUtils.addParent( c, 'group', '%s_%s_buffer_srt' % (getComponentFromName(anchor), name)) coreUtils.align(b, target, scale=1) b.setParent(anchor) return c elif anchor in pmc.listRelatives(getComponentGroup( anchor, 'input'), ad=1) or anchor in pmc.listRelatives( getComponentGroup(anchor, 'rig'), ad=1): print 'anchor is in rig or input' c = controls.boxCtrl(size=ctrlSize, name='%s_%s_ctrl' % (getComponentFromName(anchor), name)) b = coreUtils.addParent( c, 'group', '%s_%s_buffer_srt' % (getComponentFromName(anchor), name)) coreUtils.align(b, target, scale=1) offset = coreUtils.addChild( anchor, 'group', '%s_%s_offset_srt' % (getComponentFromName(anchor), name)) coreUtils.align(offset, b, scale=1) b.setParent(getComponentGroup(anchor, 'interface')) d = coreUtils.isDecomposed(offset) coreUtils.connectDecomposedMatrix(d, b) return c else: print 'anchor is not in rig, input or interface' return 'You can only attach controls to nodes in the input, interface or rig groups of a component'
def buildTwistyLimb(self, numTwistJoints): ctrlSize = coreUtils.getDistance(self.resultJoints[0], self.resultJoints[1]) * .25 # Add mid ctrl self.midBuffer = rigObjects.orientationAverageNode( self.resultJoints[0], self.resultJoints[1], '%s_mid_buffer' % self.name) self.midCtrl = controls.squareCtrl(size=ctrlSize, axis='x', name='%s_mid_ctrl' % self.name) coreUtils.align(self.midCtrl, self.midBuffer) self.midCtrl.setParent(self.midBuffer) self.midBuffer.setParent(self.interfaceGrp) pmc.addAttr(self.midCtrl, ln='auto_bend', at='double', k=1, h=0, minValue=0.0, maxValue=1.0) self.ctrls.append(self.midCtrl) # Create twisty segments self.upperTwist = drTwistySegment.DrTwistySegment( self.fkCtrls[0], self.midCtrl, name='%sUpper_%s' % (self.name.split('_')[0], self.name.split('_')[1]), numDivisions=numTwistJoints) self.upperTwist.mainGrp.setParent(self.subGrp) self.lowerTwist = drTwistySegment.DrTwistySegment( self.midCtrl, self.fkCtrls[2], name='%sLower_%s' % (self.name.split('_')[0], self.name.split('_')[1]), numDivisions=numTwistJoints) self.lowerTwist.mainGrp.setParent(self.subGrp) if self.resultJoints[1].tx.get() > 0.0: self.lowerTwist.mainGrp.invertTwist.set(1) self.upperTwist.mainGrp.invertTwist.set(1) upperNonRoll = rigObjects.nonTwistingChild(self.resultJoints[0], name='%s_upper' % self.name) componentUtils.connectIO(self.upperTwist.startIn, upperNonRoll, '%s_upperStart' % self.name) componentUtils.connectIO(self.upperTwist.endIn, self.midCtrl, '%s_upperEnd' % self.name) componentUtils.connectIO(self.lowerTwist.startIn, self.midCtrl, '%s_lowerStart' % self.name) componentUtils.connectIO(self.lowerTwist.endIn, self.resultJoints[2], '%s_lowerEnd' % self.name) self.midCtrl.auto_bend.connect(self.upperTwist.mainGrp.endAuto) self.midCtrl.auto_bend.connect(self.lowerTwist.mainGrp.startAuto) pmc.addAttr(self.settingsCtrl, ln='bendyCtrls_vis', at='bool', k=0, h=0) pmc.setAttr(self.settingsCtrl.bendyCtrls_vis, cb=1) self.settingsCtrl.bendyCtrls_vis.connect( self.upperTwist.mainGrp.visibility) self.settingsCtrl.bendyCtrls_vis.connect( self.lowerTwist.mainGrp.visibility)
def build(self, joints, alignIkToJointsUpAxis): # duplicate joints self.resultJoints = coreUtils.duplicateJoints(joints, name='%s_result_XX_jnt' % self.name) self.fkJoints = coreUtils.duplicateJoints(joints, name='%s_fk_XX_jnt' % self.name) self.ikJoints = coreUtils.duplicateJoints(joints, name='%s_ik_XX_jnt' % self.name) self.jointBufferGrp = coreUtils.addChild( self.rigGrp, 'group', '%s_jointsBuffer_srt' % self.name) coreUtils.align(self.jointBufferGrp, self.resultJoints[0]) self.resultJoints[0].setParent(self.jointBufferGrp) self.fkJoints[0].setParent(self.jointBufferGrp) self.ikJoints[0].setParent(self.jointBufferGrp) ctrlSize = coreUtils.getDistance(self.resultJoints[0], self.resultJoints[1]) * .25 # Orientation for controls and aim constraints axis = 'x' aimVec = (1, 0, 0) if self.resultJoints[1].tx.get() < 0.0: axis = '-x' aimVec = (-1, 0, 0) self.settingsCtrl = controls.squareChamferCtrl( name='%s_settings_ctrl' % self.name, size=ctrlSize * .33) self.settingsCtrl.setParent(self.interfaceGrp) pmc.addAttr(self.settingsCtrl, ln='ik_fk_blend', at='double', k=1, h=0, maxValue=1.0, minValue=0.0) settingsBuffer = coreUtils.addParent( self.settingsCtrl, 'group', '%s_settings_buffer_srt' % self.name) settingsOffset = ctrlSize * 2 if axis == '-x': settingsOffset *= -1 self.settingsCtrl.ty.set(settingsOffset) endSrt = coreUtils.decomposeMatrix(self.resultJoints[2].worldMatrix[0], name='%s_endWorldMtxToSrt_utl' % self.name) endSrt.outputTranslate.connect(settingsBuffer.t) endSrt.outputRotate.connect(settingsBuffer.r) endSrt.outputScale.connect(settingsBuffer.s) self.ctrls.append(self.settingsCtrl) # Create a dummy input to connect parts of the limb to self.baseInput = coreUtils.addChild(self.inputGrp, 'group', name='%s_base_in_srt' % self.name) coreUtils.align(self.baseInput, joints[0]) baseMtx = coreUtils.isDecomposed(self.baseInput) # set up blending for rj, ij, fj in zip(self.resultJoints, self.ikJoints, self.fkJoints): coreUtils.ikFkBlend(ij, fj, rj, blendAttr='%s.ik_fk_blend' % self.settingsCtrl) # fk controls self.fkCtrlsGrp = coreUtils.addChild(self.interfaceGrp, 'group', '%s_self.fkCtrls_hrc' % self.name) self.settingsCtrl.ik_fk_blend.connect(self.fkCtrlsGrp.visibility) buffer = None self.fkCtrls = [] for i in range(len(self.fkJoints) - 1): fj = self.fkJoints[i] num = str(i + 1).zfill(2) c = controls.circleBumpCtrl(name='%s_fk_%s_ctrl' % (self.name, num), axis=axis, radius=ctrlSize) coreUtils.align(c, fj) buffer = coreUtils.addParent( c, 'group', '%s_fk%s_buffer_srt' % (self.name, num)) if i == 0: buffer.setParent(self.fkCtrlsGrp) coreUtils.connectAttrs(c, fj, ['t', 'r', 's']) else: buffer.setParent(self.fkCtrls[-1]) m = coreUtils.decomposeLocalMatrix(c, depth=1) m.outputTranslate.connect(fj.t) m.outputScale.connect(fj.s) c.rotate.connect(fj.r) self.fkCtrls.append(c) self.ctrls.append(c) # rotate order for node in [ self.fkCtrls[1], self.fkJoints[1], self.ikJoints[1], self.resultJoints[1] ]: node.rotateOrder.set(3) # ik controls self.ikCtrl = controls.boxCtrl(name='%s_ik_ctrl' % self.name, size=ctrlSize) if alignIkToJointsUpAxis: aimAxis = 'x' if pmc.xform(joints[2], q=1, t=1, ws=1) > pmc.xform( joints[3], q=1, t=1, ws=1): aimAxis = '-x' elif pmc.xform(joints[2], q=1, t=1, ws=1) < pmc.xform( joints[3], q=1, t=1, ws=1): aimAxis = 'x' pmc.xform(self.ikCtrl, ws=1, m=coreUtils.getAimMatrix( start=self.resultJoints[2], end=self.resultJoints[3], axis=aimAxis, upAxis='y', worldUpAxis=alignIkToJointsUpAxis, upNode=self.resultJoints[2])) else: coreUtils.align(self.ikCtrl, self.ikJoints[2], orient=0) self.ikCtrlsGrp = coreUtils.addChild(self.interfaceGrp, 'group', '%s_ikCtrls_hrc' % self.name) self.ikCtrl.setParent(self.ikCtrlsGrp) ikBuffer = coreUtils.addParent(self.ikCtrl, 'group', '%s_ik_buffer_srt' % self.name) ikFkRev = coreUtils.reverse(self.settingsCtrl.ik_fk_blend, '%s_ikFkBlendReverse_UTL' % self.name) ikFkRev.outputX.connect(self.ikCtrlsGrp.visibility) self.ctrls.append(self.ikCtrl) pmc.addAttr(self.ikCtrl, longName='stretch', at='double', minValue=0, maxValue=1, defaultValue=0, keyable=True) pmc.addAttr(self.ikCtrl, longName='twist', at='double', keyable=True) pmc.addAttr(self.ikCtrl, longName='soft', at='double', minValue=0, defaultValue=0, keyable=True) pmc.addAttr(self.ikCtrl, longName='mid_pin', at='double', keyable=True, minValue=0, maxValue=1) pmc.addAttr(self.ikCtrl, longName='force_straight', at='double', keyable=True, h=0, minValue=0.0, maxValue=1.0) # Soft non-stretchy IK stuff ik_grp = coreUtils.addChild(self.rigGrp, 'group', name='%s_ik_hrc' % self.name) self.ikBufferGrp = coreUtils.addChild(ik_grp, 'group', name='%s_ik_srt' % self.name) coreUtils.align(self.ikBufferGrp, self.jointBufferGrp) self.softBlend_loc = coreUtils.createAlignedNode( self.ikCtrl, 'locator', name='%s_ik_softBlend_loc' % self.name) self.softBlend_loc.setParent(ik_grp) self.ctrl_loc = coreUtils.createAlignedNode(self.ikCtrl, 'locator', name='%s_ikCtrl_loc' % self.name) self.ctrl_loc.setParent(ik_grp) pmc.parentConstraint(self.ikCtrl, self.ctrl_loc) aim_loc = coreUtils.addChild(self.ikBufferGrp, 'locator', name='%s_softIkaim_loc' % self.name) pmc.aimConstraint(self.ctrl_loc, aim_loc, upVector=(0, 0, 0)) btm_loc = coreUtils.createAlignedNode(self.ikCtrl, 'locator', name='%s_ikBtm_loc' % self.name) btm_loc.setParent(aim_loc) chainLen = abs(self.ikJoints[1].tx.get() + self.ikJoints[2].tx.get()) ctrlDist = coreUtils.distanceBetweenNodes(aim_loc, self.ctrl_loc, name='%s_ikCtrl_utl' % self.name) globalScaleDiv = coreUtils.divide(1.0, baseMtx.outputScaleX, name='%s_globalScaleDiv_utl' % self.name) isStretchedMult = coreUtils.multiply(ctrlDist.distance, globalScaleDiv.outputX, name='%s_isStretched_utl' % self.name) softDist = coreUtils.distanceBetweenNodes(btm_loc, self.softBlend_loc, name='%s_soft_utl' % self.name) stretchDist = coreUtils.distanceBetweenNodes(aim_loc, self.softBlend_loc, name='%s_stretch_utl' % self.name) chainLenMinusSoft = coreUtils.minus([chainLen, self.ikCtrl.soft], name='%s_chainLenMinusSoft_utl' % self.name) isStretchedCond = pmc.createNode('condition', name='%s_isStretched_utl' % self.name) isStretchedCond.operation.set(2) isStretchedMult.outputX.connect(isStretchedCond.firstTerm) chainLenMinusSoft.output1D.connect(isStretchedCond.secondTerm) isStretchedMult.outputX.connect(isStretchedCond.colorIfFalseR) isSoftCond = pmc.createNode('condition', name='%s_isSoft_utl' % self.name) isSoftCond.operation.set(2) self.ikCtrl.soft.connect(isSoftCond.firstTerm) isSoftCond.colorIfFalseR.set(chainLen) ctrlDistMinusSoftChain = coreUtils.minus( [isStretchedMult.outputX, chainLenMinusSoft.output1D], name='%s_ctrlDistMinusSoftChain_utl' % self.name) divideBySoft = coreUtils.safeDivide(ctrlDistMinusSoftChain.output1D, self.ikCtrl.soft, name='%s_divideBySoft_utl' % self.name) invert = coreUtils.multiply(divideBySoft.outputX, -1, name='%s_invertSoft_utl' % self.name) exp = coreUtils.power(2.718282, invert.outputX, name='%s_exponential_utl' % self.name) multiplyBySoft = coreUtils.multiply(exp.outputX, self.ikCtrl.soft, name='%s_multiplyBySoft_utl' % self.name) minusFromChainLen = coreUtils.minus([chainLen, multiplyBySoft.outputX], name='%s_minusFromChainLen_utl' % self.name) minusFromChainLen.output1D.connect(isSoftCond.colorIfTrueR) isSoftCond.outColorR.connect(isStretchedCond.colorIfTrueR) isStretchedCond.outColorR.connect(btm_loc.tx) # IK Solvers ikHandleGrp = coreUtils.createAlignedNode(self.ikCtrl, 'group', name='%s_ikHandle_srt' % self.name) ikHandleGrp.setParent(self.softBlend_loc) pmc.orientConstraint(self.ikCtrl, ikHandleGrp, mo=1) ikHandle = pmc.ikHandle(solver='ikRPsolver', name='%s_ikHandle' % self.name, startJoint=self.ikJoints[0], endEffector=self.ikJoints[2], setupForRPsolver=1)[0] ikHandle.setParent(ikHandleGrp) self.ikCtrl.twist.connect(ikHandle.twist) endIkHandle = pmc.ikHandle(solver='ikSCsolver', name='%s_end_ikHandle' % self.name, startJoint=self.ikJoints[2], endEffector=self.ikJoints[3], setupForRPsolver=1)[0] endIkHandle.setParent(ikHandleGrp) # Pole Vector pvAimGrp = coreUtils.addChild(self.ikBufferGrp, 'group', name='%s_pvAim_srt' % self.name) pmc.aimConstraint(btm_loc, pvAimGrp, mo=0, u=(0, 0, 0), aimVector=aimVec) self.pvCtrl = controls.crossCtrl(name='%s_pv_ctrl' % self.name, size=ctrlSize) poleOffset = 3 if '-' in axis: poleOffset = -3 self.pvCtrl.setParent(self.ikJoints[1]) self.pvCtrl.t.set((0, 0, ctrlSize * poleOffset)) self.pvCtrl.setParent(self.ikCtrlsGrp) self.pvBufferGrp = coreUtils.addParent(self.pvCtrl, 'group', '%s_pv_buffer_srt' % self.name) pmc.poleVectorConstraint(self.pvCtrl, ikHandle) self.ctrls.append(self.pvCtrl) # stretchy soft IK stuff pc = pmc.pointConstraint(btm_loc, self.ctrl_loc, self.softBlend_loc) stretchRev = coreUtils.reverse(self.ikCtrl.stretch, name='%s_stretchReverse_utl' % self.name) stretchRev.outputX.connect('%s.%sW0' % (pc.nodeName(), btm_loc.nodeName())) self.ikCtrl.stretch.connect('%s.%sW1' % (pc.nodeName(), self.ctrl_loc.nodeName())) scaledSoftDist = coreUtils.multiply(globalScaleDiv.outputX, softDist.distance, name='%s_scaledSoftDist_utl' % self.name) # Stretchy Mid midLen = coreUtils.multiply((self.ikJoints[1].tx.get() / chainLen), scaledSoftDist.outputX, name='%s_midLen_utl' % self.name) stretchMidLen = coreUtils.multiply(self.ikCtrl.stretch, midLen.outputX, name='%s_stretchMidLen_utl' % self.name) stretchMidLenPlusBoneLen = coreUtils.add( [self.ikJoints[1].tx.get(), stretchMidLen.outputX], name='%s_stretchMidLenPlusBoneLen_utl' % self.name) pinUpperDist = coreUtils.distanceBetweenNodes(self.ikBufferGrp, self.pvCtrl, name='%s_pinUpper_utl' % self.name) pinMult = 1.0 if '-' in axis: pinMult = -1.0 pinUpper_uc = coreUtils.convert(pinUpperDist.distance, pinMult, name='%s_pinUpperDist_utk' % self.name) pinUpperGlobalScale = coreUtils.multiply( globalScaleDiv.outputX, pinUpper_uc.output, name='%s_pinUpperGlobalScale_utl' % self.name) pinUpperBlend = coreUtils.blend( input1=pinUpperGlobalScale.outputX, input2=stretchMidLenPlusBoneLen.output1D, blendAttr=self.ikCtrl.mid_pin, name='%s_pinUpper_utl' % self.name) # Stretchy Bot botLen = coreUtils.multiply((self.ikJoints[2].tx.get() / chainLen), scaledSoftDist.outputX, name='%s_botLen_utl' % self.name) stretchBotLen = coreUtils.multiply(self.ikCtrl.stretch, botLen.outputX, name='%s_stretchBotLen_utl' % self.name) stretchBotLenPlusBoneLen = coreUtils.add( [self.ikJoints[2].tx.get(), stretchBotLen.outputX], name='%s_stretchBotLenPlusBoneLen_utl' % self.name) pinLowerDist = coreUtils.distanceBetweenNodes(self.softBlend_loc, self.pvCtrl, name='%s_pinLower_utl' % self.name) pinLower_uc = coreUtils.convert(pinLowerDist.distance, pinMult, name='%s_pinLowerDist_utl' % self.name) pinLowerGlobalScale = coreUtils.multiply( globalScaleDiv.outputX, pinLower_uc.output, name='%s_pinLowerGlobalScale_utl' % self.name) pinLowerBlend = coreUtils.blend( input1=pinLowerGlobalScale.outputX, input2=stretchBotLenPlusBoneLen.output1D, blendAttr=self.ikCtrl.mid_pin, name='%s_pinLower_utl' % self.name) # Add ability to force straight arm straightUpper_md = coreUtils.multiply( stretchDist.distance, self.ikJoints[1].tx.get() / chainLen, name='%s_midLenTimesChainLen_utl' % self.name) straightLower_md = coreUtils.multiply( stretchDist.distance, self.ikJoints[2].tx.get() / chainLen, name='%s_botLenTimesChainLen_utl' % self.name) straightUpperBlend = coreUtils.blend( input1=straightUpper_md.outputX, input2=pinUpperBlend.outputR, blendAttr=self.ikCtrl.force_straight, name='%s_straightUpper_utl' % self.name) straightLowerBlend = coreUtils.blend( input1=straightLower_md.outputX, input2=pinLowerBlend.outputR, blendAttr=self.ikCtrl.force_straight, name='%s_straightLower_utl' % self.name) straightUpperBlend.outputR.connect(self.ikJoints[1].tx) straightLowerBlend.outputR.connect(self.ikJoints[2].tx) # connect to base input d = coreUtils.isDecomposed(self.baseInput) coreUtils.connectDecomposedMatrix(d, self.jointBufferGrp) coreUtils.connectDecomposedMatrix(d, self.ikBufferGrp) # Add basic space switching to ik ctrl, pole vector and top fk ctrl - additional spaces can be added at any point pvTargets = componentUtils.addSpaceSwitch(self.pvBufferGrp, 'pv', ['limb'], type='parent', ctrlNode=self.pvCtrl, targetNodes=[pvAimGrp]) ikTargets = componentUtils.addSpaceSwitch(ikBuffer, 'ik', ['limb'], type='parent', ctrlNode=self.ikCtrl, targetNodes=[self.baseInput]) fkTargets = componentUtils.addSpaceSwitch(self.fkCtrls[0].getParent(), 'fk', ['limb'], type='rotate', ctrlNode=self.fkCtrls[0], targetNodes=[self.baseInput]) d.outputTranslate.connect(self.fkCtrls[0].getParent().t) d.outputScale.connect(self.fkCtrls[0].getParent().s)
def build(self, ankle, ball, toe, inner, outer, heel, settingsNode=None, blendAttr=None): # duplicate joints self.resultJoints = coreUtils.duplicateJoints([ankle, ball, toe], name='%s_result_XX_jnt' % self.name) self.fkJoints = coreUtils.duplicateJoints([ankle, ball, toe], name='%s_fk_XX_jnt' % self.name) self.ikJoints = coreUtils.duplicateJoints([ankle, ball, toe], name='%s_ik_XX_jnt' % self.name) self.resultBuffer = coreUtils.addChild( self.rigGrp, 'group', '%s_resultJoints_buffer_srt' % self.name) coreUtils.align(self.resultBuffer, self.resultJoints[0]) self.resultJoints[0].setParent(self.resultBuffer) self.fkBuffer = coreUtils.addChild( self.rigGrp, 'group', '%s_fkJoints_buffer_srt' % self.name) coreUtils.align(self.fkBuffer, self.resultJoints[0]) self.fkJoints[0].setParent(self.fkBuffer) self.ikBuffer = coreUtils.addChild( self.rigGrp, 'group', '%s_ikJoints_buffer_srt' % self.name) coreUtils.align(self.ikBuffer, self.resultJoints[0]) self.ikJoints[0].setParent(self.ikBuffer) # set up blending if not blendAttr: pmc.addAttr(self.mainGrp, ln='ik_fk_blend', at='double', minValue=0, maxValue=1, k=1, h=0) blendAttr = self.mainGrp.ik_fk_blend for rj, ij, fj in zip([self.resultBuffer] + self.resultJoints, [self.ikBuffer] + self.ikJoints, [self.fkBuffer] + self.fkJoints): coreUtils.ikFkBlend(ij, fj, rj, blendAttr=blendAttr) ctrlSize = coreUtils.getDistance(self.resultJoints[0], self.resultJoints[1]) * .75 # Orientation for controls and aim constraints axis = 'x' aimVec = (1, 0, 0) if self.resultJoints[1].tx.get() < 0.0: axis = '-x' aimVec = (-1, 0, 0) # FK ctrl self.toeCtrl = controls.circleBumpCtrl(axis='x', radius=ctrlSize, name='%s_fkToe_ctrl') self.toeCtrlBuffer = coreUtils.addParent(self.toeCtrl, 'group', name='%s_fkToe_buffer_srt') coreUtils.align(self.toeCtrlBuffer, ball) self.toeCtrlBuffer.setParent(self.interfaceGrp) self.toeCtrl.r.connect(self.fkJoints[1].r) self.ctrls.append(self.toeCtrl) blendAttr.connect(self.toeCtrlBuffer.visibility) # ik Driving structure self.heel = coreUtils.createAlignedNode(heel, 'group', '%s_heel_srt' % self.name) self.heel.setParent(self.rigGrp) self.heelBuffer = coreUtils.addParent(self.heel, 'group', '%s_heel_buffer_srt' % self.name) self.toe = coreUtils.createAlignedNode(toe, 'group', '%s_toe_srt' % self.name) self.toe.setParent(self.heel) self.inner = coreUtils.createAlignedNode(inner, 'group', '%s_inner_srt' % self.name) self.inner.setParent(self.toe) innerBuffer = coreUtils.addParent(self.inner, 'group', '%s_inner_buffer_srt' % self.name) self.outer = coreUtils.createAlignedNode(outer, 'group', '%s_outer_srt' % self.name) self.outer.setParent(self.inner) outerBuffer = coreUtils.addParent(self.outer, 'group', '%s_outer_buffer_srt' % self.name) self.ballPivot = coreUtils.createAlignedNode( ball, 'group', '%s_ballPivot_srt' % self.name) self.ballPivot.setParent(self.outer) coreUtils.addParent(self.ballPivot, 'group', '%s_ballPivot_buffer_srt' % self.name) pmc.transformLimits(self.inner, rx=(0, 0), erx=(1, 0)) pmc.transformLimits(self.outer, rx=(0, 0), erx=(0, 1)) self.ball = coreUtils.createAlignedNode(ball, 'group', '%s_ball_srt' % self.name) self.ball.setParent(self.ballPivot) self.ballBuffer = coreUtils.addParent(self.ball, 'group', '%s_ball_buffer_srt' % self.name) self.toeWiggle = coreUtils.addChild(self.ballBuffer, 'group', '%s_toeWiggle_srt' % self.name) componentUtils.connectIO(self.ikBuffer, self.ball, 'ball') # ikHandles ballIkHandle = pmc.ikHandle(solver='ikRPsolver', name='%s_ball_ikHandle' % self.name, startJoint=self.ikJoints[0], endEffector=self.ikJoints[1], setupForRPsolver=1)[0] ballIkHandle.setParent(self.ball) toeIkHandle = pmc.ikHandle(solver='ikRPsolver', name='%s_toe_ikHandle' % self.name, startJoint=self.ikJoints[1], endEffector=self.ikJoints[2], setupForRPsolver=1)[0] toeIkHandle.setParent(self.toeWiggle) # IK driving attributes if not settingsNode: settingsNode = self.mainGrp attrList = [ 'heel_roll', 'heel_pivot', 'ball_roll', 'ball_pivot', 'ball_twist', 'ball_bend', 'toe_roll', 'toe_pivot', 'toe_twist', 'toe_wiggle', 'toe_bend', 'edge_roll' ] pmc.addAttr(settingsNode, ln='ik_foot_attributes', k=0, h=0, at='enum', enumName=' ') pmc.setAttr(settingsNode.ik_foot_attributes, cb=1, lock=1) for attr in attrList: pmc.addAttr(settingsNode, ln=attr, at='double', k=1, h=0) settingsNode.heel_roll.connect(self.heel.ry) settingsNode.heel_pivot.connect(self.heel.rz) settingsNode.ball_roll.connect(self.ball.ry) settingsNode.ball_pivot.connect(self.ballPivot.rz) settingsNode.ball_twist.connect(self.ball.rx) settingsNode.ball_bend.connect(self.ball.rz) settingsNode.toe_roll.connect(self.toe.ry) settingsNode.toe_pivot.connect(self.toe.rz) settingsNode.toe_twist.connect(self.toeWiggle.rx) settingsNode.toe_wiggle.connect(self.toeWiggle.ry) settingsNode.toe_bend.connect(self.toeWiggle.rz) settingsNode.edge_roll.connect(self.inner.rx) settingsNode.edge_roll.connect(self.outer.rx) # Deform joints self.dfmJoints = coreUtils.duplicateJoints([ankle, ball, toe], name='%s_XX_dfm' % self.name) self.dfmBufferGrp = coreUtils.addChild( self.deformGrp, 'group', '%s_dfmJoints_buffer_srt' % self.name) coreUtils.align(self.dfmBufferGrp, self.resultJoints[0]) self.resultBuffer.t.connect(self.dfmBufferGrp.t) self.resultBuffer.r.connect(self.dfmBufferGrp.r) self.resultBuffer.s.connect(self.dfmBufferGrp.s) self.dfmJoints[0].setParent(self.dfmBufferGrp) for i in range(3): self.resultJoints[i].t.connect(self.dfmJoints[i].t) self.resultJoints[i].r.connect(self.dfmJoints[i].r) self.resultJoints[i].s.connect(self.dfmJoints[i].s)
def build(self, joints, numJoints, axis, upAxis, worldUpAxis, reverse, ctrlInterval): # Create curves positions = [pmc.xform(joint, q=1, ws=1, t=1) for joint in joints] self.fkCrv = curveUtils.curveThroughPoints(positions=positions, name='%s_fkCrv' % self.name) self.fkCrv.setParent(self.rigGrp) self.ikCrv = curveUtils.curveThroughPoints(positions=positions, name='%s_ikCrv' % self.name) self.ikCrv.setParent(self.rigGrp) # controls ctrlSize = coreUtils.getDistance(joints[0], joints[-1]) * .5 #base self.baseCtrl = controls.hexCtrl(name='%s_base_ctrl' % self.name, axis=axis, radius=ctrlSize) self.baseCtrl.setParent(self.interfaceGrp) coreUtils.align(self.baseCtrl, joints[0]) baseBuffer = coreUtils.addParent(self.baseCtrl, 'group', name='%s_base_buffer_srt' % self.name) self.ctrls.append(self.baseCtrl) self.baseSubCtrl = controls.hexCtrl(name='%s_baseSub_ctrl' % self.name, axis=axis, radius=ctrlSize * .8) self.baseSubCtrl.setParent(self.baseCtrl) coreUtils.align(self.baseSubCtrl, joints[0]) self.ctrls.append(self.baseSubCtrl) baseMtx = coreUtils.isDecomposed(self.baseSubCtrl) # Create offset srt so that spine can be offset from body controls baseSrt = coreUtils.addChild(self.rigGrp, 'group', '%s_base_srt' % self.name) offsetSrt = coreUtils.addChild(baseSrt, 'group', '%s_offset_srt' % self.name) coreUtils.connectDecomposedMatrix(baseMtx, baseSrt) offsetMtx = coreUtils.isDecomposed(offsetSrt) # settings self.settingsCtrl = controls.squareChamferCtrl( size=ctrlSize * .2, axis=axis, name='%s_settings_ctrl' % self.name) self.settingsCtrl.setParent(self.baseSubCtrl) b = coreUtils.addParent(self.settingsCtrl, 'group', name='%s_settings_buffer_srt' % self.name) coreUtils.align(b, self.baseSubCtrl) pmc.setAttr('%s.t%s' % (b.name(), upAxis), ctrlSize * -1.5) self.ctrls.append(self.settingsCtrl) #FK self.fkCtrls = [] fkOffsetSrt = coreUtils.addChild(self.baseSubCtrl, 'group', '%s_fkOffset_srt' % self.name) coreUtils.connectAttrs(offsetSrt, fkOffsetSrt, ['t', 'r', 's']) for i in range(len(joints) - 1): num = str(i + 1).zfill(2) ctrlNum = str((i / ctrlInterval) + 1).zfill(2) c = None if i % ctrlInterval == 0: c = controls.hexCtrl(name='%s_fk_%s_ctrl' % (self.name, ctrlNum), axis=axis, radius=ctrlSize * .5) self.ctrls.append(c) else: c = coreUtils.pmc.group(empty=1, name='%s_fk_%s_srt' % (self.name, num)) self.ctrls[-1].t.connect(c.t) self.ctrls[-1].r.connect(c.r) self.ctrls[-1].s.connect(c.s) b = coreUtils.addParent(c, 'group', name='%s_fk%s_buffer_srt' % (self.name, num)) coreUtils.align(b, joints[i]) if i == 0: b.setParent(fkOffsetSrt) else: b.setParent(self.fkCtrls[-1]) self.fkCtrls.append(c) # reverse fk self.fkRevCtrls = [] if reverse: for i in range(len(joints) - 1): num = str(i + 1).zfill(2) ctrlNum = str((i / ctrlInterval) + 1).zfill(2) c = None if i % ctrlInterval == 0: c = controls.hexCtrl(name='%s_fkReverse_%s_ctrl' % (self.name, ctrlNum), axis=axis, radius=ctrlSize * .4) self.ctrls.append(c) else: c = coreUtils.pmc.group(empty=1, name='%s_fkReverse_%s_srt' % (self.name, num)) self.ctrls[-1].t.connect(c.t) self.ctrls[-1].r.connect(c.r) self.ctrls[-1].s.connect(c.s) b = coreUtils.addParent(c, 'group', name='%s_fkReverse%s_buffer_srt' % (self.name, num)) coreUtils.align(b, joints[len(joints) - i - 1]) if i == 0: b.setParent(self.fkCtrls[-1]) else: b.setParent(self.interfaceGrp) self.fkRevCtrls.append(c) srtList = [] for i in range(len(self.fkRevCtrls)): num = str(i + 1).zfill(2) fkCtrl = self.fkCtrls[len(self.fkCtrls) - i - 1] revCtrl = self.fkRevCtrls[i] multMtx = None if i == 0: multMtx = coreUtils.multiplyMatrices( [ fkCtrl.worldMatrix[0], revCtrl.parentInverseMatrix[0], revCtrl.worldMatrix[0] ], name='%s_localFkReverseMtx%s_utl' % (self.name, num)) d = coreUtils.decomposeMatrix( revCtrl.worldMatrix[0], name='%s_localFkReverseMtx01ToSrt_utl' % self.name) revCtrl.rotateOrder.connect(d.inputRotateOrder) d.outputTranslate.connect( self.fkCrv.controlPoints[len(joints) - 1]) d.outputTranslate.connect( self.ikCrv.controlPoints[len(joints) - 1]) srtList.append(d) elif i == len(self.fkRevCtrls) - 1: multMtx = coreUtils.multiplyMatrices( [ offsetSrt.worldMatrix[0], self.fkCtrls[len(self.fkCtrls) - i].worldInverseMatrix[0], revCtrl.worldMatrix[0] ], name='%s_localFkReverseMtx%s_utl' % (self.name, num)) else: multMtx = coreUtils.multiplyMatrices( [ fkCtrl.worldMatrix[0], self.fkCtrls[len(self.fkCtrls) - i].worldInverseMatrix[0], revCtrl.worldMatrix[0] ], name='%s_localFkReverseMtx%s_utl' % (self.name, num)) d = coreUtils.decomposeMatrix( multMtx.matrixSum, name='%s_localFkReverseMtx%sToSrt_utl' % (self.name, num)) self.baseCtrl.rotateOrder.connect(d.inputRotateOrder) if i < len(self.fkRevCtrls) - 1: d.outputTranslate.connect(self.fkRevCtrls[i + 1].getParent().t) d.outputRotate.connect(self.fkRevCtrls[i + 1].getParent().r) d.outputScale.connect(self.fkRevCtrls[i + 1].getParent().s) d.outputTranslate.connect( self.fkCrv.controlPoints[len(self.fkRevCtrls) - (i + 1)]) d.outputTranslate.connect( self.ikCrv.controlPoints[len(self.fkRevCtrls) - (i + 1)]) srtList.append(d) else: srtList = [] for i in range(len(self.fkCtrls)): num = str(i + 1).zfill(2) ctrl = self.fkCtrls[i] d = coreUtils.decomposeMatrix(ctrl.worldMatrix[0], name='%s_localFkMtx%sToSrt_utl' % (self.name, num)) ctrl.rotateOrder.connect(d.inputRotateOrder) d.outputTranslate.connect(self.fkCrv.controlPoints[i]) d.outputTranslate.connect(self.ikCrv.controlPoints[i]) srtList.append(d) #IK # hip self.startCtrl = controls.squareCtrl(name='%s_start_ctrl' % self.name, axis=axis, size=ctrlSize) coreUtils.align(self.startCtrl, self.baseCtrl) startBuffer = coreUtils.addParent(self.startCtrl, 'group', name='%s_start_buffer_srt' % self.name) if reverse: startBuffer.setParent(self.interfaceGrp) self.ctrls.append(self.startCtrl) srtList[-1].outputTranslate.connect(startBuffer.t) srtList[-1].outputRotate.connect(startBuffer.r) srtList[-1].outputScale.connect(startBuffer.s) else: startBuffer.setParent(self.baseSubCtrl) # end self.endCtrl = controls.squareCtrl(name='%s_end_ctrl' % self.name, axis=axis, size=ctrlSize) coreUtils.align(self.endCtrl, joints[-1]) endBuffer = coreUtils.addParent(self.endCtrl, 'group', name='%s_end_buffer_srt' % self.name) if reverse: endBuffer.setParent(self.interfaceGrp) self.ctrls.append(self.endCtrl) srtList[0].outputTranslate.connect(endBuffer.t) srtList[0].outputRotate.connect(endBuffer.r) srtList[0].outputScale.connect(endBuffer.s) else: endBuffer.setParent(self.fkCtrls[-1]) d = coreUtils.decomposeMatrix(endBuffer.worldMatrix[0], name='%s_endMtxToSrt_utl' % self.name) self.endCtrl.rotateOrder.connect(d.inputRotateOrder) d.outputTranslate.connect(self.fkCrv.controlPoints[len(joints) - 1], f=1) d.outputTranslate.connect(self.ikCrv.controlPoints[len(joints) - 1], f=1) srtList.append(d) # rotate orders for ctrls rotateOrderDict = {'x': 0, 'y': 2, 'z': 1} for ctrl in self.ctrls: ctrl.rotateOrder.set(rotateOrderDict[axis]) # crvInfo crvInfo = pmc.createNode('curveInfo', name='%s_ikCrvInfo_utl' % self.name) crvShape = coreUtils.getShape(self.fkCrv) crvShape.worldSpace[0].connect(crvInfo.inputCurve) # stretch pmc.addAttr(self.mainGrp, longName='stretch', at='double', k=0, h=1) restLenMD = coreUtils.multiply(crvInfo.arcLength.get(), baseMtx.outputScaleX, name='%s_restLength_utl' % self.name) stretchMD = coreUtils.divide(restLenMD.outputX, crvInfo.arcLength, name='%s_stretchFactor_utl' % self.name) stretchMD.outputX.connect(self.mainGrp.stretch) # ik curve skinning endGuideJoint = coreUtils.addChild(self.rigGrp, 'joint', '%s_endGuide_jnt' % self.name) endJointBuffer = coreUtils.addParent(endGuideJoint, 'group', name='%s_endJnt_buffer_srt' % self.name) endJoint = coreUtils.addChild(endJointBuffer, 'joint', '%s_end_jnt' % self.name) srt = srtList[-1] if reverse: srt = srtList[0] srt.outputTranslate.connect(endJointBuffer.t) srt.outputRotate.connect(endJointBuffer.r) srt.outputScale.connect(endJointBuffer.s) self.endCtrl.t.connect(endGuideJoint.t) self.endCtrl.r.connect(endGuideJoint.r) self.endCtrl.t.connect(endJoint.t) self.endCtrl.r.connect(endJoint.r) startGuideJoint = coreUtils.addChild(self.rigGrp, 'joint', '%s_startGuide_jnt' % self.name) startJointBuffer = coreUtils.addParent(startGuideJoint, 'group', name='%s_startJnt_buffer_srt' % self.name) startJoint = coreUtils.addChild(startJointBuffer, 'joint', '%s_start_jnt' % self.name) srt = srtList[-1] if not reverse: srt = srtList[0] srt.outputTranslate.connect(startJointBuffer.t) srt.outputRotate.connect(startJointBuffer.r) srt.outputScale.connect(startJointBuffer.s) self.startCtrl.t.connect(startGuideJoint.t) self.startCtrl.r.connect(startGuideJoint.r) self.startCtrl.t.connect(startJoint.t) self.startCtrl.r.connect(startJoint.r) jointScaleMD = coreUtils.divide(1.0, self.mainGrp.stretch, name='%s_ikJointScale_utl' % self.name) coreUtils.connectAttrToMany(jointScaleMD.outputX, [ startJoint.sx, startJoint.sy, startJoint.sz, endJoint.sx, endJoint.sy, endJoint.sz ]) guideSkin = pmc.skinCluster(endGuideJoint, startGuideJoint, self.fkCrv, dr=1) endJointBuffer.worldInverseMatrix[0].connect( guideSkin.bindPreMatrix[0]) startJointBuffer.worldInverseMatrix[0].connect( guideSkin.bindPreMatrix[1]) skin = pmc.skinCluster(endJoint, startJoint, self.ikCrv, dr=2) endJointBuffer.worldInverseMatrix[0].connect(skin.bindPreMatrix[0]) startJointBuffer.worldInverseMatrix[0].connect(skin.bindPreMatrix[1]) # create attribute on settings control to choose upAxis and avoid flipping enumString = '' axes = ['x', 'y', 'z'] for a in axes: if a != axis: enumString += (a + ':') pmc.addAttr(self.settingsCtrl, ln='upAxis', at='enum', enumName=enumString, k=1, h=0) upVecCond = pmc.createNode('condition', name='%s_upVec_utl' % self.name) self.settingsCtrl.upAxis.connect(upVecCond.firstTerm) if axis == 'x': upVecCond.colorIfTrue.set((0, 1, 0)) else: upVecCond.colorIfTrue.set((1, 0, 0)) if axis == 'y': upVecCond.colorIfFalse.set((0, 0, 1)) else: upVecCond.colorIfFalse.set((0, 1, 0)) upAxisCond = pmc.createNode('condition', name='%s_upAxis_utl' % self.name) self.settingsCtrl.upAxis.connect(upAxisCond.firstTerm) if axis == 'x': upAxisCond.colorIfTrueR.set(1) else: upAxisCond.colorIfTrueR.set(0) if axis == 'y': upAxisCond.colorIfFalseR.set(2) else: upAxisCond.colorIfFalseR.set(1) # pathNodes mps = curveUtils.nodesAlongCurve(crv=self.ikCrv, numNodes=numJoints, name=self.name, followAxis=axis, upNode=self.baseSubCtrl, upAxis=upAxis, upVec=worldUpAxis) for i in range(len(mps['mpNodes'])): mp = mps['mpNodes'][i] upVecCond.outColor.connect(mp.worldUpVector) upAxisCond.outColorR.connect(mp.upAxis) if i < numJoints / 2: self.startCtrl.worldMatrix[0].connect(mp.worldUpMatrix, f=1) else: self.endCtrl.worldMatrix[0].connect(mp.worldUpMatrix, f=1) self.baseCtrl.rotateOrder.connect(mp.rotateOrder) for grp in mps['grps']: grp.setParent(self.rigGrp) self.baseCtrl.rotateOrder.connect(grp.rotateOrder) # twisting self.twistReader = coreUtils.isolateTwist( mps['grps'][(numJoints / 2)].worldMatrix[0], mps['grps'][(numJoints / 2) - 1].worldInverseMatrix[0], name=self.name, axis=axis) twistAttr = pmc.Attribute('%s.outputRotate%s' % (self.twistReader[2].name(), axis.upper())) twistSrtList = [] for i in range(numJoints / 2): mp = mps['mpNodes'][i] grp = mps['grps'][i] g = coreUtils.addChild(grp, 'group', grp.name().replace('grp', 'twist_srt')) self.baseCtrl.rotateOrder.connect(g.rotateOrder) baseMtx.outputScale.connect(g.s) uc = coreUtils.convert(twistAttr, (1.0 / (numJoints - 1)) * i, name=g.name().replace('_srt', '_utl')) uc.output.connect(pmc.Attribute('%s.r%s' % (g.name(), axis))) twistSrtList.append(g) for i in range(numJoints - (numJoints / 2)): index = i + (numJoints / 2) mp = mps['mpNodes'][index] grp = mps['grps'][index] g = coreUtils.addChild(grp, 'group', grp.name().replace('grp', 'twist_srt')) self.baseCtrl.rotateOrder.connect(g.rotateOrder) baseMtx.outputScale.connect(g.s) uc = coreUtils.convert(twistAttr, (-1.0 / (numJoints - 1)) * ((numJoints - (numJoints / 2) - i) - 1), name=g.name().replace('_srt', '_utl')) uc.output.connect(pmc.Attribute('%s.r%s' % (g.name(), axis))) twistSrtList.append(g) # squetch for i in range(numJoints): attr = pmc.addAttr(self.settingsCtrl, longName='squetch_%s_amount' % str(i + 1).zfill(2), at='double', k=1, h=0) blend = coreUtils.blend(self.mainGrp.stretch, 1.0, name='blend_%s_squetch_%s_UTL' % (self.name, str(i + 1).zfill(2)), blendAttr=self.settingsCtrl.attr( 'squetch_%s_amount' % str(i + 1).zfill(2))) scaleDict = { 'x': mps['grps'][i].sx, 'y': mps['grps'][i].sy, 'z': mps['grps'][i].sz } for key in scaleDict.keys(): if key != axis: blend.outputR.connect(scaleDict[key]) # expose joints for i in range(numJoints): componentUtils.exposeDeformation( twistSrtList[i], '%s_%s' % (self.name, str(i + 1).zfill(2))) # colorize coreUtils.colorize('green', self.fkCtrls + [self.baseCtrl, self.settingsCtrl]) coreUtils.colorize( 'yellow', self.fkRevCtrls + [self.startCtrl, self.endCtrl, self.baseSubCtrl])
def build(self, fingerDict, addTranslateJoints): self.baseInput = coreUtils.addChild(self.inputGrp, 'group', '%s_base_in_srt' % self.name) coreUtils.align(self.baseInput, fingerDict['base']) ctrlsGrp = coreUtils.addChild(self.interfaceGrp, 'group', '%s_ctrls_srt' % self.name) d = coreUtils.isDecomposed(self.baseInput) coreUtils.connectDecomposedMatrix(d, ctrlsGrp) deformGrp = coreUtils.addChild(self.deformGrp, 'group', '%s_deform_srt' % self.name) d = coreUtils.isDecomposed(self.baseInput) coreUtils.connectDecomposedMatrix(d, deformGrp) ctrlSize = None fingerKeys = [k for k in fingerDict.keys() if not k == 'base'] for finger in fingerKeys: joints = [] fingerList = fingerDict[finger] axis = coreUtils.getDominantAxis(fingerList[0], fingerList[1]) if not ctrlSize: ctrlSize = coreUtils.getDistance(fingerList[0], fingerList[1]) * .25 for i in range(len(fingerList)): guide = fingerList[i] num = str(i+1).zfill(2) c = controls.circleBumpCtrl(radius=ctrlSize, axis=axis, name='%s_%s_%s_ctrl' % (self.name, finger, num)) coreUtils.align(c, guide) buffer = coreUtils.addParent(c, 'group', '%s_%s_%s_buffer_srt' % (self.name, finger, num)) if i == 0: buffer.setParent(ctrlsGrp) else: buffer.setParent(self.ctrls[-1]) self.ctrls.append(c) if addTranslateJoints: b = coreUtils.addChild(deformGrp, 'group', '%s_%s_%s_dfmBuffer_srt' % (self.name, finger, num)) coreUtils.align(b, buffer) jt = coreUtils.addChild(b, 'joint', '%s_%s_%s_translate_dfm' % (self.name, finger, num)) jr = coreUtils.addChild(jt, 'joint', '%s_%s_%s_rotate_dfm' % (self.name, finger, num)) self.ctrls[-1].t.connect(jt.t) self.ctrls[-1].r.connect(jr.r) self.ctrls[-1].s.connect(jr.s) if i != 0: b.setParent(joints[-1]) joints.append(jr) pmc.setAttr('%s.type' % jt, 18) jt.otherType.set('translateJoint') pmc.setAttr('%s.type' % jr, 18) jr.otherType.set('rotateJoint') else: b = coreUtils.addChild(deformGrp, 'group', '%s_%s_%s_dfmBuffer_srt' % (self.name, finger, num)) coreUtils.align(b, buffer) j = coreUtils.addChild(b, 'joint', '%s_%s_%s_dfm' % (self.name, finger, num)) self.ctrls[-1].t.connect(j.t) self.ctrls[-1].r.connect(j.r) self.ctrls[-1].s.connect(j.s) if i != 0: b.setParent(joints[-1]) joints.append(j)
def build(self, numDivisions, start, end, addMidControls, addEndControls): axisDict = {0:'x', 1:'y', 2:'z'} ctrlSize = coreUtils.getDistance(start, end) * .25 # create inputs - these should be connected to the nodes you wish to drive the twistSegment self.startIn = coreUtils.addChild(self.inputGrp, 'group', '%s_start_in_srt' % self.name) coreUtils.align(self.startIn, start) self.endIn = coreUtils.addChild(self.startIn, 'group', '%s_end_in_srt' % self.name) coreUtils.align(self.endIn, end) endTranslateList = [abs(attr.get()) for attr in [self.endIn.tx, self.endIn.ty, self.endIn.tz]] axis = axisDict[endTranslateList.index(max(endTranslateList))] upAxis = 'x' if axis in upAxis: upAxis = 'y' if pmc.getAttr('%s.t%s' % (self.endIn.name(), axis)) < 0.0: axis = '-%s' % axis self.endIn.setParent(self.inputGrp) print 'Axis = %s' % axis # build curve crv = curveUtils.curveBetweenNodes(start=self.startIn, end=self.endIn, name='%s_crv' % self.name) crv.setParent(self.rigGrp) # create attributes on main grp pmc.addAttr(self.mainGrp, ln='startAuto', at='double', minValue=0, maxValue=1, k=1, h=0) pmc.addAttr(self.mainGrp, ln='endAuto', at='double', minValue=0, maxValue=1, k=1, h=0) pmc.addAttr(self.mainGrp, ln='twist', at='double') pmc.addAttr(self.mainGrp, ln='invertTwist', at=bool, k=0, h=0) # world space srt of start and end startToSrt = coreUtils.decomposeWorldMatrix(self.startIn) endToSrt = coreUtils.decomposeWorldMatrix(self.endIn) # Vector representing direction from start to end cmpntVec = None if '-' in axis: cmpntVec = coreUtils.minus([startToSrt.outputTranslate, endToSrt.outputTranslate],'%s_cmpntVector_utl' % self.name) else: cmpntVec = coreUtils.minus([endToSrt.outputTranslate, startToSrt.outputTranslate], '%s_cmpntVector_utl' % self.name) # matrix representing cmpntVec using start as upnode cmpntVecNorm = coreUtils.normalizeVector(cmpntVec.output3D, name='%s_cmpntVectorNormalized_utl' % self.name) cmpntUpVec = coreUtils.matrixAxisToVector(self.startIn, axis=upAxis, name='%s_cmpntUpVec_utl' % self.name) normVec = coreUtils.cross(cmpntVecNorm.output, cmpntUpVec.output, name='%s_localNormalVec_utl' % self.name) orderDict = {'x': 0, 'y': 1, 'z': 2, '-x': 0, '-y': 1, '-z': 2} matrixList = ['', '', ''] matrixList[orderDict[axis]] = 'X' matrixList[orderDict[upAxis]] = 'Y' localOrientMtx = pmc.createNode('fourByFourMatrix', name='%s_localOrientMatrix_utl' % self.name) cmpntVecNorm.outputX.connect(pmc.Attribute('%s.in%s0' % (localOrientMtx.name(), matrixList.index('X')))) cmpntVecNorm.outputY.connect(pmc.Attribute('%s.in%s1' % (localOrientMtx.name(), matrixList.index('X')))) cmpntVecNorm.outputZ.connect(pmc.Attribute('%s.in%s2' % (localOrientMtx.name(), matrixList.index('X')))) cmpntUpVec.outputX.connect(pmc.Attribute('%s.in%s0' % (localOrientMtx.name(), matrixList.index('Y')))) cmpntUpVec.outputY.connect(pmc.Attribute('%s.in%s1' % (localOrientMtx.name(), matrixList.index('Y')))) cmpntUpVec.outputZ.connect(pmc.Attribute('%s.in%s2' % (localOrientMtx.name(), matrixList.index('Y')))) normVec.outputX.connect(pmc.Attribute('%s.in%s0' % (localOrientMtx.name(), matrixList.index('')))) normVec.outputY.connect(pmc.Attribute('%s.in%s1' % (localOrientMtx.name(), matrixList.index('')))) normVec.outputZ.connect(pmc.Attribute('%s.in%s2' % (localOrientMtx.name(), matrixList.index('')))) startToSrt.outputTranslateX.connect(localOrientMtx.in30) startToSrt.outputTranslateY.connect(localOrientMtx.in31) startToSrt.outputTranslateZ.connect(localOrientMtx.in32) # matrix representing positional offset of first control startEndDist = coreUtils.distanceBetweenNodes(self.startIn, self.endIn, name='%s_startEndDist_utl' % self.name) mult = .333 if '-' in axis: mult = -.333 startLocalOffsetMult = coreUtils.multiply(startEndDist.distance, mult, name='%s_startLocalOffsetMult_utl' % self.name) startLocalOffsetMtx = pmc.createNode('fourByFourMatrix', name='%s_startLocalOffsetMtx_utl' % self.name) startLocalOffsetMult.outputX.connect('%s.in3%s' % (startLocalOffsetMtx.name(), orderDict[axis[-1]])) # Matrices that convert local positional offset into either local orient space or start space startLocalMtx = coreUtils.multiplyMatrices([startLocalOffsetMtx.output, localOrientMtx.output], name='%s_startLocalMtx_utl' % self.name) startLocalMtxToSrt = coreUtils.decomposeMatrix(startLocalMtx.matrixSum, name='%s_startLocalMtxToSrt_utl' % self.name) startAutoMtx = coreUtils.multiplyMatrices([startLocalOffsetMtx.output, self.startIn.worldMatrix[0]], name='%s_startAutoMtx_utl' % self.name) startAutoMtxToSrt = coreUtils.decomposeMatrix(startAutoMtx.matrixSum, name='%s_startAutoMtxToSrt_utl' % self.name) startBlend = coreUtils.pairBlend(startLocalMtxToSrt.outputTranslate, startLocalMtxToSrt.outputRotate, startAutoMtxToSrt.outputTranslate, startAutoMtxToSrt.outputRotate, name = '%s_startAutoBlend_utl' % self.name, blendAttr=self.mainGrp.startAuto) # matrix representing positional offset of second control mult = mult *-1 endLocalOffsetMult = coreUtils.multiply(startEndDist.distance, mult, name='%s_endLocalOffsetMult_utl' % self.name) endLocalOffsetMtx = pmc.createNode('fourByFourMatrix', name='%s_endLocalOffsetMtx_utl' % self.name) endLocalOffsetMult.outputX.connect('%s.in3%s' % (endLocalOffsetMtx.name(), orderDict[axis[-1]])) # Matrices that convert local positional offset into either local orient space or start space endLocalMtx = coreUtils.multiplyMatrices([endLocalOffsetMtx.output, localOrientMtx.output], name='%s_endLocalMtx_utl' % self.name) endLocalMtxToSrt = coreUtils.decomposeMatrix(endLocalMtx.matrixSum, name='%s_endLocalMtxToSrt_utl' % self.name) endLocalPos = pmc.createNode('plusMinusAverage', name='%s_endLocalPos_utl' % self.name) if '-' in axis: endLocalPos.operation.set(2) endLocalMtxToSrt.outputTranslate.connect(endLocalPos.input3D[0]) cmpntVec.output3D.connect(endLocalPos.input3D[1]) endAutoMtx = coreUtils.multiplyMatrices([endLocalOffsetMtx.output, self.endIn.worldMatrix[0]], name='%s_endAutoMtx_utl' % self.name) endAutoMtxToSrt = coreUtils.decomposeMatrix(endAutoMtx.matrixSum, name='%s_endAutoMtxToSrt_utl' % self.name) endBlend = coreUtils.pairBlend(endLocalPos.output3D, endLocalMtxToSrt.outputRotate, endAutoMtxToSrt.outputTranslate, endAutoMtxToSrt.outputRotate, name='%s_endAutoBlend_utl' % self.name, blendAttr=self.mainGrp.endAuto) # Motion path mps = curveUtils.nodesAlongCurve(crv=crv, numNodes=numDivisions, name=self.name, followAxis=axis, upAxis=upAxis, upNode=self.startIn, upVec=upAxis, follow=1, groups=0) # twist inversion cond = pmc.createNode('condition', name='%s_twistIsInverted_utl' % self.name) self.mainGrp.twist.connect(cond.colorIfFalseR) uc = coreUtils.convert(self.mainGrp.twist, -1, name='%s_twistInvert_utl' % self.name) uc.output.connect(cond.colorIfTrueR) self.mainGrp.invertTwist.connect(cond.firstTerm) cond.secondTerm.set(1) # joints for i in range(numDivisions): num = str(i + 1).zfill(2) mp = mps['mpNodes'][i] j = pmc.joint(name='%s_%s_dfm' % (self.name, num)) j.setParent(self.deformGrp) mp.allCoordinates.connect(j.t) mp.rotate.connect(j.jointOrient) twistBlend = pmc.createNode('animBlendNodeAdditiveRotation', name='%s_%s_twistBlend_utl' % (self.name, num)) attr = pmc.Attribute('%s.inputA%s' % (twistBlend.name(), axis[-1].upper())) cond.outColorR.connect(attr) if not '-' in axis: twistBlend.weightA.set(mp.uValue.get() * -1) else: twistBlend.weightA.set(mp.uValue.get()) twistBlend.output.connect(j.r) #twisting orientInverseMtx = pmc.createNode('inverseMatrix', name='%s_localOrientInverseMatrix_utl' % self.name) localOrientMtx.output.connect(orientInverseMtx.inputMatrix) twist = coreUtils.isolateTwist(self.endIn.worldMatrix[0], orientInverseMtx.outputMatrix, name=self.name, axis=axis) twistAttr = pmc.Attribute('%s.outputRotate%s' % (twist[2].name(), axis[-1].upper())) twistAttr.connect(self.mainGrp.twist) crvShape = pmc.listRelatives(crv, c=1, s=1)[0] startToSrt.outputTranslate.connect(crvShape.controlPoints[0]) endToSrt.outputTranslate.connect(crvShape.controlPoints[3]) # bend controls if addMidControls: startCtrl = controls.squareCtrl(name='%s_start_ctrl' % self.name, axis=axis[-1], size=ctrlSize) startBuffer = coreUtils.addParent(startCtrl, 'group', '%s_startCtrl_buffer_srt' % self.name) startBuffer.setParent(self.interfaceGrp) startCtrlToSrt = coreUtils.decomposeMatrix(startCtrl.worldMatrix[0], name='%s_startCtrlWorldMtxToSrt_utl' % self.name) startBlend.outTranslate.connect(startBuffer.t) startBlend.outRotate.connect(startBuffer.r) self.ctrls.append(startCtrl) endCtrl = controls.squareCtrl(name='%s_end_ctrl' % self.name, axis=axis[-1], size=ctrlSize) endBuffer = coreUtils.addParent(endCtrl, 'group', '%s_endCtrl_buffer_srt' % self.name) endBuffer.setParent(self.interfaceGrp) endCtrlToSrt = coreUtils.decomposeMatrix(endCtrl.worldMatrix[0], name='%s_startendCtrlWorldMtxToSrt_utl' % self.name) endBlend.outTranslate.connect(endBuffer.t) endBlend.outRotate.connect(endBuffer.r) self.ctrls.append(endCtrl) startCtrlToSrt.outputTranslate.connect(crvShape.controlPoints[1]) endCtrlToSrt.outputTranslate.connect(crvShape.controlPoints[2]) else: startBlend.outTranslate.connect(crvShape.controlPoints[1]) endBlend.outTranslate.connect(crvShape.controlPoints[2]) if addEndControls: self.btmCtrl = controls.circleBumpCtrl(name='%s_btm_ctrl' % self.name, axis=axis, radius=ctrlSize) coreUtils.align(self.btmCtrl, self.startIn) btmBuffer = coreUtils.addParent(self.btmCtrl, 'group', '%s_btm_buffer_srt' % self.name) btmBuffer.setParent(self.interfaceGrp) d = coreUtils.isDecomposed(self.btmCtrl) coreUtils.connectDecomposedMatrix(d, self.startIn) self.ctrls.append(self.btmCtrl) self.topCtrl = controls.circleBumpCtrl(name='%s_top_ctrl' % self.name, axis=axis, radius=ctrlSize) coreUtils.align(self.topCtrl, self.endIn) topBuffer = coreUtils.addParent(self.topCtrl, 'group', '%s_top_buffer_srt' % self.name) topBuffer.setParent(self.interfaceGrp) d = coreUtils.isDecomposed(self.topCtrl) coreUtils.connectDecomposedMatrix(d, self.endIn) self.ctrls.append(self.topCtrl)
def buildBaseRig(name='eye', numTweaks=7, tweaks=1): ''' Create the bezier setup with corner, top and bottom controls. Radius sets the distance from the spin pivots to the rig Spread sets the width of the corners (in degrees from the centre) ''' # Base structure rootGrp = pmc.group(empty=1, name='%s_cmpnt' % name) pmc.addAttr(rootGrp, ln='rigParent', dt='string') rootGrp.rigParent.set('components_GRP') inputGrp = coreUtils.addChild(rootGrp, 'group', name='%s_input' % name) pmc.select(inputGrp) pmc.addAttr(ln='rigInputs', dt='string', multi=1) pmc.addAttr(inputGrp, at='matrix', ln='head_in_mtx') pmc.addAttr(inputGrp, at='matrix', ln='jaw_in_mtx') controlsGrp = coreUtils.addChild(rootGrp, 'group', name='%s_controls' % name) pmc.select(controlsGrp) pmc.addAttr(ln='rigInputs', dt='string', multi=1) controlsGrp.rigInputs[0].set('options_CTL.all_ctls_vis>>visibility') rigGrp = coreUtils.addChild(rootGrp, 'group', name='%s_rig' % name) rigGrp.visibility.set(0) outputGrp = coreUtils.addChild(rootGrp, 'group', name='%s_output' % name) addOutputAttrs(outputGrp) pmc.addAttr(outputGrp, ln='outputType', dt='string') # in case there is a discrepancy between the neck joint and the head control pmc.addAttr(outputGrp, ln='ctrl2Joint_offset_mtx', at='matrix') outputGrp.outputType.set('eye') # Config node config = coreUtils.addChild(controlsGrp, 'group', name='%s_config' % name) pmc.addAttr(config, ln='radius', at='double', k=0, h=0) config.radius.set(configDict['radius']) pmc.addAttr(config, ln='spread', at='doubleAngle', k=0, h=0) config.spread.set(configDict['spread']) pmc.addAttr(config, ln='height', at='double', k=0, h=0) config.height.set(configDict['height']) # Base srts rootSrt = coreUtils.addChild(controlsGrp, 'group', name='%s_root_srt' % name) headSrt = coreUtils.decomposeMatrix(inputGrp.head_in_mtx, name='%s_head_in_mtx2Srt_utl' % name) coreUtils.connectDecomposedMatrix(headSrt, rootSrt) centreSrt = coreUtils.addChild(rootSrt, 'group', name='%s_centre_srt' % name) negScaleSrt = coreUtils.addChild(centreSrt, 'group', name='%s_negScale_srt' % name) negScaleSrt.sx.set(-1) # Set up jaw blending stuff jawOffset = pmc.createNode('composeMatrix', name='%s_jawOffsetMtx_utl' % name) jawResultMtx = pmc.createNode('multMatrix', name='%s_jawResultMtx_utl' % name) jawOffset.outputMatrix.connect(jawResultMtx.matrixIn[0]) inputGrp.jaw_in_mtx.connect(jawResultMtx.matrixIn[1]) centreSrt.worldInverseMatrix[0].connect(jawResultMtx.matrixIn[2]) jawSrt = coreUtils.decomposeMatrix(jawResultMtx.matrixSum, name='%s_jawResultMtx2Srt_utl' % name) jawRotConvert = coreUtils.convert(jawSrt.outputRotateX, 1.0, name='%s_jawRotAngle2Float_utl' % name) # Spin srt + Ctrl structure ctrls = [] constGrps = [] for i in ['R', 'T', 'L', 'B']: aimDict = {'T':'up', 'L':'left', 'B':'down', 'R':'left'} constSrt = coreUtils.addChild(centreSrt, 'group', name='%s_%s_const_srt' % (name, i)) constGrps.append(constSrt) spinSrt = coreUtils.addChild(constSrt, 'group', name='%s_%s_spin_srt' % (name, i)) bufferSrt = coreUtils.addChild(spinSrt, 'group', name='%s_%s_ctrlBufferSrt' % (name, i)) negSrt = coreUtils.addChild(bufferSrt, 'group', name='%s_%s_xNegSrt' % (name, i)) ctrl = controls.triCtrl(size=config.radius.get()*.2, aim=aimDict[i], name='%s_%s_ctrl' % (name, i)) pmc.addAttr(ctrl, ln='follow_jaw', minValue=0.0, maxValue=1.0, k=1, h=0, at='double') ctrl.setParent(negSrt) config.radius.connect(bufferSrt.tz) if i == 'T': config.height.connect(bufferSrt.ty) elif i == 'B': heightInvert = coreUtils.convert(config.height, -1, name='%s_heightInvert_utl' % name) heightInvert.output.connect(bufferSrt.ty) # Negate x & y translate and connect to spin conv = coreUtils.convert(ctrl.tx, -1, name='%s_%s_invertTX_utl' % (name, i)) conv.output.connect(negSrt.tx) spinFac = coreUtils.convert(config.radius, 6.283, name='%s_%s_spinFactor_utl' % (name, i)) spinAmount = coreUtils.divide(ctrl.tx, spinFac.output, name='%s_%s_spinAmountX_utl' % (name, i)) spinConv = coreUtils.convert(spinAmount.outputX, 6.283, name='%s_%s_spinX_utl' % (name, i)) conv = coreUtils.convert(ctrl.ty, -1, name='%s_%s_invertTY_utl' % (name, i)) conv.output.connect(negSrt.ty) spinAmountY = coreUtils.divide(ctrl.ty, spinFac.output, name='%s_%s_spinAmountY_utl' % (name, i)) spinConvY = coreUtils.convert(spinAmountY.outputX, -6.283, name='%s_%s_spinY_utl' % (name, i)) if i == 'R': negScaleSrt.setParent(constSrt) spinSrt.setParent(negScaleSrt) spinSrt.s.set(1,1,1) spinSrt.r.set(0,0,0) if i == 'L' or i == 'R': spinOffset = pmc.createNode('animBlendNodeAdditiveDA', name='%s_%s_spinOffset_utl' % (name, i)) spinConv.output.connect(spinOffset.inputA) config.spread.connect(spinOffset.inputB) spinOffset.output.connect(spinSrt.ry) else: spinConv.output.connect(spinSrt.ry) spinConvY.output.connect(spinSrt.rx) spinSrt.ro.set(2) # set up jaw blending jawBlend = coreUtils.pairBlend((0,0,0), (0,0,0), jawSrt.outputTranslate, jawSrt.outputRotate, name='%s_%s_jawBlend_utl' % (name, i), blendAttr=ctrl.follow_jaw) jawBlend.outTranslate.connect(constSrt.t) jawBlend.outRotate.connect(constSrt.r) # set up corner push on jaw open if i == 'R' or i =='L': pmc.addAttr(bufferSrt, ln='jawOpenPush', at='double', k=0, h=0) rv = pmc.createNode('remapValue', name='%s_%s_jawPushRemap_utl' % (name, i)) jawAdd = pmc.createNode('animBlendNodeAdditive', name='%s_%s_jawOpenAdd_utl' % (name, i)) config.radius.connect(jawAdd.inputB) rv.outValue.connect(jawAdd.weightA) ctrl.follow_jaw.connect(rv.inputValue) jawPushMult = coreUtils.multiplyDouble(jawRotConvert.output, bufferSrt.jawOpenPush, name='%s_%s_jawPushMult' % (name, i)) jawPushMult.output.connect(jawAdd.inputA) jawAdd.output.connect(bufferSrt.tz, f=1) rv.value[1].value_Position.set(.5) rv.value[2].value_FloatValue.set(0) rv.value[2].value_Position.set(1) rv.value[0].value_Interp.set(2) rv.value[1].value_Interp.set(2) ctrls.append(ctrl) # Distance nodes for auto scaling of tangents dist_R_T = coreUtils.distanceBetweenNodes(ctrls[0], ctrls[1], name='%s_dist_R_T_utl' % name) scaledDist_R_T = coreUtils.divide(dist_R_T.distance, headSrt.outputScaleX, name='%s_scaledDist_R_T_utl' % name) dist_L_T = coreUtils.distanceBetweenNodes(ctrls[2], ctrls[1], name='%s_dist_L_T_utl' % name) scaledDist_L_T = coreUtils.divide(dist_L_T.distance, headSrt.outputScaleX, name='%s_scaledDist_L_T_utl' % name) dist_R_B = coreUtils.distanceBetweenNodes(ctrls[0], ctrls[3], name='%s_dist_R_B_utl' % name) scaledDist_R_B = coreUtils.divide(dist_R_B.distance, headSrt.outputScaleX, name='%s_scaledDist_R_B_utl' % name) dist_L_B = coreUtils.distanceBetweenNodes(ctrls[2], ctrls[3], name='%s_dist_L_B_utl' % name) scaledDist_L_B = coreUtils.divide(dist_L_B.distance, headSrt.outputScaleX, name='%s_scaledDist_L_B_utl' % name) scaledHeight = coreUtils.divide(config.height, headSrt.outputScaleY, name='%s_scaledHeight_utl' % name) # Build curves points = [(0,0,0) for i in range(7)] knots = [0,0,0,1,1,1,2,2,2] topCrv = pmc.curve(d=3, p=points, k=knots, name='%s_T_macro_crv' % name) topCrv.setParent(rigGrp) btmCrv = pmc.curve(d=3, p=points, k=knots, name='%s_B_macro_crv' % name) btmCrv.setParent(rigGrp) p1 = coreUtils.pointMatrixMult((0,0,0), ctrls[0].worldMatrix[0], name='%s_R_pos_utl' % name) p2TanLen = coreUtils.multiplyDouble(headSrt.outputScaleY, scaledHeight.outputX, name='%s_R_outTan_len_utl' % name) p2 = coreUtils.pointMatrixMult((0,0,0), ctrls[0].worldMatrix[0], name='%s_R_outTan_pos_utl' % name) p2TanLen.output.connect(p2.input1Y) p3TanLen = coreUtils.multiply(scaledDist_R_T.outputX, -.5, name='%s_T_inTan_len_utl' % name) p3 = coreUtils.pointMatrixMult(p3TanLen.output, ctrls[1].worldMatrix[0], name='%s_T_inTan_pos_utl' % name) p4 = coreUtils.pointMatrixMult((0,0,0), ctrls[1].worldMatrix[0], name='%s_T_pos_utl' % name) p5TanLen = coreUtils.multiply(scaledDist_L_T.outputX, .5, name='%s_T_outTan_len_utl' % name) p5 = coreUtils.pointMatrixMult(p5TanLen.output, ctrls[1].worldMatrix[0], name='%s_T_outTan_pos_utl' % name) p6 = coreUtils.pointMatrixMult((0,0,0), ctrls[2].worldMatrix[0], name='%s_L_inTan_pos_utl' % name) p2TanLen.output.connect(p6.input1Y) p7 = coreUtils.pointMatrixMult((0,0,0), ctrls[2].worldMatrix[0], name='%s_L_pos_utl' % name) p8TanLen = coreUtils.convert(p2TanLen.output, -1, name='%s_L_outTan_len_utl' % name) p8 = coreUtils.pointMatrixMult((0,0,0), ctrls[2].worldMatrix[0], name='%s_L_outTan_pos_utl' % name) p8TanLen.output.connect(p8.input1Y) p9TanLen = coreUtils.multiply(scaledDist_L_B.outputX, .5, name='%s_B_inTan_len_utl' % name) p9 = coreUtils.pointMatrixMult(p9TanLen.output, ctrls[3].worldMatrix[0], name='%s_B_inTan_pos_utl' % name) p10 = coreUtils.pointMatrixMult((0,0,0), ctrls[3].worldMatrix[0], name='%s_B_pos_utl' % name) p11TanLen = coreUtils.multiply(scaledDist_R_B.outputX, -.5, name='%s_B_outTan_len_utl' % name) p11 = coreUtils.pointMatrixMult(p11TanLen.output, ctrls[3].worldMatrix[0], name='%s_B_outTan_pos_utl' % name) p12 = coreUtils.pointMatrixMult((0,0,0), ctrls[0].worldMatrix[0], name='%s_R_inTan_pos_utl' % name) p8TanLen.output.connect(p12.input1Y) p1.output.connect(topCrv.controlPoints[0]) p2.output.connect(topCrv.controlPoints[1]) p3.output.connect(topCrv.controlPoints[2]) p4.output.connect(topCrv.controlPoints[3]) p5.output.connect(topCrv.controlPoints[4]) p6.output.connect(topCrv.controlPoints[5]) p7.output.connect(topCrv.controlPoints[6]) p1.output.connect(btmCrv.controlPoints[0]) p12.output.connect(btmCrv.controlPoints[1]) p11.output.connect(btmCrv.controlPoints[2]) p10.output.connect(btmCrv.controlPoints[3]) p9.output.connect(btmCrv.controlPoints[4]) p8.output.connect(btmCrv.controlPoints[5]) p7.output.connect(btmCrv.controlPoints[6]) returnDict = { 'root':rootSrt, 'topCrv':topCrv, 'btmCrv':btmCrv, 'tangents':[p2, p8], 'rigGrp':rigGrp } if not tweaks: return returnDict ##------------------------------TWEAKS-----------------------------------------## # Create motions path nodes tweakCtrls = [] tweakGrp = coreUtils.addChild(centreSrt, 'group', name='%s_tweakControls_hrc' % name) for i in range(numTweaks): num = str(i+1).zfill(2) mp = pmc.createNode('motionPath', name='%s_T_%s_tweakMotionPath_utl' % (name, num)) topCrv.worldSpace[0].connect(mp.geometryPath) mp.uValue.set(1.0 / (numTweaks-1) * i) bfr = pmc.group(empty=1, name='%s_tweak_%s_bufferSrt' % (name, num)) aim = 'up' if i==numTweaks-1 or i == 0: aim='left' ctrl = controls.triCtrl(size = configDict['radius']*.075, aim=aim, name='%s_tweak_%s_ctrl' % (name, num)) ctrl.setParent(bfr) bfrLocalPos = coreUtils.pointMatrixMult(mp.allCoordinates, centreSrt.worldInverseMatrix[0], name='%s_tweakLocalPos_%s_utl' % (name, num)) bfrLocalPos.output.connect(bfr.t) bfrAngle = pmc.createNode('angleBetween', name='%s_tweakAngle_%s_utl' % (name, num)) bfrLocalPos.output.connect(bfrAngle.vector2) bfrAngle.vector1.set((0,0,1)) euler2Quat = pmc.createNode('eulerToQuat', name='%s_tweakAngleEuler2Quat_%s_utl' % (name, num)) bfrAngle.euler.connect(euler2Quat.inputRotate) quatToEuler = pmc.createNode('quatToEuler', name='%s_tweakAngleQuat2Euler_%s_utl' % (name, num)) euler2Quat.outputQuat.connect(quatToEuler.inputQuat) quatToEuler.inputRotateOrder.set(2) bfr.ro.set(2) quatToEuler.outputRotateX.connect(bfr.rx) quatToEuler.outputRotateY.connect(bfr.ry) mp.fractionMode.set(1) tweakCtrls.append(ctrl) d = coreUtils.decomposeMatrix(ctrl.worldMatrix[0], name='%s_tweak_%s_mtx2Srt_utl' % (name, num)) if i==(numTweaks-1): tanMult = coreUtils.convert(p8.input1Y, -0.5, name='%s_T_tweakInTan_utl' % name) b = coreUtils.addChild(tweakCtrls[-1], 'group', name=bfr.name().replace('bufferSrt', 'inTan_bufferSrt')) tanMult.output.connect(b.ty) c = controls.triCtrl(size = configDict['radius']*.05, aim='up', name='%s_tweak_%s_inTan_ctrl' % (name, num)) coreUtils.align(c, b, parent=1) tweakCtrls.append(c) if i==0: tanMult = coreUtils.convert(p2.input1Y, 0.5, name='%s_T_tweakOutTan_utl' % name) b = coreUtils.addChild(tweakCtrls[0], 'group', name=bfr.name().replace('bufferSrt', 'outTan_bufferSrt')) tanMult.output.connect(b.ty) c = controls.triCtrl(size = configDict['radius']*.05, aim='up', name='%s_tweak_%s_outTan_ctrl' % (name, num)) coreUtils.align(c, b, parent=1) tweakCtrls.append(c) if d.outputTranslateX.get() < 0.0: bfr.sx.set(-1) bfr.setParent(tweakGrp) for i in range(numTweaks)[1:-1]: num = str(i+numTweaks).zfill(2) mp = pmc.createNode('motionPath', name='%s_B_%s_tweakMotionPath_utl' % (name, num)) btmCrv.worldSpace[0].connect(mp.geometryPath) mp.uValue.set(1.0 / (numTweaks-1) * i) bfr = pmc.group(empty=1, name='%s_tweak_%s_bufferSrt' % (name, num)) ctrl = controls.triCtrl(size = configDict['radius']*.075, aim='down', name='%s_tweak_%s_ctrl' % (name, num)) ctrl.setParent(bfr) bfrLocalPos = coreUtils.pointMatrixMult(mp.allCoordinates, centreSrt.worldInverseMatrix[0], name='%s_tweakLocalPos_%s_utl' % (name, num)) bfrLocalPos.output.connect(bfr.t) bfrAngle = pmc.createNode('angleBetween', name='%s_tweakAngle_%s_utl' % (name, num)) bfrLocalPos.output.connect(bfrAngle.vector2) bfrAngle.vector1.set((0,0,1)) euler2Quat = pmc.createNode('eulerToQuat', name='%s_tweakAngleEuler2Quat_%s_utl' % (name, num)) bfrAngle.euler.connect(euler2Quat.inputRotate) quatToEuler = pmc.createNode('quatToEuler', name='%s_tweakAngleQuat2Euler_%s_utl' % (name, num)) euler2Quat.outputQuat.connect(quatToEuler.inputQuat) quatToEuler.inputRotateOrder.set(2) bfr.ro.set(2) quatToEuler.outputRotateX.connect(bfr.rx) quatToEuler.outputRotateY.connect(bfr.ry) mp.fractionMode.set(1) d = coreUtils.decomposeMatrix(ctrl.worldMatrix[0], name='%s_tweak_%s_mtx2Srt_utl' % (name, num)) if i==1: tanMult = coreUtils.convert(p2.input1Y, -0.5, name='%s_B_tweakOutTan_utl' % name) b = coreUtils.addChild(tweakCtrls[0], 'group', name=tweakCtrls[0].name().replace('ctrl', 'inTan_bufferSrt')) tanMult.output.connect(b.ty) c = controls.triCtrl(size = configDict['radius']*.05, aim='down', name=tweakCtrls[0].name().replace('ctrl', 'inTan_ctrl')) coreUtils.align(c, b, parent=1) tweakCtrls.append(c) tweakCtrls.append(ctrl) if i==(numTweaks-2): tanMult = coreUtils.convert(p8.input1Y, 0.5, name='%s_B_tweakInTan_utl' % name) b = coreUtils.addChild(tweakCtrls[numTweaks], 'group', name=tweakCtrls[numTweaks].name().replace('ctrl', 'outTan_bufferSrt')) tanMult.output.connect(b.ty) c = controls.triCtrl(size = configDict['radius']*.05, aim='down', name=tweakCtrls[numTweaks].name().replace('ctrl', 'outTan_ctrl')) coreUtils.align(c, b, parent=1) tweakCtrls.append(c) if d.outputTranslateX.get() < 0.0: bfr.sx.set(-1) bfr.setParent(tweakGrp) ctrlSet = pmc.sets(ctrls + tweakCtrls, name='%s_ctls_SEL' % name) # CLEAN UP coreUtils.attrCtrl(nodeList=[ctrls[0], ctrls[2]], attrList=['sx', 'sz', 'visibility']) coreUtils.attrCtrl(nodeList=[ctrls[1], ctrls[3]], attrList=['sy', 'sz', 'visibility']) coreUtils.attrCtrl(nodeList=tweakCtrls, attrList=['sx', 'sy', 'sz', 'visibility']) coreUtils.attrCtrl(nodeList=ctrls + tweakCtrls, attrList=['aiRenderCurve', 'aiCurveWidth', 'aiSampleRate', 'aiCurveShaderR', 'aiCurveShaderG', 'aiCurveShaderB']) addOutputAttrs(outputGrp) joints = [] # top joints for i in range(len(tweakCtrls)): num = str(i+1).zfill(2) ctrl = tweakCtrls[i] t = pmc.xform(ctrl, ws=1, q=1, t=1)[0] unMirror=0 if t < 0.0: unMirror=1 faceRigging.exposeOutput(ctrl, outputGrp, 'eye', unMirror=unMirror, createJoint=0) pmc.select(None) j = pmc.joint(name='%s_T_%s_Out_Jnt' % (name, num)) joints.append(j) j.segmentScaleCompensate.set(0) pmc.addAttr(j, ln='jointIndex', at='short', k=0) j.jointIndex.set(i) pmc.addAttr(j, ln='rigType', dt='string') j.rigType.set('eye') d = coreUtils.decomposeMatrix(outputGrp.outMatrix[i], name='%s_outMtx2Srt_%s_utl' % (name, num)) coreUtils.connectDecomposedMatrix(d, j)
def addSpaceSwitch(node, name, spaces, type='parent', ctrlNode=None, targetNodes=[]): enumString = '' startIndex = 0 asset = getComponentFromName(node) choice = hasSpaceSwitch(node)[type] attr = None add = 0 if choice: add = 1 ctrlNode = pmc.listConnections(choice.selector, d=0)[0] attr = pmc.listConnections(choice.selector, d=0, p=1)[0] attrName = attr.name().split('.')[-1] enumString = pmc.attributeQuery(attrName, node=ctrlNode, listEnum=1)[0] + ':' startIndex = len(enumString.split(':')) - 1 pmc.deleteAttr(attr) else: choice = pmc.createNode('choice', name='%s_%s_%sSpaceChoice_utl' % (asset, name, type)) if not ctrlNode: ctrlNode = node for space in spaces: enumString += (space + ':') pmc.addAttr(ctrlNode, ln='%sSpace' % type, at='enum', enumName=enumString, k=1, h=0) attr = pmc.Attribute('%s.%sSpace' % (ctrlNode.name(), type)) attr.connect(choice.selector) targets = [] for i in range(len(spaces)): space = spaces[i] g = coreUtils.addChild(getComponentGroup(node, group='input'), 'group', name='%s_%s_%s_%s_in_srt' % (asset, name, space, type)) #coreUtils.align(g, node) #g.worldMatrix[0].connect(pmc.Attribute('%s.input[%s]' % (choice.name(), i + startIndex))) targets.append(g) if len(targetNodes) == len(spaces): targetNode = targetNodes[i] if getComponentFromName(node) == getComponentFromName(targetNode): if targetNode in pmc.listRelatives( getComponentGroup(targetNode, 'rig'), c=1, ad=1) or targetNode in pmc.listRelatives( getComponentGroup(targetNode, 'input'), c=1, ad=1): g.setParent(targetNode) elif targetNode in pmc.listRelatives(getComponentGroup( targetNode, 'interface'), c=1, ad=1): g.setParent(getComponentGroup(targetNode, 'rig')) d = coreUtils.isDecomposed(targetNode) coreUtils.connectDecomposedMatrix(d, g) else: connectIO(g, targetNode, space) offset = coreUtils.addChild(g, 'group', name='%s_%s_%s_%s_offset_srt' % (asset, name, space, type)) coreUtils.align(offset, node) offset.worldMatrix[0].connect( pmc.Attribute('%s.input[%s]' % (choice.name(), i + startIndex))) if not add: d = coreUtils.decomposeMatrix(choice.output, name='%s_%s_%sSpaceMtxToSrt_utl' % (asset, name, type)) if type == 'parent': coreUtils.connectDecomposedMatrix(d, node) elif type == 'translate': d.outputTranslate.connect(node.t) elif type == 'rotate': d.outputRotate.connect(node.r) return targets