def handControlSetup(self, *args): """ Create attributes on hand_cnt and connect them as needed. """ pm.addAttr(self.hand_cnt,ln='FK_IK',at='float',dv=0,min=0,max=1,k=True) # IK/FK blend color nodes pm.connectAttr( '%s.FK_IK'%self.hand_cnt, '%s.blender'%self.shldr_node1 ) pm.connectAttr( '%s.FK_IK'%self.hand_cnt, '%s.blender'%self.elbow1_node1 ) pm.connectAttr( '%s.FK_IK'%self.hand_cnt, '%s.blender'%self.elbow1_node2 ) pm.connectAttr( '%s.FK_IK'%self.hand_cnt, '%s.blender'%self.wrist_node1 ) pm.connectAttr( '%s.FK_IK'%self.hand_cnt, '%s.blender'%self.wrist_node2 ) #IK/FK controls vis switch pm.connectAttr( '%s.FK_IK'%self.hand_cnt, '%s.visibility'%self.ikChain[0] ) pm.connectAttr( '%s.FK_IK'%self.hand_cnt, '%s.visibility'%self.ikControl[0] ) pm.setDrivenKeyframe(self.fkChain[0], cd='%s.FK_IK' % self.hand_cnt, at='visibility', dv=1, v=0) pm.setDrivenKeyframe(self.fkChain[0], cd='%s.FK_IK' % self.hand_cnt, at='visibility', dv=0, v=1) # Zero hand control and parent to the following joint chian. self.zero(self.hand_cnt) bufferNode = pm.listRelatives(self.hand_cnt,parent=True) pm.parentConstraint(self.jointChain[2],bufferNode,mo=True)
def symmetryLayer(): allCtrls = pm.PyNode('CT_face_ctrl').getChildren(ad=True, type='nurbsCurve') allCtrls = set([crv.getParent() for crv in allCtrls]) # new group to hold mirrored locs symLocGrp = pm.group(em=True, n='RT_symmetryLoc_grp') allRightCtrls = [crv for crv in allCtrls if 'RT_' in crv.name()] symMatrix = pm.createNode('fourByFourMatrix', n='CT_symmetryMatrix_mat') symMatrix.in00.set(-1) for rightCtl in allRightCtrls: leftCtl = pm.PyNode(rightCtl.replace('RT_', 'LT_')) loc = pm.spaceLocator(n=rightCtl+'_symLoc') symLocGrp | loc # connect to left side mm = pm.createNode('multMatrix', n=rightCtl+'_sym_mm') symMatrix.output >> mm.matrixIn[0] leftCtl.worldMatrix >> mm.matrixIn[1] symMatrix.output >> mm.matrixIn[2] dcm = pm.createNode('decomposeMatrix', n=rightCtl+'_sym_dcm') mm.matrixSum >> dcm.inputMatrix dcm.ot >> loc.t dcm.outputRotate >> loc.r # constrain on anim layer pm.parentConstraint(loc, rightCtl, l='Symmetry', weight=1)
def create(self): grp = self.createGroup( self.groupName ) snap( self.hipsTranslationJnt, grp, type='parent') hipsTranslation = pm.group(n='hipsTranslation_hdl',em=True) snap( self.hipsTranslationJnt, hipsTranslation, type='parent') pm.parent( pm.parentConstraint( hipsTranslation, self.hipsTranslationJnt ), hipsTranslation) hipsTranslation.displayHandle.set(True) hips = pm.group(n='hips_hdl',em=True) snap( self.hipsJnt, hips, type='parent') pm.parent( pm.parentConstraint( hips, self.hipsJnt ), hips) hips.displayHandle.set(True) shoulder = pm.group(n='shoulder_hdl',em=True) snap( self.shoulderJnt, shoulder, type='parent') pm.parent( pm.parentConstraint( shoulder, self.shoulderJnt ), shoulder) setAttrs( shoulder, 'rx','ry','rz','sx','sy','sz','v', lock=True, keyable=False, channelBox=False ) shoulder.displayHandle.set(True) spines =[] for jnt in self.spineJnts: handle = pm.group(n=jnt+'_hdl',em=True) snap( jnt, handle, type='parent') pm.parent( pm.parentConstraint( handle, jnt ), handle) setAttrs( handle, 'rx','ry','rz','sx','sy','sz','v', lock=True, keyable=False, channelBox=False ) handle.displayHandle.set(True) spines.append(handle) pm.parent( hips, hipsTranslation) pm.parent( hipsTranslation, shoulder, spines, grp ) setColor( hipsTranslation, hips, shoulder, spines, c='red' )
def swap_mesh(self, new_mesh, calibrate=True): """ Change the mesh that the follicle is attached to. This is made to be used on a build InteractiveCtrlModel. :param new_mesh: A pymel.nodetypes.Mesh or pymel.nodetypes.Transform containing a mesh. """ # Resolve the node driven by the follicle. # This node contain the bindPose of the ctrl and is linked via a parentConstraint which we'll want to re-create. # todo: how do we update the constraint again? constraint = next( obj for obj in self.follicle.translate.outputs() if isinstance(obj, pymel.nodetypes.ParentConstraint)) target = constraint.getParent() pymel.delete(constraint) pos = target.getTranslation(space='world') # Get the new uv coordinates and apply them _, new_u, new_v = libRigging.get_closest_point_on_mesh(new_mesh, pos) pymel.connectAttr(new_mesh.outMesh, self.follicle.inputMesh, force=True) self.follicle.attr('parameterU').set(new_u) self.follicle.attr('parameterV').set(new_v) # Recreate the constraint pymel.parentConstraint(self.follicle, target, maintainOffset=True) if calibrate: self.calibrate()
def _connect_default_ctrl_model(self, grp_ctrl_model): """ Connect the bind pose of the avar to the bind pose of the ctrl model. This can be overriden for more complex behavior. """ # pymel.parentConstraint(self._grp_offset, grp_ctrl_model) pymel.parentConstraint(self._grp_parent, grp_ctrl_model)
def create(self): grp = self.createGroup( self.groupName ) toeBase = pm.group(n='toeBase_hdl',em=True) toeEnd = pm.group(n='toeEnd_hdl',em=True) snap( self.footJnt, grp, type='parent') snap( self.toeBaseJnt, toeBase, type='parent') snap( self.toeEndJnt, toeEnd, type='parent') pm.parent( toeBase, toeEnd, grp ) pm.parent( pm.parentConstraint( toeBase, self.toeBaseJnt ), toeBase) pm.parent( pm.parentConstraint( toeEnd, self.toeEndJnt ), toeEnd) toeBase.displayHandle.set(True) toeEnd.displayHandle.set(True) setColor( toeBase, toeEnd, c='red' ) self.toeBase = toeBase self.toeEnd = toeEnd # 부모처럼 움직일 노드에 컨스트레인 if pm.objExists('LeftFoot'): pm.parentConstraint( 'LeftFoot', grp, mo=True )
def parent_to(self, parent): """ Parent the system :param parent: The node used to parent the system :return: """ pymel.parentConstraint(parent, self._ikChainGrp, maintainOffset=True)
def FTV_generateFluidTransformSpaceGrp( name, fluidSourceData): ''' return a group that is fully constrained by fluidSourceData''' fluidSpaceTransform = pm.group( em=True, n=name ) pm.parentConstraint(fluidSourceData[0], fluidSpaceTransform) pm.scaleConstraint(fluidSourceData[0], fluidSpaceTransform) FTV_lockAndHide(fluidSpaceTransform, ['v']) return fluidSpaceTransform
def attachCurveToCtrls(self, num, mainAxis): """Excellent way to control a curve without the control objects floating away from the curve itself, the way clustering CVs would. Create num amount of ctrls, evenly spaced along the curve, then JOINTS right on top of them. parentConstrain joints to ctrls, and SKIN curve to joints. TWISTING not included.""" jnts = [] for i in range(num): pmc.select(cl=True) ctrl = self.ctrls[i] jnt = pmc.joint(n=ctrl.name().replace(self.rigData["control"], self.rigData["skinJoint"])) pmc.parentConstraint(ctrl, jnt, mo=False) # disconnect after constrain so that it is synchronized initially #pmc.Attribute(jnt+".rotate"+mainAxis).disconnect() jnts.append(jnt) jntGrp = pmc.group(jnts, n=self.rigData["root"]+self.rigData["skinJointGroup"]) jntGrp.setParent(self.rigGrp) # skin curve to joints - how to do it so that # the influences are smooth and even? # iterate through every CV, weight based on distance # from joint? Just trust it works okay? pmc.skinCluster(jnts, self.curve, maximumInfluences=2)
def makeFkIk(*args): bindRoot = pm.ls(selection = True)[0] bindChain = pm.ls(bindRoot, dag = True) fkChain = pm.duplicate(bindRoot) replaceSuffix(fkChain, 'fk') makeFk(False, fkChain) ikChain = pm.duplicate(bindRoot) replaceSuffix(ikChain, 'ik') makeIk(False, ikChain) fkChainList = pm.ls(fkChain, dag = True) ikChainList = pm.ls(ikChain, dag = True) createPad(bindRoot) suffixIndex = bindChain[0].rfind('_') hanldeName = bindChain[0][:suffixIndex] + '_switch' handle = createHandle(hanldeName) pm.rename(handle, hanldeName) pm.parentConstraint(bindChain[-1], handle) constraintList = [] for i, item in enumerate(bindChain): newConstraint = pm.orientConstraint(fkChainList[i], ikChainList[i], bindChain[i], mo = False) fkCon = pm.orientConstraint(newConstraint, q = True, wal = True)[1] ikCon = pm.orientConstraint(newConstraint, q = True, wal = True)[0] pm.setDrivenKeyframe(fkCon, cd = handle + '.switch', v = 1, dv = 10) pm.setDrivenKeyframe(fkCon, cd = handle + '.switch', v = 0, dv = 0) pm.setDrivenKeyframe(ikCon, cd = handle + '.switch', v = 0, dv = 10) pm.setDrivenKeyframe(ikCon, cd = handle + '.switch', v = 1, dv = 0)
def _makeFkControls(fkControls=None, side=None): pymelLogger.debug('Starting: _makeControls()...') topNodeList = [] for ctrl in fkControls: parent = ctrl.replace('_'+Names.suffixes['fk']+'_'+Names.suffixes['control'],'') topNode = Control.create( name=ctrl, offsets=3, shape='circle_01', size=1.5, color=_getSideColor(side), pos=None, parent=parent, typ='body' ) pm.parent(topNode, world=1) topNodeList.append(topNode) # getting ctrl and contrainting it directly to the jnt childs = topNode.listRelatives(ad=1) if 'Shape' in str(childs[0]): cc = childs[1] else: cc = childs[0] pm.parentConstraint(cc,parent, mo=1) # parent each offset to the previous ctrl topNodeList.reverse() last = '' for element in topNodeList: if last: last.setParent(element.listRelatives(ad=1)[1]) # getting transform node not shape last = element topOffsetNode = last return topOffsetNode pymelLogger.debug('End: _makeControls()...')
def setupStretchyJointSegment(self,root_joint, end_joint): """ Set up stretchy joint segments""" ## create polevector control poleVect_cont = pm.spaceLocator(name = self.userSpecifiedName + ":" + root_joint.stripNamespace() + "_poleVectorLocator") poleVect_cont_grp = pm.group(poleVect_cont, name = self.userSpecifiedName + ":" + root_joint.stripNamespace() + "_poleVectorLocatorGRP") poleVect_cont.translateY.set(-0.5) poleVect_cont.visibility.set(0) ## add stretch ik to joints ik_nodes = self.stretchy_ik(root_joint, end_joint, container = self.module_container, poleVector_object = poleVect_cont) root_locator = ik_nodes["root_locator"] end_locator = ik_nodes["end_locator"] doNotTouch_grp =ik_nodes["doNotTouch_grp"] ## determine the translation control names parent_trans_cont = self.userSpecifiedName + ":" + root_joint.stripNamespace() + "_translation_control" child_trans_cont = self.userSpecifiedName + ":" + end_joint.stripNamespace() + "_translation_control" ## point constraint root locator to root joint, end locator to translation control, root_locator to poleVectGroup pm.pointConstraint(root_joint, root_locator, maintainOffset = False, name = root_locator + "_pointConstraint") pm.pointConstraint(child_trans_cont, end_locator, maintainOffset = False, name = self.userSpecifiedName + ":" + end_locator.stripNamespace() + "_childTransContConstraint") pm.parentConstraint(parent_trans_cont, poleVect_cont_grp, maintainOffset = False, name = self.userSpecifiedName + ":" + root_locator.stripNamespace() + "_poleVectorLocatorConstraint") #utils.addNodeToContainer(self.module_container, [doNotTouch_grp], ihb = True, includeNetwork = True) return doNotTouch_grp, poleVect_cont_grp
def _parent_avar(self, avar, parent): try: avar_grp_parent = avar._grp_parent pymel.parentConstraint(parent, avar_grp_parent, maintainOffset=True) pymel.scaleConstraint(parent, avar_grp_parent, maintainOffset=True) except Exception, e: print(str(e))
def _createCurves(self, objs=None, axis=None, num=None): ''' Create two curves using .getTranslation() of passed in objects ''' _name = '_createCurves' pymelLogger.info('Started: %s' % _name) positions = [] for obj in objs: loc = pm.spaceLocator() pm.parentConstraint(obj, loc, mo=0) positions.append(pm.PyNode(loc).getTranslation()) pm.delete(loc) crv1 = pm.PyNode(pm.curve(p=positions, d=1)) crv2 = pm.PyNode(pm.curve(p=positions, d=1)) move = 0.05 if axis == 1: pm.move(crv1, move, r=1, moveX=1) pm.move(crv2, -move, r=1, moveX=1) elif axis == 2: pm.move(crv1, move, r=1, moveY=1) pm.move(crv2, -move, r=1, moveY=1) elif axis == 3: pm.move(crv1, move, r=1, moveZ=1) pm.move(crv2, -move, r=1, moveZ=1) pm.rebuildCurve( crv1, rt=0, s=num ) pm.rebuildCurve( crv2, rt=0, s=num ) pymelLogger.info('Ended: %s' % _name) return crv1, crv2
def create_bind_joint(jnt): name= jnt.name().replace('joint', "bindJoint") bind_joint = pm.duplicate(jnt, name=name, po=True)[0] pm.parentConstraint(jnt, bind_joint, mo=False) pm.scaleConstraint(jnt, bind_joint, mo=False) pm.parent(bind_joint, 'bind_joint')
def lip_setup(upperLipCurve, lowerLipCurve, upperLocators, lowerLocators, lipUp): upperLipCtrlCurve = utils.rebuild_to_ctrlCurve(upperLipCurve, spans=5, name='upperLipRCtrlCurve') lowerLipCtrlCurve = utils.rebuild_to_ctrlCurve(lowerLipCurve, spans=5, name='lowerLipRCtrlCurve') upperWireNode, upperWire, upperWireBase = utils.wire_deformer(upperLipCtrlCurve, upperLipCurve) lowerWireNode, lowerWire, lowerWireBase = utils.wire_deformer(lowerLipCtrlCurve, lowerLipCurve) upperWireMaster = utils.create_wires_master([upperWire, upperWireBase], name='upperLipRWireMaster_DELETE') lowerWireMaster = utils.create_wires_master([lowerWire, lowerWireBase], name='lowerLipRWireMaster_DELETE') #upperLocators = utils.create_locators_on_cv(upperLipCurve) for loc in upperLocators : utils.revit_locator_to_curve(loc, upperLipCurve) cmds.tangentConstraint(upperLipCurve, loc, aimVector=[1,0,0], upVector=[0,1,0], worldUpType='object', worldUpObject=lipUp) cmds.select(clear=True) j = cmds.joint() g = cmds.group(j) pm.parentConstraint(loc, g, mo=False) #lowerLocators = utils.create_locators_on_cv(lowerLipCurve) for loc in lowerLocators : utils.revit_locator_to_curve(loc, lowerLipCurve) cmds.tangentConstraint(lowerLipCurve, loc, aimVector=[1,0,0], upVector=[0,1,0], worldUpType='object', worldUpObject=lipUp) cmds.select(clear=True) j = cmds.joint() g = cmds.group(j) pm.parentConstraint(loc, g, mo=False) return upperLipCurve, lowerLipCurve, upperLipCtrlCurve, lowerLipCtrlCurve
def parent_to(self, parent): """ Parent the system to a specific object. # TODO: Implement! """ if self.grp_anm: pymel.parentConstraint(parent, self.grp_anm, maintainOffset=True)
def rig_makeBlockGeo(meshes, constrain=False, *args): ''' Args: meshes (list(pm.nt.Transform)): meshes to cut up constrain (boolean): whether to constrain them or not Returns: list (pm.nt.Transform): list of block geometries created Usage: rig_makeBlockGeo(pm.ls(sl=True), constrain=True) ''' blockgeos=[] joints=[] for mesh in meshes: skinCluster = rig_getConnectedSkinCluster(mesh) if skinCluster: joints+= skinCluster.getWeightedInfluence() if len(joints)==1: dup=pm.duplicate(mesh, n=mesh.name().replace('GEO','BLOCKGEO'))[0] blockgeos.append(dup) rig_unlockTransform(dup) pm.parentConstraint(joints[0], dup, mo=True) else: for joint in joints: blockgeo = rig_makeBlockGeoFromJoint([mesh], joint) if blockgeo: if pm.objExists(blockgeo): blockgeos+=blockgeo pm.delete(blockgeo, ch=True) if constrain: for geo in blockgeo: rig_unlockTransform(geo) pm.parentConstraint(joint, geo, mo=True) else: pm.warning('No skinCluster detected on mesh %s' % mesh) return blockgeos
def lock_child(self): selection = pm.selected() child_locker = pm.createNode("transform", name="PKD_child_locker") child_joint = pm.listRelatives(self.joint)[0] pm.parentConstraint(child_locker, child_joint, maintainOffset=True) if selection: pm.select(selection)
def build_flexi_jnts(self, follicles): """ Args: None Returns (None) """ follicle_prefix = '%s_flexiPlane_' % self.flexiPlaneNameField.getText() jntGRP_name = self.flexiPlaneNameField.getText() + '_flexiPlane_JNT_GRP' pm.group( em = True, name = jntGRP_name ) for index,follicle in enumerate(follicles): jnt_name = self.format_string.format(PREFIX = self.flexiPlaneNameField.getText(), INDEX = 'flexiPlane_jnt%03d' % (index+1), SUFFIX = 'JNT') jnt_offset_name = jnt_name.replace('_JNT','Offset_GRP') tweek_ctrlCon_name = self.format_string.format(PREFIX = self.flexiPlaneNameField.getText(), INDEX = 'flexiPlane_tweak%03d' % (index+1), SUFFIX = 'CTRLCon_GRP') pm.joint( p = ( follicle.translateX.get(), 0, 0 ), n = jnt_name ) pm.select(jnt_name, r=True) offSetGRP.add_offset_grps() pm.parent( jnt_offset_name, jntGRP_name ) pm.select( clear = True ) tweak_ctrl_con = pm.PyNode(tweek_ctrlCon_name) joint_offset = pm.PyNode(jnt_offset_name) pm.parentConstraint( tweek_ctrlCon_name, jnt_offset_name ) pm.setAttr(jnt_name + '.rotateZ', -90) pm.makeIdentity( jnt_name, apply=True, translate=True, rotate=True )
def bdConnectArms(namespace): print 'adasdasdasda' sides = {'Left':'L', 'Right':'R'} tsmArmChain = ['Arm_joint1','Arm_joint2','Arm_joint3','Arm_joint5','Arm_influence7_intermediate_constrain','Arm_joint6','Arm_joint7','Arm_joint8','Arm_joint7'] capcomArmChain = ['Shoulder','ArmDir','Arm1','Arm2','Elbow','ARoll3','ARoll4','handRot','handXR'] i=0 for jnt in tsmArmChain: try: target = pm.ls(namespace + sides['Left'] + capcomArmChain[i])[0] except: print ' cant find', capcomArmChain[i] source = pm.ls(sides.keys()[1] + jnt )[0] i+=1 pm.parentConstraint(source,target,mo=True) pm.scaleConstraint(source,target,mo=True) i=0 for jnt in tsmArmChain: target = pm.ls(namespace + sides['Right'] + capcomArmChain[i])[0] source = pm.ls(sides.keys()[0] + jnt )[0] i+=1 pm.parentConstraint(source,target,mo=True) pm.scaleConstraint(source,target,mo=True)
def create(self): grp = self.createGroup( self.groupName ) snap( self.headJnt, grp, type='parent') neck = pm.group(n='neck_hdl',em=True) head = pm.group(n='head_hdl',em=True) headEnd = pm.group(n='headEnd_hdl',em=True) snap( self.headJnt, head, type='parent') snap( self.headEndJnt, headEnd, type='parent') snap( self.neckJnt, neck, type='parent') pm.parent( headEnd, head ) pm.parent( head, neck, grp ) pm.parent( pm.parentConstraint( head, self.headJnt ), head) pm.parent( pm.parentConstraint( headEnd, self.headEndJnt ), headEnd) pm.parent( pm.parentConstraint( neck, self.neckJnt ), neck) setAttrs( head, 'sx','sy','sz','v', lock=True, keyable=False, channelBox=False ) setAttrs( headEnd, 'rx','ry','rz','sx','sy','sz','v', lock=True, keyable=False, channelBox=False ) setAttrs( neck, 'rx','ry','rz','sx','sy','sz','v', lock=True, keyable=False, channelBox=False ) head. displayHandle.set(True) headEnd.displayHandle.set(True) neck. displayHandle.set(True) setColor( neck, head, headEnd, c='red' ) self.neck = neck self.head = head self.headEnd = headEnd
def CreateFKControl(self, _joint, _parent, _moduleContainer): jointName = utils.StripAllNamespaces(_joint)[1] containedNodes = [] name = "%s_fkControl" %jointName controlObjectInstance = controlObject.ControlObject() fkControlInfo = controlObjectInstance.Create(name, "sphere.ma", self, _lod = 1, _translation = False, _rotation = True, _globalScale = False, _spaceSwitching = False) fkControl = fkControlInfo[0] pm.connectAttr("%s.rotateOrder" %_joint, "%s.rotateOrder" %fkControl) orientGrp = pm.group(name = "%s_orientGrp", empty = True, parent = _parent) containedNodes.append(orientGrp) pm.delete(pm.parentConstraint(_joint, orientGrp, maintainOffset = False)) jointParent = pm.listRelatives(_joint, parent = True)[0] orientGrp_parentConstraint = pm.parentConstraint(jointParent, orientGrp, maintainOffset = True, name = "%s_parentConstraint" %orientGrp) orientGrp_scaleConstraint = pm.scaleConstraint(jointParent, orientGrp, maintainOffset = True, name = "%s_scaleConstraint" %orientGrp) pm.parent(fkControl, orientGrp, relative = True) orientConstraint = pm.orientConstraint(fkControl, _joint, maintainOffset = False, name = "%s_orientConstraint" %_joint) containedNodes.extend([orientGrp_parentConstraint, orientGrp_scaleConstraint, orientConstraint]) utils.AddNodeToContainer(_moduleContainer, containedNodes) return fkControl
def ExtraControlForJnt( jnts=None ) : if not jnts: jnts = pm.ls( sl=True ) else: jnts = pm.ls( jnts ) for jnt in jnts: # duplicate joint pm.select( clear=True ) newJnt = pm.joint( p = [0,0,0], name= '%s_extra'%jnt.name() ) pm.delete( pm.pointConstraint( jnt, newJnt ) ) pm.delete( pm.orientConstraint( jnt, newJnt ) ) pm.parent( newJnt, jnt ) newJnt.jointOrient.set( jnt.jointOrient.get() ) # create control curve for joint ctrl = CubeCrv( name = '%s_ctrl'%jnt.name() ) pm.delete( pm.pointConstraint( jnt, ctrl ) ) pm.delete( pm.orientConstraint( jnt, ctrl ) ) zeroAndOfs = ZeroGrp( ctrl ) ctrl.translate >> newJnt.translate ctrl.rotate >> newJnt.rotate ctrl.scale >> newJnt.scale # make controls to move with base joints pm.parentConstraint( jnt, zeroAndOfs[0] ) pm.scaleConstraint( jnt, zeroAndOfs[0] )
def bdSwitchFKIK(self): if 'arm' in self.limb: print self.side + ' arm FK->IK switch ' for loc in self.ikArmCons: shadowLoc = pm.ls(self.namespace + self.side + loc + 'LOC')[0] tempLoc = pm.duplicate(shadowLoc) pm.parent(tempLoc,w=True) ikCon = pm.ls(self.namespace + self.side + loc + 'CON',type='transform')[0] if ikCon.name().find('armIK') > 0: tempCnstr = pm.parentConstraint(tempLoc,ikCon) else: tempCnstr = pm.pointConstraint(tempLoc,ikCon) pm.delete([tempCnstr,tempLoc]) self.armSwitchCon.attr('ikFkBlend').set(0) elif 'leg' in self.limb: print self.side + ' leg FK->IK switch ' for loc in self.ikLegCons: shadowLoc = pm.ls(self.namespace + self.side + loc + 'LOC')[0] tempLoc = pm.duplicate(shadowLoc) pm.parent(tempLoc,w=True) ikCon = pm.ls(self.namespace + self.side + loc + 'CON',type='transform')[0] if ikCon.name().find('legIK') > 0: tempCnstr = pm.parentConstraint(tempLoc,ikCon) else: tempCnstr = pm.pointConstraint(tempLoc,ikCon) pm.delete([tempCnstr,tempLoc]) self.legSwitchCon.attr('ikFkBlend').set(0)
def carBodyFix(): constraints=['l_frontDoorOffset_GRP_parentConstraint1', 'r_frontDoorOffset_GRP_parentConstraint1', 'l_rearDoorOffset_GRP_parentConstraint1', 'r_rearDoorOffset_GRP_parentConstraint1', 'frontBumperOffset_GRP_parentConstraint1', 'hoodOffset_GRP_parentConstraint1', 'rearBumperOffset_GRP_parentConstraint1', 'antennaOffset_GRP_parentConstraint1', 'trunkOffset_GRP_parentConstraint1', 'l_wiperOffset_GRP_parentConstraint1', 'r_wiperOffset_GRP_parentConstraint1'] pm.delete(constraints) groups = ['r_wiperOffset_GRP', 'l_wiperOffset_GRP', 'trunkOffset_GRP', 'antennaOffset_GRP', 'rearBumperOffset_GRP', 'hoodOffset_GRP', 'frontBumperOffset_GRP', 'r_rearDoorOffset_GRP', 'l_rearDoorOffset_GRP', 'r_frontDoorOffset_GRP', 'l_frontDoorOffset_GRP'] for group in groups: pm.parentConstraint('bodyJA_JNT', group, mo=True)
def createDynamicChainLocators(self, prefix = ''): #set instance prefix var self.setPrefix(prefix) pm.select(cl = True) #Create Space locators and translate self.dynamic_chain_locator_base = pm.spaceLocator(n = self.prefix + '_dynamic_chain_locator_base') self.dynamic_chain_locator_base.translate.set(0, 0, 0) pm.select(cl = True) self.dynamic_chain_locator_tip = pm.spaceLocator(n = self.prefix + '_dynamic_chain_locator_tip') self.dynamic_chain_locator_tip.translate.set(0, 10, 0) pm.select(cl = True) #Create Annotations and rename self.annotation_dynamic_chain_locator_base = pm.annotate( self.dynamic_chain_locator_base, tx = self.prefix +'_dynamic_chain_base' ) pm.rename(self.annotation_dynamic_chain_locator_base.getParent().name(), self.prefix + '_dynamic_chain_base_annotation') self.annotation_dynamic_chain_locator_tip = pm.annotate( self.dynamic_chain_locator_tip, tx = self.prefix +'_dynamic_chain_tip' ) pm.rename(self.annotation_dynamic_chain_locator_tip.getParent().name(), self.prefix + '_dynamic_chain_tip_annotation') pm.select(cl = True) #Parent constrain annotation transforms pm.parentConstraint(self.dynamic_chain_locator_base, self.annotation_dynamic_chain_locator_base.getParent(), mo = False) pm.parentConstraint(self.dynamic_chain_locator_tip, self.annotation_dynamic_chain_locator_tip.getParent(), mo = False)
def attach_to_plane(self, constraint_rot=True): """ Create follicle attached to the place for each input joint :param constraint_rot: Are the joints will be constraint in rotation on the follicle :return: Nothing """ nomenclature_rig = self.get_nomenclature_rig() fol_v = 0.5 # Always in the center #split_value = 1.0 / (len(self.chain_jnt) - 1) for i, jnt in enumerate(self.chain_jnt): #fol_u = split_value * i # TODO: Validate that we don't need to inverse the rotation separately. jnt_pos = jnt.getMatrix(worldSpace=True).translate pos, fol_u, fol_v = libRigging.get_closest_point_on_surface(self._ribbon_shape, jnt_pos) fol_name = nomenclature_rig.resolve("ribbonFollicle{0:02d}".format(i)) fol_shape = libRigging.create_follicle2(self._ribbon_shape, u=fol_u, v=fol_v) fol = fol_shape.getParent() fol.rename(fol_name) if constraint_rot: pymel.parentConstraint(fol, jnt, mo=True) else: pymel.pointConstraint(fol, jnt, mo=True) self._follicles.append(fol)
def rig_transformer_piece(transform): """ Usage: rig_transformer_piece( pm.ls(sl=True)[0] ) """ if get_parentConstraintPairs(transform): # create a control and store its groups/parts ctrl_GRP = create_boundingBoxCtrl(transform) ctrl = [ctrl for ctrl in ctrl_GRP.listRelatives(c=True, type="transform") if "CTRL" in ctrl.name()][0] ctrlCon_GRP = [ con_grp for con_grp in ctrl.listRelatives(c=True, type="transform") if "Con_GRP" in con_grp.name() ][0] # get the parent constraint information and then remove it target_weight_pairs = get_parentConstraintPairs(transform) pm.delete(target_weight_pairs[1]) # setup the new space switching based on the old parent constraint parents = [target_weight_pairs[0][0][0], "spineJA_JNT", "spineJF_JNT", "globalB_CTRL", "worldSpace_GRP"] parent_names = ["normal", "hips", "chest", "global", "world"] ctrl_setupSpaceSwitch(ctrl, ctrl_GRP, parents, parent_names) # control the object with the new space-switch controller pm.parentConstraint(ctrlCon_GRP, transform, mo=True) pm.scaleConstraint(ctrlCon_GRP, transform, mo=True) else: # if it didn't have a parentConstraint do nothing return None
def rigParentControl( joint_name ): jnt = pm.nt.Transform(joint_name) grp = pm.group(name="%s_parent"%jnt, em=True) pm.parent(grp, joint_name) grp.t.set([0,0,0]) grp.r.set([0,0,0]) pm.parent(grp, world=1) try: rig, rig_type = pm.ls('rig',showType=1) except: rig, rig_type = (None, None) if rig_type == 'transform': pm.parent(grp,rig) pm.parentConstraint( jnt.getParent(), grp, mo=1, w=1) grp.t.lock() grp.r.lock() grp.s.lock() control = createNurbsShape("%s_control"%jnt,"cube",width=0.5, height=0.5, depth=0.5) addToSet( [control], 'controlsSet' ) pm.parent(control,grp) control.t.set([0,0,0]) control.r.set([0,0,0]) control.displayHandle.set(1) pm.parentConstraint( control, jnt, mo=1, w=1) pm.select( control, r=1 ) return [ control ]
def ConstrainLoc2Joint(self): self.Constraint = pm.parentConstraint(self.Joint, self.Loc)
def buildMouth(self, crv, numCtrls, numLipJoints, cleanup): if not crv: return 'DrMouth: Please provide a curve for the mouth to ride along' self.topLip = drRail.DrRail(name='topLip', crv=crv, numCtrls=numCtrls, numSubCtrls=numLipJoints) self.topLip.main_grp.end_uValue.set(1.0) self.topLip.main_grp.setParent(self.main_grp) self.btmLip = drRail.DrRail(name='btmLip', crv=crv, numCtrls=numCtrls, numSubCtrls=numLipJoints) self.btmLip.main_grp.end_uValue.set(1.0) self.btmLip.main_grp.setParent(self.main_grp) ctrlSize = coreUtils.getDistance(crv.getCV(0), crv.getCV(1)) * .5 self.rtCtrl = controls.circleBumpCtrl(radius=ctrlSize, name='%s_rt_corner_CTRL' % self.name) coreUtils.align(self.rtCtrl, self.topLip.ctrls[0]) self.rtCtrl.setParent(self.ctrls_grp) zero = coreUtils.addParent(self.rtCtrl, 'group', '%s_rt_cornerCtrl_ZERO' % self.name) coreUtils.colorize('red', [self.rtCtrl]) self.lfCtrl = controls.circleBumpCtrl(radius=ctrlSize, name='%s_lf_corner_CTRL' % self.name) coreUtils.align(self.lfCtrl, self.topLip.ctrls[-1]) self.lfCtrl.setParent(self.ctrls_grp) zero = coreUtils.addParent(self.lfCtrl, 'group', '%s_lf_cornerCtrl_ZERO' % self.name) coreUtils.colorize('blue', [self.lfCtrl]) zero.sx.set(-1) #split into left and right for i in range(numCtrls): topCtrl = self.topLip.ctrls[i] topLoc = self.topLip.locs[i] btmCtrl = self.btmLip.ctrls[i] btmLoc = self.btmLip.locs[i] if i < numCtrls / 2: coreUtils.colorize('red', [topCtrl, btmCtrl]) elif i > numCtrls / 2: coreUtils.colorize('blue', [topCtrl, btmCtrl]) topCtrl.getParent().sx.set(-1) topLoc.getParent().sx.set(-1) btmCtrl.getParent().sx.set(-1) btmLoc.getParent().sx.set(-1) else: coreUtils.colorize('green', [topCtrl, btmCtrl]) if i == 0: pmc.delete([topCtrl.getParent(), btmCtrl.getParent()]) if i == (numCtrls - 1): pmc.delete([topCtrl.getParent(), btmCtrl.getParent()]) self.topLip.ctrls = self.topLip.ctrls[1:-1] self.btmLip.ctrls = self.btmLip.ctrls[1:-1] #split subCtrls into left and right for i in range(numLipJoints): topCtrl = self.topLip.subCtrls[i] topDrv = self.topLip.drivenGrps[i] btmCtrl = self.btmLip.subCtrls[i] btmDrv = self.btmLip.drivenGrps[i] if i < numLipJoints / 2: coreUtils.colorize('red', [topCtrl, btmCtrl]) elif i > numLipJoints / 2: coreUtils.colorize('blue', [topCtrl, btmCtrl]) topCtrl.getParent().sx.set(-1) topDrv.sx.set(-1) btmCtrl.getParent().sx.set(-1) btmDrv.sx.set(-1) else: coreUtils.colorize('green', [topCtrl, btmCtrl]) rt_loc = coreUtils.addChild(self.rig_grp, 'locator', '%s_rt_corner_LOC' % self.name) coreUtils.align(rt_loc, self.rtCtrl) rt_zero = coreUtils.addParent(rt_loc, 'group', '%s_rt_cornerLoc_ZERO' % self.name) self.rtCtrl.t.connect(rt_loc.t) self.rtCtrl.getParent().t.connect(rt_zero.t) rtCornerClosestPoint = pmc.createNode( 'nearestPointOnCurve', name='closestCrvPoint_%s_rt_corner_UTL' % self.name) locShape = pmc.listRelatives(rt_loc, s=1, c=1)[0] locShape.worldPosition[0].connect(rtCornerClosestPoint.inPosition) crvShape = coreUtils.getShape(crv) crvShape.worldSpace[0].connect(rtCornerClosestPoint.inputCurve) rtCornerClosestPoint.parameter.connect( self.topLip.main_grp.start_uValue) rtCornerClosestPoint.parameter.connect( self.btmLip.main_grp.start_uValue) self.rtCtrl.ty.connect(self.topLip.locs[0].ty) self.rtCtrl.tz.connect(self.topLip.locs[0].tz) self.rtCtrl.ty.connect(self.btmLip.locs[0].ty) self.rtCtrl.tz.connect(self.btmLip.locs[0].tz) lf_loc = coreUtils.addChild(self.rig_grp, 'locator', '%s_lf_corner_LOC' % self.name) coreUtils.align(lf_loc, self.lfCtrl) lf_zero = coreUtils.addParent(lf_loc, 'group', '%s_lf_cornerLoc_ZERO' % self.name) self.lfCtrl.t.connect(lf_loc.t) self.lfCtrl.getParent().t.connect(lf_zero.t) lfCornerClosestPoint = pmc.createNode( 'nearestPointOnCurve', name='closestCrvPoint_%s_lf_corner_UTL' % self.name) locShape = pmc.listRelatives(lf_loc, s=1, c=1)[0] locShape.worldPosition[0].connect(lfCornerClosestPoint.inPosition) crvShape.worldSpace[0].connect(lfCornerClosestPoint.inputCurve) lfCornerClosestPoint.parameter.connect(self.topLip.main_grp.end_uValue) lfCornerClosestPoint.parameter.connect(self.btmLip.main_grp.end_uValue) self.lfCtrl.ty.connect(self.topLip.locs[-1].ty) self.lfCtrl.tz.connect(self.topLip.locs[-1].tz) self.lfCtrl.ty.connect(self.btmLip.locs[-1].ty) self.lfCtrl.tz.connect(self.btmLip.locs[-1].tz) # Constrain systems pmc.parentConstraint(self.ctrls_grp, self.topLip.const_grp) pmc.scaleConstraint(self.ctrls_grp, self.topLip.const_grp) pmc.parentConstraint(self.ctrls_grp, self.btmLip.const_grp) pmc.scaleConstraint(self.ctrls_grp, self.btmLip.const_grp) if cleanup: self.cleanup()
def addOperators(self): """Create operators and set the relations for the component rig Apply operators, constraints, expressions to the hierarchy. In order to keep the code clean and easier to debug, we shouldn't create any new object in this method. """ # Auto bend ---------------------------- if self.settings["autoBend"]: mul_node = node.createMulNode( [self.autoBendChain[0].ry, self.autoBendChain[0].rz], [self.sideBend_att, self.frontBend_att], ) mul_node.outputX >> self.ik1autoRot_lvl.rz mul_node.outputY >> self.ik1autoRot_lvl.rx self.ikHandleAutoBend = primitive.addIkHandle( self.autoBend_ctl, self.getName("ikHandleAutoBend"), self.autoBendChain, "ikSCsolver", ) # Tangent position --------------------------------- # common part d = vector.getDistance(self.guide.apos[0], self.guide.apos[-1]) dist_node = node.createDistNode(self.ik0_ctl, self.ik1_ctl) rootWorld_node = node.createDecomposeMatrixNode( self.root.attr("worldMatrix")) div_node = node.createDivNode(dist_node + ".distance", rootWorld_node + ".outputScaleX") div_node = node.createDivNode(div_node + ".outputX", d) # tan0 mul_node = node.createMulNode(self.tan0_att, self.tan0_npo.getAttr("ty")) res_node = node.createMulNode(mul_node + ".outputX", div_node + ".outputX") pm.connectAttr(res_node + ".outputX", self.tan0_npo.attr("ty")) # tan1 mul_node = node.createMulNode(self.tan1_att, self.tan1_npo.getAttr("ty")) res_node = node.createMulNode(mul_node + ".outputX", div_node + ".outputX") pm.connectAttr(res_node + ".outputX", self.tan1_npo.attr("ty")) # Tangent Mid -------------------------------------- if self.settings["centralTangent"]: tanIntMat = applyop.gear_intmatrix_op( self.tan0_npo.attr("worldMatrix"), self.tan1_npo.attr("worldMatrix"), 0.5, ) applyop.gear_mulmatrix_op( tanIntMat.attr("output"), self.tan_npo.attr("parentInverseMatrix[0]"), self.tan_npo, ) pm.connectAttr(self.tan_ctl.attr("translate"), self.tan0_off.attr("translate")) pm.connectAttr(self.tan_ctl.attr("translate"), self.tan1_off.attr("translate")) # Curves ------------------------------------------- op = applyop.gear_curveslide2_op(self.slv_crv, self.mst_crv, 0, 1.5, 0.5, 0.5) pm.connectAttr(self.position_att, op + ".position") pm.connectAttr(self.maxstretch_att, op + ".maxstretch") pm.connectAttr(self.maxsquash_att, op + ".maxsquash") pm.connectAttr(self.softness_att, op + ".softness") # Volume driver ------------------------------------ crv_node = node.createCurveInfoNode(self.slv_crv) # Division ----------------------------------------- for i in range(self.settings["division"]): # References u = i / (self.settings["division"] - 1.0) if i == 0: # we add extra 10% to the first vertebra u = (1.0 / (self.settings["division"] - 1.0)) / 10 cns = applyop.pathCns(self.div_cns[i], self.slv_crv, False, u, True) cns.setAttr("frontAxis", 1) # front axis is 'Y' cns.setAttr("upAxis", 0) # front axis is 'X' # Roll intMatrix = applyop.gear_intmatrix_op( self.ik0_ctl + ".worldMatrix", self.ik1_ctl + ".worldMatrix", u) dm_node = node.createDecomposeMatrixNode(intMatrix + ".output") pm.connectAttr(dm_node + ".outputRotate", self.twister[i].attr("rotate")) pm.parentConstraint(self.twister[i], self.ref_twist[i], maintainOffset=True) pm.connectAttr(self.ref_twist[i] + ".translate", cns + ".worldUpVector") # compensate scale reference div_node = node.createDivNode( [1, 1, 1], [ rootWorld_node + ".outputScaleX", rootWorld_node + ".outputScaleY", rootWorld_node + ".outputScaleZ", ], ) # Squash n Stretch op = applyop.gear_squashstretch2_op( self.scl_transforms[i], self.root, pm.arclen(self.slv_crv), "y", div_node + ".output", ) pm.connectAttr(self.volume_att, op + ".blend") pm.connectAttr(crv_node + ".arcLength", op + ".driver") pm.connectAttr(self.st_att[i], op + ".stretch") pm.connectAttr(self.sq_att[i], op + ".squash") # Controlers if i == 0: mulmat_node = applyop.gear_mulmatrix_op( self.div_cns[i].attr("worldMatrix"), self.root.attr("worldInverseMatrix"), ) dm_node = node.createDecomposeMatrixNode(mulmat_node + ".output") pm.connectAttr(dm_node + ".outputTranslate", self.fk_npo[i].attr("t")) else: mulmat_node = applyop.gear_mulmatrix_op( self.div_cns[i].attr("worldMatrix"), self.div_cns[i - 1].attr("worldInverseMatrix"), ) dm_node = node.createDecomposeMatrixNode(mulmat_node + ".output") mul_node = node.createMulNode(div_node + ".output", dm_node + ".outputTranslate") pm.connectAttr(mul_node + ".output", self.fk_npo[i].attr("t")) pm.connectAttr(dm_node + ".outputRotate", self.fk_npo[i].attr("r")) # Orientation Lock if i == 0: dm_node = node.createDecomposeMatrixNode(self.ik0_ctl + ".worldMatrix") blend_node = node.createBlendNode( [dm_node + ".outputRotate%s" % s for s in "XYZ"], [cns + ".rotate%s" % s for s in "XYZ"], self.lock_ori0_att, ) self.div_cns[i].attr("rotate").disconnect() pm.connectAttr(blend_node + ".output", self.div_cns[i] + ".rotate") elif i == self.settings["division"] - 1: dm_node = node.createDecomposeMatrixNode(self.ik1_ctl + ".worldMatrix") blend_node = node.createBlendNode( [dm_node + ".outputRotate%s" % s for s in "XYZ"], [cns + ".rotate%s" % s for s in "XYZ"], self.lock_ori1_att, ) self.div_cns[i].attr("rotate").disconnect() pm.connectAttr(blend_node + ".output", self.div_cns[i] + ".rotate") # Connections (Hooks) ------------------------------ pm.parentConstraint(self.hip_lvl, self.cnx0) pm.scaleConstraint(self.hip_lvl, self.cnx0) pm.parentConstraint(self.scl_transforms[-1], self.cnx1) pm.scaleConstraint(self.scl_transforms[-1], self.cnx1)
def addOperators(self): # Visibilities ------------------------------------- # fk fkvis_node = nod.createReverseNode(self.blend_att) for shp in self.fk0_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) for shp in self.fk1_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) for shp in self.fk2_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) # ik for shp in self.upv_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ikcns_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ik_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) # Controls ROT order ----------------------------------- att.setRotOrder(self.fk0_ctl, "XZY") att.setRotOrder(self.fk1_ctl, "XYZ") att.setRotOrder(self.fk2_ctl, "YZX") att.setRotOrder(self.ik_ctl, "ZYX") # IK Solver ----------------------------------------- out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_loc] node = aop.gear_ikfk2bone_op(out, self.root, self.ik_ref, self.upv_ctl, self.fk_ctl[0], self.fk_ctl[1], self.fk_ref, self.length0, self.length1, self.negate) pm.connectAttr(self.blend_att, node + ".blend") pm.connectAttr(self.roll_att, node + ".roll") pm.connectAttr(self.scale_att, node + ".scaleA") pm.connectAttr(self.scale_att, node + ".scaleB") pm.connectAttr(self.maxstretch_att, node + ".maxstretch") pm.connectAttr(self.slide_att, node + ".slide") pm.connectAttr(self.softness_att, node + ".softness") pm.connectAttr(self.reverse_att, node + ".reverse") # Twist references --------------------------------- node = aop.gear_mulmatrix_op(self.eff_loc.attr("worldMatrix"), self.root.attr("worldInverseMatrix")) dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(node + ".output", dm_node + ".inputMatrix") pm.connectAttr(dm_node + ".outputTranslate", self.tws2_npo.attr("translate")) dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(node + ".output", dm_node + ".inputMatrix") pm.connectAttr(dm_node + ".outputRotate", self.tws2_npo.attr("rotate")) #spline IK for twist jnts self.ikhArmTwist, self.armTwistCrv = aop.splineIK( self.getName("armTwist"), self.armTwistChain, parent=self.root, cParent=self.bone0) self.ikhForearmTwist, self.forearmTwistCrv = aop.splineIK( self.getName("forearmTwist"), self.forearmTwistChain, parent=self.root, cParent=self.bone1) #references self.ikhArmRef, self.tmpCrv = aop.splineIK(self.getName("armRollRef"), self.armRollRef, parent=self.root, cParent=self.bone0) self.ikhForearmRef, self.tmpCrv = aop.splineIK( self.getName("forearmRollRef"), self.forearmRollRef, parent=self.root, cParent=self.eff_loc) self.ikhAuxTwist, self.tmpCrv = aop.splineIK(self.getName("auxTwist"), self.auxTwistChain, parent=self.root, cParent=self.eff_loc) #setting connexions for ikhArmTwist self.ikhArmTwist.attr("dTwistControlEnable").set(True) self.ikhArmTwist.attr("dWorldUpType").set(4) self.ikhArmTwist.attr("dWorldUpAxis").set(3) self.ikhArmTwist.attr("dWorldUpVectorZ").set(1.0) self.ikhArmTwist.attr("dWorldUpVectorY").set(0.0) self.ikhArmTwist.attr("dWorldUpVectorEndZ").set(1.0) self.ikhArmTwist.attr("dWorldUpVectorEndY").set(0.0) pm.connectAttr(self.armRollRef[0].attr("worldMatrix[0]"), self.ikhArmTwist.attr("dWorldUpMatrix")) pm.connectAttr(self.bone0.attr("worldMatrix[0]"), self.ikhArmTwist.attr("dWorldUpMatrixEnd")) #setting connexions for ikhAuxTwist self.ikhAuxTwist.attr("dTwistControlEnable").set(True) self.ikhAuxTwist.attr("dWorldUpType").set(4) self.ikhAuxTwist.attr("dWorldUpAxis").set(3) self.ikhAuxTwist.attr("dWorldUpVectorZ").set(1.0) self.ikhAuxTwist.attr("dWorldUpVectorY").set(0.0) self.ikhAuxTwist.attr("dWorldUpVectorEndZ").set(1.0) self.ikhAuxTwist.attr("dWorldUpVectorEndY").set(0.0) pm.connectAttr(self.forearmRollRef[0].attr("worldMatrix[0]"), self.ikhAuxTwist.attr("dWorldUpMatrix")) pm.connectAttr(self.eff_loc.attr("worldMatrix[0]"), self.ikhAuxTwist.attr("dWorldUpMatrixEnd")) pm.connectAttr(self.auxTwistChain[1].attr("rx"), self.ikhForearmTwist.attr("twist")) pm.parentConstraint(self.bone1, self.aux_npo, maintainOffset=True) #scale arm length for twist chain (not the squash and stretch) arclen_node = pm.arclen(self.armTwistCrv, ch=True) alAttrArm = arclen_node.attr("arcLength") muldiv_nodeArm = pm.createNode("multiplyDivide") pm.connectAttr(arclen_node.attr("arcLength"), muldiv_nodeArm.attr("input1X")) muldiv_nodeArm.attr("input2X").set(alAttrArm.get()) muldiv_nodeArm.attr("operation").set(2) for jnt in self.armTwistChain: pm.connectAttr(muldiv_nodeArm.attr("outputX"), jnt.attr("sx")) #scale forearm length for twist chain (not the squash and stretch) arclen_node = pm.arclen(self.forearmTwistCrv, ch=True) alAttrForearm = arclen_node.attr("arcLength") muldiv_nodeForearm = pm.createNode("multiplyDivide") pm.connectAttr(arclen_node.attr("arcLength"), muldiv_nodeForearm.attr("input1X")) muldiv_nodeForearm.attr("input2X").set(alAttrForearm.get()) muldiv_nodeForearm.attr("operation").set(2) for jnt in self.forearmTwistChain: pm.connectAttr(muldiv_nodeForearm.attr("outputX"), jnt.attr("sx")) #scale compensation for the first twist join dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(self.root.attr("worldMatrix[0]"), dm_node.attr("inputMatrix")) pm.connectAttr(dm_node.attr("outputScale"), self.armTwistChain[0].attr("inverseScale")) pm.connectAttr(dm_node.attr("outputScale"), self.forearmTwistChain[0].attr("inverseScale")) #tangent controls muldiv_node = pm.createNode("multiplyDivide") muldiv_node.attr("input2X").set(-1) pm.connectAttr(self.tws1A_npo.attr("rz"), muldiv_node.attr("input1X")) muldiv_nodeBias = pm.createNode("multiplyDivide") pm.connectAttr(muldiv_node.attr("outputX"), muldiv_nodeBias.attr("input1X")) pm.connectAttr(self.roundness_att, muldiv_nodeBias.attr("input2X")) pm.connectAttr(muldiv_nodeBias.attr("outputX"), self.tws1A_loc.attr("rz")) if self.negate: axis = "xz" else: axis = "-xz" aop.aimCns(self.tws1A_npo, self.tws0_loc, axis=axis, wupType=2, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) aop.aimCns(self.forearmTangentB_loc, self.forearmTangentA_npo, axis=axis, wupType=2, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) pm.pointConstraint(self.eff_loc, self.forearmTangentB_loc) muldiv_node = pm.createNode("multiplyDivide") muldiv_node.attr("input2X").set(-1) pm.connectAttr(self.tws1B_npo.attr("rz"), muldiv_node.attr("input1X")) muldiv_nodeBias = pm.createNode("multiplyDivide") pm.connectAttr(muldiv_node.attr("outputX"), muldiv_nodeBias.attr("input1X")) pm.connectAttr(self.roundness_att, muldiv_nodeBias.attr("input2X")) pm.connectAttr(muldiv_nodeBias.attr("outputX"), self.tws1B_loc.attr("rz")) if self.negate: axis = "-xz" else: axis = "xz" aop.aimCns(self.tws1B_npo, self.tws2_loc, axis=axis, wupType=2, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) aop.aimCns(self.armTangentA_loc, self.armTangentB_npo, axis=axis, wupType=2, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) # Volume ------------------------------------------- distA_node = nod.createDistNode(self.tws0_loc, self.tws1_loc) distB_node = nod.createDistNode(self.tws1_loc, self.tws2_loc) add_node = nod.createAddNode(distA_node + ".distance", distB_node + ".distance") div_node = nod.createDivNode(add_node + ".output", self.root.attr("sx")) dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(self.root.attr("worldMatrix"), dm_node + ".inputMatrix") div_node2 = nod.createDivNode(div_node + ".outputX", dm_node + ".outputScaleX") self.volDriver_att = div_node2 + ".outputX" # connecting tangent scaele compensation after volume to aboid duplicate some nodes ------------------------------ distA_node = nod.createDistNode(self.tws0_loc, self.mid_ctl) distB_node = nod.createDistNode(self.mid_ctl, self.tws2_loc) div_nodeArm = nod.createDivNode(distA_node + ".distance", dm_node.attr("outputScaleX")) div_node2 = nod.createDivNode(div_nodeArm + ".outputX", distA_node.attr("distance").get()) pm.connectAttr(div_node2.attr("outputX"), self.tws1A_loc.attr("sx")) pm.connectAttr(div_node2.attr("outputX"), self.armTangentA_loc.attr("sx")) div_nodeForearm = nod.createDivNode(distB_node + ".distance", dm_node.attr("outputScaleX")) div_node2 = nod.createDivNode(div_nodeForearm + ".outputX", distB_node.attr("distance").get()) pm.connectAttr(div_node2.attr("outputX"), self.tws1B_loc.attr("sx")) pm.connectAttr(div_node2.attr("outputX"), self.forearmTangentB_loc.attr("sx")) #conection curve aop.gear_curvecns_op(self.armTwistCrv, [ self.armTangentA_loc, self.armTangentA_ctl, self.armTangentB_ctl, self.elbowTangent_ctl ]) aop.gear_curvecns_op(self.forearmTwistCrv, [ self.elbowTangent_ctl, self.forearmTangentA_ctl, self.forearmTangentB_ctl, self.forearmTangentB_loc ]) #Tangent controls vis pm.connectAttr(self.tangentVis_att, self.armTangentA_ctl.attr("visibility")) pm.connectAttr(self.tangentVis_att, self.armTangentB_ctl.attr("visibility")) pm.connectAttr(self.tangentVis_att, self.forearmTangentA_ctl.attr("visibility")) pm.connectAttr(self.tangentVis_att, self.forearmTangentB_ctl.attr("visibility")) pm.connectAttr(self.tangentVis_att, self.elbowTangent_ctl.attr("visibility")) # Divisions ---------------------------------------- # at 0 or 1 the division will follow exactly the rotation of the controler.. and we wont have this nice tangent + roll for i, div_cns in enumerate(self.div_cns): if i < (self.settings["div0"] + 2): mulmat_node = aop.gear_mulmatrix_op( self.armTwistChain[i] + ".worldMatrix", div_cns + ".parentInverseMatrix") else: mulmat_node = aop.gear_mulmatrix_op( self.forearmTwistChain[i - (self.settings["div0"] + 2)] + ".worldMatrix", div_cns + ".parentInverseMatrix") dm_node = nod.createDecomposeMatrixNode(mulmat_node + ".output") pm.connectAttr(dm_node + ".outputTranslate", div_cns + ".t") pm.connectAttr(dm_node + ".outputRotate", div_cns + ".r") # Squash n Stretch node = aop.gear_squashstretch2_op(div_cns, None, pm.getAttr(self.volDriver_att), "x") pm.connectAttr(self.volume_att, node + ".blend") pm.connectAttr(self.volDriver_att, node + ".driver") pm.connectAttr(self.st_att[i], node + ".stretch") pm.connectAttr(self.sq_att[i], node + ".squash") # return # NOTE: next line fix the issue on meters. # This is special case becasuse the IK solver from mGear use the scale as lenght and we have shear # TODO: check for a more clean and elegant solution instead of re-match the world matrix again tra.matchWorldTransform(self.fk_ctl[0], self.match_fk0_off) tra.matchWorldTransform(self.fk_ctl[1], self.match_fk1_off) tra.matchWorldTransform(self.fk_ctl[0], self.match_fk0) tra.matchWorldTransform(self.fk_ctl[1], self.match_fk1) # match IK/FK ref pm.parentConstraint(self.bone0, self.match_fk0_off, mo=True) pm.parentConstraint(self.bone1, self.match_fk1_off, mo=True)
def create_rig(self, parent): """ Here we build the actual control rig for the spline spine :return: """ print(self.options.facing_axis) # -- Get the guide drivers, so we can place them correctly guide_drivers = self.find('GuideDriver') org = crab.create.org( description=self.options.description, side=self.options.side, parent=parent, ) # -- Create base guide master_control = crab.create.control( description='%sMaster' % self.options.description, side=self.options.side, parent=org, match_to=guide_drivers[0], shape='sphere', ) # -- Create base guide base_control = crab.create.control( description='%sBase' % self.options.description, side=self.options.side, parent=master_control, match_to=guide_drivers[0], shape='sphere', ) # -- Create tip guide tip_control = crab.create.control( description='%sTip' % self.options.description, side=self.options.side, parent=master_control, match_to=guide_drivers[3], shape='sphere', ) # -- Create base guide child base_tweak_control = crab.create.control( description='%sBaseTweaker' % self.options.description, side=self.options.side, parent=base_control, match_to=guide_drivers[1], shape='sphere', ) # -- Create base guide child tip_tweak_control = crab.create.control( description='%sTipTweaker' % self.options.description, side=self.options.side, parent=tip_control, match_to=guide_drivers[2], shape='sphere', ) # -- If we need a linear hierarchy then reparent the controls if self.options.linear_hierarchy: crab.utils.hierarchy.get_org(tip_tweak_control).setParent( base_tweak_control) crab.utils.hierarchy.get_org(tip_control).setParent( tip_tweak_control) # -- Tag all our controls - but tag them in the same order # -- as the drivers self.tag(base_control, 'MappedControl') self.tag(base_tweak_control, 'MappedControl') self.tag(tip_tweak_control, 'MappedControl') self.tag(tip_control, 'MappedControl') # -- Now constrain the ik spline setup to these controls skeletal_joints = self.find('SkeletalJoint') spline_builder = SplineIKSetup( description=self.options.description, side=self.options.side, joints_to_trace=skeletal_joints, parent=org, facing_axis=self.options.facing_axis, up_axis=self.options.up_axis, ) spline_builder.create() for driver, control in zip(spline_builder.drivers, self.find('MappedControl')): pm.parentConstraint( control, driver, mo=False, ) for skeleton_joint, mech_joint in zip( skeletal_joints, spline_builder.mechanical_joints): self.bind( skeleton_joint, mech_joint, ) return True
def createCtrl(ctrlName, type="locator", size=1, color=None, matchTarget=None, rotation=[0, 0, 0]): """ Create a controler. :param ctrlName: `string` controler name :param type: `string` controler type :param size: `float` controler size :param color: `string` controler color :param matchTarget: `PyNode` match the controler to the target object :return: `PyNode` controler object """ ctrlLib = { "locator": { "d": 1, "p": [(-1, 0, 0), (1, 0, 0), (0, 0, 0), (0, 0, -1), (0, 0, 1), (0, 0, 0), (0, 1, 0), (0, -1, 0)] }, "cube": { "d": 1, "p": [(-1, 1, -1), (-1, 1, 1), (-1, -1, 1), (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1), (-1, -1, -1), (-1, -1, 1), (1, -1, 1), (1, -1, -1), (1, 1, -1), (1, 1, 1), (1, -1, 1), (1, 1, 1), (-1, 1, 1)] }, "circle": { "d": 3, "p": [(0, -0.783612, -0.783612), (0, 0, -1.108194), (0, 0.783612, -0.783612), (0, 1.108194, 0), (0, 0.783612, 0.783612), (0, 0, 1.108194), (0, -0.783612, 0.783612), (0, -1.108194, 0), (0, -0.783612, -0.783612), (0, 0, -1.108194), (0, 0.783612, -0.783612)], "k": [-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }, "crossArrow": { "d": 1, "p": [(1, 0, 1), (3, 0, 1), (3, 0, 2), (5, 0, 0), (3, 0, -2), (3, 0, -1), (1, 0, -1), (1, 0, -3), (2, 0, -3), (0, 0, -5), (-2, 0, -3), (-1, 0, -3), (-1, 0, -1), (-3, 0, -1), (-3, 0, -2), (-5, 0, 0), (-3, 0, 2), (-3, 0, 1), (-1, 0, 1), (-1, 0, 3), (-2, 0, 3), (0, 0, 5), (2, 0, 3), (1, 0, 3), (1, 0, 1)], "k": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ] }, "cross": { "d": 1, "p": [(0.4, 0, -0.4), (0.4, 0, -2), (-0.4, 0, -2), (-0.4, 0, -0.4), (-2, 0, -0.4), (-2, 0, 0.4), (-0.4, 0, 0.4), (-0.4, 0, 2), (0.4, 0, 2), (0.4, 0, 0.4), (2, 0, 0.4), (2, 0, -0.4), (0.4, 0, -0.4)], "k": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] }, "fatCross": { "d": 1, "p": [(-1, 0, -1), (-1, 0, -2), (1, 0, -2), (1, 0, -1), (2, 0, -1), (2, 0, 1), (1, 0, 1), (1, 0, 2), (-1, 0, 2), (-1, 0, 1), (-2, 0, 1), (-2, 0, -1), (-1, 0, -1)], "k": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] }, "hollowSphere": { "d": 1, "p": [(0, 1, 0), (0, 0.9239, 0.3827), (0, 0.7071, 0.7071), (0, 0.3827, 0.9239), (0, 0, 1), (0, -0.3827, 0.9239), (0, -0.7071, 0.7071), (0, -0.9239, 0.3827), (0, -1, 0), (0, -0.9239, -0.3827), (0, -0.7071, -0.7071), (0, -0.3827, -0.9239), (0, 0, -1), (0, 0.3827, -0.9239), (0, 0.7071, -0.7071), (0, 0.9239, -0.3827), (0, 1, 0), (0.3827, 0.9239, 0), (0.7071, 0.7071, 0), (0.9239, 0.3827, 0), (1, 0, 0), (0.9239, -0.3827, 0), (0.7071, -0.7071, 0), (0.3827, -0.9239, 0), (0, -1, 0), (-0.3827, -0.9239, 0), (-0.7071, -0.7071, 0), (-0.9239, -0.3827, 0), (-1, 0, 0), (-0.9239, 0.3827, 0), (-0.7071, 0.7071, 0), (-0.3827, 0.9239, 0), (0, 1, 0), (0, 0.9239, -0.3827), (0, 0.7071, -0.7071), (0, 0.3827, -0.9239), (0, 0, -1), (-0.3827, 0, -0.9239), (-0.7071, 0, -0.7071), (-0.9239, 0, -0.3827), (-1, 0, 0), (-0.9239, 0, 0.3827), (-0.7071, 0, 0.7071), (-0.3827, 0, 0.9239), (0, 0, 1), (0.3827, 0, 0.9239), (0.7071, 0, 0.7071), (0.9239, 0, 0.3827), (1, 0, 0), (0.9239, 0, -0.3827), (0.7071, 0, -0.7071), (0.3827, 0, -0.9239), (0, 0, -1)], } } try: if type == "sphere": ctrl = pm.sphere(n=ctrlName, r=0.5, ax=[0, 1, 0], ch=0)[0] else: ctrl = pm.curve(**ctrlLib[type]) ctrl.rename(ctrlName) except: print("error creating ctrl.") return None ctrl.s.set((size, size, size)) ctrl.r.set(rotation) pm.makeIdentity(ctrl, a=1) if matchTarget and ctrl: pm.delete(pm.parentConstraint(matchTarget, ctrl, mo=0)) if color: colorObject(ctrl, color) return ctrl
def build_base_rig(): ##### 2. BUILD THE BASE RIG ##### #TODO: Generate my own generic shapes here. #TODO: Better naming conventions #TODO: If the guide doesn't exist, just build a rig with all controls at 0,0,0. Don't be an ass about it. #nSRT = 'globalsrt' nGlobal = 'world_ctl' nLocal = 'master_C0_ctl' nBody = 'COG_C0_ctl' if not pm.objExists("Rig"): rigGroup = pm.group(em=True, n='Rig') else: rigGroup = pm.PyNode("Rig") if pm.objExists('RigLayer'): pm.delete('RigLayer') if pm.objExists('GeoLayer'): pm.delete('GeoLayer') oLayer = pm.createDisplayLayer('Rig', n='RigLayer', number=1, nr=True) oLayer.color.set(14) oLayer = pm.createDisplayLayer(pm.ls('Geo'), n='GeoLayer', number=1, nr=True) oLayer.color.set(7) # Find or create the guide controls #if pm.objExists(nSRT): # oSRT = pm.PyNode(nSRT) #else: # oSRT = pm.spaceLocator(n='globalsrt') if pm.objExists(nGlobal): oGlobal = pm.PyNode(nGlobal) else: oGlobal = props_icon_lib.create_control_icon('arrowBox', 'world_ctl', [10.0, 1.0, 10.0]) if pm.objExists(nLocal): oLocal = pm.PyNode(nLocal) else: oLocal = props_icon_lib.create_control_icon('square', 'master_C0_ctl', [9.0, 1.0, 9.0]) localBB = oLocal.getBoundingBox() localWidth = localBB.width() - 1.0 localDepth = localBB.depth() - 1.0 oLocal2 = props_icon_lib.create_control_icon( 'square', 'local_C0_ctl', [localWidth, 1.0, localDepth], offset=[0.0, 0.2, 0.0], ) oLocal2.setTranslation(oLocal.getTranslation(space='world'), space='world') if pm.objExists(nBody): oBody = pm.PyNode(nBody) else: oBody = props_icon_lib.create_control_icon('square', 'COG_C0_ctl', [8.0, 1.0, 8.0]) oBody.setTranslation([0.0, 3.0, 0.0]) bodyBB = oBody.getBoundingBox() bodyWidth = bodyBB.width() - 1.0 bodyDepth = bodyBB.depth() - 1.0 oBody2 = props_icon_lib.create_control_icon( 'square', 'COG_C1_ctl', [bodyWidth, 1.0, bodyDepth], offset=[0.0, 0.0, 0.0], ) oBody2.setTranslation(oBody.getTranslation(space='world'), space='world') #chain_parent([rigGroup, oSRT, oGlobal, oLocal, oBody, oBody2]) chain_parent([rigGroup, oGlobal, oLocal, oLocal2, oBody, oBody2]) make_a_root([oGlobal, oLocal, oLocal2, oBody, oBody2]) pm.parentConstraint(oBody2, "Geo", mo=True) pm.scaleConstraint(oBody2, "Geo", mo=True) oGlobal.getShape().overrideEnabled.set(True) oLocal.getShape().overrideEnabled.set(True) oLocal2.getShape().overrideEnabled.set(True) oBody.getShape().overrideEnabled.set(True) oBody2.getShape().overrideEnabled.set(True) oGlobal.getShape().overrideColor.set(13) oLocal.getShape().overrideColor.set(22) oLocal2.getShape().overrideColor.set(22) oBody.getShape().overrideColor.set(24) oBody2.getShape().overrideColor.set(24)
def build(cls, targets, spaceName, spaceContainer, extraInfo, control, space): if not spaceName: spaceName = 'freeform' trueTarget = group(em=True, name=pdil.simpleName(control, '{0}_freeform'), p=spaceContainer) pdil.dagObj.matchTo( trueTarget, control ) # It's actually important so this can follow correctly. (line copied from MULTI_ORIENT) # Put proxies in a group that follows the "local" space. Honestly this math doesn't make # sense but it gives the results JH wants, which are sensible. proxyGrp = group(em=True, name=pdil.simpleName(control, '{0}_freeformProxies'), p=spaceContainer) pdil.dagObj.matchTo(proxyGrp, control) parentConstraint(cls.getProxy(control), proxyGrp, mo=True) rProxies = [] tProxies = [] for t, (mode, w) in zip(targets, extraInfo): d = duplicate(trueTarget)[0] d.rename(pdil.simpleName(t) + '_freeform') d.setParent(proxyGrp) if mode == cls.ORIENT: orientConstraint(t, d, mo=True) rProxies.append((d, w)) elif mode == cls.POINT: pointConstraint(t, d, mo=True) tProxies.append((d, w)) elif mode == cls.PARENT: parentConstraint(t, d, mo=True) rProxies.append((d, w)) tProxies.append((d, w)) elif mode == cls.POINT_ORIENT: orientConstraint(t, d, mo=True) pointConstraint(t, d, mo=True) rProxies.append((d, w)) tProxies.append((d, w)) elif mode == cls.PARENT_TRANS: parentConstraint(t, d, mo=True, sr=['x', 'y', 'z']) tProxies.append((d, w)) if rProxies: rConstraint = parentConstraint([p[0] for p in rProxies], trueTarget, mo=True, st=['x', 'y', 'z']) rConstraint.addAttr('rotTarget', at='bool', dv=True) rConstraint.interpType.set(2) attrs = rConstraint.getWeightAliasList() for v, attr in zip([p[1] for p in rProxies], attrs): attr.set(v) else: # If there were no rotate targets, use the parent joint or group proxy = cls.getProxy(control) if proxy: const = parentConstraint(proxy, trueTarget, mo=True, st=['x', 'y', 'z']) const.addAttr('mo_ignore', at='bool', dv=True) if tProxies: tConstraint = parentConstraint([p[0] for p in tProxies], trueTarget, mo=True, sr=['x', 'y', 'z']) attrs = tConstraint.getWeightAliasList() for v, attr in zip([p[1] for p in tProxies], attrs): attr.set(v) else: # If there were no translate targets, use the parent joint or group proxy = cls.getProxy(control) if proxy: const = parentConstraint(proxy, trueTarget, mo=True, sr=['x', 'y', 'z']) const.addAttr('mo_ignore', at='bool', dv=True) return trueTarget, spaceName
def getTargets(target): constraints = listRelatives(target, type='parentConstraint') target = tuple(parentConstraint(constraints[0], q=True, tl=True)) extra = None constraint = None return target, extra, constraint
def build_rbf(self): try: pm.loadPlugin('jsRadial.mll') except: pm.error('ERROR: jsRadial.mll not loaded.') pm.undoInfo(openChunk=True) rbf = pm.createNode('jsRadPose') # Notify if RBF is made with no connections if len(self.pose) == 0 and len(self.targets) == 0: print "RBF node made with no connections" # Only create one sigma blinn material if self.sigma_chk.isChecked(): self.sigma_shader = pm.shadingNode("lambert", asShader=True, name="sigmaLmbt") pm.setAttr(self.sigma_shader.color.colorR, 0.0) pm.setAttr(self.sigma_shader.color.colorG, 0.5) pm.setAttr(self.sigma_shader.color.colorB, 1.0) pm.setAttr(self.sigma_shader.transparency, (0.95, 0.95, 0.95)) self.sigma_sg = pm.sets(renderable=1, noSurfaceShader=1, empty=1, n="sigmaLmbt_SG") pm.connectAttr(self.sigma_shader.outColor, self.sigma_sg.surfaceShader) self.falloff_group = pm.group(empty=1, n="GRP_rbf_falloff") # Connect pose attrs if len(self.pose) == 1: # Connect pose matrix if self.matrix_chk.isChecked() == True: if self.world_rad.isChecked() == True: pm.connectAttr(self.pose[0][0].worldMatrix[0], rbf.poseMatrix) else: pm.connectAttr(self.pose[0][0].parentMatrix[0], rbf.poseMatrix) # Connect pose color if self.rgb_chk.isChecked() == True or self.alpha_chk.isChecked( ) == True: shape = pm.listRelatives(self.pose[0], shapes=1)[0] shader_grp = pm.listConnections(shape, type='shadingEngine') shader = pm.listConnections(shader_grp[0], d=0, s=1)[0] if self.rgb_chk.isChecked(): try: pm.connectAttr(shader.color, rbf.poseColor) except: try: pm.connectAttr(shader.outColor, rbf.poseColor) except: pass if self.alpha_chk.isChecked(): try: pm.connectAttr(shader.transparency, rbf.poseTransparency) except: try: pm.connectAttr(shader.outTransparency, rbf.poseTransparency) except: pass # Build pose rotate locators locX = pm.spaceLocator(n=self.pose[0][0] + '_rotLocX') locY = pm.spaceLocator(n=self.pose[0][0] + '_rotLocY') locZ = pm.spaceLocator(n=self.pose[0][0] + '_rotLocZ') pm.parent(locX, locY, locZ, self.pose[0]) pm.setAttr(locX.translate, (0, 0, 0)) pm.setAttr(locY.translate, (0, 0, 0)) pm.setAttr(locZ.translate, (0, 0, 0)) mult = pm.createNode('multiplyDivide', n='MULTinv_' + self.pose[0][0]) pm.setAttr(mult.operation, 2) pm.setAttr(mult.input1X, 1) pm.setAttr(mult.input1Y, 1) pm.setAttr(mult.input1Z, 1) pm.connectAttr(self.pose[0][0].scale, mult.input2) pm.connectAttr(mult.output, locX.scale) pm.connectAttr(mult.output, locY.scale) pm.connectAttr(mult.output, locZ.scale) mult_neg = pm.createNode('multiplyDivide', n='MULTneg_' + self.pose[0][0]) pm.setAttr(mult_neg.operation, 1) pm.setAttr(mult_neg.input1X, -1) pm.setAttr(mult_neg.input1Y, -1) pm.setAttr(mult_neg.input1Z, -1) pm.connectAttr(rbf.rotateLocatorOffset, locX.tx) pm.connectAttr(rbf.rotateLocatorOffset, locY.ty) pm.connectAttr(rbf.rotateLocatorOffset, locZ.tz) pm.connectAttr(rbf.rotateLocatorOffset, mult_neg.input2X) pm.connectAttr(rbf.rotateLocatorOffset, mult_neg.input2Y) pm.connectAttr(rbf.rotateLocatorOffset, mult_neg.input2Z) pm.connectAttr(mult_neg.outputX, locX.scalePivotX) pm.connectAttr(mult_neg.outputY, locY.scalePivotY) pm.connectAttr(mult_neg.outputZ, locZ.scalePivotZ) pm.connectAttr(locX.worldMatrix[0], rbf.poseRotateLocX) pm.connectAttr(locY.worldMatrix[0], rbf.poseRotateLocY) pm.connectAttr(locZ.worldMatrix[0], rbf.poseRotateLocZ) pm.connectAttr(rbf.rotateLocatorsVisible, locX.visibility) pm.connectAttr(rbf.rotateLocatorsVisible, locY.visibility) pm.connectAttr(rbf.rotateLocatorsVisible, locZ.visibility) pm.setAttr(locX.overrideEnabled, 1) pm.setAttr(locY.overrideEnabled, 1) pm.setAttr(locZ.overrideEnabled, 1) pm.setAttr(locX.overrideColor, 12) pm.setAttr(locY.overrideColor, 23) pm.setAttr(locZ.overrideColor, 29) # Check target list for pose and duplicates if len(self.pose) == 1: single_set = set(self.targets) self.targets = list(single_set) if self.pose[0][0] in self.targets: print "Pose " + self.pose[0][ 0] + " was removed from target list but kept as input pose." self.targets.remove(self.pose[0][0]) # Connect target attrs for i in range(0, len(self.targets)): # Connect target matrix if self.matrix_chk.isChecked() == True: if self.world_rad.isChecked() == True: pm.connectAttr(self.targets[i].worldMatrix[0], rbf.target[i].targetMatrix) else: pm.connectAttr(self.targets[i].parentMatrix[0], rbf.target[i].targetMatrix) # Connect target rbga if self.rgb_chk.isChecked() == True or self.alpha_chk.isChecked( ) == True: shape = pm.listRelatives(self.targets[i], shapes=1)[0] shader_grp = pm.listConnections(shape, type='shadingEngine') shader = pm.listConnections(shader_grp[0], d=0, s=1)[0] if self.rgb_chk.isChecked() == True: try: pm.connectAttr(shader.color, rbf.target[i].targetColor) except: try: pm.connectAttr(shader.outColor, rbf.target[i].targetColor) except: pass if self.alpha_chk.isChecked() == True: try: pm.connectAttr(shader.transparency, rbf.target[i].targetTransparency) except: try: pm.connectAttr(shader.outTransparency, rbf.target[i].targetTransparency) except: pass # Build target rotate locators locX = pm.spaceLocator(n=self.targets[i] + '_rotLocX') locY = pm.spaceLocator(n=self.targets[i] + '_rotLocY') locZ = pm.spaceLocator(n=self.targets[i] + '_rotLocZ') pm.parent(locX, locY, locZ, self.targets[i]) pm.setAttr(locX.translate, (0, 0, 0)) pm.setAttr(locY.translate, (0, 0, 0)) pm.setAttr(locZ.translate, (0, 0, 0)) mult = pm.createNode('multiplyDivide', n='MULTinv_' + self.targets[i]) pm.setAttr(mult.operation, 2) pm.setAttr(mult.input1X, 1) pm.setAttr(mult.input1Y, 1) pm.setAttr(mult.input1Z, 1) pm.connectAttr(self.targets[i].scale, mult.input2) pm.connectAttr(mult.output, locX.scale) pm.connectAttr(mult.output, locY.scale) pm.connectAttr(mult.output, locZ.scale) mult_neg = pm.createNode('multiplyDivide', n='MULTneg_' + self.targets[i]) pm.setAttr(mult_neg.operation, 1) pm.setAttr(mult_neg.input1X, -1) pm.setAttr(mult_neg.input1Y, -1) pm.setAttr(mult_neg.input1Z, -1) pm.connectAttr(rbf.rotateLocatorOffset, locX.tx) pm.connectAttr(rbf.rotateLocatorOffset, locY.ty) pm.connectAttr(rbf.rotateLocatorOffset, locZ.tz) pm.connectAttr(rbf.rotateLocatorOffset, mult_neg.input2X) pm.connectAttr(rbf.rotateLocatorOffset, mult_neg.input2Y) pm.connectAttr(rbf.rotateLocatorOffset, mult_neg.input2Z) pm.connectAttr(mult_neg.outputX, locX.scalePivotX) pm.connectAttr(mult_neg.outputY, locY.scalePivotY) pm.connectAttr(mult_neg.outputZ, locZ.scalePivotZ) pm.connectAttr(locX.worldMatrix[0], rbf.target[i].rotateLocX) pm.connectAttr(locY.worldMatrix[0], rbf.target[i].rotateLocY) pm.connectAttr(locZ.worldMatrix[0], rbf.target[i].rotateLocZ) pm.connectAttr(rbf.rotateLocatorsVisible, locX.visibility) pm.connectAttr(rbf.rotateLocatorsVisible, locY.visibility) pm.connectAttr(rbf.rotateLocatorsVisible, locZ.visibility) pm.setAttr(locX.overrideEnabled, 1) pm.setAttr(locY.overrideEnabled, 1) pm.setAttr(locZ.overrideEnabled, 1) pm.setAttr(locX.overrideColor, 12) pm.setAttr(locY.overrideColor, 23) pm.setAttr(locZ.overrideColor, 29) # Build target alias attrs on RBF node if self.alias_chk.isChecked(): alias = self.targets[i] if '|' in alias: alias = alias.replace('|', '_') pm.aliasAttr(alias, rbf.target[i]) outAlias = alias + 'Out' sigmaAlias = alias + 'Falloff' pm.aliasAttr(outAlias, rbf.outputInterpolate[i]) pm.aliasAttr(sigmaAlias, rbf.outputSigma[i]) pm.getAttr(rbf.outputInterpolate[i]) pm.getAttr(rbf.outputSigma[i]) # Build falloff spheres if self.sigma_chk.isChecked(): bb = pm.xform(self.targets[i], q=1, bb=1) scale = bb[3] - bb[0] ### hard coding sphere radius from trial and error sphere = pm.polySphere(r=5.0, sx=20, sy=20, ax=(0, 1, 0), ch=0, n=str(self.targets[i]) + '_falloff') sphereShp = pm.listRelatives(sphere, s=1) pcon = pm.parentConstraint(self.targets[i], sphere, mo=0) pm.sets(self.sigma_sg, e=1, forceElement=sphereShp) mult = pm.createNode('multiplyDivide', n='MULT_' + self.targets[i] + '_falloff') pm.setAttr(mult.input1X, 0.5) pm.setAttr(mult.operation, 2) pm.connectAttr(rbf.outputSigma[i], mult.input2X) pm.connectAttr(mult.outputX, sphere[0].scaleX) pm.connectAttr(mult.outputX, sphere[0].scaleY) pm.connectAttr(mult.outputX, sphere[0].scaleZ) pm.parent(sphere, self.falloff_group) pm.undoInfo(closeChunk=True) self.close()
def make(self): listOrigJoints = mc.listRelatives(self.rootJoint, type="joint", ad=True) listOrigJoints.append(self.rootJoint) listOrigJoints.reverse() listJoints = [] if self.makeDynamic: listJoints = rig_jointCopyChain(self.rootJoint, replaceName=(self.name, self.name + 'ChainSpline')) self.origRootJoint = str(self.rootJoint) self.rootJoint = listJoints[0] else: listJoints = listOrigJoints ''' rig_makeSpline(string $baseName, int $nControls, string $controlType, int $detail, int $nRead, string $readType, string $ctrls[], string $reads[], int $bConstrainMid ) ''' # make cMus tail joints mm.eval('string $ctrls[];string $reads[];rig_makeSpline( "' + self.name + '", 4, "cube", 8, ' + str(self.numIKCtrls) + ', "joint", $ctrls, $reads, 0);') # place them every thirds if len(self.splinePosList) == 0: thirds = len(listJoints) / 3 pm.delete( pm.parentConstraint(self.rootJoint, self.name + 'BaseIKOffset_GRP')) pm.delete( pm.parentConstraint(listJoints[thirds], self.name + 'MidAIKOffset_GRP')) pm.delete( pm.parentConstraint(listJoints[thirds + thirds], self.name + 'MidBIKOffset_GRP')) pm.delete( pm.parentConstraint(listJoints[len(listJoints) - 2], self.name + 'TipIKOffset_GRP')) elif len(self.splinePosList) > 0: pm.delete( pm.parentConstraint(self.splinePosList[0], self.name + 'BaseIKOffset_GRP')) pm.delete( pm.parentConstraint(self.splinePosList[1], self.name + 'MidAIKOffset_GRP')) pm.delete( pm.parentConstraint(self.splinePosList[2], self.name + 'MidBIKOffset_GRP')) pm.delete( pm.parentConstraint(self.splinePosList[3], self.name + 'TipIKOffset_GRP')) tailModule = rig_ikChainSpline(self.name, self.rootJoint, ctrlSize=self.ctrlSize, parent=self.parent, numIkControls=self.numIKCtrls, numFkControls=self.numFKCtrls, dWorldUpAxis=self.dWorldUpAxis) fkBaseCtrl = pm.PyNode(self.name + 'FKA_CTRL') fkBaseName = self.name + 'FKA_CTRL' if self.makeLag: pm.addAttr(fkBaseCtrl, longName='startFrame', attributeType="long", defaultValue=1, keyable=True) pm.addAttr(fkBaseCtrl, ln='lagExpr', at='enum', enumName='___________', k=True) fkBaseCtrl.lagExpr.setLocked(True) pm.addAttr(fkBaseCtrl, longName='lagBlend', attributeType="double", min=0, max=10, defaultValue=10, keyable=True) pm.addAttr(fkBaseCtrl, longName='lagStiffness', attributeType="double", min=0, max=10, defaultValue=0, keyable=True) pm.addAttr(fkBaseCtrl, longName='lagStiffnessBlend', attributeType="double", min=0, max=1, defaultValue=0, keyable=False) rig_animDrivenKey(fkBaseCtrl.lagStiffness, (0, 10), fkBaseCtrl.lagStiffnessBlend, (0, 1)) pm.addAttr(fkBaseCtrl, longName='upDownMult', attributeType="long", min=0, max=1, defaultValue=1, keyable=True) pm.addAttr(fkBaseCtrl, longName='leftRightMult', attributeType="long", min=0, max=1, defaultValue=1, keyable=True) # tail upgrade prevCtrl = fkBaseName tailLagGrp = rig_transform(0, name=self.name + 'Lag', parent=tailModule.parts).object tailJnts = pm.listRelatives(self.name + 'SplineJoints_GRP', type='joint') dynJnts = [] if self.makeDynamic: for i in range(0, len(tailJnts)): tailNme = tailJnts[i].stripNamespace() tailDyn = tailNme.replace('IK', 'DynJ') tailDyn = tailDyn.replace('_JNT', '') tailDyn = rig_transform(0, name=tailDyn, type='joint', target=tailJnts[i]).object dynJnts.append(tailDyn) pm.addAttr(fkBaseCtrl, ln='Dynamics', at='enum', enumName='___________', k=True) pm.addAttr(fkBaseCtrl, longName='dynamicBlend', attributeType="double", min=0, max=10, defaultValue=0, keyable=True) pm.addAttr(fkBaseCtrl, longName='stiffness', attributeType="double", min=0, max=10, defaultValue=5, keyable=True) for i in range(1, len(tailJnts)): tailNme = tailJnts[i].stripNamespace() tailIK = tailJnts[i] tailFK = tailNme.replace('IK', 'FK') tailFK = tailFK.replace('_JNT', '') constrainObject(tailFK + 'Modify2_GRP', [tailFK + 'Modify1_GRP', tailIK], tailFK + '_CTRL', ['parent', 'IK'], type='parentConstraint') # make lag reference locators if self.makeLag: lagOffset = rig_transform(0, name=tailFK + 'LagOffset', parent=tailLagGrp, target=tailFK + '_CTRL').object lagExpLoc = rig_transform(0, name=tailFK + 'Lag', type='locator', parent=lagOffset, target=tailFK + '_CTRL').object lagExpRefLoc = rig_transform(0, name=tailFK + 'LagRef', type='locator', parent=lagOffset, target=tailFK + '_CTRL').object lagExpDriveLoc = rig_transform(0, name=tailFK + 'LagDrive', type='locator', parent=lagExpRefLoc, target=tailFK + '_CTRL').object pm.parentConstraint(self.spine, lagOffset, mo=True) pm.parentConstraint(prevCtrl, lagExpRefLoc, mo=True) con = pm.parentConstraint(lagExpRefLoc, lagExpLoc, lagExpDriveLoc, mo=True, sr=('x', 'y', 'z')) targets = con.getWeightAliasList() rig_animDrivenKey(fkBaseCtrl.lagBlend, (0, 10), targets[0], (1, 0)) rig_animDrivenKey(fkBaseCtrl.lagBlend, (0, 10), targets[1], (0, 1)) mm.eval( 'expression -o ("' + lagExpLoc + '") -n ("' + tailFK + 'Lag_EXP") -s ("$attrStart = ' + fkBaseName + '.startFrame;vector $refLoc = <<' + lagExpRefLoc + '.translateX,' + lagExpRefLoc + '.translateY,' + lagExpRefLoc + '.translateZ>>;vector $ball = <<' + lagExpLoc + '.translateX,' + lagExpLoc + '.translateY,' + lagExpLoc + '.translateZ>>;$stiffness = 0.9+(0.1*' + fkBaseName + '.lagStiffnessBlend);$friction = 1.0;vector $velocity;vector $oldVelocity;$distanceVector = ($refLoc - $ball)/2.0;$force = $distanceVector * $stiffness;$oldVelocity = $oldVelocity +(($ball+$force)-$ball);' + lagExpLoc + '.translateX=((' + lagExpLoc + '.translateX+$oldVelocity.x)*$friction)*' + fkBaseName + '.leftRightMult;' + lagExpLoc + '.translateY=((' + lagExpLoc + '.translateY+$oldVelocity.y)*$friction)*' + fkBaseName + '.upDownMult;' + lagExpLoc + '.translateZ=((' + lagExpLoc + '.translateZ+$oldVelocity.z)*$friction)*' + fkBaseName + '.upDownMult;if(frame == $attrStart){$velocity = <<0,0,0>>;}if(frame == $attrStart){' + lagExpLoc + '.translateX = 0;' + lagExpLoc + '.translateY= 0;' + lagExpLoc + '.translateZ = 0;}") -ae 1 -uc all ;') for at in ('tx', 'ty', 'tz'): pm.connectAttr(lagExpDriveLoc + '.' + at, tailFK + 'Modify1_GRP.' + at, f=True) prevCtrl = tailFK + '_CTRL' pm.parentConstraint(self.name + 'FKACon_GRP', self.name + 'BaseIKOffset_GRP', mo=True) constrainObject( self.name + 'MidAIKOffset_GRP', [self.name + 'FKACon_GRP', self.parent, self.worldSpace], self.name + 'MidAIK_CTRL', ['base', self.parentName, 'world'], type='parentConstraint') constrainObject(self.name + 'MidBIKOffset_GRP', [ self.name + 'FKACon_GRP', self.name + 'MidAIKCon_GRP', self.parent, self.worldSpace ], self.name + 'MidBIK_CTRL', ['base', 'FK', self.parentName, 'world'], type='parentConstraint') constrainObject(self.name + 'TipIKOffset_GRP', [ self.name + 'FKACon_GRP', self.name + 'MidBIKCon_GRP', self.parent, self.worldSpace ], self.name + 'TipIK_CTRL', ['base', 'FK', self.parentName, 'world'], type='parentConstraint') ctrlSizeHalf = [ self.ctrlSize / 2.0, self.ctrlSize / 2.0, self.ctrlSize / 2.0 ] ctrlSizeQuarter = [ self.ctrlSize / 4.0, self.ctrlSize / 4.0, self.ctrlSize / 4.0 ] self.ctrlSize = [self.ctrlSize, self.ctrlSize, self.ctrlSize] # scale ctrls for ctrl in (self.name + 'MidAIK_CTRL', self.name + 'MidBIK_CTRL', self.name + 'TipIK_CTRL'): c = pm.PyNode(ctrl) pm.scale(c.cv, self.ctrlSize[0], self.ctrlSize[0], self.ctrlSize[0]) pm.move(c.cv, [0, 2 * self.ctrlSize[0], 0], relative=True, worldSpace=True) tailPointer = rig_control(name=self.name + 'Pointer', shape='pyramid', lockHideAttrs=['rx', 'ry', 'rz'], colour='white', parentOffset=tailModule.controls, rotateOrder=2, scale=self.ctrlSize) pm.delete( pm.parentConstraint(listJoints[len(listJoints) - 2], tailPointer.offset)) constrainObject(tailPointer.offset, [self.parent, self.spine, self.worldSpace], tailPointer.ctrl, [self.parentName, 'fullBody', 'world'], type='parentConstraint') tailPointerBase = rig_transform(0, name=self.name + 'PointerBase', type='locator', parent=tailModule.parts, target=self.name + 'FKA_CTRL').object tailPointerTip = rig_transform(0, name=self.name + 'PointerTip', type='locator', parent=tailModule.parts, target=tailPointer.con).object pm.rotate(tailPointerBase, 0, 0, -90, r=True, os=True) pm.rotate(tailPointerTip, 0, 0, -90, r=True, os=True) pm.parentConstraint(self.parent, tailPointerBase, mo=True) pm.parentConstraint(tailPointer.con, tailPointerTip, mo=True) tailPointerTop = mm.eval('rig_makePiston("' + tailPointerBase + '", "' + tailPointerTip + '", "' + self.name + 'PointerAim");') pm.orientConstraint(tailPointerBase.replace('LOC', 'JNT'), self.name + 'FKAModify2_GRP', mo=True) pm.parent(self.name + 'MidAIKOffset_GRP', self.name + 'MidBIKOffset_GRP', self.name + 'TipIKOffset_GRP', tailModule.controls) pm.parent(tailJnts, tailModule.skeleton) pm.parent(self.name + '_cMUS', self.name + 'BaseIKOffset_GRP', tailPointerTop, tailModule.parts) pm.parent(self.name + 'SplineSetup_GRP', self.name + 'BaseIKOffset_GRP', tailPointerTop, tailModule.parts) pm.setAttr(tailModule.skeleton + '.inheritsTransform', 0) if self.makeDynamic: chainParent(dynJnts, reverse=0) dynJnts.reverse() finalChain = rig_jointCopyChain(dynJnts[0], replaceName=('Dyn', 'Final')) mc.select(self.name + "SplineIK_CRV") mm.eval('makeCurvesDynamic 2 { "1", "0", "1", "1", "0"};') hairSystem = pm.ls("|hairSystem?")[0] nucleus = pm.ls("|nucleus?")[0] dynCurveGrp = pm.ls("|hairSystem?OutputCurves")[0] dynCurve = pm.listRelatives(dynCurveGrp, c=True)[0] dynCurve = pm.rename(dynCurve, self.name + 'Dyn_CRV') nmeUpper = self.name.capitalize() #ikData = pm.ikHandle(n='dyn'+nmeUpper, sj=dynJnts[0], ee=dynJnts[-1], # solver='ikSplineSolver',curve=dynCurve,ccv=False, ns=self.numFKCtrls) ikData = rig_ik('dyn' + nmeUpper, dynJnts[0], dynJnts[-1], 'ikSplineSolver', numSpans=self.numFKCtrls, curve=dynCurve, createCurve=False) # advanced twist pm.setAttr(ikData.handle + '.dTwistControlEnable', 1) pm.setAttr(ikData.handle + '.dWorldUpType', 2) # object up start and end pm.setAttr(ikData.handle + '.dForwardAxis', 2) # positive y pm.setAttr(ikData.handle + '.dWorldUpAxis', self.dWorldUpAxis) # positive x pm.connectAttr(self.name + 'UpperAim_LOCUp.worldMatrix[0]', ikData.handle.dWorldUpMatrixEnd, f=True) pm.connectAttr(self.name + 'LowerAim_LOCUp.worldMatrix[0]', ikData.handle.dWorldUpMatrix, f=True) mc.setAttr(hairSystem + ".collide", 0) mc.setAttr(hairSystem + ".stretchResistance", 25) mc.setAttr(hairSystem + ".bendResistance", .1) mc.setAttr(hairSystem + ".stiffness", 1) mc.setAttr(hairSystem + ".lengthFlex", 1) mc.setAttr(hairSystem + ".damp", .05) mc.setAttr(hairSystem + ".stretchDamp", 1) mc.setAttr(hairSystem + ".mass", .2) mc.setAttr(hairSystem + ".attractionDamp", 1) mc.setAttr(hairSystem + ".startCurveAttract", .5) mc.setAttr("follicleShape1.pointLock", 1) mc.setAttr("follicleShape1.overrideDynamics", 1) mc.setAttr("follicleShape1.collide", 0) mc.setAttr("follicleShape1.damp", .25) mc.setAttr("follicleShape1.stiffness", 0) #mc.setAttr( "follicleShape1.startCurveAttract" ,.3) # 0.3 default dyn stiffness at 0, 1 = 10 rig_animDrivenKey(fkBaseCtrl.stiffness, (0, 10), "follicleShape1.startCurveAttract", (0.3, 1)) pm.connectAttr(fkBaseCtrl.startFrame, 'nucleus1.startFrame', f=True) # create tail dyn controls with joints parentd underneath # creat another ikSPline 'tailDriven_CRV' and 'tailDriven_ikHandle' and drive final geo, with tail dyn jonints skinned to the ikPlane tail driven crv. sc = simpleControls(dynJnts, modify=1, constrainJoints=0, parentCon=1, colour='red') pm.parent(sc[dynJnts[0]].offset, tailModule.controlsSec) collections.OrderedDict(sorted(sc.items(), key=lambda t: t[0])) i = 0 for jnt in finalChain: driverJnt = jnt.replace('Final', 'Driver') dynJnt = jnt.replace('Final', 'Dyn') pm.parent(jnt, sc[dynJnt].con) con = pm.parentConstraint(driverJnt, dynJnt, sc[dynJnt].offset, mo=True) pm.setAttr(con.interpType, 2) targets = con.getWeightAliasList() rig_animDrivenKey(fkBaseCtrl.dynamicBlend, (0, 10), targets[0], (1, 0)) rig_animDrivenKey(fkBaseCtrl.dynamicBlend, (0, 10), targets[1], (0, 1)) i += 1 chainList = rig_chain(self.origRootJoint).chain ik = rig_ik(self.name + 'Driven', self.origRootJoint, chainList[-1], 'ikSplineSolver', numSpans=self.numIKCtrls) pm.parent(ik.handle, ik.curve, tailModule.parts) # advanced twist pm.setAttr(ik.handle + '.dTwistControlEnable', 1) pm.setAttr(ik.handle + '.dWorldUpType', 2) # object up start and end pm.setAttr(ik.handle + '.dForwardAxis', 2) # positive y pm.setAttr(ik.handle + '.dWorldUpAxis', self.dWorldUpAxis) # positive x pm.connectAttr(self.name + 'UpperAim_LOCUp.worldMatrix[0]', ik.handle.dWorldUpMatrixEnd, f=True) pm.connectAttr(self.name + 'LowerAim_LOCUp.worldMatrix[0]', ik.handle.dWorldUpMatrix, f=True) pm.skinCluster(finalChain, ik.curve, tsb=True) pm.setAttr(self.name + 'Dyn_CRV.inheritsTransform', 0) pm.parent(dynJnts[0], 'nucleus1', hairSystem, ikData.handle, ikData.curve, tailModule.parts) pm.delete('hairSystem1OutputCurves') self.module = tailModule
def addOperators(self): """Create operators and set the relations for the component rig Apply operators, constraints, expressions to the hierarchy. In order to keep the code clean and easier to debug, we shouldn't create any new object in this method. """ # Tangent position --------------------------------- # common part d = vector.getDistance(self.guide.pos["root"], self.guide.pos["neck"]) dist_node = node.createDistNode(self.root, self.ik_ctl) rootWorld_node = node.createDecomposeMatrixNode( self.root.attr("worldMatrix")) div_node = node.createDivNode(dist_node + ".distance", rootWorld_node + ".outputScaleX") div_node = node.createDivNode(div_node + ".outputX", d) # tan0 mul_node = node.createMulNode(self.tan0_att, self.tan0_loc.getAttr("ty")) res_node = node.createMulNode(mul_node + ".outputX", div_node + ".outputX") pm.connectAttr(res_node + ".outputX", self.tan0_loc + ".ty") # tan1 mul_node = node.createMulNode(self.tan1_att, self.tan1_loc.getAttr("ty")) res_node = node.createMulNode(mul_node + ".outputX", div_node + ".outputX") pm.connectAttr(res_node + ".outputX", self.tan1_loc.attr("ty")) # Curves ------------------------------------------- op = applyop.gear_curveslide2_op(self.slv_crv, self.mst_crv, 0, 1.5, 0.5, 0.5) pm.connectAttr(self.maxstretch_att, op + ".maxstretch") pm.connectAttr(self.maxsquash_att, op + ".maxsquash") pm.connectAttr(self.softness_att, op + ".softness") # Volume driver ------------------------------------ crv_node = node.createCurveInfoNode(self.slv_crv) # Division ----------------------------------------- for i in range(self.divisions): # References u = i / (self.divisions - 1.0) cns = applyop.pathCns(self.div_cns[i], self.slv_crv, False, u, True) cns.setAttr("frontAxis", 1) # front axis is 'Y' cns.setAttr("upAxis", 2) # front axis is 'Z' # Roll intMatrix = applyop.gear_intmatrix_op( self.intMRef + ".worldMatrix", self.ik_ctl + ".worldMatrix", u) dm_node = node.createDecomposeMatrixNode(intMatrix + ".output") pm.connectAttr(dm_node + ".outputRotate", self.twister[i].attr("rotate")) pm.parentConstraint(self.twister[i], self.ref_twist[i], maintainOffset=True) pm.connectAttr(self.ref_twist[i] + ".translate", cns + ".worldUpVector") # Squash n Stretch op = applyop.gear_squashstretch2_op(self.fk_npo[i], self.root, pm.arclen(self.slv_crv), "y") pm.connectAttr(self.volume_att, op + ".blend") pm.connectAttr(crv_node + ".arcLength", op + ".driver") pm.connectAttr(self.st_att[i], op + ".stretch") pm.connectAttr(self.sq_att[i], op + ".squash") op.setAttr("driver_min", 0.1) # scl compas if i != 0: div_node = node.createDivNode( [1, 1, 1], [ self.fk_npo[i - 1] + ".sx", self.fk_npo[i - 1] + ".sy", self.fk_npo[i - 1] + ".sz", ], ) pm.connectAttr(div_node + ".output", self.scl_npo[i] + ".scale") # Controlers if i == 0: mulmat_node = applyop.gear_mulmatrix_op( self.div_cns[i].attr("worldMatrix"), self.root.attr("worldInverseMatrix"), ) else: mulmat_node = applyop.gear_mulmatrix_op( self.div_cns[i].attr("worldMatrix"), self.div_cns[i - 1].attr("worldInverseMatrix"), ) dm_node = node.createDecomposeMatrixNode(mulmat_node + ".output") pm.connectAttr(dm_node + ".outputTranslate", self.fk_npo[i].attr("t")) pm.connectAttr(dm_node + ".outputRotate", self.fk_npo[i].attr("r")) # Orientation Lock if i == self.divisions - 1: dm_node = node.createDecomposeMatrixNode(self.ik_ctl + ".worldMatrix") blend_node = node.createBlendNode( [dm_node + ".outputRotate%s" % s for s in "XYZ"], [cns + ".rotate%s" % s for s in "XYZ"], self.lock_ori_att, ) self.div_cns[i].attr("rotate").disconnect() pm.connectAttr(blend_node + ".output", self.div_cns[i] + ".rotate") # Head --------------------------------------------- self.fk_ctl[-1].addChild(self.head_cns) # scale compensation dm_node = node.createDecomposeMatrixNode(self.scl_npo[0] + ".parentInverseMatrix") pm.connectAttr(dm_node + ".outputScale", self.scl_npo[0] + ".scale")
def buildEyes(self, rtPos, lfPos): if not rtPos or not lfPos: return 'DrEyes: Please supply and right and left location for your eye rig' # Make Ctrls ctrlSize = coreUtils.getDistance(rtPos, lfPos) self.mainCtrl = controls.squareCtrl(axis='z', name='%s_CTRL' % self.name, size=ctrlSize) pmc.select('%s.cv[ * ]' % coreUtils.getShape(self.mainCtrl)) pmc.scale(2.5, scaleX=1) pmc.scale(1.25, scaleY=1) self.ctrls.append(self.mainCtrl) ctrlZero = coreUtils.addParent(self.mainCtrl, 'group', '%s_ctrl_ZERO' % self.name) ctrlZero.setParent(self.ctrls_grp) midPos = coreUtils.pointsAlongVector(lfPos, rtPos)[1] ctrlZero.t.set((midPos[0], midPos[1], midPos[2] + (ctrlSize * 10))) self.rtCtrl = controls.circleCtrl(radius=ctrlSize * .25, name='rt_eye_CTRL') self.ctrls.append(self.rtCtrl) coreUtils.align(self.rtCtrl, self.mainCtrl, parent=1) rtCtrlZero = coreUtils.addParent(self.rtCtrl, 'group', 'rt_eyeCtrl_ZERO') rtCtrlZero.tx.set(rtPos[0]) self.lfCtrl = controls.circleCtrl(radius=ctrlSize * .25, name='lf_eye_CTRL') self.ctrls.append(self.lfCtrl) coreUtils.align(self.lfCtrl, self.mainCtrl, parent=1) lfCtrlZero = coreUtils.addParent(self.lfCtrl, 'group', 'lf_eyeCtrl_ZERO') lfCtrlZero.tx.set(lfPos[0]) lfCtrlZero.sx.set(-1) coreUtils.colorize('green', [self.mainCtrl]) coreUtils.colorize('red', [self.rtCtrl]) coreUtils.colorize('blue', [self.lfCtrl]) # Set up aims rtGrp = coreUtils.addChild(self.rig_grp, 'group', 'rt_eye_GRP') rtGrp.t.set(rtPos) pmc.parentConstraint(self.ctrls_grp, rtGrp, mo=1) pmc.scaleConstraint(self.ctrls_grp, rtGrp, mo=1) rtAimGrp = coreUtils.addChild(rtGrp, 'group', 'rt_eyeAim_GRP') pmc.aimConstraint(self.rtCtrl, rtAimGrp, aim=(0, 0, 1), wut='objectrotation', wuo=rtGrp) rtJnt = coreUtils.addChild(rtAimGrp, 'joint', 'rt_eyeAim_JNT') self.joints.append(rtJnt) lfGrp = coreUtils.addChild(self.rig_grp, 'group', 'lf_eye_GRP') lfGrp.t.set(lfPos) pmc.parentConstraint(self.ctrls_grp, lfGrp, mo=1) pmc.scaleConstraint(self.ctrls_grp, lfGrp, mo=1) lfAimGrp = coreUtils.addChild(lfGrp, 'group', 'lf_eyeAim_GRP') pmc.aimConstraint(self.lfCtrl, lfAimGrp, aim=(0, 0, 1), wut='objectrotation', wuo=lfGrp) lfJnt = coreUtils.addChild(lfAimGrp, 'joint', 'lf_eyeAim_JNT') self.joints.append(lfJnt) # softness pmc.addAttr(self.main_grp, longName='eye_pull', minValue=0.0, maxValue=1.0, at='double', k=1, h=0) eyePullRev = coreUtils.reverse(self.main_grp.eye_pull, name='rev_eyePull_UTL') rtSoftGrp = coreUtils.addChild(rtGrp, 'group', 'rt_eyeSoft_GRP') rtSoftJnt = coreUtils.addChild(rtSoftGrp, 'joint', 'rt_soft_JNT') self.joints.append(rtSoftJnt) con = pmc.orientConstraint(rtGrp, rtAimGrp, rtSoftGrp) con.interpType.set(2) w0 = pmc.Attribute('%s.%sW0' % (con.name(), rtGrp.name())) w1 = pmc.Attribute('%s.%sW1' % (con.name(), rtAimGrp.name())) self.main_grp.eye_pull.connect(w1) eyePullRev.outputX.connect(w0) lfSoftGrp = coreUtils.addChild(lfGrp, 'group', 'lf_eyeSoft_GRP') lfSoftJnt = coreUtils.addChild(lfSoftGrp, 'joint', 'lf_soft_JNT') self.joints.append(lfSoftJnt) con = pmc.orientConstraint(lfGrp, lfAimGrp, lfSoftGrp) con.interpType.set(2) w0 = pmc.Attribute('%s.%sW0' % (con.name(), lfGrp.name())) w1 = pmc.Attribute('%s.%sW1' % (con.name(), lfAimGrp.name())) self.main_grp.eye_pull.connect(w1) eyePullRev.outputX.connect(w0) ############################################################################################################# # Lids pmc.addAttr(self.main_grp, ln='lids_rotate_factor', at='double', k=0, h=0) pmc.setAttr(self.main_grp.lids_rotate_factor, channelBox=1) self.main_grp.lids_rotate_factor.set(-10) pmc.addAttr(self.main_grp, ln='lids_auto', at='double', k=0, h=0, minValue=0.0, maxValue=1.0) self.main_grp.lids_auto.set(1.0) rtLidGrp = coreUtils.addChild(self.rig_grp, 'group', 'rt_lids_GRP') coreUtils.align(rtLidGrp, rtGrp) # rt_top rtTopLidZero = coreUtils.addChild(rtLidGrp, 'group', 'rt_topLid_ZERO') rtTopLidAutoGrp = coreUtils.addChild(rtTopLidZero, 'group', 'rt_topLidAuto_GRP') md = coreUtils.multiply(rtAimGrp.rx, self.main_grp.lids_auto, name='md_rtLidsAuto_UTL') md.outputX.connect(rtTopLidAutoGrp.rx) # rt_btm rtBtmLidZero = coreUtils.addChild(rtLidGrp, 'group', 'rt_btmLid_ZERO') rtBtmLidAutoGrp = coreUtils.addChild(rtBtmLidZero, 'group', 'rt_btmLidAuto_GRP') md.outputX.connect(rtBtmLidAutoGrp.rx) # lf_top lfLidGrp = coreUtils.addChild(self.rig_grp, 'group', 'lf_lids_GRP') coreUtils.align(lfLidGrp, lfGrp) lfTopLidZero = coreUtils.addChild(lfLidGrp, 'group', 'lf_topLid_ZERO') lfTopLidAutoGrp = coreUtils.addChild(lfTopLidZero, 'group', 'lf_topLidAuto_GRP') md = coreUtils.multiply(lfAimGrp.rx, self.main_grp.lids_auto, name='md_lfLidsAuto_UTL') md.outputX.connect(lfTopLidAutoGrp.rx) # lf_btm lfBtmLidZero = coreUtils.addChild(lfLidGrp, 'group', 'lf_btmLid_ZERO') lfBtmLidAutoGrp = coreUtils.addChild(lfBtmLidZero, 'group', 'lf_btmLidAuto_GRP') md.outputX.connect(lfBtmLidAutoGrp.rx) def _addControl(slave, driver): md = coreUtils.multiply(driver.ty, self.main_grp.lids_rotate_factor, name='md_%s_UTL' % driver.name().replace('_CTRL', '')) md.outputX.connect(slave.rx) # CTRLS def _makeCtrl(prefix='', colour='red', pos=(0, 0, 0), grpParent=None): c = controls.squareCtrl(size=ctrlSize, name='%s_CTRL' % prefix, axis='z') c.t.set(pos) zero = coreUtils.addParent(c, 'group', '%sCtrl_ZERO' % prefix) zero.setParent(self.ctrls_grp) pmc.select('%s.cv[ * ]' % coreUtils.getShape(c)) pmc.scale(.33, scaleY=1) coreUtils.colorize(colour, [c]) self.ctrls.append(c) g = coreUtils.addChild(grpParent, 'group', '%s_DRV' % prefix) _addControl(g, c) return c, g def _makeSubCtrls(parent, prefix='', colour='red', grpParent=None): for i in range(len(subs.keys())): c = controls.squareCtrl(size=ctrlSize * .15, name='%s_%s_CTRL' % (prefix, subs[i][0]), axis='z') coreUtils.align(c, parent, parent=1) c.tx.set(ctrlSize * subs[i][1]) coreUtils.addParent(c, 'group', c.name().replace('_CTRL', 'Ctrl_ZERO')) coreUtils.colorize(colour, [c]) self.ctrls.append(c) g = coreUtils.addChild(grpParent, 'group', '%s_%s_DRV' % (prefix, subs[i][0])) j = coreUtils.addChild(g, 'joint', '%s_%s_JNT' % (prefix, subs[i][0])) jEnd = coreUtils.addChild( j, 'joint', '%s_%sEnd_JNT' % (prefix, subs[i][0])) jEnd.t.set((ctrlSize * subs[i][1], 0, ctrlSize * .33)) self.joints.append(jEnd) _addControl(g, c) subs = {0: ['in', .33], 1: ['mid', 0], 2: ['out', -.33]} # rt top lid c, g = _makeCtrl('rt_topLid', 'red', (rtPos[0], rtPos[1] + (ctrlSize * .33), rtPos[2] + ctrlSize), rtTopLidAutoGrp) _makeSubCtrls(c, 'rt_topLid', 'red', g) # rt btm lid c, g = _makeCtrl('rt_btmLid', 'red', (rtPos[0], rtPos[1] + (ctrlSize * -.33), rtPos[2] + ctrlSize), rtBtmLidAutoGrp) _makeSubCtrls(c, 'rt_btmLid', 'red', g) subs = {0: ['in', -.33], 1: ['mid', 0], 2: ['out', .33]} # lf top lid c, g = _makeCtrl('lf_topLid', 'blue', (lfPos[0], lfPos[1] + (ctrlSize * .33), lfPos[2] + ctrlSize), lfTopLidAutoGrp) _makeSubCtrls(c, 'lf_topLid', 'blue', g) #lf btm lid c, g = _makeCtrl('lf_btmLid', 'blue', (lfPos[0], lfPos[1] + (ctrlSize * -.33), lfPos[2] + ctrlSize), lfBtmLidAutoGrp) _makeSubCtrls(c, 'lf_btmLid', 'blue', g)
def addOperators(self): """Create operators and set the relations for the component rig Apply operators, constraints, expressions to the hierarchy. In order to keep the code clean and easier to debug, we shouldn't create any new object in this method. """ # Soft condition soft_cond_node = node.createConditionNode(self.soft_attr, 0.0001, 4, 0.0001, self.soft_attr) self.soft_attr_cond = soft_cond_node.outColorR if self.settings["ikSolver"]: self.ikSolver = "ikRPsolver" else: pm.mel.eval("ikSpringSolver;") self.ikSolver = "ikSpringSolver" # 1 bone chain Upv ref =============================== self.ikHandleUpvRef = primitive.addIkHandle( self.root, self.getName("ikHandleLegChainUpvRef"), self.legChainUpvRef, "ikSCsolver") pm.pointConstraint(self.ik_ctl, self.ikHandleUpvRef) pm.parentConstraint(self.legChainUpvRef[0], self.upv_cns, mo=True) # mid joints ================================================ for xjnt, midJ in zip(self.legBones[1:3], [self.mid1_jnt, self.mid2_jnt]): node.createPairBlend(None, xjnt, .5, 1, midJ) pm.connectAttr(xjnt + ".translate", midJ + ".translate", f=True) pm.parentConstraint(self.mid1_jnt, self.knee_lvl) pm.parentConstraint(self.mid2_jnt, self.ankle_lvl) # joint length multiply multJnt1_node = node.createMulNode(self.boneALenght_attr, self.boneALenghtMult_attr) multJnt2_node = node.createMulNode(self.boneBLenght_attr, self.boneBLenghtMult_attr) multJnt3_node = node.createMulNode(self.boneCLenght_attr, self.boneCLenghtMult_attr) # # IK 3 bones =============================================== self.ikHandle = primitive.addIkHandle(self.softblendLoc, self.getName("ik3BonesHandle"), self.chain3bones, self.ikSolver, self.upv_ctl) # TwistTest if [round(elem, 4) for elem in transform.getTranslation(self.chain3bones[1])] \ != [round(elem, 4) for elem in self.guide.apos[1]]: add_nodeTwist = node.createAddNode(180.0, self.roll_att) else: add_nodeTwist = node.createAddNode(0, self.roll_att) if self.negate: mulVal = 1 else: mulVal = -1 node.createMulNode(add_nodeTwist + ".output", mulVal, self.ikHandle.attr("twist")) # stable spring solver doble rotation pm.pointConstraint(self.root_ctl, self.chain3bones[0]) # softIK 3 bones operators applyop.aimCns(self.aim_tra, self.ik_ref, axis="zx", wupType=4, wupVector=[1, 0, 0], wupObject=self.root_ctl, maintainOffset=False) plusTotalLength_node = node.createPlusMinusAverage1D([ multJnt1_node.attr("outputX"), multJnt2_node.attr("outputX"), multJnt3_node.attr("outputX") ]) subtract1_node = node.createPlusMinusAverage1D( [plusTotalLength_node.attr("output1D"), self.soft_attr_cond], 2) distance1_node = node.createDistNode(self.ik_ref, self.aim_tra) div1_node = node.createDivNode(1.0, self.rig.global_ctl + ".sx") mult1_node = node.createMulNode(distance1_node + ".distance", div1_node + ".outputX") subtract2_node = node.createPlusMinusAverage1D( [mult1_node.attr("outputX"), subtract1_node.attr("output1D")], 2) div2_node = node.createDivNode(subtract2_node + ".output1D", self.soft_attr_cond) mult2_node = node.createMulNode(-1, div2_node + ".outputX") power_node = node.createPowNode(self.softSpeed_attr, mult2_node + ".outputX") mult3_node = node.createMulNode(self.soft_attr_cond, power_node + ".outputX") subtract3_node = node.createPlusMinusAverage1D([ plusTotalLength_node.attr("output1D"), mult3_node.attr("outputX") ], 2) cond1_node = node.createConditionNode( self.soft_attr_cond, 0, 2, subtract3_node + ".output1D", plusTotalLength_node + ".output1D") cond2_node = node.createConditionNode(mult1_node + ".outputX", subtract1_node + ".output1D", 2, cond1_node + ".outColorR", mult1_node + ".outputX") pm.connectAttr(cond2_node + ".outColorR", self.wristSoftIK + ".tz") # soft blend pc_node = pm.pointConstraint(self.wristSoftIK, self.ik_ref, self.softblendLoc) node.createReverseNode(self.stretch_attr, pc_node + ".target[0].targetWeight") pm.connectAttr(self.stretch_attr, pc_node + ".target[1].targetWeight", f=True) # Stretch distance2_node = node.createDistNode(self.softblendLoc, self.wristSoftIK) mult4_node = node.createMulNode(distance2_node + ".distance", div1_node + ".outputX") # bones for i, mulNode in enumerate( [multJnt1_node, multJnt2_node, multJnt3_node]): div3_node = node.createDivNode(mulNode + ".outputX", plusTotalLength_node + ".output1D") mult5_node = node.createMulNode(mult4_node + ".outputX", div3_node + ".outputX") mult6_node = node.createMulNode(self.stretch_attr, mult5_node + ".outputX") node.createPlusMinusAverage1D( [mulNode.attr("outputX"), mult6_node.attr("outputX")], 1, self.chain3bones[i + 1] + ".tx") # IK 2 bones =============================================== self.ikHandle2 = primitive.addIkHandle(self.softblendLoc2, self.getName("ik2BonesHandle"), self.chain2bones, self.ikSolver, self.upv_ctl) node.createMulNode(self.roll_att, mulVal, self.ikHandle2.attr("twist")) # stable spring solver doble rotation pm.pointConstraint(self.root_ctl, self.chain2bones[0]) parentc_node = pm.parentConstraint(self.ik2b_ikCtl_ref, self.ik2b_bone_ref, self.ik2b_blend) node.createReverseNode(self.fullIK_attr, parentc_node + ".target[0].targetWeight") pm.connectAttr(self.fullIK_attr, parentc_node + ".target[1].targetWeight", f=True) # softIK 2 bones operators applyop.aimCns(self.aim_tra2, self.ik2b_ik_ref, axis="zx", wupType=4, wupVector=[1, 0, 0], wupObject=self.root_ctl, maintainOffset=False) plusTotalLength_node = node.createPlusMinusAverage1D( [multJnt1_node.attr("outputX"), multJnt2_node.attr("outputX")]) subtract1_node = node.createPlusMinusAverage1D( [plusTotalLength_node.attr("output1D"), self.soft_attr_cond], 2) distance1_node = node.createDistNode(self.ik2b_ik_ref, self.aim_tra2) div1_node = node.createDivNode(1, self.rig.global_ctl + ".sx") mult1_node = node.createMulNode(distance1_node + ".distance", div1_node + ".outputX") subtract2_node = node.createPlusMinusAverage1D( [mult1_node.attr("outputX"), subtract1_node.attr("output1D")], 2) div2_node = node.createDivNode(subtract2_node + ".output1D", self.soft_attr_cond) mult2_node = node.createMulNode(-1, div2_node + ".outputX") power_node = node.createPowNode(self.softSpeed_attr, mult2_node + ".outputX") mult3_node = node.createMulNode(self.soft_attr_cond, power_node + ".outputX") subtract3_node = node.createPlusMinusAverage1D([ plusTotalLength_node.attr("output1D"), mult3_node.attr("outputX") ], 2) cond1_node = node.createConditionNode( self.soft_attr_cond, 0, 2, subtract3_node + ".output1D", plusTotalLength_node + ".output1D") cond2_node = node.createConditionNode(mult1_node + ".outputX", subtract1_node + ".output1D", 2, cond1_node + ".outColorR", mult1_node + ".outputX") pm.connectAttr(cond2_node + ".outColorR", self.ankleSoftIK + ".tz") # soft blend pc_node = pm.pointConstraint(self.ankleSoftIK, self.ik2b_ik_ref, self.softblendLoc2) node.createReverseNode(self.stretch_attr, pc_node + ".target[0].targetWeight") pm.connectAttr(self.stretch_attr, pc_node + ".target[1].targetWeight", f=True) # Stretch distance2_node = node.createDistNode(self.softblendLoc2, self.ankleSoftIK) mult4_node = node.createMulNode(distance2_node + ".distance", div1_node + ".outputX") for i, mulNode in enumerate([multJnt1_node, multJnt2_node]): div3_node = node.createDivNode(mulNode + ".outputX", plusTotalLength_node + ".output1D") mult5_node = node.createMulNode(mult4_node + ".outputX", div3_node + ".outputX") mult6_node = node.createMulNode(self.stretch_attr, mult5_node + ".outputX") node.createPlusMinusAverage1D( [mulNode.attr("outputX"), mult6_node.attr("outputX")], 1, self.chain2bones[i + 1] + ".tx") # IK/FK connections for i, x in enumerate(self.fk_ctl): pm.parentConstraint(x, self.legBonesFK[i], mo=True) for i, x in enumerate([self.chain2bones[0], self.chain2bones[1]]): pm.parentConstraint(x, self.legBonesIK[i], mo=True) pm.pointConstraint(self.ik2b_ik_ref, self.legBonesIK[2]) applyop.aimCns(self.legBonesIK[2], self.roll_ctl, axis="xy", wupType=4, wupVector=[0, 1, 0], wupObject=self.legBonesIK[1], maintainOffset=False) pm.connectAttr(self.chain3bones[-1].attr("tx"), self.legBonesIK[-1].attr("tx")) # foot twist roll pm.orientConstraint(self.ik_ref, self.legBonesIK[-1], mo=True) node.createMulNode(-1, self.chain3bones[-1].attr("tx"), self.ik2b_ik_ref.attr("tx")) for i, x in enumerate(self.legBones): node.createPairBlend(self.legBonesFK[i], self.legBonesIK[i], self.blend_att, 1, x) # Twist references ---------------------------------------- self.ikhArmRef, self.tmpCrv = applyop.splineIK( self.getName("legRollRef"), self.rollRef, parent=self.root, cParent=self.legBones[0]) initRound = .001 multVal = 1 multTangent_node = node.createMulNode(self.roundnessKnee_att, multVal) add_node = node.createAddNode(multTangent_node + ".outputX", initRound) pm.connectAttr(add_node + ".output", self.tws1_rot.attr("sx")) for x in ["translate"]: pm.connectAttr(self.knee_ctl.attr(x), self.tws1_loc.attr(x)) for x in "xy": pm.connectAttr(self.knee_ctl.attr("r" + x), self.tws1_loc.attr("r" + x)) multTangent_node = node.createMulNode(self.roundnessAnkle_att, multVal) add_node = node.createAddNode(multTangent_node + ".outputX", initRound) pm.connectAttr(add_node + ".output", self.tws2_rot.attr("sx")) for x in ["translate"]: pm.connectAttr(self.ankle_ctl.attr(x), self.tws2_loc.attr(x)) for x in "xy": pm.connectAttr(self.ankle_ctl.attr("r" + x), self.tws2_loc.attr("r" + x)) # Volume ------------------------------------------- distA_node = node.createDistNode(self.tws0_loc, self.tws1_loc) distB_node = node.createDistNode(self.tws1_loc, self.tws2_loc) distC_node = node.createDistNode(self.tws2_loc, self.tws3_loc) add_node = node.createAddNode(distA_node + ".distance", distB_node + ".distance") add_node2 = node.createAddNode(distC_node + ".distance", add_node + ".output") div_node = node.createDivNode(add_node2 + ".output", self.root_ctl.attr("sx")) # comp scaling dm_node = node.createDecomposeMatrixNode(self.root.attr("worldMatrix")) div_node2 = node.createDivNode(div_node + ".outputX", dm_node + ".outputScaleX") self.volDriver_att = div_node2 + ".outputX" # Flip Offset ---------------------------------------- pm.connectAttr(self.ankleFlipOffset_att, self.tws2_loc.attr("rz")) pm.connectAttr(self.kneeFlipOffset_att, self.tws1_loc.attr("rz")) # Divisions ---------------------------------------- # at 0 or 1 the division will follow exactly the rotation of the # controler.. and we wont have this nice tangent + roll for i, div_cns in enumerate(self.div_cns): subdiv = False if i == len(self.div_cns) - 1 or i == 0: subdiv = 45 else: subdiv = 45 if i < (self.settings["div0"] + 1): perc = i * .333 / (self.settings["div0"] + 1.0) elif i < (self.settings["div0"] + self.settings["div1"] + 2): perc = i * .333 / (self.settings["div0"] + 1.0) else: perc = (.5 + (i - self.settings["div0"] - 3.0) * .5 / (self.settings["div1"] + 1.0)) if i < (self.settings["div0"] + 2): perc = i * .333 / (self.settings["div0"] + 1.0) elif i < (self.settings["div0"] + self.settings["div1"] + 3): perc = (.333 + (i - self.settings["div0"] - 1) * .333 / (self.settings["div1"] + 1.0)) else: perc = ( .666 + (i - self.settings["div1"] - self.settings["div0"] - 2.0) * .333 / (self.settings["div2"] + 1.0)) # we neet to offset the ankle and knee point to force the bone # orientation to the nex bone span if perc == .333: perc = .3338 elif perc == .666: perc = .6669 perc = max(.001, min(.999, perc)) # Roll cts = [self.tws0_rot, self.tws1_rot, self.tws2_rot, self.tws3_rot] o_node = applyop.gear_rollsplinekine_op(div_cns, cts, perc, subdiv) pm.connectAttr(self.resample_att, o_node + ".resample") pm.connectAttr(self.absolute_att, o_node + ".absolute") # Squash n Stretch o_node = applyop.gear_squashstretch2_op( div_cns, None, pm.getAttr(self.volDriver_att), "x") pm.connectAttr(self.volume_att, o_node + ".blend") pm.connectAttr(self.volDriver_att, o_node + ".driver") pm.connectAttr(self.st_att[i], o_node + ".stretch") pm.connectAttr(self.sq_att[i], o_node + ".squash") # Visibilities ------------------------------------- # fk fkvis_node = node.createReverseNode(self.blend_att) for ctrl in self.fk_ctl: for shp in ctrl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) # ik for ctrl in [self.ik_ctl, self.roll_ctl]: for shp in ctrl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) # setup leg o_node scale compensate pm.connectAttr(self.rig.global_ctl + ".scale", self.setup + ".scale") return
def extendPipe( jointLength=1 ): defaultLength = 3.0 currJnt = '' name = '' root = '' newJnts = [] for sel in pm.selected(): sel.select() # for now, there's no branching, so we find the deepest joint try: currJnt = sel name = currJnt.split('_')[0] root = pm.nt.Joint( '%s_Jnt0' % name ) except: raise "select an object on the pipe that you want to extend" # naming #---------- num = int(currJnt.extractNum()) try: twoPrev = int(currJnt.getParent().getParent().extractNum()) except: twoPrev = num-2 try: prev = int(currJnt.getParent().extractNum()) except: prev = num-1 curr = num new = int(currJnt.nextUniqueName().extractNum()) print "extending from", currJnt, new branchNum = len(currJnt.getChildren()) #print '%s has %s children' % (currJnt, branchNum) if branchNum: print "new segment is a branching joint" currJnt.addAttr( 'pipeLengthInBtwn%s' % branchNum, min=0 ) #currJnt.attr( 'pipeLengthInBtwn%s' % branchNum ).showInChannelBox(1) #print twoPrev, prev, curr, new rigGrp = '%s_RigGrp' % name geoGrp = '%s_GeoGrp' % name # new skeletal joint #--------------------- if new>1: prevJnt = pm.nt.Joint( '%s_Jnt%s' % (name, prev) ) pos = 2*currJnt.getTranslation(ws=1) - prevJnt.getTranslation(ws=1) else: prevJnt = None pos = currJnt.getTranslation(ws=1) + [0,defaultLength,0] newJnt = pm.joint( p=pos, n= '%s_Jnt%s' % (name, new) ) # re-orient the last created joint, which is considered our current joint pm.joint( currJnt, e=1, zeroScaleOrient=1, secondaryAxisOrient='yup', orientJoint='xyz') # pymel method: NEEDS FIXING #currJnt.setZeroScaleOrient(1) #currJnt.setSecondaryAxisOrient('yup') # Flag secondaryAxisOrient can only be used in conjunction with orientJoint flag. #currJnt.setOrientJoint('xyz') newJnt.scale.lock() newJnt.addAttr( 'pipeLength', defaultValue=jointLength, min=.0001 ) newJnt.pipeLength.showInChannelBox(1) newJnt.addAttr( 'pipeLengthInBtwn0', min=0 ) #newJnt.attr( 'pipeLengthInBtwn0' ).showInChannelBox(1) newJnt.addAttr( 'pipeLeadIn', dv=0, min=0 ) newJnt.pipeLeadIn.showInChannelBox(1) newJnt.addAttr( 'radiusMultiplier', dv=1, min=0 ) newJnt.radiusMultiplier.showInChannelBox(1) newJnt.displayHandle = 1 newJnt.radius.showInChannelBox(0) # bend hierarchy #----------------- trans = pm.group( empty=1, n='%s_Elbow%s' % (name, new)) trans.rotateOrder = 1 pm.aimConstraint( currJnt, trans, aimVector = [0, -1, 0], upVector = [-1, 0, 0] ) pm.pointConstraint( newJnt, trans ) trans.setParent( rigGrp ) # keep the end joint oriented along the joint chain so that it can be slid back # and forth to change the length of the current pipe segment pm.delete( pm.orientConstraint( trans, newJnt ) ) # Main Pipe #------------ pipe, pipeHist = pm.polyCylinder( height = 1, radius=1, name = '%s_Geo%s' % (name, new) ) pipeHist = pipeHist.rename( '%s_GeoHist%s' % (name, new) ) pipe.setPivots( [0, -.5, 0], r=1 ) root.globalPipeRadius >> pipe.sx root.globalPipeRadius >> pipe.sz pipeHist.createUVs = 3 # normalize and preserve aspect ratio root.subdivisionsAxis >> pipeHist.subdivisionsAxis # Pipe Connectors #------------- pipeConn1, pipeConnHist1 = pm.polyCylinder( height = .1, radius=1, name = '%s_Connector1AGeo%s' % (name, new) ) pipeConnHist1 = pipeConnHist1.rename( '%s_Connector1AHist%s' % (name, new) ) pipeConn1.setPivots( [0, -.05, 0], r=1 ) pipeConn1.setParent( pipe, relative=True ) pipeConn1.rotate.lock() root.subdivisionsAxis >> pipeConnHist1.subdivisionsAxis pipeConn2, pipeConnHist2 = pm.polyCylinder( height = .1, radius=1, name = '%s_Connector2AGeo%s' % (name, new) ) pipeConnHist2 = pipeConnHist2.rename( '%s_Connector2AHist%s' % (name, new) ) pipeConn2.setPivots( [0, .05, 0], r=1 ) pipeConn2.setParent( pipe, relative=True ) pipeConn2.rotate.lock() root.subdivisionsAxis >> pipeConnHist2.subdivisionsAxis pipeConn1, pipeConnHist1 = pm.polyCylinder( height = .1, radius=1, name = '%s_Connector1BGeo%s' % (name, new) ) pipeConnHist1 = pipeConnHist1.rename( '%s_Connector1BHist%s' % (name, new) ) pipeConn1.setPivots( [0, -.05, 0], r=1 ) pipeConn1.setParent( pipe, relative=True ) pipeConn1.rotate.lock() pipeConn1.visibility = 0 root.subdivisionsAxis >> pipeConnHist1.subdivisionsAxis pipeConn2, pipeConnHist2 = pm.polyCylinder( height = .1, radius=1, name = '%s_Connector2BGeo%s' % (name, new) ) pipeConnHist2 = pipeConnHist2.rename( '%s_Connector2BHist%s' % (name, new) ) pipeConn2.setPivots( [0, .05, 0], r=1 ) pipeConn2.setParent( pipe, relative=True ) pipeConn2.rotate.lock() pipeConn2.visibility = 0 root.subdivisionsAxis >> pipeConnHist2.subdivisionsAxis pipe.setParent( geoGrp ) #constraints pm.pointConstraint( currJnt, pipe ) aim = pm.aimConstraint( newJnt, pipe ) aim.offsetZ = -90 # convert the previous pipe joint into a bendy joint if new > 1: currElbow = pm.PyNode('%s_Elbow%s' % (name, curr) ) pipeLoc = pm.spaceLocator( n= '%s_PipeDummy%s' % (name, new) ) pipeLoc.hide() tweak = pm.group(n='%s_ElbowTweak%s' % (name, new)) tweak.rotateOrder = 2 #tweak.translate = currElbow.translate.get() tweak.setParent( currElbow, r=1 ) pm.aimConstraint( prevJnt, tweak, aimVector = [1, 0, 0], upVector = [0, -1, 0], skip=['z', 'x'] ) # Pipe Joint #------------ pipeJnt, pipeJntHist = pm.polyCylinder( height = 1, radius=1, name = '%s_JntGeo%s' % (name, new), subdivisionsAxis = 20, subdivisionsHeight = 30 ) pipeJnt.setParent( geoGrp ) pipeJnt.sy = jointLength pipeJnt.visibility = 0 pipeJntHist = pipeJntHist.rename( '%s_JntGeoHist%s' % (name, new) ) pipeJntHist.createUVs = 3 # normalize and preserve aspect ratio root.subdivisionsAxis >> pipeJntHist.subdivisionsAxis root.subdivisionsJoint >> pipeJntHist.subdivisionsHeight # constraints pm.parentConstraint( pipeLoc, pipeJnt ) pipeJnt.translate.lock() pipeJnt.rotate.lock() #pipeJnt.scale.lock() aim = pm.PyNode('%s_Elbow%s_aimConstraint1' % (name, curr)) aim.setWorldUpType( 2 ) aim.setWorldUpObject( newJnt ) bend, bendHandle = pm.nonLinear( '%s_JntGeo%s' % (name, new), type='bend' ) bendHandle = pm.nt.Transform(bendHandle).rename( '%s_BendHandle%s' % (name, new) ) bendHandle.sx =.5 bendHandle.hide() bend.rename( '%s_Bend%s' % (name, new) ) pm.parentConstraint( '%s_ElbowTweak%s' % (name, new), bendHandle ) aim = '%s_ElbowTweak%s_aimConstraint1' % (name, new) #aim.worldUpType.set( 1 ) pm.aimConstraint( aim, e=1, worldUpType='object', worldUpObject=newJnt ) bendHandle.setParent(rigGrp) expr = """ float $v1[]; $v1[0] = %(name)s_Elbow%(twoPrev)s.translateX - %(name)s_Elbow%(prev)s.translateX; $v1[1] = %(name)s_Elbow%(twoPrev)s.translateY - %(name)s_Elbow%(prev)s.translateY; $v1[2] = %(name)s_Elbow%(twoPrev)s.translateZ - %(name)s_Elbow%(prev)s.translateZ; float $v2[]; $v2[0] = %(name)s_Elbow%(curr)s.translateX - %(name)s_Elbow%(prev)s.translateX; $v2[1] = %(name)s_Elbow%(curr)s.translateY - %(name)s_Elbow%(prev)s.translateY; $v2[2] = %(name)s_Elbow%(curr)s.translateZ - %(name)s_Elbow%(prev)s.translateZ; float $mag = sqrt ( $v2[0]*$v2[0] + $v2[1]*$v2[1] + $v2[2]*$v2[2] ); float $angleData[] = `angleBetween -v1 $v1[0] $v1[1] $v1[2] -v2 $v2[0] $v2[1] $v2[2] `; float $angle = $angleData[3]; if ( !equivalentTol($angle,180.0, 0.1) ) { float $jointDeg = 180 - $angle; float $jointRad = -1 * deg_to_rad( $jointDeg ); %(name)s_Bend%(curr)s.curvature = $jointRad/2; %(name)s_ElbowTweak%(curr)s.rotateZ = $jointDeg/2; %(name)s_Jnt%(prev)s.pipeLengthInBtwn%(branch)s = %(name)s_Jnt%(prev)s.pipeLength; float $pipeLength = %(name)s_Jnt%(prev)s.pipeLengthInBtwn%(branch)s; float $centerAngleRad = deg_to_rad(90 -$angle/2); float $delta = 0; float $pipeLengthRatio = 1; if ($centerAngleRad > 0.0) { float $radius = .5*%(name)s_Jnt%(prev)s.pipeLengthInBtwn%(branch)s/ $centerAngleRad; $delta = $radius - ($radius * cos( $centerAngleRad )); $pipeLengthRatio = .5 * $pipeLength / ( $radius * sin( $centerAngleRad ) ); $pipeLength *= $pipeLengthRatio; } %(name)s_PipeDummy%(curr)s.translateX = -1*$delta; %(name)s_BendHandle%(curr)s.scaleX = .5*%(name)s_Jnt%(prev)s.pipeLengthInBtwn%(branch)s; %(name)s_BendHandle%(curr)s.scaleY = %(name)s_BendHandle%(curr)s.scaleX; %(name)s_BendHandle%(curr)s.scaleZ = %(name)s_BendHandle%(curr)s.scaleX; %(name)s_JntGeo%(curr)s.scaleY = $pipeLength * (1.0+%(name)s_Jnt%(curr)s.pipeLeadIn); %(name)s_JntGeo%(curr)s.scaleX = %(name)s_Jnt0.globalPipeRadius + %(name)s_Jnt0.globalJointRadius; %(name)s_JntGeo%(curr)s.scaleZ = %(name)s_JntGeo%(curr)s.scaleX; %(name)s_JntGeo%(curr)s.visibility = 1; %(name)s_Connector1BGeo%(curr)s.visibility=1; %(name)s_Connector2BGeo%(curr)s.visibility=1; } else { %(name)s_Jnt%(prev)s.pipeLengthInBtwn%(branch)s = 0; %(name)s_JntGeo%(curr)s.scaleY = 0; %(name)s_JntGeo%(curr)s.visibility = 0; %(name)s_Connector1BGeo%(curr)s.visibility=0; %(name)s_Connector2BGeo%(curr)s.visibility=0; } %(name)s_Connector1AGeo%(curr)s.scaleY = %(name)s_Jnt0.globalConnectorThickness * (1/%(name)s_Geo%(curr)s.scaleY); %(name)s_Connector2AGeo%(curr)s.scaleY = %(name)s_Connector1AGeo%(curr)s.scaleY; %(name)s_Connector1AGeo%(curr)s.translateY = -.5 + %(name)s_Connector1AHist%(curr)s.height/2 + .1*%(name)s_Jnt0.globalConnectorOffset; %(name)s_Connector2AGeo%(curr)s.translateY = 0.5 - %(name)s_Connector1AHist%(curr)s.height/2 - .1*%(name)s_Jnt0.globalConnectorOffset; %(name)s_Connector1AGeo%(curr)s.scaleX = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector1AGeo%(curr)s.scaleZ = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector2AGeo%(curr)s.scaleX = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector2AGeo%(curr)s.scaleZ = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector1BGeo%(curr)s.scaleY = %(name)s_Jnt0.globalConnectorThickness * (1/%(name)s_Geo%(curr)s.scaleY); %(name)s_Connector2BGeo%(curr)s.scaleY = %(name)s_Connector1BGeo%(curr)s.scaleY; %(name)s_Connector1BGeo%(curr)s.translateY = -.5 + %(name)s_Connector1BHist%(curr)s.height/2 - .1*%(name)s_Jnt0.globalConnectorOffset - .1*%(name)s_Connector1BGeo%(curr)s.scaleY; %(name)s_Connector2BGeo%(curr)s.translateY = 0.5 - %(name)s_Connector1BHist%(curr)s.height/2 + .1*%(name)s_Jnt0.globalConnectorOffset + .1*%(name)s_Connector1BGeo%(curr)s.scaleY; %(name)s_Connector1BGeo%(curr)s.scaleX = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector1BGeo%(curr)s.scaleZ = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector2BGeo%(curr)s.scaleX = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector2BGeo%(curr)s.scaleZ = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Geo%(curr)s.scaleY = $mag - .5*%(name)s_Jnt%(curr)s.pipeLengthInBtwn0 - .5*%(name)s_Jnt%(prev)s.pipeLengthInBtwn%(branch)s; normalize($v2); %(name)s_Geo%(curr)s_pointConstraint1.offsetX = .5*%(name)s_Jnt%(prev)s.pipeLengthInBtwn%(branch)s * $v2[0]; %(name)s_Geo%(curr)s_pointConstraint1.offsetY = .5*%(name)s_Jnt%(prev)s.pipeLengthInBtwn%(branch)s * $v2[1]; %(name)s_Geo%(curr)s_pointConstraint1.offsetZ = .5*%(name)s_Jnt%(prev)s.pipeLengthInBtwn%(branch)s * $v2[2]; """ % { 'twoPrev' : prev, 'prev' : curr, 'curr' : new, 'new' : new+1, 'name': name, 'branch': branchNum } #print expr print 'editing %s_PipeExpr%s' % (name, new) #expression( '%s_PipeExpr%s' % (name, curr), e=1, s=expr, ae=1 ) pm.expression( s=expr, ae=1, n = '%s_PipeExpr%s' % (name, new) ) # special case for first joint else: expr = """ float $x = %(newJnt)s.tx; float $y = %(newJnt)s.ty; float $z = %(newJnt)s.tz; float $mag = sqrt ( $x*$x + $y*$y + $z*$z ); %(name)s_Geo%(curr)s.sy = $mag - .5*%(newJnt)s.pipeLengthInBtwn0; %(name)s_Connector1AGeo%(curr)s.scaleY = %(name)s_Jnt0.globalConnectorThickness * 1/%(name)s_Geo%(curr)s.scaleY; %(name)s_Connector2AGeo%(curr)s.scaleY = %(name)s_Connector1AGeo%(curr)s.scaleY; %(name)s_Connector1AGeo%(curr)s.translateY = -.5 + %(name)s_Connector1AHist%(curr)s.height/2 + .1*%(name)s_Jnt0.globalConnectorOffset; %(name)s_Connector2AGeo%(curr)s.translateY = 0.5 - %(name)s_Connector1AHist%(curr)s.height/2 - .1*%(name)s_Jnt0.globalConnectorOffset; %(name)s_Connector1AGeo%(curr)s.scaleX = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector1AGeo%(curr)s.scaleZ = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector2AGeo%(curr)s.scaleX = 1 + %(name)s_Jnt0.globalConnectorRadius; %(name)s_Connector2AGeo%(curr)s.scaleZ = 1 + %(name)s_Jnt0.globalConnectorRadius; """ % { 'newJnt': newJnt, 'curr' : new, 'name': name } print 'creating %s_PipeExpr1' % (name) pm.expression( s=expr, ae=1, n = '%s_PipeExpr1' % (name)) ''' expr = """ %(pipeJnt)s.scaleX = %(root)s.globalPipeRadius + %(root)s.globalJointRadius; %(pipeJnt)s.scaleZ = %(pipeJnt)s.scaleX; """ % { 'pipeJnt': pipeJnt, 'root' : '%s_Jnt0' % (name) } print 'creating %s_PipeExpr%s' % (name, new) expression( s=expr, ae=1, n = '%s_PipeExpr%s' % (name, new)) ''' pipe.translate.lock() pipe.rotate.lock() #pipe.scale.lock() newJnts.append( newJnt ) pm.select(newJnts)
def getTargets(cls, target): constraints = listRelatives(target, type='parentConstraint') if constraints[0].hasAttr('mo_ignore'): constraints.remove(constraints[0]) elif constraints[1].hasAttr('mo_ignore'): constraints.remove(constraints[1]) if len(constraints) == 2: rConst, tConst = ( constraints[0], constraints[1]) if constraints[0].hasAttr('rotTarget') else ( constraints[1], constraints[0]) else: if constraints[0].hasAttr('rotTarget'): rConst = constraints[0] tConst = None else: rConst = None tConst = constraints[0] # Gather the rotation proxies. rTargets = [] rExtra = [] if rConst: temp = parentConstraint(rConst, q=True, tl=True) for t in temp: type = cls.getConstType(t) actualTarget = cls.constMap[type](t, q=True, tl=True)[0] rTargets.append([actualTarget, type]) rExtra = [a.get() for a in rConst.getWeightAliasList()] # Gather the translate proxies. tTargets = [] tExtra = [] if tConst: temp = parentConstraint(tConst, q=True, tl=True) for t in temp: type = cls.getConstType(t) actualTarget = cls.constMap[type](t, q=True, tl=True)[0] tTargets.append([actualTarget, type]) tExtra = [a.get() for a in tConst.getWeightAliasList()] targets = [] weights = [] modes = [] for (rT, mode), weight in zip(rTargets, rExtra): # Point/Orient const will be in both lists so alter the mdoe if rT in [t for t, w in tTargets] and mode == cls.ORIENT: targets.append(rT) modes.append(cls.POINT_ORIENT) weights.append(weight) print(rT, cls.debugMode[cls.POINT_ORIENT]) # Otherwise it's a regular orient or regular parent else: targets.append(rT) modes.append(mode) weights.append(weight) print(rT, cls.debugMode[mode]) for (tT, mode), weight in zip(tTargets, tExtra): # Point+Orient and parent will already have been added if tT in [r for r, w in rTargets]: continue # Since it's not rotation but is Parent, it must be PARENT_TRANS elif mode == cls.PARENT: targets.append(tT) modes.append(cls.PARENT_TRANS) weights.append(weight) print(tT, cls.debugMode[cls.PARENT_TRANS]) # Otherwise it's a regular trans else: targets.append(tT) modes.append(mode) weights.append(weight) print(tT, cls.debugMode[mode]) return tuple(targets), list(zip(modes, weights)), (rConst, tConst)
def addOperators(self): """Create operators and set the relations for the component rig Apply operators, constraints, expressions to the hierarchy. In order to keep the code clean and easier to debug, we shouldn't create any new object in this method. """ # 1 bone chain Upv ref ============================================== self.ikHandleUpvRef = primitive.addIkHandle( self.root, self.getName("ikHandleArmChainUpvRef"), self.armChainUpvRef, "ikSCsolver") pm.pointConstraint(self.ik_ctl, self.ikHandleUpvRef) pm.parentConstraint(self.armChainUpvRef[0], self.upv_cns, mo=True) # Visibilities ------------------------------------- # fk fkvis_node = node.createReverseNode(self.blend_att) for shp in self.fk0_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) for shp in self.fk1_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) for shp in self.fk2_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) # ik for shp in self.upv_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ikcns_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ik_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) if self.settings["ikTR"]: for shp in self.ikRot_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) # Controls ROT order ----------------------------------- attribute.setRotOrder(self.fk0_ctl, "XZY") attribute.setRotOrder(self.fk1_ctl, "XYZ") attribute.setRotOrder(self.fk2_ctl, "YZX") attribute.setRotOrder(self.ik_ctl, "XYZ") # IK Solver ----------------------------------------- out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_loc] o_node = applyop.gear_ikfk2bone_op(out, self.root, self.ik_ref, self.upv_ctl, self.fk_ctl[0], self.fk_ctl[1], self.fk_ref, self.length0, self.length1, self.negate) if self.settings["ikTR"]: # connect the control inputs outEff_dm = o_node.listConnections(c=True)[-1][1] inAttr = self.ikRot_npo.attr("translate") outEff_dm.attr("outputTranslate") >> inAttr outEff_dm.attr("outputScale") >> self.ikRot_npo.attr("scale") dm_node = node.createDecomposeMatrixNode(o_node.attr("outB")) dm_node.attr("outputRotate") >> self.ikRot_npo.attr("rotate") # rotation mulM_node = applyop.gear_mulmatrix_op( self.ikRot_ctl.attr("worldMatrix"), self.eff_loc.attr("parentInverseMatrix")) intM_node = applyop.gear_intmatrix_op(o_node.attr("outEff"), mulM_node.attr("output"), o_node.attr("blend")) dm_node = node.createDecomposeMatrixNode(intM_node.attr("output")) dm_node.attr("outputRotate") >> self.eff_loc.attr("rotate") transform.matchWorldTransform(self.fk2_ctl, self.ikRot_cns) # scale: this fix the scalin popping issue intM_node = applyop.gear_intmatrix_op( self.fk2_ctl.attr("worldMatrix"), self.ik_ctl_ref.attr("worldMatrix"), o_node.attr("blend")) mulM_node = applyop.gear_mulmatrix_op( intM_node.attr("output"), self.eff_loc.attr("parentInverseMatrix")) dm_node = node.createDecomposeMatrixNode(mulM_node.attr("output")) dm_node.attr("outputScale") >> self.eff_loc.attr("scale") pm.connectAttr(self.blend_att, o_node + ".blend") if self.negate: mulVal = -1 else: mulVal = 1 node.createMulNode(self.roll_att, mulVal, o_node + ".roll") pm.connectAttr(self.scale_att, o_node + ".scaleA") pm.connectAttr(self.scale_att, o_node + ".scaleB") pm.connectAttr(self.maxstretch_att, o_node + ".maxstretch") pm.connectAttr(self.slide_att, o_node + ".slide") pm.connectAttr(self.softness_att, o_node + ".softness") pm.connectAttr(self.reverse_att, o_node + ".reverse") # Twist references --------------------------------- pm.pointConstraint(self.mid_ctl_twst_ref, self.tws1_npo, maintainOffset=False) pm.connectAttr(self.mid_ctl.scaleX, self.tws1_loc.scaleX) pm.orientConstraint(self.mid_ctl_twst_ref, self.tws1_npo, maintainOffset=False) o_node = applyop.gear_mulmatrix_op(self.eff_loc.attr( "worldMatrix"), self.root.attr("worldInverseMatrix")) dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix") pm.connectAttr(dm_node + ".outputTranslate", self.tws2_npo.attr("translate")) dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix") pm.connectAttr(dm_node + ".outputRotate", self.tws2_npo.attr("rotate")) o_node = applyop.gear_mulmatrix_op( self.eff_loc.attr("worldMatrix"), self.tws2_rot.attr("parentInverseMatrix")) dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix") attribute.setRotOrder(self.tws2_rot, "XYZ") pm.connectAttr(dm_node + ".outputRotate", self.tws2_rot + ".rotate") self.tws0_rot.setAttr("sx", .001) self.tws2_rot.setAttr("sx", .001) add_node = node.createAddNode(self.roundness_att, .001) pm.connectAttr(add_node + ".output", self.tws1_rot.attr("sx")) pm.connectAttr(self.armpit_roll_att, self.tws0_rot + ".rotateX") # Roll Shoulder applyop.splineIK(self.getName("rollRef"), self.rollRef, parent=self.root, cParent=self.bone0) # Volume ------------------------------------------- distA_node = node.createDistNode(self.tws0_loc, self.tws1_loc) distB_node = node.createDistNode(self.tws1_loc, self.tws2_loc) add_node = node.createAddNode(distA_node + ".distance", distB_node + ".distance") div_node = node.createDivNode(add_node + ".output", self.root.attr("sx")) dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(self.root.attr("worldMatrix"), dm_node + ".inputMatrix") div_node2 = node.createDivNode(div_node + ".outputX", dm_node + ".outputScaleX") self.volDriver_att = div_node2 + ".outputX" if self.settings["extraTweak"]: for tweak_ctl in self.tweak_ctl: for shp in tweak_ctl.getShapes(): pm.connectAttr(self.tweakVis_att, shp.attr("visibility")) # Divisions ---------------------------------------- # at 0 or 1 the division will follow exactly the rotation of the # controler.. and we wont have this nice tangent + roll for i, div_cns in enumerate(self.div_cns): if i < (self.settings["div0"] + 1): perc = i * .5 / (self.settings["div0"] + 1.0) elif i < (self.settings["div0"] + 2): perc = .49 elif i < (self.settings["div0"] + 3): perc = .50 elif i < (self.settings["div0"] + 4): perc = .51 else: perc = .5 + \ (i - self.settings["div0"] - 3.0) * .5 / \ (self.settings["div1"] + 1.0) perc = max(.001, min(.990, perc)) # Roll if self.negate: o_node = applyop.gear_rollsplinekine_op( div_cns, [self.tws2_rot, self.tws1_rot, self.tws0_rot], 1 - perc, 40) else: o_node = applyop.gear_rollsplinekine_op( div_cns, [self.tws0_rot, self.tws1_rot, self.tws2_rot], perc, 40) pm.connectAttr(self.resample_att, o_node + ".resample") pm.connectAttr(self.absolute_att, o_node + ".absolute") # Squash n Stretch o_node = applyop.gear_squashstretch2_op( div_cns, None, pm.getAttr(self.volDriver_att), "x") pm.connectAttr(self.volume_att, o_node + ".blend") pm.connectAttr(self.volDriver_att, o_node + ".driver") pm.connectAttr(self.st_att[i], o_node + ".stretch") pm.connectAttr(self.sq_att[i], o_node + ".squash") # match IK/FK ref pm.parentConstraint(self.bone0, self.match_fk0_off, mo=True) pm.parentConstraint(self.bone1, self.match_fk1_off, mo=True) if self.settings["ikTR"]: transform.matchWorldTransform(self.ikRot_ctl, self.match_ikRot) transform.matchWorldTransform(self.fk_ctl[2], self.match_fk2) return
def build(): ''' ''' mesh = nt.Mesh(u'CT_face_geoShape') placementGrp = nt.Transform(u'CT_placement_grp') #---------------------------------------------------------------------- bind if 'bind' in data.build_actions: bindGrp = face.createBndsFromPlacement(placementGrp) pm.refresh() else: bindGrp = nt.Transform(u'CT_bnd_grp') #--------------------------------------------------------- sec motion system if 'sec_motion_system' in data.build_actions: face.buildSecondaryControlSystem(placementGrp, bindGrp, mesh) pm.refresh() #------------------------------------------------------------ pri ctl system first if 'primary_ctl_system_first' in data.build_actions: # run a simple first pass # which can be used to block out mappings bndsForPriCtls = data.all_bnds_for_priCtls priCtl.setupPriCtlFirstPass(bindGrp, bndsForPriCtls) priCtl.driveAttachedPriCtlsRun(bindGrp) #------------------------------------------------------------ pri ctl system second if 'primary_ctl_system_second' in data.build_actions: if data.priCtlMappings: # if priCtlMappings is set up, use the data priCtlMappings = data.priCtlMappings priCtl.setupPriCtlSecondPass(priCtlMappings) priCtl.driveAttachedPriCtlsRun(bindGrp) pm.refresh() else: pm.warning('no data for pri ctl system') #-------------------------------------------------------------- load weights if 'load_weights' in data.build_actions: priCtlWeights = data.priCtlWeights priCtl.setPriCtlSecondPassWeights(priCtlWeights) pm.refresh() #--------------------------------------------------------------------- clean if 'clean' in data.build_actions: print 'clean' face.cleanFaceRig() pm.select(cl=True) pm.refresh() #--------------------------------------------------------------- skin_layers if 'skin_layers' in data.build_actions: mll = skin.setupSkinLayers(None, layers=[ 'base', 'jaw', 'cheeks', 'crease', 'lips', 'mouthbag', 'nose', 'brow' ]) _, skn = mll.getTargetInfo() pm.PyNode(skn).skinningMethod.set(1) pm.PyNode(skn).deformUserNormals.set(0) #---------------------------------------------------------------------- eyes if 'eyes' in data.build_actions: buildEyeRig(placementGrp) #------------------------------------------------------------------ eyeballs if 'eyeballs' in data.build_actions: #------------------------------------------ EYEBALL RIG (SIMPLE AIM CONSTRAINTS) eye.buildEyeballRig() eye.addEyeAim(prefix='LT_', distance=25) # BROKEN if there is already a # node named LT_eyeball_grp!!! eye.addEyeAim(prefix='RT_', distance=25) # BROKEN #--------------------------------------------------------------- fleshy_eyes if 'fleshy_eyes' in data.build_actions: import rigger.modules.poseReader as poseReader reload(poseReader) xfo = pm.PyNode('LT_eyeball_bnd') poseReader.radial_pose_reader(xfo) xfo = pm.PyNode('RT_eyeball_bnd') poseReader.radial_pose_reader(xfo) eye.addFleshyEye() #--------------------------------------------------------------- sticky lips if 'sticky_lips' in data.build_actions: import rigger.modules.sticky as sticky reload(sticky) sticky.Sticky(up_bnd=pm.PyNode('CT_upper_lip_bnd'), low_bnd=pm.PyNode('CT_lower_lip_bnd'), center=pm.PyNode('CT__jaw_pri_ctrl')) sticky.Sticky(up_bnd=pm.PyNode('LT_upperSide_lip_bnd'), low_bnd=pm.PyNode('LT_lowerSide_lip_bnd'), center=pm.PyNode('CT__jaw_pri_ctrl')) sticky.Sticky(up_bnd=pm.PyNode('LT_upperSneer_lip_bnd'), low_bnd=pm.PyNode('LT_lowerSneer_lip_bnd'), center=pm.PyNode('CT__jaw_pri_ctrl')) sticky.Sticky(up_bnd=pm.PyNode('LT_upperPinch_lip_bnd'), low_bnd=pm.PyNode('LT_lowerPinch_lip_bnd'), center=pm.PyNode('CT__jaw_pri_ctrl')) sticky.Sticky(up_bnd=pm.PyNode('RT_upperSide_lip_bnd'), low_bnd=pm.PyNode('RT_lowerSide_lip_bnd'), center=pm.PyNode('CT__jaw_pri_ctrl')) sticky.Sticky(up_bnd=pm.PyNode('RT_upperSneer_lip_bnd'), low_bnd=pm.PyNode('RT_lowerSneer_lip_bnd'), center=pm.PyNode('CT__jaw_pri_ctrl')) sticky.Sticky(up_bnd=pm.PyNode('RT_upperPinch_lip_bnd'), low_bnd=pm.PyNode('RT_lowerPinch_lip_bnd'), center=pm.PyNode('CT__jaw_pri_ctrl')) sticky.addStickyToFRS() sticky.patchOldSticky() #----------------------------------------------------------------- auto_sdks if 'auto_sdks' in data.build_actions: import utils.rigging as rt pCtl = pm.PyNode('CT__mouthMover_pri_ctrl') offsetGrp = priCtl.addOffset(pCtl, 'child', suffix='_autoRotate') rt.connectSDK(pCtl.tx, offsetGrp.ry, {-1.2: -15, 0: 0, 1.2: 15}) rt.connectSDK(pCtl.tx, offsetGrp.rz, {-1.2: -12, 0: 0, 1.2: 12}) rt.connectSDK(pCtl.tx, offsetGrp.tz, {-1.2: 0.4, 0: 0, 1.2: 0.4}) # squint pCtl = pm.PyNode('LT__squint_pri_ctrl') offsetGrp = priCtl.addOffset(pCtl, 'parent', suffix='_autoVolume') rt.connectSDK(pCtl.ty, offsetGrp.tz, {0: 0, 1: 0.5}) pCtl = pm.PyNode('RT__squint_pri_ctrl') offsetGrp = priCtl.addOffset(pCtl, 'parent', suffix='_autoVolume') rt.connectSDK(pCtl.ty, offsetGrp.tz, {0: 0, 1: 0.5}) # inbrow import rigger.modules.secCtl as secCtl reload(secCtl) sCtl = pm.PyNode('LT_in_brow_ctrl') offsetGrp = secCtl.addOffset(sCtl, 'parent', suffix='_autoVolume') rt.connectSDK(sCtl.tx, offsetGrp.tz, {0: 0, -1: 0.2}) sCtl = pm.PyNode('RT_in_brow_ctrl') offsetGrp = secCtl.addOffset(sCtl, 'parent', suffix='_autoVolume') rt.connectSDK(sCtl.tx, offsetGrp.tz, {0: 0, 1: 0.2}) if 'finish_mathilda' in data.build_actions: # a few mathilda specific things to finalize rig # for demo reel purposes # 1. lock all TZs for better volume allCtls = pm.ls('*_ctrl', type='transform') for ctl in allCtls: ctl.tz.set(l=True, k=False) # 2. hide eye aim locators eyeAimLocs = [ nt.Transform(u'LT_eye_aim_loc'), nt.Transform(u'RT_eye_aim_loc') ] for loc in eyeAimLocs: loc.v.set(False) # 3. go to object mode so we can select controls pm.selectMode(object=True) # 4. bind tongue and teeth geos = [ nt.Transform(u'CT_lowerGums_geo'), nt.Transform(u'CT_tongue_geo'), nt.Transform(u'CT_lowerTeeth_geo') ] for geo in geos: pm.parentConstraint(pm.PyNode('CT__jaw_bnd'), geo, mo=True) ''' # 5. reference all geos to make it easier to select controls allGeos = pm.PyNode('CT_geo_grp').getChildren(ad=True, type='mesh') for geo in allGeos: geo.overrideEnabled.set(True) geo.overrideDisplayType.set(True) ''' # 6. smooth face mesh to make it look nicer pm.PyNode('CT_face_geoShape').displaySmoothMesh.set(2)
def RibbonCreation(self, Object01, Object02, foliculeNumber=5): print 'creating riboon in %s and %s' % (Object01, Object02) self.baseObjects.append(Object01) self.baseObjects.append(Object02) VP1 = om.MVector(pm.xform(Object01, a=True, ws=True, q=True, rp=True)) VP2 = om.MVector(pm.xform(Object02, a=True, ws=True, q=True, rp=True)) plano = self.nurbPlaneBetweenObjects(Object01, Object02) planoShape = pm.listRelatives(plano, shapes=True)[0] pm.select(cl=True) RibbonSize = VP1 - VP2 print "plano = %s" % plano print "len = %s" % RibbonSize.length() MainSkeleton = pm.group(em=True, name="%sTo%sRibbon" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) self.name_conv.rename_name_in_format(MainSkeleton, {}, useName=True) HairGroup = pm.group(em=True, name="%sTo%sHairSystem" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) self.name_conv.set_name_in_format(HairGroup, useName=True) nstep = 1.0 / (foliculeNumber - 1.0) Hys = pm.language.Mel.eval('createNode hairSystem') Hys = "hairSystem1" ArrayJoints = [] HairSystemIndex = [0] folicules = [] for n in range(foliculeNumber): pm.language.Mel.eval( 'createHairCurveNode("%s", "%s" ,%s ,.5 , 1 ,0 ,0 ,0 ,0 ,"" ,1.0 ,{%s} ,"" ,"" ,2 );' % (Hys, planoShape, nstep * n, n)) NewFolicule = self.name_conv.rename_name_in_format("follicle1", {}) folicules.append(NewFolicule) pm.parent(NewFolicule, HairGroup) self.folicules = folicules pm.delete(pm.listRelatives(Hys, p=True)) index = 0 skinedJoints = pm.group(em=True, name="%sTo%sskinedJoints" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) self.name_conv.rename_name_in_format(skinedJoints, useName=True) for eachFolicule in folicules: ArrayJoints.append( pm.joint(name="%sTo%sRibbonJoints" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02)))) self.name_conv.set_name_in_format(ArrayJoints[index], useName=True) RMRigTools.RMAlign(eachFolicule, ArrayJoints[index], 3) pm.parentConstraint(eachFolicule, ArrayJoints[index]) index += 1 self.jointStructure = ArrayJoints controles = [] resetControles = [] locatorControlesList = [] locatorLookAtList = [] jointsLookAtList = [] groupLookAtList = [] GroupControls = pm.group(empty=True, name="%sTo%sControls" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) self.name_conv.rename_name_in_format(GroupControls, {}, useName=True) GroupJoints = pm.group(empty=True, name="%sTo%sGroupJointsLookAt" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) self.name_conv.rename_name_in_format(GroupJoints, {}, useName=True) self.allControls.append(GroupControls) self.joints.append(GroupJoints) for iloop in range(3): resetControlGroup, control = self.rig_controls.RMCircularControl( Object01, radius=RibbonSize.length() / 3, name="%sTo%sCtrl" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) controles.append(control) resetControles.append(resetControlGroup) locatorControl = pm.spaceLocator( name="%sTo%sLocatorCntrl" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) self.name_conv.rename_name_in_format(locatorControl, {}, useName=True) locatorControlesList.append(locatorControl[0]) RMRigTools.RMAlign(Object01, locatorControl[0], 3) locatorLookAt = pm.spaceLocator( name="%sTo%sLocatorLookAt" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) self.name_conv.rename_name_in_format(locatorLookAt, {}, useName=True) locatorLookAtList.append(locatorLookAt[0]) RMRigTools.RMAlign(Object01, locatorLookAt[0], 3) pm.select(clear=True) jointsLookAt = pm.joint( name="%sTo%sJointsLookAt" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) self.name_conv.rename_name_in_format(jointsLookAt, {}, useName=True) jointsLookAtList.append(jointsLookAt) RMRigTools.RMAlign(Object01, jointsLookAt, 3) groupLookAt = pm.group(empty=True, name="%sTo%sGroupLookAt" % (self.name_conv.get_a_short_name(Object01), self.name_conv.get_a_short_name(Object02))) self.name_conv.rename_name_in_format(groupLookAt, {}, useName=True) self.kinematics.append(groupLookAt) groupLookAtList.append(groupLookAt) RMRigTools.RMAlign(Object01, groupLookAt, 3) pm.parent(groupLookAtList, MainSkeleton) pm.move(RibbonSize.length() / 2 * iloop, 0, 0, resetControlGroup, r=True, os=True, moveX=True) pm.move(RibbonSize.length() / 2 * iloop, 0, 0, locatorControl, r=True, os=True, moveX=True) pm.move(RibbonSize.length() / 2 * iloop, 0, 1, locatorLookAt, r=True, os=True, moveXYZ=True) pm.move(RibbonSize.length() / 2 * iloop, 0, 0, jointsLookAt, r=True, os=True, moveX=True) pm.move(RibbonSize.length() / 2 * iloop, 0, 0, groupLookAt, r=True, os=True, moveX=True) pm.parent(resetControlGroup, GroupControls) pm.parent(locatorControl, groupLookAt) pm.parent(locatorLookAt, groupLookAt) pm.parent(jointsLookAt, GroupJoints) pm.makeIdentity(control, apply=True, t=1, r=0, s=1, n=0) pm.makeIdentity(jointsLookAt, apply=True, t=1, r=0, s=1, n=0) pm.parentConstraint(locatorControl, jointsLookAt) pm.parentConstraint(control, groupLookAt) self.controls = controles self.resetControls = resetControles self.resetControls = resetControles pm.aimConstraint(controles[1], locatorControlesList[0], aim=[1, 0, 0], upVector=[0, 0, 1], wut='object', worldUpObject=locatorLookAtList[0]) pm.aimConstraint(controles[1], locatorControlesList[2], aim=[1, 0, 0], upVector=[0, 0, 1], wut='object', worldUpObject=locatorLookAtList[2]) pm.parent(GroupJoints, MainSkeleton) pm.select(plano, replace=True) print jointsLookAtList for eachJoint in jointsLookAtList: pm.select(eachJoint, add=True) pm.SmoothBindSkin() pm.parent(plano, HairGroup)
def create_parentConst(self, source, dest, maintainOff=0): return (pm.parentConstraint(source, dest, mo=maintainOff))
def addOperators(self): """Create operators and set the relations for the component rig Apply operators, constraints, expressions to the hierarchy. In order to keep the code clean and easier to debug, we shouldn't create any new object in this method. """ # 1 bone chain Upv ref ============================== self.ikHandleUpvRef = primitive.addIkHandle( self.root, self.getName("ikHandleLegChainUpvRef"), self.legChainUpvRef, "ikSCsolver") pm.pointConstraint(self.ik_ctl, self.ikHandleUpvRef) pm.parentConstraint(self.legChainUpvRef[0], self.ik_ctl, self.upv_cns, mo=True) # Visibilities ------------------------------------- # shape.dispGeometry # fk fkvis_node = node.createReverseNode(self.blend_att) for shp in self.fk0_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) for shp in self.fk1_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) for shp in self.fk2_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) # ik for shp in self.upv_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ikcns_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ik_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.line_ref.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) # IK Solver ----------------------------------------- out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_loc] o_node = applyop.gear_ikfk2bone_op(out, self.root_ctl, self.ik_ref, self.upv_ctl, self.fk_ctl[0], self.fk_ctl[1], self.fk_ref, self.length0, self.length1, self.negate) pm.connectAttr(self.blend_att, o_node + ".blend") if self.negate: mulVal = -1 else: mulVal = 1 node.createMulNode(self.roll_att, mulVal, o_node + ".roll") # pm.connectAttr(self.roll_att, o_node+".roll") pm.connectAttr(self.scale_att, o_node + ".scaleA") pm.connectAttr(self.scale_att, o_node + ".scaleB") pm.connectAttr(self.maxstretch_att, o_node + ".maxstretch") pm.connectAttr(self.slide_att, o_node + ".slide") pm.connectAttr(self.softness_att, o_node + ".softness") pm.connectAttr(self.reverse_att, o_node + ".reverse") # Twist references --------------------------------- o_node = applyop.gear_mulmatrix_op( self.eff_loc.attr("worldMatrix"), self.root.attr("worldInverseMatrix")) dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix") pm.connectAttr(dm_node + ".outputTranslate", self.tws2_npo.attr("translate")) dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(o_node + ".output", dm_node + ".inputMatrix") pm.connectAttr(dm_node + ".outputRotate", self.tws2_npo.attr("rotate")) # spline IK for twist jnts self.ikhUpLegTwist, self.uplegTwistCrv = applyop.splineIK( self.getName("uplegTwist"), self.uplegTwistChain, parent=self.root, cParent=self.bone0) self.ikhLowLegTwist, self.lowlegTwistCrv = applyop.splineIK( self.getName("lowlegTwist"), self.lowlegTwistChain, parent=self.root, cParent=self.bone1) # references self.ikhUpLegRef, self.tmpCrv = applyop.splineIK( self.getName("uplegRollRef"), self.uplegRollRef, parent=self.root, cParent=self.bone0) self.ikhLowLegRef, self.tmpCrv = applyop.splineIK( self.getName("lowlegRollRef"), self.lowlegRollRef, parent=self.root, cParent=self.eff_loc) self.ikhAuxTwist, self.tmpCrv = applyop.splineIK( self.getName("auxTwist"), self.auxTwistChain, parent=self.root, cParent=self.eff_loc) # setting connexions for ikhUpLegTwist self.ikhUpLegTwist.attr("dTwistControlEnable").set(True) self.ikhUpLegTwist.attr("dWorldUpType").set(4) self.ikhUpLegTwist.attr("dWorldUpAxis").set(3) self.ikhUpLegTwist.attr("dWorldUpVectorZ").set(1.0) self.ikhUpLegTwist.attr("dWorldUpVectorY").set(0.0) self.ikhUpLegTwist.attr("dWorldUpVectorEndZ").set(1.0) self.ikhUpLegTwist.attr("dWorldUpVectorEndY").set(0.0) pm.connectAttr(self.uplegRollRef[0].attr("worldMatrix[0]"), self.ikhUpLegTwist.attr("dWorldUpMatrix")) pm.connectAttr(self.bone0.attr("worldMatrix[0]"), self.ikhUpLegTwist.attr("dWorldUpMatrixEnd")) # setting connexions for ikhAuxTwist self.ikhAuxTwist.attr("dTwistControlEnable").set(True) self.ikhAuxTwist.attr("dWorldUpType").set(4) self.ikhAuxTwist.attr("dWorldUpAxis").set(3) self.ikhAuxTwist.attr("dWorldUpVectorZ").set(1.0) self.ikhAuxTwist.attr("dWorldUpVectorY").set(0.0) self.ikhAuxTwist.attr("dWorldUpVectorEndZ").set(1.0) self.ikhAuxTwist.attr("dWorldUpVectorEndY").set(0.0) pm.connectAttr(self.lowlegRollRef[0].attr("worldMatrix[0]"), self.ikhAuxTwist.attr("dWorldUpMatrix")) pm.connectAttr(self.tws_ref.attr("worldMatrix[0]"), self.ikhAuxTwist.attr("dWorldUpMatrixEnd")) pm.connectAttr(self.auxTwistChain[1].attr("rx"), self.ikhLowLegTwist.attr("twist")) pm.parentConstraint(self.bone1, self.aux_npo, maintainOffset=True) # scale arm length for twist chain (not the squash and stretch) arclen_node = pm.arclen(self.uplegTwistCrv, ch=True) alAttrUpLeg = arclen_node.attr("arcLength") muldiv_nodeArm = pm.createNode("multiplyDivide") pm.connectAttr(arclen_node.attr("arcLength"), muldiv_nodeArm.attr("input1X")) muldiv_nodeArm.attr("input2X").set(alAttrUpLeg.get()) muldiv_nodeArm.attr("operation").set(2) for jnt in self.uplegTwistChain: pm.connectAttr(muldiv_nodeArm.attr("outputX"), jnt.attr("sx")) # scale forearm length for twist chain (not the squash and stretch) arclen_node = pm.arclen(self.lowlegTwistCrv, ch=True) alAttrLowLeg = arclen_node.attr("arcLength") muldiv_nodeLowLeg = pm.createNode("multiplyDivide") pm.connectAttr(arclen_node.attr("arcLength"), muldiv_nodeLowLeg.attr("input1X")) muldiv_nodeLowLeg.attr("input2X").set(alAttrLowLeg.get()) muldiv_nodeLowLeg.attr("operation").set(2) for jnt in self.lowlegTwistChain: pm.connectAttr(muldiv_nodeLowLeg.attr("outputX"), jnt.attr("sx")) # scale compensation for the first twist join dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(self.root.attr("worldMatrix[0]"), dm_node.attr("inputMatrix")) pm.connectAttr(dm_node.attr("outputScale"), self.uplegTwistChain[0].attr("inverseScale")) pm.connectAttr(dm_node.attr("outputScale"), self.lowlegTwistChain[0].attr("inverseScale")) # tangent controls muldiv_node = pm.createNode("multiplyDivide") muldiv_node.attr("input2X").set(-1) pm.connectAttr(self.tws1A_npo.attr("rz"), muldiv_node.attr("input1X")) muldiv_nodeBias = pm.createNode("multiplyDivide") pm.connectAttr(muldiv_node.attr("outputX"), muldiv_nodeBias.attr("input1X")) pm.connectAttr(self.roundness_att, muldiv_nodeBias.attr("input2X")) pm.connectAttr(muldiv_nodeBias.attr("outputX"), self.tws1A_loc.attr("rz")) if self.negate: axis = "xz" else: axis = "-xz" applyop.aimCns(self.tws1A_npo, self.tws0_loc, axis=axis, wupType=2, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) applyop.aimCns(self.lowlegTangentB_loc, self.lowlegTangentA_npo, axis=axis, wupType=2, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) pm.pointConstraint(self.eff_loc, self.lowlegTangentB_loc) muldiv_node = pm.createNode("multiplyDivide") muldiv_node.attr("input2X").set(-1) pm.connectAttr(self.tws1B_npo.attr("rz"), muldiv_node.attr("input1X")) muldiv_nodeBias = pm.createNode("multiplyDivide") pm.connectAttr(muldiv_node.attr("outputX"), muldiv_nodeBias.attr("input1X")) pm.connectAttr(self.roundness_att, muldiv_nodeBias.attr("input2X")) pm.connectAttr(muldiv_nodeBias.attr("outputX"), self.tws1B_loc.attr("rz")) if self.negate: axis = "-xz" else: axis = "xz" applyop.aimCns(self.tws1B_npo, self.tws2_loc, axis=axis, wupType=2, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) applyop.aimCns(self.uplegTangentA_loc, self.uplegTangentB_npo, axis=axis, wupType=2, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) # Volume ------------------------------------------- distA_node = node.createDistNode(self.tws0_loc, self.tws1_loc) distB_node = node.createDistNode(self.tws1_loc, self.tws2_loc) add_node = node.createAddNode(distA_node + ".distance", distB_node + ".distance") div_node = node.createDivNode(add_node + ".output", self.root_ctl.attr("sx")) # comp scaling issue dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(self.root.attr("worldMatrix"), dm_node + ".inputMatrix") div_node2 = node.createDivNode(div_node + ".outputX", dm_node + ".outputScaleX") self.volDriver_att = div_node2 + ".outputX" # connecting tangent scaele compensation after volume to # avoid duplicate some nodes distA_node = node.createDistNode(self.tws0_loc, self.mid_ctl) distB_node = node.createDistNode(self.mid_ctl, self.tws2_loc) div_nodeUpLeg = node.createDivNode(distA_node + ".distance", dm_node.attr("outputScaleX")) div_node2 = node.createDivNode(div_nodeUpLeg + ".outputX", distA_node.attr("distance").get()) pm.connectAttr(div_node2.attr("outputX"), self.tws1A_loc.attr("sx")) pm.connectAttr(div_node2.attr("outputX"), self.uplegTangentA_loc.attr("sx")) div_nodeLowLeg = node.createDivNode(distB_node + ".distance", dm_node.attr("outputScaleX")) div_node2 = node.createDivNode(div_nodeLowLeg + ".outputX", distB_node.attr("distance").get()) pm.connectAttr(div_node2.attr("outputX"), self.tws1B_loc.attr("sx")) pm.connectAttr(div_node2.attr("outputX"), self.lowlegTangentB_loc.attr("sx")) # conection curve cnts = [ self.uplegTangentA_loc, self.uplegTangentA_ctl, self.uplegTangentB_ctl, self.kneeTangent_ctl ] applyop.gear_curvecns_op(self.uplegTwistCrv, cnts) cnts = [ self.kneeTangent_ctl, self.lowlegTangentA_ctl, self.lowlegTangentB_ctl, self.lowlegTangentB_loc ] applyop.gear_curvecns_op(self.lowlegTwistCrv, cnts) # Tangent controls vis for shp in self.uplegTangentA_ctl.getShapes(): pm.connectAttr(self.tangentVis_att, shp.attr("visibility")) for shp in self.uplegTangentB_ctl.getShapes(): pm.connectAttr(self.tangentVis_att, shp.attr("visibility")) for shp in self.lowlegTangentA_ctl.getShapes(): pm.connectAttr(self.tangentVis_att, shp.attr("visibility")) for shp in self.lowlegTangentB_ctl.getShapes(): pm.connectAttr(self.tangentVis_att, shp.attr("visibility")) for shp in self.kneeTangent_ctl.getShapes(): pm.connectAttr(self.tangentVis_att, shp.attr("visibility")) # Divisions ---------------------------------------- # at 0 or 1 the division will follow exactly the rotation of the # controler.. and we wont have this nice tangent + roll for i, div_cns in enumerate(self.div_cns): if i < (self.settings["div0"] + 2): mulmat_node = applyop.gear_mulmatrix_op( self.uplegTwistChain[i] + ".worldMatrix", div_cns + ".parentInverseMatrix") lastUpLegDiv = div_cns else: o_node = self.lowlegTwistChain[i - (self.settings["div0"] + 2)] mulmat_node = applyop.gear_mulmatrix_op( o_node + ".worldMatrix", div_cns + ".parentInverseMatrix") lastLowLegDiv = div_cns dm_node = node.createDecomposeMatrixNode(mulmat_node + ".output") pm.connectAttr(dm_node + ".outputTranslate", div_cns + ".t") pm.connectAttr(dm_node + ".outputRotate", div_cns + ".r") # Squash n Stretch o_node = applyop.gear_squashstretch2_op( div_cns, None, pm.getAttr(self.volDriver_att), "x") pm.connectAttr(self.volume_att, o_node + ".blend") pm.connectAttr(self.volDriver_att, o_node + ".driver") pm.connectAttr(self.st_att[i], o_node + ".stretch") pm.connectAttr(self.sq_att[i], o_node + ".squash") # force translation for last loc arm and foreamr applyop.gear_mulmatrix_op(self.kneeTangent_ctl.worldMatrix, lastUpLegDiv.parentInverseMatrix, lastUpLegDiv, "t") applyop.gear_mulmatrix_op(self.tws2_loc.worldMatrix, lastLowLegDiv.parentInverseMatrix, lastLowLegDiv, "t") # NOTE: next line fix the issue on meters. # This is special case becasuse the IK solver from mGear use the # scale as lenght and we have shear # TODO: check for a more clean and elegant solution instead of # re-match the world matrix again transform.matchWorldTransform(self.fk_ctl[0], self.match_fk0_off) transform.matchWorldTransform(self.fk_ctl[1], self.match_fk1_off) transform.matchWorldTransform(self.fk_ctl[0], self.match_fk0) transform.matchWorldTransform(self.fk_ctl[1], self.match_fk1) # match IK/FK ref pm.parentConstraint(self.bone0, self.match_fk0_off, mo=True) pm.parentConstraint(self.bone1, self.match_fk1_off, mo=True) return
def createcustomCtrl(self): #alphabet = list(string.ascii_uppercase) vertsList = pm.ls(sl=1) for vert in vertsList: mainObj = pm.PyNode(vert.split(".")[0]) weightsList = self.softSelection() name = self.newControlName.toPlainText() check = cmds.ls("customCtrl_GRP") if check == []: ctrlGrp = pm.group(em=True, name="customCtrl_GRP") staticGRP = pm.group(em=True, name="staticSetup_GRP") staticGeoGRP = pm.group(em=True, name="staticGeo_GRP") pm.parent(staticGRP, ctrlGrp) pm.parent(staticGeoGRP, ctrlGrp) else: ctrlGrp = "customCtrl_GRP" staticGRP = "staticSetup_GRP" offsetGrp = pm.group(em=True, name="{}_offset_GRP".format(name)) vertPos = vert.getPosition(space="world") ctrl = self.makeCtrl(name) pm.parent(ctrl, ctrlGrp) ctrl.setTranslation(vertPos) pm.makeIdentity(ctrl, a=1) prtCns = pm.parentConstraint(ctrl, offsetGrp) pm.delete(prtCns) pm.parent(offsetGrp, ctrlGrp) mainJnt = pm.joint(n="{}MainJNT".format(name)) pm.xform(mainJnt, ws=1, t=mainObj.getTranslation()) duplikats = [] for object in weightsList[2]: mesh = object #pm.PyNode(vert.split(".")[0].replace("Shape","")) duplikat = pm.duplicate(mesh, n="{}{}BLN".format(mesh, name))[0] pm.select(cl=1) pm.skinCluster(duplikat, mainJnt) pm.parent(duplikat, staticGeoGRP) duplikats.append(duplikat) #meshBlnVert = "{}.{}".format(pm.PyNode(duplikat).getShape(),vert.split(".")[1]) #vertBln = pm.PyNode(meshBlnVert) edges = vert.connectedEdges() print edges e = pm.ls(edges, fl=1) curve = self.convertToCurve(e[:2]) curveShape = pm.PyNode(curve[0]).getShape() print curveShape pm.disconnectAttr("{}.outputcurve".format(curve[1]), "{}.create".format(curveShape)) pm.delete(curve[0]) fallowNode = "{}_fallow".format(name) pm.rename(curve[1], fallowNode) nodePoc = pm.createNode("pointOnCurveInfo", n="{}POC".format(name)) pm.setAttr("{}.parameter".format(nodePoc), 0.5) pm.connectAttr("{}.outputcurve".format(fallowNode), "{}.inputCurve".format(nodePoc)) fallowLoc = self.createLocatorFollicle() fallowLoc = pm.rename(fallowLoc, "{}_fallowLoc".format(name)) #pm.xform(fallowLoc, ws=1, t=vertPos) #pm.makeIdentity(fallowLoc, a=1) #pm.select(cl=1) jntBln = pm.joint(n="{}_blnJNT".format(name)) pm.xform(jntBln, ws=1, t=vertPos) pm.parent(jntBln, fallowLoc) pm.parent(fallowLoc, staticGRP) self.connectPosOffset(fallowLoc, offsetGrp) #pm.connectAttr("{}.position".format(nodePoc), "{}.translate".format(offsetGrp)) pm.parent(ctrl, offsetGrp) pm.makeIdentity(ctrl, a=1) #pm.connectAttr("{}.translate".format(ctrl), "{}.translate".format(fallowLoc)) activeSkincluster = \ pm.listConnections(pm.PyNode(duplikat).getShape(), type="skinCluster")[0] pm.skinCluster(activeSkincluster, e=1, wt=0, lw=1, ai=jntBln) pm.setAttr("{}.liw".format(jntBln), 0) for vert, w in zip(weightsList[0], weightsList[1]): print vert, w for duplikat in duplikats: if duplikat in vert: cmds.skinPercent(str(activeSkincluster), "{}.{}".format(duplikat,vert.split(".")[1]), transformValue=[(str(jntBln), w)])
def mapControlsToFeaturePts(): ctlGrp = pm.PyNode('face_ctrls_grp') allCtls = [ctl.getChildren()[0] for ctl in ctlGrp.getChildren()] # group level allCtls = [grp.getChildren()[0] for grp in allCtls] priCtlGrp = pm.PyNode('CT_face_primary_ctls_grp') allPriCtls = [ctl.getChildren()[0] for ctl in priCtlGrp.getChildren()] # group level allPriCtls = [grp.getChildren()[0] for grp in allPriCtls] ctlToTargetTable = {} for eachCtl in allCtls: cons = eachCtl.getChildren(type='constraint') if cons: targets = cons[0].getTargetList() ctlToTargetTable[eachCtl] = targets ctlToTargetTable = {nt.Transform(u'CT_brow_ctrl'): [nt.Transform(u'Offset_TNOS')], nt.Transform(u'CT_chin_ctrl'): [nt.Transform(u'Marker_RCHN'), nt.Transform(u'Marker_LCHN')], nt.Transform(u'CT_lower_lip_ctrl'): [nt.Transform(u'Offset_RLLP'), nt.Transform(u'Offset_LLLP')], nt.Transform(u'CT_mid_chin_ctrl'): [nt.Transform(u'Offset_CHIN')], nt.Transform(u'CT_noseTip_pri_ctrl'): [nt.Transform(u'Offset_MNOS')], nt.Transform(u'CT_upper_lip_ctrl'): [nt.Transform(u'Offset_RMLP'), nt.Transform(u'Offset_LMLP')], nt.Transform(u'LT_cheek_pri_ctrl'): [nt.Transform(u'Offset_LTCH')], nt.Transform(u'LT_chin_ctrl'): [nt.Transform(u'Offset_LCHN')], nt.Transform(u'LT_corner_lip_pri_ctrl'): [nt.Transform(u'Offset_LOLP')], nt.Transform(u'LT_eyelid_lower_pri_ctrl'): [nt.Transform(u'Offset_LLACH')], nt.Transform(u'LT_eyelid_upper_pri_ctrl'): [nt.Transform(u'Offset_LLID')], nt.Transform(u'LT_in_brow_ctrl'): [nt.Transform(u'Offset_LIBR')], nt.Transform(u'LT_in_cheek_ctrl'): [nt.Transform(u'Offset_LOEY')], nt.Transform(u'LT_in_forehead_ctrl'): [nt.Transform(u'Offset_LUFH1')], nt.Transform(u'LT_in_low_forehead_ctrl'): [nt.Transform(u'Offset_LTFH1')], nt.Transform(u'LT_in_philtrum_ctrl'): [nt.Transform(u'Offset_ULLIP1')], nt.Transform(u'LT_low_cheek_ctrl'): [nt.Transform(u'Offset_LICH')], nt.Transform(u'LT_low_crease_ctrl'): [nt.Transform(u'Offset_LBCH')], nt.Transform(u'LT_low_jaw_ctrl'): [nt.Transform(u'Offset_LMCH')], nt.Transform(u'LT_low_temple_ctrl'): [nt.Transform(u'Offset_LTEMP')], nt.Transform(u'LT_lower_pinch_lip_ctrl'): [nt.Transform(u'Offset_LBLP'), nt.Transform(u'Offset_LOLP')], nt.Transform(u'LT_lower_sneer_lip_ctrl'): [nt.Transform(u'Offset_LBLP')], nt.Transform(u'LT_lower_side_lip_ctrl'): [nt.Transform(u'Offset_LLLP')], nt.Transform(u'LT_mid_brow_pri_ctrl'): [nt.Transform(u'Offset_LMBR')], nt.Transform(u'LT_mid_chin_ctrl'): [nt.Transform(u'Offset_LCHIN')], nt.Transform(u'LT_mid_crease_ctrl'): [nt.Transform(u'Offset_LNOSE')], nt.Transform(u'LT_out_brow_ctrl'): [nt.Transform(u'Offset_LUBR')], nt.Transform(u'LT_out_cheek_ctrl'): [nt.Transform(u'Offset_LOCH')], nt.Transform(u'LT_out_forehead_ctrl'): [nt.Transform(u'Offset_LUFH')], nt.Transform(u'LT_out_low_forehead_ctrl'): [nt.Transform(u'Offset_LTFH')], nt.Transform(u'LT_philtrum_ctrl'): [nt.Transform(u'Offset_LMOU')], nt.Transform(u'LT_sneer_ctrl'): [nt.Transform(u'Offset_ULLIP')], nt.Transform(u'LT_squint_ctrl'): [nt.Transform(u'Offset_LIEY')], nt.Transform(u'LT_temple_ctrl'): [nt.Transform(u'Offset_LOBR')], nt.Transform(u'LT_up_cheek_ctrl'): [nt.Transform(u'Offset_LMEY')], nt.Transform(u'LT_up_crease_ctrl'): [nt.Transform(u'Offset_LOEY'), nt.Transform(u'Offset_LMEY'), nt.Transform(u'Offset_LNOSE'), nt.Transform(u'Offset_LMOU')], nt.Transform(u'LT_up_jaw_ctrl'): [nt.Transform(u'Offset_LTJA')], nt.Transform(u'LT_upper_pinch_lip_ctrl'): [nt.Transform(u'Offset_LTLP'), nt.Transform(u'Offset_LOLP')], nt.Transform(u'LT_upper_sneer_lip_ctrl'): [nt.Transform(u'Offset_LTLP')], nt.Transform(u'LT_upper_side_lip_ctrl'): [nt.Transform(u'Offset_LMLP')], nt.Transform(u'RT_cheek_pri_ctrl'): [nt.Transform(u'Offset_RTCH')], nt.Transform(u'RT_chin_ctrl'): [nt.Transform(u'Offset_RCHN')], nt.Transform(u'RT_corner_lip_pri_ctrl'): [nt.Transform(u'Offset_ROLP')], nt.Transform(u'RT_eyelid_lower_pri_ctrl'): [nt.Transform(u'Offset_RLACH')], nt.Transform(u'RT_eyelid_upper_pri_ctrl'): [nt.Transform(u'Offset_RLID')], nt.Transform(u'RT_in_brow_ctrl'): [nt.Transform(u'Offset_RIBR')], nt.Transform(u'RT_in_cheek_ctrl'): [nt.Transform(u'Offset_ROEY')], nt.Transform(u'RT_in_forehead_ctrl'): [nt.Transform(u'Offset_RUFH1')], nt.Transform(u'RT_in_low_forehead_ctrl'): [nt.Transform(u'Offset_RTFH1')], nt.Transform(u'RT_in_philtrum_ctrl'): [nt.Transform(u'Offset_URLIP1')], nt.Transform(u'RT_low_cheek_ctrl'): [nt.Transform(u'Offset_RICH')], nt.Transform(u'RT_low_crease_ctrl'): [nt.Transform(u'Offset_RBCH')], nt.Transform(u'RT_low_jaw_ctrl'): [nt.Transform(u'Offset_RMCH')], nt.Transform(u'RT_low_temple_ctrl'): [nt.Transform(u'Offset_RTEMP')], nt.Transform(u'RT_lower_pinch_lip_ctrl'): [nt.Transform(u'Offset_RBLP'), nt.Transform(u'Offset_ROLP')], nt.Transform(u'RT_lower_sneer_lip_ctrl'): [nt.Transform(u'Offset_RBLP')], nt.Transform(u'RT_lower_side_lip_ctrl'): [nt.Transform(u'Offset_RLLP')], nt.Transform(u'RT_mid_brow_pri_ctrl'): [nt.Transform(u'Offset_RMBR')], nt.Transform(u'RT_mid_chin_ctrl'): [nt.Transform(u'Offset_RCHIN')], nt.Transform(u'RT_mid_crease_ctrl'): [nt.Transform(u'Offset_RNOSE')], nt.Transform(u'RT_out_brow_ctrl'): [nt.Transform(u'Offset_RUBR')], nt.Transform(u'RT_out_cheek_ctrl'): [nt.Transform(u'Offset_ROCH')], nt.Transform(u'RT_out_forehead_ctrl'): [nt.Transform(u'Offset_RUFH')], nt.Transform(u'RT_out_low_forehead_ctrl'): [nt.Transform(u'Offset_RTFH')], nt.Transform(u'RT_philtrum_ctrl'): [nt.Transform(u'Offset_RMOU')], nt.Transform(u'RT_sneer_ctrl'): [nt.Transform(u'Offset_URLIP')], nt.Transform(u'RT_squint_ctrl'): [nt.Transform(u'Offset_RIEY')], nt.Transform(u'RT_temple_ctrl'): [nt.Transform(u'Offset_ROBR')], nt.Transform(u'RT_up_cheek_ctrl'): [nt.Transform(u'Offset_RMEY')], nt.Transform(u'RT_up_crease_ctrl'): [nt.Transform(u'Offset_ROEY'), nt.Transform(u'Offset_RMEY'), nt.Transform(u'Offset_RNOSE'), nt.Transform(u'Offset_RMOU')], nt.Transform(u'RT_up_jaw_ctrl'): [nt.Transform(u'Offset_RTJA')], nt.Transform(u'RT_upper_pinch_lip_ctrl'): [nt.Transform(u'Offset_RTLP'), nt.Transform(u'Offset_ROLP')], nt.Transform(u'RT_upper_sneer_lip_ctrl'): [nt.Transform(u'Offset_RTLP')], nt.Transform(u'RT_upper_side_lip_ctrl'): [nt.Transform(u'Offset_RMLP')] } for eachCtl, targets in ctlToTargetTable.items(): pm.parentConstraint(targets, eachCtl, mo=True)
def matchTransforms(source, target): """ Match transform of one object (target) to another (source) """ pm.delete(pm.parentConstraint(target, source, weight=1, mo=False))
def makeJointHair(self, sel, hairSystem): simDuped = pm.duplicate(sel, n='sim_%s' % sel.nodeName())[0] mixDuped = pm.duplicate(sel, n='mix_%s' % sel.nodeName())[0] wgtDuped = pm.duplicate(sel, n='weight_%s' % sel.nodeName())[0] selJointList = self.getJointChainList(sel) simJointList = self.getJointChainList(simDuped) mixJointList = self.getJointChainList(mixDuped) wgtJointList = self.getJointChainList(wgtDuped) if not (selJointList and simJointList and mixJointList): return False num = len(selJointList) pos = sel.getTranslation(space='world') ctrlGrp = pm.group(n='%s_ctrls#' % sel.nodeName(), em=1) axis, circle = self.makeXformController( '%s_top_ctrl#' % sel.nodeName(), '%s_top_ctrl_axis#' % sel.nodeName(), selJointList[0]) circle.addAttr('space', at='enum', en='World:Local', k=1, dv=self.dnspRBGval - 1) circle.addAttr('ctrl_size', at='double', k=1, dv=1.0) circle.attr('ctrl_size') >> circle.attr('scaleX') circle.attr('ctrl_size') >> circle.attr('scaleY') circle.attr('ctrl_size') >> circle.attr('scaleZ') pntMatrix = [] skclList = list(set(sel.outputs(type='skinCluster'))) for i in xrange(num): if i != 0: pm.rename(simJointList[i], 'sim_%s' % simJointList[i].nodeName()) pm.rename(mixJointList[i], 'mix_%s' % mixJointList[i].nodeName()) pos = selJointList[i].getTranslation(space='world') ofstJoint = pm.rename( pm.insertJoint(mixJointList[i]), mixJointList[i].nodeName().replace('mix', 'offset')) pntMatrix.append(pos) attrList = ['tx', 'ty', 'tz', 'rx', 'ry', 'rz'] for attr in attrList: simJointList[i].attr(attr) >> mixJointList[i].attr(attr) pm.parentConstraint(ofstJoint, selJointList[i], mo=True) mixJointList[i].attr('radius').set(0.0) ofstJoint.attr('radius').set(0.0) if not (i == num - 1 and not self.pctlCBXval): ''' # If on, no controllers will be created to the joints which does't have any skinCluster for skcl in skclList: if selJointList[i] in skcl.getInfluence(): break else: continue ''' if self.ctshRBGval == 1: ctrl = self.makeCircleController( '%s_ctrl' % selJointList[i].nodeName()) elif self.ctshRBGval == 2: ctrl = self.makePinController('%s_ctrl' % selJointList[i].nodeName()) elif self.ctshRBGval == 3: ctrl = self.makeOctaController('%s_ctrl' % selJointList[i].nodeName()) ctrl.attr('overrideEnabled').set(1) ctrl.attr('overrideColor').set((self.colrPLTval)) ctrlAxis = pm.group(ctrl, n='%s_ctrl_axis' % selJointList[i].nodeName()) ctrlAxis.attr('rotatePivot').set([0, 0, 0]) ctrlAxis.attr('scalePivot').set([0, 0, 0]) circle.attr('ctrl_size') >> ctrl.attr('scaleX') circle.attr('ctrl_size') >> ctrl.attr('scaleY') circle.attr('ctrl_size') >> ctrl.attr('scaleZ') pm.parentConstraint(mixJointList[i], ctrlAxis) pm.parentConstraint(ctrl, ofstJoint) pm.parent(ctrlAxis, ctrlGrp) # Pour weights to simJointList temporarily for skcl in skclList: if selJointList[i] in skcl.getInfluence(): skcl.addInfluence(wgtJointList[i], wt=0) inflList = skcl.getInfluence() isMaintainMax = skcl.attr('maintainMaxInfluences').get() maxInfl = skcl.attr('maxInfluences').get() isFullInfl = False if isMaintainMax and maxInfl == len(inflList): isFullInfl = True skcl.attr('maintainMaxInfluences').set(False) for infl in inflList: if infl == selJointList[i] or infl == wgtJointList[i]: infl.attr('lockInfluenceWeights').set(False) else: infl.attr('lockInfluenceWeights').set(True) for geo in skcl.getGeometry(): pm.skinPercent(skcl, geo.verts, nrm=True, tv=[selJointList[i], 0]) skcl.removeInfluence(selJointList[i]) if isFullInfl: skcl.attr('maintainMaxInfluences').set(True) crv1d = pm.curve(d=1, p=pntMatrix) crv = pm.fitBspline(crv1d, ch=1, tol=0.001) follicle, hcrv, hairSystem = self.assignHair(crv, hairSystem) follicleGrp = follicle.getParent() curveGrp = hcrv.getParent() ikhandle = pm.ikHandle(sj=simJointList[0], ee=simJointList[num - 1], c=hcrv, createCurve=0, solver='ikSplineSolver')[0] # Pour back for i in xrange(num): for skcl in skclList: if wgtJointList[i] in skcl.getInfluence(): skcl.addInfluence(selJointList[i], wt=0) inflList = skcl.getInfluence() isMaintainMax = skcl.attr('maintainMaxInfluences').get() maxInfl = skcl.attr('maxInfluences').get() isFullInfl = False if isMaintainMax and maxInfl == len(inflList): isFullInfl = True skcl.attr('maintainMaxInfluences').set(False) for infl in inflList: if infl == selJointList[i] or infl == wgtJointList[i]: infl.attr('lockInfluenceWeights').set(False) else: infl.attr('lockInfluenceWeights').set(True) for geo in skcl.getGeometry(): pm.skinPercent(skcl, geo.verts, nrm=True, tv=[wgtJointList[i], 0]) for infl in inflList: infl.attr('lockInfluenceWeights').set(False) attrList = [ wgtJointList[i].attr('message'), wgtJointList[i].attr('bindPose') ] for attr in attrList: for dst in pm.connectionInfo(attr, dfs=True): dst = pm.Attribute(dst) if dst.node().type() == 'dagPose': attr // dst if isFullInfl: skcl.attr('maintainMaxInfluences').set(True) pm.delete(wgtJointList) simGrp = pm.group(simJointList[0], follicle, n='sim_joints#') xformer = pm.group(simGrp, mixJointList[0], selJointList[0], n='%s_transformer#' % sel.nodeName()) hcrv.attr('scalePivot').set( selJointList[0].getTranslation(space='world')) hcrv.attr('rotatePivot').set( selJointList[0].getTranslation(space='world')) ctrlGrp.attr('scalePivot').set( selJointList[0].getTranslation(space='world')) ctrlGrp.attr('rotatePivot').set( selJointList[0].getTranslation(space='world')) simGrp.attr('scalePivot').set( selJointList[0].getTranslation(space='world')) simGrp.attr('rotatePivot').set( selJointList[0].getTranslation(space='world')) mixJointList[0].attr('template').set(1) hcrv.attr('template').set(1) hairSystem.attr('iterations').set(20) xformer.attr('scalePivot').set(axis.getTranslation()) xformer.attr('rotatePivot').set(axis.getTranslation()) wcnst = pm.parentConstraint(circle, hcrv, mo=True) lcnst = pm.parentConstraint(circle, xformer, mo=True) rev = pm.shadingNode('reverse', asUtility=True) circle.attr('space') >> wcnst.attr('%sW0' % wcnst.getTargetList()[0]) circle.attr('space') >> rev.attr('inputX') rev.attr('outputX') >> lcnst.attr('%sW0' % lcnst.getTargetList()[0]) pm.delete(follicleGrp, curveGrp, crv1d) pm.hide(simGrp) crvGrp = self.makeGroupIfNotExist('hairSystemOutputCurves', 0) ikGrp = self.makeGroupIfNotExist('hairSystemIKHandles', 1) nodesGrp = self.makeGroupIfNotExist('hairSystemNodes', 1) pm.parent(hcrv, crvGrp) pm.parent(ikhandle, ikGrp) if hairSystem.getParent() != nodesGrp: pm.parent(hairSystem, nodesGrp) if not pm.objExists(self.topName): topGrp = pm.group(n=self.topName, em=1) pm.parent(nodesGrp, ikGrp, crvGrp, xformer, axis, ctrlGrp, topGrp) else: pm.parent(xformer, axis, ctrlGrp, self.topName) topNode = pm.PyNode(self.topName) self.lockXformAttrs(topNode, False) self.lockXformAttrs(ctrlGrp, False) self.lockXformAttrs(crvGrp, False) self.lockXformAttrs(ikGrp, False) self.lockXformAttrs(nodesGrp, False) pm.select(topNode, r=1) self.selList.pop(0) windowName = 'hairSystem_Window' if pm.window(windowName, ex=1): pm.deleteUI(windowName) if self.selList: self.dialog(self.selList[0]) pm.displayInfo('"Make Joint Hair" has been successfully done.') return True
def addOperators(self): """Create operators and set the relations for the component rig Apply operators, constraints, expressions to the hierarchy. In order to keep the code clean and easier to debug, we shouldn't create any new object in this method. """ # 1 bone chain Upv ref =========================== self.ikHandleUpvRef = primitive.addIkHandle( self.root, self.getName("ikHandleLegChainUpvRef"), self.legChainUpvRef, "ikSCsolver") pm.pointConstraint(self.ik_ctl, self.ikHandleUpvRef) pm.parentConstraint(self.legChainUpvRef[0], self.ik_ctl, self.upv_cns, mo=True) # Visibilities ------------------------------------- # shape.dispGeometry # fk fkvis_node = node.createReverseNode(self.blend_att) for shp in self.fk0_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) for shp in self.fk1_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) for shp in self.fk2_ctl.getShapes(): pm.connectAttr(fkvis_node + ".outputX", shp.attr("visibility")) # ik for shp in self.upv_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ikcns_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.ik_ctl.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) for shp in self.line_ref.getShapes(): pm.connectAttr(self.blend_att, shp.attr("visibility")) # IK Solver ----------------------------------------- out = [self.bone0, self.bone1, self.ctrn_loc, self.eff_loc] o_node = applyop.gear_ikfk2bone_op(out, self.root_ctl, self.ik_ref, self.upv_ctl, self.fk_ctl[0], self.fk_ctl[1], self.fk_ref, self.length0, self.length1, self.negate) pm.connectAttr(self.blend_att, o_node + ".blend") if self.negate: mulVal = -1 else: mulVal = 1 node.createMulNode(self.roll_att, mulVal, o_node + ".roll") pm.connectAttr(self.scale_att, o_node + ".scaleA") pm.connectAttr(self.scale_att, o_node + ".scaleB") pm.connectAttr(self.maxstretch_att, o_node + ".maxstretch") pm.connectAttr(self.slide_att, o_node + ".slide") pm.connectAttr(self.softness_att, o_node + ".softness") pm.connectAttr(self.reverse_att, o_node + ".reverse") # Twist references --------------------------------- self.ikhArmRef, self.tmpCrv = applyop.splineIK( self.getName("legRollRef"), self.rollRef, parent=self.root, cParent=self.bone0) pm.pointConstraint(self.mid_ctl, self.tws1_loc, maintainOffset=False) pm.connectAttr(self.mid_ctl.scaleX, self.tws1_loc.scaleX) pm.connectAttr(self.mid_ctl.scaleX, self.tws1B_loc.scaleX) applyop.oriCns(self.mid_ctl, self.tws1_rot, maintainOffset=False) applyop.oriCns(self.mid_ctl, self.tws1B_rot, maintainOffset=False) if self.negate: axis = "xz" axisb = "-xz" else: axis = "-xz" axisb = "xz" applyop.aimCns(self.tws1_loc, self.root_ctl, axis=axis, wupType=4, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) applyop.aimCns(self.tws1B_loc, self.eff_loc, axis=axisb, wupType=4, wupVector=[0, 0, 1], wupObject=self.mid_ctl, maintainOffset=False) pm.pointConstraint(self.thick_ctl, self.tws1B_loc, maintainOffset=False) pm.pointConstraint(self.eff_loc, self.tws2_loc, maintainOffset=False) pm.scaleConstraint(self.eff_loc, self.tws2_loc, maintainOffset=False) applyop.oriCns(self.bone1, self.tws2_loc, maintainOffset=False) applyop.oriCns(self.tws_ref, self.tws2_rot) self.tws0_loc.setAttr("sx", .001) self.tws2_loc.setAttr("sx", .001) add_node = node.createAddNode(self.roundness_att, .001) pm.connectAttr(add_node + ".output", self.tws1_rot.attr("sx")) pm.connectAttr(add_node + ".output", self.tws1B_rot.attr("sx")) # Volume ------------------------------------------- distA_node = node.createDistNode(self.tws0_loc, self.tws1_loc) distB_node = node.createDistNode(self.tws1_loc, self.tws2_loc) add_node = node.createAddNode(distA_node + ".distance", distB_node + ".distance") div_node = node.createDivNode(add_node + ".output", self.root_ctl.attr("sx")) # comp scaling issue dm_node = pm.createNode("decomposeMatrix") pm.connectAttr(self.root.attr("worldMatrix"), dm_node + ".inputMatrix") div_node2 = node.createDivNode(div_node + ".outputX", dm_node + ".outputScaleX") self.volDriver_att = div_node2 + ".outputX" if self.settings["extraTweak"]: for tweak_ctl in self.tweak_ctl: for shp in tweak_ctl.getShapes(): pm.connectAttr(self.tweakVis_att, shp.attr("visibility")) # Divisions ---------------------------------------- # at 0 or 1 the division will follow exactly the rotation of the # controler.. and we wont have this nice tangent + roll b_twist = False for i, div_cns in enumerate(self.div_cns): subdiv = False if self.settings["supportJoints"]: if i == len(self.div_cns) - 1 or i == 0: subdiv = 45 else: subdiv = 10 if i < (self.settings["div0"] + 1): perc = i * .5 / (self.settings["div0"] + 1.0) elif i < (self.settings["div0"] + 2): perc = .49 subdiv = 45 elif i < (self.settings["div0"] + 3): perc = .50 subdiv = 45 elif i < (self.settings["div0"] + 4): b_twist = True perc = .51 subdiv = 45 else: perc = (.5 + (i - self.settings["div0"] - 3.0) * .5 / (self.settings["div1"] + 1.0)) else: subdiv = 40 if i < (self.settings["div0"] + 1): perc = i * .5 / (self.settings["div0"] + 1.0) elif i < (self.settings["div0"] + 2): b_twist = True perc = .501 else: perc = .5 + \ (i - self.settings["div0"] - 1.0) * .5 / \ (self.settings["div1"] + 1.0) perc = max(.001, min(.990, perc)) # mid twist distribution if b_twist: mid_twist = self.tws1B_rot else: mid_twist = self.tws1_rot # Roll if self.negate: o_node = applyop.gear_rollsplinekine_op( div_cns, [self.tws2_rot, mid_twist, self.tws0_rot], 1.0 - perc, subdiv) else: o_node = applyop.gear_rollsplinekine_op( div_cns, [self.tws0_rot, mid_twist, self.tws2_rot], perc, subdiv) pm.connectAttr(self.resample_att, o_node + ".resample") pm.connectAttr(self.absolute_att, o_node + ".absolute") # Squash n Stretch o_node = applyop.gear_squashstretch2_op( div_cns, None, pm.getAttr(self.volDriver_att), "x") pm.connectAttr(self.volume_att, o_node + ".blend") pm.connectAttr(self.volDriver_att, o_node + ".driver") pm.connectAttr(self.st_att[i], o_node + ".stretch") pm.connectAttr(self.sq_att[i], o_node + ".squash") # NOTE: next line fix the issue on meters. # This is special case becasuse the IK solver from mGear use # the scale as lenght and we have shear # TODO: check for a more clean and elegant solution instead of # re-match the world matrix again # transform.matchWorldTransform(self.fk_ctl[0], self.match_fk0_off) # transform.matchWorldTransform(self.fk_ctl[1], self.match_fk1_off) # transform.matchWorldTransform(self.fk_ctl[0], self.match_fk0) # transform.matchWorldTransform(self.fk_ctl[1], self.match_fk1) # match IK/FK ref pm.parentConstraint(self.bone0, self.match_fk0_off, mo=True) pm.parentConstraint(self.bone1, self.match_fk1_off, mo=True) # connect_reader pm.parentConstraint(self.bone0, self.readerA, mo=True) pm.parentConstraint(self.bone1, self.readerB, mo=True) # connect auto thickness if self.negate and not self.settings["mirrorMid"]: d_val = -180 / self.length1 else: d_val = 180 / self.length1 div_thick_node = node.createDivNode(self.knee_thickness_att, d_val) node.createMulNode(div_thick_node.outputX, self.readerB.rx, self.thick_lvl.tx) return
def RMCreateSpineIKSystem(self): self.spineIK, effector, self.spineCurve = pm.ikHandle( startJoint=self.spineJoints[0], endEffector=self.spineJoints[len(self.spineJoints) - 1], createCurve=True, numSpans=len(self.spineJoints), solver="ikSplineSolver", name="spineIK") self.NameConv.rename_based_on_base_name( self.spineJoints[len(self.spineJoints) - 1], self.spineIK) self.NameConv.rename_based_on_base_name( self.spineJoints[len(self.spineJoints) - 1], effector, name="spineIKEffector") self.NameConv.rename_based_on_base_name( self.spineJoints[len(self.spineJoints) - 1], self.spineCurve, name="spineIKCurve") Clusters = RMRigTools.RMCreateClustersOnCurve(self.spineCurve) ClustersGroup = RMRigTools.RMCreateGroupOnObj(Clusters[0]) RMRigTools.RMParentArray(ClustersGroup, Clusters[1:]) self.kinematics.append(ClustersGroup) self.kinematics.append(self.spineIK) #ResetCOG, COG = RMRigShapeControls.create_box_ctrl(self.spineJoints[0],Yratio=3,Zratio=3) ResetCOG, COG = RMRigShapeControls.RMImportMoveControl( self.spineJoints[0], scale=RMRigTools.RMLenghtOfBone(self.spineJoints[0]) * 7) self.NameConv.rename_set_from_name(COG, "COG", "name") ResetChest, Chest = RMRigShapeControls.RMCreateBoxCtrl( self.spineJoints[len(self.spineJoints) - 1], Yratio=3, Zratio=3) self.NameConv.rename_set_from_name(Chest, "Chest", "name") SpineLength = RMRigTools.RMPointDistance(COG, Chest) ResetChestRotation, ChestRotation = RMRigShapeControls.RMCircularControl( Chest, radius=SpineLength, name="ChestRotation") pm.parent(ResetChestRotation, Chest) pm.parentConstraint(ChestRotation, self.chestJoint, mo=True) self.ResetChestRotationControl = ResetChestRotation self.ChestRotationControl = ChestRotation #pm.parent(ResetChest,COG) pm.setAttr(self.spineIK + ".dTwistControlEnable", 1) pm.setAttr(self.spineIK + ".dWorldUpType", 4) #pm.setAttr(self.spineIK + ".dForwardAxis",0)#Valid Option only in Maya 2016 pm.setAttr(self.spineIK + ".dWorldUpAxis", 0) pm.connectAttr(COG + ".worldMatrix[0]", self.spineIK + ".dWorldUpMatrix") pm.connectAttr(Chest + ".worldMatrix[0]", self.spineIK + ".dWorldUpMatrixEnd") locators = RMRigTools.RMCreateNLocatorsBetweenObjects(COG, Chest, 3, align="FirstObj") ChestControls = [] ChestGroups = [] AllSpine = [COG] spineControlGroup = pm.group(empty=True, name="SpineControls") self.NameConv.rename_name_in_format(spineControlGroup, name=spineControlGroup) self.secondaryControls for eachPosition in locators: ControlGroup, NewControl = RMRigShapeControls.RMImportMoveControl( eachPosition, scale=SpineLength) self.secondaryControls.append(NewControl) ChestGroups.append(ControlGroup) ChestControls.append(NewControl) AllSpine.append(NewControl) ResetTransformGroup = RMRigTools.RMCreateGroupOnObj(ControlGroup) print ResetTransformGroup print spineControlGroup pm.parent(ResetTransformGroup, spineControlGroup) pm.delete(eachPosition) RMRigTools.RMLockAndHideAttributes(NewControl, "111000000h") AllSpine.append(Chest) pm.parent(spineControlGroup, COG) ChestChildGroup = RMRigTools.RMCreateGroupOnObj(Chest, Type="child", NameConv=self.NameConv) pm.xform(ChestChildGroup, t=[-SpineLength / 2, 0, 0], os=True, relative=True) spineEnds = [COG, ChestChildGroup] self.RMRedistributeConstraint(AllSpine, Clusters, 3, ConstraintType="parent") self.RMRedistributeConstraint(spineEnds, ChestGroups, 3, ConstraintType="parent") DeformedShape, OrigShape = pm.listRelatives(self.spineCurve, children=True, shapes=True) curveInfoOriginal = pm.shadingNode('curveInfo', asUtility=True, name="SpineCurveOriginalInfo") curveInfoDeformed = pm.shadingNode('curveInfo', asUtility=True, name="SpineCurveDeformedInfo") self.NameConv.rename_name_in_format(curveInfoOriginal, name=curveInfoOriginal) self.NameConv.rename_name_in_format(curveInfoDeformed, name=curveInfoDeformed) pm.connectAttr(OrigShape + ".worldSpace[0]", curveInfoOriginal + ".inputCurve") pm.connectAttr(DeformedShape + ".worldSpace[0]", curveInfoDeformed + ".inputCurve") curveScaleRatio = pm.shadingNode('multiplyDivide', asUtility=True, name="SpineScaleRatio") self.NameConv.rename_name_in_format(curveScaleRatio, name=curveScaleRatio) pm.connectAttr(curveInfoDeformed + ".arcLength", curveScaleRatio + ".input1X") pm.connectAttr(curveInfoOriginal + ".arcLength", curveScaleRatio + ".input2X") pm.setAttr(curveScaleRatio + ".operation", 2) #preparation for Scale multiplication function of each spine joint pm.addAttr(Chest, at="float", sn="ssf", ln="spineSquashFactor", hnv=1, hxv=1, h=0, k=1, smn=-10, smx=10) GaussLen = len(self.spineJoints) center = len(self.spineJoints) / 2 powMaxValue = 5 powRate = powMaxValue / center index = 1 for eachJoint in self.spineJoints[1:]: #translate stretch multiplication functions of each spine joint SpineStretchMult = pm.shadingNode( 'multiplyDivide', asUtility=True, name="SpineTranslateStretchMult" + self.NameConv.get_a_short_name(eachJoint)) self.NameConv.rename_name_in_format(SpineStretchMult, name=SpineStretchMult) CurrentXPosition = pm.getAttr(eachJoint + ".translateX") pm.setAttr(SpineStretchMult + ".input2X", CurrentXPosition) pm.connectAttr(curveScaleRatio + ".outputX", SpineStretchMult + ".input1X") pm.connectAttr(SpineStretchMult + ".outputX", eachJoint + ".translateX") #Scale multiplication function of each spine joint if index >= center: PowValue = (GaussLen - 1 - index) else: PowValue = index SpineStretchRatio = pm.shadingNode( 'multiplyDivide', asUtility=True, name="SpineStretchRatio" + self.NameConv.get_a_short_name(eachJoint)) self.NameConv.rename_name_in_format(SpineStretchRatio, name=SpineStretchRatio) pm.connectAttr(Chest + ".spineSquashFactor ", SpineStretchRatio + ".input1X") pm.setAttr(SpineStretchRatio + ".input2X", PowValue) pm.setAttr(SpineStretchRatio + ".operation", 1) SpineScaleStretchPow = pm.shadingNode( 'multiplyDivide', asUtility=True, name="SpineScaleStretchPow" + self.NameConv.get_a_short_name(eachJoint)) self.NameConv.rename_name_in_format(SpineScaleStretchPow, name=SpineScaleStretchPow) pm.connectAttr(curveScaleRatio + ".outputX ", SpineScaleStretchPow + ".input1X") pm.connectAttr(SpineStretchRatio + ".outputX ", SpineScaleStretchPow + ".input2X") pm.setAttr(SpineScaleStretchPow + ".operation", 3) SpineInversScaleRatio = pm.shadingNode( 'multiplyDivide', asUtility=True, name="SpineInverseScaleRatio") self.NameConv.rename_name_in_format(SpineInversScaleRatio, name=SpineInversScaleRatio) pm.connectAttr(SpineScaleStretchPow + ".outputX ", SpineInversScaleRatio + ".input1X") pm.setAttr(SpineInversScaleRatio + ".input2X", -1) pm.setAttr(SpineInversScaleRatio + ".operation", 3) pm.connectAttr(SpineInversScaleRatio + ".outputX", eachJoint + ".scaleY") pm.connectAttr(SpineInversScaleRatio + ".outputX", eachJoint + ".scaleZ") index += 1 resetWaist, waist = RMRigShapeControls.RMCircularControl( AllSpine[1], radius=SpineLength * .8, name="waist") pm.parent(ResetChest, waist) pm.parent(resetWaist, COG) self.chestControl = Chest self.resetChestControl = ResetChest self.waistControl = waist self.resetWaistControl = resetWaist self.COG = COG self.ResetCOG = ResetCOG self.SpineLength = SpineLength
def createAdjustmentRig(self, driver, attr): """ creates a temp control rig for the specified driver/control and attr on that controller each transform node at the end of that is driven """ if len(self.tempControls) > 0: print "temp list is occupied..." return None self.tempControls = [] drvn = pm.listConnections("{0}.{1}".format(str(driver), str(attr)), s=0, d=1, p=1) srcAttr = attr animCurves = [] nodes = {} misc = [] for x in drvn: test = pm.PyNode(str(x).split(".")[0]) if isinstance(test, pm.nodetypes.AnimCurve): animCurves.append(test) else: buf = self.trackDag(test, pm.nodetypes.AnimCurve) animCurves.append() if len(misc) > 0: print "do dag tracking here" print misc for anim in animCurves: outs = pm.listConnections("{0}.output".format(str(anim)), s=0, d=1, p=1) for x in outs: test = pm.PyNode(str(x).split(".")[0]) node = self.trackDag(test, pm.nodetypes.Transform) if node: attr = node[1] node = node[0] if node in nodes.keys(): nodes[str(node)].append((attr, anim)) else: nodes[str(node)] = [(attr, anim)] for x in nodes.keys(): node = pm.PyNode(x) animCurves = nodes[x] child = node.getChildren() if len(child) > 0: name = str(child[0]) else: name = "TEMP_{0}".format(str(node)) crv = pm.curve(d=1, p=[(0.5, 0, 0.5), (0.5, 0, -0.5), (0, 0.5, 0), (0.5, 0, 0.5), (0, -0.5, 0), (-0.5, 0, 0.5), (0.5, 0, 0.5), (0, 0.5, 0), (-0.5, 0, 0.5), (-0.5, 0, -0.5), (0, -0.5, 0), (0.5, 0, -0.5), (-0.5, 0, -0.5), (0, 0.5, 0)], k=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]) crv.rename(name + "_TEMP") crv.addAttr("driverAttribute", dt="string") crv.driverAttribute.set("{0}.{1}".format(str(driver), srcAttr)) for y in animCurves: attr = y[0] y = y[1] crv.addAttr("{0}___{1}".format(str(y), attr), at="message") y.connectAttr("message", "{0}.{1}___{2}".format(str(crv), str(y), attr), f=1) grp = pm.createNode("transform", n=str(crv).replace("_TEMP", "_TEMPGROUP")) crv.addAttr("driven", at="message") pm.parent(crv, grp) child[0].connectAttr("message", "{0}.driven".format(str(crv)), f=1) p = pm.datatypes.Vector(pm.xform(node, q=1, ws=1, t=1)) r = pm.datatypes.Vector(pm.xform(node, q=1, ws=1, ro=1)) #pm.xform(crv,ws=1,t=p,ro=r) par = pm.parentConstraint(child, grp) pm.delete(par) self.tempControls.append(crv) if len(child) > 0: pm.parentConstraint(crv, child)
def ConstrainJoint2Loc(self): self.Constraint = pm.parentConstraint(self.Loc, self.Joint)
def RMCreateClavicleSystem(self, rootClavicle, ClavicleJoints): resetClavicleControl, clavicleControl = RMRigShapeControls.RMCreateBoxCtrl( ClavicleJoints[0]) pm.parent(resetClavicleControl, self.ChestRotationControl) pm.parentConstraint(clavicleControl, ClavicleJoints[0]) return resetClavicleControl, clavicleControl