def arcCheck(self): if len(self.arcPoints)>4: # if more than the maximum of 4 points have been given, determine which to use if float(int(float(len(self.arcPoints)-1)/3.0))==float(len(self.arcPoints)-1)/3.0: #divisible by 3 self.arcPoints=\ [ self.arcPoints[0], self.arcPoints[int((len(self.arcPoints)-1)/3.0)], # 1/3 self.arcPoints[int((2*len(self.arcPoints)-1)/3.0)], # 2/3 self.arcPoints[-1] ] elif float(int(float(len(self.arcPoints)-1)/2.0))==float(len(self.arcPoints)-1)/2.0: #even self.arcPoints=\ [ self.arcPoints[0], self.arcPoints[int(float(len(self.arcPoints)-1)/2.0)], # 1/2 self.arcPoints[int(float(len(self.arcPoints)-1)/2.0)], # 1/2 self.arcPoints[-1] ] else: self.arcPoints=\ [ self.arcPoints[0], self.arcPoints[int(float(len(self.arcPoints)-1)/2.0)], # 1/2- self.arcPoints[int(float(len(self.arcPoints)-1)/2.0)+1], # 1/2+ self.arcPoints[-1] ] # check to see that all the points are not on the same vector ( co-linear ) vA=vB=vC=cD=[] realArcPoints=self.arcPoints[:] mp=midPoint(self.arcPoints[0],self.arcPoints[-1]) dist=distanceBetween(self.arcPoints[0],self.arcPoints[-1]) zp=dist/1000 offsets=[[self.poleVector[0]*zp,self.poleVector[1]*zp,self.poleVector[2]*zp],(0,zp,0),(0,0,zp),(zp,0,0)] for i in range(1,10): for offset in offsets: if len(self.arcPoints)>2: vA=normalize(self.arcPoints[1][0]-self.arcPoints[0][0],self.arcPoints[1][1]-self.arcPoints[0][1],self.arcPoints[1][2]-self.arcPoints[0][2]) vB=normalize(self.arcPoints[-1][0]-self.arcPoints[1][0],self.arcPoints[-1][1]-self.arcPoints[1][1],self.arcPoints[-1][2]-self.arcPoints[1][2]) vC=normalize(self.arcPoints[-2][0]-self.arcPoints[0][0],self.arcPoints[-2][1]-self.arcPoints[0][1],self.arcPoints[-2][2]-self.arcPoints[0][2]) vD=normalize(self.arcPoints[-1][0]-self.arcPoints[-2][0],self.arcPoints[-1][1]-self.arcPoints[-2][1],self.arcPoints[-1][2]-self.arcPoints[-2][2]) if distanceBetween(vA,vB)<zp/4 or distanceBetween(vC,vD)<zp/4 or len(self.arcPoints)==2: self.arcPoints=realArcPoints[:] if len(self.arcPoints)==2: self.arcPoints=[self.arcPoints[0],[],self.arcPoints[-1]] self.arcPoints[1]=(mp[0]+offset[0]*i,mp[1]+offset[1]*i,mp[2]+offset[2]*i) else: break if distanceBetween(vA,vB)<zp/4 or distanceBetween(vC,vD)<zp/4 or len(self.arcPoints)==2: break
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 geoConnect(*args,**keywords): """ Connects shapes and worldSpace transforms of one shape to another, or all shapes in one file or namespace to another. Accepts an input of 2 or more file names, 2 or more name spaces, or any even number of objects. """ # default options driverNameSpace='' drivenNameSpace='' drivers=[] driven=[] hide=[] recursive=False maintainOffset=False output='' returnVal=[] shortNames=\ { 'r':'recursive', 'mo':'maintainOffset', 'o':'output', 'rv':'returnVal', 'h':'hide' } for k in keywords: if k in locals(): exec(k+'=keywords[k]') elif k in shortNames: exec(shortNames[k]+'=keywords[k]') if len(args)==0 and driverNameSpace=='' and drivenNameSpace=='': sel=iterable(mc.ls(sl=True)) sel=[] for a in args: sel.extend(iterable(a)) for i in range(0,len(sel)): if sel[i]=='': sel[i]=':' fromFiles=True for i in range(0,len(sel)): if len(sel[i].split('.'))>1: if not os.path.isfile(sel[i]): filePath=findFile(sel[i]) if os.path.isfile(filePath): sel[i]=filePath else: fromFiles=False break else: fromFiles=False break hide=iterable(hide) while len(hide)<len(sel): hide.append(False) matchByNameSpace=True if fromFiles: if len(sel)==1: sel.append(sel[0]) sel[0]=mc.file(q=True,l=True)[0] else: if mc.file(q=True,l=True)[0]!=sel[0]: mc.file(sel[0],o=True,f=True) driverNameSpace=mc.namespaceInfo(cur=True) drivenNameSpace=os.path.basename(sel[1].split('.')[0]) mc.file(sel[1],i=True,ra=True,namespace=drivenNameSpace,pr=True,loadReferenceDepth='all',options='v=1') else: nameSpaces=[':']+iterable(mc.namespaceInfo(lon=True)) for s in sel: if s not in nameSpaces: matchByNameSpace=False break if not matchByNameSpace: sel=iterable(mc.ls(sel)) matchNames=False if matchByNameSpace: currentNameSpace=mc.namespaceInfo(cur=True) if not fromFiles: if len(sel)>1: driverNameSpace=sel[0] if len(sel)==1: driverNameSpace=':' drivenNameSpace=sel[1] mc.namespace(set=driverNameSpace) for d in iterable(mc.ls(mc.namespaceInfo(ls=True),type=('mesh','nurbsCurve','nurbsSurface'))): if mc.getAttr(d+'.io')==False: drivers.append(d) mc.namespace(set=drivenNameSpace) for d in iterable(mc.ls(mc.namespaceInfo(ls=True),type=('mesh','nurbsCurve','nurbsSurface'))): if mc.getAttr(d+'.io')==False: driven.append(d) mc.namespace(set=currentNameSpace) drivers.sort() driven.sort() matchNames=True elif len(sel)>1: driven=sel[int(len(sel)/2):int(len(sel)/2)*2] drivers=sel[:int(len(sel)/2)] if recursive: matchNames=True drs=drivers dns=driven if len(drs)<=len(dns): r=len(drs) else: r=len(dns) for i in range(0,r): dr=drs[i] dn=dns[i] if shape(dr)!=dr or shape(dn)!=dn: drivers.remove(dr) driven.remove(dn) if shape(dr)!=dr and shape(dn)!=dn: drc=[] for dr in iterable(mc.listRelatives(dr,ad=True,type=('mesh','nurbsCurve','nurbsSurface'))): if mc.getAttr(dr+'.io')==False: drc.append(dr) drc.sort() dnc=[] for dn in iterable(mc.listRelatives(dn,ad=True,type=('mesh','nurbsCurve','nurbsSurface'))): if mc.getAttr(dn+'.io')==False: dnc.append(dn) dnc.sort() drivers.extend(drc) driven.extend(dnc) else: #check to see if we can match by name spaces if len(drivers[0].split(':'))>1 or len(driven[0].split(':'))>1: if len(drivers[0].split(':'))>1: driverNameSpace=':'.join(drivers[0].split(':')[:-1]) if len(driven[0].split(':'))>1: drivenNameSpace=':'.join(driven[0].split(':')[:-1]) matchNames=True if len(drivers)<=len(driven): r=len(drivers) else: r=len(driven) for i in range(0,r): if\ ( ( (driverNameSpace=='' and len(drivers[i].split(':'))<2) or ':'.join(drivers[i].split(':')[:-1])==driverNameSpace ) and ( (drivenNameSpace=='' and len(driven[i].split(':'))<2) or ':'.join(driven[i].split(':')[:-1])==drivenNameSpace ) and ( drivers[i].split(':')[-1]==driven[i].split(':')[-1] ) ): pass else: matchNames=False break driversHold=drivers drivenHold=driven drivers=[] driven=[] if len(drivers)<=len(driven): r=len(drivers) else: r=len(driven) for i in range(0,r): if shape(driversHold[i])!='' and shape(drivenHold[i])!='': drivers.append(shape(drivers[i])) drivers.append(shape(driven[i])) else: return if matchNames: # match names driverParents=[] driverHasSiblings=[] driversBN=[] for i in range(0,len(drivers)): driversBN.append(drivers[i].split('|')[-1].split(':')[-1]) driverParents.append(mc.listRelatives(drivers[i],p=True)[0].split('|')[-1].split(':')[-1]) sib=False for c in mc.listRelatives(driverParents[-1],c=True,type=mc.nodeType(drivers[i])): if c!=drivers[i] and mc.getAttr(c+'.io')==False: sib=True driverHasSiblings.append(sib) drivenParents=[] drivenParentLists=[] drivenBN=[] for i in range(0,len(driven)): #if driven[i].split(':')>1: drivenBN.append(driven[i].split('|')[-1].split(':')[-1]) drivenParentLists.append(iterable(mc.ls(driven[i],l=True)[0].split('|')[:-1])) for n in range(0,len(drivenParentLists[-1])): drivenParentLists[-1][n]=drivenParentLists[-1][n].split(':')[-1] drivenParents.extend(drivenParentLists[-1]) driversHold=drivers drivenHold=driven driven=[] drivers=[] for i in range(0,len(driversBN)): matched=False if (driverParents[i] in drivenParents) and not driverHasSiblings[i]: # match by transform names for n in range(0,len(drivenParentLists)): if driverParents[i] in drivenParentLists[n]: drivers.append(driversHold[i]) driven.append(drivenHold[n]) elif driversBN[i] in drivenBN: # match by shape names drivers.append(driversHold[i]) driven.append(drivenHold[drivenBN.index(driversBN[i])]) for i in range(0,len(drivers)): driverSh=drivers[i] drivenSh=driven[i] driverTr=mc.listRelatives(driverSh,p=True)[0] drivenTr=mc.listRelatives(drivenSh,p=True)[0] #drive shape if maintainOffset==False: shapeMatch=True else: shapeMatch=False if shapeMatch and mc.nodeType(driverSh)!=mc.nodeType(drivenSh): shapeMatch=False if shapeMatch and mc.nodeType(driverSh)=='nurbsCurve' or mc.nodeType(driverSh)=='nurbsSurface': if mc.ls(driverSh+'.cv[*]')!=mc.ls(drivenSh+'.cv[*]'): shapeMatch=False if shapeMatch and mc.nodeType(driverSh)=='mesh': if\ ( len(mc.ls(driverSh+'.vtx[*]',fl=True))!=len(mc.ls(drivenSh+'.vtx[*]',fl=True)) or len(mc.ls(driverSh+'.f[*]',fl=True))!=len(mc.ls(drivenSh+'.f[*]',fl=True)) or len(mc.ls(driverSh+'.e[*]',fl=True))!=len(mc.ls(drivenSh+'.e[*]',fl=True)) ): shapeMatch=False # try to connect with blendShape if shapeMatch: try: bs=BlendShape(driverSh,drivenSh,w=10,c=False)[0] returnVal.append(bs) except: shapeMatch=False # connect transforms mm=mc.createNode('multMatrix') dm=mc.createNode('decomposeMatrix') mc.connectAttr(driverTr+'.wm[0]',mm+'.i[1]') mc.connectAttr(drivenTr+'.pim',mm+'.i[0]') mc.connectAttr(mm+'.o',dm+'.imat') mc.connectAttr(dm+'.os',drivenTr+'.s') mc.connectAttr(dm+'.osh',drivenTr+'.sh') if shapeMatch: mc.parentConstraint(driverTr,drivenTr,mo=False) else: mc.parentConstraint(driverTr,drivenTr,mo=True) for attr in ['rp','rpt','sp','spt','ra','ro','it','rq']: for a in mc.listAttr(driverTr+'.'+attr): mc.connectAttr(driverTr+'.'+a,drivenTr+'.'+a,f=True) if not shapeMatch: # connect with wrap if mc.nodeType(driverSh)=='mesh' and mc.nodeType(drivenSh)=='mesh': driverArea=mc.polyEvaluate(driverSh,a=True) drivenArea=mc.polyEvaluate(drivenSh,a=True) areaPercDiff=(driverArea-drivenArea)/drivenArea if mc.nodeType(driverSh)=='mesh' and mc.nodeType(drivenSh)=='mesh' and areaPercDiff>.1: cpom=mc.createNode('closestPointOnMesh') mc.connectAttr(driverSh+'.worldMesh[0]',cpom+'.im') driverFaces=[] drivenFaces=iterable(mc.ls(drivenSh+'.f[*]',fl=True)) mc.progressWindow(st='Analyzing mesh...',title='Working',max=len(drivenFaces)/20,ii=True) n=0 for f in drivenFaces: mc.setAttr(cpom+'.ip',*midPoint(f)) driverFaces.append(driverSh+'.f['+str(mc.getAttr(cpom+'.f'))+']') if float(n)/20.0==int(n/20): mc.progressWindow(e=True,s=1) if mc.progressWindow(q=True,ic=True): if mc.objExists(cpom): mc.delete(cpom) mc.progressWindow(e=True,ep=True) raise Exception('User interupt.') n+=1 mc.progressWindow(e=True,ep=True) driverFaces=removeDuplicates(driverFaces) wrap=Wrap(driverFaces,drivenSh) if mc.objExists(cpom): mc.delete(cpom) else: wrap=Wrap(driverSh,drivenSh) returnVal.append(wrap) if hide[0]: mc.hide(driverSh) if hide[1]: mc.hide(drivenSh) if (fromFiles or matchByNameSpace) and len(sel)>2: return geoConnect(o=output,r=recursive,mo=maintainOffset,rv=returnVal,h=(hide[0]+hide[2:]),*(sel[0]+sel[2:])) elif output!='': # save if len(output.split('.'))<2: output=output+'.'+sel[0].split('.')[-1] if not os.path.isdir(os.path.dirname(output)): output=os.path.dirname(sel[0])+'/'+output if output.split('.')[-1]=='.ma': outputType='mayaAscii' else: outputType='mayaBinary' mc.file(rename=output) mc.file(f=True,save=True,type=outputType) else: return returnVal