def mkControlObjects(self): if not mc.objExists(self.handles[-1]): self.handles[-1]=mc.createNode('transform',n=uniqueNames(self.name[-1])) mc.xform(self.handles[-1],ws=True,a=True,m=mc.xform(self.ArcCtrl.handles[-1],q=True,ws=True,m=True)) mc.xform(self.handles[-1],ws=True,a=True,piv=mc.xform(self.ArcCtrl.handles[-1],q=True,a=True,ws=True,piv=True)[:3]) if 'type' not in self.handleOptions[-1]: self.handleOptions[-1]['type']=self.handleType[-1] if 'radius' not in self.handleOptions[-1]: self.handleOptions[-1]['radius']=self.radius self.handleShape[-1]=Handle(self.handles[-1],**self.handleOptions[-1]) if mc.objExists(self.parent[-1]): mc.parent(self.handles[-1],self.parent[-1]) if mc.objExists(self.softParent[-1]): self.parentSpace[-1]=ParentSpace(self.handles[-1],self.softParent[-1]) for bp in getBindPoses(self.jointHierarchy): mc.dagPose(self.parentSpace[-1],a=True,n=bp) mc.makeIdentity(self.handles[-1],apply=True,t=True)#,r=True) mc.addAttr(self.handles[-1],ln='stretch',at='float',min=0,k=1,dv=self.stretch) mc.addAttr(self.handles[-1],ln='squash',at='float',min=0,max=1,k=1,dv=self.squash) mc.addAttr(self.handles[-1],ln='arcWeight',at='float',min=0,max=1,k=1,dv=self.arcWeight) mc.addAttr(self.handles[-1],ln='width',at='float',min=0.0001,k=1,dv=self.width) mc.connectAttr(self.handles[-1]+'.stretch',self.ArcCtrl.handles[-1]+'.stretch',f=True) mc.connectAttr(self.handles[-1]+'.squash',self.ArcCtrl.handles[-1]+'.squash',f=True) mc.connectAttr(self.handles[-1]+'.arcWeight',self.ArcCtrl.handles[-1]+'.arcWeight',f=True) mc.connectAttr(self.handles[-1]+'.width',self.ArcCtrl.handles[0]+'.width',f=True) if self.curl: mc.addAttr(self.handles[-1],ln='curl',at='doubleAngle',k=1,dv=0) for r in removeAll(self.jointHierarchy,self.rivet): axis='x' longestAxisLen=0 for a in ['x','y','z']: axisLen=abs(mc.getAttr(r+'.t'+a)) if axisLen>longestAxisLen: longestAxisLen=axisLen axis=a behaviorMirrored=False try: parentJoint=mc.listRelatives(r,p=True)[0] oppositeJoint=removeAll(r,mc.listRelatives(parentJoint,c=True,type='joint'))[0] for a in ['x','y','z']: if\ ( abs(180-abs(abs(mc.getAttr(r+'.jo'+a))-abs(mc.getAttr(oppositeJoint+'.jo'+a))))<5 ): behaviorMirrored=True break except: pass pcr=mc.listConnections(r+'.rx',type='parentConstraint')[0] pcTargets=mc.parentConstraint(pcr,q=True,tl=True) pcIDs=[] nsc=listNodeConnections(pcr,s=False,d=True) for n in range(0,len(nsc)): if len(nsc[n])==2 and mc.objExists(nsc[n][-1]): pcID=getIDs(nsc[n][-1]) if isinstance(pcID,int): pcIDs.append(pcID) pcIDs=removeDuplicates(pcIDs) pcIDs.sort() pcID=pcIDs[-1] pma=mc.createNode('plusMinusAverage') if mc.getAttr(r+'.uPos')>50: mc.setAttr(pma+'.op',2) if\ ( (behaviorMirrored and parentJoint!=self.jointHierarchy[-1]) ): mc.setAttr(pma+'.op',1) if mc.getAttr(r+'.uPos')<50: mc.setAttr(pma+'.op',1) if\ ( behaviorMirrored ): mc.setAttr(pma+'.op',2) mc.setAttr(pma+'.i1[0]',mc.getAttr(pcr+'.tg['+str(pcID)+'].tor'+axis)) mc.setAttr(pcr+'.tg['+str(pcID)+'].tor'+axis,lock=False) mc.connectAttr(self.handles[-1]+'.curl',pma+'.i1[1]') mc.connectAttr(pma+'.o1',pcr+'.tg['+str(pcID)+'].tor'+axis) mc.parentConstraint(self.handles[-1],self.ArcCtrl.handles[-1],mo=True) mc.scaleConstraint(self.handles[-1],self.ArcCtrl.handles[-1],sk=('x','y'),mo=True) for bp in getBindPoses(self.jointHierarchy): mc.dagPose(self.handles[-1],a=True,n=bp) mc.setAttr(self.handles[-1]+'.sy',k=False,lock=True) mc.setAttr(self.handles[-1]+'.sx',k=False,lock=True) if not self.spread: mc.setAttr(self.handles[-1]+'.sz',k=False,lock=True) mc.setAttr(self.handles[-1]+'.v',k=False,cb=True) for bp in getBindPoses(self.jointHierarchy): mc.dagPose(self.handles[-1],a=True,n=bp)
def __init__(self,*args,**keywords): #check to make sure unique names are used in scene uniqueNames(iterable(mc.ls(type='dagNode')),re=True) # default options self.radius=1 self.arcWeight=.75 self.handles=['ArcIKCtrl#'] self.parent=['|'] self.handleType=['doubleEllipse'] self.handleOptions=[{}] self.softParent=[''] self.name='' self.squash=20 self.stretch=20 self.width=1 self.allowScale=False # not functional self.minWidth=0 self.maxWidth=5 self.spread=False #requires ribs self.curl=False #requires ribs self.wrap=False self.shortNames=\ { 'n':'name', 'ht':'handleType', 'ho':'handleOptions', 'sp':'softParent', 'p':'parent', 'spr':'spread', 'c':'curl' } # attributes self.handleShape=[''] self.parentSpace=[''] for k in keywords: if k in self.__dict__: exec('self.'+k+'=keywords[k]') elif k in self.shortNames: exec('self.'+self.shortNames[k]+'=keywords[k]') self.handles=iterable(self.handles) self.parent=iterable(self.parent) self.handleType=iterable(self.handleType) self.softParent=iterable(self.softParent) self.name=iterable(self.name) if isinstance(self.handleOptions,dict): self.handleOptions=[self.handleOptions] # parse arguments if len(args)==0: args=mc.ls(sl=True,fl=True) sel=[] for a in args: sel.extend(iterable(a)) self.jointHierarchy=hierarchyBetween([sel[0],sel[-1]],type='joint') if ('radius' not in keywords) and ('r' not in keywords): hDist=distanceBetween(self.jointHierarchy[0],self.jointHierarchy[-1]) self.radius=hDist/3 self.ArcCtrl=ArcCtrl\ ( self.jointHierarchy, p=[self.jointHierarchy[0],'.'], stretch=self.stretch, squash=self.squash, arcWeight=self.arcWeight, createSurface=True, scaleLength=True ) self.constrainJoints() self.mkControlObjects() self[:]=self.handles
def __init__(self,*args,**keywords): # default options self.name='limb' self.stretch=20 self.squash=0 self.twist=True # performs auto detect self.sway=True self.switch='ik' # initial ik/fk switch state self.handleOptions=[{'type':'doubleEllipse','spin':-180},{'type':'doubleEllipse','spin':-90},{'type':'doubleEllipse'},{'type':'locator'}] self.tol=1.0 # angle tolerance for preferred angles self.parent='' self.shortNames=\ { 'n':'name', 'p':'parent', 'sp':'softParent', 'co':'controlObjects', 'ho':'handleOptions' } # attributes self.controlObjects=['','','',''] self.bindPoses=[] self.joints=[] self.group='' self.orientAxis='' self.bendAxis='' self.poleAxis='' self.ctrlJoints=[] self.handles=[] self.endEffector='' self.ikHandle='' self.jointParent='' self.jointParent='' self.originalRotations={} self.bendDirection=0 self.poleVector=[] self.poleVectorWorld=[] self.upVector=[] self.aimVector=[] self.parentSpaces=[] for k in keywords: if k in self.__dict__: exec('self.'+k+'=keywords[k]') elif k in self.shortNames: exec('self.'+self.shortNames[k]+'=keywords[k]') uniqueNames(re=True) if len(args)==0: args=mc.ls(sl=True) sel=[] for a in args: sel.extend(iterable(a)) sel=hierarchyOrder(sel) # parse options defualtHandleOptions=[{'type':'doubleEllipse','spin':-180},{'type':'doubleEllipse','spin':-90},{'type':'doubleEllipse'},{'type':'locator'}] i=len(self.handleOptions) while len(self.handleOptions)<4: self.handleOption.append(defualtHandleOptions[i]) i+=1 if isinstance(self.handleOptions,dict): self.handleOptions=[self.handleOptions,self.handleOptions,self.handleOptions] elif isIterable(self.handleOptions): if len(self.handleOptions)==0: self.handleOptions.append({}) while len(self.handleOptions)<3: self.handleOptions.append(self.handleOptions[-1]) else: self.handleOptions=[{},{},{}] self.controlObjects=iterable(self.controlObjects) self.orientAxis=self.orientAxis.lower() self.baseTwist='' self.hierarchy=[] if len(sel)>2: for j in sel[:-1]: if len(hierarchyBetween(j,sel[-1]))>len(self.hierarchy): self.hierarchy=hierarchyBetween(j,sel[-1]) closest=9e999 for s in removeAll([self.hierarchy[0],self.hierarchy[-1]],sel): if\ ( len(iterable(mc.listRelatives(self.hierarchy[0],p=True)))==0 or s in mc.listRelatives(mc.listRelatives(self.hierarchy[0],p=True)[0],c=True,type='joint') ): dist=distanceBetween(s,self.hierarchy[0]) if dist<closest: closest=dist self.baseTwist=s else: self.hierarchy=hierarchyBetween(sel[0],sel[-1]) self.bindPoses=iterable(getBindPoses(self.hierarchy)) self.joints=['','',''] if len(self.hierarchy)<3: raise Exception('There are no joints between your start and end joint. No IK created.') self.joints[0]=self.hierarchy[0] self.joints[-1]=self.hierarchy[-1] # find the orientation axis self.orientAxis='x' axisLen={'x':0,'y':0,'z':0} for j in self.hierarchy[1:]: for a in ['x','y','z']: axisLen[a]+=abs(mc.getAttr(j+'.t'+a)) if axisLen[a]>axisLen[self.orientAxis]: self.orientAxis=a # find bend joint and pole vector self.originalRotations={} for j in self.hierarchy[1:-1]: # check to see if any have a non-zero preferred angle for a in removeAll(self.orientAxis,['x','y','z']): if abs(mc.getAttr(j+'.pa'+a))>=self.tol: self.originalRotations[j+'.r'+a]=mc.getAttr(j+'.r'+a) mc.setAttr(j+'.r'+a,mc.getAttr(j+'.pa'+a)) greatestAngle=0 for j in self.hierarchy[1:-1]: jPos=mc.xform(j,q=True,ws=True,rp=True) prevJPos=mc.xform(self.hierarchy[self.hierarchy.index(j)-1],q=True,ws=True,rp=True) nextJPos=mc.xform(self.hierarchy[self.hierarchy.index(j)+1],q=True,ws=True,rp=True) vAngle=mc.angleBetween(v1=normalize(jPos[0]-prevJPos[0],jPos[1]-prevJPos[1],jPos[2]-prevJPos[2]),v2=normalize(nextJPos[0]-jPos[0],nextJPos[1]-jPos[1],jPos[2]-jPos[2]))[-1] if abs(vAngle)>greatestAngle: greatestAngle=abs(vAngle) self.joints[1]=j mp=midPoint\ ( self.hierarchy[0],self.hierarchy[-1], bias=\ ( distanceBetween(self.hierarchy[0],self.joints[1])/ (distanceBetween(self.hierarchy[0],self.joints[1])+distanceBetween(self.joints[1],self.hierarchy[-1])) ) ) bendPoint=mc.xform(self.joints[1],q=True,ws=True,rp=True) self.poleVectorWorld=normalize\ ( bendPoint[0]-mp[0], bendPoint[1]-mp[1], bendPoint[2]-mp[2] ) pmm=mc.createNode('pointMatrixMult') mc.setAttr(pmm+'.vm',True) mc.connectAttr(self.joints[1]+'.worldInverseMatrix',pmm+'.im') mc.setAttr(pmm+'.ip',*self.poleVectorWorld) self.poleVector=mc.getAttr(pmm+'.o')[0] disconnectNodes(pmm) mc.delete(pmm) greatestLength=0.0 for i in [0,1,2]: if abs(self.poleVector[i])>greatestLength and ['x','y','z'][i]!=self.orientAxis: self.poleAxis=['x','y','z'][i] greatestLength=abs(self.poleVector[i]) self.bendDirection=-abs(self.poleVector[i])/self.poleVector[i] for r in self.originalRotations: mc.setAttr(r,self.originalRotations[r]) preferredAngleWarning=False if not mc.objExists(self.joints[1]): preferredAngleWarning=True mp=midPoint(self.hierarchy[0],self.hierarchy[-1]) cd=9e999 dist=0 for j in self.hierarchy[1:-1]: dist=distanceBetween(j,mp) if dist<cd: cd=dist self.joints[1]=j self.bendAxis=removeAll(self.orientAxis,['z','y','x'])[0] if self.poleAxis=='': self.poleAxis=removeAll([self.orientAxis,self.bendAxis],['x','y','z'])[0] if self.bendAxis=='': self.bendAxis=removeAll([self.orientAxis,self.poleAxis],['x','y','z'])[0] if self.orientAxis=='': self.orientAxis=removeAll([self.bendAxis,self.poleAxis],['x','y','z'])[0] if self.poleAxis=='x': self.poleVector=[-self.bendDirection,0.0,0.0] if self.poleAxis=='y': self.poleVector=[0.0,-self.bendDirection,0.0] if self.poleAxis=='z': self.poleVector=[0.0,0.0,-self.bendDirection] if self.bendAxis=='x': self.upVector=[-self.bendDirection,0.0,0.0] if self.bendAxis=='y': self.upVector=[0.0,-self.bendDirection,0.0] if self.bendAxis=='z': self.upVector=[0.0,0.0,-self.bendDirection] if self.orientAxis=='x': self.aimVector=[self.bendDirection,0.0,0.0] if self.orientAxis=='y': self.aimVector=[0.0,self.bendDirection,0.0] if self.orientAxis=='z': self.aimVector=[0.0,0.0,self.bendDirection] if mc.objExists(self.baseTwist): conn=False for a in ['.r','.rx','.ry','.rz']: if mc.connectionInfo(self.baseTwist+a,id=True): conn=True if not conn: mc.orientConstraint(self.joints[0],self.baseTwist,sk=self.orientAxis) # load ik2Bsolver - ikRPSolver does not work well with this setup mel.eval('ik2Bsolver') self.create() if preferredAngleWarning: raise Warning('Warning: Joints are co-linear and no preferred angles were set. Results may be unpredictable.')
def create(self): mc.cycleCheck(e=False) if mc.objExists(self.parent): self.group=mc.createNode('transform',n=uniqueNames(self.name),p=self.parent) else: self.group=mc.createNode('transform',n=uniqueNames(self.name)) self.jointParent='' if len(iterable(mc.listRelatives(self.joints[0],p=True)))>0: self.jointParent=mc.listRelatives(self.joints[0],p=True)[0] else: self.jointParent=mc.createNode('transform',n=uniqueNames(self.name+'CtrlJointGroup')) mc.parent(self.joints[0],self.jointParent) cMuscleObjects=[] # create control joints self.ctrlJoints=[] for j in self.joints: cj=mc.createNode('joint',p=j,n=uniqueNames(self.name+'CtrlJoint')) if len(self.ctrlJoints)==0: mc.parent(cj,self.group) if mc.objExists(self.jointParent): self.jointParent=mc.rename(ParentSpace(cj,self.jointParent)[0],self.name+'CtrlJoints') else: self.jointParent=mc.rename(ParentSpace(cj)[0],self.name+'CtrlJoints') else: mc.parent(cj,self.ctrlJoints[-1]) mc.setAttr(cj+'.r',*mc.getAttr(j+'.r')[0]) mc.setAttr(cj+'.jo',*mc.getAttr(j+'.jo')[0]) self.originalRotations[cj+'.r']=list(mc.getAttr(cj+'.r')[0]) mc.setAttr(j+'.r',0,0,0) mc.setAttr(cj+'.r',0,0,0) mc.setAttr(cj+'.s',1,1,1) mc.setAttr(cj+'.radius',mc.getAttr(j+'.radius')*1.5)#0) mc.setAttr(cj+'.ovc',10) mc.connectAttr(j+'.pa',cj+'.pa') if self.joints.index(j)<len(self.joints)-1: childList=removeAll\ ( iterable(mc.listRelatives(self.joints[self.joints.index(j)+1],c=True,ad=True))+[self.joints[self.joints.index(j)+1]], iterable(mc.listRelatives(j,c=True,ad=True))+[j] ) chList=childList for c in chList: if mc.nodeType(c) not in ['transform','joint','cMuscleObject']: childList.remove(c) if mc.nodeType(c) in ['transform','joint']: for a in ['.t','.tx','.ty','.tz','.r','.rx','.ry','.rz']: if mc.connectionInfo(c+a,id=True) or mc.getAttr(c+a,l=True) or mc.getAttr(c+'.io'): childList.remove(c) break if j==self.joints[-2]: childList.append(self.joints[-1]) for jc in childList: if mc.nodeType(jc)=='transform' or mc.nodeType(jc)=='joint': if jc in self.joints[:-1]: mc.parentConstraint(cj,jc,mo=True) else: mc.parentConstraint(cj,jc,sr=('x','y','z'),mo=True) elif 'cMuscle' in mc.nodeType(jc): cMuscleObjects.append(jc) else: mc.parentConstraint(cj,j,st=('x','y','z'),mo=True) self.ctrlJoints.append(cj) mc.hide(self.jointParent) mc.setAttr(self.ctrlJoints[1]+'.ssc',False) # create ik self.ikHandle,self.endEffector=mc.ikHandle(sol='ik2Bsolver',sj=self.ctrlJoints[0],ee=self.ctrlJoints[-1],n=uniqueNames(self.name+'Handle')) self.endEffector=mc.rename(self.endEffector,self.name+'Effector') mc.setAttr(self.ikHandle+'.snapEnable',False) mc.hide(self.ikHandle) mc.setAttr(self.ikHandle+'.ikBlend',0) for j in self.originalRotations: if isIterable(self.originalRotations[j]): mc.setAttr(j,*self.originalRotations[j]) else: mc.setAttr(j,self.originalRotations[j]) # look for twist joints if self.twist: skipAxis=removeAll(self.orientAxis,['x','y','z']) twistJoints=removeAll([self.joints[-2],self.joints[-1]],hierarchyBetween(self.joints[-2],self.joints[-1],type='joint')) for i in range(0,len(twistJoints)): tj=twistJoints[i] oc=mc.orientConstraint(self.ctrlJoints[-1],tj,sk=skipAxis,mo=True) if i>0: oc=mc.orientConstraint(self.ctrlJoints[-2],tj,sk=skipAxis,mo=True) wal=mc.orientConstraint(oc,q=True,wal=True) distToBend=distanceBetween(self.ctrlJoints[-2],tj) distToEnd=distanceBetween(self.ctrlJoints[-1],tj) mc.setAttr(oc+'.'+wal[-1],distToEnd/(distToBend+distToEnd)) mc.setAttr(oc+'.'+wal[-2],distToBend/(distToBend+distToEnd)) # make stretchy db=mc.createNode('distanceBetween') mc.connectAttr(self.ctrlJoints[0]+'.t',db+'.p1') pmm1=mc.createNode('pointMatrixMult') pmm2=mc.createNode('pointMatrixMult') mc.connectAttr(self.ikHandle+'.t',pmm1+'.ip') mc.connectAttr(self.ikHandle+'.pm[0]',pmm1+'.im') mc.connectAttr(pmm1+'.o',pmm2+'.ip') mc.connectAttr(self.ctrlJoints[0]+'.pim[0]',pmm2+'.im') mc.connectAttr(pmm2+'.o',db+'.p2') mdl=mc.createNode('multDoubleLinear') mc.connectAttr(db+'.d',mdl+'.i1') mc.setAttr(mdl+'.i2',1.0/mc.getAttr(db+'.d')) cn=mc.createNode('clamp') for i in range(0,3): c=['r','g','b'][i] a=['x','y','z'][i] mc.connectAttr(mdl+'.o',cn+'.ip'+c) mc.setAttr(cn+'.mn'+c,1) mc.connectAttr(mdl+'.o',cn+'.mx'+c) mc.connectAttr(cn+'.op'+c,self.ctrlJoints[0]+'.s'+a) for cmo in cMuscleObjects: mdlcm=mc.createNode('multDoubleLinear') mc.setAttr(mdlcm+'.i1',mc.getAttr(cmo+'.length')) mc.connectAttr(cn+'.op'+['r','g','b'][['x','y','z'].index(self.orientAxis)],mdlcm+'.i2') mc.connectAttr(mdlcm+'.o',cmo+'.length') # create control objects or set control object pivots poleOffset=distanceBetween(self.ctrlJoints[1],self.ctrlJoints[0])*2 for i in range(0,len(self.controlObjects)-1): if mc.objExists(self.controlObjects[i]): mc.xform(self.controlObjects[i],ws=True,piv=mc.xform(self.ctrlJoints[-1],q=True,ws=True,rp=True)) else: if 'r' not in self.handleOptions[i] and 'radius' not in self.handleOptions[i]: self.handleOptions[i]['r']=distanceBetween(self.ctrlJoints[-1],self.ctrlJoints[0])/4 if 'name' not in self.handleOptions[i] and 'n' not in self.handleOptions[i]: self.handleOptions[i]['n']=self.joints[i]+'_ctrl' if 'x' not in self.handleOptions[i] and 'xform' not in self.handleOptions[i]: self.handleOptions[i]['xform']=self.joints[i] if 'aim' not in self.handleOptions[i] and 'a' not in self.handleOptions[i]: self.handleOptions[i]['aim']=self.aimVector self.handleOptions[i]['parent']=self.group self.handleOptions[-i]['pointTo']=self.joints[i] self.handleOptions[i]['aimAt']=self.joints[i] self.handles.append(Handle(**self.handleOptions[i])) self.controlObjects[i]=(self.handles[-1].transforms[-1]) if not mc.objExists(self.controlObjects[-1]): if 'name' not in self.handleOptions[-1] and 'n' not in self.handleOptions[-1]: self.handleOptions[-1]['n']=self.joints[1]+'_aimCtrl' if 'x' not in self.handleOptions[-1] and 'xform' not in self.handleOptions[-1]: self.handleOptions[-1]['x']=self.ctrlJoints[1] if 'aim' not in self.handleOptions[i] and 'a' not in self.handleOptions[i]: self.handleOptions[i]['aim']=self.poleVector self.handleOptions[-1]['parent']=self.group self.handleOptions[-1]['pointTo']=self.joints[1] self.handleOptions[-1]['aimAt']=self.joints[1] self.handles.append(Handle(**self.handleOptions[-1])) self.controlObjects[-1]=(self.handles[-1].transforms[-1]) mc.move\ ( poleOffset*(self.poleVector[0]), poleOffset*(self.poleVector[1]), poleOffset*(self.poleVector[2]), self.controlObjects[-1], r=True,os=True,wd=True ) # add and set control attributes mc.setAttr(self.controlObjects[-1]+'.v',k=False) for attr in ['.sx','.sy','.sz']: mc.setAttr(self.controlObjects[-1]+attr,l=True,k=False,cb=False) mc.setAttr(self.ikHandle+attr,l=True,k=False,cb=False) for attr in ['.rx','.ry','.rz']: mc.setAttr(self.controlObjects[-1]+attr,k=False,cb=False) for attr in ['.tx','.ty','.tz']: mc.setAttr(self.group+attr,l=True,k=False,cb=False) mc.setAttr(self.controlObjects[0]+attr,l=True,k=False,cb=False) mc.setAttr(self.ikHandle+'.v',k=False,cb=False) for attr in ['.tx','.ty','.tz']: mc.setAttr(self.controlObjects[1]+attr,l=True,k=False,cb=False) if not mc.objExists(self.controlObjects[-2]+'.twist'): mc.addAttr(self.controlObjects[-2],at='doubleAngle',ln='twist',k=True) if not mc.objExists(self.controlObjects[-2]+'.sway') and self.sway: mc.addAttr(self.controlObjects[-2],at='doubleAngle',ln='sway',k=1) if not mc.objExists(self.controlObjects[-2]+'.stretch'): mc.addAttr(self.controlObjects[-2],at='double',ln='stretch',k=1,dv=self.stretch,min=0) if not mc.objExists(self.controlObjects[-2]+'.squash'): mc.addAttr(self.controlObjects[-2],at='double',ln='squash',k=1,dv=self.squash,min=0,max=99) if not mc.objExists(self.controlObjects[-2]+'.ikSwitch'): mc.addAttr(self.controlObjects[-2],at='enum',ln='ikSwitch',en='ik:fk',k=True,dv=1)# if self.switch=='fk' else 0 #sway control if self.sway: adl=mc.createNode('addDoubleLinear') mc.connectAttr(self.ctrlJoints[1]+'.r'+self.poleAxis,adl+'.i1') mc.connectAttr(self.controlObjects[-2]+'.sway',adl+'.i2') childList=removeAll\ ( iterable(mc.listRelatives(self.joints[2],c=True,ad=True)), iterable(mc.listRelatives(self.joints[1],c=True,ad=True)) )+[self.joints[2],self.joints[1]] for c in childList: if mc.nodeType(c)=='transform' or mc.nodeType(c)=='joint': pc=mc.parentConstraint(c,q=True) nc=listNodeConnections(self.ctrlJoints[1],pc,s=True,d=True) for conn in nc: if conn[0]==self.ctrlJoints[1]+'.rotate': mc.disconnectAttr(conn[0],conn[1]) for a in removeAll(self.poleAxis,['x','y','z']): mc.connectAttr(conn[0]+a.upper(),conn[1]+a.upper(),f=True) mc.connectAttr(adl+'.o',conn[1]+self.poleAxis.upper(),f=True) # ik/fk switch for i in range(0,3): c=['r','g','b'][i] a=['x','y','z'][i] adl=mc.createNode('addDoubleLinear') mdl1=mc.createNode('multDoubleLinear') mc.setAttr(mdl1+'.i2',.01) mdl2=mc.createNode('multDoubleLinear') mc.setAttr(mdl2+'.i2',.01) revNode=mc.createNode('reverse') mc.setAttr(adl+'.i1',1) mc.connectAttr( mdl1+'.o',adl+'.i2') mc.connectAttr(self.controlObjects[-2]+'.stretch',mdl1+'.i1') mc.connectAttr( mdl2+'.o',revNode+'.ix') mc.connectAttr(self.controlObjects[-2]+'.squash',mdl2+'.i1') mc.connectAttr(adl+'.o',cn+'.mx'+c,f=True) mc.connectAttr(revNode+'.ox',cn+'.mn'+c,f=True) if not mc.objExists(self.controlObjects[-2]+'.zenPreviousIKState'): if self.switch=='fk': mc.addAttr(self.controlObjects[-2],at='long',ln='zenPreviousIKState',k=0,dv=1) else: mc.addAttr(self.controlObjects[-2],at='long',ln='zenPreviousIKState',k=0,dv=0) if not mc.objExists(self.controlObjects[-2]+'.zenPreviousIKParent'): if self.switch=='fk': mc.addAttr(self.controlObjects[-2],at='long',ln='zenPreviousIKParent',k=0,dv=1) else: mc.addAttr(self.controlObjects[-2],at='long',ln='zenPreviousIKParent',k=0,dv=0) for i in range(0,2): for c in mc.listRelatives(self.controlObjects[i],s=True): mc.connectAttr(self.controlObjects[-2]+'.ikSwitch',c+'.v') mc.connectAttr(self.controlObjects[-2]+'.twist',self.ikHandle+'.twist') rev=mc.createNode('reverse') mc.connectAttr(self.controlObjects[-2]+'.ikSwitch',rev+'.ix') mc.connectAttr(rev+'.ox',self.ikHandle+'.ikBlend') for c in mc.listRelatives(self.controlObjects[-1],s=True): mc.connectAttr(rev+'.ox',c+'.v') # parent spaces for i in [0,1,2]: if(mc.objExists(self.jointParent)and i in [0,2]): ParentSpace(self.controlObjects[i],self.jointParent) else: ParentSpace(self.controlObjects[i],self.controlObjects[i-1]) ParentSpace(self.controlObjects[-1],self.controlObjects[-2]) if mc.objExists(self.jointParent): ParentSpace(self.controlObjects[-1],self.jointParent).setParent(self.jointParent) ParentSpace(self.controlObjects[-2],self.jointParent).setParent(self.jointParent) else: ParentSpace(self.controlObjects[-1],self.controlObjects[0]) if self.switch=='fk': ParentSpace(self.controlObjects[2],self.controlObjects[1]) for co in self.controlObjects[2:]: freeze(co,t=True) mc.aimConstraint\ ( self.ctrlJoints[1],self.controlObjects[-1], aim=(self.aimVector[0],self.aimVector[1],self.aimVector[2]), wuo=self.ctrlJoints[1], wut='objectrotation', mo=True ) if mc.objExists(self.jointParent): mc.setAttr(self.controlObjects[0]+'.parentTo',l=True,k=False,cb=False) mc.setAttr(self.controlObjects[1]+'.parentTo',l=True,k=False,cb=False) #constraints orientConstraints=['','',''] for i in [2,1,0]: orientConstraints[i]=mc.orientConstraint(self.controlObjects[i],self.ctrlJoints[i],mo=True)[0] mc.setAttr(self.controlObjects[i]+'.v',k=False) for attr in ['.sx','.sy','.sz']: mc.setAttr(self.controlObjects[i]+attr,l=True,k=False,cb=False) if i==1: if not self.sway: mc.setAttr(self.controlObjects[i]+'.r'+self.poleAxis,l=True,k=False,cb=False) mc.setAttr(self.controlObjects[i]+'.r'+self.orientAxis,l=True,k=False,cb=False) self.poleVectorConstraint=mc.poleVectorConstraint(self.controlObjects[-1],self.ikHandle)[0] for oc in orientConstraints[:-1]: octl=mc.orientConstraint(oc,q=True,tl=True) ocwal=mc.orientConstraint(oc,q=True,wal=True) weightAlias=ocwal[octl.index(self.controlObjects[orientConstraints.index(oc)])] mc.connectAttr(self.controlObjects[-2]+'.ikSwitch',oc+'.'+weightAlias) mc.parent(self.ikHandle,self.controlObjects[2],r=False) if self.switch=='ik': mc.setAttr(self.controlObjects[-2]+'.ikSwitch',0) # link for asset detection if 'zenIkFkLimbCtrls' not in mc.listAttr(self.group): mc.addAttr(self.group,ln='zenIkFkLimbCtrls',at='message',m=True) if 'zenIkFkLimbCtrlJoints' not in mc.listAttr(self.group): mc.addAttr(self.group,ln='zenIkFkLimbCtrlJoints',at='message',m=True) for co in self.controlObjects: if 'zenCtrl' not in mc.listAttr(co): mc.addAttr(co,ln='zenCtrl',at='message') mc.connectAttr(co+'.zenCtrl',self.group+'.zenIkFkLimbCtrls['+str(firstOpenPlug(self.group+'.zenIkFkLimbCtrls'))+']') for cj in self.ctrlJoints: if 'zenCtrl' not in mc.listAttr(cj): mc.addAttr(cj,ln='zenCtrl',at='message') mc.connectAttr(cj+'.zenCtrl',self.group+'.zenIkFkLimbCtrlJoints['+str(firstOpenPlug(self.group+'.zenIkFkLimbCtrlJoints'))+']') for bp in self.bindPoses: for co in self.controlObjects: mc.dagPose(co,a=True,n=bp) self[:]=[self.group]+self.controlObjects mc.cycleCheck(e=True) mc.select(self[-2])
def __init__(self,*args,**keywords): #check to make sure unique names are used in scene uniqueNames(iterable(mc.ls(type='dagNode')),re=True) #default options self.number=1 #if there are no transforms, create this many rivets self.distribute='' self.parents=['',''] self.rebuild=False self.taper='none' # none, normal, distance self.scale='none' # none, uniform, or relative self.scaleDirection=['length','width'] # length, width self.createAimCurve=False self.aimCurve='' self.handles=[] self.handleShapes=[] self.autoFlexGroups=[] self.mo=True # maintain offset self.ctrls=[] #by default control attributes are placed on given transforms self.keepPivot=True self.snapToSurface=False self.realign=False self.rivets=[] self.ClosestPoints=[] self.aimGroups=[] self.softParents=[] self.ArcCtrl=[] self.arcWeight=.5 self.closestPoint='' # geometry, pivot self.organize=True self.constraint=False # use a parent constraint self.parent=False # create a transform and parent objects to it self.spaceTr='' self.surfaceAttr='' self.bindPoses=[] self.parentSpaces=[] self.hasGeometry=True self.skipRotate=[] self.skipTranslate=[] self.skipScale=[] self.skipScaleObjects=[] self.skipRotateObjects=[] self.skipTranslateObjects=[] self.minScaleWidth=0 self.maxScaleWidth=1 self.minScaleLength=0 self.maxScaleLength=1 self.surfaceMatrix='' self.surfaceInverseMatrix='' self.worldMatrix='' self.trs=[] self.uSpans=-1 self.vSpans=-1 self.skins=[] self.shortNames=\ { 'sd':'scaleDirection', 'p':'parents', 'sp':'softParents' } sel=[] if len(args)==0: sel=mc.ls(sl=True) for a in args: sel.extend(iterable(a)) self.bindPoses=iterable(getBindPoses(sel)) if len(self.bindPoses)>0: goToDagPose(self.bindPoses[0]) self.edges=PolyEdgeList(sel,f=True) self.trs=removeDuplicates(mc.ls(self.edges.etcObj,tr=True)) if len(self.edges)==0: #look for a surface or surface attribute reversedObjList=getReversed(self.edges.etcObj) for obj in reversedObjList: if len(obj.split('.'))>1 and mc.getAttr(obj,type=True)=='nurbsSurface': self.surfaceAttr=obj obj=mc.ls(self.surfaceAttr,o=True)[0] if mc.nodeType(obj)=='nurbsSurface': self.uSpans=mc.getAttr(obj+'.spansU') self.vSpans=mc.getAttr(obj+'.spansV') self.spaceTr=mc.listRelatives(obj,p=True)[0] break elif mc.nodeType(obj)=='nurbsSurface': self.surfaceAttr=obj+'.worldSpace[0]' self.spaceTr=mc.listRelatives(obj,p=True)[0] self.uSpans=mc.getAttr(obj+'.spansU') self.vSpans=mc.getAttr(obj+'.spansV') self.trs.remove(obj) break else: children=mc.listRelatives(obj,c=True,s=True,ni=True,type='nurbsSurface') if isIterable(children) and len(children)>0: self.spaceTr=mc.ls(obj)[0] self.surfaceAttr=children[0]+'.worldSpace[0]' self.uSpans=mc.getAttr(children[0]+'.spansU') self.vSpans=mc.getAttr(children[0]+'.spansV') self.trs.remove(obj) break else: self.spaceTr=self.edges.getTr() for k in keywords: if k in self.__dict__: exec('self.'+k+'=keywords[k]') elif k in self.shortNames: exec('self.'+self.shortNames[k]+'=keywords[k]') if len(iterable(self.parents))==1: self.parents=[iterable(self.parents)[0],iterable(self.parents)[0]] if len(iterable(self.softParents))==1: self.softParents=[iterable(self.softParents)[0],iterable(self.softParents)[0]] if len(self.ctrls)==0: self.ctrls=self.trs while len(self.ctrls)<len(self.trs): self.ctrls.append(self.ctrls[-1]) if len(self.skipRotate)>0: for i in self.skipRotate: self.skipRotateObjects.append(self.trs[self.skipRotate[i]]) if len(self.skipTranslate)>0: for i in self.skipTranslate: self.skipTranslateObjects.append(self.trs[self.skipTranslate[i]]) if len(self.skipScale)>0: for i in self.skipScale: self.skipScaleObjects.append(self.trs[self.skipScale[i]]) if len(self.trs)>0: for t in self.trs: shCount=len\ ( removeDuplicates(mc.listRelatives(t,c=True,type='nurbsSurface'))+ removeDuplicates(mc.listRelatives(t,c=True,type='nurbsCurve'))+ removeDuplicates(mc.listRelatives(t,c=True,type='mesh')) ) if shCount==0: self.hasGeometry=False self.closestPoint='pivot' break if self.closestPoint=='' and self.hasGeometry: # default to pivot if using snap to surface, otherwise defualts to geometry if self.snapToSurface: self.closestPoint='pivot' else: self.closestPoint='geometry' if len(self.trs)!=0: self.number=len(self.trs) if len(self.ctrls)<len(self.trs): self.ctrls=self.trs if not self.parent and not self.constraint: self.parent=True if self.createAimCurve: self.parent=True #self.constraint=False #find the root joint if present try: joints=removeDuplicates(mc.listConnections(iterable(mc.ls(iterable(mc.listHistory(self.surfaceAttr)))),type='joint')) if len(joints)>0: self.spaceTr=hierarchyOrder(joints)[0] except: pass self.create()
def __init__(self,*args,**keywords): #check to make sure unique names are used in scene uniqueNames(iterable(mc.ls(type='dagNode')),re=True) # default options self.createSurface=False # use for IK's etc. - creates a surface instead of a curve self.scaleLength=True # use for IK's etc. - compensates for scale self.stretch=-1 # maximum stretch %: 0 > Infinity self.squash=-1 # maximum squash %: 0 > 100 self.arcWeight=.5 # controls the balance of rotational control weight alloted to the end Handle vs the base Handle self.width=1 # surface width self.length=10 # only used if no arguments are passed self.parents=['',''] # create under parent or parents self.softParents=['',''] self.parentSpaces=['',''] self.names=['ArcCtrl#','arcCtrl_handle#'] # self.handleType=['locator','locator'] # see 'Handle' class - 'locator','doubleEllipse', self.handleOptions=[{},{}] # dictionaries passed on to the Handle class for options concerning placement of handles self.aim=(0,1,0) self.poleVector=(0,0,1) # if only two arc points are given, it will try to point the arc in this direction if possible # option abbreviations shortNames=\ { 'p':'parents', 'cs':'createSurface', 'pv':'poleVector', 'st':'stretch', 'sq':'squash', 'cs':'createSurface', 'n':'names', 'ho':'handleOptions', 'w':'width', 'pv':'poleVector', 'aw':'arcWeight', 'ht':'handleType', 'sp':'softParents' } if 'shortNames' in self.__dict__: # this is done so that we don't wipe out added short names in inheriting classes for sn in shortNames: self.shortNames[sn]=shortNames[sn] else: self.shortNames=shortNames for k in keywords: #get user options if k in self.shortNames: exec('self.'+self.shortNames[k]+'=keywords[k]') elif k in self.__dict__: exec('self.'+k+'=keywords[k]') #check and format options if\ ( len(iterable(self.aim))<3 or not isinstance(self.aim[0],(float,int,long)) or not isinstance(self.aim[1],(float,int,long)) or not isinstance(self.aim[2],(float,int,long)) ): self.aim=(0,1,0) if\ ( len(iterable(self.poleVector))<3 or not isinstance(self.poleVector[0],(float,int,long)) or not isinstance(self.poleVector[1],(float,int,long)) or not isinstance(self.poleVector[2],(float,int,long)) ): self.poleVector=(0,0,1) self.aim=normalize(self.aim) self.poleVector=normalize(self.poleVector) if len(iterable(self.softParents))==1: self.softParents=[iterable(self.softParents)[0],iterable(self.softParents)[0]] elif len(iterable(self.softParents))==0: self.softParents=['',''] if len(iterable(self.parents))==1: self.parents=[iterable(self.parents)[0],iterable(self.parents)[0]] elif len(iterable(self.parents))==0: self.parents=['','.'] if len(iterable(self.names))==1: self.names=[iterable(self.names)[0],iterable(self.names)[0]] if len(iterable(self.names))==0: self.names=['',''] if len(iterable(self.handleType))==1: self.handleType=[iterable(self.handleType)[0],iterable(self.handleType)[0]] if len(iterable(self.handleType))==0: self.handleType=['',''] if isinstance(self.handleOptions,dict): self.handleOptions=[self.handleOptions,self.handleOptions] if isinstance(self.handleOptions,(list,tuple)) and\ len(self.handleOptions)==1 and\ isinstance(self.handleOptions[0],dict): self.handleOptions=[self.handleOptions[0],self.handleOptions[0]] if self.stretch>=0 and self.squash<0 or self.stretch<0 and self.squash>=0:# squash & stretch come as a pair, set one to 0 if only 1 is set if self.stretch<0: self.stretch=0 if self.squash<0: self.squash=0 if not isinstance(self.poleVector,tuple): self.poleVector=tuple(self.poleVector) # attributes self.outputCurve='' self.outputNormal='' self.surface='' self.outputSurface='' self.handleShapes=[] self.curveShapes=[] self.arcPoints=[] self.handles=[] # parse arguments if len(args)==0: args=iterable(mc.ls(sl=True,fl=True)) # if no arguments are input, use selection if len(args)==0: args=[[0.0,0.0,0.0]] sel=[] for a in args: if isIterable(a) and not isinstance(a[0],(float,long,int)): sel.extend(a) else: sel.append(a) for s in sel: if isIterable(s) and isinstance(s[0],(float,long,int)) and len(s)>=3: self.arcPoints.append(s) elif isinstance(s,basestring) and mc.objExists(s): err=True if len(s.split('.'))>1: try: self.arcPoints.append(mc.pointPosition(s)) err=False except: err=True else: try: self.arcPoints.append(mc.pointPosition(s+'.rp')) err=False except: err=True if len(self.arcPoints)<2: if len(self.arcPoints)==0: self.arcPoints=[[0.0,0.0,0.0]] self.arcPoints=\ [ self.arcPoints[0], [ float(self.arcPoints[0][0])+float(self.aim[0])*self.length, float(self.arcPoints[0][1])+float(self.aim[1])*self.length, float(self.arcPoints[0][2])+float(self.aim[2])*self.length ] ] self.create()
def __init__(self,*args,**keywords): #check to make sure unique names are used in scene uniqueNames(iterable(mc.ls(type='dagNode')),re=True) self.tol=.001 for k in keywords: if k in self.__dict__: if type(eval('self.'+k)).__name__==type(keywords[k]).__name__: exec('self.'+k+'=keywords[k]') sel=[] for a in args: if isIterable(a): sel.extend(a) else: sel.append(a) sel=removeDuplicates(mc.ls(sel)+mc.ls(sl=True,o=True)) if len(sel)<2: raise Exception("Procedure requires two polygon meshes, nurbs surfaces, or nurbs curves.") else: sel=sel[:2] oo=Decimal('Infinity') self[:]=[[oo,oo,oo],[oo,oo,oo]] noo=Decimal('-Infinity') self.antipodes=[[noo,noo,noo],[noo,noo,noo]] self.uvs=[(-1,-1),(-1,-1)] self.closestFaces=['',''] self.closestFaceIDs=[-1,-1] self.closestVertexIDs=[-1,-1] self.antipodeFaces=['',''] self.antipodeFaceIDs=[-1,-1] self.antipodeUVs=[(-1,-1),(-1,-1)] self.antipodeVertexIDs=[-1,-1] self.trs,self.types,self.shapes,self.shAttr,self.knots,self.roughAPIDs,self.roughCPIDs,self.uv=[],[],[],[],[],[],[],[] density,maxDensity,cpID,searchID,i=0,0,0,0,0 ci,si='','' for s in sel: # find shapes and node types and determine which is denser if len(s.split('.'))>1: sha=s nt=mc.getAttr(sha,type=True) if nt=='nurbsCurve' or nt=='nurbsSurface' or nt=='mesh': self.shapes.append('') self.trs.append('') self.shAttr.append(sha) self.types.append(nt) else: raise Exception("Arguments must be polygon meshes, nurbs surfaces, or nurbs curves.") elif len(mc.ls(s,tr=True))>0: sh=[] for c in \ ( mc.listRelatives(s,c=True,s=True,ni=True,type='nurbsCurve'), mc.listRelatives(s,c=True,s=True,ni=True,type='nurbsSurface'), mc.listRelatives(s,c=True,s=True,ni=True,type='mesh') ): if isIterable(c) and len(c)>0: sh=c[0] if isinstance(sh,basestring) and mc.objExists(sh): nt=mc.nodeType(sh) self.shapes.append(sh) self.trs.append(s) self.types.append(nt) if nt=='mesh': sha=s+'.outMesh' if nt=='nurbsSurface' or nt=='nurbsCurve': sha=s+'.local' self.shAttr.append(sha) elif mc.objExists(s): nt=mc.nodeType(s) if nt=='nurbsCurve' or nt=='nurbsSurface' or nt=='mesh': self.shapes.append(s) self.trs.append(mc.listRelatives(s,p=True)[0]) self.types.append(nt) if nt=='mesh': sha=s+'.worldMesh[0]' if nt=='nurbsSurface' or nt=='nurbsCurve': sha=s+'.local' self.shAttr.append(sha) else: raise Exception("Arguments must be polygon meshes, nurbs surfaces, or nurbs curves.") else: raise Exception("Arguments must be polygon meshes, nurbs surfaces, or nurbs curves.") if nt=='mesh': self.knots.append({}) density=len(mc.ls(sh+'.vtx[*]',fl=True)) elif nt=='nurbsCurve': if not mc.objExists(ci): ci=mc.createNode('curveInfo') mc.connectAttr(sha,ci+'.ic',f=True) ku=[] kuq=removeDuplicates(mc.getAttr(ci+'.knots')[0]) for u in kuq: if u>=0: ku.append(float(u)) else: kuq.pop() k={'u':tuple(ku)} self.knots.append(k) density=len(k['u']) elif nt=='nurbsSurface': if not mc.objExists(si): si=mc.createNode('surfaceInfo') mc.connectAttr(sha,si+'.is',f=True) ku=[] kuq=removeDuplicates(mc.getAttr(ci+'.knotsU')[0]) for u in kuq: if u>=0: ku.append(float(u)) else: kuq.pop() kv=[] kvq=removeDuplicates(mc.getAttr(ci+'.knotsV')[0]) for v in kvq: if v>=0: kv.append(float(v)) else: kvq.pop() k={'u':tuple(ku),'v':tuple(kv)} self.knots.append(k) density=len(k['u'])*len(k['v']) self.uv.append([-1.0,-1.0]) self.roughAPIDs.append([-1.0,-1.0]) self.roughCPIDs.append([-1.0,-1.0]) if density>maxDensity: maxDensity=density cpID=i else: searchID=i i+=1 if self.types[searchID]=='mesh' and self.types[cpID]!='mesh': temp=cpID cpID=searchID searchID=temp if mc.objExists(ci): mc.delete(ci) if mc.objExists(si): mc.delete(si) self.lookup(cpID)