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 circle(self, joint): a = 0.25 b = 0.3432 p0 = Point(a + 0.005,0 , -a - 0.005) p1 = Point(b + 0.05, 0, 0) p2 = Point(a + 0.005, 0, a + 0.005) p3 = Point(0, 0, b) p4 = Point(-a - 0.005, 0, a + 0.005) p5 = Point(-b - 0.05, 0, 0) p6 = Point(-a - 0.005, 0, -a - 0.005) p7 = Point(0, 0, - b) points = [p0, p1, p2, p3, p4, p5, p6, p7, p0, p1, p2] pts = [] for point in points: pts.append(point.getPoint()) pm.curve(per = True, d = 3, p = pts, k = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) pm.parent("%s" % str(pm.ls(sl = True)[0]), "%s" % str(joint), relative = True) pm.parent("%s" % str(pm.ls(sl = True)[0]), world = True) pm.makeIdentity(r = True) curve = "%s" % str(pm.ls(sl = True)[0]) g = 0 while g < 8: pm.moveVertexAlongDirection(curve + ".cv[" + str(g) + "]", d = [0,1,0], m = -0.08) g += 1 group = pm.group(curve) pm.orientConstraint(curve, joint, mo = True) handle = joint + "IK" pm.pointConstraint(curve, handle, mo = True)
def LinkBindNode(self): ''' Make the actual driving connections between the Bind and Destination Nodes ''' maintainOffsets = False # Make the Bind Between the Object # if BindTrans and BindRots: # try: # con=pm.parentConstraint(self.BindNode['Main'], self.DestinationNode, mo=maintainOffsets) # con.interpType.set(2) # except: # raise StandardError('ParentConstraint Bind could not be made') if self.Settings.BindTrans: try: pm.pointConstraint(self.BindNode['Main'], self.DestinationNode, mo=maintainOffsets) except: pass if self.Settings.BindRots: try: con = pm.orientConstraint(self.BindNode['Main'], self.DestinationNode, mo=maintainOffsets) con.interpType.set(2) except: pass #Add the BindMarkers so that we can ID these nodes and connections later self.AddBindMarkers(self.DestinationNode, self.BindNode['Root'])
def create(self): pointA = self.startObj pointB = self.endObj position = (0,0,0) # 커브 생성 crv = pm.curve( d=1, p=[ position, position ], k=[0,1] ) self.curve = crv.getShape() # obj에 커브 쉐입을 종속 시킴 : 커브를 선택해도 오브젝트를 선택한 효과를 줌. pm.parent( self.curve, pointA, r=True, s=True) pm.delete( crv ) # target에 locator를 종속 시킴 self.locator = pm.pointCurveConstraint( self.curve+'.ep[1]', ch=True)[0] self.locator = pm.PyNode(self.locator) pm.pointConstraint( pointB, self.locator ) # 로케이서 속성 조정 self.locator.getShape().localPosition.set(0,0,0) #이 로케이터는 보이지 않음 self.locator.getShape().v.set(False) #이 로케이터는 보이지 않음 self.locator.v.set(False) #이 로케이터는 보이지 않음 self.locator.setParent(pointA) self.locator.rename( pointB+'_CONNLOC' ) # 커브쉐입에 어트리뷰트 추가 self.curve.addAttr( 'curveConnectedTo', at='message' ) self.curve.addAttr( 'curveConnectedLOC', at='message' ) # 어트리뷰트 연결 pointB.message >> self.curve.curveConnectedTo self.locator.message >> self.curve.curveConnectedLOC
def make_stabilized_node(nodeName=None, centered=True): ''' Very simple proc to generate a Stabilized node for raw MoCap tracking purposes... First selected node is used as the Aim axis, second selected is used as this aim's worldUp ''' RequiredMarkers = pm.ls(sl=True, l=True) #pos = pm.xform(WorldUpObj, q=True, ws=True, t=True) curve = pm.curve(ws=True, d=1, p=(0, 0, 0), k=0) if centered: AimAt = RequiredMarkers[0] WorldUpObj = RequiredMarkers[1] pm.pointConstraint(RequiredMarkers, curve) else: AimAt = RequiredMarkers[1] WorldUpObj = RequiredMarkers[2] pm.pointConstraint(RequiredMarkers[0], curve) pm.aimConstraint((AimAt, curve), weight=1, aimVector=(0, 0, 1), upVector=(0, 1, 0), worldUpType="object", worldUpObject=WorldUpObj) #Snap a curveKnot to the pivot of all referenceMarkers for node in RequiredMarkers: pm.curve(curve, a=True, ws=True, p=(pm.xform(node, q=True, ws=True, t=True))) pm.curve(curve, a=True, ws=True, p=(pm.xform(AimAt, q=True, ws=True, t=True))) return curve
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 autoPoleVector( baseJnt=None, endJnt=None, side='L' ): baseJntPos = pm.xform( baseJnt, q=True, t=True, ws=True ) endJntPos = pm.xform( endJnt, q=True, t=True, ws=True ) pm.select(clear=True) poleVectorJnt_one = pm.joint( p=baseJntPos ) poleVectorJnt_two = pm.joint( p=endJntPos ) poleVectorIKstuff = pm.ikHandle( sj = poleVectorJnt_one, ee = poleVectorJnt_two, solver = "ikSCsolver" ) pv = pm.spaceLocator() pv.setParent( poleVectorJnt_two ) pv.translate.set( 0,0,0 ) pvZeros = ZeroGrp( pv ) pm.pointConstraint( poleVectorIKstuff[0], pvZeros[0] ) if side=='L': pv.translateX.set( 1 ) elif side=='R': pv.translateX.set( -1 ) pvZeros[0].setParent( poleVectorJnt_two ) return ( pv, poleVectorIKstuff, (poleVectorJnt_one, poleVectorJnt_two) )
def addSurfaceConstraintToBnd(bnd, surface): ''' ''' secDrv = bnd.getParent() matrix = secDrv.getMatrix(worldSpace=True) # create additional nulls gc = pm.group(em=True, n=bnd.nodeName().replace('_bnd', '_gc')) gc_offset = pm.group(em=True, n=bnd.nodeName().replace('_bnd', '_gc_offset')) acs = pm.group(em=True, n=bnd.nodeName().replace('_bnd', '_acs')) # point constraint first to get precise position to secDrv pm.pointConstraint(secDrv, gc) # geometry constraint to surface pm.geometryConstraint(surface, gc) # normal constraint, using secDrv-Y as up pm.normalConstraint(surface, gc, aim=(0,0,1), u=(0,1,0), wuo=secDrv, wut='objectrotation', wu=(0,1,0)) # ensure that gc_offset stores offset to secDrv gc_offset.setMatrix(matrix, worldSpace=True) acs.setMatrix(matrix, worldSpace=True) # hierarchy secDrv | gc | gc_offset | acs | bnd
def AlignBindNode(self, **kws): ''' Overwrite the default behaviour: Align the newly made BindNode as required for this bind ''' parentNode = self.SourceNode.listRelatives(p=True)[0] if parentNode: #Parent the BindNode to the Source Driver Node pm.parent(self.BindNode['Root'], self.SourceNode.listRelatives(p=True)[0]) else: pm.parent(self.BindNode['Root'], self.SourceNode) self.BindNode['Main'].rotateOrder.set(self.SourceNode.rotateOrder.get()) self.BindNode['Root'].rotateOrder.set(self.DestinationNode.rotateOrder.get()) #Positional Alignment if self.Settings.AlignToControlTrans: pm.delete(pm.pointConstraint(self.SourceNode, self.BindNode['Root'])) pm.makeIdentity(self.BindNode['Root'], apply=True, t=1, r=0, s=0) pm.delete(pm.pointConstraint(self.DestinationNode, self.BindNode['Root'])) if self.Settings.AlignToSourceTrans: pm.delete(pm.pointConstraint(self.SourceNode, self.BindNode['Root'])) pm.makeIdentity(self.BindNode['Root'], apply=True, t=1, r=0, s=0) #Rotation Alignment if parentNode: pm.orientConstraint(self.SourceNode, self.BindNode['Root']) if self.Settings.AlignToControlRots: pm.delete(pm.orientConstraint(self.DestinationNode, self.BindNode['Main'])) if self.Settings.AlignToSourceRots: pm.delete(pm.orientConstraint(self.SourceNode, self.BindNode['Main']))
def build(self, refs=None, line_target=True, *args, **kwargs): """ Will create the ctrl node and it's line target if needed :param refs: The reference used to attach the line target :param line_target: Bool to tell if we want a line target :param args: More args passed to the super class :param kwargs: More kwargs passed to the super class :return: """ super(CtrlIkSwivel, self).build(*args, **kwargs) assert (self.node is not None) ref = next(iter(refs), None) if isinstance(refs, collections.Iterable) else refs # Create line if line_target is True and ref is not None: # Create a spaceLocator so the annotation can hook itself to it. self._line_locator = pymel.spaceLocator() locator_shape = self._line_locator.getShape() pymel.pointConstraint(ref, self._line_locator) self._line_locator.setParent(self.node) self._line_locator.hide() self._line_annotation = pymel.createNode('annotationShape') annotation_transform = self._line_annotation.getParent() self._line_annotation.setParent(self.node, relative=True, shape=True) pymel.connectAttr(locator_shape.worldMatrix, self._line_annotation.dagObjectMatrix[0], force=True) pymel.delete(annotation_transform) return self.node
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 makeNull(): #pm.melGlobals.initVar( 'string[]', 'KinectSkelNames' ) i=0 for i in range(0,24): pm.spaceLocator(p=(0, 0, 0),n=KinectSkelNames[i]) pm.spaceLocator(p=(0, 0, 0),n="KINECT_HAND") for i in range(0,15): point[i] = [0.0,0.0,0.0] makeSkel() for i in range(0,15): pm.rename('joint'+str(i+1), KinectSkelJoints[i]+'_jt') for i in range(0,15): pm.pointConstraint( KinectSkelJoints[i], KinectSkelJoints[i]+'_jt' ) pm.orientConstraint( KinectSkelJoints[i], KinectSkelJoints[i]+'_jt' ) #Create Camera cam = pm.camera()[1] #print pm.camera(cam, query=True, aspectRatio=True) cam.setAspectRatio(3) print cam.getAspectRatio()
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 AlignBindNode(self, **kws): ''' Overwrite the default behaviour: Align the newly made BindNode as required for this bind ''' #Parent the BindNode/UpVector Object to the upVectorParent Node #Parent the AimLocator Object to the Source node -used to modify the AimPoint pm.parent(self.BindNode['Root'], self.upVectorParent) pm.parent(self.BindNode['Up'], self.upVectorParent) pm.parent(self.BindNode['AimOffset'], self.SourceNode) #self.BindNode['Root'].scale.set(self.Settings.BaseScale,self.Settings.BaseScale,self.Settings.BaseScale) self.BindNode['Main'].rotateOrder.set(self.SourceNode.rotateOrder.get()) self.BindNode['Root'].rotateOrder.set(self.DestinationNode.rotateOrder.get()) #Aim Alignment pm.aimConstraint(self.BindNode['AimOffset'], self.BindNode['Root'], aimVector=(0,1,0),upVector=(0,0,1),\ worldUpType="object",worldUpObject=self.BindNode['Up']) #Positional Alignment pm.delete(pm.pointConstraint(self.SourceNode, self.BindNode['AimOffset'])) pm.makeIdentity(self.BindNode['AimOffset'], apply=True, t=1, r=1, s=0) pm.delete(pm.pointConstraint(self.upVectorParent, self.BindNode['Root'])) pm.makeIdentity(self.BindNode['Root'], apply=True, t=1, r=0, s=0) pm.delete(pm.pointConstraint(self.upVectorParent, self.BindNode['Up'])) pm.makeIdentity(self.BindNode['Up'], apply=True, t=1, r=0, s=0) pm.delete(pm.pointConstraint(self.DestinationNode, self.BindNode['Root'])) #Rotate Alignment pm.delete(pm.orientConstraint(self.DestinationNode, self.BindNode['Main']))
def createStickyControl(position, geo, name): """ Create sticky control for a transform @param geo: @return: """ # Create space locator class ctrl(): def __init__(self, name): self.ctrl = pm.spaceLocator(name=name) self.xtra = libUtilities.parZero(self.ctrl, "Xtra") self.prnt = libUtilities.parZero(self.xtra, "Prnt") self.prnt.rename(name + "_Prnt") self.ctrl.rename(name + "_Ctrl") # Create the ctrl obj newLoc = ctrl(name) newLoc.prnt.translate.set(position) # Create the follice and point contraint follicle = createFollicle(position, geo) follicle.rename(name + "_fol") pm.pointConstraint(follicle, newLoc.prnt) # Create a translate cycle md = pm.createNode("multiplyDivide", name=name + "_MD") md.input2.set([-1, -1, -1]) newLoc.ctrl.translate >> md.input1 md.output >> newLoc.xtra.translate return newLoc, follicle
def rigCurveConnect( *objs, **kwargs ): ''' update : 2015-04-15 ''' if objs: pm.select(objs) sel = pm.selected( type='transform') if not sel: raise obj = sel[0] # 삭제 delete = kwargs.get('delete', False) if delete: for crvShp in obj.getShapes(): if crvShp.hasAttr('curveConnectedLOC'): try: pm.delete( crvShp, crvShp.curveConnectedLOC.inputs() ) except: pass return True # 타겟 가져옴. target = sel[1] name = kwargs.get('name') or kwargs.get('n', target+'_CONNCRV' ) position = kwargs.get('position') or kwargs.get('p', (0,0,0) ) # 커브 생성 crvTrans = pm.curve( n=name, d=1, p=[ position, position ], k=[0,1] ) crvShape = crvTrans.getShape() # obj에 커브 쉐입을 종속 시킴 : 커브를 선택해도 오브젝트를 선택한 효과를 줌. pm.parent( crvShape, obj, r=True, s=True) pm.delete( crvTrans ) # target에 locator를 종속 시킴 loc = pm.pointCurveConstraint( crvShape+'.ep[1]', ch=True)[0] loc = pm.PyNode(loc) pm.pointConstraint( target, loc ) # 로케이서 속성 조정 loc.getShape().localPosition.set(0,0,0) loc.getShape().v.set(False) loc.v.set(False) loc.setParent(obj) loc.rename( target+'_CONNLOC' ) # 커브쉐입에 어트리뷰트 추가 crvShape.addAttr( 'curveConnectedTo', at='message' ) crvShape.addAttr( 'curveConnectedLOC', at='message' ) # 어트리뷰트 연결 target.message >> crvShape.curveConnectedTo loc. message >> crvShape.curveConnectedLOC return loc
def create_sticky_control(geo, position, name, setup_type="follicle", free_rotation=True): """ Temp setup to create sticky control at position for given geometry @param setup_type: @param position (vector) The position in worldspace where this will created @param geo (pynode) The target geometry @param name (string) The prefix identifier given to this setup @param free_rotation (bool) Whether the rotation are free @return: A dict of control object and object which is constraining. TODO: """ # Create space locator geo = libUtilities.force_pynode(geo) # Create the ctrl obj new_ctrl = libUtilities.Ctrl(name) tempCtrlShape = utils.buildCtrlShape("Spike") libUtilities.transfer_shape(tempCtrlShape, new_ctrl.ctrl,True) libUtilities.fix_shape_name(new_ctrl.ctrl) pm.delete(tempCtrlShape) info = {"ctrl": new_ctrl} if setup_type == "follicle": new_ctrl.prnt.translate.set(position) # Create the follice and point constraint follicle = create_follicle(position, geo) follicle.rename("{}_fol".format(name)) if free_rotation: pm.pointConstraint(follicle, new_ctrl.prnt) else: pm.parentConstraint(follicle, new_ctrl.prnt) # Create a translate cycle info["sticky_source"] = follicle md = pm.createNode("multiplyDivide", name=name + "_MD") md.input2.set([-1, -1, -1]) new_ctrl.ctrl.translate >> md.input1 md.output >> new_ctrl.xtra.translate info["multiplyDivide"] = md else: new_info = create_point_on_mesh(geo, position, new_ctrl.prnt, free_rotation) info.update(new_info) if free_rotation: libUtilities.cheap_point_constraint(new_info["locator"], new_ctrl.prnt) else: pm.parentConstraint(new_info["locator"], new_ctrl.prnt) new_info["locator"].rename("{}_loc".format(name)) new_info["constraint"].rename("{}_popCon".format(name)) return info
def constraintRigJnt(self): for i in range(self.numJnt): cnstr = pm.pointConstraint(self.ikJntList[i],self.rigJntList[i],mo=1,weight=1) cnstr = pm.pointConstraint(self.flcTransformList[i],self.rigJntList[i],mo=1,weight=0) ikWeight,flcWeight = pm.pointConstraint(cnstr, query=True, weightAliasList=True) self.stretchRev.outputX >> ikWeight self.mainCtrl.stretch >> flcWeight
def curveAimBelt(module, crv, aimCrv, numJnts, mo=True, aimVector=(0,1,0), upVector=(0,1,0), worldUpType="vector", worldUpVector=(0,1,0)): '''Takes two curves, creates joints on the first and aims objects at the second. Args: crv (pm.nt.nurbsCurve): nurbs curve to generate things on aimCrv (pm.nt.nurbsCurve): nurbs curve to aim things to numJnts (int): number of joints to be generated other : all of the aim vector constraint settings Returns list(grp, list(joints)) Usage: curveAimBelt("path", pm.ls(sl=True)[0], pm.ls(sl=True)[1], 40) ''' grp = pm.group(em=True, n=module+'_GRP') aimgrp = pm.group(em=True, n=module+'_AIMDRV_GRP', p=grp) joints = rig_makeJointsAlongCurve(module+"Drive", crv, numJnts) ikJoints = rig_makeJointsAlongCurve(module+"IK", crv, numJnts) skelgrp = pm.group(em=True, n=module+'Skeleton_GRP', p=grp) ikskelgrp = pm.group(em=True, n=module+'ikJNT_GRP', p=skelgrp) jntgrp = pm.group(em=True, n=module+'JNT_GRP', p=skelgrp) clstrGrp = pm.group(em=True, n=module+'Clusters_GRP', p=grp) crvGrp = pm.group(em=True, n=module+'Curves_GRP', p=grp) for joint,ikJoint in zip(joints,ikJoints): joint.setParent(jntgrp) pociResult = rig_getClosestPointAndPositionOnCurve(joint, crv) pociResult[2].setParent(aimgrp) pociOrig = pociResult[0] poci = pm.nodetypes.PointOnCurveInfo(n=joint+"_POCI") aimCrv.getShape().attr("worldSpace[0]").connect(poci.inputCurve) pociOrig.parameter.connect(poci.parameter) loc = pm.spaceLocator( n=joint+'AIMDRV_GRP' ) loc.setParent(aimgrp) poci.position.connect(loc.t) pm.pointConstraint(ikJoint, joint, mo=True) pm.aimConstraint(loc, joint, mo=mo, aimVector=aimVector, upVector=upVector, worldUpType=worldUpType, worldUpVector=worldUpVector) ikHandle=pm.ikHandle(sj=ikJoints[0], ee=ikJoints[-1], sol='ikSplineSolver', c=crv, ccv=False, rtm=False)[0] origClusters = rig_clusterCurve(crv, ends=True) offsetClusters = rig_clusterCurve(aimCrv, ends=True) for clstr, oClstr in zip(origClusters, offsetClusters): pm.parentConstraint(clstr[1], oClstr[1], mo=True) oClstr[1].visibility.set(0) clstr[1].setParent(clstrGrp) oClstr[1].setParent(clstrGrp) ikJoints[0].setParent(ikskelgrp) ikskelgrp.visibility.set(0) crvGrp.visibility.set(0) crv.setParent(crvGrp) aimCrv.setParent(crvGrp) ikHandle.setParent(ikskelgrp) aimgrp.inheritsTransform.set(0) return [grp, joints]
def rope_connect(): pm.pointConstraint(sel[0], 'M_start_CTRL' ) pm.pointConstraint(sel[1], 'M_end_CTRL' ) pm.pointConstraint(sel[2], 'M_mid_A_CTRL' ) pm.pointConstraint(sel[3], 'M_mid_CTRL' ) pm.pointConstraint(sel[4], 'M_mid_B_CTRL' ) for obj in sel: cns_connections = pm.listConnections (type = 'constraint') pm.delete(cns_connections)
def buildShoulderNoRoll(self): ''' Setup no roll shoulder. Assumes Elbow is child of Shoulder. ''' self.logger.info('buildShoulderNoRoll(): Starting...') # Get the shoulder / elbow / wrist joint shldrJ = str(self.ui.shldrJointLineEdit.text()) elbowJ = str(self.ui.elbowJointLineEdit.text()) wristJ = str(self.ui.wristJointLineEdit.text()) parentJ = str(self.ui.jointChainLineEdit.text()) # Get as PyNodes pm.select(elbowJ,r=1) elbowJ = pm.ls(sl=1)[0] pm.select(shldrJ,r=1) shldrJ = pm.ls(sl=1)[0] pm.select(wristJ,r=1) wristJ = pm.ls(sl=1)[0] #--- No roll rig nfShldr = self.noRollRig( startJnt=shldrJ ) # Get the nfWrist joint for each in pm.listRelatives( nfShldr, children=1 ): if each.type() == 'joint': nfWrist = each self.logger.info('buildShoulderNoRoll(): Selected noroll wrist: %s'%nfWrist) break #--- Create the spline joint chain numJoints = self.ui.clavJointLcdNumber.value() startJ, endJ = self.createJoints( startJnt=shldrJ, endJnt=elbowJ, numJoints=numJoints ) #--- Setup the Ik Spline with Advanced Twist ikHandle, ikCurve = self.advancedSplineIK( startJ=startJ, endJ=endJ, start=shldrJ, nfStart=nfShldr ) pm.parentConstraint(shldrJ, ikCurve, mo=True) #--- Create twist result joint twistJnt = self.createTwistJnt(jnt=elbowJ, nfJnt=nfShldr, ikHandle=ikHandle) #--- Create rig grp grp = pm.group(em=True, name='%s_noroll_grp'%shldrJ) pm.delete(pm.parentConstraint(shldrJ, grp, mo=False)) pm.parent(nfShldr, grp) pm.parent(ikHandle, grp) pm.parent(ikCurve, grp) clavJ = pm.listRelatives(shldrJ, parent=True) pm.parentConstraint(clavJ, grp, mo=True) pm.pointConstraint(shldrJ,nfShldr,mo=True) pm.parent(startJ, parentJ) self.logger.info('buildShoulderNoRoll(): End.')
def constraint(self, parent, start, end ): # 축을 start에 먼저 맞추고, # 축을 유지한 채로 컨스트레인 검. pm.delete( pm.parentConstraint(start, self.constMe_to_start) ) pm.parentConstraint(parent, self.constMe_to_parent, mo=True) pm.pointConstraint(start, self.constMe_to_start) pm.parentConstraint(end, self.constMe_to_end) pm.delete( pm.pointConstraint(self.mid_T_anim, self.start_T_anim, self.mid1_T_anim) ) pm.delete( pm.pointConstraint(self.mid_T_anim, self.end_T_anim, self.mid2_T_anim) )
def create_control(node, name='', shape="", axis="", size=1, point=True, orient=True, scale=False, help=False): node = pm.PyNode(node) if not shape: shape = "circle" if not name: name = "%s_ctrl" %node.name() shapeMELs = { "circle" : "circle -c 0 0 0 -nr 0 1 0 -sw 360 -r 0.5 -d 3 -ut 0 -s 8 -ch 0", "diamond" : "circle -c 0 0 0 -nr 0 1 0 -sw 360 -r 0.5 -d 1 -ut 0 -s 4 -ch 0", "square" : "curve -d 1 -p -0.5 0 0.5 -p -0.5 0 -0.5 -p 0.5 0 -0.5 -p 0.5 0 0.5 -p -0.5 0 0.5 -k 0 -k 1 -k 2 -k 3 -k 4", "global" : "curve -d 3 -p 0 0 0.75 -p 0.25 0 0.5 -p 0.25 0 0.5 -p 0.25 0 0.5 -p 0.375 0 0.5 -p 0.5 0 0.5 -p 0.5 0 0.375 -p 0.5 0 -0.375 -p 0.5 0 -0.5 -p 0.375 0 -0.5 -p -0.375 0 -0.5 -p -0.5 0 -0.5 -p -0.5 0 -0.375 -p -0.5 0 0.375 -p -0.5 0 0.5 -p -0.375 0 0.5 -p -0.25 0 0.5 -p -0.25 0 0.5 -p -0.25 0 0.5 -p 0 0 0.75 -k 0 -k 0 -k 0 -k 1 -k 2 -k 3 -k 4 -k 5 -k 6 -k 7 -k 8 -k 9 -k 10 -k 11 -k 12 -k 13 -k 14 -k 15 -k 16 -k 17 -k 17 -k 17", "local" : "curve -d 3 -p 0 0 0.5 -p 0.125 0 0.375 -p 0.125 0 0.375 -p 0.125 0 0.375 -p 0.25 0 0.375 -p 0.375 0 0.375 -p 0.375 0 0.25 -p 0.375 0 -0.25 -p 0.375 0 -0.375 -p 0.25 0 -0.375 -p -0.25 0 -0.375 -p -0.375 0 -0.375 -p -0.375 0 -0.25 -p -0.375 0 0.25 -p -0.375 0 0.375 -p -0.25 0 0.375 -p -0.125 0 0.375 -p -0.125 0 0.375 -p -0.125 0 0.375 -p 0 0 0.5 -k 0 -k 0 -k 0 -k 1 -k 2 -k 3 -k 4 -k 5 -k 6 -k 7 -k 8 -k 9 -k 10 -k 11 -k 12 -k 13 -k 14 -k 15 -k 16 -k 17 -k 17 -k 17", "root" : "curve -d 1 -p 0 0 0.325 -p -0.0634045 0 0.318755 -p -0.124372 0 0.300261 -p -0.180561 0 0.270228 -p -0.22981 0 0.22981 -p -0.270228 0 0.180561 -p -0.300261 0 0.124372 -p -0.318755 0 0.0634045 -p -0.325 0 0 -p -0.318755 0 -0.0634045 -p -0.300261 0 -0.124372 -p -0.270228 0 -0.180561 -p -0.22981 0 -0.22981 -p -0.180561 0 -0.270228 -p -0.124372 0 -0.300261 -p -0.0634045 0 -0.318755 -p 0 0 -0.325 -p 0.0634045 0 -0.318755 -p 0.124372 0 -0.300261 -p 0.180561 0 -0.270228 -p 0.22981 0 -0.22981 -p 0.270228 0 -0.180561 -p 0.300261 0 -0.124372 -p 0.318755 0 -0.0634045 -p 0.325 0 0 -p 0.318755 0 0.0634045 -p 0.300261 0 0.124372 -p 0.270228 0 0.180561 -p 0.22981 0 0.22981 -p 0.180561 0 0.270228 -p 0.124372 0 0.300261 -p 0.0634045 0 0.318755 -p 0 0 0.325 -p 0 0 -0.325 -p 0 0 -0.25 -p -0.0487726 0 -0.245197 -p -0.095671 0 -0.23097 -p -0.138893 0 -0.207868 -p -0.176777 0 -0.176777 -p -0.207868 0 -0.138893 -p -0.23097 0 -0.095671 -p -0.245197 0 -0.0487726 -p -0.25 0 0 -p -0.325 0 0 -p 0.325 0 0 -p -0.25 0 0 -p -0.245197 0 0.0487726 -p -0.23097 0 0.095671 -p -0.207868 0 0.138893 -p -0.176777 0 0.176777 -p -0.138893 0 0.207868 -p -0.095671 0 0.23097 -p -0.0487726 0 0.245197 -p 0 0 0.25 -p 0.0487726 0 0.245197 -p 0.095671 0 0.23097 -p 0.138893 0 0.207868 -p 0.176777 0 0.176777 -p 0.207868 0 0.138893 -p 0.23097 0 0.095671 -p 0.245197 0 0.0487726 -p 0.25 0 0 -p 0.245197 0 -0.0487726 -p 0.23097 0 -0.095671 -p 0.207868 0 -0.138893 -p 0.176777 0 -0.176777 -p 0.138893 0 -0.207868 -p 0.095671 0 -0.23097 -p 0.0487726 0 -0.245197 -p 0 0 -0.25 -k 0 -k 1 -k 2 -k 3 -k 4 -k 5 -k 6 -k 7 -k 8 -k 9 -k 10 -k 11 -k 12 -k 13 -k 14 -k 15 -k 16 -k 17 -k 18 -k 19 -k 20 -k 21 -k 22 -k 23 -k 24 -k 25 -k 26 -k 27 -k 28 -k 29 -k 30 -k 31 -k 32 -k 33 -k 34 -k 35 -k 36 -k 37 -k 38 -k 39 -k 40 -k 41 -k 42 -k 43 -k 44 -k 45 -k 46 -k 47 -k 48 -k 49 -k 50 -k 51 -k 52 -k 53 -k 54 -k 55 -k 56 -k 57 -k 58 -k 59 -k 60 -k 61 -k 62 -k 63 -k 64 -k 65 -k 66 -k 67 -k 68 -k 69", } if help: print "################################" print "- Available Control Shape List -" for key in shapeMELs: print key print "################################" return shapeMEL = "%s -n %s" % (shapeMELs[shape], name) rotations = {'x' : [90, 0 , 0], '-x' : [-90, 0 , 0], 'y' : [0, 90, 0], '-y' : [0, -90, 0], 'z' : [0, 0, 90], '-z' : [0, 0, -90], } try: pm.mel.eval(shapeMEL) ctrl = pm.PyNode(name) ctrl.scale.set(size, size, size) if axis: ctrl.rotate.set(rotations[axis]) pm.makeIdentity(ctrl, apply=True, t=True, r=True, s=True) pm.delete(pm.parentConstraint(node, ctrl, mo=False)) if point : pm.pointConstraint(ctrl, node, mo=True, name="%s_tConst"%node.name()) if orient : pm.orientConstraint(ctrl, node, mo=True, name="%s_rConst"%node.name()) if scale : pm.scaleConstraint(ctrl, node, mo=True, name="%s_sConst"%node.name()) return ctrl except Exception as e: pm.warning("error while creating control %s" %e)
def __finalizeIkChain(self): ''' Create the ikHandle and the constraints to the control ''' #create ikHandle ikHandleName = nameUtils.getUniqueName(self.side, self.baseName, "IK") self.ikHandle = pm.ikHandle(n = ikHandleName, sj = self.chain[0], ee = self.chain[-1], solver = "ikRPsolver")[0] #create parent constraint from the ikHandle to the last control pm.pointConstraint(self.controlsArray[-1].control, self.ikHandle, mo = 1) #create a pole vector control pm.poleVectorConstraint(self.controlsArray[0].control, self.ikHandle)
def create( self ): # # Create Kinect2 Joints # aimer = [] for kjot in self.k2map: tag = self.k2map[kjot][0] aimid = self.k2map[kjot][2] aim = None if aimid is None else self.k2map[aimid][0] aimv = (1,0,0) t = pm.xform( tag, q=True, ws=True, t=True ) pm.select( cl=True ) pm.joint( p=t, n=kjot ) if not aim is None: aimv = (-1,0,0) if pm.getAttr(aim+'.tx') < 0 else aimv aimer.append(pm.aimConstraint( aim, kjot, aim=aimv, wut='objectrotation', u=(0,1,0), wu=(0,1,0), wuo=tag )) pm.delete( aimer ) # # Make Joints Hierarchy # for kjot in self.k2map: parent = self.k2map[kjot][1] aimid = self.k2map[kjot][2] if not parent is None: pm.parent( kjot, self.k2map[kjot][1] ) if aimid is None: pm.setAttr( kjot+'.jointOrient', (0,0,0) ) # Freeze Transformations pm.makeIdentity( kjot, a=True, jo=False, t=False, r=True, s=False, n=0, pn=True ) # # Make Constraint # for kjot in self.k2map: tag = self.k2map[kjot][0] aimid = self.k2map[kjot][2] aim = None if aimid is None else self.k2map[aimid][0] aimv = (1,0,0) # Aim Constraint pm.pointConstraint( tag, kjot ) # Aim Constraint if not aim is None: aimv = (-1,0,0) if pm.getAttr(aim+'.tx') < 0 else aimv pm.aimConstraint( aim, kjot, aim=aimv, wut='objectrotation', u=(0,1,0), wu=(0,1,0), wuo=tag ) return
def createPoleVectorLocatorAndLinkingCurve(self): pm.select(cl = True) #PoleVector #---------------------------------------------------- #Create leg ik pole vector loc self.leg_ik_pole_vector_locator = pm.spaceLocator(n = self.prefix +'_leg_ik_pole_vector_locator') pm.select(cl = True) #Group leg ik pole vec self.leg_ik_pole_vector_locator_grp = pm.group(self.leg_ik_pole_vector_locator, n = self.prefix + '_leg_ik_pole_vector_locator_grp') pm.select(cl = True) #Translate leg_ik_pole_vector_locator_grp self.leg_ik_pole_vector_locator_grp.translate.set(self.leg_locator_poleVector_worldCoords) #LinkingCurve #---------------------------------------------------- #Create linking curve loc self.leg_ik_pole_vector_locator_linking_curve_locator = pm.spaceLocator(n = self.prefix +'_leg_ik_pole_vector_locator_linking_curve_locator') pm.select(cl = True) #point con linking curve loc to leg ik j base pm.pointConstraint(self.leg_ik_j_base, self.leg_ik_pole_vector_locator_linking_curve_locator , mo = False) #Create Pole vector Linking Curve self.pole_vector_linking_curve = pm.curve(p = [self.leg_locator_base_worldCoords , self.leg_locator_poleVector_worldCoords], d = 1, n = self.prefix +'_pole_vector_linking_curve') pm.select(cl = True) #make curve not selectable pm.setAttr(self.pole_vector_linking_curve.getShape().overrideEnabled, 1) pm.setAttr(self.pole_vector_linking_curve.getShape().overrideDisplayType, 2) pm.select(cl = True) #Connect loc world space coords to curve points self.leg_ik_pole_vector_locator_linking_curve_locator.getShape().worldPosition[0] >> self.pole_vector_linking_curve.getShape().controlPoints[0] self.leg_ik_pole_vector_locator.getShape().worldPosition[0] >> self.pole_vector_linking_curve.getShape().controlPoints[1] pm.select(cl = True) #Create grp self.pole_vector_linking_curve_grp = pm.group( n = self.prefix +'_pole_vector_linking_curve_grp') pm.select(cl = True) #parent objects in group pm.parent(self.leg_ik_pole_vector_locator_linking_curve_locator, self.pole_vector_linking_curve ,self.pole_vector_linking_curve_grp) pm.select(cl = True)
def add_space(target, prefix): pin = pm.spaceLocator(name=prefix + "_space_pin") pin.visibility.set(0) pm.delete(pm.parentConstraint(target, pin, mo=False)) grp = pm.group(empty=True, name=prefix + "_space") pm.parent(pin, target, r=True) pm.pointConstraint(pin, grp, mo=0, name=grp.name() + "_tConst") pm.orientConstraint(pin, grp, mo=0, name=grp.name() + "_rConst") return grp
def unique_spine_zero_controller(self): # Create Root Costrain Jnt Unde Hip cotrol # Duplicate zero Jnt tempConst = pm.duplicate(self.joints.zeroJoint, po=True, name=("Const_" + self.joints.zeroJoint )) rootConst_jnt = tempConst[0] pm.parent(rootConst_jnt, self.hipCtrl.drawnNode) pm.pointConstraint(rootConst_jnt, self.joints.zeroJoint) pm.orientConstraint(rootConst_jnt, self.joints.zeroJoint) pm.setAttr(rootConst_jnt.visibility, 0) self._stuff.append(rootConst_jnt)
def __finalizeFkChainOriCnst(self): reversedList = list(self.controlsArray) reversedList.reverse() for i in range(len(reversedList)): if i != (len(reversedList)-1): pm.parent(reversedList[i].controlGrp,reversedList[i+1].control) #orient cnst for i,c in enumerate(self.controlsArray): pm.orientConstraint(c.control,self.chain[i],mo = 1) if self.pointCnst == 1: pm.pointConstraint(c.control,self.chain[i],mo = 1)
def addJacketCollarNoRotBinds(): # add collar joint no-rotate collarjnts = pm.ls(sl=True) for jnt in collarjnts: pm.select(cl=True) noRotJnt = pm.joint(n=jnt.replace('_jnt', '_norot_bnd')) wMat = jnt.getMatrix(worldSpace=True) noRotJnt.setMatrix(wMat, worldSpace=True) pm.makeIdentity(noRotJnt, a=True) noRotJnt.radius.set(0.5) grp = jnt.getParent(3) grp | noRotJnt pm.pointConstraint(jnt, noRotJnt)
def constrain(self, node_in, constType='point', targetType='constObj', maintainOff=0): """ :param constType: It can bePoint Orient or Parent :param targetType: It can be constObj or targetObj if targetType is constObj node in object Constrain drawnNode if targetType is targetObj drawnNode Constrain node in object :param node_in: if it is 1 preserve the constrained object’s position :param target: it should be constObj or targetObj :param maintainOffset: if it is 1 preserve the constrained object’s position """ tempConst = None target, constrained, setObjType = self._validate_targetType(node_in, targetType) if constType is 'point': tempConst = pm.pointConstraint(target, constrained, mo=maintainOff) if setObjType is 'setConstrainedPoint': self._constrainedPoint = tempConst else: self._targetPoint = tempConst elif constType is 'orient': tempConst = pm.orienConstraint(target, constrained, mo=maintainOff) if setObjType is 'setConstrainedPoint': self._constrainedOrient = tempConst else: self._targetOrient = tempConst elif constType is 'parent': tempConst = pm.parentConstraint(target, constrained, mo=maintainOff) if setObjType is 'setConstrainedPoint': self._constrainedParent = tempConst else: self._targetParent = tempConst return tempConst
def createMainNodes(self): #grps #chain grp self.chainGrp = pm.duplicate(self.rigGrp, parentOnly=True)[0] self.chainGrp.renameNode(name=self.TipName, nodeType='chain') self.chainGrp.setParent(self.rigGrp) #horizontal driver self.horizontalDriver = pm.duplicate(self.chainGrp, parentOnly=True)[0] self.horizontalDriver.renameNode(name=self.TipName, nodeType='horizDriver') pm.delete(pm.pointConstraint(self.startJoint, self.horizontalDriver)) #vertical driver self.verticalDriver = pm.duplicate(self.horizontalDriver, parentOnly=True)[0] self.verticalDriver.renameNode(name=self.TipName, nodeType='vertDriver') #main pm.select(self.horizontalDriver) self.driver = pm.joint() self.driver.renameNode(name=self.TipName, nodeType='driver') self.driver.addCon() self.driver.getParent().setParent(self.chainGrp) self.driver.getParent().visibility.set(0) pm.select(self.driver) self.main = pm.joint() self.main.renameNode(name=self.TipName, descriptor='system') pm.select(self.endJoint) self.eff = pm.joint() self.eff.renameNode(name=self.TipName, nodeType='effector') self.eff.setParent(self.driver) self.horizontalDriver.setParent(self.chainGrp) self.verticalDriver.setParent(self.chainGrp) #connectEye self.startJoint.rotate.connect(self.driver.getParent().rotate)
def bdLocOnJnt(): selection = pm.ls(sl=1) if len(selection) != 2: return rootJnt = pm.ls(sl=True)[0] crvPath = pm.ls(sl=True)[1] allJnt = rootJnt.listRelatives(f=True, ad=True, type='joint') allJnt = allJnt + [rootJnt] allJnt.reverse() locators = [] for jnt in allJnt: loc = pm.spaceLocator(name=jnt.name().replace('_jnt', '_loc')) locGrp = pm.group(n=loc.name() + '_grp') tempCnstr = pm.pointConstraint(jnt, locGrp, mo=0) pm.delete(tempCnstr) locators.append(locGrp) bdMultiMotionPath(crvPath, locators) bdParentJntToLocs(allJnt)
def bdSwitchFKIK(self, limb, side): if 'arm' in limb: print side + ' FK->IK arm switch ' fkWristConObj = pm.ls(side + self.fkArmCons[2] + 'CON')[0] fkWristPos = fkWristConObj.getTranslation(space='world') fkWristRot = fkWristConObj.getRotation(space='world') ikWristConObj = pm.ls(side + self.ikArmCons[0] + 'CON')[0] ikPVCon = pm.ls(side + self.ikArmCons[1] + 'CON')[0] ikWristConObj.setTranslation(fkWristPos, space='world') ikWristConObj.setRotation(fkWristRot, space='world') # vector fun fkWristVec = om.MVector(fkWristPos) fkElbowConObj = pm.ls(side + self.fkArmCons[1] + 'CON')[0] fkElbowPos = fkElbowConObj.getTranslation(space='world') fkElbowVec = om.MVector(fkElbowPos) fkShoulderConObj = pm.ls(side + self.fkArmCons[0] + 'CON')[0] fkShoulderPos = fkShoulderConObj.getTranslation(space='world') fkShoulderVec = om.MVector(fkShoulderPos) fkMidPoint = (fkWristVec + fkShoulderVec) / 2 pvVec = ((fkElbowVec - fkMidPoint) * 4) + fkMidPoint tempObj = pm.circle(c=[pvVec.x, pvVec.y, pvVec.z])[0] tempObj.centerPivots() # ikPVCon.setTranslation([pvVec.x,pvVec.y,pvVec.z],space='world') tempCnstr = pm.pointConstraint(tempObj, ikPVCon) pm.delete([tempCnstr, tempObj]) self.armSwitchCon.attr('ikFkBlend').set(0)
def createFootCtrl(self): """ Create foot nurbs curve and place in the feel of the character. The control will have the size from the heel helper to the end foot helper """ footCtrl = rigUtils.createRigControl('foot') pm.rename(footCtrl, self.side + footCtrl) footCtrl = self.side + footCtrl # mirror ctrl if we are doing the right side if self.side == 'R': pm.scale(footCtrl, (-1, 1, 1)) pm.makeIdentity(footCtrl, a=True, s=True) # place the foot ctrl in the 3rd rig helper (heel) pm.delete(pm.pointConstraint(self.side + '_leg_3_rigHelper', footCtrl)) pm.makeIdentity(footCtrl, a=True, t=True) endFootHelper = pm.PyNode(self.side + '_leg_5_rigHelper') endFootCtrl = pm.PyNode(self.side + '_foot_ctrl') # gets the heel helper world position and the bounding box of the foot controller endFootHelperPos = endFootHelper.getTranslation('world') bbox = pm.exactWorldBoundingBox(footCtrl) # gets the correct scale to feet the helpers scaleFactor = (endFootHelperPos[2] - bbox[5]) + 1 pm.scale(footCtrl, scaleFactor, scaleFactor, scaleFactor) pm.makeIdentity(footCtrl, a=True, s=True) # parent the control to the new created foot chain rigUtils.setControlColor(footCtrl) pm.parent(self.footJnt, self.side + '_foot_ctrl') return footCtrl
def clusLoc(): """ create locator at a centroid position in a ring of edges how to use: select edges loop and excute this command from rigWorkshop.ws_user.jun.utils import clusLoc reload(clusLoc) clusLoc.clusLoc() """ edges = pm.selected(flatten=True) #list comprehension verts = list(set(sum([list(e.connectedVertices()) for e in edges], []))) #cluster clusDFM, clusTRN = pm.cluster(verts) #locator loc = pm.spaceLocator() #point constraint pm.delete(pm.pointConstraint(clusTRN, loc, mo=False)) pm.delete(clusTRN)
def outputPoint(self, constrained=None, maintainOff=None): if constrained is None and maintainOff is None: return self._outputPoint else: self._outputPoint = pm.pointConstraint(self.drawnNode, constrained, mo=maintainOff)
def createRivetTweak(mesh, edgePair, name, parent=None, ctlParent=None, color=[0, 0, 0], size=.04, defSet=None): """Create a tweak joint attached to the mesh using a rivet Args: mesh (mesh): The object to add the tweak edgePair (pari list): The edge pairt to create the rivet name (str): The name for the tweak parent (None or dagNode, optional): The parent for the tweak ctlParent (None or dagNode, optional): The parent for the tweak control color (list, optional): The color for the control """ blendShape = blendShapes.getBlendShape(mesh) inputMesh = blendShape.listConnections(sh=True, t="shape", d=False)[0] oRivet = rivet.rivet() base = oRivet.create(inputMesh, edgePair[0], edgePair[1], parent) # get side if base.getTranslation(space='world')[0] < -0.01: side = "R" elif base.getTranslation(space='world')[0] > 0.01: side = "L" else: side = "C" nameSide = name + "_tweak_" + side pm.rename(base, nameSide) # Joints NPO npo = pm.PyNode( pm.createNode("transform", n=nameSide + "_npo", p=ctlParent, ss=True)) pm.pointConstraint(base, npo) # set proper orientation pos = base.getTranslation(space="world") temp = pm.spaceLocator() pm.parent(temp, base) temp.attr("ty").set(0) temp.attr("tz").set(0) temp.attr("tx").set(1) lookat = temp.getTranslation(space="world") up = datatypes.Vector(0, 1, 0) t = transform.getTransformLookingAt(pos, lookat, up, axis="xy", negate=False) npo.setMatrix(t, worldSpace=True) pm.delete(temp) # create joints jointBase = primitive.addJoint(npo, nameSide + "_jnt_lvl") joint = primitive.addJoint(jointBase, nameSide + "_jnt") # hidding joint base by changing the draw mode pm.setAttr(jointBase + ".drawStyle", 2) if not defSet: try: defSet = pm.PyNode("rig_deformers_grp") except TypeError: pm.sets(n="rig_deformers_grp") defSet = pm.PyNode("rig_deformers_grp") pm.sets(defSet, add=joint) controlType = "sphere" o_icon = icon.create(jointBase, nameSide + "_ctl", datatypes.Matrix(), color, controlType, w=size) for t in [".translate", ".scale", ".rotate"]: pm.connectAttr(o_icon + t, joint + t) # create the attributes to handlde mirror and symetrical pose attribute.addAttribute(o_icon, "invTx", "bool", 0, keyable=False, niceName="Invert Mirror TX") attribute.addAttribute(o_icon, "invTy", "bool", 0, keyable=False, niceName="Invert Mirror TY") attribute.addAttribute(o_icon, "invTz", "bool", 0, keyable=False, niceName="Invert Mirror TZ") attribute.addAttribute(o_icon, "invRx", "bool", 0, keyable=False, niceName="Invert Mirror RX") attribute.addAttribute(o_icon, "invRy", "bool", 0, keyable=False, niceName="Invert Mirror RY") attribute.addAttribute(o_icon, "invRz", "bool", 0, keyable=False, niceName="Invert Mirror RZ") attribute.addAttribute(o_icon, "invSx", "bool", 0, keyable=False, niceName="Invert Mirror SX") attribute.addAttribute(o_icon, "invSy", "bool", 0, keyable=False, niceName="Invert Mirror SY") attribute.addAttribute(o_icon, "invSz", "bool", 0, keyable=False, niceName="Invert Mirror SZ") # magic of doritos connection doritosMagic(mesh, joint, jointBase) # reset axis and inver behaviour for axis in "XYZ": pm.setAttr(jointBase + ".jointOrient" + axis, 0) pm.setAttr(npo + ".translate" + axis, 0) pm.setAttr(jointBase + ".translate" + axis, 0) p = o_icon.getParent().getParent() pp = p.getParent() pm.parent(p, w=True) for axis in "xyz": p.attr("r" + axis).set(0) if side == "R": p.attr("ry").set(180) p.attr("sz").set(-1) pm.parent(p, pp) return o_icon
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 startPipe( basename='pipe', pipeRadius = 0.2, jointRadius = 0.02, subdivAxis = 16, subdivJoint = 8, jointLength = .8, connectorRadius = .1, connectorThickness = .2, connectorOffset = .001 ): print basename i=1 name = basename + str(i) while pm.ls( name + '_Jnt0'): i += 1 name = basename + str(i) try: startPos = pm.selected()[0].getTranslation(ws=1) except: startPos = [0,0,0] pm.select(cl=1) rigGrp = pm.group(empty=True, n='%s_RigGrp' % name) geoGrp = pm.group(empty=True, n='%s_GeoGrp' % name) root = pm.joint( name=name+'_Jnt0') trans = pm.group(empty=True, n='%s_Elbow0' % name) pm.pointConstraint( root, trans ) root.scale.lock() root.addAttr( 'globalPipeRadius', defaultValue=pipeRadius, min=.0001 ) root.globalPipeRadius.showInChannelBox(1) root.addAttr( 'globalJointRadius', defaultValue=jointRadius ) root.globalJointRadius.showInChannelBox(1) root.addAttr( 'subdivisionsAxis', at = 'short', defaultValue=subdivAxis, min=4 ) root.subdivisionsAxis.showInChannelBox(1) root.addAttr( 'subdivisionsJoint', at = 'short', defaultValue=subdivJoint ) root.subdivisionsJoint.showInChannelBox(1) root.addAttr( 'globalConnectorRadius', defaultValue=connectorRadius ) root.globalConnectorRadius.showInChannelBox(1) root.addAttr( 'globalConnectorThickness', defaultValue=connectorThickness ) root.globalConnectorThickness.showInChannelBox(1) root.addAttr( 'globalConnectorOffset', min = 0, defaultValue=connectorOffset ) root.globalConnectorOffset.showInChannelBox(1) root.radius.showInChannelBox(0) root.displayHandle = 1 root.setParent(rigGrp) trans.setParent(rigGrp) root.setTranslation( startPos ) root.select() extendPipe(jointLength)
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 kiddoRigModules(): print 'Create kiddo rig modules' bodyModule = rig_module('body') pm.parent('mainJA_JNT', bodyModule.skeleton) main = rig_control(name='main', shape='box', targetOffset='mainJA_JNT', constrain='mainJA_JNT', parentOffset=bodyModule.controls, scale=(45, 10, 50), colour='white') main.gimbal = createCtrlGimbal(main) main.pivot = createCtrlPivot(main, overrideScale=(10, 10, 10)) upperBody = rig_control(name='upperBody', shape='box', modify=1, targetOffset='mainJA_JNT', constrainOffset=main.con, scale=(35, 15, 40), colour='yellow', parentOffset=bodyModule.controls, lockHideAttrs=['tx', 'ty', 'tz'], rotateOrder=2) pm.move(upperBody.ctrl.cv, [0, 10, 0], relative=True, objectSpace=True) upperWaistXYZ = simpleControls( ['upperWaistY_JA_JNT', 'upperWaistZ_JA_JNT', 'upperWaistX_JA_JNT'], modify=1, scale=(45, 10, 50), parentOffset=bodyModule.parts, lockHideAttrs=['tx', 'ty', 'tz']) upperWaistY = upperWaistXYZ['upperWaistY_JA_JNT'] upperWaistZ = upperWaistXYZ['upperWaistZ_JA_JNT'] upperWaistX = upperWaistXYZ['upperWaistX_JA_JNT'] pm.hide(upperWaistY.offset, upperWaistZ.offset, upperWaistX.offset) constrainObject(upperBody.modify, [upperBody.offset, 'worldSpace_GRP'], upperBody.ctrl, ['main', 'world'], type='orientConstraint') constrainObject(upperWaistY.modify, [upperWaistY.offset, 'worldSpace_GRP'], upperBody.ctrl, ['main', 'world'], type='orientConstraint', skip=('x', 'z')) constrainObject(upperWaistZ.modify, [upperWaistZ.offset, 'worldSpace_GRP'], upperBody.ctrl, ['main', 'world'], type='orientConstraint', skip=('x', 'y')) constrainObject(upperWaistX.modify, [upperWaistX.offset, 'worldSpace_GRP'], upperBody.ctrl, ['main', 'world'], type='orientConstraint', skip=('z', 'y')) pm.connectAttr(upperBody.ctrl.rotateX, upperWaistX.ctrl.rotateX) pm.connectAttr(upperBody.ctrl.rotateY, upperWaistY.ctrl.rotateY) pm.connectAttr(upperBody.ctrl.rotateZ, upperWaistZ.ctrl.rotateZ) lowerBody = rig_control(name='lowerBody', shape='box', modify=1, targetOffset='lowerBodyJA_JNT', constrainOffset=main.con, scale=(40, 20, 30), colour='green', parentOffset=bodyModule.controls, lockHideAttrs=['tx', 'ty', 'tz', 'rx', 'rz'], rotateOrder=2) constrainObject(lowerBody.modify, [lowerBody.offset, 'worldSpace_GRP'], lowerBody.ctrl, ['main', 'world'], type='orientConstraint', skip=('x', 'z')) pm.parentConstraint(lowerBody.con, 'lowerBodyJA_JNT', mo=True) pm.move(lowerBody.ctrl.cv, [0, -10, 0], relative=True, objectSpace=True) biped = rig_biped() biped.spineConnection = 'upperWaistX_JA_JNT' biped.pelvisConnection = 'lowerBodyJA_JNT' biped.centerConnection = 'mainJA_JNT' for side in ['l', 'r']: armModule = biped.arm(side, ctrlSize=10) fingersModule = biped.hand(side, ctrlSize=2.5) shoulderModule = biped.shoulder(side, ctrlSize=12) biped.connectArmShoulder(side) secColour = 'deepskyblue' if side == 'r': secColour = 'magenta' # make leg legName = side + '_leg' legModule = rig_module(legName) hipZJnt = side + '_hipZ_JA_JNT' hipYJnt = side + '_hipY_JA_JNT' legJnt = side + '_legJA_JNT' kneeJnt = side + '_kneeJA_JNT' ankleJnt = side + '_ankleJA_JNT' footJnt = side + '_footJA_JNT' pm.setAttr(hipYJnt + '.rotateOrder', 2) # chain IK legJntIK = rig_transform(0, name=side + '_legIK', type='joint', target=legJnt, parent=legModule.parts).object kneeJntIK = rig_transform(0, name=side + '_kneeIK', type='joint', target=kneeJnt).object ankleJntIK = rig_transform( 0, name=side + '_ankleIK', type='joint', target=ankleJnt, ).object footJntIK = rig_transform( 0, name=side + '_footIK', type='joint', target=footJnt, ).object chainIK = [legJntIK, kneeJntIK, ankleJntIK, footJntIK] chainParent(chainIK) chainIK.reverse() # create ik ik = rig_ik(legName, legJntIK, footJntIK, 'ikSpringSolver') pm.parent(ik.handle, legModule.parts) # pole vector legPoleVector = rig_control(side=side, name='legPV', shape='pointer', modify=1, lockHideAttrs=['rx', 'ry', 'rz'], targetOffset=[legJnt, footJnt], parentOffset=legModule.parts, scale=(2, 2, 2)) pm.delete(pm.aimConstraint(ankleJnt, legPoleVector.offset, mo=False)) kneePos = pm.xform(kneeJnt, translation=True, query=True, ws=True) poleVectorPos = pm.xform(legPoleVector.con, translation=True, query=True, ws=True) pvDistance = lengthVector(kneePos, poleVectorPos) pm.xform(legPoleVector.offset, translation=[-25, 0, 0], os=True, r=True) pm.poleVectorConstraint(legPoleVector.con, ik.handle) # create pv #pm.parentConstraint(biped.centerConnection, legPoleVector.offset, mo=True) pm.parentConstraint(hipYJnt, legPoleVector.offset, mo=True) if side == 'r': pm.rotate(legPoleVector.ctrl.cv, 0, -90, 0, r=True, os=True) else: pm.rotate(legPoleVector.ctrl.cv, 0, 90, 0, r=True, os=True) # create foot control foot = rig_control(side=side, name='foot', shape='box', modify=1, scale=(13, 13, 13), parentOffset=legModule.controls, lockHideAttrs=['rx', 'ry', 'rz']) pm.delete(pm.pointConstraint(footJnt, foot.offset)) pm.parentConstraint(foot.con, ik.handle, mo=True) #pm.pointConstraint( foot.con, legPoleVector.modify, mo=True ) foot.gimbal = createCtrlGimbal(foot) foot.pivot = createCtrlPivot(foot) constrainObject( foot.offset, [biped.pelvisConnection, biped.centerConnection, 'worldSpace_GRP'], foot.ctrl, ['pelvis', 'main', 'world'], type='parentConstraint') pm.setAttr(foot.ctrl.space, 2) pm.addAttr(foot.ctrl, longName='twist', at='float', k=True) pm.addAttr(foot.ctrl, longName='springBiasBottom', at='float', min=0, max=1, k=True, dv=0) pm.addAttr(foot.ctrl, longName='springBiasTop', at='float', min=0, max=1, k=True, dv=0.5) pm.connectAttr(foot.ctrl.twist, ik.handle.twist) pm.connectAttr(foot.ctrl.springBiasBottom, ik.handle + '.springAngleBias[0].springAngleBias_FloatValue', f=True) pm.connectAttr(foot.ctrl.springBiasTop, ik.handle + '.springAngleBias[1].springAngleBias_FloatValue', f=True) # create hip aims hipAimZ_loc = rig_transform(0, name=side + '_hipAimZ', type='locator', parent=legModule.parts, target=hipZJnt).object footAimZ_loc = rig_transform(0, name=side + '_footAimZ', type='locator', parent=legModule.parts).object pm.pointConstraint(biped.pelvisConnection, hipAimZ_loc, mo=True) pm.parentConstraint(foot.con, footAimZ_loc) # z rotation hipAimZ = mm.eval('rig_makePiston("' + footAimZ_loc + '", "' + hipAimZ_loc + '", "' + side + '_hipAimZ");') hipZ = rig_control(side=side, name='hipRoll', shape='sphere', modify=1, scale=(5, 5, 7), parentOffset=legModule.parts, targetOffset=hipZJnt, lockHideAttrs=['tx', 'ty', 'tz', 'rx', 'ry'], rotateOrder=0) pm.parentConstraint(hipZ.con, hipZJnt, mo=True) pm.parentConstraint(lowerBody.con, hipZ.offset, mo=True) rotCon = pm.orientConstraint(hipZ.offset, hipAimZ_loc, hipZ.modify, mo=True, skip=('x', 'y')) targetZ = rotCon.getWeightAliasList() #pm.addAttr(hipZ.ctrl, longName='aim', at='float', k=True, min=0, max=1, # dv=1) #pm.connectAttr ( hipZ.ctrl.aim, target ) # y rotation hipAimY_loc = rig_transform(0, name=side + '_hipAimY', type='locator', parent=legModule.parts, target=hipYJnt).object footAimY_loc = rig_transform(0, name=side + '_footAimY', type='locator', parent=legModule.parts).object pm.pointConstraint(hipZJnt, hipAimY_loc, mo=True) pm.parentConstraint(foot.con, footAimY_loc) hipAimY = mm.eval('rig_makePiston("' + footAimY_loc + '", "' + hipAimY_loc + '", ' '"' + side + '_hipAimY");') pm.setAttr(side + '_hipAimZ_LOC.rotateOrder', 4) hipY = rig_control(side=side, name='hipYaw', shape='sphere', modify=2, scale=(5, 7, 5), parentOffset=legModule.controls, targetOffset=hipYJnt, lockHideAttrs=['tx', 'ty', 'tz', 'rx', 'rz'], rotateOrder=2) pm.parentConstraint(hipY.con, hipYJnt, mo=True) pm.parentConstraint(hipZ.con, hipY.offset, mo=True) #rotCon = pm.parentConstraint(hipAimY_loc, hipY.modify, mo=True, # skipTranslate=('x', 'y', 'z'), # skipRotate=('x', 'z')) rotCon = pm.orientConstraint(hipY.offset, hipAimY_loc, hipY.modify[0], mo=True, skip=('x', 'z')) targetY = rotCon.getWeightAliasList() pm.addAttr(hipY.ctrl, longName='aim', at='float', k=True, min=0, max=1, dv=1) pm.connectAttr(hipY.ctrl.aim, targetY[1]) pm.connectAttr(hipY.ctrl.aim, targetZ[1]) connectReverse(name=side + '_leg', input=(hipY.ctrl.aim, hipY.ctrl.aim, 0), output=(targetY[0], targetZ[0], 0)) pm.setAttr(rotCon.interpType, 2) pm.transformLimits(hipY.modify[0], ry=(-30, 10), ery=(1, 1)) pm.addAttr(hipY.ctrl, longName='aimRotation', at='float', k=True, min=0, max=10, dv=0) pm.addAttr(hipY.ctrl, longName='limitOutRotation', at='float', k=True, min=0, max=10, dv=3) pm.addAttr(hipY.ctrl, longName='limitInRotation', at='float', k=True, min=0, max=10, dv=0) hipY.ctrl.limitOutRotation.set(cb=True) hipY.ctrl.limitInRotation.set(cb=True) pm.setDrivenKeyframe(hipY.modify[0] + '.minRotYLimit', cd=hipY.ctrl.limitOutRotation, dv=0, v=-45) pm.setDrivenKeyframe(hipY.modify[0] + '.minRotYLimit', cd=hipY.ctrl.limitOutRotation, dv=10, v=0) pm.setDrivenKeyframe(hipY.modify[0] + '.maxRotYLimit', cd=hipY.ctrl.limitInRotation, dv=0, v=10) pm.setDrivenKeyframe(hipY.modify[0] + '.maxRotYLimit', cd=hipY.ctrl.limitInRotation, dv=10, v=0) rotCon = pm.orientConstraint(hipY.offset, hipY.modify[0], hipY.modify[1], mo=True) conTargets = rotCon.getWeightAliasList() pm.setDrivenKeyframe(conTargets[0], cd=hipY.ctrl.aimRotation, dv=0, v=1) pm.setDrivenKeyframe(conTargets[0], cd=hipY.ctrl.aimRotation, dv=10, v=0) connectReverse(name=side + '_hipYTarget', input=(conTargets[0], 0, 0), output=(conTargets[1], 0, 0)) # constrain shizzle legTop = rig_transform(0, name=side + '_legTop', target=legJnt, parent=legModule.skeleton).object pm.setAttr(legTop + '.inheritsTransform', 0) pm.scaleConstraint('worldSpace_GRP', legTop) legSkeletonParts = rig_transform(0, name=side + '_legSkeletonParts', parent=legTop).object pm.parent(hipAimY, hipAimZ, legModule.parts) pm.parent(legJntIK, legJnt, legSkeletonParts) pm.hide(legJntIK) pm.parentConstraint(hipYJnt, legTop, mo=True, skipRotate=('x', 'y', 'z')) #pm.connectAttr(legJntIK+'.rotate', legJnt+'.rotate') pm.connectAttr(kneeJntIK + '.rotate', kneeJnt + '.rotate') pm.connectAttr(ankleJntIK + '.rotate', ankleJnt + '.rotate') multiplyDivideNode('legRotate', 'multiply', input1=[ legJntIK + '.rotateX', legJntIK + '.rotateY', legJntIK + '.rotateZ' ], input2=[1, hipY.ctrl.aim, hipY.ctrl.aim], output=[ legJnt + '.rotateX', legJnt + '.rotateY', legJnt + '.rotateZ' ]) pm.parent(hipZJnt, legModule.skeleton) pm.parent(hipYJnt, legModule.skeleton) footJnts = [ side + '_heelRotY_JA_JNT', side + '_footRotX_JA_JNT', side + '_footRotY_JA_JNT', side + '_footRotZ_JA_JNT' ] footControls = simpleControls(footJnts, modify=2, scale=(11, 3, 20), parentOffset=legModule.parts, colour=secColour, lockHideAttrs=['tx', 'ty', 'tz']) #footControls[side+''] ankle = rig_control(side=side, name='ankle', shape='box', modify=1, scale=(10, 6, 8), colour=secColour, parentOffset=legModule.controls, targetOffset=side + '_footRotZ_JA_JNT', lockHideAttrs=['tx', 'ty', 'tz', 'ry']) pm.parentConstraint(footJnt, ankle.offset, mo=True) heel = footControls[side + '_heelRotY_JA_JNT'] footRotX = footControls[side + '_footRotX_JA_JNT'] footRotY = footControls[side + '_footRotY_JA_JNT'] footRotZ = footControls[side + '_footRotZ_JA_JNT'] pm.parent(heel.offset, legModule.controls) heel.ctrl.rotateX.setKeyable(False) heel.ctrl.rotateX.setLocked(True) heel.ctrl.rotateZ.setKeyable(False) heel.ctrl.rotateZ.setLocked(True) pm.parentConstraint(footRotY.con, heel.modify[0], mo=True) pm.parentConstraint(footRotZ.con, footRotY.modify[0], mo=True) pm.parentConstraint(footRotX.con, footRotZ.modify[0], mo=True) footSpace = footJnt if side == 'l': footSpace = rig_transform(0, name='l_footSpace', parent=legModule.parts, target=footJnt).object pm.setAttr(footSpace + '.rotateX', 0) pm.parentConstraint(footJnt, footSpace, mo=True) toeSpaceList = ('lowerBody', 'foot', 'main', 'world') constrainObject(heel.modify[1], [ biped.pelvisConnection, footSpace, biped.centerConnection, 'worldSpace_GRP' ], heel.ctrl, toeSpaceList, type='orientConstraint', skip=('x', 'z')) constrainObject(footRotX.modify[0], [ biped.pelvisConnection, footSpace, biped.centerConnection, 'worldSpace_GRP' ], footRotX.ctrl, toeSpaceList, type='orientConstraint', skip=('y', 'z')) constrainObject(footRotZ.modify[1], [ biped.pelvisConnection, footSpace, biped.centerConnection, 'worldSpace_GRP' ], footRotZ.ctrl, toeSpaceList, type='orientConstraint', skip=('x', 'y')) pm.connectAttr(ankle.ctrl.rotateX, footRotX.ctrl.rotateX) #pm.connectAttr( ankle.ctrl.rotateY, heel.ctrl.rotateY ) #connectNegative(ankle.ctrl.rotateY, heel.ctrl.rotateY) pm.connectAttr(ankle.ctrl.rotateZ, footRotZ.ctrl.rotateZ) pm.addAttr(ankle.ctrl, ln='SPACES', at='enum', enumName='___________', k=True) ankle.ctrl.SPACES.setLocked(True) pm.addAttr(ankle.ctrl, ln='rollSpace', at='enum', enumName='lowerBody:foot:main:world', k=True) #pm.addAttr(ankle.ctrl, ln='yawSpace', at='enum', # enumName='lowerBody:foot:main:world', k=True) pm.addAttr(ankle.ctrl, ln='pitchSpace', at='enum', enumName='lowerBody:foot:main:world', k=True) pm.connectAttr(ankle.ctrl.rollSpace, footRotX.ctrl.space) #pm.connectAttr( ankle.ctrl.yawSpace, heel.ctrl.space) pm.connectAttr(ankle.ctrl.pitchSpace, footRotZ.ctrl.space) pm.addAttr(ankle.ctrl, ln='MOTION', at='enum', enumName='___________', k=True) ankle.ctrl.MOTION.setLocked(True) pm.addAttr(ankle.ctrl, longName='footFangs', at='float', k=True, min=0, max=10, dv=0) pm.addAttr(ankle.ctrl, longName='toeFangs', at='float', k=True, min=0, max=10, dv=0) fangsJnt = pm.PyNode(side + '_toeFangsJA_JNT') toeFangsJnt = pm.PyNode(side + '_footFangsJA_JNT') fangsTranslate = fangsJnt.translate.get() pm.setDrivenKeyframe(fangsJnt.translateX, cd=ankle.ctrl.footFangs, dv=0, v=fangsTranslate[0]) pm.setDrivenKeyframe(fangsJnt.translateY, cd=ankle.ctrl.footFangs, dv=0, v=fangsTranslate[1]) pm.setDrivenKeyframe(fangsJnt.translateZ, cd=ankle.ctrl.footFangs, dv=0, v=fangsTranslate[2]) pm.move(0, 1.5, 0, fangsJnt, r=True, os=True) fangsTranslate = fangsJnt.translate.get() pm.move(0, -1.5, 0, fangsJnt, r=True, os=True) pm.setDrivenKeyframe(fangsJnt.translateX, cd=ankle.ctrl.footFangs, dv=10, v=fangsTranslate[0]) pm.setDrivenKeyframe(fangsJnt.translateY, cd=ankle.ctrl.footFangs, dv=10, v=fangsTranslate[1]) pm.setDrivenKeyframe(fangsJnt.translateZ, cd=ankle.ctrl.footFangs, dv=10, v=fangsTranslate[2]) # foot fangs fangsTranslate = toeFangsJnt.translate.get() pm.setDrivenKeyframe(toeFangsJnt.translateX, cd=ankle.ctrl.toeFangs, dv=0, v=fangsTranslate[0]) pm.setDrivenKeyframe(toeFangsJnt.translateY, cd=ankle.ctrl.toeFangs, dv=0, v=fangsTranslate[1]) pm.setDrivenKeyframe(toeFangsJnt.translateZ, cd=ankle.ctrl.toeFangs, dv=0, v=fangsTranslate[2]) pm.move(0, 0, -4.7, toeFangsJnt, r=True, os=True) fangsTranslate = toeFangsJnt.translate.get() pm.move(0, 0, 4.7, toeFangsJnt, r=True, os=True) pm.setDrivenKeyframe(toeFangsJnt.translateX, cd=ankle.ctrl.toeFangs, dv=10, v=fangsTranslate[0]) pm.setDrivenKeyframe(toeFangsJnt.translateY, cd=ankle.ctrl.toeFangs, dv=10, v=fangsTranslate[1]) pm.setDrivenKeyframe(toeFangsJnt.translateZ, cd=ankle.ctrl.toeFangs, dv=10, v=fangsTranslate[2]) pm.addAttr(ankle.ctrl, longName='toeCapRotate', at='float', k=True, dv=0) if side == 'l': pm.connectAttr(ankle.ctrl.toeCapRotate, 'l_footCapJA_JNT.rotateX', f=True) else: connectReverse(ankle.ctrl.toeCapRotate, 'r_footCapJA_JNT.rotateX') # simple controls legSidesSimpleControls(legModule, side, secColour) armSidesSimpleControls(armModule, side, secColour) # asymettrical controls bodySimpleControls(bodyModule)
def squishySplineIk(startLoc, endLoc): ikJoints = list() startJoint = pmc.createNode('joint') adv.alignObjects(startJoint, startLoc) endJoint = pmc.createNode('joint') adv.alignObjects(endJoint, endLoc) pmc.parent(endJoint, startJoint) startJoint.orientJoint('xzy', secondaryAxisOrient='zup') pmc.makeIdentity(endJoint, apply=True, jointOrient=True) Splitter.doSplit(startJoint, 10) ikJoints.append(startJoint) ikJoints.extend(reversed(startJoint.getChildren(ad=True, type='joint'))) for i, ikj in enumerate(ikJoints): ikj.radius.set(2) ikj.rename('ikj_spine{0:02d}'.format(i)) # Create second set of joints rigJoints = adv.makeDuplicateJoints(joints=ikJoints, search='ikj_', replace='local_rig_', connectBone=False) # HACK I haven't figured out how to create SDK nodes procedurally, # so making some dummy locs to make the curve I need a = pmc.createNode('transform') b = pmc.createNode('transform') pmc.setKeyframe(a.ty, t=0, value=2.5, inTangentType='flat', outTangentType='flat') pmc.setKeyframe(a.ty, t=10, value=0, inTangentType='flat', outTangentType='flat') pmc.keyTangent(a.ty, index=[0], inAngle=0) pmc.keyTangent(a.ty, index=[1], inAngle=-30) pmc.keyTangent(a.ty, index=[0], outAngle=0) pmc.keyTangent(a.ty, index=[1], outAngle=-30) animSquashCurve = a.ty.listConnections()[0] animSquashCurve.output.disconnect(a.ty) animSquashCurve.rename('squash_ramp') pmc.setKeyframe(a.tx, t=0, value=0, inTangentType='flat', outTangentType='flat') pmc.setKeyframe(a.tx, t=5, value=1, inTangentType='flat', outTangentType='flat') pmc.setKeyframe(a.tx, t=10, value=0, inTangentType='flat', outTangentType='flat') animTwistCurve = a.tx.listConnections()[0] animTwistCurve.output.disconnect(a.tx) animTwistCurve.rename('twist_ramp') pmc.delete(a, b) animControls = dict() animControls['lower_spine'] = adv.makeControlNode('ctl_lower_spine', targetObject=rigJoints[2], alignRotation=False) animControls['middle_spine'] = adv.makeControlNode('ctl_middle_spine') animControls['upper_spine'] = adv.makeControlNode('ctl_upper_spine', targetObject=rigJoints[-2], alignRotation=False) animControls['lower_spine'][0].rotateOrder.set(adv.ROO_YXZ) animControls['middle_spine'][0].rotateOrder.set(adv.ROO_YXZ) animControls['upper_spine'][0].rotateOrder.set(adv.ROO_YXZ) pmc.pointConstraint(animControls['lower_spine'][0], animControls['upper_spine'][0], animControls['middle_spine'][1], mo=False) pmc.orientConstraint(animControls['lower_spine'][0], animControls['upper_spine'][0], animControls['middle_spine'][1], mo=False) splineIk = pmc.ikHandle(sj=ikJoints[0], ee=ikJoints[-1], sol='ikSplineSolver', parentCurve=False, createCurve=True, simplifyCurve=True, numSpans=2, rootOnCurve=False, n='sik_spine') splineIkHandle = splineIk[0] spline = splineIk[2] spline.rename('crv_spine') clusterJoints = list() clusterJoints.append(pmc.createNode('joint', n='clj_spine0')) pmc.parentConstraint(animControls['lower_spine'][0], clusterJoints[-1]) clusterJoints.append(pmc.createNode('joint', n='clj_spine1')) pmc.parentConstraint(animControls['middle_spine'][0], clusterJoints[-1]) clusterJoints.append(pmc.createNode('joint', n='clj_spine2')) pmc.parentConstraint(animControls['upper_spine'][0], clusterJoints[-1]) pmc.skinCluster(clusterJoints, spline, maximumInfluences=3) pmc.parentConstraint(animControls['lower_spine'][0], ikJoints[0], maintainOffset=True) for clj in clusterJoints: clj.radius.set(3) splineIkHandle.dTwistControlEnable.set(1) splineIkHandle.dWorldUpType.set(4) splineIkHandle.dWorldUpAxis.set(0) splineIkHandle.dWorldUpVector.set([0.0, 0.0, 1.0]) splineIkHandle.dWorldUpVectorEnd.set([0.0, 0.0, 1.0]) animControls['lower_spine'][0].worldMatrix[0].connect(splineIkHandle.dWorldUpMatrix) animControls['upper_spine'][0].worldMatrix[0].connect(splineIkHandle.dWorldUpMatrixEnd) normalizeNode = stretchySplineIk(splineIkHandle, useScale=True, globalScaleAttr='ctl_main.size') sqrtScale = pmc.createNode('multiplyDivide', n='sqrt_spine_scale') sqrtScale.operation.set(3) sqrtScale.input2X.set(0.5) normalizeNode.outputX.connect(sqrtScale.input1X) invScale = pmc.createNode('multiplyDivide', n='div_spine_inverse_scale') invScale.operation.set(2) invScale.input1X.set(1.0) sqrtScale.outputX.connect(invScale.input2X) jointGroups = list() for i, jnt in enumerate(rigJoints): preTransform = adv.zeroOut(jnt, 'pre') jointGroups.append(preTransform) ikNode = adv.zeroOut(jnt, 'hlp_ik') pmc.pointConstraint(ikJoints[i], ikNode) pmc.orientConstraint(ikJoints[i], ikNode) twistNode = adv.zeroOut(jnt, 'hlp_twist') twistCache = pmc.createNode('frameCache', n='frm_{0}_twist'.format(jnt)) animTwistCurve.output.connect(twistCache.stream) twistCache.varyTime.set(i) rotateMultiplier = pmc.createNode('multiplyDivide', n='mul_{0}_twist'.format(jnt.shortName())) twistCache.varying.connect(rotateMultiplier.input2X) animControls['middle_spine'][0].rotateY.connect(rotateMultiplier.input1X) rotateMultiplier.outputX.connect(twistNode.rotateX) volumeCache = pmc.createNode('frameCache', n='frm_{0}_volume'.format(jnt.shortName())) animSquashCurve.output.connect(volumeCache.stream) volumeCache.varyTime.set(i) pow_ = pmc.createNode('multiplyDivide', n='pow_{0}'.format(jnt.shortName())) pow_.operation.set(3) invScale.outputX.connect(pow_.input1X) volumeCache.varying.connect(pow_.input2X) pow_.outputX.connect(jnt.scaleY) pow_.outputX.connect(jnt.scaleZ) pmc.group(animControls['lower_spine'][1], animControls['upper_spine'][1], animControls['middle_spine'][1], n='grp_spine_anim') pmc.group(splineIkHandle, spline, n='grp_spine_rig_systems') pmc.group(clusterJoints, startJoint, n='grp_spine_system_joints') pmc.group(jointGroups, n='grp_spine_bind_joints') return rigJoints
def rigCurveConnect(*objs, **kwargs): ''' update : 2015-04-15 update : 2016-11-03 ''' if objs: pm.select(objs) sel = pm.selected(type='transform') if not sel: raise obj = sel[0] # # 삭제 # delete = kwargs.get('delete', False) if delete: deleteList = [] for crvShp in obj.getShapes(): if crvShp.hasAttr('curveConnectedLOC'): deleteList = [ crvShp, crvShp.curveConnectedLOC.inputs(), crvShp.history(type='nurbsCurve')[-1] ] if deleteList: pm.delete(deleteList) print deleteList return # # 생성 # # 타겟 가져옴. target = sel[1] position = kwargs.get('position') or kwargs.get('p', (0, 0, 0)) # 커브 생성 crvTrans = pm.curve(d=1, p=[position, position], k=[0, 1]) crvShape = crvTrans.getShape() # obj에 커브 쉐입을 종속 시킴 : 커브를 선택해도 오브젝트를 선택한 효과를 줌. pm.parent(crvShape, obj, r=True, s=True) pm.delete(crvTrans) crvShape.rename(obj + 'Shape') # target에 locator를 종속 시킴 loc, leastSquaresModifier = pm.pointCurveConstraint(crvShape + '.ep[1]', ch=True) loc = pm.PyNode(loc) leastSquaresModifier = pm.PyNode(leastSquaresModifier) const = pm.pointConstraint(target, loc) # 로케이서 속성 조정 loc.getShape().localPosition.set(0, 0, 0) loc.getShape().v.set(False) loc.v.set(False) loc.setParent(obj) loc.rename(target + '_locator#') const.rename(target + '_pointConst#') # 커브쉐입에 어트리뷰트 추가 (깔끔 삭제용) crvShape.addAttr('curveConnectedTo', at='message') crvShape.addAttr('curveConnectedLOC', at='message') crvShape.addAttr('curveConnectedOrgShape', at='message') # 어트리뷰트 연결 target.message >> crvShape.curveConnectedTo loc.message >> crvShape.curveConnectedLOC # 선택 pm.select(obj) return loc
def cycleTweak(name, edgePair, mirrorAxis, baseMesh, rotMesh, transMesh, setupParent, ctlParent, jntOrg=None, grp=None, iconType="square", size=.025, color=13, ro=datatypes.Vector(1.5708, 0, 1.5708 / 2)): """The command to create a cycle tweak. A cycle tweak is a tweak that cycles to the parent position but doesn't create a cycle of dependency. This type of tweaks are very useful to create facial tweakers. Args: name (string): Name for the cycle tweak edgePair (list): List of edge pair to attach the cycle tweak mirrorAxis (bool): If true, will mirror the x axis behaviour. baseMesh (Mesh): The base mesh for the cycle tweak. rotMesh (Mesh): The mesh that will support the rotation transformations for the cycle tweak transMesh (Mesh): The mesh that will support the translation and scale transformations for the cycle tweak setupParent (dagNode): The parent for the setup objects ctlParent (dagNode): The parent for the control objects jntOrg (None or dagNode, optional): The parent for the joints grp (None or set, optional): The set to add the controls iconType (str, optional): The controls shape size (float, optional): The control size color (int, optional): The control color ro (TYPE, optional): The control shape rotation offset Returns: multi: the tweak control and the list of related joints. """ # rotation sctructure rRivet = rivet.rivet() rBase = rRivet.create( baseMesh, edgePair[0], edgePair[1], setupParent, name + "_rRivet_loc") pos = rBase.getTranslation(space="world") # translation structure tRivetParent = pm.createNode("transform", n=name + "_tRivetBase", p=ctlParent) tRivetParent.setMatrix(datatypes.Matrix(), worldSpace=True) tRivet = rivet.rivet() tBase = tRivet.create(transMesh, edgePair[0], edgePair[1], tRivetParent, name + "_tRivet_loc") # create the control tweakBase = pm.createNode("transform", n=name + "_tweakBase", p=ctlParent) tweakBase.setMatrix(datatypes.Matrix(), worldSpace=True) tweakNpo = pm.createNode("transform", n=name + "_tweakNpo", p=tweakBase) tweakBase.setTranslation(pos, space="world") tweakCtl = icon.create(tweakNpo, name + "_ctl", tweakNpo.getMatrix(worldSpace=True), color, iconType, w=size, d=size, ro=ro) inverseTranslateParent(tweakCtl) pm.pointConstraint(tBase, tweakBase) # rot rotBase = pm.createNode("transform", n=name + "_rotBase", p=setupParent) rotBase.setMatrix(datatypes.Matrix(), worldSpace=True) rotNPO = pm.createNode("transform", n=name + "_rot_npo", p=rotBase) rotJointDriver = pm.createNode("transform", n=name + "_rotJointDriver", p=rotNPO) rotBase.setTranslation(pos, space="world") node.createMulNode([rotNPO.attr("tx"), rotNPO.attr("ty"), rotNPO.attr("tz")], [-1, -1, -1], [rotJointDriver.attr("tx"), rotJointDriver.attr("ty"), rotJointDriver.attr("tz")]) pm.pointConstraint(rBase, rotNPO) pm.connectAttr(tweakCtl.r, rotNPO.r) pm.connectAttr(tweakCtl.s, rotNPO.s) # transform posNPO = pm.createNode("transform", n=name + "_pos_npo", p=setupParent) posJointDriver = pm.createNode("transform", n=name + "_posJointDriver", p=posNPO) posNPO.setTranslation(pos, space="world") pm.connectAttr(tweakCtl.t, posJointDriver.t) # mirror behaviour if mirrorAxis: tweakBase.attr("ry").set(tweakBase.attr("ry").get() + 180) rotBase.attr("ry").set(rotBase.attr("ry").get() + 180) posNPO.attr("ry").set(posNPO.attr("ry").get() + 180) tweakBase.attr("sz").set(-1) rotBase.attr("sz").set(-1) posNPO.attr("sz").set(-1) # create joints rJoint = rigbits.addJnt(rotJointDriver, jntOrg, True, grp) tJoint = rigbits.addJnt(posJointDriver, jntOrg, True, grp) # add to rotation skin # TODO: add checker to see if joint is in the skincluster. rSK = skin.getSkinCluster(rotMesh) pm.skinCluster(rSK, e=True, ai=rJoint, lw=True, wt=0) # add to transform skin # TODO: add checker to see if joint is in the skincluster. tSK = skin.getSkinCluster(transMesh) pm.skinCluster(tSK, e=True, ai=tJoint, lw=True, wt=0) return tweakCtl, [rJoint, tJoint]
def makeSpline(self, name, suffixCtrl='ctrl', suffixJnt='jnt', suffixGrp='grp', suffixDrv='drv', charSize=1.0, numControls=3, controlType='cube', numDrivens=5, drivenType='joint', constrainMid=False, mainSetName='setMUSCLERIGS', rigSetSuffix='RIG', muscleSplineName='tpMuscleSpline', controlsGrpSuffix='controls', jointsGrpSuffix='joints', rootSuffix='root', autoSuffix='auto', lockScale=True, lockJiggleAttributes=False): """ Makes a muscle spline rig :param str prefix: Prefix for the muscle setup :param str name: Name for the muscle setup :param str suffixCtrl: Suffix for controls objects of the muscle setup :param str suffixJnt: Suffix for joints objects of the muscle setup :param int numControls: Number of controls for the muscle rig setup :param float charSize: Number that controls the global scale of the muscle setup :param int numControls: Number of control curves for the muscle setup :param str controlType: Name of the control type we want to use for the controls (cube, circleY, null) :param int numDrivens: Number of deformations joints for the muscle setup :param str drivenType: Name of the control type we want to use for the controls (cube, circleY, null) :param bool constrainMid: True if you want to constraint the mid control to the start and end controls :return: None """ test = pm.pluginInfo('MayaMuscle.mll', query=True, loaded=True) if not pm.pluginInfo('MayaMuscle.mll', query=True, loaded=True): print 'Maya Muscle plugin is not loaded. Trying to load ...' try: pm.loadPlugin('MayaMuscle.mll') except: pm.error('Impossible to load Maya Muscle plugin ...') return baseName = name if not pm.objExists(mainSetName): pm.sets(name=mainSetName, empty=True) setRig = 'set' + baseName + rigSetSuffix if not pm.objExists(setRig): pm.sets(name=setRig, empty=True) pm.sets(setRig, include=mainSetName) if pm.objExists(muscleSplineName + '_' + baseName) or pm.objExists( baseName + '_' + muscleSplineName + '_' + suffixGrp): msgBox = QMessageBox() msgBox.setWindowTitle('Muscle/Spline Already Exists') msgBox.setText( 'A Muscle or Spline with the given name "Spline" already exists.\nPlease choose a different name.' ) msgBox.exec_() pm.error( 'Muscle spline {0} already exists'.format(baseName + '_' + muscleSplineName)) return False # Make main group self.mainGrp = pm.group(name=baseName + '_' + muscleSplineName + '_' + suffixGrp, empty=True, world=True) pm.sets(setRig, include=self.mainGrp) # Create spline node self.splineNode = pm.createNode('cMuscleSpline', name=baseName + '_' + muscleSplineName + 'Shape') self.splineNodeXForm = pm.rename( pm.listRelatives(self.splineNode, parent=True, type='transform'), baseName + '_' + muscleSplineName) self.splineNodeXForm.inheritsTransform.set(False) pm.parent(self.splineNodeXForm, self.mainGrp) for attr in ['DISPLAY', 'TANGENTS', 'LENGTH']: pm.setAttr(self.splineNode + '.' + attr, lock=True) for xform in ['t', 'r', 's']: for axis in ['x', 'y', 'z']: pm.setAttr(self.splineNodeXForm + '.' + xform + axis, lock=True, keyable=False) pm.connectAttr("time1.outTime", self.splineNode + '.inTime', force=True) pm.sets(setRig, include=self.splineNode) # Make some interesting attributes of the cMuscleSpline node available to the user through channel box pm.addAttr(self.splineNode, longName='curLen', keyable=True) pm.addAttr(self.splineNode, longName='pctSquash', keyable=True) pm.addAttr(self.splineNode, longName='pctStretch', keyable=True) self.splineNode.curLen.connect(self.splineNode.outLen) self.splineNode.pctSquash.connect(self.splineNode.outPctSquash) self.splineNode.pctStretch.connect(self.splineNode.outPctStretch) # Create group for the controls self.controlsGrp = pm.group(name=baseName + '_' + muscleSplineName + '_' + controlsGrpSuffix, empty=True, world=True) self.controlsGrp.inheritsTransform.set(True) pm.parent(self.controlsGrp, self.mainGrp) for xform in ['t', 'r', 's']: for axis in ['x', 'y', 'z']: pm.setAttr(self.controlsGrp + '.' + xform + axis, lock=True, keyable=False) pm.sets(setRig, include=self.controlsGrp) # Create drivens group self.drivensGrp = pm.group(name=baseName + '_' + muscleSplineName + '_' + jointsGrpSuffix, empty=True, world=True) self.drivensGrp.inheritsTransform.set(False) pm.parent(self.drivensGrp, self.mainGrp) for xform in ['t', 'r', 's']: for axis in ['x', 'y', 'z']: pm.setAttr(self.drivensGrp + '.' + xform + axis, lock=True, keyable=False) pm.sets(setRig, include=self.drivensGrp) # Create controls self.controls = [] self.consGrps = [] self.rootGrps = [] for i in range(numControls): ctrlName = baseName + '_' + muscleSplineName + '_' + str( i) + '_' + suffixCtrl ctrl = tpMuscleSplineCtrl(ctrlName, controlType, charSize) self.controls.append(ctrl) # Create root and auto groups rootGrp = pm.group(name=ctrlName.replace(suffixCtrl, rootSuffix), empty=True, world=True) consGrp = pm.group(name=ctrlName.replace(suffixCtrl, autoSuffix), empty=True, world=True) self.rootGrps.append(rootGrp) self.consGrps.append(consGrp) ctrl.root = rootGrp ctrl.auto = consGrp # Place the controls and its groups vertically on the Y axis for toTransform in [ctrl.control, rootGrp, consGrp]: pm.xform(toTransform, translation=(0, i * charSize, 0), absolute=True, worldSpace=True) # Parent all the controls pm.parent(ctrl.control, consGrp) pm.parent(consGrp, rootGrp) pm.parent(rootGrp, self.controlsGrp) # Color the controls if ctrl.control.getShape() is not None: ctrl.control.getShape().overrideEnabled.set(True) ctrl.control.getShape().overrideColor.set(17) # Make middle controls jiggle by default jiggle = 1.0 if (i == 0 or i == numControls - 1): jiggle = 0.0 pm.addAttr(ctrl.control, longName='tangentLength', shortName='tanlen', minValue=0.0, defaultValue=1.0, keyable=True) pm.addAttr(ctrl.control, longName='jiggle', shortName='jig', defaultValue=jiggle, keyable=True) pm.addAttr(ctrl.control, longName='jiggleX', shortName='jigX', defaultValue=jiggle, keyable=True) pm.addAttr(ctrl.control, longName='jiggleY', shortName='jigY', defaultValue=jiggle, keyable=True) pm.addAttr(ctrl.control, longName='jiggleZ', shortName='jigZ', defaultValue=jiggle, keyable=True) pm.addAttr(ctrl.control, longName='jiggleImpact', shortName='jigimp', defaultValue=(0.5 * jiggle), keyable=True) pm.addAttr(ctrl.control, longName='jiggleImpactStart', shortName='jigimpst', defaultValue=1000, keyable=True) pm.addAttr(ctrl.control, longName='jiggleImpactStop', shortName='jigimpsp', defaultValue=0.001, keyable=True) pm.addAttr(ctrl.control, longName='cycle', shortName='cyc', minValue=1.0, defaultValue=12.0, keyable=True) pm.addAttr(ctrl.control, longName='rest', shortName='rst', minValue=1.0, defaultValue=24.0, keyable=True) for attr in [ 'tangentLength', 'jiggle', 'jiggleX', 'jiggleX', 'jiggleY', 'jiggleZ', 'jiggleImpact', 'jiggleImpactStart', 'jiggleImpactStop', 'cycle', 'rest' ]: pm.setAttr(ctrl.control + '.' + attr, lock=lockJiggleAttributes) if lockScale: # Unlock controls scale for xform in ['s']: for axis in ['x', 'y', 'z']: pm.setAttr(ctrl.control + '.' + xform + axis, lock=True, keyable=False) pm.setAttr(ctrl.control + '.visibility', lock=True, keyable=False) # Connect the attributes pm.connectAttr( ctrl.control + '.worldMatrix', self.splineNode + '.controlData[' + str(i) + '].insertMatrix') pm.connectAttr( ctrl.control + '.tangentLength', self.splineNode + '.controlData[' + str(i) + '].tangentLength') pm.connectAttr( ctrl.control + '.jiggle', self.splineNode + '.controlData[' + str(i) + '].jiggle') pm.connectAttr( ctrl.control + '.jiggleX', self.splineNode + '.controlData[' + str(i) + '].jiggleX') pm.connectAttr( ctrl.control + '.jiggleY', self.splineNode + '.controlData[' + str(i) + '].jiggleY') pm.connectAttr( ctrl.control + '.jiggleZ', self.splineNode + '.controlData[' + str(i) + '].jiggleZ') pm.connectAttr( ctrl.control + '.jiggleImpact', self.splineNode + '.controlData[' + str(i) + '].jiggleImpact') pm.connectAttr( ctrl.control + '.jiggleImpactStart', self.splineNode + '.controlData[' + str(i) + '].jiggleImpactStart') pm.connectAttr( ctrl.control + '.jiggleImpactStop', self.splineNode + '.controlData[' + str(i) + '].jiggleImpactStop') pm.connectAttr( ctrl.control + '.cycle', self.splineNode + '.controlData[' + str(i) + '].cycle') pm.connectAttr( ctrl.control + '.rest', self.splineNode + '.controlData[' + str(i) + '].rest') # # For each in-between control (not in the start and end control) we will use the constraint group above it and constraint it to the top and bottom # # groups. Doing this, mid controls will follow top and end controls. Also, we will aim constraints so in-between controls always aim starta and end # # controls blend = "" if constrainMid: for i in range(1, numControls - 1): # Get point constraint weight and create point constraint for intermediate controls pct = 1.0 * i / (numControls - 1.0) pm.pointConstraint(self.controls[0].control, self.consGrps[i], weight=(1.0 - pct)) pm.pointConstraint(self.controls[numControls - 1].control, self.consGrps[i], weight=pct) # Create aim groups # We create one for the forward aim and another one for the back aim, then we have to # orient between both at the right amount grpAimFwd = pm.group(name=baseName + '_aimFwd_' + str(i) + '_' + suffixGrp, empty=True, world=True) grpAimBck = pm.group(name=baseName + '_aimBack_' + str(i) + '_' + suffixGrp, empty=True, world=True) for grp in [grpAimFwd, grpAimBck]: snap(grp, self.controls[i].control) pm.sets(setRig, include=[self.rootGrps[i], grpAimFwd, grpAimBck]) # Aim Forward group will aim the last control and Aim Back group will aim to the first control # This will give a twist behaviour on the aim groups aCons = pm.aimConstraint( self.controls[numControls - 1].control, grpAimFwd, weight=1, aimVector=(0, 1, 0), upVector=(1, 0, 0), worldUpVector=(1, 0, 0), worldUpType="objectrotation", worldUpObject=self.controls[numControls - 1].control) bCons = pm.aimConstraint( self.controls[0].control, grpAimBck, weight=1, aimVector=(0, -1, 0), upVector=(1, 0, 0), worldUpVector=(1, 0, 0), worldUpType="objectrotation", worldUpObject=self.controls[0].control) pm.sets(setRig, include=[aCons, bCons]) # Now we drive the aims with the up info (we do this, only once) ... if i == 1: # We make sure that the up axis attribute exists on the cMuscleNode ... if pm.objExists(self.splineNode + '.upAxis') != True: pm.addAttr(self.splineNode, at="enum", longName="upAxis", enumName="X-Axis=0:Z-Axis=1", keyable=True) # We use this blend to select the return the Z axis (vector 0,0,1) or X axis (vector 1,0,0) blend = pm.createNode('blendColors', name=baseName + '_' + muscleSplineName + '_Aim_blend') self.splineNode.upAxis.connect(blend.blender) blend.color1.set(0, 0, 1) blend.color2.set(1, 0, 0) pm.sets(setRig, include=blend) # Each aim constraint up vector will follow the up axis attribute of the cMuscleSpineNode # We can switch between Z or X up axis if you get flipping when rotatig controls for cons in [aCons, bCons]: blend.output.connect(cons.upVector) blend.output.connect(cons.worldUpVector) # Aim groups also will follow start and end controls (so it will be positioned at the same position of its respective control) pConsFwd = pm.pointConstraint(self.controls[0].control, grpAimFwd, weight=(1.0 - pct)) pConsFwd = pm.pointConstraint(self.controls[numControls - 1].control, grpAimFwd, weight=pct) pConsBack = pm.pointConstraint(self.controls[0].control, grpAimBck, weight=(1.0 - pct)) pConsBack = pm.pointConstraint(self.controls[numControls - 1].control, grpAimBck, weight=pct) pm.sets(setRig, include=[pConsFwd, pConsBack]) # The auto groups will follow the orientation of the aim groups # So, the controls (wihch are child of the auto groups) will follow the aim orientaiton oCons = pm.orientConstraint(grpAimBck, self.consGrps[i], weight=(1.0 - pct)) oCons.interpType.set(2) oCons = pm.orientConstraint(grpAimFwd, self.consGrps[i], weight=pct) oCons.interpType.set(2) pm.sets(setRig, include=oCons) # At the end, we create root grops for each one of the aim groups (so its xfrorms are zeroed out) grpAimFwdRoot = pm.group(name=baseName + '_' + muscleSplineName + '_grpAimFwd_' + rootSuffix, empty=True, world=True) grpAimBckRoot = pm.group(name=baseName + '_' + muscleSplineName + '_grpAimBck_' + rootSuffix, empty=True, world=True) snap(grpAimFwdRoot, grpAimFwd) snap(grpAimBckRoot, grpAimBck) # snap(grpAimFwd, grpAimFwdRoot) # snap(grpAimBck, grpAimBckRoot) pm.sets(setRig, include=[grpAimFwdRoot, grpAimBckRoot]) pm.parent(grpAimFwdRoot, self.rootGrps[i]) pm.parent(grpAimFwd, grpAimFwdRoot) pm.parent(grpAimBckRoot, self.rootGrps[i]) pm.parent(grpAimBck, grpAimFwdRoot) self.drivens = [] for i in range(numDrivens): # Get normalized values between 0 and 1 and the correct name u = i / (numDrivens - 1.0) name = baseName + '_' + muscleSplineName + '_' + str( i) + '_' + suffixDrv if drivenType == "joint": self.drivens.append(pm.joint(name=name)) elif drivenType == "circleY": ctrl = pm.circle(name=name, degree=3, center=[0, 0, 0], normal=[0, 1, 0], sweep=360, radius=1.0 * charSize, useTolerance=False, sections=8, constructionHistory=False)[0] self.drivens.append(ctrl) else: self.drivens.append(pm.group(name=name, empty=True, world=True)) pm.select(clear=True) pm.addAttr(self.drivens[i], longName="uValue", minValue=0.0, maxValue=1.0, defaultValue=u, keyable=True) pm.parent(self.drivens[i], self.drivensGrp) pm.sets(setRig, include=self.drivens[i]) pm.connectAttr(self.drivens[i] + '.uValue', self.splineNode + '.readData[' + str(i) + '].readU', force=True) pm.connectAttr(self.drivens[i] + '.rotateOrder', self.splineNode + '.readData[' + str(i) + '].readRotOrder', force=True) pm.connectAttr(self.splineNode + '.outputData[' + str(i) + '].outTranslate', self.drivens[i] + '.translate', force=True) pm.connectAttr(self.splineNode + '.outputData[' + str(i) + '].outRotate', self.drivens[i] + '.rotate', force=True) len = self.splineNode.outLen.get() self.splineNode.lenDefault.set(len) self.splineNode.lenSquash.set(len * 0.5) self.splineNode.lenStretch.set(len * 2.0) pm.select(self.mainGrp) return self.splineNode
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 create(cntrlList=[], axis='x', num=0): if not cntrlList: cntrlList = pm.selected() if not cntrlList: pm.warning('Must select controls to create sine tool on') return #variables cubePos = -.5 axis = axis.upper() time = pm.PyNode('time1') cubeList = [] digitList = [] sineList = pm.ls('*sineTool_grp*', type='transform') #num are the cubes, if its 0 the the cubes will be the same as the cntrls (default accuracy) if num == 0: num = len(cntrlList) #distance between each cube if num == 1: cubeDist = 0.0 else: cubeDist = 1 / (float(num - 1)) #figure out what prefix our SineTool will have, allows up to 10 sinetool in one scene at a time if sineList != []: for sine in sineList: for x in sine: if x.isdigit() == True: digitList.append(x) prefix = 'SN' + str(int(max(digitList)) + 1) + axis else: prefix = 'SN1' + axis #master group sineTool = pm.group(name=prefix + 'sineTool_grp', empty=True) #Sine Cntrl sineCntrl = pm.circle(n=prefix + 'sineController', ch=False)[0] pm.parent(sineCntrl, sineTool) #adding atributes to sineCntrl pm.addAttr(sineCntrl, longName='outputVisibility', k=True, min=0, max=1, dv=1, at='bool') pm.addAttr(sineCntrl, longName='resultVisibility', k=True, min=0, max=1, dv=1, at='bool') pm.addAttr(sineCntrl, longName='sineLength', k=True) pm.addAttr(sineCntrl, longName='sineValue', k=True) pm.addAttr(sineCntrl, longName='sineSpeed', k=True) pm.addAttr(sineCntrl, longName='_', k=True, at='enum', en='_') pm.addAttr(sineCntrl, longName='proportion', k=True, dv=1) sineCntrl._.lock() #groups to keep everything separated sineValueMaster = pm.group(name=prefix + 'sineValue_grp', empty=True, parent=sineCntrl) outputGrp = pm.group(name=prefix + 'sineOutput_grp', empty=True, parent=sineTool) resultGrp = pm.group(name=prefix + 'sineResult_grp', empty=True, parent=sineTool) #connecting time and visibility sineMult = pm.shadingNode('multiplyDivide', n='sineSpeedMult', au=True) time.outTime >> sineMult.input1X sineCntrl.sineSpeed >> sineMult.input2X sineMult.outputX >> sineValueMaster.rz sineCntrl.outputVisibility >> sineValueMaster.visibility sineCntrl.resultVisibility >> resultGrp.visibility for i in range(num): #for the first sineValueGrp we make, parent it to the master group. Parent the rest to the previous sineValueGrp if i == 0: sineValueGrp = pm.group(name=prefix + 'sineValue_grp_' + str(1), empty=True, parent=sineValueMaster) else: sineValueGrp = pm.group(name=prefix + 'sineValue_grp_' + str(i + 1), empty=True, parent=sineValueGrp) #makes locators that will be the points in our circle sineLoc = pm.spaceLocator(name=prefix + 'sineLoc_' + str(i + 1)) pm.parent(sineLoc, sineValueGrp) sineCntrl.sineLength >> sineValueGrp.rz sineCntrl.sineValue >> sineLoc.tx #makes outputs so that we can grab the Y value of our locators in world space output = pm.group(name=prefix + 'sineOutput_' + str(i + 1), empty=True, parent=outputGrp) pm.pointConstraint(sineLoc, output) #the cube is a visual representation of our output cube = pm.polyCube(d=.1, w=.1, h=.1, ch=False, n=prefix + 'sineResult_' + str(i + 1))[0] pm.parent(cube, resultGrp) cube.tx.set(cubePos) cubePos = cubePos + cubeDist #add influence attribute to control how much each cube is influenced by our outputs pm.addAttr(sineCntrl, longName='influence_' + str(i + 1), k=True, min=0, max=1, dv=((i + 1) / float(num))**2) influenceMult = pm.shadingNode('multiplyDivide', n=prefix + 'influenceMult_' + str(i + 1), au=True) output.ty >> influenceMult.input1X pm.connectAttr(sineCntrl + '.influence_' + str(i + 1), influenceMult.input2X) influenceMult.outputX >> cube.ty cubeList.append(cube) #place the sine tool in the middle of our selected cntrls and gets the distance between the cntrls distance = placeSine(sineTool, cntrlList) #set the attribute proportion to be distance/10 sineCntrl.proportion.set(distance / float(10)) #create our offsets that are the groups that will be rotated, these will be parents of our cntrls offsetList = offsetCreator(cntrlList, name=prefix + 'offset') for cntrl, offset in zip(cntrlList, offsetList): distanceList = [] #for each cntrl, get how far each cube is from the cntrl for cube in cubeList: distanceList.append(getDistance(cube, cntrl)) #the minCube is the closest cube to the current cntrl minCube = cubeList[distanceList.index(min(distanceList))] #connect each cube with our offsets based on whatever axis we specified proportionMult = pm.shadingNode('multiplyDivide', n=prefix + 'sineProportion' + offset + 'Mult', au=True) pm.connectAttr(minCube + '.ty', proportionMult.input1X) pm.connectAttr(sineCntrl.proportion, proportionMult.input2X) pm.connectAttr(proportionMult.outputX, offset + '.rotate' + axis) pm.select(clear=True) pm.select(sineCntrl)
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(target): target = pointConstraint(target, q=True, tl=True)[0] extra = None constraint = None return target, extra, constraint
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 getTargets(target): constraints = listRelatives(target, type='pointConstraint') target = tuple(pointConstraint(constraints[0], q=True, tl=True)) extra = None constraint = None return target, extra, constraint
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 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 clusLoc2(debugLevel="DEBUG"): """create locator or position selected joint at a centroid position in a ring of edges how to use: from rigWorkshop.ws_user.jun.utils import clusLoc reload(clusLoc) clusLoc.clusLoc2() """ # set debug level logger.setLevel(debugLevel) sel = pm.selected(flatten=True) verts = [] edges = [] TRNs = [] for s in sel: sortMe = s.__class__.__name__ if sortMe == "Joint" or sortMe == "transform": TRNs.append(s) if sortMe == "MeshVertex": verts.append(s) if sortMe == "MeshEdge": edges.append(s) # convert egdes to vertex if edges: edgeVerts = list( set(sum([list(e.connectedVertices()) for e in edges], []))) verts = verts + edgeVerts logger.debug("verts = %s" % verts) logger.debug("TRNs = %s" % TRNs) clusDef, clusTRN = pm.cluster(verts) if not TRNs: loc = pm.spaceLocator() TRNs.append(loc) logger.debug("Locator %s has been created" % TRNs) for TRN in TRNs: #hierarchy issues prepped parent = TRN.getParent() logger.debug("parent is %s " % parent) children = TRN.getChildren(type="transform") logger.debug("children is %s " % children) if parent: TRN.setParent(world=True) for child in children: child.setParent(world=True) pm.delete(pm.pointConstraint(clusTRN, TRN, mo=False)) for child in children: child.setParent(TRN) if parent: TRN.setParent(parent) pm.delete(clusTRN) logger.debug("Done!!")
def inputPoint(self, target=None, maintainOff=None): if target is None and maintainOff is None: return self._inputPoint else: self._inputPoint = pm.pointConstraint(target, self.drawnNode, mo=maintainOff)
def connectTargets(self): 'Create point constraint to all of the targets' pm.pointConstraint(self.targetList, self.name, weight=0.0)
def gizmoRigModules(): print 'Create gizmo rig modules' biped = rig_biped() biped.elbowAxis = 'ry' biped.spine(ctrlSize=6) biped.pelvis(ctrlSize=5) biped.neck(ctrlSize=2.5) biped.head(ctrlSize=5) for side in ['l', 'r']: armModule = biped.arm(side, ctrlSize=3) fingersModule = biped.hand(side, ctrlSize=0.5) shoulderModule = biped.shoulder(side, ctrlSize=2) biped.connectArmShoulder(side) legModule = biped.leg(side, ctrlSize=3) toesModule = biped.foot(side, ctrlSize=0.5) biped.connectLegPelvis() # make tail ''' tailModule = rig_ikChainSpline('tail', 'tailJA_JNT', ctrlSize=1, parent='pelvisJA_JNT', numIkControls=4, numFkControls=4) chainList = rig_chain('tailJOTip_JNT').chain print '====== MAKING TAIL TIP ==============' fkCtrls = fkControlChain(chainList, modify=1, scale=[1, 1, 1], directCon=1) for fk in fkCtrls: pm.parent(fk.offset, tailModule.controls) ''' tailModule = rig_ikChainSpline('tail', 'tailHiJA_JNT', ctrlSize=1, parent='pelvisJA_JNT', numIkControls=12, numFkControls=12) # tail upgrade tailJnts = pm.listRelatives('tailskeleton_GRP', type='joint') 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', [tailIK, tailFK + 'Modify1_GRP'], tailFK + '_CTRL', ['IK', 'parent'], type='parentConstraint') pm.parentConstraint('tailFKACon_GRP', 'tailBaseIKOffset_GRP', mo=True) constrainObject('tailMidAIKOffset_GRP', ['tailFKACon_GRP', 'pelvisCon_GRP', 'worldSpace_GRP'], 'tailMidAIK_CTRL', ['base', 'pelvis', 'world'], type='parentConstraint') constrainObject('tailMidBIKOffset_GRP', [ 'tailFKACon_GRP', 'tailMidAIKCon_GRP', 'pelvisCon_GRP', 'worldSpace_GRP' ], 'tailMidBIK_CTRL', ['base', 'FK', 'pelvis', 'world'], type='parentConstraint') constrainObject('tailTipIKOffset_GRP', [ 'tailFKACon_GRP', 'tailMidBIKCon_GRP', 'pelvisCon_GRP', 'worldSpace_GRP' ], 'tailTipIK_CTRL', ['base', 'FK', 'pelvis', 'world'], type='parentConstraint') tailPointer = rig_control(name='tailPointer', shape='pyramid', scale=(1, 2, 1), lockHideAttrs=['rx', 'ry', 'rz'], colour='white', parentOffset=tailModule.controls, rotateOrder=2) pm.delete(pm.parentConstraint('tailHiJEnd_JNT', tailPointer.offset)) constrainObject( tailPointer.offset, ['pelvisCon_GRP', 'spineFullBodyCon_GRP', 'worldSpace_GRP'], tailPointer.ctrl, ['pelvis', 'fullBody', 'world'], type='parentConstraint') tailPointerBase = rig_transform(0, name='tailPointerBase', type='locator', parent=tailModule.parts, target='tailFKA_CTRL').object tailPointerTip = rig_transform(0, name='tailPointerTip', 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('pelvisCon_GRP', tailPointerBase, mo=True) pm.parentConstraint(tailPointer.con, tailPointerTip, mo=True) tailPointerTop = mm.eval('rig_makePiston("' + tailPointerBase + '", "' + tailPointerTip + '", "tailPointerAim");') pm.orientConstraint(tailPointerBase.replace('LOC', 'JNT'), 'tailFKAModify2_GRP', mo=True) pm.parent('tailMidAIKOffset_GRP', 'tailMidBIKOffset_GRP', 'tailTipIKOffset_GRP', tailModule.controls) pm.parent(tailJnts, tailModule.skeleton) pm.parent('tail_cMUS', 'tailBaseIKOffset_GRP', tailPointerTop, tailModule.parts) pm.setAttr(tailModule.skeleton + '.inheritsTransform', 0) # build facial facialModule = rig_module('facial') pm.parent(facialModule.top, 'rigModules_GRP') # build shape locators for side in ['l', 'r']: muzzleCtrl = fourWayShapeControl( side + '_muzzleShape_LOC', (side + 'MuzzleUp', side + 'MuzzleDown', side + 'MuzzleForward', side + 'MuzzleBack'), 'headShapeWorld_GRP', ctrlSize=1) pm.rotate(muzzleCtrl.ctrl.cv, 0, 0, 90, r=True, os=True) pm.rotate(muzzleCtrl.ctrl.cv, -45, 0, 0, r=True, os=True) browCtrl = twoWayShapeControl(side + '_browShape_LOC', (side + 'BrowUp', side + 'BrowDown'), 'headShapeWorld_GRP', ctrlSize=0.8) pm.rotate(browCtrl.ctrl.cv, 90, 0, 0, r=True, os=True) pm.rotate(browCtrl.ctrl.cv, 0, -75, 0, r=True, os=True) blinkCtrl = oneWayShapeControl(side + '_blinkShape_LOC', side + 'Blink', 'headShapeWorld_GRP', ctrlSize=0.5) if side == 'r': pm.rotate(blinkCtrl.ctrl.cv, 0, 0, 180, r=True, os=True) #pm.move(blinkCtrl.ctrl.cv, 0, -0.4, 0, relative=True) #pm.parent( muzzleCtrl.offset, browCtrl.offset , blinkCtrl.offset ,facialModule.controls) pm.parent('headShapeWorld_GRP', facialModule.controls) pm.parentConstraint('headJA_JNT', 'headShapeWorld_GRP') # build simple controllers facialLocalWorldControllers(facialModule, 'headJAWorld_GRP', ctrlSize=0.1) pm.parentConstraint('headJA_JNT', 'headJAWorld_GRP') pm.parent('headJAWorld_GRP', facialModule.controlsSec) pm.move(pm.PyNode('noseTwk_CTRL').cv, 0.15, 0, 0, r=True, os=True) pm.scale(pm.PyNode('noseTwk_CTRL').cv, 2.5, 2.5, 2.5) # jaw control jawControl = rig_control(name='jaw', shape='circle', scale=(2, 2, 2), lockHideAttrs=['rx'], parentOffset=facialModule.controls, colour='white') pm.rotate(jawControl.ctrl.cv, -90, 0, 0, r=True, os=True) pm.move(jawControl.ctrl.cv, 2, 0, 0, r=True, os=True) pm.delete(pm.parentConstraint('jawJA_JNT', jawControl.offset)) pm.parentConstraint('headJA_JNT', jawControl.offset, mo=True) pm.parent('jawHeadOffset_LOC', jawControl.offset) pm.pointConstraint(jawControl.con, 'jawHeadOffset_LOC', mo=True) facialLoc = 'facialShapeDriver_LOC' rig_animDrivenKey(jawControl.ctrl.rotateY, (0, 35), facialLoc + '.jawOpen', (0, 1)) rig_animDrivenKey(jawControl.ctrl.rotateY, (0, -5), facialLoc + '.jawClosed', (0, 1)) rig_animDrivenKey(jawControl.ctrl.rotateZ, (0, -10), facialLoc + '.rJawSide', (0, 1)) rig_animDrivenKey(jawControl.ctrl.rotateZ, (0, 10), facialLoc + '.lJawSide', (0, 1)) pm.transformLimits(jawControl.ctrl, ry=(-5, 35), ery=(1, 1)) pm.transformLimits(jawControl.ctrl, rz=(-10, 10), erz=(1, 1)) pm.transformLimits(jawControl.ctrl, tx=(-0.1, 0.1), etx=(1, 1)) pm.transformLimits(jawControl.ctrl, ty=(-0.1, 0.1), ety=(1, 1)) pm.transformLimits(jawControl.ctrl, tz=(0, 0.1), etz=(1, 1)) upperLipCtrls = pm.ls("*upperLip*Twk*CTRL") for c in upperLipCtrls: pm.scale(c.cv, 0.6, 0.6, 0.6, r=True) pm.move(c.cv, 0, 0, 0.3, r=True) pm.move(c.cv, 0, 0.1, 0, r=True) lowerLipCtrls = pm.ls("*lowerLip*Twk*CTRL") for c in lowerLipCtrls: pm.scale(c.cv, 0.6, 0.6, 0.6, r=True) pm.move(c.cv, 0, 0, 0.3, r=True) pm.move(c.cv, 0, -0.1, 0, r=True) pm.setAttr(facialModule.parts + '.inheritsTransform', 0) pm.parent('tongueControls_GRP', facialModule.controls) # eye controls eyeModule = rig_module('eye') pm.parent(eyeModule.top, 'rigModules_GRP') eyeControl = rig_control(name='eye', shape='circle', modify=1, parentOffset=eyeModule.controls, scale=(1, 1, 1), rotateOrder=2, lockHideAttrs=['rx', 'ry', 'rz']) pm.delete(pm.parentConstraint('eyeAim_LOC', eyeControl.offset)) #pm.parentConstraint( 'headCon_GRP', eyeControl.offset, mo=True ) pm.rotate(eyeControl.ctrl.cv, 90, 0, 0, r=True, os=True) pm.select(eyeControl.ctrl.cv[1], r=True) pm.select(eyeControl.ctrl.cv[5], add=True) pm.scale(0, 0, 0, r=True) constrainObject(eyeControl.offset, ['headCon_GRP', 'worldSpace_GRP'], eyeControl.ctrl, ['head', 'world'], type='parentConstraint') pm.parent('eyeAim_LOC', eyeControl.con) pm.hide('eyeAim_LOC') for side in ('l', 'r'): eyeBase = rig_transform(0, name=side + '_eyeBase', type='locator', target=side + '_eyeJA_JNT', parent=eyeModule.parts).object eyeTarget = rig_transform(0, name=side + '_eyeTarget', type='locator', target='eyeAim_LOC', parent=eyeModule.parts).object pm.parentConstraint('headJA_JNT', eyeBase, mo=True) pm.parentConstraint('eyeAim_LOC', eyeTarget, mo=True) eyeAimTop = mm.eval('rig_makePiston("' + eyeBase + '", "' + eyeTarget + '", ' '"' + side + '_eyeAim");') pm.orientConstraint(side + '_eyeBase_JNT', side + '_eyeJA_JNT', mo=True) pm.parent(eyeAimTop, eyeModule.parts) upperEyeControl = rig_control( side=side, name='eyeUpper', shape='circle', modify=1, parentOffset=eyeModule.controlsSec, scale=(0.1, 0.1, 0.1), constrain=side + '_upperEyeLidRotateOffset_GRP', rotateOrder=2, directCon=1, lockHideAttrs=['tx', 'ty', 'tz', 'rx', 'ry']) pm.delete( pm.parentConstraint(side + '_eyeLocalOffset_GRP', upperEyeControl.offset)) pm.delete( pm.pointConstraint(side + '_eyeJA_JNT', upperEyeControl.offset)) lowerEyeControl = rig_control( side=side, name='eyeLower', shape='circle', modify=1, parentOffset=eyeModule.controlsSec, scale=(0.1, 0.1, 0.1), constrain=side + '_lowerEyeLidRotateOffset_GRP', rotateOrder=2, directCon=1, lockHideAttrs=['tx', 'ty', 'tz', 'rx', 'ry']) pm.delete( pm.parentConstraint(side + '_eyeLocalOffset_GRP', lowerEyeControl.offset)) pm.delete( pm.pointConstraint(side + '_eyeJA_JNT', lowerEyeControl.offset)) ''' eyeControl = rig_control(side=side, name='eye', shape='circle', modify=1, parentOffset=eyeModule.controls, scale=(1,1,1), rotateOrder=2, lockHideAttrs=['rx', 'ry', 'rz']) ''' # ear controls chainEars = rig_chain(side + '_earJA_JNT').chain earCtrls = fkControlChain( [side + '_earJA_JNT', side + '_earJB_JNT', side + '_earJC_JNT'], modify=0, scale=[0.8, 0.8, 0.8], directCon=0) # parent ears to headJA_JNT for ctrl in earCtrls: pm.parent(ctrl.parent, 'headControlsSecondary_GRP')
def cyroShoulderUpgrade(side='', ctrlSize=1): name = side + '_quadShoulder' module = rig_module(name) ctrlSizeHalf = [ctrlSize / 2.0, ctrlSize / 2.0, ctrlSize / 2.0] ctrlSize = [ctrlSize, ctrlSize, ctrlSize] shoulderControl = rig_control(side=side, name='quadShoulder', shape='pyramid', targetOffset=side + '_clavicleJA_JNT', modify=1, parentOffset=module.controls, lockHideAttrs=['rx', 'ry', 'rz'], scale=ctrlSize, rotateOrder=0) clavPos = pm.xform(side + '_clavicleJA_JNT', translation=True, query=True, ws=True) armPos = pm.xform(side + '_scapulaJA_JNT', translation=True, query=True, ws=True) clavLength = lengthVector(armPos, clavPos) if side == 'l': pm.move(pm.PyNode(shoulderControl.offset), clavLength, 0, 0, r=True, os=True) else: pm.move(pm.PyNode(shoulderControl.offset), -1 * clavLength, 0, 0, r=True, os=True) pm.rotate(pm.PyNode(shoulderControl.offset), 0, 0, -90, r=True, os=True) pm.parentConstraint('spineJF_JNT', shoulderControl.offset, mo=True) clavicleAim = rig_transform(0, name=side + '_clavicleAim', type='locator', parent=module.parts, target=side + '_clavicleJA_JNT').object armAim = rig_transform(0, name=side + '_quadShoulderAim', type='locator', parent=module.parts).object pm.pointConstraint('spineJF_JNT', clavicleAim, mo=True) pm.pointConstraint(shoulderControl.con, armAim) quadShoulderAimTop = mm.eval('rig_makePiston("' + clavicleAim + '", "' + armAim + '", "' + side + '_quadShoulderAim");') #pm.orientConstraint( clavicleAim, side+'_shoulder_CTRL', mo=True ) pm.delete(pm.listRelatives(side + '_shoulderOffset_GRP', type='constraint')) pm.parentConstraint(clavicleAim, side + '_shoulderOffset_GRP', mo=True) pm.addAttr(shoulderControl.ctrl, longName='followArm', at='float', k=True, min=0, max=10, defaultValue=1) pm.connectAttr(shoulderControl.ctrl.followArm, side + '_shoulder_CTRL.followArm') baseLimit = 15 pm.transformLimits(shoulderControl.ctrl, tx=(-1 * baseLimit, baseLimit), etx=(1, 1)) pm.transformLimits(shoulderControl.ctrl, ty=(-1 * baseLimit, baseLimit), ety=(1, 1)) pm.transformLimits(shoulderControl.ctrl, tz=(-1 * baseLimit, baseLimit), etz=(1, 1)) scapulaControl = rig_control(side=side, name='quadScapula', shape='box', targetOffset=side + '_scapulaJEnd_JNT', modify=1, parentOffset=module.controls, lockHideAttrs=['rx', 'ry', 'rz'], scale=ctrlSize, rotateOrder=0) pm.delete( pm.orientConstraint(side + '_scapulaJA_JNT', scapulaControl.offset)) scapulaAim = rig_transform(0, name=side + '_quadScapulaAim', type='locator', parent=module.parts).object scapulaEndAim = rig_transform(0, name=side + '_quadScapulaEndAim', type='locator', parent=module.parts).object pm.delete(pm.parentConstraint(side + '_scapulaJA_JNT', scapulaAim)) pm.pointConstraint(side + '_clavicleJA_JNT', scapulaAim, mo=True) pm.pointConstraint(scapulaControl.con, scapulaEndAim) pm.delete(pm.orientConstraint(side + '_scapulaJA_JNT', scapulaEndAim)) quadScapulaAimTop = mm.eval('rig_makePiston("' + scapulaAim + '", "' + scapulaEndAim + '", "' + side + '_quadScapulaAim");') #pm.parentConstraint( side+'_clavicleJA_JNT', 'spineJE_JNT', scapulaControl.offset, mo=True ) constrainObject(scapulaControl.offset, [side + '_clavicleJA_JNT', 'spineJE_JNT'], '', [], type='parentConstraint', doSpace=0, setVal=(0.5, 1)) baseLimit = 5 pm.transformLimits(scapulaControl.ctrl, tx=(-1 * baseLimit, baseLimit), etx=(1, 1)) pm.transformLimits(scapulaControl.ctrl, ty=(-1 * baseLimit, baseLimit), ety=(1, 1)) pm.transformLimits(scapulaControl.ctrl, tz=(-1 * baseLimit, baseLimit), etz=(1, 1)) pm.orientConstraint(scapulaAim, side + '_scapulaJA_JNT', mo=True) pm.hide(side + '_shoulderOffset_GRP') pm.parent(quadShoulderAimTop, quadScapulaAimTop, module.parts)
def AddWorldLocalSpace(**kwargs): """ select control object and a world control object, then run this. see script editor for more info. 1. first parent your control under the default control ( for example: parent your hand_IK_ctrl under torso_ctrl ) 2. select control object that you want to add the "local-world" space switch for ( for example: hand_IK_ctrl ) 3. shift select the object you as world ( for example: main_control or COG_control ) 4. run this """ ctrl = kwargs.setdefault( 'ctrl') # object you want to create space switch for worldCtrl = kwargs.setdefault('worldCtrl') # world space node point = kwargs.setdefault(False) orient = kwargs.setdefault(False) objs = pm.ls(sl=True) if len(objs) != 2: pm.error(helpMessage) ctrl = objs[0] worldCtrl = objs[1] # create three zero groups matching the transfrom of selected control zeroGrp = pm.group(empty=True, name='%s_space' % ctrl.name()) pm.delete(pm.pointConstraint(ctrl, zeroGrp)) pm.delete(pm.orientConstraint(ctrl, zeroGrp)) localGrp = pm.duplicate(zeroGrp)[0] pm.rename(localGrp, '%s_spacelocal' % ctrl.name()) worldGrp = pm.duplicate(zeroGrp)[0] pm.rename(worldGrp, '%s_spaceworld' % ctrl.name()) # parent one under first parent and the other under second parent ctrlParent = ctrl.getParent() pm.parent(zeroGrp, ctrlParent) pm.parent(localGrp, ctrlParent) pm.parent(worldGrp, worldCtrl) pm.parent(ctrl, zeroGrp) # orient constraint zero group with two copied nulls as drivers if orient: const = pm.orientConstraint(worldGrp, localGrp, zeroGrp) elif point: const = pm.pointConstraint(worldGrp, localGrp, zeroGrp) else: #parent const = pm.parentConstraint(worldGrp, localGrp, zeroGrp) # add parentTo attribute with value '---------' and lock it pm.addAttr(ctrl, ln='parentTo', keyable=True, at="enum", en='---------') pm.setAttr(ctrl.parentTo, lock=True) # make world_local attribute with the range 0-1 and connect it second weight of orient constraint pm.addAttr(ctrl, ln='world_local', nn='world <---> local', keyable=True, at="double", min=0.0, max=1.0) ctrl.world_local >> const.attr(('%sW1' % localGrp.name())) # create reverse and connect it to second weight revNode = pm.createNode('reverse', name='%s_worldlocal_rev' % ctrl.name()) ctrl.world_local >> revNode.inputX revNode.outputX >> const.attr('%sW0' % worldGrp.name())