diff --git a/data/apfData.py b/data/apfData.py index 37ffe6c..e5a940f 100644 --- a/data/apfData.py +++ b/data/apfData.py @@ -7,7 +7,7 @@ class ApfData( data.Data ): ''' Apf data class definition ''' - + def __init__(self,apfFile=''): ''' Apf data class initializer @@ -16,14 +16,14 @@ def __init__(self,apfFile=''): ''' # Execute Super Class Initilizer super(ApfData, self).__init__() - + # Initialize Data Type self.dataType = 'ApfData' - + if apfFile: self.read(apfFile) - + self.apfChan = ['tx','ty','tz','rx','ry','rz'] - + def read(self,apfFile): ''' @param apfFile: Apf file to load. @@ -32,33 +32,33 @@ def read(self,apfFile): # Check File if not os.path.isfile(apfFile): raise Exception('Apf file "'+apfFile+'" is not a valid path!') - + # Read File f = open(apfFile,'r') - + # Sort Data char = '' for line in f: - + # Get Line Data lineData = line.split() - + # Skip Empty Lines if not lineData: continue - + # Check BEGIN if lineData[0] == 'BEGIN': char = lineData[1] self._data[char] = {} continue - + # Check Character if not char: continue - + # Parse Line Data lineObj = lineData[0] lineVal = [float(i) for i in lineData[1:]] - self._data[char][lineObj] = lineVal + self._data[char][lineObj] = lineVal def processDir(srcDir): ''' @@ -69,31 +69,31 @@ def processDir(srcDir): # Check Source Directory if not os.path.isdir(srcDir): raise Exception('Source directory "'+srcDir+'" is not a valid path!') - + # Start Timer timer = mc.timerX() - + # Find all APF files apfFiles = [i for i in os.listdir(srcDir) if i.endswith('.apf')] apfFiles.sort() bpfFiles = [] for apfFile in apfFiles: - + # Check File srcFile = srcDir+'/'+apfFile if not os.path.isfile(srcFile): raise Exception('Apf file "'+srcFile+'" is not a valid path!') - + print apfFile - + apfData = ApfData(srcFile) bpfFile = apfData.save(srcFile.replace('.apf','.bpf')) bpfFiles.append(bpfFile) - + # Print Result totalTime = mc.timerX(st=timer) print 'Total time: '+str(totalTime) - + # Return Result return bpfFiles @@ -108,33 +108,33 @@ def loadAnim(srcDir,agentNS): # Check Source Directory if not os.path.isdir(srcDir): raise Exception('Source directory "'+srcDir+'" is not a valid path!') - + # Start Timer timer = mc.timerX() - + # Load Agent Animation bpfFiles = [i for i in os.listdir(srcDir) if i.endswith('.bpf')] bpfIndex = [int(i.split('.')[1]) for i in bpfFiles] bpfIndex.sort() - + # For Each File apfChan = ['tx','ty','tz','rx','ry','rz'] for ind in bpfIndex: data = ApfData().load(srcDir+'/frame.'+str(ind)+'.bpf') if data._data.has_key(agentNS): for item in data._data[agentNS].iterkeys(): - + # Check Agent:Item Exists if not mc.objExists(agentNS+':'+item): continue - + # Load Anim Channels if item == 'Hips': for i in range(3): mc.setKeyframe(agentNS+':'+item,at=apfChan[i],t=ind,v=data._data[agentNS][item][i]) for i in range(3,6): mc.setKeyframe(agentNS+':'+item,at=apfChan[i],t=ind,v=data._data[agentNS][item][i]) - - + + # Print Result totalTime = mc.timerX(st=timer) print 'Total time: '+str(totalTime) diff --git a/data/buildData.py b/data/buildData.py index 8c600c1..055e9d7 100644 --- a/data/buildData.py +++ b/data/buildData.py @@ -15,63 +15,63 @@ def buildDeformerData(deformer): # ========== # - Checks - # ========== - + # Check Deformer if not glTools.utils.deformer.isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # Get Deformer Type deformerType = mc.objectType(deformer) - + # ============================ # - Initialize Deformer Data - # ============================ - + dData = glTools.data.deformerData.DeformerData() - + # Cluster if deformerType == 'cluster': dData = glTools.data.clusterData.ClusterData() - + # CurveTwist if deformerType == 'curveTwist': dData = glTools.data.clusterData.ClusterData() - + # DirectionalSmooth if deformerType == 'directionalSmooth': dData = glTools.data.deformerData.DirectionalSmoothData() - + # SkinCluster elif deformerType == 'skinCluster': dData = glTools.data.skinClusterData.SkinClusterData() - + # StrainRelaxer if deformerType == 'strainRelaxer': dData = glTools.data.deformerData.StrainRelaxerData() - + # SurfaceSkin elif deformerType == 'surfaceSkin': dData = glTools.data.surfaceSkinData.SurfaceSkinData() - + # Wire elif deformerType == 'wire': dData = glTools.data.wireData.WireData() - + # Unsupported Type !! else: print('Using base DeformerData class for "'+deformerType+'" deformer "'+deformer+'"!') - + # ======================= # - Build Deformer Data - # ======================= - + try: dData.buildData(deformer) except: raise Exception('DeformerData: Error building data object for deformer "'+deformer+'"!') - + # ================= # - Return Result - # ================= - + return dData diff --git a/data/channelData.py b/data/channelData.py index aa472b4..c021ae9 100644 --- a/data/channelData.py +++ b/data/channelData.py @@ -14,17 +14,17 @@ def __init__(self,nodeList=[],chanList=[],verbosity=0): ''' # Execute Super Class Initilizer super(ChannelData, self).__init__() - + # Initialize Channel Data self._channelData = {} self.userChannelList = chanList - + # Set Verbosity self.verbosity = verbosity - + # Build ChannelData if nodeList: self.buildData(nodeList,chanList) - + def buildData(self,nodeList=None,chanList=None): ''' Build ChannelData class. @@ -36,72 +36,72 @@ def buildData(self,nodeList=None,chanList=None): # ========== # - Checks - # ========== - + # Node List if not nodeList: print('ChannelData: Empty node list! Unable to build channelData!') return - + # Channel List if not chanList: chanList = self.userChannelList if not chanList: chanList = [] - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Reset Data --- ? self.reset() - + # Build Node Channel Data self._data['channelDataNodes'] = [] for node in nodeList: - + # Check Node if not mc.objExists(node): if self.verbosity > 0: print('Node "'+node+'" does not exist!! Skipping...') continue - + # Initialize Node Data self._channelData[node] = {} self._data['channelDataNodes'].append(node) - + # Build Node.Channel List nodeChanList = [node+'.'+i for i in chanList if mc.objExists(node+'.'+i)] - + # Get Value Channel List valChanList = [] if chanList: valChanList = chanList else: valChanList = mc.listAttr(node,se=True,r=True,w=True,m=True,v=True) - + # Get Source Connection Channel List srcChanList = [] if nodeChanList: srcChanList = mc.listConnections(nodeChanList,s=True,d=False,p=True,c=True,sh=True) or [] else: srcChanList = mc.listConnections(node,s=True,d=False,p=True,c=True,sh=True) or [] - + # Get Destination Connection Channel List dstChanList = [] if nodeChanList: dstChanList = mc.listConnections(nodeChanList,s=False,d=True,p=True,c=True,sh=True) or [] else: dstChanList = mc.listConnections(node,s=False,d=True,p=True,c=True,sh=True) or [] - + # Add Channel Value Data for chan in valChanList: - + # Check Attribute #if not mc.attributeQuery(chan,n=node,ex=True): if not mc.objExists(node+'.'+chan): if self.verbosity > 0: print('ChannelData: Node "'+node+'" has no attribute "'+chan+'"! Skipping...') continue - + # Check Settable if not mc.getAttr(node+'.'+chan,se=True): if not mc.listConnections(node+'.'+chan,s=True,d=False): if self.verbosity > 0: print('ChannelData: Attribute "'+node+'.'+chan+'" is not settable! Skipping...') continue - + # Get Channel Value chanVal = None try: chanVal = mc.getAttr(node+'.'+chan) @@ -111,26 +111,26 @@ def buildData(self,nodeList=None,chanList=None): else: # Create Channel Entry if not self._channelData[node].has_key(chan): self._channelData[node][chan] = {} - + # Store Channel Value if not chanVal == None: if type(chanVal) == list: if type(chanVal[0]) == tuple: chanVal = list(chanVal[0]) self._channelData[node][chan]['value'] = chanVal - + # Add Channel Source Data for i in range(0,len(srcChanList),2): - + # Get Channel Name chan = str(srcChanList[i].replace(node+'.','')) - + # Create Channel Entry if not self._channelData[node].has_key(chan): self._channelData[node][chan] = {} - + # Store Channel Source Data self._channelData[node][chan]['source'] = srcChanList[i+1] - + # Store Channel Value Data try: chanVal = mc.getAttr(srcChanList[i]) except Exception, e: @@ -138,29 +138,29 @@ def buildData(self,nodeList=None,chanList=None): if self.verbosity > 1: print('ChannelData: Exception message: '+str(e)) else: self._channelData[node][chan]['value'] = chanVal - + # Add Channel Desitination Data for i in range(0,len(dstChanList),2): - + # Get Channel Name chan = dstChanList[i].replace(node+'.','') - + # Create Channel Entry if not self._channelData[node].has_key(chan): self._channelData[node][chan] = {} - + # Store Channel Desitination Data self._channelData[node][chan]['destination'] = dstChanList[i+1] - + # Print timer result buildTime = mc.timerX(st=timer) print('ChannelData: Data build time for nodes "'+str(nodeList)+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return self._data.keys() - + def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination=False): ''' Rebuild the channel values and connections from the stored ChannelData. @@ -170,55 +170,55 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= @type chanList: List @param connectSource: Attempt to restore all source connections. @type connectSource: bool - @param connectDestination: Attempt to restore all destination connections. + @param connectDestination: Attempt to restore all destination connections. @type connectDestination: bool ''' # ========== # - Checks - # ========== - + # Node List if not self._data['channelDataNodes']: raise Exception('ChannelData has not been initialized!') - + # ======================== # - Rebuild Channel Data - # ======================== - + # Start Timer timer = mc.timerX() - + # Get Node List if not nodeList: nodeList = self._data['channelDataNodes'] if not nodeList: print('ChannelData: No channel data nodes to rebuild!') return - + # Rebuild Node Channel Data for node in nodeList: - + # Check Node Key if not self._channelData.has_key(node): if self.verbosity > 0: print('ChannelData: No channel data stored for "'+node+'"!! Skipping...') - + # Get Node Channel List channelList = self._channelData[node].keys() - + # Rebuild Node Channel Data for chan in sorted(channelList): - + # Check Channel Exists if not mc.objExists(node+'.'+chan): if self.verbosity > 0: print('ChannelData: Channel "'+node+'.'+chan+'" does not exist! Unable to rebuild channel data! Skipping...') continue - + # Restore Channel Value if self._channelData[node][chan].has_key('value'): chanVal = self._channelData[node][chan]['value'] - + # Set Channel Value if mc.getAttr(node+'.'+chan,se=True): - + # Get Channel Type chanType = str(mc.getAttr(node+'.'+chan,type=True)) #print chanType @@ -246,13 +246,13 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= else: if self.verbosity > 0: print('ChannelData: Node channel "'+node+'.'+chan+'" is not settable!! Unable to restore channel value...') - + # Restore Channel Destination Connection if connectDestination: if self._channelData[node][chan].has_key('destination'): src = node+'.'+chan dst = self._channelData[node][chan]['destination'] - + # Check Existing Connections connect = True dstConn = mc.listConnections(dst,s=True,d=False,p=True,sh=True) @@ -260,7 +260,7 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= if dstConn[0] == src: if self.verbosity > 0: print('ChannelData: "'+src+'" already connected to "'+dst+'"! Skipping...') connect = False - + # Check Locked Destination if connect: dstLocked = mc.getAttr(dst,l=True) @@ -272,7 +272,7 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= connect = False else: if self.verbosity > 0: print('ChannelData: Unlocked channel "'+dst+'"') - + # Rebuild Connection if connect: try: mc.connectAttr(src,dst,f=True) @@ -288,14 +288,14 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= if self.verbosity > 1: print('ChannelData: Exception message '+str(e)) else: if self.verbosity > 0: print('ChannelData: Relocked channel "'+dst+'"') - + # Rebuild Channel Source Connection if connectSource: - + if self._channelData[node][chan].has_key('source'): src = self._channelData[node][chan]['source'] dst = node+'.'+chan - + # Check existing connections connect = True dstConn = mc.listConnections(dst,s=True,d=False,p=True,sh=True) @@ -303,7 +303,7 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= if dstConn[0] == src: if self.verbosity > 0: print('ChannelData: "'+src+'" already connected to "'+dst+'"! Skipping...') connect = False - + # Check Locked Destination if connect: dstLocked = mc.getAttr(dst,l=True) @@ -315,7 +315,7 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= connect = False else: if self.verbosity > 0: print('ChannelData: Unlocked channel "'+dst+'"') - + # Rebuild Connection if connect: try: mc.connectAttr(src,dst,f=True) @@ -331,17 +331,17 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= if self.verbosity > 1: print('ChannelData: Exception message '+str(e)) else: if self.verbosity > 0: print('ChannelData: Relocked channel "'+dst+'"') - + # Print timer result buildTime = mc.timerX(st=timer) print('ChannelData: Rebuild time "'+str(nodeList)+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return nodeList - + def nodeChannels(self,node): ''' Return a list of stored channel data for the specified node. @@ -350,5 +350,5 @@ def nodeChannels(self,node): if self.verbosity > 0: print('ChannelData: No channel data stored for "'+node+'"!! Skipping...') channelList = sorted(self._channelData[node].keys()) return channelList - + diff --git a/data/channelStateData.py b/data/channelStateData.py index 0209039..b7f1a81 100644 --- a/data/channelStateData.py +++ b/data/channelStateData.py @@ -16,19 +16,19 @@ def __init__(self,verbosity=0): ''' # Define Channel List chanList=['channelState','defaultAttrState'] - + # Define Node List nodeList = [] chanStateList = mc.ls('*.channelState',r=True,o=True) if chanStateList: nodeList.extend(chanStateList) attrStateList = mc.ls('*.defaultAttrState',r=True,o=True) if attrStateList: nodeList.extend(attrStateList) - + # Execute Super Class Initilizer super(ChannelStateData, self).__init__( nodeList=nodeList, chanList=chanList, verbosity=verbosity ) - + def buildData(self,nodeList=None,chanList=None): ''' Build ChannelData class. @@ -38,67 +38,67 @@ def buildData(self,nodeList=None,chanList=None): # ========== # - Checks - # ========== - + # Node List if not nodeList: print('ChannelData: Empty node list! Unable to build channelData!') return - + # Channel List if not chanList: chanList = self.userChannelList if not chanList: chanList = [] - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Reset Data --- ? self.reset() - + # Build Node Channel Data self._data['channelDataNodes'] = [] for node in nodeList: - + # Initialize Node Data self._channelData[node] = {} self._data['channelDataNodes'].append(node) - + # Build Node.Channel List nodeChanList = [node+'.'+i for i in chanList if mc.objExists(node+'.'+i)] - + # Get Value Channel List valChanList = [] if chanList: valChanList = chanList else: valChanList = mc.listAttr(node,se=True,r=True,w=True,m=True,v=True) - + # Get Source Connection Channel List srcChanList = [] if nodeChanList: srcChanList = mc.listConnections(nodeChanList,s=True,d=False,p=True,c=True,sh=True) or [] else: srcChanList = mc.listConnections(node,s=True,d=False,p=True,c=True,sh=True) or [] - + # Get Destination Connection Channel List dstChanList = [] if nodeChanList: dstChanList = mc.listConnections(nodeChanList,s=False,d=True,p=True,c=True,sh=True) or [] else: dstChanList = mc.listConnections(node,s=False,d=True,p=True,c=True,sh=True) or [] - + # Add Channel Value Data for chan in valChanList: - + # Check Attribute #if not mc.attributeQuery(chan,n=node,ex=True): if not mc.objExists(node+'.'+chan): if self.verbosity > 0: print('ChannelData: Node "'+node+'" has no attribute "'+chan+'"! Skipping...') continue - + # Check Settable if not mc.getAttr(node+'.'+chan,se=True): if not mc.listConnections(node+'.'+chan,s=True,d=False): if self.verbosity > 0: print('ChannelData: Attribute "'+node+'.'+chan+'" is not settable! Skipping...') continue - + # Get Channel Value chanVal = None try: chanVal = mc.getAttr(node+'.'+chan) @@ -108,26 +108,26 @@ def buildData(self,nodeList=None,chanList=None): else: # Create Channel Entry if not self._channelData[node].has_key(chan): self._channelData[node][chan] = {} - + # Store Channel Value if not chanVal == None: if type(chanVal) == list: if type(chanVal[0]) == tuple: chanVal = list(chanVal[0]) self._channelData[node][chan]['value'] = chanVal - + # Add Channel Source Data for i in range(0,len(srcChanList),2): - + # Get Channel Name chan = str(srcChanList[i].replace(node+'.','')) - + # Create Channel Entry if not self._channelData[node].has_key(chan): self._channelData[node][chan] = {} - + # Store Channel Source Data self._channelData[node][chan]['source'] = srcChanList[i+1] - + # Store Channel Value Data try: chanVal = mc.getAttr(srcChanList[i]) except Exception, e: @@ -135,29 +135,29 @@ def buildData(self,nodeList=None,chanList=None): if self.verbosity > 1: print('ChannelData: Exception message: '+str(e)) else: self._channelData[node][chan]['value'] = chanVal - + # Add Channel Desitination Data for i in range(0,len(dstChanList),2): - + # Get Channel Name chan = dstChanList[i].replace(node+'.','') - + # Create Channel Entry if not self._channelData[node].has_key(chan): self._channelData[node][chan] = {} - + # Store Channel Desitination Data self._channelData[node][chan]['destination'] = dstChanList[i+1] - + # Print timer result buildTime = mc.timerX(st=timer) print('ChannelData: Data build time for nodes "'+str(nodeList)+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return self._data.keys() - + def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination=False): ''' Rebuild the channel values and connections from the stored ChannelData. @@ -167,55 +167,55 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= @type chanList: List @param connectSource: Attempt to restore all source connections. @type connectSource: bool - @param connectDestination: Attempt to restore all destination connections. + @param connectDestination: Attempt to restore all destination connections. @type connectDestination: bool ''' # ========== # - Checks - # ========== - + # Node List if not self._data['channelDataNodes']: raise Exception('ChannelData has not been initialized!') - + # ======================== # - Rebuild Channel Data - # ======================== - + # Start Timer timer = mc.timerX() - + # Get Node List if not nodeList: nodeList = self._data['channelDataNodes'] if not nodeList: print('ChannelData: No channel data nodes to rebuild!') return - + # Rebuild Node Channel Data for node in nodeList: - + # Check Node Key if not self._channelData.has_key(node): if self.verbosity > 0: print('ChannelData: No channel data stored for "'+node+'"!! Skipping...') - + # Get Node Channel List channelList = self._channelData[node].keys() - + # Rebuild Node Channel Data for chan in sorted(channelList): - + # Check Channel Exists if not mc.objExists(node+'.'+chan): if self.verbosity > 0: print('ChannelData: Channel "" does not exist! Unable to rebuild channel data! Skipping...') continue - + # Restore Channel Value if self._channelData[node][chan].has_key('value'): chanVal = self._channelData[node][chan]['value'] - + # Set Channel Value if mc.getAttr(node+'.'+chan,se=True): - + # Get Channel Type chanType = str(mc.getAttr(node+'.'+chan,type=True)) #print chanType @@ -243,13 +243,13 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= else: if self.verbosity > 0: print('ChannelData: Node channel "'+node+'.'+chan+'" is not settable!! Unable to restore channel value...') - + # Restore Channel Destination Connection if connectDestination: if self._channelData[node][chan].has_key('destination'): src = node+'.'+chan dst = self._channelData[node][chan]['destination'] - + # Check existing connections connect = True dstConn = mc.listConnections(dst,s=True,d=False,p=True,sh=True) @@ -257,7 +257,7 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= if dstConn[0] == src: if self.verbosity > 0: print('ChannelData: "'+src+'" already connected to "'+dst+'"! Skipping...') connect = False - + # Check Locked Destination if connect: dstLocked = mc.getAttr(dst,l=True) @@ -269,7 +269,7 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= connect = False else: if self.verbosity > 0: print('ChannelData: Unlocked channel "'+dst+'"') - + # Rebuild Connection if connect: try: mc.connectAttr(src,dst,f=True) @@ -285,14 +285,14 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= if self.verbosity > 1: print('ChannelData: Exception message '+str(e)) else: if self.verbosity > 0: print('ChannelData: Relocked channel "'+dst+'"') - + # Rebuild Channel Source Connection if connectSource: - + if self._channelData[node][chan].has_key('source'): src = self._channelData[node][chan]['source'] dst = node+'.'+chan - + # Check existing connections connect = True dstConn = mc.listConnections(dst,s=True,d=False,p=True,sh=True) @@ -300,7 +300,7 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= if dstConn[0] == src: if self.verbosity > 0: print('ChannelData: "'+src+'" already connected to "'+dst+'"! Skipping...') connect = False - + # Check Locked Destination if connect: dstLocked = mc.getAttr(dst,l=True) @@ -312,7 +312,7 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= connect = False else: if self.verbosity > 0: print('ChannelData: Unlocked channel "'+dst+'"') - + # Rebuild Connection if connect: try: mc.connectAttr(src,dst,f=True) @@ -328,17 +328,17 @@ def rebuild(self,nodeList=[],chanList=[],connectSource=False,connectDestination= if self.verbosity > 1: print('ChannelData: Exception message '+str(e)) else: if self.verbosity > 0: print('ChannelData: Relocked channel "'+dst+'"') - + # Print timer result buildTime = mc.timerX(st=timer) print('ChannelData: Rebuild time "'+str(nodeList)+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return nodeList - + def nodeChannels(self,node): ''' Return a list of stored channel data for the specified node. @@ -347,5 +347,5 @@ def nodeChannels(self,node): if self.verbosity > 0: print('ChannelData: No channel data stored for "'+node+'"!! Skipping...') channelList = sorted(self._channelData[node].keys()) return channelList - - + + diff --git a/data/clusterData.py b/data/clusterData.py index 8473d0f..74a5aca 100644 --- a/data/clusterData.py +++ b/data/clusterData.py @@ -14,15 +14,15 @@ def __init__(self): ''' # Execute Super Class Initilizer super(ClusterData, self).__init__() - + # Initialize Cluster Handle Data self._data['clusterHandle'] = '' - + # Deformer Attribute Connections #self._data['attrConnectionList'].append('matrix') self._data['attrConnectionList'].append('bindPreMatrix') self._data['attrConnectionList'].append('geomMatrix') - + def buildData(self,cluster): ''' Build ClusterData class data. @@ -31,42 +31,42 @@ def buildData(self,cluster): ''' # Verify node glTools.utils.base.verifyNode(cluster,'cluster') - + # Reset Data Object self.reset() - + # Buid Data super(ClusterData, self).buildData(cluster) - + # Store ClusterHandle Data clsHandle = mc.listConnections(cluster+'.matrix',s=True,d=False,sh=True) if clsHandle: self._data['clusterHandle'] = clsHandle[0] - + # Return Result return cluster - + def rebuild(self,overrides={}): ''' Rebuild the cluster deformer from the recorded deformerData - @param overrides: Dictionary of data overrides to apply + @param overrides: Dictionary of data overrides to apply @type overrides: dict ''' # Apply Overrides self._data.update(overrides) - + # ========== # - Checks - # ========== - + # Check target geometry for obj in self._data['affectedGeometry']: if not mc.objExists(obj): raise Exception('Deformer affected object "'+obj+'" does not exist!') - + # ==================== # - Rebuild Deformer - # ==================== - + # Build Cluster Deformer and Handle if not mc.objExists(self._data['name']): # Create New Cluster @@ -76,10 +76,10 @@ def rebuild(self,overrides={}): # Check Cluster if mc.objectType(self._data['name']) != 'cluster': raise Exception('Object "'+self._data['name']+'" is not a valid cluster deformer!') - + # Rebuild Deformer result = super(ClusterData, self).rebuild(overrides) - + # Restore ClusterHandle Data if self._data['clusterHandle']: if not mc.objExists(self._data['clusterHandle']): @@ -88,10 +88,10 @@ def rebuild(self,overrides={}): mc.cluster(self._data['name'],edit=True,bindState=True,wn=(self._data['clusterHandle'],self._data['clusterHandle'])) except: pass - + # ================= # - Return Result - # ================= - + return result - + diff --git a/data/compoundDeformerData.py b/data/compoundDeformerData.py index 22114c8..846a8ad 100644 --- a/data/compoundDeformerData.py +++ b/data/compoundDeformerData.py @@ -8,9 +8,9 @@ class CompoundDeformerData( data.Data ): CompoundDeformerData class object. Contains functions to save, load and rebuild ordered deformer data from a specified geometry. ''' - + TYPES = ['mesh','nurbsSurface','nurbsCurve','lattice','particle'] - + def __init__(self,geo=None): ''' CompoundDeformerData class initializer. @@ -18,23 +18,23 @@ def __init__(self,geo=None): # ================================== # - Execute Super Class Initilizer - # ================================== - + super(CompoundDeformerData, self).__init__() - + # ========================================= # - Initialize Default Class Data Members - # ========================================= - + self._data['geo'] = None self._data['geoType'] = None self._data['deformerData'] = [] - + # ============== # - Build Data - # ============== - + if geo: self.buildData(geo) - + def buildData(self,geo): ''' Build Compound Deformer Data. @@ -44,34 +44,34 @@ def buildData(self,geo): # ========== # - Checks - # ========== - + # Geometry if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') geoShapes = mc.ls(mc.listRelatives(geo,s=True,ni=True) or [],type=self.TYPES) if not geoShapes: raise Exception('Object "'+geo+'" has no valid geometry shapes!') - + self._data['geo'] = geo self._data['geoType'] = mc.objectType(geoShapes[0]) - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Get Ordered Deformer List deformerList = glTools.utils.deformer.getDeformerList(affectedGeometry=[geo],nodeType='geometryFilter') deformerList.reverse() - + # Build Deformer Data List for deformer in deformerList: - + # Check Deformer if not glTools.utils.deformer.isDeformer(deformer): continue - + # Build Deformer Data try: deformerData = glTools.data.utils.buildDeformerData(deformer) @@ -80,17 +80,17 @@ def buildData(self,geo): print('CompoundDeformerData: Error building deformerData for "'+deformer+'"! Skipping...') print(str(e)) continue - + # Get Timer Val buildTime = mc.timerX(st=timer) print('CompoundDeformerData: Data build time for "'+geo+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return deformerList - + def rebuild(self,deformList=None,overrides={}): ''' Rebuild deformers from the stored deformerData @@ -101,24 +101,24 @@ def rebuild(self,deformList=None,overrides={}): ''' # Apply Overrides self._data.update(overrides) - + # ========== # - Checks - # ========== - + # Check Geometry geo = self._data['geo'] if not mc.objExists(geo): raise Exception('CompoundDeformerData: Geometry "'+geo+'" does not exist!') - + # Check Deformer Data if not self._data['deformerData']: raise Exception('CompoundDeformerData: No deformerData stored!') - + # ===================== # - Rebuild Deformers - # ===================== - + deformerList = [] for deformerData in self._data['deformerData']: deformer = None @@ -127,13 +127,13 @@ def rebuild(self,deformList=None,overrides={}): print(str(e)) print('CompoundDeformerData: Error loading deformer data for "'+deformerData._data['name']+'"!') deformerList.append(deformer) - + # ================= # - Return Result - # ================= - + return deformerList - + def deformerList(self): ''' Return the list of deformers stored in the CompoundDeformerData object. diff --git a/data/constraintData.py b/data/constraintData.py index a457d97..0b3023c 100644 --- a/data/constraintData.py +++ b/data/constraintData.py @@ -12,38 +12,38 @@ class ConstraintData( data.Data ): # ============= # - CONSTANTS - # ============= - + TYPE = 'constraint' - + ATTR_VAL = [] ATTR_CON = [] - + INTERP = [ 'NoFlip', 'Average', 'Shortest', 'Longest', 'Cache' ] - + WORLD_UP = [ 'Scene Up', 'Object Up', 'Object Rotation Up', 'Vector', 'None' ] - + TRANSLATE = { 'x':'translateX', 'y':'translateY', 'z':'translateZ' } ROTATE = { 'x':'rotateX', 'y':'rotateY', 'z':'rotateZ' } - + def __init__(self,nodeList=None): ''' ConstraintData class initializer. ''' # Execute Super Class Initilizer super(ConstraintData, self).__init__() - + #self.attrValList.append('lockOutput') #self.attrValList.append('offset') #self.attrValList.append('offsetPolarity') @@ -56,24 +56,24 @@ def __init__(self,nodeList=None): #self.attrValList.append('worldUpVector') #self.attrValList.append('worldUpType') #self.attrConList.append('worldUpMatrix') - - + + # Build ChannelData if nodeList: self.buildData(nodeList) - + def name(self): ''' Return class name ''' return self.__class__.__name__ - + def verify(self): ''' Verify constraint data ''' if not self._data: raise Exception(self.name()+' has not been initialized! No data...') - + def buildData(self,nodeList): ''' Build ConstraintData. @@ -82,81 +82,81 @@ def buildData(self,nodeList): ''' # Check Node List if not nodeList: return - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Reset Data self.reset() - + # Build Constraint Data for constraint in nodeList: - + # Check Constraint if not glTools.utils.constraint.isConstraint(constraint): print(self.name()+': Object "'+constraint+'" is not a valid '+self.TYPE+'! Skipping...') continue - + # Initialize Constraint Data self._data[constraint] = {} - + # Constraint Type self._data[constraint]['type'] = mc.objectType(constraint) - + # Constraint Slave Transform slave = glTools.utils.constraint.slave(constraint) self._data[constraint]['slave'] = slave - + # Target List targetList = glTools.utils.constraint.targetList(constraint) self._data[constraint]['targetList'] = targetList self._data[constraint]['targetAliasList'] = [glTools.utils.constraint.targetAlias(constraint,target) for target in targetList] self._data[constraint]['targetIndex'] = [glTools.utils.constraint.targetIndex(constraint,target) for target in targetList] self._data[constraint]['targetWeight'] = [mc.getAttr(constraint+'.'+target) for target in targetList] - + # Constraint Slave Attributes constraintAttrs = [mc.ls(i,o=True)[0] for i in mc.listConnections(constraint,s=False,d=True,p=True,sh=True) or [] if i.startswith(slave+'.')] self._data[constraint]['skipTranslate'] = sorted([i for i in self.TRANSLATE.keys() if not self.TRANSLATE[i] in constraintAttrs]) self._data[constraint]['skipRotate'] = sorted([i for i in self.ROTATE.keys() if not self.ROTATE[i] in constraintAttrs]) - + # Print Timer Result buildTime = mc.timerX(st=timer) print(self.name()+': Data build time for nodes "'+str(nodeList)+'": '+str(buildTime)) - + # ======================== # - Build Attribute Data - # ======================== - + self.buildAttrValueData() self.buildAttrConnectionData() - + # ================= # - Return Result - # ================= - + return self._data - + def buildAttrValueData(self): ''' Build constraint attribute value data ''' # Verify Data self.verify() - + # ============================== # - Build Attribute Value Data - # ============================== - + for constraint in self._data.iterkeys(): - + # Check Constraint if not mc.objExists(constraint): print(self.name()+': '+self.TYPE+' "'+constraint+'" does not exist! Skipping...') - + # Build Attribute Value Data for attr in self.ATTR_VAL: if mc.attributeQuery(attr,n=constraint,ex=True): @@ -167,24 +167,24 @@ def buildAttrValueData(self): self._data[constraint][attr] = attrVal else: print(self.name()+': '+self.TYPE+' "'+constraint+'" has no attribute "'+attr+'"! Skipping...') - + def buildAttrConnectionData(self): ''' Build constraint attribute connection data ''' # Verify Data self.verify() - + # =================================== # - Build Attribute Connection Data - # =================================== - + for constraint in self._data.iterkeys(): - + # Check Constraint if not mc.objExists(constraint): print(self.name()+': '+self.TYPE+' "'+constraint+'" does not exist! Skipping...') - + # Build Attribute Connection Data for attr in self.ATTR_CON: if mc.attributeQuery(attr,n=constraint,ex=True): @@ -192,30 +192,30 @@ def buildAttrConnectionData(self): if attrCon: self._data[constraint][attr] = attrCon[0] else: print(self.name()+': '+self.TYPE+' "'+constraint+'" has no attribute "'+attr+'"! Skipping...') - + def restoreAttrValues(self): ''' Restore constraint attribute values. ''' # Verify Data self.verify() - + # ============================ # - Restore Attribute Values - # ============================ - + for constraint in self._data.iterkeys(): - + # Check Constraint if not mc.objExists(constraint): print(self.name()+': '+self.TYPE+' "'+constraint+'" does not exist! Unable to restore attribute values...') - + # For Each Attribute Value for attr in self.ATTR_VAL: - + # Check Attribute Value Data if self._data[constraint].has_key(attr): - + # Restore Attribute Value attrVal = self._data[constraint][attr] try: @@ -227,7 +227,7 @@ def restoreAttrValues(self): print(self.name()+': Unable to set constraint attribute value "'+constraint+'.'+attr+'"! Exception msg: '+str(e)) else: print(self.name()+': No attribute value data stored for "'+attr+'"! Skipping...') - + def restoreAttrConnections(self,force=False): ''' Restore constraint attribute connections. @@ -236,23 +236,23 @@ def restoreAttrConnections(self,force=False): ''' # Verify Data self.verify() - + # ================================= # - Restore Attribute Connections - # ================================= - + for constraint in self._data.iterkeys(): - + # Check Constraint if not mc.objExists(constraint): print(self.name()+': '+self.TYPE+' "'+constraint+'" does not exist! Unable to restore attribute values...') - + # For Each Attribute Connection for attr in self.ATTR_CON: - + # Check Attribute Connection Data if self._data[constraint].has_key(attr): - + # Retore Attribute Connection src = self._data[constraint][attr] if mc.objExists(src): @@ -262,7 +262,7 @@ def restoreAttrConnections(self,force=False): print(self.name()+': Attribute connection source "'+src+'" does not exist! Unable to restore attribute connection...') else: print(self.name()+': No attribute connection data stored for "'+attr+'"! Skipping...') - + def rebuild(self,nodeList=None): ''' Rebuild constraint(s) from data @@ -272,50 +272,50 @@ def rebuild(self,nodeList=None): # ========== # - Checks - # ========== - + self.verify() - + # =========================== # - Rebuild Constraint Data - # =========================== - + # Start timer timer = mc.timerX() - + # Get Node List if not nodeList: nodeList = self._data.keys() - + # ================================= # - Rebuild Constraints from Data - # ================================= - + print(self.name()+': Rebuilding Constraints...') - + constraintList = [] for constraint in nodeList: - + # Check Constraint Key if not self._data.has_key(constraint): print('No constraint data for "'+constraint+'"!! Skipping...') continue if not self._data[constraint]['type'] == 'aimConstraint': raise Exception('Invalid constraint data type! ('+self._data[constraint]['type']+')') - + # Rebuild Constraint print('REBUILDING - "'+constraint+'"...') constraintNode = self.rebuildConstraint(constraint) constraintList.append(constraintNode) - + # Print Timer Result buildTime = mc.timerX(st=timer) print(self.name()+': Rebuild time "'+str(nodeList)+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return constraintList - + def rebuildConstraint(self,constraint): ''' Rebuild single constraint using stored values. @@ -329,7 +329,7 @@ class AimConstraintData( ConstraintData ): ''' ''' TYPE = 'aimConstraint' - + ATTR_VAL = [ 'lockOutput', 'offset', 'enableRestPosition', @@ -338,9 +338,9 @@ class AimConstraintData( ConstraintData ): 'upVector', 'worldUpVector', 'worldUpType' ] - + ATTR_CON = [ 'worldUpMatrix' ] - + def rebuildConstraint(self,constraint): ''' Rebuild single constraint using stored values. @@ -353,20 +353,20 @@ def rebuildConstraint(self,constraint): skip=self._data[constraint]['skipRotate'], weight=self._data[constraint]['targetWeight'], name=constraint )[0] - + # Return Result return constraintNode - + class PointConstraintData( ConstraintData ): ''' ''' TYPE = 'pointConstraint' - + ATTR_VAL = [ 'lockOutput', 'offset', 'enableRestPosition', 'restTranslate' ] - + def rebuildConstraint(self,constraint): ''' Rebuild single constraint using stored values. @@ -379,7 +379,7 @@ def rebuildConstraint(self,constraint): skip=self._data[constraint]['skipTranslate'], weight=self._data[constraint]['targetWeight'], name=constraint )[0] - + # Return Result return constraintNode @@ -387,13 +387,13 @@ class OrientConstraintData( ConstraintData ): ''' ''' TYPE = 'pointConstraint' - + ATTR_VAL = [ 'lockOutput', 'offset', 'enableRestPosition', 'restRotate', 'interpType' ] - + def rebuildConstraint(self,constraint): ''' Rebuild single constraint using stored values. @@ -406,7 +406,7 @@ def rebuildConstraint(self,constraint): skip=self._data[constraint]['skipRotate'], weight=self._data[constraint]['targetWeight'], name=constraint )[0] - + # Return Result return constraintNode @@ -414,14 +414,14 @@ class ParentConstraintData( ConstraintData ): ''' ''' TYPE = 'parentConstraint' - + ATTR_VAL = [ 'lockOutput', 'offset', 'enableRestPosition', 'restTranslate', 'restRotate', 'interpType' ] - + def buildData(self,nodeList=None): ''' Build ConstraintData. @@ -430,32 +430,32 @@ def buildData(self,nodeList=None): ''' # Check Node List if not nodeList: return - + # Execute Super Class Build super(PointConstraintData, self).buildData(nodeList) - + # Target Offset Data for constraint in self._data.iterkeys(): - + # Initialize Offsets self._data[constraint]['targetOffsetTranslate'] = [] self._data[constraint]['targetOffsetRotate'] = [] - + # For Each Target targetList = self._data[constraint]['targetList'] for t in range(len(targetList)): - + # Get Target Index targetIndex = self._data[constraint]['targetIndex'][t] - + # Get Target Offset Data from Constraint offsetT = mc.getAttr(constraint+'.target['+str(targetIndex)+'].targetOffsetTranslate')[0] offsetR = mc.getAttr(constraint+'.target['+str(targetIndex)+'].targetOffsetRotate')[0] - - # Append Target Offset Lists + + # Append Target Offset Lists self._data[constraint]['targetOffsetTranslate'].append(offsetT) self._data[constraint]['targetOffsetRotate'].append(offsetR) - + def rebuildConstraint(self,constraint): ''' Rebuild single constraint using stored values. @@ -469,18 +469,18 @@ def rebuildConstraint(self,constraint): skipRotate=self._data[constraint]['skipRotate'], weight=self._data[constraint]['targetWeight'], name=constraint )[0] - + # Apply Target Offsets for target in range(len(constraintTarget)): - + # Get Target Index targetIndex = self._data[constraint]['targetIndex'][target] - + # Get Target Offset Data from Constraint offsetT = self._data[constraint]['targetOffsetTranslate'][target] offsetR = self._data[constraint]['targetOffsetRotate'][target] mc.setAttr(constraint+'.target['+str(targetIndex)+'].targetOffsetTranslate',offsetT) mc.setAttr(constraint+'.target['+str(targetIndex)+'].targetOffsetRotate',offsetR) - + # Return Result return constraintNode diff --git a/data/controlCurveData.py b/data/controlCurveData.py index f216cf1..9c9419e 100644 --- a/data/controlCurveData.py +++ b/data/controlCurveData.py @@ -16,9 +16,9 @@ def __init__(self): ''' # Execute Super Class Initilizer super(ControlCurveData, self).__init__() - + self.setWorldSpace = False - + def buildData(self,ctrls=[]): ''' Build Data @@ -28,7 +28,7 @@ def buildData(self,ctrls=[]): # ============================ # - Get Control Curve Shapes - # ============================ - + if not ctrls: ctrls = mc.ls('*.ctrlLod',o=True) #if not ctrls: ctrls = mc.ls(type='nurbsCurve',o=True) if not ctrls: raise Exception('No control curves specified!') @@ -36,40 +36,40 @@ def buildData(self,ctrls=[]): ctrlCurves = mc.ls(ctrlShapes,type='nurbsCurve') ctrlCurves += mc.ls(ctrls, type='nurbsCurve') or [] if not ctrlCurves: return - + # ============================= # - Record Control Curve Data - # ============================= - + # Reset Data self.reset() - + # Record Curve Data for ctrlCurve in ctrlCurves: - + # Get curve point list curveFn = glTools.utils.curve.getCurveFn(ctrlCurve) ptArray = OpenMaya.MPointArray() worldPtArray = OpenMaya.MPointArray() curveFn.getCVs(ptArray,OpenMaya.MSpace.kObject) curveFn.getCVs(worldPtArray,OpenMaya.MSpace.kWorld) - + # Build CV array cvArray = [] worldCvArray = [] for i in range(ptArray.length()): cvArray.append([ptArray[i].x,ptArray[i].y,ptArray[i].z]) worldCvArray.append([worldPtArray[i].x,worldPtArray[i].y,worldPtArray[i].z]) - + # Store cvArray self._data[ctrlCurve] = [ cvArray, worldCvArray ] - + # ================= # - Return Result - # ================= - + return ctrls - + def rebuild(self,ctrls=[]): ''' Build Data @@ -79,17 +79,17 @@ def rebuild(self,ctrls=[]): # ==================== # - Get Control List - # ==================== - + data_keys = self._data.keys() if not data_keys: return if not ctrls: ctrls = data_keys - + # ========================== # - Rebuild Control Shapes - # ========================== - + for ctrl in ctrls: - + # Check ctrl if not mc.objExists(ctrl): print ('ControlCurveData: Control Shape "'+ctrl+'" does not exist!') @@ -97,30 +97,30 @@ def rebuild(self,ctrls=[]): if not data_keys.count(ctrl): print ('ControlCurveData: No Data for Control Shape "'+ctrl+'"!') continue - + # Build Point Array ptArray = OpenMaya.MPointArray() - + if self.setWorldSpace: ctrlCrv = self._data[ctrl][1] else: ctrlCrv = self._data[ctrl][0] - + for cv in ctrlCrv: ptArray.append(OpenMaya.MPoint(cv[0],cv[1],cv[2],1.0)) - + # Set CV Positions curveFn = glTools.utils.curve.getCurveFn(ctrl) if self.setWorldSpace: curveFn.setCVs(ptArray,OpenMaya.MSpace.kWorld) else: curveFn.setCVs(ptArray,OpenMaya.MSpace.kObject) - + curveFn.updateCurve() - + # ================= # - Return Result - # ================= - + return ctrls diff --git a/data/data.py b/data/data.py index c95b635..291eb47 100644 --- a/data/data.py +++ b/data/data.py @@ -10,20 +10,20 @@ class Data( object ): Base Data Object Class Contains functions to save and load standard rig data. ''' - + def __init__(self): ''' Data Object Class Initializer ''' # Initialize Data self._data = {} - + # Initialize Data Type self.dataType = 'Data' - + # File Filter self.fileFilter = "All Files (*.*)" - + def save(self,filePath,force=False): ''' Save data object to file. @@ -35,40 +35,40 @@ def save(self,filePath,force=False): # Check Directory Path dirpath = os.path.dirname(filePath) if not os.path.isdir(dirpath): os.makedirs(dirpath) - + # Check File Path if os.path.isfile(filePath) and not force: raise Exception('File "'+filePath+'" already exists! Use "force=True" to overwrite the existing file.') - + # Save File fileOut = open(filePath,'wb') cPickle.dump(self,fileOut) fileOut.close() - + # Print Message print('Saved '+self.__class__.__name__+': "'+filePath+'"') - + # Return Result return filePath - + def saveAs(self): ''' Save data object to file. - Opens a file dialog, to allow the user to specify a file path. + Opens a file dialog, to allow the user to specify a file path. ''' # Specify File Path filePath = mc.fileDialog2(fileFilter=self.fileFilter,dialogStyle=2,fileMode=0,caption='Save As') - + # Check Path if not filePath: return filePath = filePath[0] - + # Save Data File filePath = self.save(filePath,force=True) - + # Return Result return filePath - + def load(self,filePath=''): ''' Load data object from file. @@ -83,18 +83,18 @@ def load(self,filePath=''): else: if not os.path.isfile(filePath): raise Exception('File "'+filePath+'" does not exist!') - + # Open File fileIn = open(filePath,'rb') dataIn = cPickle.load(fileIn) - + # Print Message dataType = dataIn.__class__.__name__ print('Loaded '+dataType+': "'+filePath+'"') - + # Return Result return dataIn - + def reset(self): ''' Reset data object diff --git a/data/deformerData.py b/data/deformerData.py index 65908cc..92a3934 100644 --- a/data/deformerData.py +++ b/data/deformerData.py @@ -24,29 +24,29 @@ def __init__(self,deformer=''): # ================================== # - Execute Super Class Initilizer - # ================================== - + super(DeformerData, self).__init__() - + # ========================================= # - Initialize Default Class Data Members - # ========================================= - + # Common Deformer Data self._data['name'] = '' self._data['type'] = '' self._data['affectedGeometry'] = [] - + # Deformer Attribute - Definition self._data['attrValueList'] = ['envelope'] self._data['attrConnectionList'] = [] - + # Deformer Attribute - Storage self._data['attrValueDict'] = {} self._data['attrConnectionDict'] = {} - + # Build Data if deformer: self.buildData(deformer) - + def buildData(self,deformer): ''' Build Deformer Data. @@ -56,34 +56,34 @@ def buildData(self,deformer): # ========== # - Checks - # ========== - + # Deformer if not deformer: return if not glTools.utils.deformer.isDeformer(deformer): raise Exception('Object '+deformer+' is not a valid deformer! Unable to instantiate DeformerData() class object!') - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Reset Data Object - (Maintain Incoming Attribute Lists) attrValueList = copy.deepcopy(self._data['attrValueList']) attrConnectionList = copy.deepcopy(self._data['attrConnectionList']) self.reset() self._data['attrValueList'] = copy.deepcopy(attrValueList) self._data['attrConnectionList'] = copy.deepcopy(attrConnectionList) - + # Get basic deformer info self._data['name'] = deformer self._data['type'] = mc.objectType(deformer) - + # Get geometry affected by deformer affectedGeo = glTools.utils.deformer.getAffectedGeometry(deformer,returnShapes=False) self._data['affectedGeometry'] = [str(i) for i in glTools.utils.arrayUtils.dict_orderedKeyListFromValues(affectedGeo)] - + # Build data lists for each affected geometry for geo in self._data['affectedGeometry']: geoShape = mc.listRelatives(geo,s=True,ni=True,pa=True)[0] @@ -92,92 +92,92 @@ def buildData(self,deformer): self._data[geo]['geometryType'] = str(mc.objectType(geoShape)) self._data[geo]['membership'] = glTools.utils.deformer.getDeformerSetMemberIndices(deformer,geo) self._data[geo]['weights'] = glTools.utils.deformer.getWeights(deformer,geo) - + if self._data[geo]['geometryType'] == 'mesh': self._data[geo]['mesh'] = meshData.MeshData(geo) - + # ========================= # - Custom Attribute Data - # ========================= - + # Add Pre-Defined Custom Attributes self.customDeformerAttributes(self._data['type']) self.getDeformerAttrValues() self.getDeformerAttrConnections() - + # Get Timer Val buildTime = mc.timerX(st=timer) print('DeformerData: Data build time for "'+deformer+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return deformer - + def rebuild(self,overrides={}): ''' Rebuild the deformer from the stored deformerData - @param overrides: Dictionary of data overrides to apply + @param overrides: Dictionary of data overrides to apply @type overrides: dict ''' # Apply Overrides self._data.update(overrides) - + # ========== # - Checks - # ========== - + # Check target geometry for geo in self._data['affectedGeometry']: if not mc.objExists(geo): raise Exception('Deformer ('+self._data['name']+') affected geometry "'+geo+'" does not exist!') - + # ==================== # - Rebuild Deformer - # ==================== - + # Start timer timer = mc.timerX() - + deformer = self._data['name'] if not mc.objExists(self._data['name']): deformer = mc.deformer(self.getMemberList(),typ=self._data['type'],n=deformer)[0] else: self.setDeformerMembership() - + # Set deformer weights self.loadWeights() - + # ================================ # - Set Deformer Attribute Values - # ================================ - + self.setDeformerAttrValues() self.setDeformerAttrConnections() - + # ================= # - Return Result - # ================= - + # Print Timed Result totalTime = mc.timerX(st=timer) print(self.__class__.__name__+': Rebuild time for deformer "'+deformer+'": '+str(totalTime)) - + return deformer - + def rename(self,name): ''' Rename deformer - @param name: New name for deformer + @param name: New name for deformer @type name: str ''' # Rename Deformer self._data['name'] = name - + # Return Result return self._data['name'] - + def remapGeometry(self,oldGeometry,newGeometry): ''' Remap the stored deformer data from one geometry to another. @@ -189,29 +189,29 @@ def remapGeometry(self,oldGeometry,newGeometry): # ========== # - Checks - # ========== - + if self._data.has_key(newGeometry): raise Exception('Deformer data for "'+newGeometry+'" already exists!!') if not self._data.has_key(oldGeometry): raise Exception('No deformer data stored for geometry "'+oldGeometry+'"!!') - + # ================== # - Remap Geometry - # ================== - + self._data[newGeometry] = self._data[oldGeometry] self._data.pop(oldGeometry) - + # Update Affected Geometry List oldGeometryId = self._data['affectedGeometry'].index(oldGeometry) self._data['affectedGeometry'][oldGeometryId] = newGeometry - + # ================= # - Return Result - # ================= - + return newGeometry - + def getMemberList(self,geoList=[]): ''' Return a list of component member names that can be passed to other functions/methods. @@ -221,11 +221,11 @@ def getMemberList(self,geoList=[]): # Check geoList if not geoList: geoList = self._data['affectedGeometry'] - + # Build member component list memberList = [] for geo in geoList: - + # Mesh if self._data[geo]['geometryType'] == 'mesh': if not self._data[geo]['membership']: @@ -233,7 +233,7 @@ def getMemberList(self,geoList=[]): else: for i in self._data[geo]['membership']: memberList.append(geo+'.vtx['+str(i)+']') - + # Curve if self._data[geo]['geometryType'] == 'nurbsCurve': if not self._data[geo]['membership']: @@ -241,7 +241,7 @@ def getMemberList(self,geoList=[]): else: for i in self._data[geo]['membership']: memberList.append(geo+'.cv['+str(i)+']') - + # Particle if self._data[geo]['geometryType'] == 'particle': if not self._data[geo]['membership']: @@ -249,7 +249,7 @@ def getMemberList(self,geoList=[]): else: for i in self._data[geo]['membership']: memberList.append(geo+'.pt['+str(i)+']') - + # Surface if self._data[geo]['geometryType'] == 'nurbsSurface': if not self._data[geo]['membership']: @@ -257,7 +257,7 @@ def getMemberList(self,geoList=[]): else: for i in self._data[geo]['membership']: memberList.append(geo+'.cv['+str(i[0])+']['+str(i[1])+']') - + # Lattice if self._data[geo]['geometryType'] == 'lattice': if not self._data[geo]['membership']: @@ -265,50 +265,50 @@ def getMemberList(self,geoList=[]): else: for i in self._data[geo]['membership']: memberList.append(geo+'.pt['+str(i[0])+']['+str(i[1])+']['+str(i[2])+']') - + # Return Result return memberList - + def setDeformerMembership(self,geoList=[]): ''' Set deformer membership based on stored deformerData. @param geoList: List of affected geometries to set deformer membership for @type geoList: str ''' - + # ========== # - Checks - # ========== - + # Check geometry list if not geoList: geoList = self._data['affectedGeometry'] - + # Check deformer deformer = self._data['name'] if not mc.objExists(deformer): raise Exception('Deformer "'+deformer+'" does not exist!') if not glTools.utils.deformer.isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # ========================= # - Get Deformer Set Data - # ========================= - + deformerSet = glTools.utils.deformer.getDeformerSet(deformer) - + for geo in geoList: - + # Get Current and Stored Member Data setMembers = self._data[geo]['membership'] currMembers = glTools.utils.deformer.getDeformerSetMemberIndices(deformer,geo) removeMembers = [i for i in currMembers if not setMembers.count(i)] - + # ========================= # - Remove Unused Members - # ========================= - + if removeMembers: - + # Mesh if self._data[geo]['geometryType'] == 'mesh': mc.sets([geo+'.vtx['+str(i)+']' for i in removeMembers],rm=deformerSet) @@ -324,13 +324,13 @@ def setDeformerMembership(self,geoList=[]): # Lattice if self._data[geo]['geometryType'] == 'lattice': mc.sets([geo+'.pt['+str(i[0])+']['+str(i[1])+']['+str(i[2])+']' for i in removeMembers],rm=deformerSet) - + # ========================= # - Add Remaining Members - # ========================= - + mc.sets(self.getMemberList([geo]),fe=deformerSet) - + def loadWeights(self,geoList=[]): ''' Load deformer weights for all affected geometry @@ -340,23 +340,23 @@ def loadWeights(self,geoList=[]): # ========== # - Checks - # ========== - + # Check Geometry List if not geoList: geoList = self._data['affectedGeometry'] - + # Check Deformer deformer = self._data['name'] if not mc.objExists(deformer): raise Exception('Deformer "'+deformer+'" does not exist!') if not glTools.utils.deformer.isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # ========================= # - Load Deformer Weights - # ========================= - + for geo in geoList: - + # Check Geometry if not mc.objExists(geo): print('Geometry "'+geo+'" does not exist! Skipping...') @@ -364,59 +364,59 @@ def loadWeights(self,geoList=[]): if not self._data.has_key(geo): print('No data stored for geometry "'+geo+'"! Skipping...') continue - + # Get stored weight values wt = self._data[geo]['weights'] - + # Apply defomer weights glTools.utils.deformer.setWeights(deformer,wt,geo) - + def mirrorWeights(): ''' ''' pass - + def flipWeights(): ''' ''' pass - + def rebuildMeshFromData(self,mesh): ''' Rebuild the specified mesh from the stored deformer data - @param mesh: Mesh to rebuild geometry from data for. + @param mesh: Mesh to rebuild geometry from data for. @type mesh: str ''' # Checks Mesh Data if not self._data.has_key(mesh): raise Exception('No data stored for mesh "'+mesh+'"!') - + # Rebuild Mesh mesh = self._data[mesh]['mesh'].rebuildMesh() - + # Return Result return mesh - + def rebuildMeshData(self,mesh,sourceMesh=''): ''' Rebuild the mesh data for the specified mesh. - @param mesh: Mesh to rebuild geometry from data for. + @param mesh: Mesh to rebuild geometry from data for. @type mesh: str - @param sourceMesh: The source mesh to rebuild the data from. + @param sourceMesh: The source mesh to rebuild the data from. @type sourceMesh: str ''' # Check Source Mesh if not sourceMesh: sourceMesh = mesh if not mc.objExists(sourceMesh): raise Exception('Source mesh "'+sourceMesh+'" does not exist! Unable to rebuild mesh data...') - + # Checks Mesh Data if not self._data.has_key(mesh): raise Exception('No data stored for mesh "'+mesh+'"!') - + # Rebuild Mesh Data mesh = self._data[mesh]['mesh'].buildData(sourceMesh) - + def rebuildWorldSpaceData(self,sourceGeo,targetGeo='',method='closestPoint'): ''' Rebuild the deformer membership and weight arrays for the specified geometry using the stored world space geometry data. @@ -429,37 +429,37 @@ def rebuildWorldSpaceData(self,sourceGeo,targetGeo='',method='closestPoint'): ''' # Start timer timer = mc.timerX() - + # Display Progress glTools.utils.progressBar.init(status=('Rebuilding world space deformer data...'),maxValue=100) - + # ========== # - Checks - # ========== - + # Target Geometry if not targetGeo: targetGeo = sourceGeo - + # Check Deformer Data if not self._data.has_key(sourceGeo): raise Exception('No deformer data stored for geometry "'+sourceGeo+'"!') - + # Check Geometry if not mc.objExists(targetGeo): raise Exception('Geometry "'+targetGeo+'" does not exist!') if not glTools.utils.mesh.isMesh(targetGeo): raise Exception('Geometry "'+targetGeo+'" is not a valid mesh!') - + # Check Mesh Data if not self._data[sourceGeo].has_key('mesh'): raise Exception('No world space mesh data stored for mesh geometry "'+sourceGeo+'"!') - + # ===================== # - Rebuild Mesh Data - # ===================== - + meshData = self._data[sourceGeo]['mesh']._data - + meshUtil = OpenMaya.MScriptUtil() numVertices = len(meshData['vertexList'])/3 numPolygons = len(meshData['polyCounts']) @@ -467,111 +467,111 @@ def rebuildWorldSpaceData(self,sourceGeo,targetGeo='',method='closestPoint'): polygonConnects = OpenMaya.MIntArray() meshUtil.createIntArrayFromList(meshData['polyCounts'],polygonCounts) meshUtil.createIntArrayFromList(meshData['polyConnects'],polygonConnects) - + # Rebuild Vertex Array vertexArray = OpenMaya.MFloatPointArray(numVertices,OpenMaya.MFloatPoint.origin) vertexList = [vertexArray.set(i,meshData['vertexList'][i*3],meshData['vertexList'][i*3+1],meshData['vertexList'][i*3+2],1.0) for i in xrange(numVertices)] - + # Rebuild Mesh meshFn = OpenMaya.MFnMesh() meshDataFn = OpenMaya.MFnMeshData().create() meshObj = meshFn.create(numVertices,numPolygons,vertexArray,polygonCounts,polygonConnects,meshDataFn) - + # Create Mesh Intersector meshPt = OpenMaya.MPointOnMesh() meshIntersector = OpenMaya.MMeshIntersector() if method == 'closestPoint': meshIntersector.create(meshObj) - + # ======================================== # - Rebuild Weights and Membership List - # ======================================== - + # Initialize Influence Weights and Membership new_weights = [] new_membership = [] - + # Get Target Mesh Data targetMeshFn = glTools.utils.mesh.getMeshFn(targetGeo) targetMeshPts = targetMeshFn.getRawPoints() numTargetVerts = targetMeshFn.numVertices() targetPtUtil = OpenMaya.MScriptUtil() - + # Initialize Float Pointers for Barycentric Coords uUtil = OpenMaya.MScriptUtil() vUtil = OpenMaya.MScriptUtil() uPtr = uUtil.asFloatPtr() vPtr = vUtil.asFloatPtr() - + # Get Progress Step progressInd = int(numTargetVerts*0.01) - + for i in range(numTargetVerts): - + # Get Target Point targetPt = OpenMaya.MPoint( targetPtUtil.getFloatArrayItem(targetMeshPts,(i*3)+0), targetPtUtil.getFloatArrayItem(targetMeshPts,(i*3)+1), targetPtUtil.getFloatArrayItem(targetMeshPts,(i*3)+2) ) - + # Get Closest Point Data meshIntersector.getClosestPoint(targetPt,meshPt) - + # Get Barycentric Coords meshPt.getBarycentricCoords(uPtr,vPtr) u = OpenMaya.MScriptUtil(uPtr).asFloat() v = OpenMaya.MScriptUtil(vPtr).asFloat() baryWt = [u,v,1.0-(u+v)] - + # Get Triangle Vertex IDs idUtil = OpenMaya.MScriptUtil() idPtr = idUtil.asIntPtr() meshFn.getPolygonTriangleVertices(meshPt.faceIndex(),meshPt.triangleIndex(),idPtr) - + # Calculate Weight and Membership wt = 0.0 isMember = False for n in range(3): - + # Get Triangle Vertex ID triId = OpenMaya.MScriptUtil().getIntArrayItem(idPtr,n) - + # Check Against Source Membership if self._data[sourceGeo]['membership'].count(triId): wtId = self._data[sourceGeo]['membership'].index(triId) wt += self._data[sourceGeo]['weights'][wtId] * baryWt[n] isMember = True - + # Check Weight if isMember: new_weights.append(wt) new_membership.append(i) - + # Update Progress Bar if not i % progressInd: glTools.utils.progressBar.update(step=1) - + # ======================== # - Update Deformer Data - # ======================== - + self._data[sourceGeo]['membership'] = new_membership self._data[sourceGeo]['weights'] = new_weights - + # ================= # - Return Result - # ================= - + # End Progress - glTools.utils.progressBar.end() - + glTools.utils.progressBar.end() + # Print Timed Result buildTime = mc.timerX(st=timer) print('DeformerData: Rebuild world space data for deformer "'+self._data['name']+'": '+str(buildTime)) - + # Return Weights return new_weights - + def getDeformerAttrValues(self): ''' - Get deformer attribute values based on the specified deformer attribute list. + Get deformer attribute values based on the specified deformer attribute list. ''' deformer = self._data['name'] # Get Custom Attribute Values @@ -580,7 +580,7 @@ def getDeformerAttrValues(self): self._data['attrConnectionList'].append(attr) else: self._data['attrValueDict'][attr] = mc.getAttr(deformer+'.'+attr) - + def getDeformerAttrConnections(self): ''' Get custom (non-standard) deformer attribute connections based on the specified deformer connection list. @@ -590,30 +590,30 @@ def getDeformerAttrConnections(self): for attr in self._data['attrConnectionList']: attrConn = mc.listConnections(deformer+'.'+attr,s=True,d=False,p=True,sh=True,skipConversionNodes=True) if attrConn: self._data['attrConnectionDict'][attr] = attrConn[0] - + def setDeformerAttrValues(self): ''' - Set deformer attribute values based on the stored deformer attribute data. + Set deformer attribute values based on the stored deformer attribute data. ''' # =============================== # - Set Custom Attribute Values - # =============================== - + for attr in self._data['attrValueDict'].iterkeys(): - + # Define Deformer Attribute deformerAttr = self._data['name']+'.'+attr - + # Check attribute exists if not mc.objExists(deformerAttr): print('Deformer attribute "'+deformerAttr+'" does not exist! Skipping...') continue - + # Check attribute is settable if not mc.getAttr(deformerAttr,se=True): print('Deformer attribute "'+deformerAttr+'" is not settable! Skipping...') continue - + # Set attribute attrVal = self._data['attrValueDict'][attr] # Check list value (ie. compound or multi value attribute result) @@ -623,7 +623,7 @@ def setDeformerAttrValues(self): mc.setAttr(deformerAttr,*attrVal) else: mc.setAttr(deformerAttr,attrVal) - + def setDeformerAttrConnections(self): ''' Set custom (non-standard) deformer attribute connections based on the stored deformer connection data. @@ -631,12 +631,12 @@ def setDeformerAttrConnections(self): # ==================================== # - Set Custom Attribute Connections - # ==================================== - + for attr in self._data['attrConnectionDict'].iterkeys(): - + # Define Deformer Attribute deformerAttr = self._data['name']+'.'+attr - + # Check connection destination if not mc.objExists(deformerAttr): print('Deformer attribute connection destination "'+deformerAttr+'" does not exist!('+self._data['name']+')') @@ -651,24 +651,24 @@ def setDeformerAttrConnections(self): continue # Create Connection mc.connectAttr(self._data['attrConnectionDict'][attr],deformerAttr,f=True) - + def customDeformerAttributes(self,deformerType): ''' ''' # Curve Twist if deformerType == 'curveTwist': - + self._data['attrValueList'].append('twistAngle') self._data['attrValueList'].append('twistType') self._data['attrValueList'].append('twistAxis') self._data['attrValueList'].append('distance') self._data['attrValueList'].append('scale') - + self._data['attrConnectionList'].append('twistCurve') - + # Directional Smooth elif deformerType == 'directionalSmooth': - + self._data['attrValueList'].append('iterations') self._data['attrValueList'].append('smoothFactor') self._data['attrValueList'].append('smoothMethod') @@ -680,17 +680,17 @@ def customDeformerAttributes(self,deformerType): self._data['attrValueList'].append('weightV') self._data['attrValueList'].append('weightN') self._data['attrValueList'].append('useReferenceUVs') - + self._data['attrConnectionList'].append('referenceMesh') - + # Strain Relaxer elif deformerType == 'strainRelaxer': - + self._data['attrValueList'].append('iterations') self._data['attrValueList'].append('bias') - + self._data['attrConnectionList'].append('refMesh') - + # Undefined else: pass @@ -702,10 +702,10 @@ class MultiInfluenceDeformerData( DeformerData ): the parent class for all other multiInfluence deformer data classes. """ def __init__(self): - + # Execute Super Class Initializer super(MultiInfluenceDeformerData, self).__init__() - + # Initialize Influence Data self._influenceData = {} @@ -723,7 +723,7 @@ def __init__(self): ''' # Execute Super Class Initilizer super(BulgeSkinBasicData, self).__init__() - + # Deformer Attribute Values self._data['attrValueList'].append('method') self._data['attrValueList'].append('projectPoint') @@ -734,7 +734,7 @@ def __init__(self): self._data['attrValueList'].append('averageNormal') self._data['attrValueList'].append('maxDistance') self._data['attrValueList'].append('collisionOffset') - + # Deformer Attribute Connections self._data['attrConnectionList'].append('collisionGeometry') self._data['attrConnectionList'].append('collisionMatrix') @@ -749,13 +749,13 @@ def __init__(self): ''' # Execute Super Class Initilizer super(BulgeSkinPrimData, self).__init__() - + # Deformer Attribute Values self._data['attrValueList'].append('projectMethod') self._data['attrValueList'].append('projectVector') self._data['attrValueList'].append('primitiveType') self._data['attrValueList'].append('primitiveSize') - + # Deformer Attribute Connections self._data['attrConnectionList'].append('primitiveMatrix') @@ -769,14 +769,14 @@ def __init__(self): ''' # Execute Super Class Initilizer super(CurveTwistData, self).__init__() - + # Deformer Attribute Values self._data['attrValueList'].append('twistAngle') self._data['attrValueList'].append('twistType') self._data['attrValueList'].append('twistAxis') self._data['attrValueList'].append('distance') self._data['attrValueList'].append('scale') - + # Deformer Attribute Connections self._data['attrConnectionList'].append('twistCurve') @@ -790,7 +790,7 @@ def __init__(self): ''' # Execute Super Class Initilizer super(DirectionalSmoothData, self).__init__() - + # Deformer Attribute Values self._data['attrValueList'].append('iterations') self._data['attrValueList'].append('smoothFactor') @@ -803,7 +803,7 @@ def __init__(self): self._data['attrValueList'].append('weightV') self._data['attrValueList'].append('weightN') self._data['attrValueList'].append('useReferenceUVs') - + # Deformer Attribute Connections self._data['attrConnectionList'].append('referenceMesh') @@ -817,7 +817,7 @@ def __init__(self): ''' # Execute Super Class Initilizer super(PeakDeformerData, self).__init__() - + # Deformer Attribute Values self._data['attrValueList'].append('peak') self._data['attrValueList'].append('bulge') @@ -834,12 +834,12 @@ def __init__(self): ''' # Execute Super Class Initilizer super(StrainRelaxerData, self).__init__() - + # Deformer Attribute Values self._data['attrValueList'].append('iterations') self._data['attrValueList'].append('bias') - + # Deformer Attribute Connections self._data['attrConnectionList'].append('refMesh') - + diff --git a/data/graphConnectionData.py b/data/graphConnectionData.py index cc17504..ef98cc1 100644 --- a/data/graphConnectionData.py +++ b/data/graphConnectionData.py @@ -8,24 +8,24 @@ import data class GraphConnectionData(data.Data): - + def __init__(self, nodeList=[], filePath=None): ''' GraphConnectionData class initializer. ''' # Execute Super Class Initilizer super(GraphConnectionData, self).__init__() - + self._data['filePath'] = filePath self.dataType = 'GraphConnectionData' - + self.fileFilter = "All Files (*.*)" # Build ChannelData if nodeList: self.buildData(nodeList) - - self.nodeList = nodeList - + + self.nodeList = nodeList + def save(self,filePath,force=False): ''' Save mayaBinary to disk. @@ -33,40 +33,40 @@ def save(self,filePath,force=False): @type filePath: str @param force: Force save if file already exists. (Overwrite). @type force: bool - ''' + ''' # Check Directory Path dirpath = os.path.dirname(filePath) if not os.path.isdir(dirpath): os.makedirs(dirpath) - + fileWoExtension = filePath.split('.')[0] mayaFilePath = '%s.mb' % fileWoExtension pklFilePath = '%s.pkl' % fileWoExtension - + self._data['filePath'] = mayaFilePath - + # Check File Path for .mb file if os.path.isfile(mayaFilePath) and not force: raise Exception('File "'+mayaFilePath+'" already exists! Use "force=True" to overwrite the existing file.') - + # Check File Path for .pkl file if os.path.isfile(pklFilePath) and not force: raise Exception('File "'+pklFilePath+'" already exists! Use "force=True" to overwrite the existing file.') - + # save maya file mc.select(cl=True) mc.select(self.nodeList) mc.file(mayaFilePath, force=force, type="mayaBinary", exportSelected=True, ch=False, channels=False ) mc.select(cl=True) - + # Save pkl File fileOut = open(pklFilePath,'wb') cPickle.dump(self,fileOut) fileOut.close() - + # Print Message print 'Saved %s : %s' % (self.__class__.__name__, mayaFilePath) print 'Saved %s : %s' % (self.__class__.__name__, pklFilePath) - + def load(self,filePath=''): ''' Load data mayaBinary from file. @@ -85,106 +85,106 @@ def load(self,filePath=''): # Open File fileIn = open(filePath,'rb') dataIn = cPickle.load(fileIn) - + # Print Message dataType = dataIn.__class__.__name__ print('Loaded '+dataType+': "'+filePath+'"') - + self._data = dataIn - + # Return Result return dataIn - + def importFile(self): self.mayaFilePath = self._data['filePath'] print "Loading maya file :: %s" % self.mayaFilePath - + # Open File - try: + try: self.nodeList = mc.file(self.mayaFilePath, type="mayaBinary", i=True, returnNewNodes=True) - except: + except: raise Exception ("Could not load %s" % self.mayaFilePath) - + # Print Message print('Loaded "GraphConnectionData" : '+self.mayaFilePath+'"') - + def restoreConnections(self): if not self.nodeList: raise Exception("No nodes specified") - + # Start timer timer = mc.timerX() - + # init ConnectionAttrStorage object attrStorage = glTools.tools.connectionAttrStorage.ConnectionAttrStorage() - + # Add the nodes from the maya file attrStorage.addNodes(self.nodeList) - + # get the connection data off the attrs attrStorage.getAttrs() - + # re-establish connections attrStorage.rebuildConnections() - + # Print Timer Result buildTime = mc.timerX(st=timer) print('SetData: Rebuild time : '+str(buildTime)) - + def rebuild(self): - + self.importFile() - + self.restoreConnections() - - + + def buildData(self,nodeList=None): ''' Build GraphConnectionData class. @param nodeList: List of nodes to store connections for. @type nodeList: list - ''' + ''' # Node List if not nodeList: print('GraphConnectionData: Empty node list! Unable to build GraphConnectionData!') return - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Reset Data --- ? self.reset() - + self.nodeList = nodeList - + cas = glTools.tools.connectionAttrStorage.ConnectionAttrStorage() - + # set the nodes to operate on cas.addNodes(nodeList) - + # get the parents cas.getParent() - + # get connections cas.getIncomingConnections() cas.getOutgoingConnections() - + # Create attributes to store connections cas.createAttrs() - + # set all the collected data into the attrs cas.setAttrs() - - + + def reset(self): ''' Reset data object ''' self.__init__() - + diff --git a/data/latticeData.py b/data/latticeData.py index ac2e32b..af85df7 100644 --- a/data/latticeData.py +++ b/data/latticeData.py @@ -13,22 +13,22 @@ def __init__(self,deformer=None): # Update Attr Value/Connection List #self._data['attrValueList'] #self._data['attrConnectionList'] - + # Execute Super Class Initilizer super(LatticeData, self).__init__(deformer) - + def buildData(self,deformer): ''' ''' # ========== # - Checks - # ========== - + # Verify node lattice = deformer if not mc.objExists(lattice): raise Exception('Lattice deformer '+lattice+' does not exists! No influence data recorded!!') - + objType = mc.objectType(lattice) if objType == 'transform': lattice = mc.listRelatives(lattice,s=True,ni=True)[0] @@ -38,11 +38,11 @@ def buildData(self,deformer): objType = mc.objectType(lattice) if objType != 'ffd': raise Exception('Object '+lattice+' is not a vaild lattice deformer! Incorrect class for node type '+objType+'!!') - + # ===================== # - Get Deformer Data - # ===================== - + # FFD Attributes self.local = mc.getAttr(lattice+'.local') self.outside = mc.getAttr(lattice+'.outsideLattice') @@ -53,22 +53,22 @@ def buildData(self,deformer): self.localInfluenceS = mc.getAttr(lattice+'.localInfluenceS') self.localInfluenceT = mc.getAttr(lattice+'.localInfluenceT') self.localInfluenceU = mc.getAttr(lattice+'.localInfluenceU') - + # Get Input Lattice and Base self.latticeShape = mc.listConnections(lattice+'.deformedLatticePoints',sh=True)[0] self.lattice = mc.listRelatives(self.latticeShape,p=True)[0] self.latticeBaseShape = mc.listConnections(lattice+'.baseLatticeMatrix',sh=True)[0] self.latticeBase = mc.listRelatives(self.latticeBaseShape,p=True)[0] - + # Get Lattice Data self.sDivisions = mc.getAttr(self.latticeShape+'.sDivisions') self.tDivisions = mc.getAttr(self.latticeShape+'.tDivisions') self.uDivisions = mc.getAttr(self.latticeShape+'.uDivisions') self.latticeXform = mc.xform(self.lattice,q=True,ws=True,m=True) - + # Get Lattice Base Data self.baseXform = mc.xform(self.latticeBase,q=True,ws=True,m=True) - + def rebuild(self): ''' Rebuild the lattice deformer from the recorded deformerData @@ -78,7 +78,7 @@ def rebuild(self): lattice = ffd[0] latticeShape = ffd[1] latticeBase = ffd[2] - + # Set Deformer Attributes mc.setAttr(lattice+'.local',self.local) mc.setAttr(lattice+'.outsideLattice',self.outside) @@ -89,15 +89,15 @@ def rebuild(self): mc.setAttr(lattice+'.localInfluenceS',self.localInfluenceS) mc.setAttr(lattice+'.localInfluenceT',self.localInfluenceT) mc.setAttr(lattice+'.localInfluenceU',self.localInfluenceU) - + # Set Lattice Shape Attributes mc.setAttr(latticeShape+'.sDivisions',self.sDivisions) mc.setAttr(latticeShape+'.tDivisions',self.tDivisions) mc.setAttr(latticeShape+'.uDivisions',self.uDivisions) - + # Restore World Transform Data mc.xform(lattice,ws=True,m=self.latticeXform) mc.xform(latticeBase,ws=True,m=self.baseXform) - + # Return result return lattice diff --git a/data/mayaData.py b/data/mayaData.py index 3940464..1029296 100644 --- a/data/mayaData.py +++ b/data/mayaData.py @@ -9,38 +9,38 @@ class MayaData( data.Data ): Maya Data Object Class Contains functions to save and load standard maya data. ''' - + def __init__(self): ''' Data Object Class Initializer ''' # Execute Super Class Initilizer super(MayaData, self).__init__() - + # Initialize Data Type self.dataType = 'MayaData' - + # File Filter self.fileFilter = "All Files (*.*)" - + def saveAs(self): ''' Save data object to file. - Opens a file dialog, to allow the user to specify a file path. + Opens a file dialog, to allow the user to specify a file path. ''' # Specify File Path filePath = mc.fileDialog2(fileFilter=self.fileFilter,dialogStyle=2,caption='Save As') - + # Check Path if not filePath: return filePath = filePath[0] - + # Save Data File self.save(filePath,force=True) - + # Return Result return filePath - + def load(self,filePath=''): ''' Load data object from file. @@ -55,11 +55,11 @@ def load(self,filePath=''): else: if not os.path.isfile(filePath): raise Exception('File "'+filePath+'" does not exist!') - + # Open File dataIn = super(MayaData, self).load(filePath) - + # Return Result return dataIn - + diff --git a/data/meshData.py b/data/meshData.py index 63a3ff2..fbab1e0 100644 --- a/data/meshData.py +++ b/data/meshData.py @@ -20,18 +20,18 @@ def __init__(self,mesh=''): # Initialize Class Defaults self.maxDist = 9999999.9 - + # Initialize Default Class Data Members self._data['name'] = '' self._data['vertexList'] = [] self._data['polyCounts'] = [] self._data['polyConnects'] = [] - + self._data['uvCounts'] = [] self._data['uvIds'] = [] self._data['uArray'] = [] self._data['vArray'] = [] - + # Build Data if mesh: self.buildData(mesh) @@ -44,18 +44,18 @@ def buildData(self,mesh): # ========== # - Checks - # ========== - + # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a vaild Mesh node!') - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Get basic mesh info self._data['name'] = mesh @@ -74,18 +74,18 @@ def buildData(self,mesh): numVerts = meshFn.numVertices() meshPtUtil = OpenMaya.MScriptUtil() self._data['vertexList'] = [meshPtUtil.getFloatArrayItem(meshPts,i) for i in xrange(numVerts*3)] - + # ======= # - UVs - # ======= - + # UV Connect Data uvCounts = OpenMaya.MIntArray() uvIds = OpenMaya.MIntArray() meshFn.getAssignedUVs(uvCounts,uvIds) self._data['uvCounts'] = list(uvCounts) self._data['uvIds'] = list(uvIds) - + # Get UVs uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() @@ -96,11 +96,11 @@ def buildData(self,mesh): # Print timer result buildTime = mc.timerX(st=timer) print('MeshData: Data build time for mesh "'+mesh+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return self._data['name'] def rebuild(self): @@ -117,7 +117,7 @@ def rebuild(self): polygonConnects = OpenMaya.MIntArray() meshUtil.createIntArrayFromList(self._data['polyCounts'],polygonCounts) meshUtil.createIntArrayFromList(self._data['polyConnects'],polygonConnects) - + # Rebuild UV Data uvCounts = OpenMaya.MIntArray() uvIds = OpenMaya.MIntArray() @@ -143,10 +143,10 @@ def rebuild(self): uArray, vArray, meshData ) - + # Assign UVs meshFn.assignUVs(uvCounts,uvIds) - + meshObjHandle = OpenMaya.MObjectHandle(meshObj) # Print Timed Result @@ -156,7 +156,7 @@ def rebuild(self): # ================= # - Return Result - # ================= - + return meshObjHandle def rebuildMesh(self): @@ -174,7 +174,7 @@ def rebuildMesh(self): polygonConnects = OpenMaya.MIntArray() meshUtil.createIntArrayFromList(self._data['polyCounts'],polygonCounts) meshUtil.createIntArrayFromList(self._data['polyConnects'],polygonConnects) - + # Rebuild UV Data uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() @@ -199,7 +199,7 @@ def rebuildMesh(self): uArray, vArray, meshData ) - + # Assign UVs meshFn.assignUVs(uvCounts,uvIds) @@ -217,5 +217,5 @@ def rebuildMesh(self): # ================= # - Return Result - # ================= - + return mesh diff --git a/data/meshIntersectData.py b/data/meshIntersectData.py index 0a5e3dd..2f43964 100644 --- a/data/meshIntersectData.py +++ b/data/meshIntersectData.py @@ -70,14 +70,14 @@ def getClosestPointList(self,ptList): # ================= # - Return Result - # ================= - + # End Progress - if showProgress: glTools.utils.progressBar.end() + if showProgress: glTools.utils.progressBar.end() # Print timer result buildTime = mc.timerX(st=timer) print('MeshIntersectData: Closest Point search time for mesh "'+self._data['name']+'": '+str(buildTime)) - + return pntList def getClosestPointCoords(self,ptList): @@ -88,7 +88,7 @@ def getClosestPointCoords(self,ptList): # Display Progress glTools.utils.progressBar.init(status=('Building Closest Point Coord Array...'),maxValue=int(len(ptList)*0.1)) - + # ===================== # - Rebuild Mesh Data - # ===================== @@ -147,12 +147,12 @@ def getClosestPointCoords(self,ptList): # ================= # - Return Result - # ================= - + # End Progress - if showProgress: glTools.utils.progressBar.end() - + if showProgress: glTools.utils.progressBar.end() + # Print timer result buildTime = mc.timerX(st=timer) print('MeshIntersectData: Data search time for mesh "'+self._data['name']+'": '+str(buildTime)) - + return baryCoords diff --git a/data/nConstraintData.py b/data/nConstraintData.py index b93c85e..2e885f0 100644 --- a/data/nConstraintData.py +++ b/data/nConstraintData.py @@ -17,15 +17,15 @@ def __init__(self,nConstraint=None): ''' # Execute Super Class Initilizer super(NConstraintData, self).__init__() - + # Initialize Default Class Data Members self._data['name'] = '' self._data['membership'] = [] self.mode = ['add','replace'] - + # Build Data if setNode: self.buildData(nConstraint) - + def buildData(self,nConstraint): ''' Build setData class. @@ -35,83 +35,83 @@ def buildData(self,nConstraint): # ========== # - Checks - # ========== - + if not glTools.utils.nDynamics.isNConstraint(nConstraint): raise Exception('Object "'+nConstraint+'" is not a valid nDynamics constraint!') - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Reset Data self.reset() - + # Get nDynamics info self._data['name'] = nConstraint self._data['nucleus'] = glTools.utils.nDynamics.getConnectedNucleus(nConstraint) self._data['nComponent'] = glTools.utils.nDynamics.getConnectedNComponent(nConstraint) self._data['nMesh'] = glTools.utils.nDynamics.getConnectedMesh(self._data['nComponent']) self._data['componentIndices'] = mc.getAttr(self._data['nComponent']+'.componentIndices')[0] - + # Print timer result buildTime = mc.timerX(st=timer) print('NConstraintData: Data build time for set "'+nConstraint+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return self._data['name'] - + def rebuild(self): ''' Rebuild the set from the stored setData. @param mode: Membership mode if the specified set already exists. Accepted values are "add" and "replace". @type mode: str - @param forceMembership: Forces addition of items to the set. If items are in another set which is in the same partition as the given set, the items will be removed from the other set in order to keep the sets in the partition mutually exclusive with respect to membership. + @param forceMembership: Forces addition of items to the set. If items are in another set which is in the same partition as the given set, the items will be removed from the other set in order to keep the sets in the partition mutually exclusive with respect to membership. @type forceMembership: bool ''' # ========== # - Checks - # ========== - + # Set Name if not self._data['name']: raise Exception('SetData has not been initialized!') - + # Member Items memberList = self._data['membership'] or [] for obj in memberList: if not mc.objExists(obj): print('Set member item "'+obj+'" does not exist! Unable to add to set...') memberList.remove(obj) - + # Flatten Membership List memberList = mc.ls(memberList,fl=True) or [] - + # Mode if not mode in self.mode: raise Exception('Invalid set membership mode "'+mode+'"! Use "add" or "replace"!') - + # =============== # - Rebuild Set - # =============== - + # Start timer timer = mc.timerX() - + # Create Set setName = self._data['name'] - + # Delete Set (REPLACE only) if mc.objExists(setName) and mode == 'replace': mc.delete(setName) - + # Create Set if not mc.objExists(setName): setName = mc.sets(n=setName) - + # Add Members if memberList: if forceMembership: @@ -126,20 +126,20 @@ def rebuild(self): except Exception, e: print('Error adding item "'+obj+'" to set "'+setName+'"! Skipping') print(str(e)) - + # Print Timer Result buildTime = mc.timerX(st=timer) print('SetData: Rebuild time for set "'+setName+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + self.setName = setName - + result = {} result['set'] = setName result['membership'] = memberList return result - + diff --git a/data/nurbsCurveData.py b/data/nurbsCurveData.py index 5dd1f23..2afa4f3 100644 --- a/data/nurbsCurveData.py +++ b/data/nurbsCurveData.py @@ -39,56 +39,56 @@ def buildData(self,curve,worldSpace=False): # ========== # - Checks - # ========== - + # Check Curve if not glTools.utils.curve.isCurve(curve): raise Exception('Object "'+curve+'" is not a vaild NURBS curve node!') - + # World Space space = OpenMaya.MSpace.kObject if worldSpace: space = OpenMaya.MSpace.kWorld - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Get basic curve info self._data['name'] = curve # Get Curve Function Class curveFn = glTools.utils.curve.getCurveFn(curve) - + # Get Curve Degree and Form self._data['degree'] = curveFn.degreeU() self._data['form'] = int(curveFn.formInU()) - + # Get Curve Knots knotArray = OpenMaya.MDoubleArray() curveFn.getKnotsInU(knotArray) self._data['knots'] = list(knotArray) - + # Get Control Vertices cvArray = OpenMaya.MPointArray() curveFn.getCVs(cvArray,space) self._data['cv'] = [(cvArray[i].x,cvArray[i].y,cvArray[i].z) for i in range(cvArray.length())] - + # Get Edit Points editPt = OPenMaya.MPoint() for u in self._data['knots']: curveFn.getPointAtParam(u,editPt,space) self._data['editPt'].append((editPt.x,editPt.y,editPt.z)) - + # ================= # - Return Result - # ================= - + # Print timer result buildTime = mc.timerX(st=timer) print('NurbsCurveData: Data build time for curve "'+curve+'": '+str(buildTime)) - + return self._data['name'] def rebuild(self): @@ -100,13 +100,13 @@ def rebuild(self): # ======================== # - Rebuild Curve Data - # ======================== - + # Rebuild Control Vertices numCVs = len(self._data['cv']) cvArray = OpenMaya.MPointArray(numCVs,OpenMaya.MPoint.origin) for i in range(numCVs): cvArray.set(OpenMaya.MPoint(self._data['cv'][i][0],self._data['cv'][i][1],self._data['cv'][i][2],1.0),i) - + # Rebuild Curve Knot Arrays numKnots = len(self._data['knots']) knots = OpenMaya.MDoubleArray(numKnots,0) @@ -127,11 +127,11 @@ def rebuild(self): # ================= # - Return Result - # ================= - + # Print Timed Result buildTime = mc.timerX(st=timer) print('NurbsCurveData: Data rebuild time for curve "'+self._data['name']+'": '+str(buildTime)) - + return curveObjHandle def rebuildCurve(self): @@ -139,22 +139,22 @@ def rebuildCurve(self): ''' # Start timer timer = mc.timerX() - + # ======================== # - Rebuild Curve Data - # ======================== - + # Rebuild Control Vertices numCVs = len(self._data['cv']) cvArray = OpenMaya.MPointArray(numCVs,OpenMaya.MPoint.origin) for i in range(numCVs): cvArray.set(OpenMaya.MPoint(self._data['cv'][i][0],self._data['cv'][i][1],self._data['cv'][i][2],1.0),i) - + # Rebuild Curve Knot Arrays numKnots = len(self._data['knots']) knots = OpenMaya.MDoubleArray(numKnots,0) for i in range(numKnots): knots.set(self._data['knots'][i],i) - + # Rebuild Curve curveFn = OpenMaya.MFnMesh() curveData = OpenMaya.MObject() @@ -168,13 +168,13 @@ def rebuildCurve(self): # Rename Curve curve = OpenMaya.MFnDependencyNode(curveObj).setName(self._data['name']) - + # ================= # - Return Result - # ================= - + # Print timer result buildTime = mc.timerX(st=timer) print('NurbsCurveData: Geometry rebuild time for mesh "'+curve+'": '+str(buildTime)) - + return curve diff --git a/data/nurbsSurfaceData.py b/data/nurbsSurfaceData.py index c520677..553cd26 100644 --- a/data/nurbsSurfaceData.py +++ b/data/nurbsSurfaceData.py @@ -39,34 +39,34 @@ def buildData(self,surface,worldSpace=False): # ========== # - Checks - # ========== - + # Check Surface if not glTools.utils.surface.isSurface(surface): raise Exception('Object "'+surface+'" is not a vaild NURBS surface node!') - + # World Space space = OpenMaya.MSpace.kObject if worldSpace: space = OpenMaya.MSpace.kWorld - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Get basic surface info self._data['name'] = surface # Get Surface Function Class surfaceFn = glTools.utils.surface.getSurfaceFn(surface) - + # Get Surface Degree and Form self._data['degreeU'] = surfaceFn.degreeU() self._data['degreeV'] = surfaceFn.degreeV() self._data['formU'] = int(surfaceFn.formInU()) self._data['formV'] = int(surfaceFn.formInV()) - + # Get Surface Knots knotsUarray = OpenMaya.MDoubleArray() knotsVarray = OpenMaya.MDoubleArray() @@ -79,15 +79,15 @@ def buildData(self,surface,worldSpace=False): cvArray = OpenMaya.MPointArray() surfaceFn.getCVs(cvArray,space) self._data['cv'] = [(cvArray[i].x,cvArray[i].y,cvArray[i].z) for i in range(cvArray.length())] - + # ================= # - Return Result - # ================= - + # Print timer result buildTime = mc.timerX(st=timer) print('NurbsSurfaceData: Data build time for surface "'+surface+'": '+str(buildTime)) - + return self._data['name'] def rebuild(self): @@ -99,13 +99,13 @@ def rebuild(self): # ======================== # - Rebuild Surface Data - # ======================== - + # Rebuild Control Vertices numCVs = len(self._data['cv']) cvArray = OpenMaya.MPointArray(numCVs,OpenMaya.MPoint.origin) for i in range(numCVs): cvArray.set(OpenMaya.MPoint(self._data['cv'][i][0],self._data['cv'][i][1],self._data['cv'][i][2],1.0),i) - + # Rebuild Surface Knot Arrays numKnotsU = len(self._data['knotsU']) numKnotsV = len(self._data['knotsV']) @@ -131,11 +131,11 @@ def rebuild(self): # ================= # - Return Result - # ================= - + # Print Timed Result buildTime = mc.timerX(st=timer) print('NurbsSurfaceData: Data rebuild time for surface "'+self._data['name']+'": '+str(buildTime)) - + return surfaceObjHandle def rebuildSurface(self): @@ -143,17 +143,17 @@ def rebuildSurface(self): ''' # Start timer timer = mc.timerX() - + # ======================== # - Rebuild Surface Data - # ======================== - + # Rebuild Control Vertices numCVs = len(self._data['cv']) cvArray = OpenMaya.MPointArray(numCVs,OpenMaya.MPoint.origin) for i in range(numCVs): cvArray.set(OpenMaya.MPoint(self._data['cv'][i][0],self._data['cv'][i][1],self._data['cv'][i][2],1.0),i) - + # Rebuild Surface Knot Arrays numKnotsU = len(self._data['knotsU']) numKnotsV = len(self._data['knotsV']) @@ -185,9 +185,9 @@ def rebuildSurface(self): # ================= # - Return Result - # ================= - + # Print timer result buildTime = mc.timerX(st=timer) print('NurbsSurfaceData: Geometry rebuild time for surface "'+surface+'": '+str(buildTime)) - + return surface diff --git a/data/setData.py b/data/setData.py index dc7b49d..5c5b4ff 100644 --- a/data/setData.py +++ b/data/setData.py @@ -10,19 +10,19 @@ class SetData( data.Data ): def __init__(self,setNode=None): ''' SetData class initializer. - + ''' # Execute Super Class Initilizer super(SetData, self).__init__() - + # Initialize Default Class Data Members self._data['name'] = '' self._data['membership'] = [] self.mode = ['add','replace'] - + # Build Data if setNode: self.buildData(setNode) - + def verifySet(self,setNode): ''' Run standard checks on the specified set @@ -32,11 +32,11 @@ def verifySet(self,setNode): # Check Set Exists if not mc.objExists(setNode): raise Exception('Set "'+setNode+'" does not exists!') - + # Check Set Node Type if mc.objectType(setNode) != 'objectSet': raise Exception('Object "'+setNode+'" is not a vaild "set" node!') - + def buildData(self,setNode): ''' Build setData class. @@ -46,83 +46,83 @@ def buildData(self,setNode): # ========== # - Checks - # ========== - + if not setNode: raise Exception('Invalid set node! Unable to build setData...') return - + self.verifySet(setNode) - + # ============== # - Build Data - # ============== - + # Start timer timer = mc.timerX() - + # Reset Data self.reset() - + # Get basic set info self._data['name'] = setNode self._data['membership'] = mc.sets(setNode,q=True) - + # Print timer result buildTime = mc.timerX(st=timer) print('SetData: Data build time for set "'+setNode+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + return self._data['name'] - + def rebuild(self,mode='add',forceMembership=True): ''' Rebuild the set from the stored setData. @param mode: Membership mode if the specified set already exists. Accepted values are "add" and "replace". @type mode: str - @param forceMembership: Forces addition of items to the set. If items are in another set which is in the same partition as the given set, the items will be removed from the other set in order to keep the sets in the partition mutually exclusive with respect to membership. + @param forceMembership: Forces addition of items to the set. If items are in another set which is in the same partition as the given set, the items will be removed from the other set in order to keep the sets in the partition mutually exclusive with respect to membership. @type forceMembership: bool ''' # ========== # - Checks - # ========== - + # Set Name if not self._data['name']: raise Exception('SetData has not been initialized!') - + # Member Items memberList = self._data['membership'] or [] for obj in memberList: if not mc.objExists(obj): print('Set member item "'+obj+'" does not exist! Unable to add to set...') memberList.remove(obj) - + # Flatten Membership List memberList = mc.ls(memberList,fl=True) or [] - + # Mode if not mode in self.mode: raise Exception('Invalid set membership mode "'+mode+'"! Use "add" or "replace"!') - + # =============== # - Rebuild Set - # =============== - + # Start timer timer = mc.timerX() - + # Create Set setName = self._data['name'] - + # Delete Set (REPLACE only) if mc.objExists(setName) and mode == 'replace': mc.delete(setName) - + # Create Set if not mc.objExists(setName): setName = mc.sets(n=setName) - + # Add Members if memberList: if forceMembership: @@ -137,20 +137,20 @@ def rebuild(self,mode='add',forceMembership=True): except Exception, e: print('Error adding item "'+obj+'" to set "'+setName+'"! Skipping') print(str(e)) - + # Print Timer Result buildTime = mc.timerX(st=timer) print('SetData: Rebuild time for set "'+setName+'": '+str(buildTime)) - + # ================= # - Return Result - # ================= - + self.setName = setName - + result = {} result['set'] = setName result['membership'] = memberList return result - + diff --git a/data/skinClusterData.py b/data/skinClusterData.py index f477393..bdb15bb 100644 --- a/data/skinClusterData.py +++ b/data/skinClusterData.py @@ -21,23 +21,23 @@ def __init__(self,skinCluster=''): ''' # Execute Super Class Initilizer super(SkinClusterData, self).__init__() - + # SkinCluster Custom Attributes self._data['attrValueList'].append('skinningMethod') self._data['attrValueList'].append('useComponents') self._data['attrValueList'].append('normalizeWeights') self._data['attrValueList'].append('deformUserNormals') - + # Build SkinCluster Data if skinCluster: self.buildData(skinCluster) - + def verifySkinCluster(self,skinCluster): ''' ''' # Check skinCluster if not glTools.utils.skinCluster.isSkinCluster(skinCluster): raise Exception('Object "'+skinCluster+'" is not a valid skinCluster!') - + def buildData(self,skinCluster): ''' Build skinCluster data and store as class object dictionary entries @@ -47,23 +47,23 @@ def buildData(self,skinCluster): # ========== # - Checks - # ========== - + # Check skinCluster self.verifySkinCluster(skinCluster) - + # Clear Data self.reset() - + # ======================= # - Build Deformer Data - # ======================= - + # Start Timer timer = mc.timerX() - + self._data['name'] = skinCluster self._data['type'] = 'skinCluster' - + # Get affected geometry skinGeoShape = mc.skinCluster(skinCluster,q=True,g=True) if len(skinGeoShape) > 1: raise Exception('SkinCluster "'+skinCluster+'" output is connected to multiple shapes!') @@ -72,44 +72,44 @@ def buildData(self,skinCluster): if not skinGeo: raise Exception('Unable to determine geometry transform for object "'+skinGeoShape+'"!') self._data['affectedGeometry'] = skinGeo skinGeo = skinGeo[0] - + skinClusterSet = glTools.utils.deformer.getDeformerSet(skinCluster) - + self._data[skinGeo] = {} self._data[skinGeo]['index'] = 0 self._data[skinGeo]['geometryType'] = str(mc.objectType(skinGeoShape)) self._data[skinGeo]['membership'] = glTools.utils.deformer.getDeformerSetMemberIndices(skinCluster,skinGeo) self._data[skinGeo]['weights'] = [] - + if self._data[skinGeo]['geometryType'] == 'mesh': self._data[skinGeo]['mesh'] = meshData.MeshData(skinGeo) - + # ======================== # - Build Influence Data - # ======================== - + # Get skinCluster influence list influenceList = mc.skinCluster(skinCluster,q=True,inf=True) if not influenceList: raise Exception('Unable to determine influence list for skinCluster "'+skinCluster+'"!') - + # Get Influence Wieghts weights = glTools.utils.skinCluster.getInfluenceWeightsAll(skinCluster) - + # For each influence for influence in influenceList: - + # Initialize influence data self._influenceData[influence] = {} - + # Get influence index infIndex = glTools.utils.skinCluster.getInfluenceIndex(skinCluster,influence) self._influenceData[influence]['index'] = infIndex - + # Get Influence BindPreMatrix bindPreMatrix = mc.listConnections(skinCluster+'.bindPreMatrix['+str(infIndex)+']',s=True,d=False,p=True) if bindPreMatrix: self._influenceData[influence]['bindPreMatrix'] = bindPreMatrix[0] else: self._influenceData[influence]['bindPreMatrix'] = '' - + # Get Influence Type (Transform/Geometry) infGeomConn = mc.listConnections(skinCluster+'.driverPoints['+str(infIndex)+']') if infGeomConn: @@ -118,23 +118,23 @@ def buildData(self,skinCluster): self._influenceData[influence]['nurbsSamples'] = mc.skinCluster(skinCluster,inf=influence,q=True,ns=True) else: self._influenceData[influence]['type'] = 0 - + # Get Influence Weights pInd = glTools.utils.skinCluster.getInfluencePhysicalIndex(skinCluster,influence) self._influenceData[influence]['wt'] = weights[pInd] - + # ========================= # - Custom Attribute Data - # ========================= - + # Add Pre-Defined Custom Attributes self.getDeformerAttrValues() self.getDeformerAttrConnections() - + # ================= # - Return Result - # ================= - + skinTime = mc.timerX(st=timer) print('SkinClusterData: Data build time for "'+skinCluster+'": '+str(skinTime)) @@ -145,22 +145,22 @@ def rebuild(self): # ========== # - Checks - # ========== - + # Check geometry skinGeo = self._data['affectedGeometry'][0] if not mc.objExists(skinGeo): raise Exception('SkinCluster geometry "'+skinGeo+'" does not exist! Use remapGeometry() to load skinCluster data for a different geometry!') - + # ======================= # - Rebuild SkinCluster - # ======================= - + # Start timer timer = mc.timerX() - + # Initialize Temp Joint tempJnt = '' - + # Unlock Influences influenceList = self._influenceData.keys() for influence in influenceList: @@ -171,87 +171,87 @@ def rebuild(self): if mc.getAttr(influence+'.liw'): try: mc.setAttr(influence+'.liw',False) except: print('Error setting attribute "'+influence+'.liw" to False! This could problems when rebuilding the skinCluster...') - + # Check SkinCluster skinCluster = self._data['name'] if not mc.objExists(skinCluster): - + # Get Transform Influences jointList = [inf for inf in influenceList if not self._influenceData[inf]['type']] - + # Check Transform Influences if not jointList: - + # Create Temporary Bind Joint mc.select(cl=1) tempJnt = mc.joint(n=skinCluster+'_tempJoint') print('No transform influences specified for skinCluster "'+skinCluster+'"! Creating temporary bind joint "'+tempJnt+'"!') jointList = [tempJnt] - + else: - + # Get Surface Influences influenceList = [inf for inf in influenceList if self._influenceData[inf]['type']] - + # Create skinCluster skinCluster = mc.skinCluster(jointList,skinGeo,tsb=True,n=skinCluster)[0] - + else: - + # Check Existing SkinCluster affectedGeo = glTools.utils.deformer.getAffectedGeometry(skinCluster) if affectedGeo.keys()[0] != skinGeo: raise Exception('SkinCluster "'+skinCluster+'" already exists, but is not connected to the expeced geometry "'+skinGeo+'"!') - + # Add skinCluster influences for influence in influenceList: - + # Check influence if not mc.objExists(influence): raise Exception('Influence "'+influence+'" does not exist! Use remapInfluence() to apply data to a different influence!') - + # Check existing influence connection if not mc.skinCluster(skinCluster,q=True,inf=True).count(influence): - + # Add influence if self._influenceData[influence]['type']: # Geometry polySmooth = self._influenceData[influence]['polySmooth'] nurbsSamples = self._influenceData[influence]['nurbsSamples'] mc.skinCluster(skinCluster,e=True,ai=influence,ug=True,ps=polySmooth,ns=nurbsSamples,wt=0.0,lockWeights=True) - + else: # Transform mc.skinCluster(skinCluster,e=True,ai=influence,wt=0.0,lockWeights=True) - + # Bind Pre Matrix if self._influenceData[influence]['bindPreMatrix']: infIndex = glTools.utils.skinCluster.getInfluenceIndex(skinCluster,influence) mc.connectAttr(self._influenceData[influence]['bindPreMatrix'],skinCluster+'.bindPreMatrix['+str(infIndex)+']',f=True) - + # Load skinCluster weights mc.setAttr(skinCluster+'.normalizeWeights',0) glTools.utils.skinCluster.clearWeights(skinGeo) self.loadWeights() mc.setAttr(skinCluster+'.normalizeWeights',1) - + # Restore Custom Attribute Values and Connections self.setDeformerAttrValues() self.setDeformerAttrConnections() - + # Clear Selection mc.select(cl=True) - + # ================= # - Return Result - # ================= - + # Print Timed Result totalTime = mc.timerX(st=timer) print('SkinClusterData: Rebuild time for skinCluster "'+skinCluster+'": '+str(totalTime)) - + return skinCluster - + def setWeights(self,componentList=[]): ''' Apply the stored skinCluster weights to the specified skinCluster. @@ -259,39 +259,39 @@ def setWeights(self,componentList=[]): @type componentList: str ''' print('!!! - DEPRICATED: skinClusterData.setWeights()! Use loadWeights() method instead - !!!') - + # ========== # - Checks - # ========== - + # Check SkinCluster skinCluster = self._data['name'] self.verifySkinCluster(skinCluster) - + # Check Geometry skinGeo = self._data['affectedGeometry'][0] if not mc.objExists(skinGeo): raise Exception('SkinCluster geometry "'+skinGeo+'" does not exist! Use remapGeometry() to load skinCluster data to a different geometry!') - + # Check Component List if not componentList: componentList = glTools.utils.component.getComponentStrList(skinGeo) componentSel = glTools.utils.selection.getSelectionElement(componentList,0) - + # Get Component Index List indexList = OpenMaya.MIntArray() componentFn = OpenMaya.MFnSingleIndexedComponent(componentSel[1]) componentFn.getElements(indexList) componentIndexList = list(indexList) - + # =========================== # - Set SkinCluster Weights - # =========================== - + # Build influence index array infIndexArray = OpenMaya.MIntArray() influenceList = mc.skinCluster(skinCluster,q=True,inf=True) [infIndexArray.append(i) for i in range(len(influenceList))] - + # Build master weight array wtArray = OpenMaya.MDoubleArray() oldWtArray = OpenMaya.MDoubleArray() @@ -301,19 +301,19 @@ def setWeights(self,componentList=[]): wtArray.append(self._influenceData[influenceList[i]]['wt'][c]) else: wtArray.append(0.0) - + # Get skinCluster function set skinFn = glTools.utils.skinCluster.getSkinClusterFn(skinCluster) - + # Set skinCluster weights skinFn.setWeights(componentSel[0],componentSel[1],infIndexArray,wtArray,False,oldWtArray) - + # ================= # - Return Result - # ================= - + return influenceList - + def loadWeights( self, skinCluster = None, influenceList = None, @@ -333,16 +333,16 @@ def loadWeights( self, # ========== # - Checks - # ========== - + # Check SkinCluster if not skinCluster: skinCluster = self._data['name'] self.verifySkinCluster(skinCluster) - + # Check Geometry skinGeo = self._data['affectedGeometry'][0] if not mc.objExists(skinGeo): raise Exception('SkinCluster geometry "'+skinGeo+'" does not exist! Use remapGeometry() to load skinCluster data to a different geometry!') - + # Check Influence List if not influenceList: influenceList = self._influenceData.keys() or [] for influence in influenceList: @@ -350,12 +350,12 @@ def loadWeights( self, raise Exception('Object "'+influence+'" is not a valid influence of skinCluster "'+skinCluster+'"! Unable to load influence weights...') if not self._influenceData.has_key(influence): raise Exception('No influence data stored for "'+influence+'"! Unable to load influence weights...') - + # Check Component List if not componentList: componentList = glTools.utils.component.getComponentStrList(skinGeo) componentSel = glTools.utils.selection.getSelectionElement(componentList,0) - + # Get Component Index List #indexList = OpenMaya.MIntArray() #componentFn = OpenMaya.MFnSingleIndexedComponent(componentSel[1]) @@ -363,17 +363,17 @@ def loadWeights( self, #componentIndexList = list(indexList) componentIndexList = glTools.utils.component.getSingleIndexComponentList(componentList) componentIndexList = componentIndexList[componentIndexList.keys()[0]] - + # ===================================== # - Set SkinCluster Influence Weights - # ===================================== - + # Get Influence Index infIndexArray = OpenMaya.MIntArray() for influence in influenceList: infIndex = glTools.utils.skinCluster.getInfluencePhysicalIndex(skinCluster,influence) infIndexArray.append(infIndex) - + # Build Weight Array wtArray = OpenMaya.MDoubleArray() oldWtArray = OpenMaya.MDoubleArray() @@ -383,19 +383,19 @@ def loadWeights( self, wtArray.append(self._influenceData[influenceList[i]]['wt'][c]) else: wtArray.append(0.0) - + # Get skinCluster function set skinFn = glTools.utils.skinCluster.getSkinClusterFn(skinCluster) - + # Set skinCluster weights skinFn.setWeights(componentSel[0],componentSel[1],infIndexArray,wtArray,normalize,oldWtArray) - + # ================= # - Return Result - # ================= - + return list(wtArray) - + def swapWeights(self,inf1,inf2): ''' Swap influence weight values between 2 skinCluster influeneces. @@ -409,13 +409,13 @@ def swapWeights(self,inf1,inf2): raise Exception('No influence data for "'+inf1+'"! Unable to swap weights...') if not self._influenceData.has_key(inf2): raise Exception('No influence data for "'+inf2+'"! Unable to swap weights...') - + # Swap Weights self._influenceData[inf1]['wt'][:], self._influenceData[inf2]['wt'][:] = self._influenceData[inf2]['wt'][:], self._influenceData[inf1]['wt'][:] - + # Return Result print('SkinClusterData: Swap Weights Complete - "'+inf1+'" <> "'+inf2+'"') - + def moveWeights(self,sourceInf,targetInf,mode='add'): ''' Move influence weight values from one skinCluster influenece to another. @@ -431,11 +431,11 @@ def moveWeights(self,sourceInf,targetInf,mode='add'): raise Exception('No influence data for source influence "'+sourceInf+'"! Unable to move weights...') if not self._influenceData.has_key(targetInf): raise Exception('No influence data for target influence "'+targetInf+'"! Unable to move weights...') - + # Check Mode if not ['add','replace'].count(mode): raise Exception('Invalid mode value ("'+mode+'")!') - + # Move Weights sourceWt = self._influenceData[sourceInf]['wt'] targetWt = self._influenceData[targetInf]['wt'] @@ -444,10 +444,10 @@ def moveWeights(self,sourceInf,targetInf,mode='add'): elif mode == 'replace': self._influenceData[targetInf]['wt'] = [i for i in sourceWt] self._influenceData[sourceInf]['wt'] = [0.0 for i in sourceWt] - + # Return Result print('SkinClusterData: Move Weights Complete - "'+sourceInf+'" >> "'+targetInf+'"') - + def remapInfluence(self,oldInfluence,newInfluence): ''' Remap stored skinCluster influence data from one influence to another @@ -459,16 +459,16 @@ def remapInfluence(self,oldInfluence,newInfluence): # Check influence if not self._influenceData.has_key(oldInfluence): print ('No data stored for influence "'+oldInfluence+'" in skinCluster "'+self._data['name']+'"! Skipping...') - return + return #raise Exception('No data stored for influence "'+oldInfluence+'" in skinCluster "'+self._data['name']+'"!') - + # Update influence data self._influenceData[newInfluence] = self._influenceData[oldInfluence] self._influenceData.pop(oldInfluence) - + # Print message print('Remapped influence "'+oldInfluence+'" to "'+newInfluence+'" for skinCluster "'+self._data['name']+'"!') - + def combineInfluence(self,sourceInfluenceList,targetInfluence,removeSource=False): ''' Combine stored skinCluster influence data from a list of source influences to a single target influence. @@ -481,99 +481,99 @@ def combineInfluence(self,sourceInfluenceList,targetInfluence,removeSource=False # =========================== # - Check Source Influences - # =========================== - + skipSource = [] for i in range(len(sourceInfluenceList)): - + # Check influence if not self._influenceData.has_key(sourceInfluenceList[i]): print('No data stored for influence "'+sourceInfluenceList[i]+'" in skinCluster "'+self._data['name']+'"! Skipping...') skipSource.append(sourceInfluenceList[i]) - + # ============================= # - Initialize Influence Data - # ============================= - + if list(set(sourceInfluenceList)-set(skipSource)): if not self._influenceData.has_key(targetInfluence): self._influenceData[targetInfluence] = {'index':0,'type':0,'bindPreMatrix':''} else: return - + # ========================== # - Combine Influence Data - # ========================== - + wtList = [] for i in range(len(sourceInfluenceList)): - + # Get Source Influence sourceInfluence = sourceInfluenceList[i] - + # Check Skip Source if skipSource.count(sourceInfluence): continue - + # Get Basic Influence Data from first source influence if not i: - + # Index self._influenceData[targetInfluence]['index'] = self._influenceData[sourceInfluence]['index'] - + # Type self._influenceData[targetInfluence]['type'] = self._influenceData[sourceInfluence]['type'] - + # Poly Smooth if self._influenceData[sourceInfluence].has_key('polySmooth'): self._influenceData[targetInfluence]['polySmooth'] = self._influenceData[sourceInfluence]['polySmooth'] else: if self._influenceData[targetInfluence].has_key('polySmooth'): self._influenceData[targetInfluence].pop('polySmooth') - + # Nurbs Samples if self._influenceData[sourceInfluence].has_key('nurbsSamples'): self._influenceData[targetInfluence]['nurbsSamples'] = self._influenceData[sourceInfluence]['nurbsSamples'] else: if self._influenceData[targetInfluence].has_key('nurbsSamples'): self._influenceData[targetInfluence].pop('nurbsSamples') - - # Get Source Influence Weights + + # Get Source Influence Weights wtList = self._influenceData[sourceInfluence]['wt'] - + else: - + if wtList: - + # Combine Source Influence Weights wtList = [(x+y) for x,y in zip(wtList,self._influenceData[sourceInfluence]['wt'])] - + else: - + wtList = self._influenceData[sourceInfluence]['wt'] - + # ================================== # - Assign Combined Source Weights - # ================================== - + self._influenceData[targetInfluence]['wt'] = wtList - + # ======================================= # - Remove Unused Source Influence Data - # ======================================= - + if removeSource: - + # For Each Source Influence for sourceInfluence in sourceInfluenceList: - + # Check Skip Source if skipSource.count(sourceInfluence): continue - + # Check Source/Target if sourceInfluence != targetInfluence: - + # Remove Unused Source Influence self._influenceData.pop(sourceInfluence) - + def remapGeometry(self,geometry): ''' Remap the skinCluster data for one geometry to another @@ -583,24 +583,24 @@ def remapGeometry(self,geometry): # Checks oldGeometry = self._data['affectedGeometry'][0] if geometry == oldGeometry: return geometry - + # Check Skin Geo Data if not self._data.has_key(oldGeometry): raise Exception('SkinClusterData: No skin geometry data for affected geometry "'+oldGeometry+'"!') - + # Remap Geometry self._data['affectedGeometry'] = [geometry] - + # Update Skin Geo Data self._data[geometry] = self._data[oldGeometry] self._data.pop(oldGeometry) - + # Print Message print('Geometry for skinCluster "'+self._data['name']+'" remaped from "'+oldGeometry+'" to "'+geometry+'"') - + # Return result return self._data['affectedGeometry'] - + def rebuildWorldSpaceData(self,targetGeo='',method='closestPoint'): ''' Rebuild the skinCluster deformer membership and weight arrays for the specified geometry using the stored world space geometry data. @@ -611,25 +611,25 @@ def rebuildWorldSpaceData(self,targetGeo='',method='closestPoint'): ''' # Start timer timer = mc.timerX() - + # Display Progress glTools.utils.progressBar.init(status=('Rebuilding world space skinCluster data...'),maxValue=100) - + # ========== # - Checks - # ========== - + # Get Source Geometry sourceGeo = self._data['affectedGeometry'][0] - + # Target Geometry if not targetGeo: targetGeo = sourceGeo - + # Check Deformer Data if not self._data.has_key(sourceGeo): glTools.utils.progressBar.end() raise Exception('No deformer data stored for geometry "'+sourceGeo+'"!') - + # Check Geometry if not mc.objExists(targetGeo): glTools.utils.progressBar.end() @@ -637,18 +637,18 @@ def rebuildWorldSpaceData(self,targetGeo='',method='closestPoint'): if not glTools.utils.mesh.isMesh(targetGeo): glTools.utils.progressBar.end() raise Exception('Geometry "'+targetGeo+'" is not a valid mesh!') - + # Check Mesh Data if not self._data[sourceGeo].has_key('mesh'): glTools.utils.progressBar.end() raise Exception('No world space mesh data stored for mesh geometry "'+sourceGeo+'"!') - + # ===================== # - Rebuild Mesh Data - # ===================== - + meshData = self._data[sourceGeo]['mesh']._data - + meshUtil = OpenMaya.MScriptUtil() numVertices = len(meshData['vertexList'])/3 numPolygons = len(meshData['polyCounts']) @@ -656,62 +656,62 @@ def rebuildWorldSpaceData(self,targetGeo='',method='closestPoint'): polygonConnects = OpenMaya.MIntArray() meshUtil.createIntArrayFromList(meshData['polyCounts'],polygonCounts) meshUtil.createIntArrayFromList(meshData['polyConnects'],polygonConnects) - + # Rebuild Vertex Array vertexArray = OpenMaya.MFloatPointArray(numVertices,OpenMaya.MFloatPoint.origin) vertexList = [vertexArray.set(i,meshData['vertexList'][i*3],meshData['vertexList'][i*3+1],meshData['vertexList'][i*3+2],1.0) for i in xrange(numVertices)] - + # Rebuild Mesh meshFn = OpenMaya.MFnMesh() meshDataFn = OpenMaya.MFnMeshData().create() meshObj = meshFn.create(numVertices,numPolygons,vertexArray,polygonCounts,polygonConnects,meshDataFn) - + # Create Mesh Intersector meshPt = OpenMaya.MPointOnMesh() meshIntersector = OpenMaya.MMeshIntersector() if method == 'closestPoint': meshIntersector.create(meshObj) - + # ======================================== # - Rebuild Weights and Membership List - # ======================================== - + # Initialize Influence Weights and Membership influenceList = self._influenceData.keys() influenceWt = [[] for inf in influenceList] membership = set([]) - + # Get Target Mesh Data targetMeshFn = glTools.utils.mesh.getMeshFn(targetGeo) targetMeshPts = targetMeshFn.getRawPoints() numTargetVerts = targetMeshFn.numVertices() targetPtUtil = OpenMaya.MScriptUtil() - + # Initialize Float Pointers for Barycentric Coords uUtil = OpenMaya.MScriptUtil(0.0) vUtil = OpenMaya.MScriptUtil(0.0) uPtr = uUtil.asFloatPtr() vPtr = vUtil.asFloatPtr() - + # Get Progress Step progressInd = int(numTargetVerts*0.01) - if progressInd < 1: progressInd = 1 - + if progressInd < 1: progressInd = 1 + for i in range(numTargetVerts): - + # Get Target Point targetPt = OpenMaya.MPoint( targetPtUtil.getFloatArrayItem(targetMeshPts,(i*3)+0), targetPtUtil.getFloatArrayItem(targetMeshPts,(i*3)+1), targetPtUtil.getFloatArrayItem(targetMeshPts,(i*3)+2) ) - + # Get Closest Point Data meshIntersector.getClosestPoint(targetPt,meshPt) - + # Get Barycentric Coords meshPt.getBarycentricCoords(uPtr,vPtr) u = OpenMaya.MScriptUtil(uPtr).asFloat() v = OpenMaya.MScriptUtil(vPtr).asFloat() baryWt = [u,v,1.0-(u+v)] - + # Get Triangle Vertex IDs idUtil = OpenMaya.MScriptUtil([0,1,2]) idPtr = idUtil.asIntPtr() @@ -719,37 +719,37 @@ def rebuildWorldSpaceData(self,targetGeo='',method='closestPoint'): triId = [OpenMaya.MScriptUtil().getIntArrayItem(idPtr,n) for n in range(3)] memId = [self._data[sourceGeo]['membership'].count(t) for t in triId] wtId = [self._data[sourceGeo]['membership'].index(t) for t in triId] - + # For Each Influence for inf in range(len(influenceList)): - + # Calculate Weight and Membership wt = 0.0 isMember = False for n in range(3): - + # Check Against Source Membership if memId[n]: wt += self._influenceData[influenceList[inf]]['wt'][wtId[n]] * baryWt[n] isMember = True - + # Check Member if isMember: # Append Weight Value influenceWt[inf].append(wt) # Append Membership membership.add(i) - + # Update Progress Bar if not i % progressInd: glTools.utils.progressBar.update(step=1) - + # ======================== # - Update Deformer Data - # ======================== - + # Remap Geometry self.remapGeometry(targetGeo) - + # Rename SkinCluster targetSkinCluster = glTools.utils.skinCluster.findRelatedSkinCluster(targetGeo) if targetSkinCluster: @@ -757,26 +757,26 @@ def rebuildWorldSpaceData(self,targetGeo='',method='closestPoint'): else: prefix = targetGeo.split(':')[-1] self._data['name'] = prefix+'_skinCluster' - + # Update Membership and Weights self._data[sourceGeo]['membership'] = list(membership) for inf in range(len(influenceList)): self._influenceData[influenceList[inf]]['wt'] = influenceWt[inf] - + # ================= # - Return Result - # ================= - + # End Progress - glTools.utils.progressBar.end() - + glTools.utils.progressBar.end() + # Print Timed Result buildTime = mc.timerX(st=timer) print('SkinClusterData: Rebuild world space data for skinCluster "'+self._data['name']+'": '+str(buildTime)) - + # Return Weights return - + def mirror(self,search='lf',replace='rt'): ''' Mirror SkinCluster Data using search and replace for naming. @@ -789,20 +789,20 @@ def mirror(self,search='lf',replace='rt'): # ========== # - Checks - # ========== - + # =========================== # - Search and Replace Name - # =========================== - + if self._data['name'].count(search): self._data['name'] = self._data['name'].replace(search,replace) - + # =============================== # - Search and Replace Geometry - # =============================== - + for i in range(len(self._data['affectedGeometry'])): - + if self._data['affectedGeometry'][i].count(search): # Get 'mirror' geometry mirrorGeo = self._data['affectedGeometry'][i].replace(search,replace) @@ -812,11 +812,11 @@ def mirror(self,search='lf',replace='rt'): # Assign 'mirror' geometry self.remapGeometry(mirrorGeo) #self._data['affectedGeometry'][i] = mirrorGeo - + # Search and Replace Inlfuences influenceList = self._influenceData.keys() for i in range(len(influenceList)): - + if influenceList[i].count(search): # Get 'mirror' influence mirrorInfluence = influenceList[i].replace(search,replace) @@ -837,7 +837,7 @@ def __init__(self): ''' # Execute Super Class Initilizer super(SkinClusterListData, self).__init__() - + def buildData(self,skinClusterList): ''' Build SkinClusterList data. @@ -846,17 +846,17 @@ def buildData(self,skinClusterList): ''' # For Each SkinCluster for skinCluster in skinClusterList: - + # Check skinCluster if not mc.objExists(skinCluster): raise Exception('SkinCluster "'+skinCluster+'" does not exist!') if not glTools.utils.skinCluster.isSkinCluster(skinCluster): raise Exception('"'+skinCluster+'" is not a valid skinCluster!') - + # Build SkinCLuster Data self._data[skinCluster] = SkinClusterData() self._data[skinCluster].buildData(skinCluster) - + def rebuild(self,skinClusterList): ''' Rebuild a list of skinClusters from the stored SkinClusterListData @@ -865,17 +865,17 @@ def rebuild(self,skinClusterList): ''' # Start timer timer = mc.timerX() - + # For Each SkinCluster for skinCluster in skinClusterList: - + # Check skinClusterData if not self._data.has_key(skinCluster): print('No data stored for skinCluster "'+skinCluster+'"! Skipping...') - + # Rebuild SkinCluster self._data[skinCluster].rebuild() - + # Print timed result totalTime = mc.timerX(st=timer) print('SkinClusterListData: Total build time for skinCluster list: '+str(skinTime)) diff --git a/data/utils.py b/data/utils.py index acb0fcc..5beff57 100644 --- a/data/utils.py +++ b/data/utils.py @@ -38,35 +38,35 @@ def buildData(node): # ========== # - Checks - # ========== - + # Check Node if not mc.objExists(node): raise Exception('Node "'+node+'" does not exist! Unable to determine data type.') - + # ======================= # - Determine Data Type - # ======================= - + # Check Deformer if glTools.utils.deformer.isDeformer(node): return buildDeformerData(node) - + # Check Constraint if glTools.utils.constraint.isConstraint(node): return buildConstraintData(node) - + # Check Geometry if glTools.utils.geometry.isGeometry(node): return buildGeometryData(node) - + # Check Set if 'objectSet' in mc.nodeType(node,i=True): return setData.SetData(node) - + # ========================= # - Unsupported Node Type - # ========================= - + raise Exception('Unsupported node type! Unable to build data for "'+node+'" ('+mc.nodeType(node)+')') def buildDeformerData(deformer): @@ -78,82 +78,82 @@ def buildDeformerData(deformer): # ========== # - Checks - # ========== - + # Check Deformer if not glTools.utils.deformer.isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # Get Deformer Type deformerType = mc.objectType(deformer) - + # ============================ # - Initialize Deformer Data - # ============================ - + dDataObj = deformerData.DeformerData - + # BulgeSkinBasic if deformerType == 'bulgeSkinBasic': dDataObj = deformerData.BulgeSkinBasicData - + # BulgeSkinPrim elif deformerType == 'bulgeSkinPrim': dDataObj = deformerData.BulgeSkinPrimData - + # Cluster elif deformerType == 'cluster': dDataObj = clusterData.ClusterData - + # CurveTwist elif deformerType == 'curveTwist': dDataObj = clusterData.ClusterData - + # DirectionalSmooth elif deformerType == 'directionalSmooth': dDataObj = deformerData.DirectionalSmoothData - + # Lattice elif deformerType == 'ffd': dDataObj = latticeData.LatticeData - + # Peak elif deformerType == 'peakDeformer': dDataObj = deformerData.PeakDeformerData - + # SkinCluster elif deformerType == 'skinCluster': dDataObj = skinClusterData.SkinClusterData - + # StrainRelaxer elif deformerType == 'strainRelaxer': dDataObj = deformerData.StrainRelaxerData - + # SurfaceSkin elif deformerType == 'surfaceSkin': dDataObj = surfaceSkinData.SurfaceSkinData - + # Wire elif deformerType == 'wire': dDataObj = wireData.WireData - + # Unsupported Type !! else: print('Unsupported Deformer! Using base DeformerData class for '+deformerType+' "'+deformer+'"!') - + # ======================= # - Build Deformer Data - # ======================= - + dData = dDataObj() try: dData.buildData(deformer) except Exception, e: print(str(e)) raise Exception('DeformerData: Error building data object for "'+deformer+'"!') - + # ================= # - Return Result - # ================= - + return dData def buildConstraintData(constraint): @@ -165,46 +165,46 @@ def buildConstraintData(constraint): # ========== # - Checks - # ========== - + if not glTools.utils.constraint.isConstraint(constraint): raise Exception('Object "'+constraint+'" is not a valid constraint! Unable to build constraint data...') - + # Get Constraint Type constraintType = mc.objectType(constraint) - + # ============================== # - Initialize Constraint Data - # ============================== - + cDataObj = constraintData.ConstraintData - + if constraintType == 'aimConstraint': cDataObj = constraintData.AimConstraintData - + elif constraintType == 'pointConstraint': cDataObj = constraintData.PointConstraintData - + elif constraintType == 'orientConstraint': cDataObj = constraintData.OrientConstraintData - + elif constraintType == 'parentConstraint': cDataObj = constraintData.ParentConstraintData - + else: print('Unsupported Constraint! Using base ConstraintData class for '+constraintType+' "'+constraint+'"!') - + # ======================= # - Build Deformer Data - # ======================= - + cData = cDataObj() try: cData.buildData(constraint) except: raise Exception('ConstraintData: Error building data object for "'+constraint+'"!') - + # ================= # - Return Result - # ================= - + return cData def buildGeometryData(geometry): diff --git a/data/wireData.py b/data/wireData.py index 7513ac0..c0f19d0 100644 --- a/data/wireData.py +++ b/data/wireData.py @@ -17,24 +17,24 @@ def __init__(self): # ================================== # - Execute Super Class Initilizer - # ================================== - + super(WireData, self).__init__() - + # ======================== # - Initialize Wire Data - # ======================== - + self._data['attrValueList'].append('crossingEffect') self._data['attrValueList'].append('tension') self._data['attrValueList'].append('localInfluence') self._data['attrValueList'].append('rotation') - + # =============================== # - Initialize Custom Wire Data - # =============================== - + self._locatorData = {} - + def buildData(self,wire): ''' Build wire data and store as class object dictionary entries @@ -44,32 +44,32 @@ def buildData(self,wire): # ========== # - Checks - # ========== - + # Verify node glTools.utils.base.verifyNode(wire,'wire') - + # ===================== # - Get Deformer Data - # ===================== - + # Clear Data self.reset() - + # Get influence curves influenceList = glTools.utils.connection.connectionListToAttr(wire,'deformedWire') - + # Custom Attribute Data for inf in influenceList.keys(): ind = influenceList[inf][1] self._data['attrConnectionList'].append('dropoffDistance['+str(ind)+']') self._data['attrConnectionList'].append('scale['+str(ind)+']') - + super(WireData, self).buildData(wire) - + # ====================== # - Get Influence Data - # ====================== - + for influence in influenceList.keys(): infIndex = influenceList[influence][1] self._influenceData[influence] = {} @@ -77,18 +77,18 @@ def buildData(self,wire): self._influenceData[influence]['influenceBase'] = mc.listConnections(wire+'.baseWire['+str(infIndex)+']',s=True,d=False)[0] self._influenceData[influence]['dropoffDist'] = mc.getAttr(wire+'.dropoffDistance['+str(infIndex)+']') self._influenceData[influence]['scale'] = mc.getAttr(wire+'.scale['+str(infIndex)+']') - + # ============================ # - Get Dropoff Locator Data - # ============================ - + dropoffLocatorList = glTools.utils.connection.connectionListToAttr(wire,'wireLocatorParameter') - + for locator in dropoffLocatorList.keys(): - + # Initialize dropoff locator data dictionary self._locatorData[locator] = {} - + # Build dropoff locator data locIndex = dropoffLocatorList[locator][1] self._locatorData[locator]['index'] = locIndex @@ -96,12 +96,12 @@ def buildData(self,wire): self._locatorData[locator]['twist'] = mc.getAttr(wire+'.wireLocatorTwist['+str(locIndex)+']') self._locatorData[locator]['percent'] = mc.getAttr(locator+'.percent') self._locatorData[locator]['parameter'] = mc.getAttr(locator+'.param') - + # Get wire curve parent locParent = mc.listRelatives(locator,p=True)[0] crvParent = mc.listRelatives(locParent,p=True)[0] self._locatorData[locator]['parent'] = crvParent - + def rebuild(self): ''' Rebuild the wire deformer from the recorded deformerData @@ -109,83 +109,83 @@ def rebuild(self): # ========== # - Checks - # ========== - + # Check Data for influence in self._influenceData.iterkeys(): - + # Check Wire Curve if not mc.objExists(influence): print('Wire curve "'+influence+'" does not exist! Curve will not be added to deformer!') - + # Check Base Curves baseCurve = self._influenceData[influence]['influenceBase'] if not mc.objExists(baseCurve): print('Wire curve base "'+baseCurve+'" does not exist! A static base curve will be generated from the deforming wire curve!') - + # Check Dropoff Locators for locator in self._locatorData.iterkeys(): if mc.objExists(locator): mc.delete(mc.listRelatives(locator,p=True)[0]) - + # ==================== # - Rebuild Deformer - # ==================== - + result = super(WireData, self).rebuild() wireDeformer = result['deformer'] - + # ======================= # - Connect Wire Curves - # ======================= - + for influence in self._influenceData.iterkeys(): - + # Get current wire curve pair wireCurve = influence infIndex = self._influenceData[influence]['index'] baseCurve = self._influenceData[influence]['influenceBase'] - + # Connect deformed wire if not mc.objExists(influence): continue mc.connectAttr(wireCurve+'.worldSpace[0]',wireDeformer+'.deformedWire['+str(infIndex)+']',f=True) - + # Connect base wire if not mc.objExists(baseCurve): baseCurve = mc.duplicate(influence,n=baseCurve)[0] mc.connectAttr(baseCurve+'.worldSpace[0]',wireDeformer+'.baseWire['+str(infIndex)+']',f=True) mc.setAttr(baseCurve+'.v',0) - + # Set Influence Attributes if mc.getAttr(wireDeformer+'.dropoffDistance['+str(infIndex)+']',se=True): mc.setAttr(wireDeformer+'.dropoffDistance['+str(infIndex)+']',self._influenceData[influence]['dropoffDist']) if mc.getAttr(wireDeformer+'.scale['+str(infIndex)+']',se=True): mc.setAttr(wireDeformer+'.scale['+str(infIndex)+']',self._influenceData[influence]['scale']) - + # ============================ # - Rebuild Dropoff Locators - # ============================ - + for locator in self._locatorData.iterkeys(): - + # Get data parent = self._locatorData[locator]['parent'] param = self._locatorData[locator]['parameter'] env = self._locatorData[locator]['envelope'] percent = self._locatorData[locator]['percent'] twist = self._locatorData[locator]['twist'] - + # Create Locator loc = mc.dropoffLocator(env,percent,wire,parent+'.u['+str(param)+']')[0] - + # Apply Twist locConn = mc.listConnections(loc+'.param',s=False,d=True,p=True)[0] locConnIndex = locConn.split('[')[-1].split(']')[0] mc.setAttr(wireDeformer+'.wireLocatorTwist['+str(locConnIndex)+']',twist) - + # ================= # - Return Result - # ================= - + self.result['influence'] = self._influenceData.keys() self.result['dropoffLocator'] = self._locatorData.keys() - + return self.result diff --git a/data/wrapData.py b/data/wrapData.py index eab3e11..5c70b45 100644 --- a/data/wrapData.py +++ b/data/wrapData.py @@ -17,21 +17,21 @@ def __init__(self): # ================================== # - Execute Super Class Initilizer - # ================================== - + super(WrapData, self).__init__() - + # ======================== # - Initialize Wrap Data - # ======================== - + self._data['attrValueList'].append('weightThreshold') self._data['attrValueList'].append('maxDistance') self._data['attrValueList'].append('autoWeightThreshold') self._data['attrValueList'].append('exclusiveBind') self._data['attrValueList'].append('falloffMode') - + self._data['attrConnectionList'].append('geomMatrix') - + def buildData(self,wrap): ''' Build wrap data and store as class object dictionary entries @@ -41,32 +41,32 @@ def buildData(self,wrap): # ========== # - Checks - # ========== - + # Verify node glTools.utils.base.verifyNode(wrap,'wrap') - + # ===================== # - Get Deformer Data - # ===================== - + # Clear Data self.reset() - + # Get influence curves influenceList = glTools.utils.connection.connectionListToAttr(wire,'deformedWire') - + # Custom Attribute Data for inf in influenceList.keys(): ind = influenceList[inf][1] self._data['attrConnectionList'].append('dropoffDistance['+str(ind)+']') self._data['attrConnectionList'].append('scale['+str(ind)+']') - + super(WrapData, self).buildData(wrap) - + # ====================== # - Get Influence Data - # ====================== - + for influence in influenceList.keys(): infIndex = influenceList[influence][1] self._influenceData[influence] = {} @@ -74,18 +74,18 @@ def buildData(self,wrap): self._influenceData[influence]['influenceBase'] = mc.listConnections(wire+'.baseWire['+str(infIndex)+']',s=True,d=False)[0] self._influenceData[influence]['dropoffDist'] = mc.getAttr(wire+'.dropoffDistance['+str(infIndex)+']') self._influenceData[influence]['scale'] = mc.getAttr(wire+'.scale['+str(infIndex)+']') - + # ============================ # - Get Dropoff Locator Data - # ============================ - + dropoffLocatorList = glTools.utils.connection.connectionListToAttr(wire,'wireLocatorParameter') - + for locator in dropoffLocatorList.keys(): - + # Initialize dropoff locator data dictionary self._locatorData[locator] = {} - + # Build dropoff locator data locIndex = dropoffLocatorList[locator][1] self._locatorData[locator]['index'] = locIndex @@ -93,12 +93,12 @@ def buildData(self,wrap): self._locatorData[locator]['twist'] = mc.getAttr(wire+'.wireLocatorTwist['+str(locIndex)+']') self._locatorData[locator]['percent'] = mc.getAttr(locator+'.percent') self._locatorData[locator]['parameter'] = mc.getAttr(locator+'.param') - + # Get wire curve parent locParent = mc.listRelatives(locator,p=True)[0] crvParent = mc.listRelatives(locParent,p=True)[0] self._locatorData[locator]['parent'] = crvParent - + def rebuild(self): ''' Rebuild the wire deformer from the recorded deformerData @@ -106,83 +106,83 @@ def rebuild(self): # ========== # - Checks - # ========== - + # Check Data for influence in self._influenceData.iterkeys(): - + # Check Wire Curve if not mc.objExists(influence): print('Wire curve "'+influence+'" does not exist! Curve will not be added to deformer!') - + # Check Base Curves baseCurve = self._influenceData[influence]['influenceBase'] if not mc.objExists(baseCurve): print('Wire curve base "'+baseCurve+'" does not exist! A static base curve will be generated from the deforming wire curve!') - + # Check Dropoff Locators for locator in self._locatorData.iterkeys(): if mc.objExists(locator): mc.delete(mc.listRelatives(locator,p=True)[0]) - + # ==================== # - Rebuild Deformer - # ==================== - + result = super(WireData, self).rebuild() wireDeformer = result['deformer'] - + # ======================= # - Connect Wire Curves - # ======================= - + for influence in self._influenceData.iterkeys(): - + # Get current wire curve pair wireCurve = influence infIndex = self._influenceData[influence]['index'] baseCurve = self._influenceData[influence]['influenceBase'] - + # Connect deformed wire if not mc.objExists(influence): continue mc.connectAttr(wireCurve+'.worldSpace[0]',wireDeformer+'.deformedWire['+str(infIndex)+']',f=True) - + # Connect base wire if not mc.objExists(baseCurve): baseCurve = mc.duplicate(influence,n=baseCurve)[0] mc.connectAttr(baseCurve+'.worldSpace[0]',wireDeformer+'.baseWire['+str(infIndex)+']',f=True) mc.setAttr(baseCurve+'.v',0) - + # Set Influence Attributes if mc.getAttr(wireDeformer+'.dropoffDistance['+str(infIndex)+']',se=True): mc.setAttr(wireDeformer+'.dropoffDistance['+str(infIndex)+']',self._influenceData[influence]['dropoffDist']) if mc.getAttr(wireDeformer+'.scale['+str(infIndex)+']',se=True): mc.setAttr(wireDeformer+'.scale['+str(infIndex)+']',self._influenceData[influence]['scale']) - + # ============================ # - Rebuild Dropoff Locators - # ============================ - + for locator in self._locatorData.iterkeys(): - + # Get data parent = self._locatorData[locator]['parent'] param = self._locatorData[locator]['parameter'] env = self._locatorData[locator]['envelope'] percent = self._locatorData[locator]['percent'] twist = self._locatorData[locator]['twist'] - + # Create Locator loc = mc.dropoffLocator(env,percent,wire,parent+'.u['+str(param)+']')[0] - + # Apply Twist locConn = mc.listConnections(loc+'.param',s=False,d=True,p=True)[0] locConnIndex = locConn.split('[')[-1].split(']')[0] mc.setAttr(wireDeformer+'.wireLocatorTwist['+str(locConnIndex)+']',twist) - + # ================= # - Return Result - # ================= - + self.result['influence'] = self._influenceData.keys() self.result['dropoffLocator'] = self._locatorData.keys() - + return self.result diff --git a/model/__init__.py b/model/__init__.py index 8d1c8b6..8b13789 100644 --- a/model/__init__.py +++ b/model/__init__.py @@ -1 +1 @@ - + diff --git a/model/checksum.py b/model/checksum.py index dacbae1..384b810 100644 --- a/model/checksum.py +++ b/model/checksum.py @@ -15,17 +15,17 @@ def checksum_mesh(mesh): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object '+mesh+' is not a valid polygon mesh!') - + # Get Mesh Face Vertices vtxCnt = OpenMaya.MIntArray() vtxList = OpenMaya.MIntArray() glTools.utils.mesh.getMeshFn(mesh).getVertices(vtxCnt,vtxList) - + # Generate Checksum m = hashlib.md5() m.update(str(list(vtxList))) hexVal = m.hexdigest() - + # Return Checksum Hash return hexVal @@ -35,7 +35,7 @@ def checksum_meshUV(mesh): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object '+mesh+' is not a valid polygon mesh!') - + # Return Result return @@ -47,26 +47,26 @@ def checksum_meshDict(meshList): ''' # Initialize Checksum Dict checksum_dict = {} - + # Check Mesh List if not meshList: return checksum_dict - + # For Each Mesh for mesh in meshList: - + # Check Mesh if not glTools.utils.mesh.isMesh(mesh): print('Object '+mesh+' is not a valid polygon mesh! Skipping...') continue - + # Get Transform Parent meshTransform = mesh if not mc.objectType(mesh) == 'transform': meshTransform = mc.listRelatives(mesh,p=True)[0] - + # Get Checksum Value checksum_dict[meshTransform] = checksum_mesh(mesh) - + # Return Result return checksum_dict @@ -79,16 +79,16 @@ def checksum_meshDict_fromFile(filePath): # Check File if not os.path.isfile(filePath): raise Exception('No valid file at location "'+filePath+'"!') - + # Open File mc.file(filePath,o=True,prompt=False,force=True) - + # Get List of Mesh Objects meshList = mc.ls(type='mesh') - + # Get Checksum Dictionary checksum_dict = checksum_meshDict(meshList) - + # Return Result return checksum_dict diff --git a/model/cleanup.py b/model/cleanup.py index 781729e..2a0c4c0 100644 --- a/model/cleanup.py +++ b/model/cleanup.py @@ -20,10 +20,10 @@ def getGeoList(geoList=[]): else: geoList = [geo for geo in geoList if glTools.utils.geometry.isGeometry(geo)] if not geoList: return [] - + # Remove Duplicates geoList = list(set(geoList)) - + # Return Result return geoList @@ -39,17 +39,17 @@ def getMeshList(meshList=[]): else: meshList = [mesh for mesh in meshList if glTools.utils.mesh.isMesh(mesh)] if not meshList: return [] - + # Remove Duplicates meshList = list(set(meshList)) - + # Return Result return meshList # ========== # - Checks - # ========== - + def triangles(meshList=[]): ''' Return a list of all 3-sided polygon faces in a specified mesh list. @@ -59,14 +59,14 @@ def triangles(meshList=[]): # Check Mesh List meshList = getMeshList(meshList) if not meshList: return [] - + # Find Triangles mc.select(meshList) mc.polySelectConstraint(mode=3,type=0x0008,size=1) mc.polySelectConstraint(disable=True) tris = mc.filterExpand(ex=True,sm=34) or [] mc.select(meshList) - + # Return Result return tris @@ -79,14 +79,14 @@ def nGons(meshList=[]): # Check Mesh List meshList = getMeshList(meshList) if not meshList: return [] - + # Find N-Gons mc.select(meshList) mc.polySelectConstraint(mode=3,type=0x0008,size=3) mc.polySelectConstraint(disable=True) ngon = mc.filterExpand(ex=True,sm=34) or [] mc.select(meshList) - + # Return Result return ngon @@ -108,14 +108,14 @@ def nonManifold(meshList=[]): # Check Mesh List meshList = getMeshList(meshList) if not meshList: return [] - + # Check Non Manifold mc.select(meshList) mc.polySelectConstraint(mode=3,type=0x0001,nm=1) mc.polySelectConstraint(disable=True) nonManifoldList = mc.filterExpand(ex=True,sm=31) or [] mc.select(meshList) - + # Return result return nonManifoldList @@ -128,17 +128,17 @@ def lamina(meshList=[]): # Check Mesh List meshList = getMeshList(meshList) if not meshList: return [] - + # Check Lamina mc.select(meshList) mc.polySelectConstraint(mode=3,type=0x0008,topology=2) mc.polySelectConstraint(disable=True) laminaList = mc.filterExpand(ex=True,sm=34) or [] mc.select(meshList) - + # Return result return laminaList - + def checkLockedVertexNormals(meshList=[]): ''' Check for locked vertex normals @@ -148,21 +148,21 @@ def checkLockedVertexNormals(meshList=[]): # Check meshList meshList = getMeshList(meshList) if not meshList: return [] - + # Check Locked Normals lockedNormalList = [] for mesh in meshList: - + # Shapes meshShapes = mc.listRelatives(mesh,s=True,ni=True,pa=True) if not meshShapes: continue for meshShape in meshShapes: - + # Check Normals if True in mc.polyNormalPerVertex(meshShape+'.vtx[*]',q=True,fn=True): lockedNormalList.append(mesh) continue - + # Return Result return lockedNormalList @@ -175,35 +175,35 @@ def checkVertexTransforms(meshList=[]): # Check meshList meshList = getMeshList(meshList) if not meshList: return [] - + # Check Vertex Transforms vtxTransformList = [] for mesh in meshList: - + # Shapes meshShapes = mc.listRelatives(mesh,s=True,ni=True,pa=True) or [] for meshShape in meshShapes: - + # Avoid Redundant Checks if vtxTransformList.count(mesh): break - + # Check Shape Type if mc.objectType(meshShape) != 'mesh': continue - + # Check NonZero Values #if [i for sublist in mc.getAttr(meshShape+'.pnts[*]') for i in sublist if abs(i) > 0.0000000001]: try: for tweak in mc.getAttr(meshShape+'.pnts[*]'): for i in tweak: if abs(i) > 0.0000000001: - + # Append Result vtxTransformList.append(mesh) raise RecursiveBreak - + except RecursiveBreak: pass - + # Return Result return vtxTransformList @@ -216,14 +216,14 @@ def checkMultipleUVsets(meshList=[]): # Check meshList meshList = getMeshList(meshList) if not meshList: return [] - + # Check Multiple UV Sets multipleUVsets = [] for mesh in meshList: UVsets = mc.polyUVSet(mesh,q=True,allUVSets=True) if not UVsets: continue if len(UVsets) > 1: multipleUVsets.append(mesh) - + # Return Result return multipleUVsets @@ -236,13 +236,13 @@ def checkMissingUVsets(meshList=[]): # Check meshList meshList = getMeshList(meshList) if not meshList: return [] - + # Check Missing UV Sets missingUVsets = [] for mesh in meshList: UVsets = mc.polyUVSet(mesh,q=True,allUVSets=True) if not UVsets: missingUVsets.append(mesh) - + # Return Result return missingUVsets @@ -258,33 +258,33 @@ def checkUvShells(meshList=[],faceCountTol=1): # Check meshList meshList = getMeshList(meshList) if not meshList: return [] - + # Check Multiple UV Sets meshUVshells = [] for mesh in meshList: - + # Shapes meshShapes = mc.listRelatives(mesh,s=True,ni=True,pa=True) if not meshShapes: continue for meshShape in meshShapes: - + # Get Face Count faceCount = mc.polyEvaluate(meshShape,f=True) if faceCount <= faceCountTol: continue - + # Get UV Sets uvSets = mc.polyUVSet(meshShape,q=True,allUVSets=True) if not uvSets: continue - + # For Each UV Set for uvSet in uvSets: - + # Get Num UV Shells UVshells = glTools.utils.mesh.numUvShells(meshShape,uvSet=uvSet) if UVshells == faceCount: meshUVshells.append(mesh) break - + # Return Result return meshUVshells @@ -308,10 +308,10 @@ def unlockVertexNormals(meshList=[]): # Check meshList if not meshList: meshList = getMeshList(meshList) if not meshList: return [] - + # Unlock Normals for mesh in meshList: mc.polyNormalPerVertex(mesh,ufn=True) - + # Return Result return meshList @@ -324,10 +324,10 @@ def freezeVertexTransforms(meshList=[]): # Check meshList if not meshList: meshList = getMeshList(meshList) if not meshList: return [] - + # Freeze Vertex Transforms for mesh in meshList: glTools.utils.mesh.freezeVertices(mesh) - + # Return Result return meshList @@ -340,11 +340,11 @@ def mergeUVs(meshList=[],dist=0.0001): # Check meshList if not meshList: meshList = getMeshList(meshList) if not meshList: return [] - + # Merge UVs for mesh in meshList: mc.polyMergeUV(mesh,d=dist,ch=False) - + # Return Result return meshList @@ -361,6 +361,6 @@ def bakeCreaseSets(creaseSets=[]): # Check Crease Sets if not creaseSets: creaseSets = checkCreaseSets() if not creaseSets: return [] - + # Bake Crease Sets - + diff --git a/model/measure.py b/model/measure.py index 8ca665c..e4f6fa1 100644 --- a/model/measure.py +++ b/model/measure.py @@ -8,64 +8,64 @@ def measureBoundingBox(geo): ''' # Check Geo if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!!') - + # ============================== # - Create Distance Dimensions - # ============================== - + del_locs = [] - + # Height hDimensionShape = mc.distanceDimension(sp=(0,0,0),ep=(1,1,1)) locs = mc.listConnections(hDimensionShape,s=True,d=False) or [] del_locs += locs hDimension = mc.listRelatives(hDimensionShape,p=True)[0] hDimension = mc.rename(hDimension,geo+'_height_measure') - + # Width wDimensionShape = mc.distanceDimension(sp=(0,0,0),ep=(1,1,1)) locs = mc.listConnections(wDimensionShape,s=True,d=False) or [] del_locs += locs wDimension = mc.listRelatives(wDimensionShape,p=True)[0] wDimension = mc.rename(wDimension,geo+'_width_measure') - + # Depth dDimensionShape = mc.distanceDimension(sp=(0,0,0),ep=(1,1,1)) locs = mc.listConnections(dDimensionShape,s=True,d=False) or [] del_locs += locs dDimension = mc.listRelatives(dDimensionShape,p=True)[0] dDimension = mc.rename(dDimension,geo+'_depth_measure') - + # Group measure_grp = mc.group([hDimension,wDimension,dDimension],n=geo+'_measure_grp') - + # =============================== # - Connect Distance Dimensions - # =============================== - + # Height mc.connectAttr(geo+'.boundingBoxMin',hDimension+'.startPoint',f=True) addHeightNode = mc.createNode('plusMinusAverage',n=geo+'_height_plusMinusAverage') mc.connectAttr(geo+'.boundingBoxMin',addHeightNode+'.input3D[0]',f=True) mc.connectAttr(geo+'.boundingBoxSizeY',addHeightNode+'.input3D[1].input3Dy',f=True) mc.connectAttr(addHeightNode+'.output3D',hDimension+'.endPoint',f=True) - + # Width mc.connectAttr(geo+'.boundingBoxMin',wDimension+'.startPoint',f=True) addWidthNode = mc.createNode('plusMinusAverage',n=geo+'_width_plusMinusAverage') mc.connectAttr(geo+'.boundingBoxMin',addWidthNode+'.input3D[0]',f=True) mc.connectAttr(geo+'.boundingBoxSizeX',addWidthNode+'.input3D[1].input3Dx',f=True) mc.connectAttr(addWidthNode+'.output3D',wDimension+'.endPoint',f=True) - + # Depth mc.connectAttr(geo+'.boundingBoxMin',dDimension+'.startPoint',f=True) addDepthNode = mc.createNode('plusMinusAverage',n=geo+'_depth_plusMinusAverage') mc.connectAttr(geo+'.boundingBoxMin',addDepthNode+'.input3D[0]',f=True) mc.connectAttr(geo+'.boundingBoxSizeZ',addDepthNode+'.input3D[1].input3Dz',f=True) mc.connectAttr(addDepthNode+'.output3D',dDimension+'.endPoint',f=True) - + # Delete Unused Locators if del_locs: mc.delete(del_locs) - + # Return Result return measure_grp diff --git a/model/menu.py b/model/menu.py index 8f72950..41b5ee0 100644 --- a/model/menu.py +++ b/model/menu.py @@ -8,47 +8,47 @@ def create(): # This is a temporary hack to get maya to evaluate $gMainWindow gMainWindow = mm.eval('string $temp = $gMainWindow') if mc.menu('modelToolsMenu',q=True,ex=True): mc.deleteUI('modelToolsMenu') - + if gMainWindow: - + mc.setParent(gMainWindow) mc.menu('modelToolsMenu', label='Model Tools', tearOff=True, allowOptionBoxes=True) - + #----------------------------------------# - + mc.menuItem(label='Checks', subMenu=True, tearOff=True) - + mc.menuItem(label='Run Checks', command='import glTools.spotcheck.runChecks;reload(glTools.spotcheck.runChecks);glTools.spotcheck.runChecks.run(envKey="IKA_MODEL_SPOTCHECKS",checkTitle="Rig Checks",selectedNodes=False)') mc.menuItem(label='Run Checks On Selected', command='import glTools.spotcheck.runChecks;reload(glTools.spotcheck.runChecks);glTools.spotcheck.runChecks.run(envKey="IKA_MODEL_SPOTCHECKS",checkTitle="Rig Checks",selectedNodes=True)') - + mc.setParent('..', menu=True) - + #----------------------------------------# - + mc.menuItem(divider=True) - + # GENERAL mc.menuItem(allowOptionBoxes=True, label='General', subMenu=True, tearOff=True) - + mc.menuItem(label='Align to Ground Plane', command='import glTools.model.utils;reload(glTools.model.utils);[glTools.model.utils.setVerticalPlacement(i) for i in mc.ls(sl=True)]') mc.menuItem(label='Build Poly Edge Curves', command='import glTools.tools.polyEdgeCurve;reload(glTools.tools.polyEdgeCurve);glTools.tools.polyEdgeCurve.buildEdgeCurvesUI()') - + mc.setParent('..', menu=True) - + mc.menuItem(divider=True) - + # TOOLS mc.menuItem(allowOptionBoxes=True, label='Tools', subMenu=True, tearOff=True) - + mc.menuItem(label='Slide Deformer', command='import glTools.model.utils;reload(glTools.model.utils);[glTools.model.utils.slideDeformer(i) for i in mc.ls(sl=1)]') mc.menuItem(label='Strain Relaxer', command='import glTools.model.utils;reload(glTools.model.utils);[glTools.model.utils.strainRelaxer(i) for i in mc.ls(sl=1)]') mc.menuItem(label='Directional Smooth', command='import glTools.model.utils;reload(glTools.model.utils);[glTools.model.utils.directionalSmooth(i) for i in mc.ls(sl=1)]') mc.menuItem(label='Straighten Vertices...', command='import glTools.model.straightenVerts;reload(glTools.model.straightenVerts);glTools.model.straightenVerts.straightenVertsUI()') mc.menuItem(label='Even Edge Spacing...', command='import glTools.model.straightenVerts;reload(glTools.model.straightenVerts);glTools.model.straightenVerts.evenEdgeSpacingUI()') mc.menuItem(label='Smooth Edge Line...', command='import glTools.model.straightenVerts;reload(glTools.model.straightenVerts);glTools.model.straightenVerts.smoothEdgeLineUI()') - + mc.menuItem(allowOptionBoxes=True, label='Mirror Tools', subMenu=True, tearOff=True) - + mc.menuItem(label='Auto Mirror', command='import glTools.utils.edgeFlowMirror;reload(glTools.utils.edgeFlowMirror);glTools.utils.edgeFlowMirror.autoMirror()') mc.menuItem(label='Mirror X (+ -> -)', command='import glTools.utils.edgeFlowMirror;reload(glTools.utils.edgeFlowMirror);glTools.utils.edgeFlowMirror.mirrorGeo(mc.ls(sl=True,fl=True)[0])') mc.menuItem(label='Mirror X (- -> +)', command='import glTools.utils.edgeFlowMirror;reload(glTools.utils.edgeFlowMirror);glTools.utils.edgeFlowMirror.mirrorGeo(mc.ls(sl=True,fl=True)[0],posToNeg=False)') @@ -56,33 +56,33 @@ def create(): mc.menuItem(label='Mirror Y (- -> +)', command='import glTools.utils.edgeFlowMirror;reload(glTools.utils.edgeFlowMirror);glTools.utils.edgeFlowMirror.mirrorGeo(mc.ls(sl=True,fl=True)[0],axis="y",posToNeg=False)') mc.menuItem(label='Mirror Z (+ -> -)', command='import glTools.utils.edgeFlowMirror;reload(glTools.utils.edgeFlowMirror);glTools.utils.edgeFlowMirror.mirrorGeo(mc.ls(sl=True,fl=True)[0]),axis="z"') mc.menuItem(label='Mirror Z (- -> +)', command='import glTools.utils.edgeFlowMirror;reload(glTools.utils.edgeFlowMirror);glTools.utils.edgeFlowMirror.mirrorGeo(mc.ls(sl=True,fl=True)[0],axis="z",posToNeg=False)') - + mc.setParent('..', menu=True) - + mc.menuItem(allowOptionBoxes=True, label='Align Tools', subMenu=True, tearOff=True) - + mc.menuItem(label='Align to Best Fit', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="bestFitPlane",localAxis=False)') - + mc.menuItem(label='Align (+X) Local', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="+x",localAxis=True)') mc.menuItem(label='Align (-X) Local', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="-x",localAxis=True)') mc.menuItem(label='Align (+Y) Local', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="+y",localAxis=True)') mc.menuItem(label='Align (-Y) Local', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="-y",localAxis=True)') mc.menuItem(label='Align (+Z) Local', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="+z",localAxis=True)') mc.menuItem(label='Align (-Z) Local', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="-z",localAxis=True)') - + mc.menuItem(label='Align (+X) World', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="+x",localAxis=False)') mc.menuItem(label='Align (-X) World', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="-x",localAxis=False)') mc.menuItem(label='Align (+Y) World', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="+y",localAxis=False)') mc.menuItem(label='Align (-Y) World', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="-y",localAxis=False)') mc.menuItem(label='Align (+Z) World', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="+z",localAxis=False)') mc.menuItem(label='Align (-Z) World', command='import glTools.model.utils;reload(glTools.model.utils);glTools.model.utils.alignControlPoints(mc.ls(sl=True,fl=True),axis="-z",localAxis=False)') - + mc.setParent('..', menu=True) - + mc.setParent('..', menu=True) - + #----------------------------------------# - + mc.menuItem(divider =True) mc.menuItem(label='Refresh Menu', command='import glTools.model.menu;reload(glTools.model.menu);glTools.model.menu.create()') mc.setParent('..') diff --git a/model/normalCheck.py b/model/normalCheck.py index 5c3caa5..85a1342 100644 --- a/model/normalCheck.py +++ b/model/normalCheck.py @@ -12,7 +12,7 @@ def normalCheck(meshList=[]): # Check Mesh List meshList = cleanup.getMeshList(meshList) if not meshList: return [] - + # Check Normal Shader normalSG = 'normalCheckSG' normalShader = 'normalCheckShader' @@ -23,29 +23,29 @@ def normalCheck(meshList=[]): mc.connectAttr(normalShader+'.outColor',normalSG+'.surfaceShader',f=True) mc.setAttr(normalShader+'.color',0,0,0) mc.setAttr(normalShader+'.incandescence',1,0,0) - + # Setup Normal Check for mesh in meshList: - + # Clear selection mc.select(cl=True) - + # Turn on double sided mc.setAttr(mesh+'.doubleSided',1) - + # Extrude face numFace = mc.polyEvaluate(mesh,f=True) polyExtrude = mc.polyExtrudeFacet(mesh+'.f[0:'+str(numFace)+']',ch=1,kft=True,pvt=(0,0,0),divisions=2,twist=0,taper=1,off=0,smoothingAngle=30) mm.eval('PolySelectTraverse 1') extrudeFaceList = mc.filterExpand(ex=True,sm=34) mc.setAttr(polyExtrude[0]+'.localTranslateZ',-0.001) - + # Apply shader mc.sets(extrudeFaceList,fe=normalSG) - + # Set selection mc.select(meshList) - + # Retrun result return meshList @@ -58,33 +58,33 @@ def normalCheckRemove(meshList=[]): # Check Mesh List meshList = cleanup.getMeshList(meshList) if not meshList: return [] - + # Remove Normal Check for mesh in meshList: - + # Clear Selection mc.select(cl=True) - + # Turn Off Double Sided mc.setAttr(mesh+'.doubleSided',0) - + # Remove Extrude Face polyExtrude = mc.ls(mc.listHistory(mesh),type='polyExtrudeFace') if polyExtrude: mc.delete(polyExtrude) - + # Delete History mc.delete(mesh,ch=True) - + # Apply Initial Shading Group mc.sets(mesh,fe='initialShadingGroup') - + # Check normalShader members normalSG = 'normalCheckSG' normalShader = 'normalCheckShader' if not mc.sets(normalSG,q=True): mc.delete(normalShader,normalSG) - + # Set Selection mc.select(meshList) - + # Retrun Result return meshList diff --git a/model/straightenVerts.py b/model/straightenVerts.py index cd80530..77cafd5 100644 --- a/model/straightenVerts.py +++ b/model/straightenVerts.py @@ -34,12 +34,12 @@ def straightenVerts( edgeList, edgeList = mc.filterExpand(edgeList,ex=True,sm=32) or [] if not edgeList: raise Exception('Invalid or empty edge list! Unable to straighten vertices...') - + # Build Edge Curve from Vertices edgeCrvList = glTools.tools.extractCurves.extractEdgeCurves(edgeList,keepHistory=False) straightCrvList = [] for edgeCrv in edgeCrvList: - + # Build Straight Curve straightCrv = mc.rebuildCurve( edgeCrv, ch = False, @@ -53,7 +53,7 @@ def straightenVerts( edgeList, s = 1, d = 1, tol = 0 )[0] - + # Rebuild Straight Curve dist = [] total = 0.0 @@ -71,36 +71,36 @@ def straightenVerts( edgeList, params.append(d) else: params = glTools.utils.mathUtils.distributeValue(pts.length(),rangeEnd=max)[1:-1] - + params = [straightCrv+'.u['+str(i)+']' for i in params] mc.insertKnotCurve(params,ch=False,numberOfKnots=1,add=True,ib=False,rpo=True) - + # Snap To Mesh mesh = mc.ls(edgeList,o=True)[0] if snapToOriginal: pts = glTools.utils.component.getComponentStrList(straightCrv) glTools.utils.mesh.snapPtsToMesh(mesh,pts) - + # Append List straightCrvList.append(straightCrv) - + # ================= # - Deform Points - # ================= - + # Build Wire Deformer wire = glTools.utils.wire.createMulti(mesh,edgeCrvList,dropoffDist=falloff,prefix=mesh.split(':')[-1]) mc.setAttr(wire[0]+'.rotation',0) - + # Blend to Straight Curve for i in range(len(edgeCrvList)): blendShape = glTools.utils.blendShape.create(baseGeo=edgeCrvList[i],targetGeo=[straightCrvList[i]]) mc.setAttr(blendShape+'.'+straightCrvList[i],influence) - + # ================== # - Delete History - # ================== - + if deleteHistory: wireBaseList = glTools.utils.wire.getWireBase(wire[0]) mc.delete(mesh,ch=True) @@ -113,15 +113,15 @@ def straightenVerts( edgeList, for wireBase in wireBaseList: if mc.objExists(wireBase): mc.delete(wireBase) - + # ================= # - Return Result - # ================= - + if edgeList: mc.hilite(mesh) mc.select(edgeList) - + return edgeList def straightenVertsUI(): @@ -132,17 +132,17 @@ def straightenVertsUI(): window = 'straightenVertsUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Straighten Vertices',s=True) - + # Layout CL = mc.columnLayout() - + # UI Elements mc.floatSliderGrp('straightenVerts_falloffFSG',label='Falloff Distance',field=True,precision=3,minValue=0.0,maxValue=10.0,fieldMinValue=0.0,fieldMaxValue=100.0,value=0.01) mc.checkBoxGrp('straightenVerts_edgeSpacingCBG',label='Maintain Edge Spacing',numberOfCheckBoxes=1,v1=False) mc.checkBoxGrp('straightenVerts_snapToOrigCBG',label='Maintain Shape',numberOfCheckBoxes=1,v1=False) # columnWidth2=[100,165] mc.checkBoxGrp('straightenVerts_deleteHistoryCBG',label='Delete History',numberOfCheckBoxes=1,v1=False) mc.button('straightenVertsB',l='Straighten',w=390,c='glTools.model.straightenVerts.straightenVertsFromUI()') - + # Show Window mc.window(window,e=True,wh=[392,92]) mc.showWindow(window) @@ -162,23 +162,23 @@ def straightenVertsFromUI(): if not edges: print('Select a list of connected vertices or edges and run again...') return - + # Get Mesh from vertices mesh = mc.ls(edges,o=True) - + # Get UI Parameters falloff = mc.floatSliderGrp('straightenVerts_falloffFSG',q=True,value=True) edgeSpacing = mc.checkBoxGrp('straightenVerts_edgeSpacingCBG',q=True,v1=True) snapToOrig = mc.checkBoxGrp('straightenVerts_snapToOrigCBG',q=True,v1=True) delHistory = mc.checkBoxGrp('straightenVerts_deleteHistoryCBG',q=True,v1=True) - + # Straighten Vertices straightenVerts( edgeList = edges, falloff = falloff, keepEdgeSpacing = edgeSpacing, snapToOriginal = snapToOrig, deleteHistory = delHistory) - + # Restore Selection if sel: mc.selectMode(component=True) @@ -207,11 +207,11 @@ def evenEdgeSpacing( edgeList, edgeList = mc.filterExpand(edgeList,ex=True,sm=32) or [] if not edgeList: raise Exception('Invalid or empty edge list! Unable to even edge spacing...') - + edgeCrvList = glTools.tools.extractCurves.extractEdgeCurves(edgeList,keepHistory=False) evenCrvList = [] for edgeCrv in edgeCrvList: - + # Rebuild Even Curve evenCrv = mc.rebuildCurve( edgeCrv, ch = False, @@ -225,32 +225,32 @@ def evenEdgeSpacing( edgeList, s = 0, d = 1, tol = 0 )[0] - + # Smooth Curve if smooth: smoothCurve(evenCrv,smooth,True) - + # Snap To Mesh mesh = mc.ls(edgeList,o=True)[0] if snapToOrig: pts = glTools.utils.component.getComponentStrList(evenCrv) glTools.utils.mesh.snapPtsToMesh(mesh,pts) - + evenCrvList.append(evenCrv) - + # Apply Even Spacing to Mesh Edge Vertices wire = glTools.utils.wire.createMulti(mesh,edgeCrvList,dropoffDist=0.01,prefix=mesh.split(':')[-1]) mc.setAttr(wire[0]+'.rotation',0) mc.setAttr(wire[0]+'.envelope',influence) - + # Blend to Even Curve for i in range(len(edgeCrvList)): blendShape = glTools.utils.blendShape.create(baseGeo=edgeCrvList[i],targetGeo=[evenCrvList[i]]) mc.setAttr(blendShape+'.'+evenCrvList[i],1) - + # ================== # - Delete History - # ================== - + if deleteHistory: wireBaseList = glTools.utils.wire.getWireBase(wire[0]) mc.delete(mesh,ch=True) @@ -263,15 +263,15 @@ def evenEdgeSpacing( edgeList, for wireBase in wireBaseList: if mc.objExists(wireBase): mc.delete(wireBase) - + # ================= # - Return Result - # ================= - + if edgeList: mc.hilite(mesh) mc.select(edgeList) - + return edgeList def evenEdgeSpacingUI(): @@ -282,17 +282,17 @@ def evenEdgeSpacingUI(): window = 'evenEdgeSpacingUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Even Edge Spacing',s=True) - + # Layout CL = mc.columnLayout() - + # UI Elements mc.intSliderGrp('evenEdgeSpacing_smoothISG',label='Smooth',field=True,minValue=0,maxValue=20,fieldMinValue=0,fieldMaxValue=100,value=4) mc.floatSliderGrp('evenEdgeSpacing_influenceFSG',label='Influence',field=True,minValue=0.0,maxValue=1.0,fieldMinValue=0.0,fieldMaxValue=1.0,value=1.0) mc.checkBoxGrp('evenEdgeSpacing_snapToOrigCBG',label='Maintain Shape',numberOfCheckBoxes=1,v1=False) # columnWidth2=[100,165] mc.checkBoxGrp('evenEdgeSpacing_deleteHistoryCBG',label='Delete History',numberOfCheckBoxes=1,v1=False) mc.button('evenEdgeSpacingB',l='Even Edge Spacing',w=390,c='glTools.model.straightenVerts.evenEdgeSpacingFromUI()') - + # Show Window mc.window(window,e=True,wh=[392,99]) mc.showWindow(window) @@ -312,23 +312,23 @@ def evenEdgeSpacingFromUI(): if not edges: print('Select a list of connected vertices or edges and run again...') return - + # Get Mesh from vertices mesh = mc.ls(edges,o=True) - + # Get UI Parameters smooth = mc.intSliderGrp('evenEdgeSpacing_smoothISG',q=True,v=True) influence = mc.floatSliderGrp('evenEdgeSpacing_influenceFSG',q=True,v=True) snapToOrig = mc.checkBoxGrp('evenEdgeSpacing_snapToOrigCBG',q=True,v1=True) delHistory = mc.checkBoxGrp('evenEdgeSpacing_deleteHistoryCBG',q=True,v1=True) - + # Even Edge Spacing evenEdgeSpacing( edgeList = edges, smooth = smooth, influence = influence, snapToOrig = snapToOrig, deleteHistory = delHistory ) - + # Restore Selection if sel: mc.selectMode(component=True) @@ -348,40 +348,40 @@ def smoothEdgeLine( edgeList, edgeList = mc.filterExpand(edgeList,ex=True,sm=32) or [] if not edgeList: raise Exception('Invalid or empty edge list! Unable to even edge spacing...') - + edgeCrvList = glTools.tools.extractCurves.extractEdgeCurves(edgeList,keepHistory=False) smoothCrvList = [] for edgeCrv in edgeCrvList: - + # Smooth Edge Line smoothCrv = mc.duplicate(edgeCrv,n=edgeCrv+'_smoothed')[0] smoothCurve( crv = smoothCrv, iterations = smooth, keepEnds = True, keepSpacing = keepEdgeSpacing ) - + # Snap To Mesh mesh = mc.ls(edgeList,o=True)[0] if snapToOrig: pts = glTools.utils.component.getComponentStrList(smoothCrv) glTools.utils.mesh.snapPtsToMesh(mesh,pts) - + # Append List smoothCrvList.append(smoothCrv) - + # Apply Smoothed Edge to Vertices wire = glTools.utils.wire.createMulti(mesh,edgeCrvList,dropoffDist=falloff,prefix=mesh.split(':')[-1]) mc.setAttr(wire[0]+'.rotation',0) - + # Blend to Smooth Curve for i in range(len(edgeCrvList)): blendShape = glTools.utils.blendShape.create(baseGeo=edgeCrvList[i],targetGeo=[smoothCrvList[i]]) mc.setAttr(blendShape+'.'+smoothCrvList[i],1) - + # ================== # - Delete History - # ================== - + if deleteHistory: wireBaseList = glTools.utils.wire.getWireBase(wire[0]) mc.delete(mesh,ch=True) @@ -394,15 +394,15 @@ def smoothEdgeLine( edgeList, for wireBase in wireBaseList: if mc.objExists(wireBase): mc.delete(wireBase) - + # ================= # - Return Result - # ================= - + if edgeList: mc.hilite(mesh) mc.select(edgeList) - + return edgeList def smoothEdgeLineUI(): @@ -413,10 +413,10 @@ def smoothEdgeLineUI(): window = 'smoothEdgesUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Smooth Edge Line',s=True) - + # Layout CL = mc.columnLayout() - + # UI Elements mc.intSliderGrp('smoothEdges_smoothISG',label='Smooth',field=True,minValue=1,maxValue=20,fieldMinValue=1,fieldMaxValue=100,value=4) mc.floatSliderGrp('smoothEdges_falloffFSG',label='Falloff Distance',field=True,precision=3,minValue=0.0,maxValue=10.0,fieldMinValue=0.0,fieldMaxValue=100.0,value=0.01) @@ -424,7 +424,7 @@ def smoothEdgeLineUI(): mc.checkBoxGrp('smoothEdges_snapToOrigCBG',label='Maintain Shape',numberOfCheckBoxes=1,v1=False) # columnWidth2=[100,165] mc.checkBoxGrp('smoothEdges_deleteHistoryCBG',label='Delete History',numberOfCheckBoxes=1,v1=False) mc.button('smoothEdgesB',l='Smooth',w=390,c='glTools.model.straightenVerts.smoothEdgeLineFromUI()') - + # Show Window mc.window(window,e=True,wh=[392,115]) mc.showWindow(window) @@ -444,17 +444,17 @@ def smoothEdgeLineFromUI(): if not edges: print('Select a list of connected vertices or edges and run again...') return - + # Get Mesh from vertices mesh = mc.ls(edges,o=True) - + # Get UI Parameters smooth = mc.intSliderGrp('smoothEdges_smoothISG',q=True,v=True) falloff = mc.floatSliderGrp('smoothEdges_falloffFSG',q=True,v=True) edgeSpacing = mc.checkBoxGrp('smoothEdges_edgeSpacingCBG',q=True,v1=True) snapToOrig = mc.checkBoxGrp('smoothEdges_snapToOrigCBG',q=True,v1=True) delHistory = mc.checkBoxGrp('smoothEdges_deleteHistoryCBG',q=True,v1=True) - + # Smooth Edges smoothEdgeLine( edges, smooth = smooth, @@ -462,7 +462,7 @@ def smoothEdgeLineFromUI(): snapToOrig = snapToOrig, keepEdgeSpacing = edgeSpacing, deleteHistory = delHistory ) - + # Restore Selection if sel: mc.selectMode(component=True) @@ -499,7 +499,7 @@ def smoothLine(pts,iterations=1,keepEnds=True,keepSpacing=False): else: pt = (curr * 0.4) + OpenMaya.MVector((next+OpenMaya.MVector(prev)) * 0.3) pts[i] = [pt.x,pt.y,pt.z] - + # Return Result return pts @@ -520,10 +520,10 @@ def smoothCurve(crv,iterations,keepEnds=True,keepSpacing=False): iterations = iterations, keepEnds = keepEnds, keepSpacing = keepSpacing ) - + # Flatten Smooth Points List ptsFlat = [] [ptsFlat.extend(i) for i in pts] - + # Apply Smoothed Points mc.setAttr(crv+'.cv[0:'+str(len(pts)-1)+']',*ptsFlat) diff --git a/model/ui.py b/model/ui.py index b1091be..d71c6dd 100644 --- a/model/ui.py +++ b/model/ui.py @@ -5,26 +5,26 @@ def displayListWindow(itemList,title): ''' # Check itemList if not itemList: return - + # Window window = 'displayListWindowUI' if mc.window(window,q=True,ex=True): mc.deleteUI(window) window = mc.window(window,t=title,s=True) - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # UI Elements TSL = mc.textScrollList('displayListWindowTSL',allowMultiSelection=True) for item in itemList: mc.textScrollList(TSL,e=True,a=item) mc.textScrollList(TSL,e=True,sc='glTools.ui.utils.selectFromTSL("'+TSL+'")') closeB = mc.button('displayListWindowB',l='Close',c='mc.deleteUI("'+window+'")') - + # Form Layout mc.formLayout(FL,e=True,af=[(TSL,'top',5),(TSL,'left',5),(TSL,'right',5)]) mc.formLayout(FL,e=True,af=[(closeB,'bottom',5),(closeB,'left',5),(closeB,'right',5)]) mc.formLayout(FL,e=True,ac=[(TSL,'bottom',5,closeB)]) - + # Display Window mc.showWindow(window) @@ -33,23 +33,23 @@ def reportWindow(msg,title): ''' # Check message if not msg: return - + # Window window = 'reportWindowUI' if mc.window(window,q=True,ex=True): mc.deleteUI(window) window = mc.window(window,t=title,s=True) - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # UI Elements reportSF = mc.scrollField('reportWindowSF',editable=False,wordWrap=True,text=msg) closeB = mc.button('reportWindowB',l='Close',c='mc.deleteUI("'+window+'")') - + # Form Layout mc.formLayout(FL,e=True,af=[(reportSF,'top',5),(reportSF,'left',5),(reportSF,'right',5)]) mc.formLayout(FL,e=True,af=[(closeB,'bottom',5),(closeB,'left',5),(closeB,'right',5)]) mc.formLayout(FL,e=True,ac=[(reportSF,'bottom',5,closeB)]) - + # Display Window mc.showWindow(window) diff --git a/model/utils.py b/model/utils.py index befda70..8b347c2 100644 --- a/model/utils.py +++ b/model/utils.py @@ -21,14 +21,14 @@ def setVerticalPlacement(obj,freezeTransform=False): # Checks if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!!') - + # Get Bounding Box Base bbox = glTools.utils.base.getMBoundingBox(obj) base = bbox.min().y - + # Set position mc.move(0,-base,0,obj,ws=True,r=True) - + # Freeze Transforms if freezeTransform: mc.makeIdentity() @@ -39,13 +39,13 @@ def alignControlPoints(controlPointList,axis,localAxis=True): @type controlPointList: list @param axis: Axis to align control points to. Accepted values are "+x", "-x", "+y", "-y", "+z", "-z" and "bestFitPlane". @type axis: str - @param localAxis: Specify if the align axis is in local or world relative. + @param localAxis: Specify if the align axis is in local or world relative. @type localAxis: bool ''' # ========== # - Checks - # ========== - + # Control Point List if not controlPointList: raise Exception('Invalid control points list specified!') @@ -53,22 +53,22 @@ def alignControlPoints(controlPointList,axis,localAxis=True): axisList = ['+x','-x','+y','-y','+z','-z','bestFitPlane'] if not axisList.count(axis): raise Exception('Invalid axis value specified! ("'+axis+'")') - + # Filter Control Point List controlPointList = mc.filterExpand(controlPointList,sm=[28,31,46]) - + # Local Axis if axis == 'bestFitPlane': localAxis = False - + # ======================== # - Align Control Points - # ======================== - + # Get Control Point Position List ptList = [] for cp in controlPointList: ptList.append(mc.pointPosition(cp,w=not(localAxis),l=localAxis)) - + # Align Positions minVal = 99999.9 maxVal = -99999.9 @@ -76,67 +76,67 @@ def alignControlPoints(controlPointList,axis,localAxis=True): for i in range(len(ptList)): if ptList[i][0] > maxVal: maxVal = ptList[i][0] ptList = [(maxVal,pt[1],pt[2]) for pt in ptList] - + elif axis == '-x': for i in range(len(ptList)): if ptList[i][0] < minVal: minVal = ptList[i][0] ptList = [(minVal,pt[1],pt[2]) for pt in ptList] - + elif axis == '+y': for i in range(len(ptList)): if ptList[i][1] > maxVal: maxVal = ptList[i][1] ptList = [(pt[0],maxVal,pt[2]) for pt in ptList] - + elif axis == '-y': for i in range(len(ptList)): if ptList[i][1] < minVal: minVal = ptList[i][1] ptList = [(pt[0],minVal,pt[2]) for pt in ptList] - + elif axis == '+z': for i in range(len(ptList)): if ptList[i][2] > maxVal: maxVal = ptList[i][2] ptList = [(pt[0],pt[1],maxVal) for pt in ptList] - + elif axis == '-z': for i in range(len(ptList)): if ptList[i][2] < minVal: minVal = ptList[i][2] ptList = [(pt[0],pt[1],minVal) for pt in ptList] - + elif axis == 'bestFitPlane': - + # Get Best Fit Plane Matrix mat = glTools.tools.bestFitPlane.bestFitPlaneMatrix(ptList) - + print('Got best fit plane') - + for i in range(len(ptList)): - + print(controlPointList[i]) - - # Get Best Fit Plane Position + + # Get Best Fit Plane Position pPt = glTools.utils.matrix.vectorMatrixMultiply( vector = ptList[i], matrix = mat, transformAsPoint = True, invertMatrix = True) - + # Project to Best Fit Plane pPt = (pPt[0],0.0,pPt[2]) - + # Get World Space Position ptList[i] = glTools.utils.matrix.vectorMatrixMultiply( vector = pPt, matrix = mat, transformAsPoint = True, invertMatrix = False) - + else: raise Exception('Invalid axis value! ("'+axis+'")') - + print('Aligned!') - + # =============================== # - Set Control Point Positions - # =============================== - + for i in range(len(ptList)): print i mc.move(ptList[i][0],ptList[i][1],ptList[i][2],controlPointList[i],a=True,ws=not(localAxis),os=localAxis) @@ -147,11 +147,11 @@ def loadIkaRigTools(): ''' # Check if plugin is loaded if not mc.pluginInfo('glToolsTools',q=True,l=True): - + # Load Plugin try: mc.loadPlugin('glToolsTools') except: raise Exception('Unable to load glToolsTools plugin!') - + # Return Result return 1 @@ -164,39 +164,39 @@ def slideDeformer(geo): # ========== # - Checks - # ========== - + if not mc.objExists(geo): raise Exception('Object "'+geo+'" does not exist!!') - + # Mesh Shape if not glTools.utils.mesh.isMesh(geo): raise Exception('Object "'+geo+'" is not a valid mesh!!') shape = mc.listRelatives(geo,s=True,ni=True) if not shape: raise Exception('Object "'+geo+'" has no deformable geometry!!') - + # Load Plugin loadIkaRigTools() - + # Get Prefix prefix = geo.split(':')[-1] - + # =================== # - Create Deformer - # =================== - + slideDeformer = mc.deformer(geo,type='slideDeformer',n=prefix+'_slideDeformer')[0] - + # Connect Ref Mesh Shape inputMesh = None try: inputMesh = glTools.utils.shape.findInputShape(shape[0],recursive=True) except: pass if inputMesh: mc.connectAttr(inputMesh+'.outMesh',slideDeformer+'.referenceMesh',f=True) - + # ================= # - Return Result - # ================= - + return slideDeformer def strainRelaxer(geo): @@ -208,39 +208,39 @@ def strainRelaxer(geo): # ========== # - Checks - # ========== - + if not mc.objExists(geo): raise Exception('Object "'+geo+'" does not exist!!') - + # Mesh Shape if not glTools.utils.mesh.isMesh(geo): raise Exception('Object "'+geo+'" is not a valid mesh!!') shape = mc.listRelatives(geo,s=True,ni=True) if not shape: raise Exception('Object "'+geo+'" has no deformable geometry!!')\ - + # Load Plugin loadIkaRigTools() - + # Get Prefix prefix = geo.split(':')[-1] - + # =================== # - Create Deformer - # =================== - + strainRelaxer = mc.deformer(geo,type='strainRelaxer',n=prefix+'_strainRelaxer')[0] - + # Connect Ref Mesh Shape inputMesh = '' try: inputMesh = glTools.utils.shape.findInputShape(shape[0],recursive=True) except: pass if inputMesh: mc.connectAttr(inputMesh+'.outMesh',strainRelaxer+'.refMesh',f=True) - + # ================= # - Return Result - # ================= - + return strainRelaxer def directionalSmooth(geo): @@ -252,39 +252,39 @@ def directionalSmooth(geo): # ========== # - Checks - # ========== - + if not mc.objExists(geo): raise Exception('Object "'+geo+'" does not exist!!') - + # Mesh Shape if not glTools.utils.mesh.isMesh(geo): raise Exception('Object "'+geo+'" is not a valid mesh!!') shape = mc.listRelatives(geo,s=True,ni=True) if not shape: raise Exception('Object "'+geo+'" has no deformable geometry!!') - + # Load Plugin loadIkaRigTools() - + # Get Prefix prefix = geo.split(':')[-1] - + # =================== # - Create Deformer - # =================== - + directionalSmooth = mc.deformer(geo,type='directionalSmooth',n=prefix+'_directionalSmooth')[0] - + # Connect Ref Mesh Shape inputMesh = '' try: inputMesh = glTools.utils.shape.findInputShape(shape[0],recursive=True) except: pass if inputMesh: mc.connectAttr(inputMesh+'.outMesh',directionalSmooth+'.referenceMesh',f=True) - + # ================= # - Return Result - # ================= - + return directionalSmooth def deltaMush(geo): @@ -296,42 +296,42 @@ def deltaMush(geo): # ========== # - Checks - # ========== - + # Check Geometry if not mc.objExists(geo): raise Exception('Object "'+geo+'" does not exist!!') - + # Mesh Shape if not glTools.utils.mesh.isMesh(geo): raise Exception('Object "'+geo+'" is not a valid mesh!!') shape = mc.listRelatives(geo,s=True,ni=True) if not shape: raise Exception('Object "'+geo+'" has no deformable geometry!!') - + # Load Plugin if not mc.pluginInfo('deltaMush',q=True,l=True): - + # Load Plugin try: mc.loadPlugin('deltaMush') except: raise Exception('Unable to load glToolsTools plugin!') - + # Get Prefix prefix = geo.split(':')[-1] - + # =================== # - Create Deformer - # =================== - + deltaMush = mc.deformer(geo,type='deltaMush',n=prefix+'_deltaMush')[0] - + # Connect Ref Mesh Shape inputMesh = None try: inputMesh = glTools.utils.shape.findInputShape(shape[0],recursive=True) except: pass if inputMesh: mc.connectAttr(inputMesh+'.outMesh',deltaMush+'.referenceMesh',f=True) - + # ================= # - Return Result - # ================= - + return deltaMush diff --git a/rig/attach.py b/rig/attach.py index 593ed36..0996821 100644 --- a/rig/attach.py +++ b/rig/attach.py @@ -34,79 +34,79 @@ def switchConstraint( attachType, # ========== # - Checks - # ========== - + # Attach Type if not attachType in ['point','orient','parent','scale','all']: raise Exception('Invalid attach type! ("'+attachType+'")') - + # Prefix if not prefix: prefix = transform - + # Transform if not mc.objExists(transform): raise Exception('Transform "'+transform+'" does not exist!') - + # Target for target in targetList: if not mc.objExists(target): raise Exception('Target transform "'+target+'" does not exist!') - + # Target Alias List if not aliasList: aliasList = targetList - + # Switch Control if switchCtrl and not mc.objExists(switchCtrl): raise Exception('Switch control "'+switchCtrl+'" does not exist!') - + # ===================== # - Switch Attributes - # ===================== - + # Create Switch Attribute if switchCtrl: if not mc.objExists(switchCtrl+'.'+switchAttr): mc.addAttr(switchCtrl,ln=switchAttr,at='enum',en=':'.join(aliasList),k=True) - + # ============================ # - Create Target Transforms - # ============================ - + # Initialize new target list if createTarget: - + # For Each Target cTargetList = [] for t in range(len(targetList)): - + # Duplicate transform to generate new target cTarget = mc.createNode('transform',n=prefix+'_'+aliasList[t]+'_target') glTools.utils.transform.match(cTarget,transform) - + # Parent Control Target to Current Constraint Target try: cTarget = mc.parent(cTarget,targetList[t])[0] except: raise Exception('Unable to parent target null "'+cTarget+'" to target transform "'+targetList[t]+'"!') - + # Target Display Override glTools.utils.base.displayOverride(cTarget,overrideEnable=1,overrideDisplay=2) - + # Append to Target List cTargetList.append(cTarget) - + # Update target list targetList = cTargetList - + # Set Channel States chStateUtil = glTools.utils.channelState.ChannelState() chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,2],objectList=targetList) - + # ===================== # - Create Constraint - # ===================== - + # Initialize scale constraint valiables ("all" only) scaleConstraint = None scaleWtAlias = [] - + if attachType == 'point': constraint = mc.pointConstraint(targetList,transform,mo=False,n=prefix+'_pointConstraint')[0] wtAlias = mc.pointConstraint(constraint,q=True,wal=True) @@ -124,41 +124,41 @@ def switchConstraint( attachType, wtAlias = mc.parentConstraint(constraint,q=True,wal=True) scaleConstraint = mc.scaleConstraint(targetList,transform,mo=False,n=prefix+'_scaleConstraint')[0] scaleWtAlias = mc.scaleConstraint(scaleConstraint,q=True,wal=True) - + # ============================= # - Connect to Switch Control - # ============================= - + if switchCtrl: - + # Initialize switch list switchNodes = [] for i in range(len(targetList)): - + # Create Switch Node switchNode = mc.createNode('condition',n=prefix+'_'+wtAlias[i]+'_condition') - + # Connect to switch attr mc.connectAttr(switchCtrl+'.'+switchAttr,switchNode+'.firstTerm',f=True) mc.setAttr(switchNode+'.secondTerm',i) mc.setAttr(switchNode+'.operation',0) # Equal mc.setAttr(switchNode+'.colorIfTrue',1,0,0) mc.setAttr(switchNode+'.colorIfFalse',0,1,1) - + # Connect to constraint target weight mc.connectAttr(switchNode+'.outColorR',constraint+'.'+wtAlias[i]) - + # Connect to scale constraint, if necessary ("all" only) if scaleConstraint: mc.connectAttr(switchNode+'.outColorR',scaleConstraint+'.'+scaleWtAlias[i]) - + # Append switch list switchNodes.append(switchNode) - + # ================= # - Return Result - # ================= - + return constraint def switchTargetVisibility( switchConstraint, @@ -177,38 +177,38 @@ def switchTargetVisibility( switchConstraint, # ========== # - Checks - # ========== - + # Check Constraint if not glTools.utils.constraint.isConstraint(switchConstraint): raise Exception('Object "'+switchConstraint+'" is not a valid constraint!') - + # =============================== # - Get Switch Constraint Nodes - # =============================== - + # Get Switch Conditions from Constraint switchCond = mc.ls(mc.listConnections(switchConstraint,s=True,d=False),type='condition') - + # Get Switch Control from Conditions switchAttr = list(set(mc.listConnections(switchCond,s=True,d=False,p=True))) if len(switchAttr) > 1: raise Exception('Multiple input attributes driving switchConstraint "'+switchConstraint+'"!') switchCtrl = mc.ls(switchAttr[0],o=True)[0] switchAttr = switchAttr[0].split('.')[-1] - + # Get Switch Targets from Constraint switchTargets = glTools.utils.constraint.targetList(switchConstraint) switchAlias = mc.addAttr(switchCtrl+'.'+switchAttr,q=True,en=True).split(':') - + # ============================= # - Connect Target Visibility - # ============================= - + # Check Target Visibility Attribute if not targetVisAttr: targetVisAttr = switchAttr+'Vis' if not mc.objExists(switchCtrl+'.'+targetVisAttr): mc.addAttr(switchCtrl,ln=targetVisAttr,at='enum',en='Off:On') mc.setAttr(switchCtrl+'.'+targetVisAttr,cb=True,l=False) - + # Target Label Visibility labelVisChoice = None if targetLabels: @@ -218,17 +218,17 @@ def switchTargetVisibility( switchConstraint, mc.setAttr(labelVisChoice+'.input[0]',0) mc.setAttr(labelVisChoice+'.input[1]',0) mc.setAttr(labelVisChoice+'.input[2]',1) - + # For Each Target for t in range(len(switchTargets)): - + # Connect Display Handle Visibility mc.setAttr(switchTargets[t]+'.displayHandle',1,l=True) mc.connectAttr(switchCtrl+'.'+targetVisAttr,switchTargets[t]+'.v',f=True) - + # Connect Target Label Visibility if targetLabels: labelShape = mc.createNode('annotationShape',n=switchTargets[t]+'Shape',p=switchTargets[t]) mc.connectAttr(labelVisChoice+'.output',labelShape+'.v',f=True) mc.setAttr(labelShape+'.text',switchAlias[t],type='string') - mc.setAttr(labelShape+'.displayArrow',0,l=True) \ No newline at end of file + mc.setAttr(labelShape+'.displayArrow',0,l=True) diff --git a/rig/autoModuleBuild.py b/rig/autoModuleBuild.py index 689d9f0..6915c00 100644 --- a/rig/autoModuleBuild.py +++ b/rig/autoModuleBuild.py @@ -21,12 +21,12 @@ def checkModuleTemplate(moduleTemplateGrp,moduleType,moduleAttrs): raise Exception('Module template group "'+moduleTemplateGrp+'" does not exist!') if not mc.attributeQuery('moduleTemplate',n=moduleTemplateGrp,ex=True): raise Exception('Module template attribute "'+moduleTemplateGrp+'.moduleTemplate'+'" does not exist!') - + # Check Module Type moduleTemplateType = mc.getAttr(moduleTemplateGrp+'.moduleTemplate') if moduleTemplateType != moduleType: raise Exception('Expecting module type "'+moduleType+'", found "'+moduleTemplateType+'"!') - + # Check Module Attributes for attr in moduleAttrs: if not mc.attributeQuery(attr,n=moduleTemplateGrp,ex=True): @@ -39,13 +39,13 @@ def moduleBuildAll(): ''' # Find All Module Template Groups moduleTemplateList = mc.ls('*.moduleTemplate',o=True) - + # Build Modules resultList = [] for moduleTemplateGrp in moduleTemplateList: result = moduleBuild( moduleTemplateGrp ) resultList.append(result) - + # Return Result return resultList @@ -58,28 +58,28 @@ def moduleBuild( moduleTemplateGrp ): # ========== # - Checks - # ========== - + # Module Type if not mc.attributeQuery('moduleTemplate',n=moduleTemplateGrp,ex=True): raise Exception('Module template attribute "'+moduleTemplateGrp+'.moduleTemplate'+'" does not exist!') moduleType = mc.getAttr(moduleTemplateGrp+'.moduleTemplate') - + # =================================== # - Build Module From Template Data - # =================================== - + # Initialize Result result = None - + # Build Module if moduleType == 'base': result = baseModuleBuild( moduleTemplateGrp ) elif moduleType == 'fkChain': result = fkChainModuleBuild( moduleTemplateGrp ) elif moduleType == 'ikChain': result = ikChainModuleBuild( moduleTemplateGrp ) - + # ================= # - Return Result - # ================= - + return result def baseModuleBuild( moduleTemplateGrp ): @@ -91,7 +91,7 @@ def baseModuleBuild( moduleTemplateGrp ): # ========== # - Checks - # ========== - + # Define Attribute List attrList = [ 'moduleName', 'moduleParent', @@ -103,24 +103,24 @@ def baseModuleBuild( moduleTemplateGrp ): 'followCtrl', 'constraintCtrl', 'labelText' ] - + # Check Module Template checkModuleTemplate(moduleTemplateGrp,moduleType='base',moduleAttrs=attrList) - + # ========================= # - Get Raw Template Data - # ========================= - + data = {} for attr in attrList: data[attr] = mc.getAttr(moduleTemplateGrp+'.'+attr) - + # Encode template override dictionary overrides = ast.literal_eval(data['overrides']) - + # =================================== # - Build Module From Template Data - # =================================== - + base = glTools.nrig.module.base.BaseModule() result = base.build( name = data['asset_name'], type = data['asset_type'], @@ -131,11 +131,11 @@ def baseModuleBuild( moduleTemplateGrp ): labelText = bool(data['labelText']), overrides = overrides, prefix = data['moduleName'] ) - + # ================= # - Return Result - # ================= - + return result def fkChainModuleBuild( moduleTemplateGrp ): @@ -147,7 +147,7 @@ def fkChainModuleBuild( moduleTemplateGrp ): # ========== # - Checks - # ========== - + # Define Attribute List attrList = [ 'moduleName', 'moduleParent', @@ -163,35 +163,35 @@ def fkChainModuleBuild( moduleTemplateGrp ): 'controlOrient', 'controlScale', 'controlLod' ] - + # Check Module Template checkModuleTemplate(moduleTemplateGrp,moduleType='fkChain',moduleAttrs=attrList) - + # ========================= # - Get Raw Template Data - # ========================= - + data = {} for attr in attrList: data[attr] = mc.getAttr(moduleTemplateGrp+'.'+attr) - + # Encode template override dictionary overrides = ast.literal_eval(data['overrides']) - + # Control Offset controlPosition = data['controlPositionOffset'][0] controlRotate = data['controlRotateOffset'][0] - + # Get control shape ctrlShapeList = glTools.tools.controlBuilder.ControlBuilder().controlType controlShape = ctrlShapeList[data['controlShape']] - + # Get control LOD controlLod = ['primary','secondary','tertiary'][data['controlLod']] - + # =================================== # - Build Module From Template Data - # =================================== - + fkChain = glTools.nrig.module.fkChain.FkChainModule() result = fkChain.build( startJoint = data['startJoint'], endJoint = data['endJoint'], @@ -207,11 +207,11 @@ def fkChainModuleBuild( moduleTemplateGrp ): allScale = data['allScale'], overrides = overrides, prefix = data['moduleName'] ) - + # ================= # - Return Result - # ================= - + return result def ikChainModuleBuild( moduleTemplateGrp ): @@ -223,7 +223,7 @@ def ikChainModuleBuild( moduleTemplateGrp ): # ========== # - Checks - # ========== - + # Define Attribute List attrList = [ 'moduleName', 'moduleParent', @@ -238,30 +238,30 @@ def ikChainModuleBuild( moduleTemplateGrp ): 'enableFKToggle', 'ikFkBlendAttribute', 'controlLod' ] - + # Check Module Template checkModuleTemplate(moduleTemplateGrp,moduleType='ikChain',moduleAttrs=attrList) - + # ========================= # - Get Raw Template Data - # ========================= - + data = {} for attr in attrList: data[attr] = mc.getAttr(moduleTemplateGrp+'.'+attr) - + # Encode template override dictionary overrides = ast.literal_eval(data['overrides']) - + # Get control LOD controlLod = ['primary','secondary','tertiary'][data['controlLod']] - + # Get ikSolver ikSolver = ['ikSCsolver','ikRPsolver'][data['ikSolver']] - + # =================================== # - Build Module From Template Data - # =================================== - + ikChain = glTools.nrig.module.ikChain.IkChainModule() result = ikChain.build( startJoint = data['startJoint'], endJoint = data['endJoint'], @@ -276,9 +276,9 @@ def ikChainModuleBuild( moduleTemplateGrp ): allScale = data['allScale'], overrides = overrides, prefix = data['moduleName'] ) - + # ================= # - Return Result - # ================= - + return result diff --git a/rig/autoModuleTemplate.py b/rig/autoModuleTemplate.py index 47995cc..87470e6 100644 --- a/rig/autoModuleTemplate.py +++ b/rig/autoModuleTemplate.py @@ -17,8 +17,8 @@ def moduleTemplateDialog( buildMethod ): defaultButton='Create', cancelButton='Cancel', dismissString='Cancel' ) - - + + if result == 'Create': moduleName = mc.promptDialog(q=True,text=True) if moduleName: buildMethod(moduleName) @@ -38,54 +38,54 @@ def moduleTemplate( moduleName, # ========== # - Checks - # ========== - + moduleTemplateName = moduleName+'_moduleTemplate' if mc.objExists(moduleTemplateName): raise Exception('Module template group "'+moduleTemplateName+'" already exists!!') - + # ================================ # - Create Module Template Group - # ================================ - + moduleTemplateGrp = mc.group(em=True,n=moduleTemplateName) - + # ================================== # - Add Module Template Attributes - # ================================== - + # Module Type mc.addAttr(moduleTemplateGrp,ln='moduleTemplate',dt='string') mc.setAttr(moduleTemplateGrp+'.moduleTemplate',moduleType,type='string') mc.setAttr(moduleTemplateGrp+'.moduleTemplate',l=True) - + # Module Name mc.addAttr(moduleTemplateGrp,ln='moduleName',dt='string') mc.setAttr(moduleTemplateGrp+'.moduleName',moduleName,type='string') - + # Module Parent mc.addAttr(moduleTemplateGrp,ln='moduleParent',dt='string') mc.setAttr(moduleTemplateGrp+'.moduleParent','module',type='string') - + # Module Scale (allScale) mc.addAttr(moduleTemplateGrp,ln='allScale',dt='string') mc.setAttr(moduleTemplateGrp+'.allScale','all.uniformScale',type='string') - + # Template Overrides mc.addAttr(moduleTemplateGrp,ln='overrides',dt='string') mc.setAttr(moduleTemplateGrp+'.overrides','{}',type='string') - + # ======================= # - Parent Module Nodes - # ======================= - + if moduleNodes: moduleNodes = mc.ls(moduleNodes,dag=True) mc.parent(moduleNodes,moduleTemplateGrp) - + # ================= # - Return Result - # ================= - + return moduleTemplateGrp def moduleTemplateOverrideNotes(moduleTemplateGrp,templateData): @@ -99,11 +99,11 @@ def moduleTemplateOverrideNotes(moduleTemplateGrp,templateData): # ============================ # - Template Overrides Notes - # ============================ - + # Add Notes Attribute if not mc.objExists(moduleTemplateGrp+'.notes'): mc.addAttr(moduleTemplateGrp,ln='notes',sn='nts',dt='string',hidden=True) - + # Template Overrides - Notes templateNotes = '' templateNotes += '# ==============================\n' @@ -111,19 +111,19 @@ def moduleTemplateOverrideNotes(moduleTemplateGrp,templateData): templateNotes += '# ==============================\n' templateNotes += '\n' templateNotes += 'overrides = {\n' - + # Add Key/Value Notes keyList = templateData.keys() keyList.sort() for key in keyList: templateNotes += '\t'+str(key)+':'+str(templateData[key])+'\n' - + # Close Notes templateNotes += '}\n' - + # Set Notes value mc.setAttr(moduleTemplateGrp+'.notes',templateNotes,type='string') - + # Return Result return templateNotes @@ -139,7 +139,7 @@ def checkModuleTemplate( moduleTemplateGrp ): raise Exception('Module template group "'+moduleTemplateGrp+'" does not exist!') if not mc.attributeQuery('moduleTemplate',n=moduleTemplateGrp,ex=True): raise Exception('Module template attribute "'+moduleTemplateGrp+'.moduleTemplate'+'" does not exist!') - + # Check Module Template Attributes if not mc.attributeQuery('moduleName',n=moduleTemplateGrp,ex=True): raise Exception('Module template attribute "'+moduleTemplateGrp+'.moduleName'+'" does not exist!') @@ -185,63 +185,63 @@ def baseModuleTemplate( moduleName, # ========== # - Checks - # ========== - + # - + # ================================ # - Create Module Template Group - # ================================ - + moduleTemplateGrp = moduleTemplate( moduleName = moduleName, moduleType = 'base', moduleNodes = moduleNodes ) - + # ================================== # - Add Module Template Attributes - # ================================== - + # Asset Name mc.addAttr(moduleTemplateGrp,ln='asset_name',dt='string') mc.setAttr(moduleTemplateGrp+'.asset_name',asset_name,type='string') - + # Asset Type mc.addAttr(moduleTemplateGrp,ln='asset_type',dt='string') mc.setAttr(moduleTemplateGrp+'.asset_type',asset_type,type='string') - + # Scale mc.addAttr(moduleTemplateGrp,ln='rigScale',at='float',min=0.0,dv=1.0) mc.setAttr(moduleTemplateGrp+'.rigScale',scale) mc.setAttr(moduleTemplateGrp+'.rigScale',cb=False) - + # Config Control mc.addAttr(moduleTemplateGrp,ln='configCtrl',at='bool') mc.setAttr(moduleTemplateGrp+'.configCtrl',configCtrl) mc.setAttr(moduleTemplateGrp+'.configCtrl',cb=False) - + # Follow Control mc.addAttr(moduleTemplateGrp,ln='followCtrl',at='bool') mc.setAttr(moduleTemplateGrp+'.followCtrl',followCtrl) mc.setAttr(moduleTemplateGrp+'.followCtrl',cb=False) - + # Constraint Control mc.addAttr(moduleTemplateGrp,ln='constraintCtrl',at='bool') mc.setAttr(moduleTemplateGrp+'.constraintCtrl',constraintCtrl) mc.setAttr(moduleTemplateGrp+'.constraintCtrl',cb=False) - + # Label mc.addAttr(moduleTemplateGrp,ln='labelText',at='bool') mc.setAttr(moduleTemplateGrp+'.labelText',labelText) mc.setAttr(moduleTemplateGrp+'.labelText',cb=False) - + # Template Overrides templateData = glTools.rig.module.base.BaseModule().templateData moduleTemplateOverrideNotes(moduleTemplateGrp,templateData) mc.setAttr(moduleTemplateGrp+'.overrides',str(templateData),type='string') - + # ================= # - Return Result - # ================= - + return moduleTemplateGrp def fkChainModuleTemplate( moduleName, @@ -286,45 +286,45 @@ def fkChainModuleTemplate( moduleName, # ========== # - Checks - # ========== - + # Control Shape ctrlShapeList = glTools.tools.controlBuilder.ControlBuilder().controlType if not ctrlShapeList.count(controlShape): raise Exception('Unsupported control shape! ("'+controlShape+'")') - + # ================================ # - Create Module Template Group - # ================================ - + moduleTemplateGrp = moduleTemplate( moduleName = moduleName, moduleType = 'fkChain', moduleNodes = moduleNodes ) - + # ================================== # - Add Module Template Attributes - # ================================== - + # Attach Parent mc.addAttr(moduleTemplateGrp,ln='attachParent',dt='string') mc.setAttr(moduleTemplateGrp+'.attachParent',attachParent,type='string') - + # Start Joint mc.addAttr(moduleTemplateGrp,ln='startJoint',dt='string') mc.setAttr(moduleTemplateGrp+'.startJoint',startJoint,type='string') - + # End Joint mc.addAttr(moduleTemplateGrp,ln='endJoint',dt='string') mc.setAttr(moduleTemplateGrp+'.endJoint',startJoint,type='string') - + # Control Shape mc.addAttr(moduleTemplateGrp,ln='controlShape',at='enum',en=':'.join(ctrlShapeList)) mc.setAttr(moduleTemplateGrp+'.controlShape',ctrlShapeList.index(controlShape)) - + # End Control mc.addAttr(moduleTemplateGrp,ln='endControl',at='bool') mc.setAttr(moduleTemplateGrp+'.endControl',endCtrl) mc.setAttr(moduleTemplateGrp+'.endControl',cb=False) - + # Control Position Offset mc.addAttr(moduleTemplateGrp,ln='controlPositionOffset',at='double3') mc.addAttr(moduleTemplateGrp,ln='controlPositionOffsetX',at='double',parent='controlPositionOffset') @@ -332,7 +332,7 @@ def fkChainModuleTemplate( moduleName, mc.addAttr(moduleTemplateGrp,ln='controlPositionOffsetZ',at='double',parent='controlPositionOffset') mc.setAttr(moduleTemplateGrp+'.controlPositionOffset',*ctrlPosition) mc.setAttr(moduleTemplateGrp+'.controlPositionOffset',cb=False) - + # Control Rotate Offset mc.addAttr(moduleTemplateGrp,ln='controlRotateOffset',at='double3') mc.addAttr(moduleTemplateGrp,ln='controlRotateOffsetX',at='double',parent='controlRotateOffset') @@ -340,31 +340,31 @@ def fkChainModuleTemplate( moduleName, mc.addAttr(moduleTemplateGrp,ln='controlRotateOffsetZ',at='double',parent='controlRotateOffset') mc.setAttr(moduleTemplateGrp+'.controlRotateOffset',*ctrlRotate) mc.setAttr(moduleTemplateGrp+'.controlRotateOffset',cb=False) - + # Control Orient mc.addAttr(moduleTemplateGrp,ln='controlOrient',at='bool') mc.setAttr(moduleTemplateGrp+'.controlOrient',ctrlOrient) mc.setAttr(moduleTemplateGrp+'.controlOrient',cb=False) - + # Control Scale mc.addAttr(moduleTemplateGrp,ln='controlScale',at='float',min=0.0,dv=1.0) mc.setAttr(moduleTemplateGrp+'.controlScale',ctrlScale) mc.setAttr(moduleTemplateGrp+'.controlScale',cb=False) - + # Control LOD ctrlLodList = ['primary','secondary','tertiary'] mc.addAttr(moduleTemplateGrp,ln='controlLod',at='enum',en=':primary:secondary:tertiary:') mc.setAttr(moduleTemplateGrp+'.controlLod',ctrlLodList.index(ctrlLod)) mc.setAttr(moduleTemplateGrp+'.controlLod',cb=False) - + # Template Override Defaults - Notes templateData = glTools.rig.module.fkChain.FkChainModule().templateData moduleTemplateOverrideNotes(moduleTemplateGrp,templateData) - + # ================= # - Return Result - # ================= - + return moduleTemplateGrp def ikChainModuleTemplate( moduleName, @@ -406,74 +406,74 @@ def ikChainModuleTemplate( moduleName, # ========== # - Checks - # ========== - + # IK Solver ikSolverList = ['ikSCsolver','ikRPsolver'] if not ikSolverList.count(ikSolver): raise Exception('Invalid IkSolver - "'+ikSolver+'"!') - + # ================================ # - Create Module Template Group - # ================================ - + moduleTemplateGrp = moduleTemplate( moduleName = moduleName, moduleType = 'ikChain', moduleNodes = moduleNodes ) - + # ================================== # - Add Module Template Attributes - # ================================== - + # Attach Parent mc.addAttr(moduleTemplateGrp,ln='attachParent',dt='string') mc.setAttr(moduleTemplateGrp+'.attachParent',attachParent,type='string') - + # Start Joint mc.addAttr(moduleTemplateGrp,ln='startJoint',dt='string') mc.setAttr(moduleTemplateGrp+'.startJoint',startJoint,type='string') - + # End Joint mc.addAttr(moduleTemplateGrp,ln='endJoint',dt='string') mc.setAttr(moduleTemplateGrp+'.endJoint',startJoint,type='string') - + # Control Shape mc.addAttr(moduleTemplateGrp,ln='ikSolver',at='enum',en=':'.join(ikSolverList)) mc.setAttr(moduleTemplateGrp+'.ikSolver',ikSolverList.index(ikSolver)) mc.setAttr(moduleTemplateGrp+'.ikSolver',cb=False) - + # Pole Vector mc.addAttr(moduleTemplateGrp,ln='poleVectorTransform',dt='string') mc.setAttr(moduleTemplateGrp+'.poleVectorTransform',poleVectorPos,type='string') - + # Orient IK Control mc.addAttr(moduleTemplateGrp,ln='orientIkControl',at='bool') mc.setAttr(moduleTemplateGrp+'.orientIkControl',orientIkCtrl) mc.setAttr(moduleTemplateGrp+'.orientIkControl',cb=False) - + # FK Toggle mc.addAttr(moduleTemplateGrp,ln='enableFKToggle',at='bool') mc.setAttr(moduleTemplateGrp+'.enableFKToggle',fkToggle) mc.setAttr(moduleTemplateGrp+'.enableFKToggle',cb=False) - + # IK/FK Blend Attribute mc.addAttr(moduleTemplateGrp,ln='ikFkBlendAttribute',dt='string') mc.setAttr(moduleTemplateGrp+'.ikFkBlendAttribute',blendAttr,type='string') - + # Control LOD ctrlLodList = ['primary','secondary','tertiary'] mc.addAttr(moduleTemplateGrp,ln='controlLod',at='enum',en=':primary:secondary:tertiary:') mc.setAttr(moduleTemplateGrp+'.controlLod',ctrlLodList.index(ctrlLod)) mc.setAttr(moduleTemplateGrp+'.controlLod',cb=False) - + # Template Overrides templateData = glTools.rig.module.ikChain.IkChainModule().templateData moduleTemplateOverrideNotes(moduleTemplateGrp,templateData) #overrideStr = "{'ikCtrlScale': 0.2, 'ikCtrlShape': 'box', 'ikCtrlRotate': [0, 0, 0], 'fkCtrlShape': 'circle','fkCtrlScale': 0.3,'fkCtrlRotate': [0, 90, 0], 'blendAttr': 'ikFkBlend'}" mc.setAttr(moduleTemplateGrp+'.overrides',str(templateData),type='string') - + # ================= # - Return Result - # ================= - + return moduleTemplateGrp diff --git a/rig/check.py b/rig/check.py index efccdf5..67beb6d 100644 --- a/rig/check.py +++ b/rig/check.py @@ -28,7 +28,7 @@ def objectsAreAligned(obj1,obj2,axis,tol=0.00001): if not mc.objExists(obj2): print('Object "'+obj2+'" does not exist! Returning False...') return False - + # Get World Axis if isinstance(axis,types.StringTypes): if str(axis).lower() == 'x': axis = (1,0,0) @@ -39,16 +39,16 @@ def objectsAreAligned(obj1,obj2,axis,tol=0.00001): return False # Normalize Axis Vector axis = glTools.utils.mathUtils.normalizeVector(axis) - + # Get Object World Positions pos1 = glTools.utils.base.getPosition(obj1) pos2 = glTools.utils.base.getPosition(obj2) - + # Check Align Axis alignAxis = glTools.utils.mathUtils.offsetVector(pos1,pos2) alignAxis = glTools.utils.mathUtils.normalizeVector(alignAxis) alignDot = abs(glTools.utils.mathUtils.dotProduct(axis,alignAxis)) - + # Return Result if (1.0-alignDot) > abs(tol): return False else: return True @@ -72,7 +72,7 @@ def axisIsAligned(obj,objAxis,axis,tol=0.00001): if not glTools.utils.transform.isTransform(obj): print('Object "'+obj+'" is not a valid transform! Returning False...') return False - + # Get World Axis if isinstance(axis,types.StringTypes): if str(axis).lower() == 'x': axis = (1,0,0) @@ -86,7 +86,7 @@ def axisIsAligned(obj,objAxis,axis,tol=0.00001): return False # Normalize World Axis Vector axis = glTools.utils.mathUtils.normalizeVector(axis) - + # Get Transform Axis if isinstance(objAxis,types.StringTypes): if str(objAxis).lower() == 'x': objAxis = (1,0,0) @@ -98,17 +98,17 @@ def axisIsAligned(obj,objAxis,axis,tol=0.00001): else: print('Invalid axis value! Returning False...') return False - + # Transform Axis to World Space objMatrix = glTools.utils.matrix.getMatrix(obj) objAxis = glTools.utils.matrix.vectorMatrixMultiply(objAxis,objMatrix) - + # Normalize Transform Axis Vector objAxis = glTools.utils.mathUtils.normalizeVector(objAxis) - + # Check Axis Alignment alignDot = glTools.utils.mathUtils.dotProduct(axis,objAxis) - + # Return Result if (1.0-alignDot) > abs(tol): return False else: return True @@ -128,13 +128,13 @@ def inverseScaleConnected(joint,connectedTo=None): if not glTools.utils.joint.isJoint(joint): print('Object "'+joint+'" is not a valid joint! Returning False...') return False - + # Check Inv Scale Connection invScaleConn = mc.listConnections(joint+'.inverseScale',s=True,d=False,p=True) or [] if not invScaleConn: return False invScaleConn = mc.ls(invScaleConn[0])[0] invScaleObj = mc.ls(invScaleConn[0],o=True)[0] - + # Check Connection Source if connectedTo: if not mc.objExists(connectedTo): @@ -146,7 +146,7 @@ def inverseScaleConnected(joint,connectedTo=None): else: # Check As Object if not connectedTo == invScaleObj: return False - + # Return Result return True @@ -162,24 +162,24 @@ def attrsAtDefault(obj,attrList=None,tol=0.000001): if not mc.objExists(obj): print('Object "'+obj+'" does not exist! Returning False...') return False - + # Check Attribute List if not attrList: attrList = [] attrList += mc.listAttr(obj,k=True) or [] attrList += mc.listAttr(obj,cb=True) or [] - + # Get List of User Defined Attributes udAttrList = [mc.attributeName(obj+'.'+at,s=True) for at in mc.listAttr(obj,ud=True) or []] - + # Check Attribute Values for at in attrList: - + # Check Attribute Exists if not mc.attributeQuery(at,n=obj,ex=True): print('Object attribute "'+obj+'.'+at+'" not found!') continue - + # Check Value attr = mc.attributeName(obj+'.'+at,s=True) if attr in ['tx','ty','tz','rx','ry','rz']: @@ -196,11 +196,11 @@ def attrsAtDefault(obj,attrList=None,tol=0.000001): defVal = mc.addAttr(obj+'.'+attr,q=True,dv=True) if abs(defVal - mc.getAttr(obj+'.'+attr)) > tol: return False - + # ================= # - Return Result - # ================= - + return True def childJointOffset(): diff --git a/rig/cleanup.py b/rig/cleanup.py index ce5f8bc..5180e96 100644 --- a/rig/cleanup.py +++ b/rig/cleanup.py @@ -19,37 +19,37 @@ def clean(showProgress=False): print('===========================================') print('=============== RIG CLEANUP ===============') print('===========================================') - + # Delete Unused Nodes deleteUnusedNodes() - + # Channel States channelStateSet() - + # Toggle End/Con Joints toggleJointVis() - + # Reorder Shapes reorderShapes() - + # Clean Deformers #cleanDeformers(weightThreshold=0.001,showProgress) - + # Clean SkinClusters cleanSkinClusters(showProgress) - + # Lock Joint Orients lockJointAttrs() - + # Lock Influence Weights lockInfluenceWeights() - + # Lock and Hide Unused Attributes lockAndHideAttributes() - + # Copy Input Shape User Attributes copyInputShapeAttrs() - + print('============================================') print('=========== RIG CLEANUP COMPLETE ===========') print('============================================') @@ -62,42 +62,42 @@ def lockAndHideAttributes(): meshAttr = ['smoothOffset', 'uvSet'] for attr in meshAttr: for mesh in mc.ls(mc.ls('*.'+attr,o=True,r=True),type='mesh'): - if mc.getAttr(mesh+'.'+attr,settable=True): + if mc.getAttr(mesh+'.'+attr,settable=True): try: mc.setAttr(mesh+'.'+attr,l=True,k=False) except: print "Can not lock :: %s.%s" % (mesh, attr) - + def deleteUnusedNodes(): ''' Delete unused nodes ''' # Start Timer timer = mc.timerX() - + # BindPose print('Deleting bind pose ("dagPose") nodes') dagPoseNodes = mc.ls(type='dagPose') if dagPoseNodes: mc.delete(dagPoseNodes) - + # Unknown print('Deleting unknown nodes') glTools.utils.cleanup.deleteUnknownNodes() - + # Sets #print('Deleting empty sets') #glTools.utils.cleanup.deleteEmptySets() - + # Display Layers print('Deleting display layers') glTools.utils.cleanup.deleteDisplayLayers() - + # Render Layers print('Deleting render layers') glTools.utils.cleanup.deleteRenderLayers() - + # Turtle print('Removing Turtle plugin') glTools.utils.cleanup.removeTurtle() - + # Print Timed Result print('# Clean Rig: Delete Unused Nodes - '+str(mc.timerX(st=timer))) @@ -108,16 +108,16 @@ def channelStateSet(): ''' # Start Timer timer = mc.timerX() - + # Channel State - All ON print('Channel States Enabled') glTools.utils.channelState.ChannelState().set(1) - + # Default Attr State - All ON print('Default Attribute States Enabled') glTools.utils.defaultAttrState.setDisplayOverridesState(displayOverrideState=1) glTools.utils.defaultAttrState.setVisibilityState(visibilityState=1) - + # Print Timed Result print('# Clean Rig: Channel States - '+str(mc.timerX(st=timer))) @@ -127,11 +127,11 @@ def toggleJointVis(): ''' # Start Timer timer = mc.timerX() - + print('# Clean Rig: Lock Unused Joints (toggle display overrides for all "End" and "Con" joints)') glTools.utils.cleanup.toggleEnds(0) glTools.utils.cleanup.toggleCons(0) - + # Print Timed Result print('# Clean Rig: End/Con Joints Locked - '+str(mc.timerX(st=timer))) @@ -140,22 +140,22 @@ def reorderShapes(): ''' # Start Timer timer = mc.timerX() - + print('Reordeing Constraints Nodes (push constraints to end of child list)') constraintList = mc.ls(type='constraint') if constraintList: mc.reorder(constraintList,b=True) - + # Print Timed Result print( '# Clean Rig: Reorder Constraints - '+str(mc.timerX(st=timer)) ) - - + + # Start Timer timer = mc.timerX() - + print('Reordeing Shape Nodes (push shapes to end of child list)') shapeList = mc.ls(type=['mesh','nurbsCurve','nurbsCurve']) if shapeList: mc.reorder(shapeList,b=True) - + # Print Timed Result print( '# Clean Rig: Reorder Shapes - '+str(mc.timerX(st=timer)) ) @@ -165,32 +165,32 @@ def cleanDeformers(eightThreshold=0.001,showProgress=False): Prune small weights and membership ''' print('# Clean Rig: Cleaning Deformers (prune weights and membership)') - + # Start Timer timer = mc.timerX() - + deformerList = glTools.utils.deformer.getDeformerList(nodeType='weightGeometryFilter') - + if showProgress and interactive: mc.progressBar( gMainProgressBar,e=True,bp=True,ii=True,status=('Cleaning Deformers...'),maxValue=len(deformerList) ) - + # For Each Deformer for deformer in deformerList: - + # Clean Deformers try: glTools.utils.deformer.clean(deformer,threshold=weightThreshold) except: print('# Clean Rig: XXXXXXXXX ======== Unable to clean deformer "'+deformer+'"! ======== XXXXXXXXX') - + # Update Progress Bar if showProgress and interactive: if mc.progressBar(gMainProgressBar,q=True,isCancelled=True): mc.progressBar(gMainProgressBar,e=True,endProgress=True) raise UserInterupted('Operation cancelled by user!') mc.progressBar(gMainProgressBar,e=True,step=1) - - if showProgress and interactive: + + if showProgress and interactive: mc.progressBar(gMainProgressBar,e=True,endProgress=True) - + # Print Timed Result print('# Clean Rig: Clean Deformers - '+str(mc.timerX(st=timer))) @@ -199,27 +199,27 @@ def cleanSkinClusters(showProgress=False): ''' # Start Timer timer = mc.timerX() - + # Clean SkinClusters skinClusterList = mc.ls(type='skinCluster') - + if showProgress and interactive: mc.progressBar( gMainProgressBar,e=True,bp=True,ii=True,status=('Cleaning SkinClusters...'),maxValue=len(skinClusterList) ) - + for skinCluster in skinClusterList: try: glTools.utils.skinCluster.clean(skinCluster,tolerance=0.001) except: print('# Clean Rig: XXXXXXXXX ======== Unable to clean skinCluster "'+skinCluster+'"! ======== XXXXXXXXX') - + # Update Progress Bar if showProgress and interactive: if mc.progressBar(gMainProgressBar,q=True,isCancelled=True): mc.progressBar(gMainProgressBar,e=True,endProgress=True) raise UserInterupted('Operation cancelled by user!') mc.progressBar(gMainProgressBar,e=True,step=1) - - if showProgress and interactive: + + if showProgress and interactive: mc.progressBar(gMainProgressBar,e=True,endProgress=True) - + # Print Timed Result print('# Clean Rig: Clean SkinClusters - '+str(mc.timerX(st=timer))) @@ -231,10 +231,10 @@ def lockJointAttrs(): ''' # Start Timer timer = mc.timerX() - + print('Locked Unused Joint Attributes (jointOrient, preferredAngle)') glTools.rig.utils.lockJointAttrs([]) - + # Print Timed Result print('# Clean Rig: Clean Deformers - '+str(mc.timerX(st=timer))) @@ -244,12 +244,12 @@ def lockInfluenceWeights(): ''' # Start Timer timer = mc.timerX() - + print('Lock SkinCluster Influence Weights') influenceList = mc.ls('*.liw',o=True,r=True) for influence in influenceList: glTools.utils.skinCluster.lockInfluenceWeights(influence,lock=True,lockAttr=True) - + # Print Timed Result print('# Clean Rig: Lock SkinCluster Influences - '+str(mc.timerX(st=timer))) @@ -258,9 +258,9 @@ def copyInputShapeAttrs(): ''' # Start Timer timer = mc.timerX() - + print('# Clean Rig: Copy Input Shape User Attributes') glTools.utils.cleanup.copyInputShapeAttrs(0) - + # Print Timed Result print('# Clean Rig: Copy Input Shape User Attributes - '+str(mc.timerX(st=timer))) diff --git a/rig/constraintTargetControl.py b/rig/constraintTargetControl.py index 7d3765c..668b806 100644 --- a/rig/constraintTargetControl.py +++ b/rig/constraintTargetControl.py @@ -28,46 +28,46 @@ def createParentControl(name,ctrlShape='cross',translate=[0,0,0],rotate=[0,0,0], # ========== # - Checks - # ========== - + # Name if mc.objExists(name): raise Exception('Object "'+name+'" already exists!') - + # Control Shape ctrlBuilder = glTools.tools.controlBuilder.ControlBuilder() if not ctrlBuilder.controlType.count(ctrlShape): raise Exception('Invalid control shape ("'+ctrlShape+'")!') - + # ========================= # - Create Parent Control - # ========================= - + # Create Transform Node pCtrl = mc.createNode('transform',n=name) - + # Attach Shape ctrlBuilder.controlShape(pCtrl,ctrlShape,translate=translate,rotate=rotate,scale=scale) - + # Tag Control glTools.rig.utils.tagCtrl(pCtrl,'primary') - + # ================== # - Add Attributes - # ================== - + # Constraint Transform (message) mc.addAttr(pCtrl,ln='constraintTransform',at='message',m=True) mc.addAttr(pCtrl,ln='constraintTarget',at='message',m=True) mc.addAttr(pCtrl,ln='constraintLabel',at='message',m=True) - + # Display Labels mc.addAttr(pCtrl,ln='displayLabels',at='enum',en=':Off:On:',dv=0) mc.setAttr(pCtrl+'.displayLabels',k=False,cb=True) - + # ================= # - Return Result - # ================= - + return pCtrl def createTargetLocator(targetTransform='',targetLabel=''): @@ -76,76 +76,76 @@ def createTargetLocator(targetTransform='',targetLabel=''): Constraint target locators are added to rig templates for automated creation of rig attach constraints. @param targetTransform: The target transform for the rig attach constrain @type targetTransform: str - @param targetLabel: The target label which will be used as a naming and attribute prefix on the constraint control. + @param targetLabel: The target label which will be used as a naming and attribute prefix on the constraint control. @type targetLabel: str ''' # ==================== # - Check Input Args - # ==================== - + # Target Transform if not targetTransform: - + # Check interactive maya python session if OpenMaya.MGlobal.mayaState() != 0: raise Exception('No valid targetTransform value provided!') - + result = mc.promptDialog( title='Constraint Target Transform', message='Enter Target Transform:', button=['Create', 'Cancel'], defaultButton='Create', cancelButton='Cancel', dismissString='Cancel' ) - + if result == 'Create': targetTransform = mc.promptDialog(q=True,text=True) if not targetTransform: raise Exception('Invalid targetTransform value!') if not mc.objExists(targetTransform): raise Exception('Target transform "'+targetTransform+'" does not exist!') - + # Target Label if not targetLabel: - + # Check interactive maya python session if OpenMaya.MGlobal.mayaState() != 0: raise Exception('No valid targetLabel value provided!') - + result = mc.promptDialog( title='Constraint Target Label', message='Enter Target Label:', button=['Create', 'Cancel'], defaultButton='Create', cancelButton='Cancel', dismissString='Cancel' ) - + if result == 'Create': targetLabel = mc.promptDialog(q=True,text=True) if not targetLabel: raise Exception('Invalid targetLabel value!') - + # ========================= # - Create Target Locator - # ========================= - + # Create Locator targetLocator = mc.spaceLocator(n=targetLabel+'_constraintLoc')[0] - + # Add Locator Attribute mc.addAttr(targetLocator,ln='targetTransform',dt='string') mc.setAttr(targetLocator+'.targetTransform',targetTransform,type='string') mc.addAttr(targetLocator,ln='targetLabel',dt='string') mc.setAttr(targetLocator+'.targetLabel',targetLabel,type='string') - + # Match Transform glTools.utils.transform.match(targetLocator,targetTransform) - + # Set Colour glTools.utils.colorize.setColour(targetLocator) - + # ================= # - Return Result - # ================= - + return targetLocator def createTargetLocatorFromSel(sel=[]): @@ -158,25 +158,25 @@ def createTargetLocatorFromSel(sel=[]): if not sel: # Get User Selection sel = mc.ls(sl=1) - + # For each item in selection targetLocatorList = [] for obj in sel: - + # Check Transform if not glTools.utils.transform.isTransform(obj): raise Exception('Object "'+obj+'" is not a valid transform!') - + # Get Label Prefix label = glTools.utils.stringUtils.stripSuffix(obj) - + # Create Constraint Target Locator targetLocator = createTargetLocator(targetTransform=obj,targetLabel=label) targetLocatorList.append(targetLocator) - + # Return Result return targetLocatorList - + def addConstraintTransform(parentCtrl,prefix): ''' Create constraint target transform and add to an existing constraint target control parent control. @@ -188,47 +188,47 @@ def addConstraintTransform(parentCtrl,prefix): # ========== # - Checks - # ========== - + # Check Parent Control if not mc.objExists(parentCtrl+'.constraintTransform'): raise Exception('Object "'+parentCtrl+'" is not a valid constraint target control parent transform!') - + # ====================================== # - Create Constraint Target Transform - # ====================================== - + # Create Ctrl Transform name = prefix+'_constraintTarget_ctrl' targetTransform = mc.createNode('transform',n=name,p=parentCtrl) - + # Tag Control glTools.rig.utils.tagCtrl(targetTransform,'primary') - + # Add Constraint Interp Type Attr if not mc.objExists(targetTransform+'.interpType'): mc.addAttr(targetTransform,ln='interpType',at='enum',en=':No Flip:Average:Shortest:Longest:Cache:',dv=1) # Set Interp Type Default mc.setAttr(targetTransform+'.interpType',2) # Shortest - + # Add control shape ctrlBuilder = glTools.tools.controlBuilder.ControlBuilder() ctrlBuilder.controlShape(targetTransform,'locator') - + # Connect to Parent Control connIndex = mc.getAttr(parentCtrl+'.constraintTransform',s=True) mc.connectAttr(targetTransform+'.message',parentCtrl+'.constraintTransform['+str(connIndex)+']',f=True) - + # Add Visibility Toggle to Parent Control mc.addAttr(parentCtrl,ln=prefix+'_Vis',at='enum',en=':Off:On:',dv=0) mc.setAttr(parentCtrl+'.'+prefix+'_Vis',k=False,cb=True) mc.connectAttr(parentCtrl+'.'+prefix+'_Vis',targetTransform+'.v',f=True) - + # ================= # - Return Result - # ================= - + return targetTransform - + def getConstraintTransforms(parentCtrl): ''' Get a list of connected constraint target transforms from a specified constraint target control parent transform @@ -238,22 +238,22 @@ def getConstraintTransforms(parentCtrl): # ========== # - Checks - # ========== - + # Check Parent Control if not mc.objExists(parentCtrl+'.constraintTransform'): raise Exception('Object "'+parentCtrl+'" is not a valid constraint target control parent transform!') - + # ======================================= # - Get Connected Constraint Transforms - # ======================================= - + targetTransformList = mc.listConnections(parentCtrl+'.constraintTransform',s=True,d=False) if not targetTransformList: targetTransformList = [] - + # ================= # - Return Result - # ================= - + return targetTransformList def getConstraintTargets(parentCtrl): @@ -265,22 +265,22 @@ def getConstraintTargets(parentCtrl): # ========== # - Checks - # ========== - + # Check Parent Control if not mc.objExists(parentCtrl+'.constraintTarget'): raise Exception('Object "'+parentCtrl+'" is not a valid constraint target control parent transform!') - + # ======================================= # - Get Connected Constraint Transforms - # ======================================= - + constraintTargetList = mc.listConnections(parentCtrl+'.constraintTarget',s=True,d=False) if not constraintTargetList: constraintTargetList = [] - + # ================= # - Return Result - # ================= - + return constraintTargetList def addTarget(parentCtrl,targetTransform,matchTransform='',label=''): @@ -298,81 +298,81 @@ def addTarget(parentCtrl,targetTransform,matchTransform='',label=''): # ========== # - Checks - # ========== - + # Check Parent Control if not mc.objExists(parentCtrl+'.constraintTarget'): raise Exception('Object "'+parentCtrl+'" is not a valid constraint target control parent transform!') - + # Check Constraint Target List constraintTargetList = getConstraintTargets(parentCtrl) if constraintTargetList.count(targetTransform): raise Exception('Constraint target control "'+parentCtrl+'" is already connected to target "'+targetTransform+'"!') - + if matchTransform and not mc.objExists(matchTransform): raise Exception('Constraint target match transform "'+matchTransform+'" does not exist!') - + # Check Target Label if mc.objExists(targetTransform+'.targetLabel'): targetLabelCon = mc.listConnections(targetTransform+'.targetLabel',s=True,d=False) if targetLabelCon: raise Exception('Target transform "'+targetTransform+'" is already a constraint target!') - + # ========================= # - Add Constraint Target - # ========================= - + # Create Label Annotation targetShape = mc.createNode('annotationShape',n=targetTransform+'_targetShape') target = mc.listRelatives(targetShape,p=True,pa=True)[0] target = mc.rename(target,targetTransform+'_target') mc.parent(target,targetTransform) glTools.utils.colorize.setColour(targetShape) - + # Set Annotation Attributes mc.setAttr(targetShape+'.text',label,type='string') mc.setAttr(targetShape+'.displayArrow',0,l=True) - + # Add Label String Attribute if not mc.objExists(target+'.label'): mc.addAttr(target,ln='label',dt='string') mc.setAttr(target+'.label',label,type='string',l=True) - + # Connect Label to Target Transform if not mc.objExists(targetTransform+'.targetLabel'): mc.addAttr(targetTransform,ln='targetLabel',at='message') mc.connectAttr(target+'.message',targetTransform+'.targetLabel',f=True) - + # Match Transform if matchTransform: glTools.utils.transform.match(target,matchTransform) else: glTools.utils.transform.match(target,targetTransform) - + # Set Channel State channelState = glTools.utils.channelState.ChannelState() channelState.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=[target]) - + # ============================= # - Connect to Parent Control - # ============================= - + # Connect Label Vis mc.connectAttr(parentCtrl+'.displayLabels',targetShape+'.v',f=True) - + # Connect Target Message connIndex = mc.getAttr(parentCtrl+'.constraintTarget',s=True) mc.connectAttr(targetTransform+'.message',parentCtrl+'.constraintTarget['+str(connIndex)+']',f=True) - + # Connect Label Message connIndex = mc.getAttr(parentCtrl+'.constraintLabel',s=True) mc.connectAttr(target+'.message',parentCtrl+'.constraintLabel['+str(connIndex)+']',f=True) - + # ================= # - Return Result - # ================= - + return target - + def connectTargets(parentCtrl): ''' Add all constraint targets to constraint transforms connected to the specified constraint target control parent transform @@ -382,29 +382,29 @@ def connectTargets(parentCtrl): # ========== # - Checks - # ========== - + # Check Parent Control if not mc.objExists(parentCtrl+'.constraintTarget'): raise Exception('Object "'+parentCtrl+'" is not a valid constraint target control parent transform!') - + # ============================================= # - Get Constraint Transform and Target Lists - # ============================================= - + constraintTransformList = getConstraintTransforms(parentCtrl) constraintTargetList = getConstraintTargets(parentCtrl) - + if not constraintTransformList: raise Exception('No valid constraint transforms connected to parent control "'+parentCtrl+'"!') if not constraintTargetList: raise Exception('No valid constraint targets connected to parent control "'+parentCtrl+'"!') - + # ====================== # - Create Constraints - # ====================== - + for constraintTransform in constraintTransformList: - + # Check existing constraint node pTargetList = [] sTargetList = [] @@ -412,7 +412,7 @@ def connectTargets(parentCtrl): sConstraintNode = '' existingParentConstraint = mc.listConnections(constraintTransform+'.t',s=True,d=False,type='parentConstraint') existingScaleConstraint = mc.listConnections(constraintTransform+'.s',s=True,d=False,type='scaleConstraint') - + # Get Existing Constraint Target Lists if existingParentConstraint: pConstraintNode = existingParentConstraint[0] @@ -420,51 +420,51 @@ def connectTargets(parentCtrl): if existingScaleConstraint: sConstraintNode = existingScaleConstraint[0] sTargetList = glTools.utils.constraint.targetList(sConstraintNode) - + # For Each Constraint Target for constraintTarget in constraintTargetList: - + # Check Target Label Attribute if not mc.objExists(constraintTarget+'.targetLabel'): raise Exception('Constraint target "'+constraintTarget+'" has no "targetLabel" attribute! Unable to determine associated target label transform.') - + # Check Target Label Connection targetCon = mc.listConnections(constraintTarget+'.targetLabel',s=True,d=False) if not targetCon: raise Exception('Constraint target "'+constraintTarget+'" has no "targetLabel" connection! Unable to determine associated target label transform.') target = targetCon[0] - + # Check existing Constraint Target if pTargetList.count(target): raise Exception('Constraint target "'+target+'" is already a target transform for constraint node "'+pConstraintNode+'"!') if sTargetList.count(target): raise Exception('Constraint target "'+target+'" is already a target transform for constraint node "'+sConstraintNode+'"!') - + # Get Target Label if not mc.objExists(target+'.label'): raise Exception('Constraint target "'+target+'" has no "label" attribute! Unable to determine label string.') label = mc.getAttr(target+'.label') - + # Attach as Constraint Target pConstraintNode = mc.parentConstraint(target,constraintTransform,mo=False)[0] pConstraintTargetAlias = glTools.utils.constraint.targetAlias(pConstraintNode,target) sConstraintNode = mc.scaleConstraint(target,constraintTransform,mo=False)[0] sConstraintTargetAlias = glTools.utils.constraint.targetAlias(sConstraintNode,target) - + # Connect To Constraint Target Weight if not mc.objExists(constraintTransform+'.'+label): mc.addAttr(constraintTransform,ln=label,min=0,max=1,dv=0,k=True) mc.connectAttr(constraintTransform+'.'+label,pConstraintNode+'.'+pConstraintTargetAlias,f=True) mc.connectAttr(constraintTransform+'.'+label,sConstraintNode+'.'+sConstraintTargetAlias,f=True) - + # Set Constraint Rest Values mc.setAttr(pConstraintNode+'.restTranslate',0,0,0) mc.setAttr(pConstraintNode+'.restRotate',0,0,0) - + # Connect Interpolation Type pConstraintInterpCon = mc.listConnections(pConstraintNode+'.interpType',s=True,d=False,p=True) if not pConstraintInterpCon: pConstraintInterpCon = [] if not pConstraintInterpCon.count(constraintTransform+'.interpType'): try: mc.connectAttr(constraintTransform+'.interpType',pConstraintNode+'.interpType',f=True) except: pass - + diff --git a/rig/face_tools.py b/rig/face_tools.py index cdbfe61..639e172 100644 --- a/rig/face_tools.py +++ b/rig/face_tools.py @@ -10,12 +10,12 @@ import glTools.utils.shape import glTools.utils.stringUtils - + def duplicateAsDrivenTransform(transform, name, transformType=0): - + if mc.objExists(name): return name - + pos = mc.xform(transform,q=True,ws=True,rp=True) if transformType == 0: drivenTrans = mc.group(empty=True, name=name) @@ -24,18 +24,18 @@ def duplicateAsDrivenTransform(transform, name, transformType=0): mc.setAttr('%s.visibility' % drivenTrans, 0) else: raise Exception('transformType must be set to 0 or 1') - + mc.connectAttr('%s.translate' % transform, '%s.translate' % drivenTrans) mc.connectAttr('%s.rotate' % transform, '%s.rotate' % drivenTrans) mc.connectAttr('%s.scale' % transform, '%s.scale' % drivenTrans) - + channelState = glTools.utils.channelState.ChannelState() channelState.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=[drivenTrans]) - + return drivenTrans - - - + + + def mirrorPts(ctrlPts): @@ -48,48 +48,48 @@ def mirrorPts(ctrlPts): # ========================== # - For Each Control Point - # ========================== - + mirrorPts = [] for ctrlPt in ctrlPts: - + # ============================ # - Get Control Point Mirror - # ============================ - + mirrorPt = ctrlPt if ctrlPt.startswith('lf_'): mirrorPt = ctrlPt.replace('lf_','rt_') elif ctrlPt.startswith('rt_'): mirrorPt = ctrlPt.replace('rt_','lf_') else: continue if not mc.objExists(mirrorPt): raise Exception('Control point mirror "'+mirrorPt+'" does not exist!') - + # =================== # - Mirror Position - # =================== - + pos = mc.xform(ctrlPt,q=True,ws=True,rp=True) mpos = mc.xform(mirrorPt,q=True,ws=True,rp=True) mc.move(-pos[0]-mpos[0],pos[1]-mpos[1],pos[2]-mpos[2],mirrorPt,r=True) - + # =================== # - Mirror Rotation - # =================== - + rot = mc.getAttr(ctrlPt+'.r')[0] mc.setAttr(mirrorPt+'.r',rot[0],-rot[1],-rot[2]) - + # ================= # - Append Result - # ================= - + mirrorPts.append(mirrorPt) - + # ================= # - Return Result - # ================= - + return mirrorPts - + def ctrlPointCurve( curve, numCtrlPts = 3, guideGeo = None, @@ -112,21 +112,21 @@ def ctrlPointCurve( curve, # ========== # - Checks - # ========== - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # ========================= # - Create Control Points - # ========================= - + paramList = glTools.utils.curve.sampleParam( curve = curve, samples = numCtrlPts, useDistance = True ) - + # Build Anchors ctrlPts = [] for i in range(len(paramList)): - + # Create Anchor ind = glTools.utils.stringUtils.alphaIndex(i) ctrlPt = glTools.tools.createAlongCurve.createAtParam( curve, @@ -134,11 +134,11 @@ def ctrlPointCurve( curve, objType = 'locator', name = prefix+'_ctrlPt'+ind+'_loc' ) ctrlPts.append(ctrlPt) - + # =============== # - Build Curve - # =============== - + degree = 3 if numCtrlPts < 4: degree = 1 ctrlCrv = glTools.utils.curve.createFromLocators( locatorList = ctrlPts, @@ -149,52 +149,52 @@ def ctrlPointCurve( curve, if degree == 1: glTools.utils.shape.createIntermediate(ctrlCrv) mc.rebuildCurve(ctrlCrv,d=3,s=0,rt=0,rpo=1,end=1,fitRebuild=0) - + # Group Curve grp = mc.group(ctrlCrv,ctrlPts,n=prefix+'_grp') - + # ========================= # - Constrain to Geometry - # ========================= - + geoConstraint = None intersectPt = [] if guideGeo: - + # Use meshIntersectArray if meshIntersect: for ctrlPt in ctrlPts: #ctrlPtAttr = mc.listConnections(ctrlPt+'.worldPosition[0]',s=False,d=True,p=True)[0] intersectPt.append( mc.duplicate(ctrlPt, name='%s_intersectPt_loc' % prefix)[0]) outputAttr = glTools.utils.meshIntersectArray.addIntersect(meshIntersect,intersectPt[-1]+'.worldPosition[0]') - + mc.connectAttr(outputAttr[0],'%s.translate' % ctrlPt ,f=True) - + # Use geometryConstraint else: geoConstraint = [mc.geometryConstraint(guideGeo,ctrlPt)[0] for ctrlPt in ctrlPts] - + ''' may want to add an option in the future for using follicles uvList = [] for i, pt in enumerate(ctrlPts): pos = mc.pointPosition(pt, world=True) uv = glTools.utils.mesh.closestUV(guideGeo,point=pos) uvList.append(uv) - + follicleList.append( glTools.utils.follicle.create( targetGeo = guideGeo, parameter = uv, prefix = '%s_%s_follicle' % (prefix, i) ) ) - + mc.parent(pt, follicleList[-1]) mc.parent(follicleList[-1], grp) mc.setAttr('%s.translate' % pt, *[0,0,0]) mc.setAttr('%s.rotate' % pt, *[0,0,0]) ''' - + # ================= # - Return Result - # ================= - + result = {} result['grp'] = grp result['crv'] = ctrlCrv @@ -203,7 +203,7 @@ def ctrlPointCurve( curve, result['intersectPt'] = intersectPt return result - + def midPtConstraint( midPt, @@ -231,21 +231,21 @@ def midPtConstraint( midPt, # ========== # - Checks - # ========== - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(midPt) - + # ============================== # - Build Mid Point Constraint - # ============================== - + ptConst = mc.pointConstraint(pt1,pt2,midPt,n=prefix+'_midPt_pointConstraint')[0] - + # =============================== # - Build Distance Weight Remap - # =============================== - + if distRemap: - + # Distance Remap Output remap = glTools.tools.distanceDriver.distanceRemapOutput( pt1, pt2, @@ -256,20 +256,20 @@ def midPtConstraint( midPt, restValue = 0.5, attrObject = midPt, prefix = prefix ) - + wtAttr = remap[0] wtRev = mc.createNode('reverse',n=prefix+'_midPt_reverse') mc.connectAttr(wtAttr,wtRev+'.inputX',f=True) wtRevAttr = wtRev+'.outputX' - + # Connect Contstraint Weights mc.connectAttr(wtAttr,ptConst+'.w0',f=True) mc.connectAttr(wtRevAttr,ptConst+'.w1',f=True) - + # ================= # - Return Result - # ================= - + return ptConst def buildCurvePoints( curve, @@ -296,14 +296,14 @@ def buildCurvePoints( curve, # ========== # - Checks - # ========== - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) if not suffix: suffix = 'pt' - + # ================== # - Build Controls - # ================== - + pts = glTools.tools.createAlongCurve.create( curve, 'locator', objCount=numPts, @@ -314,27 +314,27 @@ def buildCurvePoints( curve, spacing=1.0, prefix=prefix, suffix=suffix ) - + # Attach Controls for pt in pts: - + attach = glTools.utils.attach.attachToCurve( curve, pt, useClosestPoint=True, uAttr='param', prefix=prefix ) - + # Project To Mesh if meshIntersect: - + # Add Intersection pointOnCurve = attach[0] intersectOut = glTools.utils.meshIntersectArray.addIntersect(meshIntersect,pointOnCurve+'.position') mc.connectAttr(intersectOut[0],pt+'.translate') - + # Delete Point Constraint mc.delete(attach[1]) - + # Return Result return pts @@ -352,16 +352,16 @@ def createCtrlPtProj( curve, ''' # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # Create Control Points paramList = glTools.utils.curve.sampleParam( curve = curve, samples = numCtrlPts, useDistance = True ) - + # Build Anchors ctrlPtList = [] for i in range(len(paramList)): - + # Create Anchor ind = glTools.utils.stringUtils.alphaIndex(i) ctrlPt = glTools.tools.createAlongCurve.createAtParam( curve, @@ -369,10 +369,10 @@ def createCtrlPtProj( curve, objType = 'locator', name = prefix+'_ctrlPt'+ind+'_loc' ) ctrlPtList.append(ctrlPt) - + # Build Curve ctrlPtCurve = glTools.utils.meshIntersectArray.pointProjectCurve(meshIntersect,ctrlPtList,prefix+'_ctrlPt') - + glTools.utils.shape.createIntermediate(ctrlPtCurve) rebuildCrv = mc.rebuildCurve( ctrlPtCurve, degree = 3, @@ -382,11 +382,11 @@ def createCtrlPtProj( curve, rebuildType = 0, end = 1 ) rebuildCrv = mc.rename(rebuildCrv[1],prefix+'_ctrlPtCrv_rebuildCurve') - + # Group grp = mc.group(em=True,n=prefix+'_ctrlPt_grp') mc.parent(ctrlPtCurve,ctrlPtList,grp) - + # Return Result return [grp,ctrlPtCurve,ctrlPtList] @@ -398,32 +398,32 @@ def createAnchors( curve, ''' # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # Build Anchors Param List paramList = glTools.utils.curve.sampleParam( curve = curve, samples = numAnchors, useDistance = useDistance ) - + # Build Anchors anchorList = [] for i in range(len(paramList)): - + # Create Anchor ind = glTools.utils.stringUtils.alphaIndex(i) anchor = glTools.tools.createAlongCurve.createAtParam( curve, param = paramList[i], objType = 'locator', name = prefix+'_anchor'+ind+'_loc' ) - + # Attach Anchor glTools.utils.attach.attachToCurve( curve, anchor, useClosestPoint=True, uAttr='param', prefix=prefix+'_anchor'+ind ) - + anchorList.append(anchor) - + # Return Result return anchorList @@ -437,37 +437,37 @@ def createIntermediates( curve, # ========== # - Checks - # ========== - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # ========================== # - Generate Intermediates - # ========================== - + # Get Anchor Params param1 = mc.getAttr(anchor1+'.param') param2 = mc.getAttr(anchor2+'.param') - + # Get Intermediate Params # - Add 2 to num samples to only pull inside values # - List slice used to trim bookend values intParam = glTools.utils.mathUtils.distributeValue( numIntermediate+2, rangeStart = param1, rangeEnd = param2 )[1:-1] - + # Build Intermediates intermediateList = [] for i in range(len(intParam)): - + # Create Anchor intermediate = glTools.tools.createAlongCurve.createAtParam( curve, param = intParam[i], objType = 'locator', name = prefix+'_intermediate'+ind+'_loc' ) - + # Append Result intermediateList.append(intermediate) - + # Return Result return intermediateList @@ -484,10 +484,10 @@ def buildLinearPoints( curve, # ========== # - Checks - # ========== - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) if not suffix: suffix = 'jnt' - + # Build Controls ctrls = glTools.tools.createAlongCurve.create( curve, 'locator', @@ -499,25 +499,25 @@ def buildLinearPoints( curve, spacing=1.0, prefix=prefix, suffix=suffix ) - + # Attach Controls for ctrl in ctrls: - + mc.select(ctrl) jnt = mc.joint() - + attach = glTools.utils.attach.attachToCurve( curve, ctrl, useClosestPoint=True, uAttr='param', prefix=prefix ) - + # Constrain to Guide if guideSrf: - + # Constrain Position geomConst = mc.geometryConstraint(guideSrf,ctrl)[0] - + # Constrain Orient if orient: normConst = mc.normalConstraint( guideSrf, @@ -525,9 +525,9 @@ def buildLinearPoints( curve, aimVector=(0,0,1), upVector=(-1,0,0), worldUpType='vector' )[0] - + mc.connectAttr(attach[0]+'.tangent',normConst+'.worldUpVector',f=True) - + # Return Result return ctrls diff --git a/rig/face_utils.py b/rig/face_utils.py index 7541700..5fa8ace 100644 --- a/rig/face_utils.py +++ b/rig/face_utils.py @@ -42,18 +42,18 @@ def subControl( parentControl, scale = ctrlScale ) ctrlGrp = mc.group(em=True,n=prefix+'_ctrlGrp') mc.parent(ctrl,ctrlGrp) - + # Position and Parent control ctrlPt = mc.xform(parentControl,q=True,ws=True,rp=True) mc.move(ctrlPt[0],ctrlPt[1],ctrlPt[2],ctrlGrp) mc.parent(ctrlGrp,parentControl) mc.setAttr(ctrlGrp+'.r',0,0,0) - + # Add Ctrl Vis Toggle mc.addAttr(parentControl,ln='subCtrlVis',at='enum',en=':Off:On:',dv=1) mc.setAttr(parentControl+'.subCtrlVis',k=False,cb=True) mc.connectAttr(parentControl+'.subCtrlVis',ctrlGrp+'.v',f=True) - + # Return Result result = {} result['ctrl'] = ctrl @@ -77,47 +77,47 @@ def ctrlOffsetGrp( ctrl, # ========== # - Checks - # ========== - + # Control if not mc.objExists(ctrl): raise Exception('Control "'+ctrl+'" does not exist!') - + # Pivot if not pivot: pivot = ctrl if not mc.objExists(pivot): raise Exception('Pivot "'+pivot+'" does not exist!') - + # Orient To if orientTo: if not mc.objExists(orientTo): raise Exception('Orient target "'+orientTo+'" does not exist!') - + # Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(ctrl) - + # ====================== # - Build Offset Group - # ====================== - + # Create Offset Group offsetGrp = mc.group(em=True,n=prefix+'_offsetGrp') - + # Set Pivot piv = mc.xform(pivot,q=True,ws=True,rp=True) mc.xform(offsetGrp,ws=True,piv=piv) - + # Orient Offset Group if orientTo: mc.delete(mc.orientConstraint(orientTo,offsetGrp)) - + # Parent Control mc.parent(ctrl,offsetGrp) - + # ================= # - Return Result - # ================= - + return offsetGrp def distanceConstrainedControl( ctrlDistPt, @@ -153,30 +153,30 @@ def distanceConstrainedControl( ctrlDistPt, # ========== # - Checks - # ========== - + # UpVector Object if (upType == 'object' or upType == 'objectrotation') and not mc.objExists(upObject): raise Exception('UpVector transform "'+upObject+'" does not exist!') - + # ================== # - Create Control - # ================== - + ctrl = glTools.tools.controlBuilder.ControlBuilder().create(ctrlType,prefix+'_ctrl',scale=ctrlScale) ctrl_mvCancelGrp = mc.group(ctrl,n=prefix+'_moveCancel_grp') ctrlGrp = mc.group(ctrl_mvCancelGrp,n=prefix+'_ctrlGrp') ctrlGrpXform = mc.group(em=True,n=prefix+'_ctrlGrpXform') - + # ======================================= # - Build Reference Transform Hierarchy - # ======================================= - + ctrlLocalTrans = mc.spaceLocator(n=prefix+'_localTrans_loc')[0] ctrlLocalTransGrp = mc.group(ctrlLocalTrans,n=prefix+'_localTrans_grp') ctrlReferenceGrp = mc.group(ctrlLocalTransGrp,n=prefix+'_reference_grp') - + mc.setAttr(ctrlLocalTrans+'.localScale',0.05,0.05,0.05) - + # Curvature compensation addCurveComp= True if addCurveComp: @@ -189,18 +189,18 @@ def distanceConstrainedControl( ctrlDistPt, mc.connectAttr(ctrlLocalTrans+'.curvatureY',curveCompNode+'.input2Y',f=True) mc.connectAttr(curveCompNode+'.outputX',ctrlLocalTransGrp+'.rotateY',f=True) mc.connectAttr(curveCompNode+'.outputY',ctrlLocalTransGrp+'.rotateX',f=True) - + # ======================= # - Position Transforms - # ======================= - + for c in [ctrlGrp,ctrlGrpXform,ctrlReferenceGrp]: mc.move(ctrlPt[0],ctrlPt[1],ctrlPt[2],c) - + # ============================= # - Build Distance Constraint - # ============================= - + # Aim Constraint mc.aimConstraint( ctrlLocalTrans, ctrlGrpXform, @@ -209,20 +209,20 @@ def distanceConstrainedControl( ctrlDistPt, wut = upType, wuo = upObject, n = prefix+'_aimConstraint' ) - + # Match Rotation mc.setAttr(ctrlGrp+'.r',*mc.getAttr(ctrlGrpXform+'.r')[0]) - + # ============================ # - Build Connection Network - # ============================ - + # CtrlXform -> CtrlLocalTrans for at in ['tx','ty']: mc.connectAttr(ctrl+'.'+at,ctrlLocalTrans+'.'+at,f=True) - + # CtrlGrpXform -> CtrlGrp for at in ['rx','ry','rz']: mc.connectAttr(ctrlGrpXform+'.'+at,ctrlGrp+'.'+at,f=True) - + # Translate Negation localTransNeg = mc.createNode('multiplyDivide',n=prefix+'_moveCancel_multiplyDivide') mc.connectAttr(ctrl+'.t',localTransNeg+'.input1',f=True) @@ -230,18 +230,18 @@ def distanceConstrainedControl( ctrlDistPt, mc.connectAttr(localTransNeg+'.outputX',ctrl_mvCancelGrp+'.tx',f=True) mc.connectAttr(localTransNeg+'.outputY',ctrl_mvCancelGrp+'.ty',f=True) mc.connectAttr(localTransNeg+'.outputZ',ctrl_mvCancelGrp+'.tz',f=True) - + # Set Pivot Positions mc.xform(ctrlGrpXform,ws=True,rp=ctrlDistPt) mc.xform(ctrlGrp,ws=True,rp=ctrlDistPt) - + # Match Rotation mc.setAttr(ctrlReferenceGrp+'.r',*mc.getAttr(ctrlGrpXform+'.r')[0]) - + # ================= # - Return Result - # ================= - + result = {} result['ctrl'] = ctrl result['moveCancel'] = ctrl_mvCancelGrp @@ -251,7 +251,7 @@ def distanceConstrainedControl( ctrlDistPt, result['ctrlLocalTransGrp'] = ctrlLocalTransGrp result['ctrlReferenceGrp'] = ctrlReferenceGrp result['localTransNeg'] = localTransNeg - + return result def surfaceConstrainedCtrl( surface, @@ -298,54 +298,54 @@ def surfaceConstrainedCtrl( surface, # ========== # - Checks - # ========== - + # Surface if not mc.objExists(surface): raise Exception('Surface "'+surface+'" does not exist!') - + # Method methodList = ['geometryConstraint','rayIntersect'] if not methodList.count(method): raise Exception('Invalid constraint method "'+method+'"!') - + # Ray Origin if not rayOrigin: rayOrigin = '' if method == 'rayIntersect' and not mc.objExists(rayOrigin): raise Exception('Ray origin transform "'+rayOrigin+'" does not exist!') - + # UpVector Object if (upType == 'object' or upType == 'objectrotation') and not mc.objExists(upObject): raise Exception('UpVector transform "'+upObject+'" does not exist!') - + # ================== # - Create Control - # ================== - + ctrlBuilder = glTools.tools.controlBuilder.ControlBuilder() ctrl = ctrlBuilder.create( ctrlType, prefix+'_ctrl', translate = ctrlPosition, rotate = ctrlRotate, scale = ctrlScale ) - + ctrlGrp = mc.group(em=True,n=prefix+'_ctrlGrp') ctrl_mvCancelGrp = mc.group(em=True,n=prefix+'_moveCancel_grp') mc.parent(ctrl_mvCancelGrp,ctrlGrp) mc.parent(ctrl,ctrl_mvCancelGrp) - + # Control Xform Group ctrlGrpXform = mc.group(em=True,n=prefix+'_ctrlGrpXform') - + # ======================================= # - Build Reference Transform Hierarchy - # ======================================= - + ctrlLocalTrans = mc.spaceLocator(n=prefix+'_localTrans_loc')[0] ctrlLocalTransGrp = mc.group(ctrlLocalTrans,n=prefix+'_localTrans_grp') ctrlReferenceGrp = mc.group(ctrlLocalTransGrp,n=prefix+'_reference_grp') - + mc.setAttr(ctrlLocalTrans+'.localScale',0.05,0.05,0.05) - + # Curvature compensation if addCurveComp: mc.addAttr(ctrlLocalTrans,ln='curvatureX',dv=0.0,k=True) @@ -357,44 +357,44 @@ def surfaceConstrainedCtrl( surface, mc.connectAttr(ctrlLocalTrans+'.curvatureY',curveCompNode+'.input2Y',f=True) mc.connectAttr(curveCompNode+'.outputX',ctrlLocalTransGrp+'.rotateY',f=True) mc.connectAttr(curveCompNode+'.outputY',ctrlLocalTransGrp+'.rotateX',f=True) - + # ======================= # - Position Transforms - # ======================= - + for c in [ctrlGrpXform,ctrlReferenceGrp]: mc.move(ctrlPt[0],ctrlPt[1],ctrlPt[2],c) - + # ============================ # - Build Surface Constraint - # ============================ - + if method == 'geometryConstraint': constrainToSurface_geometryConstraint(surface,ctrlLocalTrans,ctrlGrpXform,prefix) elif method == 'rayIntersect': constrainToSurface_rayIntersect(surface,ctrlLocalTrans,ctrlGrpXform,rayOrigin,allowOffset,prefix) - + # Normal Constraint if upObject: normCon = mc.normalConstraint(surface,ctrlGrpXform,aim=[0,0,1],u=upVector,wut=upType,wuo=upObject,n=prefix+'_normalConstraint')[0] else: normCon = mc.normalConstraint(surface,ctrlGrpXform,aim=[0,0,1],u=upVector,wut=upType,n=prefix+'_normalConstraint')[0] - + # Orient Control Reference mc.setAttr(ctrlReferenceGrp+'.r',*mc.getAttr(ctrlGrpXform+'.r')[0]) - + # ============================ # - Build Connection Network - # ============================ - + attrList = ['tx','ty','tz','rx','ry','rz','sx','sy','sz'] - + # CtrlXform -> CtrlLocalTrans for at in ['tx','ty']: mc.connectAttr(ctrl+'.'+at,ctrlLocalTrans+'.'+at,f=True) - + # CtrlGrpXform -> CtrlGrp for at in attrList: mc.connectAttr(ctrlGrpXform+'.'+at,ctrlGrp+'.'+at,f=True) - + # Translate Negation localTransNeg = mc.createNode('multiplyDivide',n=prefix+'_moveCancel_multiplyDivide') mc.connectAttr(ctrl+'.t',localTransNeg+'.input1',f=True) @@ -404,11 +404,11 @@ def surfaceConstrainedCtrl( surface, mc.connectAttr(localTransNeg+'.outputZ',ctrl_mvCancelGrp+'.tz',f=True) # Allow Offset - Cancel translateZ negation if allowOffset: mc.setAttr(localTransNeg+'.input2Z',0) - + # ================= # - Return Result - # ================= - + result = {} result['ctrl'] = ctrl result['moveCancel'] = ctrl_mvCancelGrp @@ -419,7 +419,7 @@ def surfaceConstrainedCtrl( surface, result['ctrlReferenceGrp'] = ctrlReferenceGrp result['localTransNeg'] = localTransNeg result['normalConstraint'] = normCon - + return result @@ -443,11 +443,11 @@ def constrainToSurface_geometryConstraint(surface,target,xform,prefix): raise Exception('Target transform "'+target+'" does not exist!') if not mc.objExists(xform): raise Exception('Constraint transform "'+xform+'" does not exist!') - + # Create Constraints pntCon = mc.pointConstraint(target,xform,n=prefix+'_pointConstraint') geoCon = mc.geometryConstraint(surface,xform,n=prefix+'_geometryConstraint') - + # Return Result return [geoCon,pntCon] @@ -476,16 +476,16 @@ def constrainToSurface_rayIntersect(surface,target,xform,rayOrigin,allowOffset=F raise Exception('Constraint transform "'+xform+'" does not exist!') if not mc.objExists(rayOrigin): raise Exception('Ray Origin locator "'+rayOrigin+'" does not exist!') - + # Create Nodes rayIntersect = mc.createNode('rayIntersect',n=prefix+'_rayIntersect') rayDirectionNode = mc.createNode('plusMinusAverage',n=prefix+'_plusMinusAverage') intersectWorldPt = mc.createNode('vectorProduct',n=prefix+'_vectorProduct') - + # SetAttr mc.setAttr(rayDirectionNode+'.operation',2) # Subtract mc.setAttr(intersectWorldPt+'.operation',4) # Point/Matrix product - + # ConnectAttr mc.connectAttr(target+'.worldPosition',rayDirectionNode+'.input3D[0]',f=True) mc.connectAttr(rayOrigin+'.worldPosition',rayDirectionNode+'.input3D[1]',f=True) @@ -496,7 +496,7 @@ def constrainToSurface_rayIntersect(surface,target,xform,rayOrigin,allowOffset=F mc.connectAttr(rayIntersect+'.point',intersectWorldPt+'.input1',f=True) mc.connectAttr(xform+'.parentMatrix[0]',intersectWorldPt+'.matrix',f=True) mc.connectAttr(intersectWorldPt+'.output',xform+'.translate',f=True) - + # Surface Offset if allowOffset: rayDistNode = mc.createNode('distanceBetween',n=prefix+'_rayDist_distanceBetween') @@ -509,17 +509,17 @@ def constrainToSurface_rayIntersect(surface,target,xform,rayOrigin,allowOffset=F mc.connectAttr(target+'.worldPosition',offsetNode+'.colorIfTrue',f=True) mc.connectAttr(rayIntersect+'.point',offsetNode+'.colorIfFalse',f=True) mc.connectAttr(offsetNode+'.outColor',intersectWorldPt+'.input1',f=True) - + # Return Result return [rayIntersect] - + def secondaryControlInfluence(localTransGrp,slaveCtrl,targetCtrlList,targetAliasList,prefix=''): ''' ''' # ========== # - Checks - # ========== - + if not mc.objExists(localTransGrp): raise Exception('localTransGrp "'+localTransGrp+'" does not exist!') if not mc.objExists(slaveCtrl): @@ -527,32 +527,32 @@ def secondaryControlInfluence(localTransGrp,slaveCtrl,targetCtrlList,targetAlias for targetCtrl in targetCtrlList: if not mc.objExists(targetCtrl): raise Exception('Target Control "'+targetCtrl+'" does not exist!') - + # targetCtrlList/targetAliasList if len(targetCtrlList) != len(targetAliasList): raise Exception('Target Control and Alias list length mis-match!') - + # ============================= # - Add Target Ctrl Influence - # ============================= - + attrList=['tx','ty','tz'] inputAttrList=['input2X','input2Y','input2Z'] addInflNode = mc.createNode('plusMinusAverage',n=prefix+'_addCtrlInf_plusMinusAverage') for t in range(len(targetCtrlList)): ctrlMultNode = mc.createNode('multiplyDivide',n=prefix+'_'+targetAliasList[t]+'Inf_multiplyDivide') mc.connectAttr(targetCtrlList+'.t',ctrlMultNode+'.input1',f=True) - + # Add Influence Control Attrs for at in range(len(attrList)): if not mc.objExists(slaveCtrl+'.'+targetAliasList[t]+'_'+attrList[at].upper()): mc.addAttr(slaveCtrl,ln=targetAliasList[t]+'_'+attrList[at].upper(),min=-1.0,max=1.0,dv=0.0) mc.connectAttr(slaveCtrl+'.'+targetAliasList[t]+'_'+attrList[at].upper(),ctrlMultNode+'.'+inputAttrList[at],f=True) - + # Connect to Add Ctrl Influence Node addInfIndex = glTools.utils.attribute.nextAvailableMultiIndex(addInflNode+'.input3D') mc.connectAttr(ctrlMultNode+'.output',addInflNode+'.input3D['+str(addInfIndex)+']',f=True) - + # Connect to LocalTransGrp mc.connectAttr(addInflNode+'.output3D',localTransGrp+'.t',f=True) @@ -562,17 +562,17 @@ def midControlConstraint(ctrlXform,target1,target2,prefix): # Create target locators loc1 = mc.spaceLocator(n=prefix+'_target1_loc')[0] loc2 = mc.spaceLocator(n=prefix+'_target2_loc')[0] - + # Position locators mc.delete(mc.parentConstraint(ctrlXform,loc1)) mc.delete(mc.parentConstraint(ctrlXform,loc2)) # Parent locators mc.parent(loc1,target1) mc.parent(loc2,target2) - + # Constrain controls xform ptCon = mc.pointConstraint([loc1,loc2],ctrlXform,n=prefix+'_pointConstraint') - + # Return Result return ptCon @@ -588,12 +588,12 @@ def blendUpVector(constraint,target1,target2,upVector=[0,1,0],blendAttr='',prefi mc.connectAttr(target2+'.worldMatrix[0]',targetVector2+'.matrix',f=True) mc.setAttr(targetVector2+'.operation',3) # Vector/Matrix Product mc.setAttr(targetVector2+'.input1',*upVector) - + # Create Blend Node vectorBlend = mc.createNode('blendColors',n=prefix+'_blendUpVector_blendColors') mc.connectAttr(targetVector1+'.output',vectorBlend+'.color1',f=True) mc.connectAttr(targetVector2+'.output',vectorBlend+'.color2',f=True) - + # Add blend attribute if blendAttr: if not blendAttr.count('.'): @@ -603,11 +603,11 @@ def blendUpVector(constraint,target1,target2,upVector=[0,1,0],blendAttr='',prefi if not mc.objExists(blendNode+'.'+blendAttr): mc.addAttr(blendNode,ln=blendAttr,min=0,max=1,dv=0.5) mc.connectAttr(blendNode+'.'+blendAttr,vectorBlend+'.blender',f=True) - + # Connect UpVector mc.connectAttr(vectorBlend+'.output',constraint+'.worldUpVector',f=True) mc.setAttr(constraint+'.worldUpType',3) # Vector - + # Return Result result = {} result['worldVector1'] = targetVector1 @@ -621,22 +621,22 @@ def ctrlMeshConstraint(ctrl,ctrlRef='',faceAxis='y',faceScale=0.05,prefix=''): # ========== # - Checks - # ========== - + if not mc.objExists(ctrl): raise Exception('Control object "'+ctrl+'" does not exist!!') if ctrlRef and not mc.objExists(ctrlRef): raise Exception('Control reference object "'+ctrlRef+'" does not exist!!') - + # ======================= # - Create Control Face - # ======================= - + ctrlFace = glTools.tools.pointFaceMesh.transformFaceMesh([ctrl],faceAxis,faceScale,False,prefix)[0] - + # ============================ # - Attach Control Reference - # ============================ - + if ctrlRef: faceLoc = ctrlRef faceCon = mc.pointOnPolyConstraint(ctrlFace,ctrlRef,n=prefix+'_pointOnPolyConstraint')[0] @@ -644,14 +644,14 @@ def ctrlMeshConstraint(ctrl,ctrlRef='',faceAxis='y',faceScale=0.05,prefix=''): faceLoc = mc.spaceLocator(n=prefix+'_ctrlFace_loc')[0] mc.setAttr(faceLoc+'.localScale',faceScale,faceScale,faceScale) faceCon = mc.pointOnPolyConstraint(ctrlFace,faceLoc,n=prefix+'_pointOnPolyConstraint')[0] - + mc.setAttr(faceCon+'.'+ctrlFace+'U0',0.5) mc.setAttr(faceCon+'.'+ctrlFace+'V0',0.5) - + # ================= # - Return Result - # ================= - + result = {} result['face'] = ctrlFace result['locator'] = faceLoc @@ -671,26 +671,26 @@ def createVertexLocators(vtxList,locScale=0.1,prefix=''): # ========== # - Checks - # ========== - + # Flatten vertex list vtxList = mc.ls(vtxList,fl=True) - + # =================== # - Create Locators - # =================== - + # Get mesh from vertex selection mesh = mc.ls(vtxList[0],o=True)[0] - + # Initialize locator list locList = [] - + # For each vertex for v in range(len(vtxList)): - + # Determine string index strInd = glTools.utils.stringUtils.stringIndex(v+1) - + # Get Vtx Position pt = mc.pointPosition(vtxList[v]) # Create Locator @@ -698,17 +698,17 @@ def createVertexLocators(vtxList,locScale=0.1,prefix=''): mc.setAttr(loc+'.localScale',locScale,locScale,locScale) # Position Locator mc.move(pt[0],pt[1],pt[2],loc,ws=True) - + # Record Vertex ID glTools.utils.mesh.closestVertexAttr(loc,mesh) - + # Append Return List locList.append(loc) - + # ================= # - Return Result - # ================= - + return locList def createControlLocators(ptList): @@ -746,35 +746,35 @@ def controlFromLocator( locList, # ========== # - Checks - # ========== - + # Check Locators for loc in locList: if not mc.objExists(loc): raise Exception('Locator "'+loc+'" does not exist!') - + # Check Control LOD ctrlLodList = ['primary','secondary', 'tertiary'] if not ctrlLod in ctrlLodList: raise Exception('Invalid control LOD (level of detail)! ("'+ctrlLod+'")') - + # =================== # - Create Controls - # =================== - + ctrlBuilder = glTools.tools.controlBuilder.ControlBuilder() - + ctrlList = [] ctrlGrpList = [] driverList = [] driverGrpList = [] for loc in locList: - + # Clear Selection mc.select(cl=True) - + # Generate Naming Prefix prefix = glTools.utils.stringUtils.stripSuffix(loc) - + # Create Control ctrl = '' ctrlGrp = '' @@ -791,24 +791,24 @@ def controlFromLocator( locList, if not driverType: glTools.rig.utils.tagBindJoint(ctrl) else: raise Exception('Invalid control transform type "'+ctrlType+'"!') - + # Parent to Locator if parentToLoc: mc.parent(ctrlGrp,loc) - + # Create Control Shape ctrlBuilder.controlShape(ctrl,controlType=ctrlShape,scale=ctrlScale) - + # Tag Control glTools.rig.utils.tagCtrl(ctrl,ctrlLod) - + # Create Driver driver = None driverGrp = None if driverType: - + # Clear Selection mc.select(cl=True) - + if driverType == 'transform': driver = mc.createNode(ctrlType,n=prefix+'_driver') driverGrp = mc.group(ctrl,n=prefix+'_driverGrp') @@ -822,42 +822,42 @@ def controlFromLocator( locList, glTools.rig.utils.tagBindJoint(driver) else: raise Exception('Invalid control driver type "'+driverType+'"!') - + # Connect Driver for at in 'trs': mc.connectAttr(ctrl+'.'+at,driver+'.'+at,f=True) mc.connectAttr(driverGrp+'.'+at,ctrlGrp+'.'+at,f=True) - + # Position Driver Group mc.delete(mc.pointConstraint(loc,driverGrp)) if orient: mc.delete(mc.orientConstraint(loc,driverGrp)) - + # Parent to Locator if parentToLoc: mc.parent(driverGrp,loc) - + else: - + # Position Control Group mc.delete(mc.pointConstraint(loc,ctrlGrp)) if orient: mc.delete(mc.orientConstraint(loc,ctrlGrp)) - + # Append to Return Lists ctrlList.append(ctrl) ctrlGrpList.append(ctrlGrp) driverList.append(driver) driverGrpList.append(driverGrp) - + # ================= # - Return Result - # ================= - + result = {} - + result['ctrl'] = ctrlList result['ctrlGrp'] = ctrlGrpList result['driver'] = driverList result['driverGrp'] = driverGrpList - + return result def separateInfluenceMesh(baseMesh,inputMesh,setList,suffix='mesh'): @@ -875,35 +875,35 @@ def separateInfluenceMesh(baseMesh,inputMesh,setList,suffix='mesh'): # ========== # - Checks - # ========== - + # Check Mesh if not mc.objExists(baseMesh): raise Exception('Base Mesh "'+baseMesh+'" does not exist!') if not mc.objExists(inputMesh): raise Exception('Input Mesh "'+inputMesh+'" does not exist!') - + # Sets for faceSet in setList: for face in mc.sets(faceSet,q=True): if not mc.ls(face,o=True)[0] != baseMesh: raise Exception('Invalid item "'+face+'" in set "'+faceSet+'"') - + # =========================== # - Separate Mesh Face Sets - # =========================== - + infMeshList = [] delCompList = [] - + for faceSet in setList: - + # Get Set Prefix prefix = glTools.utils.stringUtils.stripSuffix(faceSet) - + # Duplicate Connected Mesh infMesh = mc.polyDuplicateAndConnect(inputMesh)[0] infMesh = mc.rename(infMesh,prefix+'_'+suffix) - + # Delete Unwanted Faces allFaces = mc.ls(infMesh+'.f[*]',fl=True) setFaces = mc.ls(mc.sets(faceSet,q=True),fl=True) @@ -911,25 +911,25 @@ def separateInfluenceMesh(baseMesh,inputMesh,setList,suffix='mesh'): #meshFaces = list(set(allFaces) & set(setFaces)) # Set Intersection delFaces = list(set(allFaces) - set(setFaces)) mc.delete(delFaces) - + # Rename deleteComponent node delNode = mc.ls(mc.listHistory(infMesh),type='deleteComponent') if not delNode: raise Exception('Unable to determine deleteComponent from mesh "'+infMesh+'"!') delNode = mc.rename(delNode[0],prefix+'_deleteComponent') - + # Append to return list infMeshList.append(infMesh) delCompList.append(delNode) - + # ================= # - Return Result - # ================= - + result = {} - + result['influenceMesh'] = infMeshList result['deleteComponent'] = delCompList - + return result def asymmetricalBaseMesh(baseMesh,symMesh,asymMesh): @@ -945,27 +945,27 @@ def asymmetricalBaseMesh(baseMesh,symMesh,asymMesh): # ========== # - Checks - # ========== - + if not mc.objExists(baseMesh): raise Exception('Base mesh "'+baseMesh+'" does not exist!') if not mc.objExists(symMesh): raise Exception('Symmetrical target mesh "'+symMesh+'" does not exist!') if not mc.objExists(asymMesh): raise Exception('Asymmetrical target mesh "'+asymMesh+'" does not exist!') - + # ============================== # - Generate Asymmetrical Base - # ============================== - + # Duplicate base to create asymmetrical base asymBase = mc.duplicate(baseMesh,n='face_asym_target')[0] - + # Duplicate target to use as wrap deformer symWrap = mc.duplicate(symMesh,n='face_asym_wrapTarget')[0] # Create Asymmetricl BlendShape asymBlend = mc.blendShape(asymMesh,symWrap)[0] asymAlias = mc.listAttr(asymBlend+'.w',m=True)[0] - + # Create Wrap Deformer -------------- WTF! Wrap Deformers Suck BALLLZ! sel = mc.ls(sl=1) mc.select(asymBase,symWrap) @@ -973,22 +973,22 @@ def asymmetricalBaseMesh(baseMesh,symMesh,asymMesh): wrap = mc.ls(mc.listHistory(asymBase),type='wrap')[0] wrapBase = mc.listConnections(wrap+'.basePoints',s=True,d=False) if sel: mc.select(sel) - + # Apply Blend Target mc.setAttr(asymBlend+'.'+asymAlias,1.0) - + # ============ # - Clean Up - # ============ - + mc.delete(asymBase,ch=True) mc.delete(symWrap) mc.delete(wrapBase) - + # ================= # - Return Result - # ================= - + return asymBase def surfaceControlMesh(baseMesh,inputMesh,asymMesh='',asymAttr='',prefix=''): @@ -1008,7 +1008,7 @@ def surfaceControlMesh(baseMesh,inputMesh,asymMesh='',asymAttr='',prefix=''): # ========== # - Checks - # ========== - + if not mc.objExists(baseMesh): raise Exception('Base mesh "'+baseMesh+'" does not exist!') if not mc.objExists(inputMesh): @@ -1017,19 +1017,19 @@ def surfaceControlMesh(baseMesh,inputMesh,asymMesh='',asymAttr='',prefix=''): raise Exception('Asymmetrical target mesh "'+asymMesh+'" does not exist!') if asymAttr and not mc.objExists(asymAttr): raise Exception('Asymmetry control attribute "'+asymAttr+'" does not exist!') - + # =============================== # - Generate Control Drive Mesh - # =============================== - + # Duplicate base mesh to create drive and deform mesh driveMesh = mc.duplicate(baseMesh,n=prefix+'Drive_mesh')[0] deformMesh = mc.duplicate(baseMesh,n=prefix+'Deform_mesh')[0] - + # ====================== # - Connect Input Mesh - # ====================== - + # Drive Mesh driveTargetList = [inputMesh] if mc.objExists(asymMesh): driveTargetList.append(asymMesh) @@ -1037,7 +1037,7 @@ def surfaceControlMesh(baseMesh,inputMesh,asymMesh='',asymAttr='',prefix=''): driveBlendAlias = mc.listAttr(driveBlendShape+'.w',m=True) mc.setAttr(driveBlendShape+'.'+driveBlendAlias[0],1.0) if mc.objExists(asymAttr): mc.connectAttr(asymAttr,driveBlendShape+'.'+driveBlendAlias[1],f=True) - + # Deform Mesh deformTargetList = [inputMesh] #if mc.objExists(asymMesh): deformTargetList.append(asymMesh) @@ -1045,11 +1045,11 @@ def surfaceControlMesh(baseMesh,inputMesh,asymMesh='',asymAttr='',prefix=''): deformBlendAlias = mc.listAttr(deformBlendShape+'.w',m=True) mc.setAttr(deformBlendShape+'.'+deformBlendAlias[0],1.0) #if mc.objExists(asymAttr): mc.connectAttr(asymAttr,deformBlendShape+'.'+deformBlendAlias[1],f=True) - + # ================= # - Return Result - # ================= - + result = {} result['driveMesh'] = driveMesh result['deformMesh'] = deformMesh @@ -1058,19 +1058,19 @@ def surfaceControlMesh(baseMesh,inputMesh,asymMesh='',asymAttr='',prefix=''): def surfaceControlCreate(ctrlLocs,ctrlDriveMesh,guideMesh,ctrlType='joint',ctrlShape='sphere',ctrlScale=0.05,ctrlLod='primary',prefix=''): ''' Generate surface constrainted control - @param ctrlLocs: + @param ctrlLocs: @type ctrlLocs: list - @param ctrlDriveMesh: + @param ctrlDriveMesh: @type ctrlDriveMesh: str - @param guideMesh: + @param guideMesh: @type guideMesh: str - @param ctrlType: + @param ctrlType: @type ctrlType: str - @param ctrlShape: + @param ctrlShape: @type ctrlShape: str - @param ctrlScale: + @param ctrlScale: @type ctrlScale: str - @param ctrlLod: + @param ctrlLod: @type ctrlLod: str @param prefix: Naming prefix for new nodes @type prefix: str @@ -1078,23 +1078,23 @@ def surfaceControlCreate(ctrlLocs,ctrlDriveMesh,guideMesh,ctrlType='joint',ctrlS # ========== # - Checks - # ========== - + # =================================== # - Constrain Locator To Drive Mesh - # =================================== - + # Build Target Vertex List vtxList = [ctrlDriveMesh+'.vtx['+str(mc.getAttr(loc+'.vtx'))+']' for loc in ctrlLocs] meshConstraint = glTools.tools.autoRivet.meshVertexConstraintList(vtxList,ctrlLocs,orient=False,prefix=prefix) - + # Orient Locators to Guide Mesh for loc in ctrlLocs: mc.delete( mc.normalConstraint(guideMesh,loc,aim=[0,0,1],u=[1,0,0],wut='vector',wu=[1,0,0]) ) - + # ================================= # - Create Controls From Locators - # ================================= - + locCtrl = glTools.rig.face_utils.controlFromLocator( ctrlLocs, ctrlType, ctrlShape, @@ -1102,62 +1102,62 @@ def surfaceControlCreate(ctrlLocs,ctrlDriveMesh,guideMesh,ctrlType='joint',ctrlS ctrlLod, orient=True, parentToLoc=True ) - + # ================= # - Return Result - # ================= - + result = {} - + result['locator'] = ctrlLocs result['ctrl'] = locCtrl['ctrl'] result['ctrlGrp'] = locCtrl['ctrlGrp'] result['constraint'] = meshConstraint - + return result - + def controlOverride(ctrl,duplicateParentOnly=True,connect=True,originalIsSlave=True,autoDetectParent=False,parentTo=''): ''' Create an override control for the specified control transform. Options to connect the override control, using the original as either the slave or master. Connections are established as local transform overrides. - @param ctrl: Control to create control override for. + @param ctrl: Control to create control override for. @type ctrl: str - @param duplicateParentOnly: Duplicate parent transform only, all child transforms and shapes will be ignored. + @param duplicateParentOnly: Duplicate parent transform only, all child transforms and shapes will be ignored. @type duplicateParentOnly: bool - @param connect: Connect the control and control override transforms. + @param connect: Connect the control and control override transforms. @type connect: bool - @param originalIsSlave: Set the original as the destination transform for all incoming connections. + @param originalIsSlave: Set the original as the destination transform for all incoming connections. @type originalIsSlave: bool - @param autoDetectParent: Parent the control override based on incoming control override connections of the original control parent. + @param autoDetectParent: Parent the control override based on incoming control override connections of the original control parent. @type autoDetectParent: bool - @param parentTo: The transform to parent the control override to. This will be overridden if a valid parent is detected as a sresult of autoDetectParent=True. + @param parentTo: The transform to parent the control override to. This will be overridden if a valid parent is detected as a sresult of autoDetectParent=True. @type parentTo: str ''' # ========== # - Checks - # ========== - + # Control if not mc.objExists(ctrl): raise Exception('Control object "'+ctrl+'" does not exist!') # Parent if parentTo and not mc.objExists(parentTo): raise Exception('Parent object "'+parentTo+'" does not exist!') - + # ===================== # - Duplicate Control - # ===================== - + ctrlDup = mc.duplicate(ctrl,po=duplicateParentOnly)[0] if not duplicateParentOnly: ctrlDupChildren = mc.listRelatives(ctrlDup,c=True,pa=True) ctrlDupChildren = mc.ls(ctrlDupChildren,type=['transform','joint','ikHandle']) if ctrlDupChildren: mc.delete(ctrlDupChildren) - + # Rename Controls ctrlDrive = mc.rename(ctrl,ctrl+'DRV') ctrl = mc.rename(ctrlDup,ctrl) - + # Connect Controls if originalIsSlave: src = ctrl @@ -1183,7 +1183,7 @@ def controlOverride(ctrl,duplicateParentOnly=True,connect=True,originalIsSlave=T for attr in cbAttrList: if mc.getAttr(dst+'.'+attr,se=True): mc.connectAttr(src+'.'+attr,dst+'.'+attr,f=True) - + # Connect Shape Vis if connect: ctrlShapes = mc.listRelatives(ctrl,s=True,pa=True) @@ -1193,21 +1193,21 @@ def controlOverride(ctrl,duplicateParentOnly=True,connect=True,originalIsSlave=T for i in range(len(ctrlShapes)): if i > len(ctrlDrvShapes): break mc.connectAttr(ctrlDrvShapes[i]+'.v',ctrlShapes[i]+'.v',f=True) - + # Connect Visibility mc.setAttr(ctrl+'.v',l=False) mc.connectAttr(ctrlDrive+'.v',ctrl+'.v',f=True) - + # Connect Msg Attributes mc.addAttr(dst,ln='controlMaster',at='message') mc.addAttr(src,ln='controlSlave',at='message') mc.connectAttr(src+'.message',dst+'.controlMaster') mc.connectAttr(dst+'.message',src+'.controlSlave') - + # ========== # - Parent - # ========== - + # Auto Detect if autoDetectParent: dstParent = mc.listRelatives(dst,p=True,pa=True)[0] @@ -1217,13 +1217,13 @@ def controlOverride(ctrl,duplicateParentOnly=True,connect=True,originalIsSlave=T elif mc.objExists(dstParent+'.controlMaster'): dstTarget = mc.listConnections(dstParent+'.controlMaster',s=True,d=False) if dstTarget: parentTo = dstTarget[0] - + # Parent if parentTo: mc.parent(ctrl,parentTo) - + # ================= # - Return Result - # ================= - + return ctrlDrive diff --git a/rig/ikFkMatch.py b/rig/ikFkMatch.py index 13ea5de..66bd6a8 100644 --- a/rig/ikFkMatch.py +++ b/rig/ikFkMatch.py @@ -20,51 +20,51 @@ def match(ctrl): # ========== # - Checks - # ========== - + # Check Namespace ns = glTools.utils.namespace.getNS(ctrl) ctrl = glTools.utils.namespace.stripNS(ctrl) if ns: ns += ':' NSctrl = ns+ctrl - + # Check Module if not mc.objExists(NSctrl+'.ctrlModule'): print('Unable to determine module from control "'+NSctrl+'"!') return - + # Get Module limbModule = mc.getAttr(NSctrl+'.ctrlModule') limbModuleGrp = ns+limbModule+'_module' if not mc.objExists(limbModuleGrp): raise Exception('Limb module "'+limbModuleGrp+'" does not exist!') - + # Rebuild Limb Module limb = module.Module() limb.rebuildFromData(limbModuleGrp) limbType = limb.moduleData['moduleType'] - + # !!! This step is to strip the unneccessary namespace from the limb type string - # !!! Once the rig module data is split to data/nodes/attrs...this can be removed! + # !!! Once the rig module data is split to data/nodes/attrs...this can be removed! limbType = glTools.utils.namespace.stripNS(limbType) - + if limbType != 'LimbModule': raise Exception('Unsupported IK/FK match module type "'+limbType+'"!') - + # Get Limb End Module endModule = {'lf_arm':'lf_hand','rt_arm':'rt_hand','lf_leg':'lf_foot','rt_leg':'rt_foot'}[limbModule] endModuleGrp = ns+endModule+'_module' if not mc.objExists(endModuleGrp): raise Exception('Limb end module "'+endModuleGrp+'" does not exist!') - + # Rebuild Limb End Module limbEnd = module.Module() limbEnd.rebuildFromData(endModuleGrp) limbEndType = limbEnd.moduleData['moduleType'] - + # !!! This step is to strip the unneccessary namespace from the limb type string - # !!! Once the rig module data is split to data/nodes/attrs...this can be removed! + # !!! Once the rig module data is split to data/nodes/attrs...this can be removed! limbEndType = glTools.utils.namespace.stripNS(limbEndType) - + # FK Joints fkJnts = [jnt for jnt in limb.moduleNode['fkJointList']] for jnt in fkJnts: @@ -75,14 +75,14 @@ def match(ctrl): for jnt in ikJnts: if not mc.objExists(jnt): raise Exception('IK joint "'+jnt+'" does not exist!') - + # Rotate Order rotateOrder_list = glTools.utils.lib.rotateOrder_list() - + # ==================== # - Get Limb Details - # ==================== - + ikCtrl = limb.moduleNode['ikCtrl'] if not mc.objExists(ikCtrl): raise Exception('IK control "'+ikCtrl+'" does not exist!') pvCtrl = limb.moduleNode['pvCtrl'] @@ -92,19 +92,19 @@ def match(ctrl): ikEnd = limb.moduleNode['ikEndJoint'] if not mc.objExists(ikEnd): raise Exception('IK end joint "'+ikEnd+'" does not exist!') ikCtrlGrp = mc.listRelatives(ikCtrl,p=True,pa=True)[0] - + # IK Offset Ctrl ikOffset = '' if limb.moduleNode.has_key('ikOffset'): ikOffset = limb.moduleNode['ikOffset'] if not mc.objExists(ikOffset): raise Exception('IK offset control "'+ikOffset+'" does not exist!') - + # Get IK Blend Attribute ikBlendAttr = limb.moduleAttr['ikBlendAttr'] if not mc.objExists(ikBlendAttr): raise Exception('Ik Blend attribute "'+ikBlendAttr+'" does not exist!') ikBlendState = mc.getAttr(ikBlendAttr) - + # Limb End Details limbEndIk = '' limbEndFk = '' @@ -122,20 +122,20 @@ def match(ctrl): if limbEndFk and not mc.objExists(limbEndFk): raise Exception('Limb end FK control "'+limbEndFk+'" does not exist!') if limbEndIk: limbEndIkParent = mc.listRelatives(limbEndIk,p=True,pa=True)[0] if limbEndFk: limbEndFkParent = mc.listRelatives(limbEndFk,p=True,pa=True)[0] - + # ========= # - Match - # ========= - + if ikBlendState: - + # ================== # - Match IK to FK - # ================== - + if limbEndFk: fkEndMatrix = glTools.utils.matrix.getMatrix(limbEndFk,local=False) - + # Switch limb to FK if mc.getAttr(ikBlendAttr,se=True): mc.setAttr(ikBlendAttr,0) @@ -146,15 +146,15 @@ def match(ctrl): mc.setAttr(ikBlendConn[0],0) else: raise Exception('The attribute "'+ikBlendAttr+'" is locked or connected and cannot be modified!') - + # Calculate IK control positions wristPt = glTools.utils.base.getPosition(fkEnd) poleVec = glTools.rig.utils.poleVectorPosition(fkJnts[0],fkJnts[1],fkJnts[-1],distance=1.5) - + # Set IK control positions mc.move(wristPt[0],wristPt[1],wristPt[2],ikCtrl,ws=True,a=True) mc.move(poleVec[0],poleVec[1],poleVec[2],pvCtrl,ws=True,a=True) - + # Calculate IK control orientation ikMatrix = glTools.utils.matrix.getMatrix(ikEnd,local=False) fkMatrix = glTools.utils.matrix.getMatrix(fkEnd,local=False) @@ -165,36 +165,36 @@ def match(ctrl): ctrlOffsetMatrix = ctrlMatrix * ikMatrix.inverse() offsetMatrix = ctrlOffsetMatrix * ikfkOffsetMatrix * ikMatrix localMatrix = offsetMatrix * ctrlGrpMatrix.inverse() - + # Set IK control orientation offset = glTools.utils.matrix.getRotation(localMatrix,mc.getAttr(ikCtrl+'.ro')) mc.rotate(offset[0],offset[1],offset[2],ikCtrl) - + # ============ # - Limb End - # ============ - + if limbEndFk and limbEndIk: ikEndPMatrix = glTools.utils.matrix.getMatrix(limbEndIkParent,local=False) localMatrix = fkEndMatrix * ikEndPMatrix.inverse() offset = glTools.utils.matrix.getRotation(localMatrix,mc.getAttr(limbEndIk+'.ro')) mc.rotate(offset[0],offset[1],offset[2],limbEndIk) - + # ============= # - IK Offset - # ============= - + if ikOffset: glTools.rig.utils.setToDefault(ikOffset) - + else: - + # ================== # - Match FK to IK - # ================== - + if limbEndIk: ikEndMatrix = glTools.utils.matrix.getMatrix(limbEndIk,local=False) - + # Switch limb to FK if mc.getAttr(ikBlendAttr,se=True): mc.setAttr(ikBlendAttr,1) @@ -205,28 +205,28 @@ def match(ctrl): mc.setAttr(ikBlendConn[0],1) else: raise Exception('The attribute "'+ikBlendAttr+'" is locked or connected and cannot be modified!') - + # For each FK joint for i in range(len(fkJnts)-1): - + # Reset Translation mc.setAttr(fkJnts[i]+'.t',0,0,0) - + # Set FK Chain Rotation rotateValue = mc.getAttr(ikJnts[i]+'.r')[0] mc.setAttr(fkJnts[i]+'.r',rotateValue[0],rotateValue[1],rotateValue[2]) - + # Set FK Chain Scale scaleValue = mc.getAttr(ikJnts[i]+'.s')[0] mc.setAttr(fkJnts[i]+'.s',scaleValue[0],scaleValue[1],scaleValue[2]) - + # Get IK Wrist Matrix ikMatrix = glTools.utils.matrix.getMatrix(ikCtrl,local=False) - + # ============ # - Limb End - # ============ - + if limbEndFk and limbEndIk: fkEndPMatrix = glTools.utils.matrix.getMatrix(limbEndFkParent,local=False) localMatrix = ikEndMatrix * fkEndPMatrix.inverse() @@ -239,54 +239,54 @@ def matchAnim(ctrl,start=None,end=None): # ========== # - Checks - # ========== - + # Check Namespace ns = glTools.utils.namespace.getNS(ctrl) ctrl = glTools.utils.namespace.stripNS(ctrl) if ns: ns += ':' NSctrl = ns+ctrl - + # Check Module if not mc.objExists(NSctrl+'.ctrlModule'): print('Unable to determine module from control "'+NSctrl+'"!') return - + # =================== # - Get Ctrl Module - # =================== - + limbModule = mc.getAttr(NSctrl+'.ctrlModule') limbModuleGrp = ns+limbModule+'_module' if not mc.objExists(limbModuleGrp): raise Exception('Limb module "'+limbModuleGrp+'" does not exist!') - + # Rebuild Limb Module limb = module.Module() limb.rebuildFromData(limbModuleGrp) limbType = limb.moduleData['moduleType'] - + # !!! This step is to strip the unneccessary namespace from the limb type string # !!! Once the rig module data is split to data/nodes/attrs...this can be removed! limbType = glTools.utils.namespace.stripNS(limbType) - + if limbType != 'LimbModule': raise Exception('Unsupported IK/FK match module type "'+limbType+'"!') - + # Get Limb End Module endModule = {'lf_arm':'lf_hand','rt_arm':'rt_hand','lf_leg':'lf_foot','rt_leg':'rt_foot'}[limbModule] endModuleGrp = ns+endModule+'_module' if not mc.objExists(endModuleGrp): raise Exception('Limb end module "'+endModuleGrp+'" does not exist!') - + # Rebuild Limb End Module limbEnd = module.Module() limbEnd.rebuildFromData(endModuleGrp) limbEndType = limbEnd.moduleData['moduleType'] - + # !!! This step is to strip the unneccessary namespace from the limb type string - # !!! Once the rig module data is split to data/nodes/attrs...this can be removed! + # !!! Once the rig module data is split to data/nodes/attrs...this can be removed! limbEndType = glTools.utils.namespace.stripNS(limbEndType) - + # FK Joints fkJnts = [jnt for jnt in limb.moduleNode['fkJointList']] for jnt in fkJnts: @@ -297,14 +297,14 @@ def matchAnim(ctrl,start=None,end=None): for jnt in ikJnts: if not mc.objExists(jnt): raise Exception('IK joint "'+jnt+'" does not exist!') - + # Rotate Order rotateOrder_list = glTools.utils.lib.rotateOrder_list() - + # ==================== # - Get Limb Details - # ==================== - + ikCtrl = limb.moduleNode['ikCtrl'] if not mc.objExists(ikCtrl): raise Exception('IK control "'+ikCtrl+'" does not exist!') pvCtrl = limb.moduleNode['pvCtrl'] @@ -314,19 +314,19 @@ def matchAnim(ctrl,start=None,end=None): ikEnd = limb.moduleNode['ikEndJoint'] if not mc.objExists(ikEnd): raise Exception('IK end joint "'+ikEnd+'" does not exist!') ikCtrlGrp = mc.listRelatives(ikCtrl,p=True,pa=True)[0] - + # IK Offset Ctrl ikOffset = '' if limb.moduleNode.has_key('ikOffset'): ikOffset = limb.moduleNode['ikOffset'] if not mc.objExists(ikOffset): raise Exception('IK offset control "'+ikOffset+'" does not exist!') - + # Get IK Blend Attribute ikBlendAttr = limb.moduleAttr['ikBlendAttr'] if not mc.objExists(ikBlendAttr): raise Exception('Ik Blend attribute "'+ikBlendAttr+'" does not exist!') ikBlendState = mc.getAttr(ikBlendAttr) - + # Limb End Details limbEndIk = '' limbEndFk = '' @@ -344,20 +344,20 @@ def matchAnim(ctrl,start=None,end=None): if limbEndFk and not mc.objExists(limbEndFk): raise Exception('Limb end FK control "'+limbEndFk+'" does not exist!') if limbEndIk: limbEndIkParent = mc.listRelatives(limbEndIk,p=True,pa=True)[0] if limbEndFk: limbEndFkParent = mc.listRelatives(limbEndFk,p=True,pa=True)[0] - + # ========= # - Match - # ========= - + if ikBlendState: - + # ================== # - Match IK to FK - # ================== - + if limbEndFk: fkEndMatrix = glTools.utils.matrix.getMatrix(limbEndFk,local=False) - + # Switch limb to FK if mc.getAttr(ikBlendAttr,se=True): mc.setAttr(ikBlendAttr,0) @@ -368,15 +368,15 @@ def matchAnim(ctrl,start=None,end=None): mc.setAttr(ikBlendConn[0],0) else: raise Exception('The attribute "'+ikBlendAttr+'" is locked or connected and cannot be modified!') - + # Calculate IK control positions wristPt = glTools.utils.base.getPosition(fkEnd) poleVec = glTools.rig.utils.poleVectorPosition(fkJnts[0],fkJnts[1],fkJnts[-1],distance=1.5) - + # Set IK control positions mc.move(wristPt[0],wristPt[1],wristPt[2],ikCtrl,ws=True,a=True) mc.move(poleVec[0],poleVec[1],poleVec[2],pvCtrl,ws=True,a=True) - + # Calculate IK control orientation ikMatrix = glTools.utils.matrix.getMatrix(ikEnd,local=False) fkMatrix = glTools.utils.matrix.getMatrix(fkEnd,local=False) @@ -387,36 +387,36 @@ def matchAnim(ctrl,start=None,end=None): ctrlOffsetMatrix = ctrlMatrix * ikMatrix.inverse() offsetMatrix = ctrlOffsetMatrix * ikfkOffsetMatrix * ikMatrix localMatrix = offsetMatrix * ctrlGrpMatrix.inverse() - + # Set IK control orientation offset = glTools.utils.matrix.getRotation(localMatrix,mc.getAttr(ikCtrl+'.ro')) mc.rotate(offset[0],offset[1],offset[2],ikCtrl) - + # ============ # - Limb End - # ============ - + if limbEndFk and limbEndIk: ikEndPMatrix = glTools.utils.matrix.getMatrix(limbEndIkParent,local=False) localMatrix = fkEndMatrix * ikEndPMatrix.inverse() offset = glTools.utils.matrix.getRotation(localMatrix,mc.getAttr(limbEndIk+'.ro')) mc.rotate(offset[0],offset[1],offset[2],limbEndIk) - + # ============= # - IK Offset - # ============= - + if ikOffset: glTools.rig.utils.setToDefault(ikOffset) - + else: - + # ================== # - Match FK to IK - # ================== - + if limbEndIk: ikEndMatrix = glTools.utils.matrix.getMatrix(limbEndIk,local=False) - + # Switch limb to FK if mc.getAttr(ikBlendAttr,se=True): mc.setAttr(ikBlendAttr,1) @@ -427,7 +427,7 @@ def matchAnim(ctrl,start=None,end=None): mc.setAttr(ikBlendConn[0],1) else: raise Exception('The attribute "'+ikBlendAttr+'" is locked or connected and cannot be modified!') - + # For each FK joint for i in range(len(fkJnts)-1): # Reset Translation @@ -438,14 +438,14 @@ def matchAnim(ctrl,start=None,end=None): # Set FK chain scale scaleValue = mc.getAttr(ikJnts[i]+'.s')[0] mc.setAttr(fkJnts[i]+'.s',scaleValue[0],scaleValue[1],scaleValue[2]) - + # Get IK Wrist Matrix ikMatrix = glTools.utils.matrix.getMatrix(ikCtrl,local=False) - + # ============ # - Limb End - # ============ - + if limbEndFk and limbEndIk: fkEndPMatrix = glTools.utils.matrix.getMatrix(limbEndFkParent,local=False) localMatrix = ikEndMatrix * fkEndPMatrix.inverse() @@ -471,22 +471,22 @@ def armIkToFk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): # ========== # - Checks - # ========== - + # Get Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # Get IK/FK Joints ikJntList = [rigNS+':'+side+'_arm_ik'+i+'_jnt' for i in ['A','B']] fkJntList = [rigNS+':'+side+'_arm_fk'+i+'_jnt' for i in ['A','B']] - + # ===================== # - Bake IK Limb Anim - # ===================== - + # Set Arm to IK mode mc.setAttr(rigNS+':config.'+side+'ArmIkFkBlend',0) # IK - + # Bake Wrist to Locator wristLoc = None wristJnt = rigNS+':'+side+'_handA_jnt' @@ -497,19 +497,19 @@ def armIkToFk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): sampleBy = sampleBy, simulation=True, attrList = ['rx','ry','rz'] ) - - + + # Duplicate FK Joints and Constrain to IK fkDupList = [] fkOriList = [] for i in range(2): fkDupList.append(mc.duplicate(fkJntList[i],po=True)[0]) fkOriList.append(mc.orientConstraint(ikJntList[i],fkDupList[-1])[0]) - + # ============================= # - Transfer Baked Anim to FK - # ============================= - + mc.refresh(suspend=True) for i in range(2): mc.bakeResults( fkDupList[i], @@ -521,7 +521,7 @@ def armIkToFk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): mc.cutKey(fkDupList[i],at=['rx','ry','rz'],t=(start,end)) mc.pasteKey(fkJntList[i],at=['rx','ry','rz'],t=(start,end),option='replace') mc.refresh(suspend=False) - + # Delete Duplicate Joints and Constraints if fkOriList: try: mc.delete(fkOriList) @@ -529,10 +529,10 @@ def armIkToFk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): if fkDupList: try: mc.delete(fkDupList) except Exception, e: print('Error deleting nodes '+str(fkDupList)+'! Exception Msg: '+str(e)) - + # Set to FK mode mc.setAttr(rigNS+':config.'+side+'ArmIkFkBlend',1) # FK - + # Bake Wrist from Locator if bakeWrist: glTools.anim.utils.bakeAnimFromLocator( loc=wristLoc, @@ -542,16 +542,16 @@ def armIkToFk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): sampleBy=sampleBy, simulation=False, attrList=['rx','ry','rz'] ) - + # Cleanup if mc.objExists(wristLoc): try: mc.delete(wristLoc) except: pass - + # ================= # - Return Result - # ================= - + return fkJntList def armFkToIk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): @@ -573,27 +573,27 @@ def armFkToIk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): # ========== # - Checks - # ========== - + # Get Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # Get FK Joints fkShoulder = rigNS+':'+side+'_arm_fkA_jnt' fkElbow = rigNS+':'+side+'_arm_fkB_jnt' fkWrist = rigNS+':'+side+'_handA_jnt' - + # Get IK Controls ikWrist = rigNS+':'+side+'_arm_ik_ctrl' ikElbow = rigNS+':'+side+'_arm_pv_ctrl' - + # ===================== # - Transfer FK to IK - # ===================== - + # Set Arm to FK mode mc.setAttr(rigNS+':config.'+side+'ArmIkFkBlend',1) # FK - + # Bake Wrist to Locator wristLoc = None if bakeWrist: @@ -603,15 +603,15 @@ def armFkToIk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): sampleBy = sampleBy, simulation = True, attrList = ['rx','ry','rz'] ) - + # Duplicate IK Controls ikWristLoc = mc.duplicate(ikWrist,po=True)[0] ikElbowLoc = mc.duplicate(ikElbow,po=True)[0] - + # Constrain IK to FK joints ikWristCon = mc.pointConstraint(fkWrist,ikWristLoc)[0] pvWristCon = mc.pointConstraint(fkElbow,ikElbowLoc)[0] - + # Bake Constraint Keys mc.refresh(suspend=True) mc.bakeResults( [ikWristLoc,ikElbowLoc], @@ -621,13 +621,13 @@ def armFkToIk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): preserveOutsideKeys=True, sampleBy=sampleBy ) mc.refresh(suspend=False) - + # Transfer Keys to IK Controls mc.copyKey(ikWristLoc,at=['tx','ty','tz'],t=(start,end)) mc.pasteKey(ikWrist,at=['tx','ty','tz'],t=(start,end),option='replace') mc.copyKey(ikElbowLoc,at=['tx','ty','tz'],t=(start,end)) mc.pasteKey(ikElbow,at=['tx','ty','tz'],t=(start,end),option='replace') - + # Delete Duplicate Joints and Constraints for item in [ikWristLoc,ikElbowLoc]: if mc.objExists(item): @@ -635,10 +635,10 @@ def armFkToIk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): except Exception, e: print('Error deleting node "'+str(item)+'"!') print(str(e)) - + # Set to FK mode mc.setAttr(rigNS+':config.'+side+'ArmIkFkBlend',0) # IK - + # Bake Wrist from Locator if bakeWrist: glTools.anim.utils.bakeAnimFromLocator( loc = wristLoc, @@ -648,11 +648,11 @@ def armFkToIk(rigNS,side,bakeWrist=True,start=None,end=None,sampleBy=1): sampleBy = sampleBy, simulation = True, attrList = ['rx','ry','rz'] ) - + # ================= # - Return Result - # ================= - + return [ikWrist,ikElbow] def legIkToFk(rigNS,side,start=None,end=None,sampleBy=1): @@ -672,23 +672,23 @@ def legIkToFk(rigNS,side,start=None,end=None,sampleBy=1): # Get Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # Set Leg to IK mode mc.setAttr(rigNS+':config.'+side+'LegIkFkBlend',0) # IK - + # Build IK/FK Joint List ikJntList = [rigNS+':'+side+'_leg_ik'+i+'_jnt' for i in ['A','B']] ikJntList += [rigNS+':'+side+'_foot_ik'+i+'_jnt' for i in ['A','B']] fkJntList = [rigNS+':'+side+'_leg_fk'+i+'_jnt' for i in ['A','B']] fkJntList += [rigNS+':'+side+'_foot_fk'+i+'_jnt' for i in ['A','B']] - + # Duplicate FK Joints and Constrain to IK fkDupList = [] fkOriList = [] for i in range(len(ikJntList)): fkDupList.append(mc.duplicate(fkJntList[i],po=True)[0]) fkOriList.append(mc.orientConstraint(ikJntList[i],fkDupList[-1])[0]) - + # Transfer Baked Anim to FK Joints mc.refresh(suspend=True) for i in range(len(fkDupList)): @@ -701,7 +701,7 @@ def legIkToFk(rigNS,side,start=None,end=None,sampleBy=1): mc.copyKey(fkDupList[i],at=['rx','ry','rz'],t=(start,end)) mc.pasteKey(fkJntList[i],at=['rx','ry','rz'],t=(start,end),option='replace') mc.refresh(suspend=False) - + # Delete Duplicate Joints and Constraints if fkOriList: try: mc.delete(fkOriList) @@ -709,7 +709,7 @@ def legIkToFk(rigNS,side,start=None,end=None,sampleBy=1): if fkDupList: try: mc.delete(fkDupList) except Exception, e: print('Error deleting nodes '+str(fkDupList)+'! Exception Msg: '+str(e)) - + # Set to FK mode mc.setAttr(rigNS+':config.'+side+'LegIkFkBlend',1) # FK @@ -730,45 +730,45 @@ def legFkToIk(rigNS,side,start=None,end=None,sampleBy=1): # ========== # - Checks - # ========== - + # Get Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # Set Leg to FK mode mc.setAttr(rigNS+':config.'+side+'LegIkFkBlend',1) # FK - + # Get IK Controls ikAnkle = rigNS+':'+side+'_leg_ik_ctrl' ikKnee = rigNS+':'+side+'_leg_pv_ctrl' ikToe = rigNS+':'+side+'_foot_toe_ctrl' - + # Get FK Joints fkLeg = rigNS+':'+side+'_leg_fkA_jnt' fkKnee = rigNS+':'+side+'_leg_fkB_jnt' fkFoot = rigNS+':'+side+'_foot_fkA_jnt' fkToe = rigNS+':'+side+'_foot_fkB_jnt' - + # ===================== # - Transfer FK to IK - # ===================== - + # Duplicate IK Controls ikAnkleLoc = mc.duplicate(ikAnkle,po=True)[0] ikKneeLoc = mc.duplicate(ikKnee,po=True)[0] ikToeLoc = mc.duplicate(ikToe,po=True)[0] - + # Constrain IK to FK joints ikWristCon = mc.pointConstraint(fkFoot,ikAnkleLoc)[0] pvWristCon = mc.pointConstraint(fkKnee,ikKneeLoc)[0] - + # Set to IK mode mc.setAttr(rigNS+':config.'+side+'LegIkFkBlend',0) # IK - + # ================= # - Return Result - # ================= - + return [ikAnkle,ikKnee] def limbsIkToFkOLD(rigNS,start=None,end=None,sampleBy=1): @@ -786,50 +786,50 @@ def limbsIkToFkOLD(rigNS,start=None,end=None,sampleBy=1): # ========== # - Checks - # ========== - + # Get Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # ========================== # - Build IK/FK Joint List - # ========================== - + ikJntList = [] fkJntList = [] - + index = ['A','B'] sides = ['lf','rt'] for side in sides: if not mc.getAttr(rigNS+':config.'+side+'ArmIkFkBlend'): #ikJntList += [rigNS+':'+side+'_arm_ik'+i+'_jnt' for i in index] #fkJntList += [rigNS+':'+side+'_arm_fk'+i+'_jnt' for i in index] - + armIkToFk(rigNS,side,True,start,end,sampleBy) - + if not mc.getAttr(rigNS+':config.'+side+'LegIkFkBlend'): #ikJntList += [rigNS+':'+side+'_leg_ik'+i+'_jnt' for i in index] #fkJntList += [rigNS+':'+side+'_leg_fk'+i+'_jnt' for i in index] #ikJntList += [rigNS+':'+side+'_foot_ik'+i+'_jnt' for i in index] #fkJntList += [rigNS+':'+side+'_foot_fk'+i+'_jnt' for i in index] - + legIkToFk(rigNS,side,start,end,sampleBy) - + # Check IK/FK State if not fkJntList: print('Limbs already in FK mode! Nothing to do...') return fkJntList - + # ==================================== # - Bake Wrist Animation to Locators - # ==================================== - + # Build Wrist Duplicates for Baking wristJnts = [rigNS+':'+side+'_handA_jnt' for side in sides] wristDups = [mc.duplicate(jnt,po=True)[0] for jnt in wristJnts] keys = mc.copyKey(wristJnts,at=['rx','ry','rz'],t=(start,end)) if keys: mc.pasteKey(wristDups,at=['rx','ry','rz'],t=(start,end),option='replace') - + # Bake Wrists to Locators wristLocs = glTools.anim.utils.bakeAnimToLocators( objList = wristJnts, start = start, @@ -837,18 +837,18 @@ def limbsIkToFkOLD(rigNS,start=None,end=None,sampleBy=1): sampleBy = sampleBy, simulation = True, attrList = ['rx','ry','rz'] ) - + # ======================= # - Bake Limb Animation - # ======================= - + # Duplicate FK Joints and Constrain to IK fkDupList = [] fkOriList = [] for i in range(len(ikJntList)): fkDupList.append(mc.duplicate(fkJntList[i],po=True)[0]) fkOriList.append(mc.orientConstraint(ikJntList[i],fkDupList[-1])[0]) - + # Transfer Baked Anim to FK Joints mc.refresh(suspend=True) for i in range(len(fkDupList)): @@ -858,14 +858,14 @@ def limbsIkToFkOLD(rigNS,start=None,end=None,sampleBy=1): simulation=True, preserveOutsideKeys=True, sampleBy=sampleBy ) - + # Transfer Keys for i in range(len(fkDupList)): keys = mc.copyKey(fkDupList[i],at=['rx','ry','rz'],t=(start,end)) if keys: mc.pasteKey(fkJntList[i],at=['rx','ry','rz'],t=(start,end),option='replace') - + mc.refresh(suspend=False) - + # Delete Duplicate Joints and Constraints if fkOriList: try: mc.delete(fkOriList) @@ -873,16 +873,16 @@ def limbsIkToFkOLD(rigNS,start=None,end=None,sampleBy=1): if fkDupList: try: mc.delete(fkDupList) except Exception, e: print('Error deleting nodes '+str(fkDupList)+'! Exception Msg: '+str(e)) - + # ====================================== # - Bake Wrist Animation from Locators - # ====================================== - + # Set to FK Mode for side in sides: mc.setAttr(rigNS+':config.'+side+'ArmIkFkBlend',1) mc.setAttr(rigNS+':config.'+side+'LegIkFkBlend',1) - + # Bake Wrists from Locators glTools.anim.utils.bakeAnimFromLocators( locList = wristLocs, start = start, @@ -890,11 +890,11 @@ def limbsIkToFkOLD(rigNS,start=None,end=None,sampleBy=1): sampleBy = sampleBy, simulation = True, attrList = ['rx','ry','rz'] ) - + # Transfer Baked Keys keys = mc.copyKey(wristDups,at=['rx','ry','rz'],t=(start,end)) if keys: mc.pasteKey(wristJnts,at=['rx','ry','rz'],t=(start,end),option='replace') - + # Cleanup if wristLocs: try: mc.delete(wristLocs) @@ -902,11 +902,11 @@ def limbsIkToFkOLD(rigNS,start=None,end=None,sampleBy=1): if wristDups: try: mc.delete(wristDups) except: pass - + # ================= # - Return Result - # ================= - + return fkJntList def limbsIkToFk(rigNS,start=None,end=None,sampleBy=1,lock=False): @@ -924,15 +924,15 @@ def limbsIkToFk(rigNS,start=None,end=None,sampleBy=1,lock=False): # ========== # - Checks - # ========== - + # Get Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # ========================== # - Build IK/FK Joint List - # ========================== - + index = ['A','B'] sides = ['lf','rt'] for side in sides: @@ -942,11 +942,11 @@ def limbsIkToFk(rigNS,start=None,end=None,sampleBy=1,lock=False): if not mc.getAttr(rigNS+':config.'+side+'LegIkFkBlend'): legIkToFk(rigNS,side,start,end,sampleBy) if lock: mc.cutKey(rigNS+':config.'+side+'ArmIkFkBlend') - + # ================= # - Return Result - # ================= - + print('Limbs IK -> FK bake complete!') return @@ -959,15 +959,15 @@ def armIkToFk_fromSel(): if not sel: print('Invalid or empty selection! Unable to transfer IK to FK...') return - + # Iterate Over Selection for item in sel: - + # Get Item Namespace rigNS = glTools.utils.namespace.getNS(item) if rigNS: rigNS += ':' else: rigNS = '' - + # Check Side side = '' if item.startswith(rigNS+'lf'): side = 'lf' @@ -975,13 +975,13 @@ def armIkToFk_fromSel(): if not side: print('Invalid side item ('+item+')! Select left ("lf*") or right ("rt*") control...') continue - + # Check IK Control(s) ikCtrl = rigNS+side+'_arm_ik_ctrl' if not mc.objExists(ikCtrl): print('IK control "'+ikCtrl+'" not found! Unable to transfer IK to FK...') continue - + # Transfer IK to FK try: armIkToFk(rigNS[:-1],side) except Exception, e: print('Error transferring IK to FK! Exception Msg: '+str(e)) @@ -996,15 +996,15 @@ def armFkToIk_fromSel(): if not sel: print('Invalid or empty selection! Unable to transfer FK to IK...') return - + # Iterate Over Selection for item in sel: - + # Get Item Namespace rigNS = glTools.utils.namespace.getNS(item) if rigNS: rigNS += ':' else: rigNS = '' - + # Check Side side = '' if item.startswith(rigNS+'lf'): side = 'lf' @@ -1012,13 +1012,13 @@ def armFkToIk_fromSel(): if not side: print('Invalid side item ('+item+')! Select left ("lf*") or right ("rt*") control...') continue - + # Check FK Control(s) fkCtrl = rigNS+side+'_arm_fkA_jnt' if not mc.objExists(fkCtrl): print('FK control "'+fkCtrl+'" not found! Unable to transfer FK to IK...') continue - + # Transfer FK to IK try: armFkToIk(rigNS[:-1],side) except Exception, e: print('Error transferring FK to IK! Exception Msg: '+str(e)) diff --git a/rig/mirrorAnim.py b/rig/mirrorAnim.py index 4c8dfb6..8ccfb5f 100644 --- a/rig/mirrorAnim.py +++ b/rig/mirrorAnim.py @@ -13,12 +13,12 @@ def swapAnim(srcCtrl,dstCtrl): ''' # Temp Key Node tmpCtrl = mc.duplicate(srcCtrl,po=True,n=srcCtrl+'TEMP')[0] - + # Swap Left <> Right cutPasteKey(srcCtrl,tmpCtrl) cutPasteKey(dstCtrl,srcCtrl) cutPasteKey(tmpCtrl,dstCtrl) - + # Delete Temp Node if mc.objExists(tmpCtrl): try: mc.delete(tmpCtrl) @@ -33,30 +33,30 @@ def mirrorBipedAnim(rigNS): # ============= # - Check Rig - # ============= - + if not mc.namespace(ex=rigNS): raise Exception('Rig namespace "'+rigNS+'" not found! Unable to mirror animation...') - + # ==================== # - Get Rig Controls - # ==================== - + # Body bodyA = rigNS+':cn_bodyA_jnt' bodyB = rigNS+':cn_bodyB_jnt' - + # Spine/Neck/Head spineA = rigNS+':cn_spineA_jnt' spineB = rigNS+':cn_spineB_jnt' spineC = rigNS+':cn_spineC_jnt' - + spineBase = rigNS+':cn_spine_base_ctrl' spineMid = rigNS+':cn_spine_mid_ctrl' spineTop = rigNS+':cn_spine_top_ctrl' - + neck = rigNS+':cn_neckA_jnt' head = rigNS+':cn_headA_jnt' - + # Arms clav = rigNS+':SIDE_clavicleA_jnt' armFkA = rigNS+':SIDE_arm_fkA_jnt' @@ -64,7 +64,7 @@ def mirrorBipedAnim(rigNS): armIk = rigNS+':SIDE_arm_ik_ctrl' armPv = rigNS+':SIDE_arm_pv_ctrl' hand = rigNS+':SIDE_handA_jnt' - + # Fingers fingerList = [ 'thumbA','thumbB','thumbC', 'indexA','indexB','indexC','indexD', @@ -72,119 +72,119 @@ def mirrorBipedAnim(rigNS): 'ringA','ringB','ringC','ringD', 'pinkyA','pinkyB','pinkyC','pinkyD' ] fingers = [rigNS+':SIDE_'+finger+'_jnt' for finger in fingerList] - + # Legs legFkA = rigNS+':SIDE_leg_fkA_jnt' legFkB = rigNS+':SIDE_leg_fkB_jnt' legIk = rigNS+':SIDE_leg_ik_ctrl' legPv = rigNS+':SIDE_leg_pv_ctrl' - + # Feet footIk = rigNS+':SIDE_foot_ik_ctrl' toeIk = rigNS+':SIDE_foot_toe_ctrl' footFkA = rigNS+':foot_fkA_jnt' footFkB = rigNS+':foot_fkB_jnt' - + # ==================== # - Mirror Animation - # ==================== - + # Body for ctrl in [bodyA,bodyB]: if mc.objExists(ctrl): mc.scaleKey(ctrl,at=['tx','ry','rz'],valueScale=-1.0,valuePivot=0.0) - + # Spine/Neck/Head for ctrl in [spineA,spineB,spineC,spineBase,spineMid,spineTop,neck,head]: if mc.objExists(ctrl): mc.scaleKey(ctrl,at=['tz','rx','ry'],valueScale=-1.0,valuePivot=0.0) - + # Arms - FK (Clavicle,Arm,Hand) for ctrl in [clav,armFkA,armFkB,hand]: - + # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE','lf') rtCtrl = ctrl.replace('SIDE','rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): - + # Swap Left <> Right swapAnim(lfCtrl,rtCtrl) - + # Scale Keys mc.scaleKey(lfCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) mc.scaleKey(rtCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) - + # Arms - IK for ctrl in [armIk,armPv]: - + # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE','lf') rtCtrl = ctrl.replace('SIDE','rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): - + # Swap Left <> Right swapAnim(lfCtrl,rtCtrl) - + # Scale Keys mc.scaleKey(lfCtrl,at=['tx','ry','rz'],valueScale=-1.0,valuePivot=0.0) mc.scaleKey(rtCtrl,at=['tx','ry','rz'],valueScale=-1.0,valuePivot=0.0) - + # Fingers for ctrl in fingers: - + # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE','lf') rtCtrl = ctrl.replace('SIDE','rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): - + # Swap Left <> Right swapAnim(lfCtrl,rtCtrl) - + # Scale Keys mc.scaleKey(lfCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) mc.scaleKey(rtCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) - + # Legs - FK for ctrl in [legFkA,legFkB,footFkA,footFkB]: - + # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE','lf') rtCtrl = ctrl.replace('SIDE','rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): - + # Swap Left <> Right swapAnim(lfCtrl,rtCtrl) - + # Scale Keys mc.scaleKey(lfCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) mc.scaleKey(rtCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) - + # Legs - IK for ctrl in [legIk,legPv]: - + # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE','lf') rtCtrl = ctrl.replace('SIDE','rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): - + # Swap Left <> Right swapAnim(lfCtrl,rtCtrl) - + # Scale Keys mc.scaleKey(lfCtrl,at=['tx','ry','rz'],valueScale=-1.0,valuePivot=0.0) - mc.scaleKey(rtCtrl,at=['tx','ry','rz'],valueScale=-1.0,valuePivot=0.0) - + mc.scaleKey(rtCtrl,at=['tx','ry','rz'],valueScale=-1.0,valuePivot=0.0) + # Feet - IK for ctrl in [footIk,toeIk]: - + # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE','lf') rtCtrl = ctrl.replace('SIDE','rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): - + # Swap Left <> Right swapAnim(lfCtrl,rtCtrl) - + # Scale Keys mc.scaleKey(lfCtrl,at=['tx','ry','rz'],valueScale=-1.0,valuePivot=0.0) mc.scaleKey(rtCtrl,at=['tx','ry','rz'],valueScale=-1.0,valuePivot=0.0) @@ -195,7 +195,7 @@ def mirrorBipedAnimFromSel(): # Get Current Selection sel = mc.ls(sl=True,transforms=True) NSlist = glTools.utils.namespace.getNSList(sel,topOnly=True) - + # Mirror Animation for rigNS in NSlist: try: mirrorBipedAnim(rigNS) @@ -210,27 +210,27 @@ def mirrorBipedMocap(rigNS): # ============= # - Check Rig - # ============= - + if not mc.namespace(ex=rigNS): raise Exception('Rig namespace "'+rigNS+'" not found! Unable to mirror animation...') - + # ==================== # - Get Rig Controls - # ==================== - + # Body body = rigNS+':Hips' - + # Spine/Neck/Head spine = rigNS+':Spine' neck = rigNS+':Neck' head = rigNS+':Head' - + # Arms clav = rigNS+':SIDEShoulder' arm = rigNS+':SIDEArm' foreArm = rigNS+':SIDEForeArm' - + # Hand hand = rigNS+':SIDEHand' thumb = rigNS+':SIDEHandThumb' @@ -239,31 +239,31 @@ def mirrorBipedMocap(rigNS): ring = rigNS+':SIDEHandRing' pinky = rigNS+':SIDEHandPinky' finger = [thumb,index,middle,ring,pinky] - + # Legs upLeg = rigNS+':SIDEUpLeg' leg = rigNS+':SIDELeg' - + # Foot foot = rigNS+':SIDEFoot' toe = rigNS+':SIDEToeBase' - + # Roll roll = 'Roll' - + # Side left = 'Left' right = 'Right' - + # ==================== # - Mirror Animation - # ==================== - + # Body for ctrl in [body]: if mc.objExists(ctrl): mc.scaleKey(ctrl,at=['tx','ry','rz'],valueScale=-1.0,valuePivot=0.0) - + # Spine/Neck/Head for item in [spine,neck,head]: ind = '' @@ -272,7 +272,7 @@ def mirrorBipedMocap(rigNS): mc.scaleKey(ctrl,at=['rx','ry'],valueScale=-1.0,valuePivot=0.0) if not ind: ind = 0 ind += 1 - + # Shoulder for ctrl in [clav]: # Get Left/Right Nodes @@ -282,10 +282,10 @@ def mirrorBipedMocap(rigNS): swapAnim(lfCtrl,rtCtrl) mc.scaleKey(lfCtrl,at=['tz'],valueScale=-1.0,valuePivot=0.0) mc.scaleKey(rtCtrl,at=['tz'],valueScale=-1.0,valuePivot=0.0) - + # Arms for ctrl in [arm,foreArm,hand]: - + # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE',left) rtCtrl = ctrl.replace('SIDE',right) @@ -293,7 +293,7 @@ def mirrorBipedMocap(rigNS): swapAnim(lfCtrl,rtCtrl) mc.scaleKey(lfCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) mc.scaleKey(rtCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) - + # Get Roll Nodes lfCtrl = lfCtrl+roll rtCtrl = rtCtrl+roll @@ -301,14 +301,14 @@ def mirrorBipedMocap(rigNS): swapAnim(lfCtrl,rtCtrl) mc.scaleKey(lfCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) mc.scaleKey(rtCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) - + # Fingers for ctrl in finger: - + # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE',left) rtCtrl = ctrl.replace('SIDE',right) - + ind = 1 while mc.objExists(lfCtrl+str(ind)) and mc.objExists(rtCtrl+str(ind)): lfCtrlInd = lfCtrl+str(ind) @@ -318,10 +318,10 @@ def mirrorBipedMocap(rigNS): mc.scaleKey(rtCtrlInd,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) if not ind: ind = 0 ind += 1 - + # Legs for ctrl in [upLeg,leg,foot,toe]: - + # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE',left) rtCtrl = ctrl.replace('SIDE',right) @@ -329,7 +329,7 @@ def mirrorBipedMocap(rigNS): swapAnim(lfCtrl,rtCtrl) mc.scaleKey(lfCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) mc.scaleKey(rtCtrl,at=['tx','ty','tz'],valueScale=-1.0,valuePivot=0.0) - + # Get Roll Nodes lfCtrl = lfCtrl+roll rtCtrl = rtCtrl+roll @@ -344,7 +344,7 @@ def mirrorBipedMocaFromSel(): # Get Current Selection sel = mc.ls(sl=True,transforms=True) NSlist = glTools.utils.namespace.getNSList(sel,topOnly=True) - + # Mirror Animation for rigNS in NSlist: try: mirrorBipedMocap(rigNS) diff --git a/rig/mirrorTemplate.py b/rig/mirrorTemplate.py index ebe0756..041a8fe 100644 --- a/rig/mirrorTemplate.py +++ b/rig/mirrorTemplate.py @@ -5,7 +5,7 @@ def mirror(rootList=[],locList=[],leftToRight=True): ''' Mirror rig template components - @param rootList: List of template root joints to mirror. + @param rootList: List of template root joints to mirror. @type rootList: list @param locList: List of template locators to mirror. @type locList: list @@ -15,47 +15,47 @@ def mirror(rootList=[],locList=[],leftToRight=True): # ============== # - Check Side - # ============== - + src = 'lf_' dst = 'rt_' if not leftToRight: src = 'rt_' dst = 'lf_' - + # ======================================== # - Removed Existing Desitination Joints - # ======================================== - + for root in rootList: if root.startswith(dst): mc.delete(root) - + # ====================== # - Mirror Root Joints - # ====================== - + # Mirror Joints for root in rootList: - + # Check Side if root.startswith(src): - + # Mirror Joint mirrorJoint = mc.mirrorJoint(root,mirrorYZ=True,mirrorBehavior=True,searchReplace=[src,dst]) - + # Colour Hierarchy glTools.utils.colorize.colourHierarchy(root) glTools.utils.colorize.colourHierarchy(mirrorJoint[0]) - + # =================== # - Mirror Locators - # =================== - + # Mirror Locator using Match() for loc in locList: - + # Check Side if loc.startswith(src): - + # Mirror Locator glTools.tools.match.Match().twin(loc) diff --git a/rig/mocapOverride.py b/rig/mocapOverride.py index bd69527..9d747f8 100644 --- a/rig/mocapOverride.py +++ b/rig/mocapOverride.py @@ -36,32 +36,32 @@ def buildOverrideTransform(transform,prefix=None): # ========== # - Checks - # ========== - + if not mc.objExists(transform): raise Exception('Rig control transform "'+transform+'" does not exist!') - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(transform) - + # ============================= # - Create Override Transform - # ============================= - + # Duplicate Transform overrideTransform = mc.duplicate(transform,po=True,n=prefix+'_grp')[0] - + # Set Display Mode glTools.utils.base.displayOverride(overrideTransform,overrideEnable=1,overrideLOD=1) if glTools.utils.joint.isJoint(overrideTransform): mc.setAttr(overrideTransform+'.drawStyle',2) # None - + # Delete Unused Attributes glTools.utils.attribute.deleteUserAttrs(overrideTransform) - + # ================= # - Return Result - # ================= - + return overrideTransform def getOverrideConstraint(control): @@ -73,12 +73,12 @@ def getOverrideConstraint(control): # Check Control if not mc.objExists(control): raise Exception('Rig control transform "'+control+'" does not exist!') - + # Override Enable Attribute overrideAttr = overrideAttribute() if not mc.objExists(control+'.'+overrideAttr): raise Exception('OverrideEnable attribute "'+control+'.'+overrideAttr+'" does not exist!') - + # Override Constraint overrideConstraint = mc.listConnections(control+'.'+overrideAttr,s=False,d=True) if not overrideConstraint: @@ -86,7 +86,7 @@ def getOverrideConstraint(control): overrideConstraint = mc.ls(overrideConstraint,type='constraint') if not overrideConstraint: raise Exception('Override constraint could not be determined from overrideEnabled attribute "'+control+'.'+overrideAttr+'"!') - + # Return Result return list(set(overrideConstraint)) @@ -98,12 +98,12 @@ def getOverrideTarget(control): ''' # Get Override Constraint overrideConstraint = getOverrideConstraint(control) - + # Get Override Target overrideTarget = glTools.utils.constraint.targetList(overrideConstraint[0]) if not overrideTarget: raise Exception('Unable to determine override target transform from constraint "'+overrideConstraint[0]+'"!') - + # Return Result return overrideTarget[0] @@ -120,7 +120,7 @@ def getOverrideTargetNew(control): overrideTarget = mc.listConnections(control+'.'+overrideTargetAttr,s=True,d=False) if not overrideTarget: raise Exception('Unable to determine override target transform! Attribute "'+control+'.'+overrideTargetAttr+'" has no incoming connections.') - + # Return Result return overrideTarget[0] @@ -135,75 +135,75 @@ def createControlOverride(transform,prefix=None): # ========== # - Checks - # ========== - + if not mc.objExists(transform): raise Exception('Rig control transform "'+transform+'" does not exist!') - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(transform) - + # ====================================== # - Create Control Override Transforms - # ====================================== - + overrideTarget = buildOverrideTransform(transform,prefix=prefix+'_overrideTarget') overrideTransform = buildOverrideTransform(transform,prefix=prefix+'_overrideTransform') - + # Set Channel States channelState = glTools.utils.channelState.ChannelState() channelState.setFlags([0,0,0,0,0,0,2,2,2,1],objectList=[overrideTarget]) channelState.setFlags([1,1,1,1,1,1,2,2,2,1],objectList=[overrideTransform]) channelState.set(1,[overrideTarget,overrideTransform]) - + # Parent Control to Override Transform mc.parent(transform,overrideTransform) - + # ====================================== # - Create Control Override Constraint - # ====================================== - + # Create ParentConstraint overrideConstraint = mc.parentConstraint(overrideTarget,overrideTransform,n=prefix+'_overrideTransform_parentConstraint')[0] overrideAlias = mc.parentConstraint(overrideConstraint,q=True,wal=True) - + # Reset Rest Values mc.setAttr(overrideConstraint+'.restTranslate',0,0,0) mc.setAttr(overrideConstraint+'.restRotate',0,0,0) - + # ========================== # - Create Override Toggle - # ========================== - + # Create Toggle Attribute overrideAttr = overrideAttribute() if mc.objExists(transform+'.'+overrideAttr): mc.deleteAttr(transform+'.'+overrideAttr) mc.addAttr(transform,ln=overrideAttr,at='bool') mc.setAttr(transform+'.'+overrideAttr,False) - + # Connect Toggle Attribute mc.connectAttr(transform+'.'+overrideAttr,overrideConstraint+'.'+overrideAlias[0],f=True) - + # ========================== # - Create Override Offset - # ========================== - + offsetAttr = overrideOffsetAttribute() if mc.objExists(transform+'.'+offsetAttr): mc.deleteAttr(transform+'.'+offsetAttr) - + mc.addAttr(transform,ln=offsetAttr,at='double3') mc.addAttr(transform,ln=offsetAttr+'X',at='double',p=offsetAttr,dv=0) mc.addAttr(transform,ln=offsetAttr+'Y',at='double',p=offsetAttr,dv=0) mc.addAttr(transform,ln=offsetAttr+'Z',at='double',p=offsetAttr,dv=0) - + # Connect Offset mc.connectAttr(transform+'.'+offsetAttr,overrideConstraint+'.target[0].targetOffsetTranslate',f=True) - + # ================= # - Return Result - # ================= - + result = {} result['overrideTarget'] = overrideTarget result['overrideTransform'] = overrideTransform @@ -221,27 +221,27 @@ def createControlOverrideNew(transform,prefix=''): # ========== # - Checks - # ========== - + if not mc.objExists(transform): raise Exception('Rig control transform "'+transform+'" does not exist!') - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(transform) - + # ====================================== # - Create Control Override Transforms - # ====================================== - + overrideTarget = buildOverrideTransform(transform,prefix=prefix+'_overrideTarget') overrideTransform = buildOverrideTransform(transform,prefix=prefix+'_overrideTransform') - + # Parent Control to Override Transform mc.parent(transform,overrideTransform) - + # ========================== # - Create Override Toggle - # ========================== - + # Create Toggle Attribute overrideAttr = overrideAttribute() if mc.objExists(transform+'.'+overrideAttr): @@ -249,22 +249,22 @@ def createControlOverrideNew(transform,prefix=''): mc.addAttr(transform,ln=overrideAttr,at='enum',en='Off:On') mc.setAttr(transform+'.'+overrideAttr,k=False,cb=True) mc.setAttr(transform+'.'+overrideAttr,False) - + # Mocap Override Message Connection overrideTargetAttr = 'mocapOverrideTarget' if mc.objExists(transform+'.'+overrideTargetAttr): mc.deleteAttr(transform+'.'+overrideTargetAttr) mc.addAttr(transform,ln=overrideTargetAttr,at='message') mc.connectAttr(overrideTarget+'.message',transform+'.'+overrideTargetAttr,f=True) - + # =================================== # - Create Control Override Network - # =================================== - + # Create Override Conditions overrideTranslate = mc.createNode('condition',n=prefix+'_overrideTranslate_condition') overrideRotate = mc.createNode('condition',n=prefix+'_overrideRotate_condition') - + # Override Translate baseTranslate = mc.getAttr(overrideTransform+'.t')[0] mc.setAttr(overrideTranslate+'.colorIfFalse',*baseTranslate,l=True,cb=False) @@ -274,7 +274,7 @@ def createControlOverrideNew(transform,prefix=''): mc.setAttr(overrideTranslate+'.secondTerm',1,l=True,cb=False) mc.connectAttr(transform+'.'+overrideAttr,overrideTranslate+'.firstTerm',f=True) mc.setAttr(overrideTranslate+'.firstTerm',l=True,cb=False) - + # Override Rotate baseRotate = mc.getAttr(overrideTransform+'.r')[0] mc.setAttr(overrideRotate+'.colorIfFalse',*baseRotate,l=True,cb=False) @@ -284,26 +284,26 @@ def createControlOverrideNew(transform,prefix=''): mc.setAttr(overrideRotate+'.operation',0,l=True,cb=False) # Equal mc.connectAttr(transform+'.'+overrideAttr,overrideRotate+'.firstTerm',f=True) mc.setAttr(overrideRotate+'.firstTerm',l=True,cb=False) - + # ================== # - Channel States - # ================== - + chanState = glTools.utils.channelState.ChannelState() chanState.setFlags([0,0,0,0,0,0,2,2,2,1],objectList=[overrideTarget]) chanState.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=[overrideTransform]) #chanState.set(1,[overrideTarget,overrideTransform]) - + # ================= # - Return Result - # ================= - + result = {} result['overrideTarget'] = overrideTarget result['overrideTransform'] = overrideTransform result['overrideTranslate'] = overrideTranslate result['overrideRotate'] = overrideRotate - + return result def constrainControlOverrideTarget( control, @@ -337,11 +337,11 @@ def constrainControlOverrideTarget( control, # ========== # - Checks - # ========== - + # Control if not mc.objExists(control): raise Exception('Rig control transform "'+control+'" does not exist!') - + # Constraint Target if isinstance(constraintTarget,types.StringTypes): if not mc.objExists(constraintTarget): @@ -352,16 +352,16 @@ def constrainControlOverrideTarget( control, raise Exception('Override transform target "'+target+'" does not exist!') else: raise Exception('Invalid argument type for constraintTarget!') - + # Constraint Type if not constraintType in ['point','orient','parent']: raise Exception('Unsupported constraint type "'+constraintType+'"!') - + # Override Enable Attribute overrideAttr = overrideAttribute() if not mc.objExists(control+'.'+overrideAttr): raise Exception('OverrideEnable attribute "'+control+'.'+overrideAttr+'" does not exist!') - + # Override Constraint overrideConstraint = mc.listConnections(control+'.'+overrideAttr,s=False,d=True) if not overrideConstraint: @@ -369,28 +369,28 @@ def constrainControlOverrideTarget( control, overrideConstraint = mc.ls(overrideConstraint,type='constraint') if not overrideConstraint: raise Exception('Override constraint could not be determined from overrideEnabled attribute "'+control+'.'+overrideAttr+'"!') - + # Override Target overrideTarget = glTools.utils.constraint.targetList(overrideConstraint[0]) if not overrideTarget: raise Exception('Unable to determine override target transform from constraint "'+overrideConstraint[0]+'"!') - + # InterpType interpIndex = {'average':1,'shortest':2,'longest':3} if constraintType == 'parent' or constraintType == 'orient': if interpType and not interpType in interpIndex.keys(): raise Exception('Invalid interpolation type "'+interpType+'"!') - + # Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(control) - + # ===================================== # - Create Override Target Constraint - # ===================================== - + overrideTargetConstraint = '' - + # Create pointConstraint if constraintType == 'point': overrideTargetConstraint = mc.pointConstraint( constraintTarget, @@ -398,7 +398,7 @@ def constrainControlOverrideTarget( control, mo = maintainOffset, sk = skipTranslate, n = prefix+'_overrideTarget_pointConstraint' )[0] - + # Create orientConstraint elif constraintType == 'orient': overrideTargetConstraint = mc.orientConstraint( constraintTarget, @@ -408,7 +408,7 @@ def constrainControlOverrideTarget( control, n = prefix+'_overrideTarget_orientConstraint' )[0] # Interp Type if interpType: mc.setAttr(overrideTargetConstraint+'.interpType',interpIndex[interpType]) - + # Create parentConstraint elif constraintType == 'parent': overrideTargetConstraint = mc.parentConstraint( constraintTarget, @@ -419,18 +419,18 @@ def constrainControlOverrideTarget( control, n = prefix+'_overrideTarget_parentConstraint' )[0] # Interp Type if interpType: mc.setAttr(overrideTargetConstraint+'.interpType',interpIndex[interpType]) - + # Unsupported Constraint Type else: raise Exception('Unsupported constraint type "'+constraintType+'"!') - + # Enable overrideConstraint mc.setAttr(control+'.'+overrideAttr,True) - + # ================= # - Return Result - # ================= - + return overrideTargetConstraint def constrainControlToTarget( control, @@ -464,11 +464,11 @@ def constrainControlToTarget( control, # ========== # - Checks - # ========== - + # Control if not mc.objExists(control): raise Exception('Rig control transform "'+control+'" does not exist!') - + # Constraint Target if isinstance(constraintTarget,types.StringTypes): if not mc.objExists(constraintTarget): @@ -477,27 +477,27 @@ def constrainControlToTarget( control, for target in constraintTarget: if not mc.objExists(target): raise Exception('Override transform target "'+target+'" does not exist!') - + # Constraint Type if not constraintType in ['point','orient','parent']: raise Exception('Unsupported constraint type "'+constraintType+'"!') - + # InterpType interpIndex = {'average':1,'shortest':2,'longest':3} if constraintType == 'parent' or constraintType == 'orient': if interpType and not interpType in interpIndex.keys(): raise Exception('Invalid interpolation type "'+interpType+'"!') - + # Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(control) - + # ===================================== # - Create Override Target Constraint - # ===================================== - + overrideCtrlConstraint = None - + # Create pointConstraint if constraintType == 'point': try: @@ -508,7 +508,7 @@ def constrainControlToTarget( control, n = prefix+'_overrideCtrl_pointConstraint' )[0] except Exception, e: raise Exception('Error creating point constraint for control "'+control+'"! '+str(e)) - + # Create orientConstraint elif constraintType == 'orient': try: @@ -519,10 +519,10 @@ def constrainControlToTarget( control, n = prefix+'_overrideCtrl_orientConstraint' )[0] except Exception, e: raise Exception('Error creating orient constraint for control "'+control+'"! '+str(e)) - + # Interp Type if interpType: mc.setAttr(overrideCtrlConstraint+'.interpType',interpIndex[interpType]) - + # Create parentConstraint elif constraintType == 'parent': try: @@ -535,14 +535,14 @@ def constrainControlToTarget( control, attrList = attrList ) except Exception, e: raise Exception('Error creating parent constraint for control "'+control+'"! '+str(e)) - + # Interp Type if interpType: mc.setAttr(overrideCtrlConstraint+'.interpType',interpIndex[interpType]) - + # ================= # - Return Result - # ================= - + return overrideCtrlConstraint def bakeControlOverrideTarget(controlList,start=None,end=None,bakeSim=True): @@ -558,29 +558,29 @@ def bakeControlOverrideTarget(controlList,start=None,end=None,bakeSim=True): @type bakeSim: bool ''' print('!!==== DEPRICATED ====!! (glTools.rig.mocapOverride.bakeControlOverrideTarget)') - + # ========== # - Checks - # ========== - + # Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # For Each Control overrideTargetList = [] overrideConstraintList = [] for control in controlList: - + # Control if not mc.objExists(control): raise Exception('Rig control transform "'+control+'" does not exist!') - + # Override Enable Attribute overrideAttr = overrideAttribute() if not mc.objExists(control+'.'+overrideAttr): raise Exception('OverrideEnable attribute "'+control+'.'+overrideAttr+'" does not exist!') - + # Override Constraint overrideConstraint = mc.listConnections(control+'.'+overrideAttr,s=False,d=True) if not overrideConstraint: @@ -588,45 +588,45 @@ def bakeControlOverrideTarget(controlList,start=None,end=None,bakeSim=True): overrideConstraint = mc.ls(overrideConstraint,type='constraint') if not overrideConstraint: raise Exception('Override constraint could not be determined from overrideEnabled attribute "'+control+'.'+overrideAttr+'"!') - + # Override Target overrideTarget = glTools.utils.constraint.targetList(overrideConstraint[0]) if not overrideTarget: raise Exception('Unable to determine override target transform from constraint "'+overrideConstraint[0]+'"!') - + # Override Target Constraint overrideTargetConstraint = mc.ls(mc.listConnections(overrideTarget[0],s=True,d=False),type='constraint') if not overrideTargetConstraint: - + # Check PairBlend (intermediate) Connection # - This fix was made in preparation for baking keys from multiple mocap sources (bake in frame chunks). overrideTargetPairBlend = mc.ls(mc.listConnections(overrideTarget[0],s=True,d=False),type='pairBlend') if overrideTargetPairBlend: overrideTargetConstraint = mc.ls(mc.listConnections(overrideTargetPairBlend,s=True,d=False),type='constraint') - + if not overrideTargetConstraint: print('Unable to determine override target constraint from override target transform "'+overrideTarget[0]+'"!') continue - + # Append to Override Target List overrideTargetList.append(overrideTarget[0]) # Append to Override Constraint List [overrideConstraintList.append(i) for i in overrideTargetConstraint if not i in overrideConstraintList] - + # ================================= # - Bake Override Target Channels - # ================================= - + mc.bakeResults( overrideTargetList, t = (start,end), at = ['tx','ty','tz','rx','ry','rz'], preserveOutsideKeys = True, simulation = bakeSim ) - + # ====================== # - Delete Constraints - # ====================== - + mc.delete(overrideConstraintList) def bakeControlOverride(controlList,start=None,end=None,bakeSim=True): @@ -642,69 +642,69 @@ def bakeControlOverride(controlList,start=None,end=None,bakeSim=True): @type bakeSim: bool ''' print('!!==== DEPRICATED ====!! (glTools.rig.mocapOverride.bakeControlOverride)') - + # ========== # - Checks - # ========== - + # Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # For Each Control bakeControlList = [] constraintList = [] for control in controlList: - + # Control if not mc.objExists(control): raise Exception('Rig control transform "'+control+'" does not exist!') - + # Override Target Constraint overrideConstraint = mc.ls(mc.listConnections(control+'.'+overrideAttribute(),d=True,s=False),type='constraint') if not overrideConstraint: - + # Check PairBlend (intermediate) Connection # - This fix was made in preparation for baking keys from multiple mocap sources (bake in frame chunks). overridePairBlend = mc.ls(mc.listConnections(control,s=True,d=False),type='pairBlend') if overridePairBlend: overrideConstraint = mc.ls(mc.listConnections(overrideTargetPairBlend,s=True,d=False) or [],type='constraint') - + if not overrideConstraint: print('Unable to determine override constraint from control transform "'+control+'"!') continue - + # Append to Override Target List bakeControlList.append(control) # Append to Override Constraint List [constraintList.append(i) for i in overrideConstraint if not i in constraintList] - + # ================================= # - Bake Override Target Channels - # ================================= - + # Check Bake Control List if not bakeControlList: print('Found no controls to bake! Skipping...') return None - + # Bake to Controls mc.bakeResults( bakeControlList, t = (start,end), at = ['tx','ty','tz','rx','ry','rz'], preserveOutsideKeys = True, simulation = bakeSim ) - + # ====================== # - Delete Constraints - # ====================== - + if constraintList: mc.delete(constraintList) - + # ================= # - Return Result - # ================= - + return bakeControlList def bakeExportSkeleton(exportNS,start=1,end=0): @@ -720,41 +720,41 @@ def bakeExportSkeleton(exportNS,start=1,end=0): # ========== # - Checks - # ========== - + # Start/End if start > end: start = mc.playbackOptions(q=True,min=True) end = mc.playbackOptions(q=True,max=True) - + # Namespace if not exportNS: raise Exception('An export namespace must be specified') - + exportNS = exportNS+':' if not mc.namespace(exists=':'+exportNS): raise Exception('Export namespace "'+exportNS+'" does not exist!') - + # ====================== # - Bake Export Joints - # ====================== - + jointList = mc.ls(exportNS+'*',type='joint') bakeList = [i for i in jointList if mc.ls(mc.listConnections(i,s=True,d=False),type='constraint')] mc.bakeResults(bakeList,t=(start,end),at=['tx','ty','tz','rx','ry','rz','sx','sy','sz'],simulation=True) - + # ====================== # - Delete Constraints - # ====================== - + constraintList = mc.ls(exportNS+'*',type='constraint') if not constraintList: raise Exception('Unbale to determine export skeleton constraint list!') mc.delete(constraintList) - + # ================= # - Return Result - # ================= - + return bakeList def fbxExportSkeleton(exportNS,exportPath,force=False): @@ -770,14 +770,14 @@ def fbxExportSkeleton(exportNS,exportPath,force=False): # ========== # - Checks - # ========== - + # Namespace if not exportNS: raise Exception('An export namespace must be specified') exportNS = exportNS+':' if not mc.namespace(exists=':'+exportNS): raise Exception('Export namespace "'+exportNS+'" does not exist!') - + # Check Directory Path exportDir = os.path.dirname(exportPath) if not os.path.isdir(exportDir): @@ -785,25 +785,25 @@ def fbxExportSkeleton(exportNS,exportPath,force=False): os.makedirs(exportDir) else: raise Exception('Export directory "'+exportDir+'" does not exist! Use "force=True" to automatically create the required directory structure.') - + # Check File Extension if not os.path.splitext(exportPath)[-1].lower() == '.fbx': exportPath += '.fbx' - + # Check File Path if os.path.isfile(exportPath) and not force: raise Exception('File "'+exportPath+'" already exista! Use "force=True" to overwrite the existing file.') - + # ========== # - Export - # ========== - + # Define export selection exportList = mc.ls(exportNS+'*',type='joint') if not exportList: raise Exception('Export namespace "'+exportNS+'" is empty!') mc.select(exportList) - + # Set FBX export options mm.eval('FBXExportFileVersion "FBX200900"') mm.eval('FBXExportInAscii -v 1') @@ -813,18 +813,18 @@ def fbxExportSkeleton(exportNS,exportPath,force=False): mm.eval('FBXExportCameras -v 0') mm.eval('FBXExportLights -v 0') mm.eval('FBXExportAnimationOnly -v 0') - + # Set Scale Conversion #mm.eval('FBXExportConvertUnitString "m"') - + # Export Selected Nodes to FBX file mm.eval('FBXExport -f "'+exportPath+'" -s;') - + # Clear Selection mc.select(cl=True) - + # ================= # - Return Result - # ================= - + return exportPath diff --git a/rig/templateCheck.py b/rig/templateCheck.py index 89e691d..7717fcb 100644 --- a/rig/templateCheck.py +++ b/rig/templateCheck.py @@ -14,13 +14,13 @@ def checkTemplateElements(template): # ================================= # - Check Template Elements Exist - # ================================= - + for key in template.iterkeys(): - + # Get template component list templateList = template[key] for item in templateList: - + # Check template item exists if not mc.objExists(item): raise Exception('Template component "'+str(key)+'" item "'+item+'" does not exist!') @@ -43,15 +43,15 @@ def checkJointAxis(joint,axis='x',vector='x',warnThreshold=0.5,errorThreshold=0. # Check Joint if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') - + # Get Joint Axis as World Vector axisVec = glTools.utils.transform.axisVector(joint,axis,normalize=True) # Get Camparison World Vector refVec = glTools.utils.lib.axis_dict()[vector] - + # Compare Vectors dot = glTools.utils.mathUtils.dotProduct(axisVec,refVec) - + # Check Thresholds if dot < errorThreshold: print ('Template Check ERROR: Joint "'+joint+'" axis "'+axis+'" is below the maximum comparison threshold to its target world vector ('+str(refVec)+')!') @@ -69,10 +69,10 @@ def checkZeroJointOrient(joint,fix=False): # Check Joint Orient jointOri = mc.getAttr(joint+'.jo') if (jointOri[0] + jointOri[1] + jointOri[2]) > 0.001: - + # Print Warning print('Template Check Warning: Joint "'+joint+'" has non zero joint orients! ('str(jointOri[0])'+'str(jointOri[1])'+'str(jointOri[2])')') - + # Zero Joint Orient if fix: mc.setAttr(joint+'.jo',0,0,0) @@ -90,7 +90,7 @@ def checkInverseScaleConnection(joint,fix=False): parentJoint = mc.listRelatives(joint,p=True) if not parentJoint: return if not mc.objectType(parentJoint[0]) == 'joint': return - + # Get Existing Inverse Scale Connection invScalConn = mc.listConnections(joint+'.inverseScale',s=True,d=False) if not invScalConn: invScalConn = [] @@ -113,14 +113,14 @@ def checkJointTranslation(joint,offsetAxis='',ignoreMultipleSibling=False): if not mc.objectType(parentJoint[0]) == 'joint': print('Template Check: Parent transform ("'+parentJoint[0]+'") of joint ("'+joint+'") is not a joint! Offset axis is being ignored for translation check.') offsetAxis='' - + # Get List of Joint Siblings jointSiblings = mc.ls(mc.listRelatives(parentJoint[0],c=True,pa=True),type='joint') jointSiblings.remove(joint) if jointSiblings and ignoreMultipleSibling: print('Template Check: Joint ("'+joint+'") has one or more joint siblings! Joint translation is expected for joints with siblings. Skipping check...') return - + # Check Joint Translation tSum = 0 t = mc.getAttr(joint+'.t')[0] @@ -136,7 +136,7 @@ def checkBipedTemplate(fix=False): # ============================ # - Define Template Elements - # ============================ - + template = {} template['body'] = ['cn_bodyA_jnt','cn_bodyEnd_jnt'] template['spine'] = ['cn_spineA_jnt','cn_spineB_jnt','cn_spineC_jnt','cn_spineEnd_jnt'] @@ -164,37 +164,37 @@ def checkBipedTemplate(fix=False): template['rt_foot'] = ['rt_footA_jnt','rt_footB_jnt','rt_footEnd_jnt'] template['lf_foot_loc'] = ['lf_foot_loc', 'lf_heel_loc', 'lf_toe_loc', 'lf_footInner_loc', 'lf_footOuter_loc'] template['rt_foot_loc'] = ['rt_foot_loc', 'rt_heel_loc', 'rt_toe_loc', 'rt_footInner_loc', 'rt_footOuter_loc'] - + # ================================= # - Check Template Elements Exist - # ================================= - + checkTemplateElements(template) - + # ======================= # - Check Joint Orients - # ======================= - + # Body for joint in template['body'][:-1]: checkJointAxis(joint=joint,axis='z',vector='z',warnThreshold=0.999,errorThreshold=0.9) checkJointAxis(joint=joint,axis='y',vector='y',warnThreshold=0.999,errorThreshold=0.9) - + # Spine for joint in template['spine'][:-1]: checkJointAxis(joint=joint,axis='z',vector='x',warnThreshold=0.999,errorThreshold=0.9) checkJointAxis(joint=joint,axis='x',vector='y',warnThreshold=0.8,errorThreshold=0.5) - + # Neck for joint in template['neck'][:-1]: checkJointAxis(joint=joint,axis='z',vector='x',warnThreshold=0.999,errorThreshold=0.9) checkJointAxis(joint=joint,axis='x',vector='y',warnThreshold=0.5,errorThreshold=0.0) - + # Head for joint in template['head'][:-1]: checkJointAxis(joint=joint,axis='z',vector='x',warnThreshold=0.999,errorThreshold=0.9) checkJointAxis(joint=joint,axis='x',vector='y',warnThreshold=0.8,errorThreshold=0.5) - + # Clavicles for joint in template['lf_clav'][:-1]: checkJointAxis(joint=joint,axis='x',vector='x',warnThreshold=0.75,errorThreshold=0.25) @@ -202,7 +202,7 @@ def checkBipedTemplate(fix=False): for joint in template['rt_clav'][:-1]: checkJointAxis(joint=joint,axis='x',vector='x',warnThreshold=0.75,errorThreshold=0.25) checkJointAxis(joint=joint,axis='z',vector='y',warnThreshold=0.9,errorThreshold=0.8) - + # Arms for joint in template['lf_arm'][:-1]: checkJointAxis(joint=joint,axis='x',vector='x',warnThreshold=0.75,errorThreshold=0.25) @@ -210,7 +210,7 @@ def checkBipedTemplate(fix=False): for joint in template['rt_arm'][:-1]: checkJointAxis(joint=joint,axis='x',vector='x',warnThreshold=0.75,errorThreshold=0.25) checkJointAxis(joint=joint,axis='z',vector='y',warnThreshold=0.9,errorThreshold=0.8) - + # Legs for joint in template['lf_leg'][:-1]: checkJointAxis(joint=joint,axis='x',vector='-y',warnThreshold=0.75,errorThreshold=0.5) @@ -218,7 +218,7 @@ def checkBipedTemplate(fix=False): for joint in template['rt_leg'][:-1]: checkJointAxis(joint=joint,axis='x',vector='y',warnThreshold=0.75,errorThreshold=0.5) checkJointAxis(joint=joint,axis='z',vector='x',warnThreshold=0.9,errorThreshold=0.8) - + # Feet for joint in template['lf_foot'][:-1]: checkJointAxis(joint=joint,axis='x',vector='z',warnThreshold=0.75,errorThreshold=0.25) @@ -226,7 +226,7 @@ def checkBipedTemplate(fix=False): for joint in template['rt_foot'][:-1]: checkJointAxis(joint=joint,axis='x',vector='-z',warnThreshold=0.75,errorThreshold=0.25) checkJointAxis(joint=joint,axis='z',vector='x',warnThreshold=0.9,errorThreshold=0.8) - + # Hands for joint in template['lf_hand']: checkJointAxis(joint=joint,axis='x',vector='x',warnThreshold=0.75,errorThreshold=0.25) @@ -234,7 +234,7 @@ def checkBipedTemplate(fix=False): for joint in template['rt_hand']: checkJointAxis(joint=joint,axis='x',vector='x',warnThreshold=0.75,errorThreshold=0.25) checkJointAxis(joint=joint,axis='z',vector='y',warnThreshold=0.9,errorThreshold=0.8) - + # Fingers lf_fingerList = template['lf_index'] + template['lf_middle'] + template['lf_ring'] + template['lf_pinky'] rt_fingerList = template['rt_index'] + template['rt_middle'] + template['rt_ring'] + template['rt_pinky'] @@ -250,34 +250,34 @@ def checkBipedTemplate(fix=False): for joint in template['rt_thumb'][:-1]: checkJointAxis(joint=joint,axis='x',vector='x',warnThreshold=0.25,errorThreshold=0.0) checkJointAxis(joint=joint,axis='z',vector='y',warnThreshold=0.25,errorThreshold=0.0) - + # ========================== # - Check Joint Properties - # ========================== - + # For Each Joint for joint in mc.ls(type='joint'): - + # ========================== # - Zero End Joint Orients - # ========================== - + # Check End Joint if glTools.utils.joint.isEndJoint(joint): - + # Check Joint Orient checkZeroJointOrient(joint,fix=fix) - + # =================================== # - Check Inverse Scale Connections - # =================================== - + checkInverseScaleConnection(joint,fix=fix) - + # ========================== # - Check Joint Transforms - # ========================== - + checkJointTranslation(joint,'x',ignoreMultipleSibling=True) def checkBoxtrollTemplate(): @@ -286,7 +286,7 @@ def checkBoxtrollTemplate(): # ============================ # - Define Template Elements - # ============================ - + template = {} template['body'] = ['cn_bodyA_jnt','cn_bodyEnd_jnt'] template['box'] = ['cn_boxA_jnt','cn_boxEnd_jnt'] @@ -314,22 +314,22 @@ def checkBoxtrollTemplate(): template['rt_ear'] = ['rt_earA_jnt','rt_earB_jnt','rt_earEnd_jnt'] template['lf_foot_loc'] = ['lf_foot_loc', 'lf_heel_loc', 'lf_toe_loc', 'lf_footInner_loc', 'lf_footOuter_loc'] template['rt_foot_loc'] = ['rt_foot_loc', 'rt_heel_loc', 'rt_toe_loc', 'rt_footInner_loc', 'rt_footOuter_loc'] - + # ================================= # - Check Template Elements Exist - # ================================= - + checkTemplateElements(template) - + # ======================= # - Check Joint Orients - # ======================= - + # Zero End Joint Orients - + # Check Inverse Scale Connections - + # Check Transforms - + # Translation in Single Axis for Lone Sibling - + diff --git a/rig/twist.py b/rig/twist.py index 504b39f..808102b 100644 --- a/rig/twist.py +++ b/rig/twist.py @@ -27,50 +27,50 @@ def createTwistJoints( joint, # ========== # - Checks - # ========== - + # Check joint if not mc.objExists(joint): raise Exception('Joint '+joint+' does not exist!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(joint) - + # Offset Axis if not ['x','y','z'].count(offsetAxis): raise Exception('Invalid offset axis value! ("'+offsetAxis+'")') - + # ================= # - Create Joints - # ================= - + # Get joint length jointEnd = mc.listRelatives(joint,c=True)[0] jointLen = mc.getAttr(jointEnd+'.t'+offsetAxis) jointOffset = jointLen/(numTwistJoints-1) - + # Create twist joints twistJoints = [] for i in range(numTwistJoints): - + alphaInd = glTools.utils.stringUtils.alphaIndex(i,upper=True) - + # Duplicate joint twistJoint = mc.duplicate(joint,po=True,n=prefix+'_twist'+alphaInd+'_jnt')[0] # Remove user attributes glTools.utils.attribute.deleteUserAttrs(twistJoint) # Parent to joint mc.parent(twistJoint,joint) - + # Position joint mc.setAttr(twistJoint+'.t'+offsetAxis,jointOffset*i) - + # Append joint list twistJoints.append(twistJoint) - + # ================= # - Return Result - # ================= - + return twistJoints def build( sourceJoint, @@ -83,19 +83,19 @@ def build( sourceJoint, prefix = '' ): ''' Build twist joint setup using an aimConstraint to calculate rotation. - @param sourceJoint: Twist base joint + @param sourceJoint: Twist base joint @type sourceJoint: str @param targetJoint: Twist target or end joint @type targetJoint: str - @param numJoint: Number of twist joints to generate + @param numJoint: Number of twist joints to generate @type numJoint: int - @param aimAxis: Axis along the length of the source joint + @param aimAxis: Axis along the length of the source joint @type aimAxis: list or tuple - @param upAxis: Upward facing axis of the source joint + @param upAxis: Upward facing axis of the source joint @type upAxis: list or tuple - @param baseToTip: Twist from the base to the tip + @param baseToTip: Twist from the base to the tip @type baseToTip: bool - @param enableCtrl: Enable the twist child joint as a control + @param enableCtrl: Enable the twist child joint as a control @type enableCtrl: bool @param prefix: Naming prefix for created nodes @type prefix: str @@ -103,68 +103,68 @@ def build( sourceJoint, # ========== # - Checks - # ========== - + # Define Axis Dictionary axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + if not mc.objExists(sourceJoint): raise Exception('Source joint "'+sourceJoint+'" does not exist!') if not mc.objExists(targetJoint): raise Exception('Target joint "'+targetJoint+'" does not exist!') - + if not axisDict.has_key(aimAxis): raise Exception('Invalid aim axis value! ("'+aimAxis+'")') if not axisDict.has_key(upAxis): raise Exception('Invalid up axis value! ("'+upAxis+'")') - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(sourceJoint) - + # ====================== # - Configure Modifier - # ====================== - + twistCtrlScale = 0.2 ctrlBuilder = glTools.tools.controlBuilder.ControlBuilder() - + # ======================= # - Create Twist Joints - # ======================= - + twistJoints = createTwistJoints( joint = sourceJoint, numTwistJoints = numJoints, offsetAxis = aimAxis[-1], prefix = prefix ) - + # Check baseToTip - Reverse list order if false if not baseToTip: twistJoints.reverse() - + # Create Joint Groups/Attributes/Tags twistJointGrps = [] twistFactor = 1.0/(len(twistJoints)-1) jntLen = glTools.utils.joint.length(sourceJoint) for i in range(len(twistJoints)): - + # Add Twist Control Attribute mc.addAttr(twistJoints[i],ln='twist',min=-1.0,max=1.0,dv=twistFactor*i) - + # Add Twist Joint Group twistJointGrp = glTools.utils.joint.group(twistJoints[i],indexStr='Twist') twistJointGrps.append(twistJointGrp) - + # Tag Bind Joint glTools.rig.utils.tagBindJoint(twistJoints[i],True) - + # Create Joint Control if enableCtrl: glTools.rig.utils.tagCtrl(twistJoints[i],'tertiary') ctrlBuilder.controlShape(transform=twistJoints[i],controlType='sphere',controlScale=twistCtrlScale) - + # Set Display Override if enableCtrl: glTools.utils.base.displayOverride(twistJoints[i],overrideEnable=1,overrideDisplay=0,overrideLOD=1) else: glTools.utils.base.displayOverride(twistJoints[i],overrideEnable=1,overrideDisplay=2,overrideLOD=0) - + # Create Twist Group twistGrp = mc.joint(n=prefix+'_twistJoint_grp') glTools.utils.base.displayOverride(twistGrp,overrideEnable=1,overrideDisplay=2,overrideLOD=1) @@ -174,15 +174,15 @@ def build( sourceJoint, mc.setAttr(twistGrp+'.radius',0) mc.parent(twistGrp,sourceJoint) mc.parent(twistJointGrps,twistGrp) - + # Connect Inverse Scale for twistJointGrp in twistJointGrps: mc.connectAttr(sourceJoint+'.scale',twistJointGrp+'.inverseScale',f=True) - + # ========================== # - Create Twist Aim Setup - # ========================== - + # Create Twist Aim Joint twistAimJnt = mc.duplicate(sourceJoint,po=True,n=prefix+'_twistAim_jnt')[0] # Remove user attributes @@ -191,7 +191,7 @@ def build( sourceJoint, mc.parent(twistAimJnt,sourceJoint) # Display Overrides glTools.utils.base.displayOverride(twistAimJnt,overrideEnable=1,overrideDisplay=2,overrideLOD=0) - + # Create Twist Aim Locator twistAimLoc = mc.group(em=True,n=prefix+'_twistAim_loc') mc.delete(mc.pointConstraint(targetJoint,twistAimLoc,mo=False)) @@ -199,7 +199,7 @@ def build( sourceJoint, mc.parent(twistAimLoc,targetJoint) # Display Overrides glTools.utils.base.displayOverride(twistAimLoc,overrideEnable=1,overrideDisplay=2,overrideLOD=0) - + # Create Twist Aim Constraint twistAimCon = mc.aimConstraint( targetJoint, twistAimJnt, @@ -208,36 +208,36 @@ def build( sourceJoint, wu=axisDict[upAxis], wuo=twistAimLoc, wut='objectrotation' )[0] - + # ======================== # - Connect Twist Joints - # ======================== - + twistMultNode = [] for i in range(len(twistJoints)): - + alphaInd = glTools.utils.stringUtils.alphaIndex(i,upper=True) twistMult = mc.createNode('multDoubleLinear',n=prefix+'_twist'+alphaInd+'_multDoubleLinear') mc.connectAttr(twistAimJnt+'.r'+aimAxis[-1],twistMult+'.input1',f=True) mc.connectAttr(twistJoints[i]+'.twist',twistMult+'.input2',f=True) mc.connectAttr(twistMult+'.output',twistJointGrps[i]+'.r'+aimAxis[-1],f=True) twistMultNode.append(twistMult) - + # ====================== # - Set Channel States - # ====================== - + chStateUtil = glTools.utils.channelState.ChannelState() chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=[twistGrp]) chStateUtil.setFlags([0,0,0,0,0,0,0,0,0,1],objectList=twistJoints) chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=twistJointGrps) chStateUtil.setFlags([2,2,2,1,1,1,2,2,2,1],objectList=[twistAimJnt]) chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=[twistAimLoc]) - + # ================= # - Return Result - # ================= - + result = {} result['twistGrp'] = twistGrp result['twistJoints'] = twistJoints @@ -259,21 +259,21 @@ def build_shoulder( shoulder, prefix = '' ): ''' Build shoudler twist using custom shoulderConstraint node - @param shoulder: Shoulder or upper arm joint + @param shoulder: Shoulder or upper arm joint @type shoulder: str - @param spine: Spine end joint + @param spine: Spine end joint @type spine: str - @param numJoint: Number of twist joints to generate + @param numJoint: Number of twist joints to generate @type numJoint: int - @param shoulderAim: Axis along the length of the shoulder joint + @param shoulderAim: Axis along the length of the shoulder joint @type shoulderAim: list or tuple - @param shoulderFront: Forward facing axis of the shoulder joint + @param shoulderFront: Forward facing axis of the shoulder joint @type shoulderFront: list or tuple - @param spineAim: Axis along the length of the spine joint + @param spineAim: Axis along the length of the spine joint @type spineAim: list or tuple - @param spineFront: Forward facing axis of the spine joint + @param spineFront: Forward facing axis of the spine joint @type spineFront: list or tuple - @param enableCtrl: Enable the twist child joint as a control + @param enableCtrl: Enable the twist child joint as a control @type enableCtrl: bool @param prefix: Naming prefix for created nodes @type prefix: str @@ -281,15 +281,15 @@ def build_shoulder( shoulder, # ========== # - Checks - # ========== - + # Define Axis Dictionary axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + if not mc.objExists(shoulder): raise Exception('Shoulder joint "'+shoulder+'" does not exist!') if not mc.objExists(spine): raise Exception('Spine joint "'+spine+'" does not exist!') - + if not axisDict.has_key(shoulderAim): raise Exception('Invalid shoulder aim axis value! ("'+shoulderAim+'")') if not axisDict.has_key(shoulderFront): @@ -298,33 +298,33 @@ def build_shoulder( shoulder, raise Exception('Invalid spine aim axis value! ("'+spineAim+'")') if not axisDict.has_key(spineFront): raise Exception('Invalid spine front axis value! ("'+spineFront+'")') - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(shoulder) - + # Check Plugin if not mc.pluginInfo('twistConstraint',q=True,l=True): try: mc.loadPlugin('twistConstraint') except: raise Exception('Unable to load plugin "twistConstraint"!') - + # ===================== # - Configure Control - # ===================== - + twistCtrlScale = 0.2 ctrlBuilder = glTools.tools.controlBuilder.ControlBuilder() - + # ======================= # - Create Twist Joints - # ======================= - + twistJoints = createTwistJoints( joint = shoulder, numTwistJoints = numJoints, offsetAxis = shoulderAim[-1], prefix = prefix ) - + # Reverse twist joint list twistJoints.reverse() - + # Create Twist Driver Joint mc.select(cl=True) shoulderTwist = mc.joint(n=prefix+'_twistDrive_jnt') @@ -332,34 +332,34 @@ def build_shoulder( shoulder, mc.delete(mc.parentConstraint(shoulder,shoulderTwistGrp)) mc.parent(shoulderTwistGrp,shoulder) glTools.utils.base.displayOverride(shoulderTwist,overrideEnable=1,overrideDisplay=2,overrideLOD=0) - + # Create Shoulder Twist Joints twistJointGrps = [] twistFactor = 1.0/(len(twistJoints)-1) jntLen = glTools.utils.joint.length(shoulder) for i in range(len(twistJoints)): - + # Add twist attribute mc.addAttr(twistJoints[i],ln='twist',min=-1.0,max=1.0,dv=twistFactor*i) - + # Add Twist Joint Group twistJointGrp = glTools.utils.joint.group(twistJoints[i],indexStr='Twist') twistJointGrps.append(twistJointGrp) - + # Tag Bind joint glTools.rig.utils.tagBindJoint(twistJoints[i],True) - + # Create Joint Control if enableCtrl: glTools.rig.utils.tagCtrl(twistJoints[i],'tertiary') ctrlBuilder.controlShape(transform=twistJoints[i],controlType='sphere',controlScale=twistCtrlScale) - + # Set Display Override if enableCtrl: glTools.utils.base.displayOverride(twistJoints[i],overrideEnable=1,overrideDisplay=0,overrideLOD=1) else: glTools.utils.base.displayOverride(twistJoints[i],overrideEnable=1,overrideDisplay=2,overrideLOD=0) - + # Create Twist Group twistGrp = mc.joint(n=prefix+'_twistJoint_grp') glTools.utils.base.displayOverride(twistGrp,overrideEnable=1,overrideLOD=1) @@ -369,18 +369,18 @@ def build_shoulder( shoulder, mc.setAttr(twistGrp+'.radius',0) mc.parent(twistGrp,shoulder) mc.parent(twistJointGrps,twistGrp) - + # Connect Inverse Scale for twistJointGrp in twistJointGrps: mc.connectAttr(shoulder+'.scale',twistJointGrp+'.inverseScale',f=True) - + # =============================== # - Create Shoulder Twist Setup - # =============================== - + # Create shoulderConstraint node shoulderCon = mc.createNode('shoulderConstraint',n=prefix+'_shoulderConstraint') - + # Set and connect shoulderConstraint attributes mc.connectAttr(shoulder+'.worldMatrix[0]',shoulderCon+'.shoulder',f=True) mc.connectAttr(spine+'.worldMatrix[0]',shoulderCon+'.spine',f=True) @@ -392,46 +392,46 @@ def build_shoulder( shoulder, mc.setAttr(shoulderCon+'.spineAim',*axisDict[spineAim]) mc.setAttr(shoulderCon+'.spineFront',*axisDict[spineFront]) mc.setAttr(shoulderCon+'.raisedAngleOffset',0) - + # Connect to shoudler twist joint mc.connectAttr(shoulderCon+'.outRotate',shoulderTwist+'.rotate',f=True) - + # Correct initial offset twistOffset = mc.getAttr(shoulderTwist+'.r'+shoulderAim[-1]) mc.setAttr(shoulderTwist+'.jo'+shoulderAim[-1],twistOffset) - + # ======================== # - Connect Twist Joints - # ======================== - + twistMultNode = [] for i in range(len(twistJoints)): - + alphaInd = glTools.utils.stringUtils.alphaIndex(i,upper=True) twistMult = mc.createNode('multDoubleLinear',n=prefix+'_twist'+alphaInd+'_multDoubleLinear') mc.connectAttr(shoulderTwist+'.r'+shoulderAim[-1],twistMult+'.input1',f=True) mc.connectAttr(twistJoints[i]+'.twist',twistMult+'.input2',f=True) mc.connectAttr(twistMult+'.output',twistJointGrps[i]+'.r'+shoulderAim[-1],f=True) twistMultNode.append(twistMult) - + # Reverse twist joint list twistJoints.reverse() - + # ====================== # - Set Channel States - # ====================== - + chStateUtil = glTools.utils.channelState.ChannelState() chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=[twistGrp]) chStateUtil.setFlags([0,0,0,0,0,0,0,0,0,1],objectList=twistJoints) chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=twistJointGrps) chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=[shoulderTwistGrp]) chStateUtil.setFlags([2,2,2,1,1,1,2,2,2,1],objectList=[shoulderTwist]) - + # ================= # - Return Result - # ================= - + result = {} result['twistGrp'] = twistGrp result['twistJoints'] = twistJoints @@ -452,21 +452,21 @@ def build_hip( hip, prefix = '' ): ''' Build hip twist using custom hipConstraint node - @param hip: Hip or upper leg joint + @param hip: Hip or upper leg joint @type hip: str - @param pelvis: Pelvis joint + @param pelvis: Pelvis joint @type pelvis: str - @param numJoint: Number of twist joints to generate + @param numJoint: Number of twist joints to generate @type numJoint: int - @param hipAim: Axis along the length of the hip/leg joint + @param hipAim: Axis along the length of the hip/leg joint @type hipAim: list or tuple - @param hipFront: Forward facing axis of the hip/leg joint + @param hipFront: Forward facing axis of the hip/leg joint @type hipFront: list or tuple - @param pelvisAim: Axis along the length of the pelvis joint + @param pelvisAim: Axis along the length of the pelvis joint @type pelvisAim: list or tuple - @param pelvisFront: Forward facing axis of the pelvis joint + @param pelvisFront: Forward facing axis of the pelvis joint @type pelvisFront: list or tuple - @param enableCtrl: Enable the twist child joint as a control + @param enableCtrl: Enable the twist child joint as a control @type enableCtrl: bool @param prefix: Naming prefix for created nodes @type prefix: str @@ -474,15 +474,15 @@ def build_hip( hip, # ========== # - Checks - # ========== - + # Define Axis Dictionary axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + if not mc.objExists(hip): raise Exception('Hip joint "'+hip+'" does not exist!') if not mc.objExists(pelvis): raise Exception('Pelvis joint "'+pelvis+'" does not exist!') - + if not axisDict.has_key(hipAim): raise Exception('Invalid hip aim axis value! ("'+hipAim+'")') if not axisDict.has_key(hipFront): @@ -491,32 +491,32 @@ def build_hip( hip, raise Exception('Invalid pelvis aim axis value! ("'+pelvisAim+'")') if not axisDict.has_key(pelvisFront): raise Exception('Invalid pelvis front axis value! ("'+pelvisFront+'")') - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(hip) - + # Check Plugin if not mc.pluginInfo('twistConstraint',q=True,l=True): try: mc.loadPlugin('twistConstraint') except: raise Exception('Unable to load plugin "twistConstraint"!') - + # ====================== # - Configure Modifier - # ====================== - + twistCtrlScale = 0.2 ctrlBuilder = glTools.tools.controlBuilder.ControlBuilder() - + # ======================= # - Create Twist Joints - # ======================= - + twistJoints = createTwistJoints( joint = hip, numTwistJoints = numJoints, offsetAxis = hipAim[-1], prefix = prefix ) # Reverse twist joint list twistJoints.reverse() - + # Create Twist Driver Joint mc.select(cl=True) hipTwist = mc.joint(n=prefix+'_twistDrive_jnt') @@ -524,34 +524,34 @@ def build_hip( hip, mc.delete(mc.parentConstraint(hip,hipTwistGrp)) mc.parent(hipTwistGrp,hip) glTools.utils.base.displayOverride(hipTwist,overrideEnable=1,overrideDisplay=2,overrideLOD=0) - + # Create Hip Twist Joints twistJointGrps = [] twistFactor = 1.0/(len(twistJoints)-1) jntLen = glTools.utils.joint.length(hip) for i in range(len(twistJoints)): - + # Add Twist Control Attribute mc.addAttr(twistJoints[i],ln='twist',min=-1.0,max=1.0,dv=twistFactor*i) - + # Add Twist Joint Group twistJointGrp = glTools.utils.joint.group(twistJoints[i],indexStr='Twist') twistJointGrps.append(twistJointGrp) - + # Tag Bind Joint glTools.rig.utils.tagBindJoint(twistJoints[i],True) - + # Create Joint Control if enableCtrl: glTools.rig.utils.tagCtrl(twistJoints[i],'tertiary') ctrlBuilder.controlShape(transform=twistJoints[i],controlType='sphere',controlScale=twistCtrlScale) - + # Set Display Override if enableCtrl: glTools.utils.base.displayOverride(twistJoints[i],overrideEnable=1,overrideDisplay=0,overrideLOD=1) else: glTools.utils.base.displayOverride(twistJoints[i],overrideEnable=1,overrideDisplay=2,overrideLOD=0) - + # Create Twist Group twistGrp = mc.joint(n=prefix+'_twistJoint_grp') glTools.utils.base.displayOverride(twistGrp,overrideEnable=1,overrideLOD=1) @@ -561,18 +561,18 @@ def build_hip( hip, mc.setAttr(twistGrp+'.radius',0) mc.parent(twistGrp,hip) mc.parent(twistJointGrps,twistGrp) - + # Connect Inverse Scale for twistJointGrp in twistJointGrps: mc.connectAttr(hip+'.scale',twistJointGrp+'.inverseScale',f=True) - + # ========================== # - Create Hip Twist Setup - # ========================== - + # Create hipConstraint node hipCon = mc.createNode('hipConstraint',n=prefix+'_hipConstraint') - + # Set and connect hipConstraint attributes mc.connectAttr(hip+'.worldMatrix[0]',hipCon+'.hip',f=True) mc.connectAttr(pelvis+'.worldMatrix[0]',hipCon+'.pelvis',f=True) @@ -583,46 +583,46 @@ def build_hip( hip, mc.setAttr(hipCon+'.hipFront',*axisDict[hipFront]) mc.setAttr(hipCon+'.pelvisAim',*axisDict[pelvisAim]) mc.setAttr(hipCon+'.pelvisFront',*axisDict[pelvisFront]) - + # Connect to hip twist joint mc.connectAttr(hipCon+'.outRotate',hipTwist+'.rotate',f=True) - + # Correct initial offset twistOffset = mc.getAttr(hipTwist+'.r'+hipAim[-1]) mc.setAttr(hipTwist+'.jo'+hipAim[-1],twistOffset) - + # ======================== # - Connect Twist Joints - # ======================== - + twistMultNode = [] for i in range(len(twistJoints)): - + alphaInd = glTools.utils.stringUtils.alphaIndex(i,upper=True) twistMult = mc.createNode('multDoubleLinear',n=prefix+'_twist'+alphaInd+'_multDoubleLinear') mc.connectAttr(hipTwist+'.r'+hipAim[-1],twistMult+'.input1',f=True) mc.connectAttr(twistJoints[i]+'.twist',twistMult+'.input2',f=True) mc.connectAttr(twistMult+'.output',twistJointGrps[i]+'.r'+hipAim[-1],f=True) twistMultNode.append(twistMult) - + # Reverse twist joint list twistJoints.reverse() - + # ====================== # - Set Channel States - # ====================== - + chStateUtil = glTools.utils.channelState.ChannelState() chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=[twistGrp]) chStateUtil.setFlags([0,0,0,0,0,0,0,0,0,1],objectList=twistJoints) chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=twistJointGrps) chStateUtil.setFlags([2,2,2,2,2,2,2,2,2,1],objectList=[hipTwistGrp]) chStateUtil.setFlags([2,2,2,1,1,1,2,2,2,1],objectList=[hipTwist]) - + # ================= # - Return Result - # ================= - + result = {} result['twistGrp'] = twistGrp result['twistJoints'] = twistJoints diff --git a/rig/ui.py b/rig/ui.py index 642b047..940541e 100644 --- a/rig/ui.py +++ b/rig/ui.py @@ -14,36 +14,36 @@ def importDataUI(): ''' rig = Rig() dataPath = rig.setDataPath() - + # Build Window window = rig.IMPORT_DATA_UI if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='RIG: Import Data') - + # Layout FL = mc.formLayout() - + # UI Elements dataPathTBG = mc.textFieldButtonGrp(rig.IMPORT_PATH_TBG,label='Data Path',buttonLabel='...',text=dataPath) filterTFG = mc.textFieldGrp(rig.IMPORT_FILTER_TFG,label='Filter',text='') fileListTSL = mc.textScrollList(rig.IMPORT_LIST_TSL,ams=True) importB = mc.button('rigImportData_importB',label='Import',c='glTools.rig.ui.importDataFromUI()') cancelB = mc.button('rigImportData_cancelB',label='Close',c='mc.deleteUI("'+window+'")') - + # UI Callbacks mc.textFieldButtonGrp(dataPathTBG,e=True,bc='glTools.ui.utils.importFolderBrowser("'+dataPathTBG+'")') mc.textFieldButtonGrp(dataPathTBG,e=True,cc='glTools.ui.utils.loadFileList("'+fileListTSL+'","'+mc.textFieldButtonGrp(dataPathTBG,q=True,text=True)+'",filesOnly=True,filterStr=".pkl")') - + # Form Layout mc.formLayout(FL,e=True,af=[(dataPathTBG,'top',5),(dataPathTBG,'left',5),(dataPathTBG,'right',5)]) mc.formLayout(FL,e=True,ac=[(filterTFG,'top',5,dataPathTBG)],af=[(filterTFG,'left',5),(filterTFG,'right',5)]) mc.formLayout(FL,e=True,ac=[(fileListTSL,'top',5,filterTFG),(fileListTSL,'bottom',5,importB)],af=[(fileListTSL,'left',5),(fileListTSL,'right',5)]) mc.formLayout(FL,e=True,ac=[(importB,'bottom',5,cancelB)],af=[(importB,'left',5),(importB,'right',5)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Load Data files if dataPath: glTools.ui.utils.loadFileList(fileListTSL,dataPath,filesOnly=True,filterStr='.pkl',sort=True) - + # Show Window mc.showWindow(window) @@ -52,26 +52,26 @@ def importDataFromUI(): Import selected Rig data from UI. ''' rig = Rig() - + # Check Window window = rig.IMPORT_DATA_UI if not mc.window(window,q=True,ex=1): raise Exception('Rig import data UI does not exist!') - + # Get Data Path dataPath = mc.textFieldButtonGrp(rig.IMPORT_PATH_TBG,q=True,text=True) # Get Data Selection fileList = mc.textScrollList(rig.IMPORT_LIST_TSL,q=True,si=True) - + # Import Selected Data for dataFile in fileList: - + # Build Data Object data = Data().load(os.path.join(dataPath,dataFile)) # Rebuild Data try: data.rebuild() except: print('IMPORT DATA FAILED: Unable to load data from file "'+dataFile+'"!') - + # Return Result return fileList @@ -81,36 +81,36 @@ def exportDataUI(): ''' rig = Rig() dataPath = rig.setDataPath() - + # Build Window window = rig.EXPORT_DATA_UI if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='RIG: Export Data') - + # Layout FL = mc.formLayout() - + # UI Elements dataPathTBG = mc.textFieldButtonGrp(rig.EXPORT_PATH_TBG,label='Data Path',buttonLabel='...',text=dataPath) dataListTSL = mc.textScrollList(rig.EXPORT_LIST_TSL,ams=True) reloadB = mc.button('rigExportData_reloadB',label='Reload',c='glTools.rig.ui.reloadDataUIList()') exportB = mc.button('rigExportData_exportB',label='Export',c='glTools.rig.ui.exportDataFromUI()') cancelB = mc.button('rigExportData_cancelB',label='Close',c='mc.deleteUI("'+window+'")') - + # UI Callbacks mc.textFieldButtonGrp(dataPathTBG,e=True,bc='glTools.ui.utils.exportFolderBrowser("'+dataPathTBG+'")') mc.textFieldButtonGrp(dataPathTBG,e=True,cc='glTools.ui.utils.loadFileList("'+dataListTSL+'","'+mc.textFieldButtonGrp(dataPathTBG,q=True,text=True)+'",filesOnly=True,filterStr=".pkl")') - + # Form Layout mc.formLayout(FL,e=True,af=[(dataPathTBG,'top',5),(dataPathTBG,'left',5),(dataPathTBG,'right',5)]) mc.formLayout(FL,e=True,ac=[(dataListTSL,'top',5,dataPathTBG),(dataListTSL,'bottom',5,reloadB)],af=[(dataListTSL,'left',5),(dataListTSL,'right',5)]) mc.formLayout(FL,e=True,ac=[(reloadB,'bottom',5,exportB)],af=[(reloadB,'left',5),(reloadB,'right',5)]) mc.formLayout(FL,e=True,ac=[(exportB,'bottom',5,cancelB)],af=[(exportB,'left',5),(exportB,'right',5)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Load Deformer List reloadDataUIList() - + # Show Window mc.showWindow(window) @@ -119,21 +119,21 @@ def exportDataFromUI(): Export selected Rig data from UI. ''' rig = Rig() - + # Check Window window = rig.EXPORT_DATA_UI if not mc.window(window,q=True,ex=1): raise Exception('Rig export data UI does not exist!') - + # Get Data Path dataPath = mc.textFieldButtonGrp(rig.EXPORT_PATH_TBG,q=True,text=True) # Get Data Selection deformerList = mc.textScrollList(rig.EXPORT_LIST_TSL,q=True,si=True) - + # Import Selected Data rig.rigData['dataPath'] = dataPath rig.exportData(exportDeformerList=deformerList,exportSetList=None,exportCrvList=None,force=True) - + # Return Result return deformerList @@ -142,22 +142,22 @@ def reloadDataUIList(): List deformers in export data UI. ''' rig = Rig() - + # Check Window window = rig.EXPORT_DATA_UI if not mc.window(window,q=True,ex=1): return [] - + # Get Deformers from Selection sel = mc.ls(sl=1,dag=True) if sel: deformerList = mc.ls(mc.listHistory(sel),type='geometryFilter') else: deformerList = mc.ls(type='geometryFilter') deformerList = [i for i in deformerList if mc.objectType(i) != 'tweak'] deformerList = sorted(list(set(deformerList))) - + # Update List mc.textScrollList(rig.EXPORT_LIST_TSL,e=True,ra=True) for deformer in deformerList: mc.textScrollList(rig.EXPORT_LIST_TSL,e=True,a=deformer) - + # Return Result return deformerList diff --git a/rig/utils.py b/rig/utils.py index 43fe573..0765542 100644 --- a/rig/utils.py +++ b/rig/utils.py @@ -41,29 +41,29 @@ def tagCtrl(control,ctrlLod='primary',module=None,category=None): # ========== # - Checks - # ========== - + # Check Control if not mc.objExists(control): raise Exception('Control object "'+control+'" does not exist!') - + # Check Control LOD ctrlLodList = ['primary','secondary','tertiary','allTrans','face','costume','hair','prop','misc'] if not ctrlLod in ctrlLodList: raise Exception('Invalid control LOD "'+ctrlLod+'"!') ctrlLodIndex = ctrlLodList.index(ctrlLod) - + # =================== # - Tag Control LOD - # =================== - + lodAttr = 'ctrlLod' if not mc.objExists(control+'.'+lodAttr): mc.addAttr(control,ln=lodAttr,at='enum',en=':'.join(ctrlLodList)) mc.setAttr(control+'.'+lodAttr,ctrlLodIndex) - + # ====================== # - Tag Control Module - # ====================== - + if module: moduleAttr = 'ctrlModule' if not mc.objExists(control+'.'+moduleAttr): @@ -72,34 +72,34 @@ def tagCtrl(control,ctrlLod='primary',module=None,category=None): mc.setAttr(control+'.'+moduleAttr,l=False) mc.setAttr(control+'.'+moduleAttr,module,type='string') mc.setAttr(control+'.'+moduleAttr,l=True) - + # ======================== # - Tag Control Category - # ======================== - + if category: categoryAttr = 'ctrlCategory' if not mc.objExists(control+'.'+categoryAttr): mc.addAttr(control,ln=categoryAttr,dt='string') mc.setAttr(control+'.'+categoryAttr,category,type='string') mc.setAttr(control+'.'+categoryAttr,l=True) - + # ================= # - Clean Control - # ================= - + # Set Rotate Order Keyable try: mc.setAttr(control+'.ro',cb=True) except: pass - + # Hide Joint Attrs if mc.objExists(control+'.radius'): mc.setAttr(control+'.radius',k=False,cb=False) if mc.objExists(control+'.liw'): mc.setAttr(control+'.liw',k=False,cb=False) - + # ================= # - Return Result - # ================= - + return control def tagBindJoint(joint,bind=True): @@ -113,23 +113,23 @@ def tagBindJoint(joint,bind=True): # ========== # - Checks - # ========== - + if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') if mc.objectType(joint) != 'joint': raise Exception('Object "'+joint+'" is not a valid joint!') - + # ============= # - Tag Joint - # ============= - + if not mc.objExists(joint+'.bindJoint'): mc.addAttr(joint,ln='bindJoint',at='bool',dv=True) - + # =============== # - Clean Joint - # =============== - + if mc.objExists(joint+'.radius'): mc.setAttr(joint+'.radius',k=False,cb=False) if mc.objExists(joint+'.liw'): @@ -154,45 +154,45 @@ def offsetGroup( ctrl, # ========== # - Checks - # ========== - + # Control if not mc.objExists(ctrl): raise Exception('Control "'+ctrl+'" does not exist!') - + # Pivot if not pivot: pivot = ctrl if not mc.objExists(pivot): raise Exception('Pivot "'+pivot+'" does not exist!') - + # Orient To if orientTo: if not mc.objExists(orientTo): raise Exception('Orient target "'+orientTo+'" does not exist!') - + # Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(ctrl) - + # ====================== # - Build Offset Group - # ====================== - + # Create Offset Group offsetGrp = mc.group(em=True,n=prefix+'_offsetGrp') - + # Set Pivot piv = mc.xform(pivot,q=True,ws=True,rp=True) mc.xform(offsetGrp,ws=True,piv=piv) - + # Orient Offset Group if orientTo: mc.delete(mc.orientConstraint(orientTo,offsetGrp)) - + # Parent Control mc.parent(ctrl,offsetGrp) - + # ================= # - Return Result - # ================= - + return offsetGrp def negateTransform( ctrl, @@ -219,59 +219,59 @@ def negateTransform( ctrl, # ========== # - Checks - # ========== - + # Control if not mc.objExists(ctrl): raise Exception('Control "'+ctrl+'" does not exist!') - + # Negate Group if negateGrp: if not mc.objExists(negateGrp): raise Exception('Control "'+ctrl+'" does not exist!') - + # Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(ctrl) - + # ====================== # - Build Negate Group - # ====================== - + if not negateGrp: negateGrp = mc.duplicate(ctrl,po=True,n=prefix+'_negate')[0] glTools.utils.attribute.deleteUserAttrs(negateGrp) mc.parent(ctrl,negateGrp) - + # ====================== # - Build Negate Nodes - # ====================== - + if translate: tNegate = mc.createNode('multiplyDivide',n=prefix+'_translateNegate_multiplyDivide') mc.connectAttr(ctrl+'.t',tNegate+'.input1',f=True) mc.setAttr(tNegate+'.input2',-1,-1,-1) mc.connectAttr(tNegate+'.output',negateGrp+'.t',f=True) - + if rotate: rNegate = mc.createNode('multiplyDivide',n=prefix+'_rotateNegate_multiplyDivide') mc.connectAttr(ctrl+'.r',rNegate+'.input1',f=True) mc.setAttr(rNegate+'.input2',-1,-1,-1) mc.connectAttr(rNegate+'.output',negateGrp+'.r',f=True) - + # Reverse Rotate Order rotOrderMap = [5,3,4,1,2,0] mc.setAttr(negateGrp+'.ro',rotOrderMap[mc.getAttr(ctrl+'.ro')]) - + if scale: sNegate = mc.createNode('multiplyDivide',n=prefix+'_scaleNegate_multiplyDivide') mc.connectAttr(ctrl+'.s',sNegate+'.input2',f=True) mc.setAttr(sNegate+'.input1',1,1,1) mc.setAttr(sNegate+'.operation',2) # Divide mc.connectAttr(sNegate+'.output',negateGrp+'.s',f=True) - + # ================= # - Return Result - # ================= - + return negateGrp def lockJointAttrs(jointList=[]): @@ -283,27 +283,27 @@ def lockJointAttrs(jointList=[]): # ========== # - Checks - # ========== - + if not jointList: jointList = mc.ls(type='joint') or [] - + # ========================= # - Lock Joint Attributes - # ========================= - + for joint in jointList: - + # Lock Joint Orient if mc.getAttr(joint+'.jointOrient',se=True): mc.setAttr(joint+'.jointOrient',l=True) - + # Lock Preferred Angle Attr if mc.getAttr(joint+'.preferredAngle',se=True): mc.setAttr(joint+'.preferredAngle',l=True) - + # ================= # - Return Result - # ================= - + return jointList def setToDefault(ctrl): @@ -315,31 +315,31 @@ def setToDefault(ctrl): # ================= # - Check Control - # ================= - + if not mc.objExists(ctrl): raise Exception('Control "'+ctrl+'" does not exist!') - + # ============================== # - Define Transform Constants - # ============================== - + tAttr = ['tx','ty','tz'] rAttr = ['rx','ry','rz'] sAttr = ['sx','sy','sz'] - + # ======================= # - Get User Attributes - # ======================= - + udAttr = mc.listAttr(ctrl,ud=True,k=True) if not udAttr: udAttr = [] cbAttr = mc.listAttr(ctrl,ud=True,cb=True) if not cbAttr: cbAttr = [] - + # ===================== # - Reset to Defaults - # ===================== - + for attr in tAttr: if mc.getAttr(ctrl+'.'+attr,se=True): mc.setAttr(ctrl+'.'+attr,0.0) @@ -375,22 +375,22 @@ def isCtrlZeroed(ctrl,tol=0.00001,skipLocked=True,skipNonkeyable=False,verbose=F # Check Control if not mc.objExists(ctrl): raise Exception('Control "'+ctrl+'" does not exist!') - + # Define standard transform controls tAttr = ['tx','ty','tz'] rAttr = ['rx','ry','rz'] sAttr = ['sx','sy','sz'] - + # Get user defined attrs udAttr = mc.listAttr(ctrl,ud=True,k=True) if not udAttr: udAttr = [] cbAttr = mc.listAttr(ctrl,ud=True,cb=True) if not cbAttr: cbAttr = [] - + # ============================ # - Check Attribute Defaults - # ============================ - + # Translate for attr in tAttr: if not mc.getAttr(ctrl+'.'+attr,se=True) and skipLocked: continue @@ -398,7 +398,7 @@ def isCtrlZeroed(ctrl,tol=0.00001,skipLocked=True,skipNonkeyable=False,verbose=F if not glTools.utils.mathUtils.isEqual(mc.getAttr(ctrl+'.'+attr),0.0,tol): if verbose: print ('Attribute "'+ctrl+'.'+attr+'" is not zeroed ('+str(mc.getAttr(ctrl+'.'+attr))+')!') return False - + # Rotate for attr in rAttr: if not mc.getAttr(ctrl+'.'+attr,se=True) and skipLocked: continue @@ -406,7 +406,7 @@ def isCtrlZeroed(ctrl,tol=0.00001,skipLocked=True,skipNonkeyable=False,verbose=F if not glTools.utils.mathUtils.isEqual(mc.getAttr(ctrl+'.'+attr),0.0,tol): if verbose: print ('Attribute "'+ctrl+'.'+attr+'" is not zeroed ('+str(mc.getAttr(ctrl+'.'+attr))+')!') return False - + # Scale for attr in sAttr: if not mc.getAttr(ctrl+'.'+attr,se=True) and skipLocked: continue @@ -414,7 +414,7 @@ def isCtrlZeroed(ctrl,tol=0.00001,skipLocked=True,skipNonkeyable=False,verbose=F if not glTools.utils.mathUtils.isEqual(mc.getAttr(ctrl+'.'+attr),1.0,tol): if verbose: print ('Attribute "'+ctrl+'.'+attr+'" is not zeroed ('+str(mc.getAttr(ctrl+'.'+attr))+')!') return False - + # User Defined (Keyable) for attr in udAttr: if not mc.getAttr(ctrl+'.'+attr,se=True) and skipLocked: continue @@ -422,7 +422,7 @@ def isCtrlZeroed(ctrl,tol=0.00001,skipLocked=True,skipNonkeyable=False,verbose=F if not glTools.utils.mathUtils.isEqual(mc.getAttr(ctrl+'.'+attr),dv,tol): if verbose: print ('Attribute "'+ctrl+'.'+attr+'" is not zeroed ('+str(mc.getAttr(ctrl+'.'+attr))+')!') return False - + # Channel Box (Non-Keyable) if not skipNonkeyable: for attr in cbAttr: @@ -431,11 +431,11 @@ def isCtrlZeroed(ctrl,tol=0.00001,skipLocked=True,skipNonkeyable=False,verbose=F if not glTools.utils.mathUtils.isEqual(mc.getAttr(ctrl+'.'+attr),dv,tol): if verbose: print ('Attribute "'+ctrl+'.'+attr+'" is not zeroed ('+str(mc.getAttr(ctrl+'.'+attr))+')!') return False - + # ================= # - Return Result - # ================= - + return True def poleVectorPosition(startJoint,midJoint,endJoint,distance=1.0): @@ -457,24 +457,24 @@ def poleVectorPosition(startJoint,midJoint,endJoint,distance=1.0): raise Exception('Middle joint "'+midJoint+'" does not exist!') if not mc.objExists(endJoint): raise Exception('End joint "'+endJoint+'" does not exist!') - + # Get joint positions stPt = glTools.utils.base.getPosition(startJoint) mdPt = glTools.utils.base.getPosition(midJoint) enPt = glTools.utils.base.getPosition(endJoint) - + # Get Joint lengths stLen = glTools.utils.joint.length(startJoint) mdLen = glTools.utils.joint.length(midJoint) pvLen = glTools.utils.mathUtils.distanceBetween(stPt,enPt) * distance wt = stLen/(stLen+mdLen) - + # Calculate Center Point ctPt = glTools.utils.mathUtils.averagePosition(stPt,enPt,wt) - + # Calculate Pole Vector Offset pvOffset = glTools.utils.mathUtils.offsetVector(ctPt,mdPt) - + # Check Center Point Offset if glTools.utils.mathUtils.mag(pvOffset) < 0.001: stRotate = [i/abs(i) if (abs(i)>0) else 0 for i in mc.getAttr(startJoint+'.preferredAngle')[0]] @@ -487,13 +487,13 @@ def poleVectorPosition(startJoint,midJoint,endJoint,distance=1.0): pvOffset = glTools.utils.mathUtils.offsetVector(cnPt,mdPt) mc.setAttr(startJoint+'.r',0,0,0) mc.setAttr(midJoint+'.r',0,0,0) - + # Calculate poleVector poleVec = glTools.utils.mathUtils.normalizeVector(pvOffset) - + # Calculate poleVector position pvPt = [ctPt[0]+(poleVec[0]*pvLen),ctPt[1]+(poleVec[1]*pvLen),ctPt[2]+(poleVec[2]*pvLen)] - + # Return result return pvPt @@ -536,22 +536,22 @@ def ikFkBlend( blendJoints, attr = blendAttr.split('.')[-1] if not mc.objExists(ctrl): raise Exception('Blend control "'+ctrl+'" does not exist!') mc.addAttr(ctrl,ln=attr,min=0,max=1,dv=0,k=True) - + # Check joint chains if (len(blendJoints) != len(fkJoints)) or (len(blendJoints) != len(ikJoints)): raise Exception('Chain length mis-match!!') - + # Check Skip End if skipEnd: blendJoints = blendJoints[:-1] fkJoints = fkJoints[:-1] ikJoints = ikJoints[:-1] - + # Blend Joint Translate/Rotate/Scale tBlendNode = '' rBlendNode = '' sBlendNode = '' - + # Blend Attribute Reverse blendRevNode = '' if useConstraints: @@ -559,46 +559,46 @@ def ikFkBlend( blendJoints, mc.connectAttr(blendAttr,blendRevNode+'.inputX',f=True) mc.connectAttr(blendAttr,blendRevNode+'.inputY',f=True) mc.connectAttr(blendAttr,blendRevNode+'.inputZ',f=True) - + for i in range(len(blendJoints)): - + # Naming index ind = glTools.utils.stringUtils.alphaIndex(i,upper=True) - + # Translate if translate: - + # Create blend node tBlendNode = mc.createNode('blendColors',n=prefix+'_tr'+ind+'_blendColors') - + # Connect blend node mc.connectAttr(fkJoints[i]+'.tx',tBlendNode+'.color1R',f=True) mc.connectAttr(fkJoints[i]+'.ty',tBlendNode+'.color1G',f=True) mc.connectAttr(fkJoints[i]+'.tz',tBlendNode+'.color1B',f=True) mc.setAttr(tBlendNode+'.color2',0,0,0) mc.connectAttr(blendAttr,tBlendNode+'.blender',f=True) - + # Connect to joint mc.connectAttr(tBlendNode+'.outputR',blendJoints[i]+'.tx',f=True) mc.connectAttr(tBlendNode+'.outputG',blendJoints[i]+'.ty',f=True) mc.connectAttr(tBlendNode+'.outputB',blendJoints[i]+'.tz',f=True) - + # Rotate if rotate: - + if useConstraints: - + # Create orientConstraint node rBlendNode = mc.orientConstraint(fkJoints[i],ikJoints[i],blendJoints[i],n=prefix+'_rt'+ind+'_orientConstraint')[0] rBlendAlias = mc.orientConstraint(rBlendNode,q=True,wal=True) mc.connectAttr(blendAttr,rBlendNode+'.'+rBlendAlias[0],f=True) mc.connectAttr(blendRevNode+'.outputY',rBlendNode+'.'+rBlendAlias[1],f=True) - + else: - + # Create blend node rBlendNode = mc.createNode('blendColors',n=prefix+'_rt'+ind+'_blendColors') - + # Connect blend node mc.connectAttr(fkJoints[i]+'.rx',rBlendNode+'.color1R',f=True) mc.connectAttr(fkJoints[i]+'.ry',rBlendNode+'.color1G',f=True) @@ -607,28 +607,28 @@ def ikFkBlend( blendJoints, mc.connectAttr(ikJoints[i]+'.ry',rBlendNode+'.color2G',f=True) mc.connectAttr(ikJoints[i]+'.rz',rBlendNode+'.color2B',f=True) mc.connectAttr(blendAttr,rBlendNode+'.blender',f=True) - + # Connect to joint mc.connectAttr(rBlendNode+'.outputR',blendJoints[i]+'.rx',f=True) mc.connectAttr(rBlendNode+'.outputG',blendJoints[i]+'.ry',f=True) mc.connectAttr(rBlendNode+'.outputB',blendJoints[i]+'.rz',f=True) - + # Scale if scale: - + #if useConstraints: - # + # # # Create scaleConstraint node # sBlendNode = mc.scaleConstraint(fkJoints[i],ikJoints[i],blendJoints[i],n=prefix+'_sc'+ind+'_scaleConstraint')[0] # sBlendAlias = mc.scaleConstraint(sBlendNode,q=True,wal=True) # mc.connectAttr(blendAttr,sBlendNode+'.'+sBlendAlias[0],f=True) # mc.connectAttr(blendRevNode+'.outputZ',sBlendNode+'.'+sBlendAlias[1],f=True) - # + # #else: - + # Create blend node sBlendNode = mc.createNode('blendColors',n=prefix+'_sc'+ind+'_blendColors') - + # Connect blend node mc.connectAttr(fkJoints[i]+'.sx',sBlendNode+'.color1R',f=True) mc.connectAttr(fkJoints[i]+'.sy',sBlendNode+'.color1G',f=True) @@ -637,12 +637,12 @@ def ikFkBlend( blendJoints, mc.connectAttr(ikJoints[i]+'.sy',sBlendNode+'.color2G',f=True) mc.connectAttr(ikJoints[i]+'.sz',sBlendNode+'.color2B',f=True) mc.connectAttr(blendAttr,sBlendNode+'.blender',f=True) - + # Connect to joint mc.connectAttr(sBlendNode+'.outputR',blendJoints[i]+'.sx',f=True) mc.connectAttr(sBlendNode+'.outputG',blendJoints[i]+'.sy',f=True) mc.connectAttr(sBlendNode+'.outputB',blendJoints[i]+'.sz',f=True) - + # Return Result return [tBlendNode,rBlendNode,sBlendNode] @@ -652,14 +652,14 @@ def getAllCtrls(all='all'): # Check all exists if not mc.objExists(all): raise Exception('All node '+all+' does not exist!') - + # Get comtrols list return mc.getAttr(all+'.allCtrls') def setAllCtrls(all='all',ctrlList=[],append=False): ''' Add a multi string attribute to a specified node to store a list of all rig control names - @param all: The node to add the control name list atribute to. Generally, the top node of the rig. ("all") + @param all: The node to add the control name list atribute to. Generally, the top node of the rig. ("all") @type all: str @param ctrlList: The list of control names to add to the multi string attribute. @type ctrlList: list @@ -669,17 +669,17 @@ def setAllCtrls(all='all',ctrlList=[],append=False): # Check all exists if not mc.objExists(all): raise Exception('All node '+all+' does not exist!') - + # Check All Controls Attribute if not mc.objExists(all+'.allCtrls'): mc.addAttr(all,ln='allCtrls',dt='string',multi=True,hidden=True) - + # Check append if append: allCtrls = getAllCtrls(all) allCtrls.extend(ctrlList) ctrlList = allCtrls - + # Set all controls attribute array values for i in range(len(ctrlList)): mc.setAttr(all+'.allCtrls['+str(i)+']',ctrlList[i],type='string') @@ -693,28 +693,28 @@ def connectControlVisOld(ctrlLodAttr=['all.primaryCtrlVis','all.secondaryCtrlVis ''' # Get Control LOD node ctrlLodNode = mc.ls(ctrlLodAttr[0],o=True)[0] - + # Get Control List ctrlList = mc.ls('*.ctrlLod',o=True) ctrlList.sort() - + # Connect Control Visibility for ctrl in ctrlList: - + # Get Control Shapes ctrlShapes = mc.listRelatives(ctrl,s=True,ni=True,pa=True,type='nurbsCurve') if not ctrlShapes: continue - + # Get Control Lod ctrlLod = mc.getAttr(ctrl+'.ctrlLod') - + # Connect to Visibility for ctrlShape in ctrlShapes: - + # Check Existing Connections shapeVisConn = mc.listConnections(ctrlShape+'.v',s=True,d=False,skipConversionNodes=True) if shapeVisConn and not (shapeVisConn[0] == ctrlLodNode): - + # Double check intermediate visibility connection # !! This is a little more messy than I would like. But will keep until it breaks !! - (10/15/12) shapeVisConnCheck = mc.listConnections(shapeVisConn[0],s=True,d=False,skipConversionNodes=True,p=True) @@ -722,20 +722,20 @@ def connectControlVisOld(ctrlLodAttr=['all.primaryCtrlVis','all.secondaryCtrlVis for shapeVisNodeCheck in shapeVisConnCheck: if ctrlLodAttr.count(shapeVisNodeCheck): mc.delete(shapeVisConn[0]) - + # Get connections with plug information shapeVisConn = mc.listConnections(ctrlShape+'.v',s=True,d=False,p=True) - + # Merge visibility inputs shapePrefix = glTools.utils.stringUtils.stripSuffix(ctrlShape) shapeVisNode = mc.createNode('multDoubleLinear',n=shapePrefix+'_allVis_multDoubleLinear') mc.connectAttr(shapeVisConn[0],shapeVisNode+'.input1',f=True) mc.connectAttr(ctrlLodAttr[ctrlLod],shapeVisNode+'.input2',f=True) mc.connectAttr(shapeVisNode+'.output',ctrlShape+'.v',f=True) - + else: - - # No existing connection - Direct connection + + # No existing connection - Direct connection try: mc.connectAttr(ctrlLodAttr[ctrlLod],ctrlShape+'.v',f=True) except: pass @@ -755,67 +755,67 @@ def connectControlVis( ctrlList = None, # ========== # - Checks - # ========== - + # Control LOD Toggle Node if not mc.objExists(ctrlLodNode): raise Exception('Control LOD toggle node "'+ctrlLodNode+'" does not exist!') - + # Control List if not ctrlList: ctrlList = mc.ls('*.ctrlLod',o=True,r=True) - + # ============================== # - Connect Control Visibility - # ============================== - + for ctrl in ctrlList: - + # Get Control Lod if not mc.attributeQuery('ctrlLod',n=ctrl,ex=True): continue ctrlLod = mc.getAttr(ctrl+'.ctrlLod') if ctrlLod >= len(ctrlLodAttr): continue - + # Get Control Shapes ctrlShapes = mc.listRelatives(ctrl,s=True,ni=True,pa=True,type='nurbsCurve') - + # ------------------------------------------------------------------------------- # !!! If No Shapes, Show Display Handle and LOD Override (Normal/BoundingBox) !!! # ------------------------------------------------------------------------------- if not ctrlShapes: - + # Show Display Handle mc.setAttr(ctrl+'.displayHandle',True) - + # Get/Create LOD Switch Reverse Node rev = mc.ls(mc.listConnections(ctrlLodNode+'.'+ctrlLodAttr[ctrlLod],s=False,d=True) or [],type='reverse') or [] if not rev: rev = mc.createNode('reverse',n=ctrlLodAttr[ctrlLod]+'_reverse') mc.connectAttr(ctrlLodNode+'.'+ctrlLodAttr[ctrlLod],rev+'.inputX',f=True) else: rev = rev[0] - + # Set/Connect Display Overrides mc.setAttr(ctrl+'.overrideEnabled',1) mc.connectAttr(rev+'.outputX',ctrl+'.overrideLevelOfDetail',f=True) - + # Connect Control Shape Visibility else: for ctrlShape in ctrlShapes: - + # Check Existing Connections lodVisConn = mc.listConnections(ctrlShape+'.lodVisibility',s=True,d=False) if lodVisConn: - + # Disconnect Attribute lodVisConn = mc.listConnections(ctrlShape+'.lodVisibility',s=True,d=False,p=True) mc.disconnectAttr(lodVisConn[0],ctrlShape+'.lodVisibility') - + # Connect LOD Visibility try: mc.connectAttr(ctrlLodNode+'.'+ctrlLodAttr[ctrlLod],ctrlShape+'.lodVisibility',f=True) except: print('Error connecting ctrl LOD attr to "'+ctrlShape+'.lodVisibility"!') - + # ================= # - Return Result - # ================= - + return ctrlList def connectCostumeCtrlVis( ctrlList = None, @@ -834,47 +834,47 @@ def connectCostumeCtrlVis( ctrlList = None, # ========== # - Checks - # ========== - + # Control Vis Toggle Node if not mc.objExists(ctrlVisNode): raise Exception('Visibility control toggle node "'+ctrlVisNode+'" does not exist!') - + # Control List if not ctrlList: if useCategory: ctrlList = mc.ls('*.ctrlCategory',o=True,r=True) else: ctrlList = mc.ls('*.ctrlLod',o=True,r=True) - + # ====================================== # - Connect Costume Control Visibility - # ====================================== - + # Add Control Attribute if not mc.attributeQuery(ctrlVisAttr,n=ctrlVisNode,ex=True): mc.addAttr(ctrlVisNode,ln=ctrlVisAttr,at='enum',en='Off:On',dv=0) mc.setAttr(ctrlVisNode+'.'+ctrlVisAttr,cb=True) - + # Connect Control Visibility for ctrl in ctrlList: - + ctrlTag = mc.getAttr(ctrl+'.ctrlLod') if useCategory: ctrlTag = mc.getAttr(ctrl+'.ctrlCategory') if ctrlTag != 'costume': continue - + # Connect Control Shapes ctrlShapes = mc.listRelatives(ctrl,s=True,ni=True,pa=True,type='nurbsCurve') for ctrlShape in ctrlShapes: - + # Check Existing Connections lodVisConn = mc.listConnections(ctrlShape+'.lodVisibility',s=True,d=False) if lodVisConn: # Disconnect Attribute lodVisConn = mc.listConnections(ctrlShape+'.lodVisibility',s=True,d=False,p=True) mc.disconnectAttr(lodVisConn[0],ctrlShape+'.lodVisibility') - + # Connect LOD Visibility try: mc.connectAttr(ctrlVisNode+'.'+ctrlVisAttr,ctrlShape+'.lodVisibility',f=True) except: print('Error connecting ctrl LOD attr to "'+ctrlShape+'.lodVisibility"!') - + # Print Msg print('Costume Control Shape "'+ctrlShape+'" connected to "'+ctrlVisNode+'.'+ctrlVisAttr+'"...') @@ -887,20 +887,20 @@ def connectLoresVis(toggleAttr='all.loGeoVis'): # Check visibility toggle attribute if not mc.objExists(toggleAttr): raise Exception('Visibility toggle attribute "'+toggleAttr+'" does not exist!') - + # Get all joint list jointList = mc.ls(type='joint') if not jointList: return - + # Iterate over all joints for joint in jointList: - + # Get all joint mesh shapes allShapes = mc.listRelatives(joint,s=True,pa=True) if not allShapes: continue meshShapes = mc.ls(allShapes,type='mesh') if not meshShapes: continue - + # Connect mesh shape visibility to vis toggle attr for meshShape in meshShapes: mc.connectAttr(toggleAttr,meshShape+'.v',f=True) @@ -919,14 +919,14 @@ def connectVisOld(objList=[],toggleAttr='all.hiGeoVis',attrName='',defaultValue= ''' #### DEPRECATED WARNING print('#### - DEPRECATED (glTools.rig.utils.connectVisOld) - ####') - + # Check Object List if type(objList) == str or type(objList) == unicode: objList = [str(objList)] for obj in objList: if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check Visibility Toggle Attribute if not mc.objExists(toggleAttr): node = toggleAttr.split('.')[0] @@ -937,7 +937,7 @@ def connectVisOld(objList=[],toggleAttr='all.hiGeoVis',attrName='',defaultValue= mc.setAttr(node+'.'+attr,cb=True) else: mc.addAttr(toggleAttr,e=True,dv=defaultValue) - + # Connect Visibility for obj in objList: visConn = mc.listConnections(obj+'.v',s=True,d=False,p=True) @@ -945,7 +945,7 @@ def connectVisOld(objList=[],toggleAttr='all.hiGeoVis',attrName='',defaultValue= if not visConn.count(toggleAttr): try: mc.connectAttr(toggleAttr,obj+'.v',f=True) except: print 'Unable to connect "'+obj+'" visibility!' - + # Return Result return toggleAttr @@ -977,11 +977,11 @@ def connectVis( objList, # ========== # - Checks - # ========== - + if not objList: raise Exception('Invalid or empty object list argument! (objList)') if not toggleNode: raise Exception('Invalid or empty toggle node argument! (toggleNode)') if not toggleAttr: raise Exception('Invalid or empty toggle attribute argument! (toggleAttr)') - + # Check Object List if isinstance(objList,types.StringTypes): objList = [str(objList)] @@ -990,14 +990,14 @@ def connectVis( objList, for obj in objList: if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check Toggle Node if not mc.objExists(toggleNode): raise Exception('Visibility control node "'+obj+'" does not exist!') - + # Check Toggle Name if not toggleName: toggleName = toggleAttr - + # Check Visibility Toggle Attribute if not mc.attributeQuery(toggleAttr,n=toggleNode,ex=True): mc.addAttr(toggleNode,ln=toggleAttr,nn=toggleName,at='enum',en=enumStr,dv=defaultValue) @@ -1005,13 +1005,13 @@ def connectVis( objList, else: mc.addAttr(toggleNode+'.'+toggleAttr,e=True,nn=toggleName,dv=defaultValue) toggleNodeAttr = toggleNode+'.'+toggleAttr - + # ====================== # - Connect Visibility - # ====================== - + for obj in objList: - + # Check Incoming Connections nodeVisConn = mc.listConnections(obj+'.v',s=True,d=False) if nodeVisConn: @@ -1025,11 +1025,11 @@ def connectVis( objList, # Connect Visibility try: mc.connectAttr(toggleNodeAttr,obj+'.v',f=True) except: raise Exception('Problem connecting visibility! ('+toggleNodeAttr+' >> '+obj+'.v)') - + # ================= # - Return Result - # ================= - + return toggleNodeAttr def connectDisplayTypeOld(objList,toggleAttr='all.meshDisplayType',defaultValue=0): @@ -1044,14 +1044,14 @@ def connectDisplayTypeOld(objList,toggleAttr='all.meshDisplayType',defaultValue= ''' #### DEPRECATED WARNING print('#### - DEPRECATED (glTools.rig.utils.connectDisplayTypeOld) - ####') - + # Check Object List if type(objList) == str or type(objList) == unicode: objList = [str(objList)] for obj in objList: if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check visibility toggle attribute if not mc.objExists(toggleAttr): node = toggleAttr.split('.')[0] @@ -1062,7 +1062,7 @@ def connectDisplayTypeOld(objList,toggleAttr='all.meshDisplayType',defaultValue= mc.setAttr(node+'.'+attr,cb=True) else: mc.addAttr(toggleAttr,e=True,dv=defaultValue) - + # Connect Display Type for obj in objList: mc.setAttr(obj+'.overrideEnabled',1) @@ -1073,7 +1073,7 @@ def connectDisplayTypeOld(objList,toggleAttr='all.meshDisplayType',defaultValue= print('Attribute "'+toggleAttr+'" is already connect to "'+obj+'.overrideDisplayType"! Skipping connectAttr...') else: print('Unable to connect "'+toggleAttr+'" to "'+obj+'.overrideDisplayType"!') - + # Return Result return toggleAttr @@ -1104,11 +1104,11 @@ def connectDisplayType( objList, # ========== # - Checks - # ========== - + if not objList: raise Exception('Invalid or empty object list argument! (objList)') if not toggleNode: raise Exception('Invalid or empty toggle node argument! (toggleNode)') if not toggleAttr: raise Exception('Invalid or empty toggle attribute argument! (toggleAttr)') - + # Check Object List if isinstance(objList,types.StringTypes): objList = [str(objList)] @@ -1117,14 +1117,14 @@ def connectDisplayType( objList, for obj in objList: if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check Toggle Node if not mc.objExists(toggleNode): raise Exception('Display type control node "'+obj+'" does not exist!') - + # Check Toggle Name if not toggleName: toggleName = toggleAttr - + # Check Visibility Toggle Attribute if not mc.attributeQuery(toggleAttr,n=toggleNode,ex=True): mc.addAttr(toggleNode,ln=toggleAttr,nn=toggleName,at='enum',en=enumStr,dv=defaultValue) @@ -1132,16 +1132,16 @@ def connectDisplayType( objList, else: mc.addAttr(toggleNode+'.'+toggleAttr,e=True,nn=toggleName,dv=defaultValue) toggleNodeAttr = toggleNode+'.'+toggleAttr - + # ======================== # - Connect Display Type - # ======================== - + for obj in objList: - + # Enable Display Overrides mc.setAttr(obj+'.overrideEnabled',1) - + # Check Incoming Connections nodeDispAttr = 'overrideDisplayType' nodeDispConn = mc.listConnections(obj+'.'+nodeDispAttr,s=True,d=False) @@ -1156,11 +1156,11 @@ def connectDisplayType( objList, # Connect Visibility try: mc.connectAttr(toggleNodeAttr,obj+'.'+nodeDispAttr,f=True) except: raise Exception('Problem connecting visibility! ('+toggleNodeAttr+' >> '+obj+'.'+nodeDispAttr+')') - + # ================= # - Return Result - # ================= - + return toggleNodeAttr def connectAttr(targetNode,targetAttr,sourceNode,sourceAttr,force=True): @@ -1180,40 +1180,40 @@ def connectAttr(targetNode,targetAttr,sourceNode,sourceAttr,force=True): # ========== # - Checks - # ========== - + if not targetNode: raise Exception('Invalid or empty target node argument! (targetNode)') if not targetAttr: raise Exception('Invalid or empty target attribute argument! (targetAttr)') if not sourceNode: raise Exception('Invalid or empty source node argument! (sourceNode)') if not sourceAttr: raise Exception('Invalid or empty source attribute argument! (sourceAttr)') - + if not mc.objExists(targetNode): raise Exception('Target node "'+targetNode+'" does not exist!') if not mc.objExists(sourceNode): raise Exception('Source node "'+targetNode+'" does not exist!') if not mc.attributeQuery(targetAttr,n=targetNode,ex=True): raise Exception('Target attribute "'+targetNode+'.'+targetAttr+'" does not exist!') if not mc.attributeQuery(sourceAttr,n=sourceNode,ex=True): raise Exception('Source attribute "'+sourceNode+'.'+sourceAttr+'" does not exist!') - + sourceNodeAttr = sourceNode+'.'+sourceAttr targetNodeAttr = targetNode+'.'+targetAttr - + # Check Existing Connection to Target existingConn = mc.listConnections(targetNodeAttr,s=True,d=False,p=True) or [] if existingConn: for srcConn in existingConn: print('Breaking existing connection - "'+srcConn+'" >< "'+targetNodeAttr+'"...') mc.disconnectAttr(srcConn,targetNodeAttr) - + # ===================== # - Connect Attribute - # ===================== - + try: mc.connectAttr(sourceNodeAttr,targetNodeAttr,f=force) except Exception, e: raise Exception('Error connecting attribute "'+sourceNodeAttr+'" >> "'+targetNodeAttr+'"! Exception Msg: '+str(e)) else: print('Connecting attributes - "'+sourceNodeAttr+'" >> "'+targetNodeAttr+'"...') - + # ================= # - Return Result - # ================= - + return sourceNodeAttr,targetNodeAttr def nonRenderableFaceSet(facelist,buildStandin=False): @@ -1229,79 +1229,79 @@ def nonRenderableFaceSet(facelist,buildStandin=False): # ========== # - Checks - # ========== - + facelist = mc.filterExpand(facelist,sm=34) if not facelist: raise Exception('Invalid face list!') - + # =================== # - Get Set Members - # =================== - + # Sort Faces by Object faceObjList = glTools.utils.selection.componentListByObject(facelist) - + # For Each Object in Set meshPreviewList = [] for faceList in faceObjList: - + # Get Mesh faceMesh = mc.ls(faceList[0],o=True)[0] if not glTools.utils.transform.isTransform(faceMesh): faceMesh = mc.listRelatives(faceMesh,p=True,pa=True)[0] - + # Get Face Id List faceIdList = glTools.utils.component.singleIndexList(faceList) faceIdStr = str(faceIdList)[1:-1] - + # ======================== # - Add ABC PrimVar Attr - # ======================== - + attrName = 'deleteFaceSet' if mc.objExists(faceMesh+'.ABC_'+attrName): try: mc.setAttr(faceMesh+'.ABC_'+attrName,l=False) except: pass mc.deleteAttr(faceMesh+'.ABC_'+attrName) - + glTools.utils.primvar.addAbcPrimVarStr( geo = faceMesh, attrName = attrName, stringVal = faceIdStr, lock = False ) - + # ================= # - Build Standin - # ================= - + if buildStandin: - + # Duplicate Original (with Connections) meshPreview = mc.polyDuplicateAndConnect(faceMesh)[0] meshPreview = mc.rename(meshPreview,faceMesh+'_standin') - + # Reparent Object try: mc.parent(meshPreview,w=True) except: pass - + # Delete Unused Shapes meshPreviewShapes = mc.listRelatives(meshPreview,s=True,pa=True) if meshPreviewShapes: meshPreviewIntShapes = mc.ls(meshPreviewShapes,intermediateObjects=True) if meshPreviewIntShapes: mc.delete(meshPreviewIntShapes) - + # Rename Shape meshPreviewShapes = mc.listRelatives(meshPreview,s=True,pa=True) if meshPreviewShapes: meshPreviewShape = mc.rename(meshPreviewShapes[0],meshPreview+'Shape') - + # Delete Faces mc.delete([meshPreview+'.f['+str(i)+']' for i in faceIdList]) - + # Append Output List meshPreviewList.append(meshPreview) - + # ================= # - Return Result - # ================= - + return meshPreviewList def selectNonRenderableFaces(geo): @@ -1311,33 +1311,33 @@ def selectNonRenderableFaces(geo): # ========== # - Checks - # ========== - + # Check Mesh if not glTools.utils.mesh.isMesh(geo): mc.warning('Object "'+geo+'" is not a valid mesh! Unable to select non-renderable faces...') return [] - + # Check Attribute attrName = 'ABC_deleteFaceSet' if not mc.attributeQuery(attrName,n=geo,ex=True): mc.warning('Attribute "'+geo+'.'+attrName+'" does not exist! Unable to select non-renderable faces...') return [] - + # ================ # - Select Faces - # ================ - + faceIdStr = mc.getAttr(geo+'.'+attrName) faceIdList = ast.literal_eval(faceIdStr) faceList = [geo+'.f['+str(i)+']' for i in faceIdList] - + try: mc.select(faceList) except: mc.warning('Problem selecting face list! '+str(faceList)) - + # ================= # - Return Result - # ================= - + return faceList def checkNonReferencedInputShape(geo): @@ -1349,14 +1349,14 @@ def checkNonReferencedInputShape(geo): # ========== # - Checks - # ========== - + # Check Geometry Exists if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') # Check Geometry is Referenced if not glTools.utils.reference.isReferenced(geo): raise Exception('Geometry "'+geo+'" is not referenced! No referenced shapes under nonReference parent...') - + # Get Geometry Shapes shapes = mc.listRelatives(geo,s=True,pa=True) if not shapes: @@ -1364,19 +1364,19 @@ def checkNonReferencedInputShape(geo): if len(shapes) == 1: print('Geometry "'+geo+'" has only one shape! Nothing to do here, skipping...') return False - + # Check for Referenced Shapes refShapes = [shape for shape in shapes if glTools.utils.reference.isReferenced(shape)] if not refShapes: raise Exception('No referenced shapes found under geometry "'+geo+'"!') - + # Get Output Shape resultShape = mc.listRelatives(geo,s=True,ni=True,pa=True) if not resultShape: raise Exception('No non-intermediate shapes under geometry "'+geo+'"!') if len(resultShape) != 1: print('Multiple non-intermediate shapes! Checking first shape ("'+resultShape[0]+'") for input connections... ') - + # Get Input Shape inputShape = glTools.utils.shape.findInputShape(resultShape[0],recursive=True) if not inputShape: @@ -1387,7 +1387,7 @@ def checkNonReferencedInputShape(geo): else: print('Output shape "'+resultShape[0]+'" has no incoming connections! Nothing to do, skipping...') return False - + # Check Input Shape is Referenced return not glTools.utils.reference.isReferenced(inputShape) @@ -1400,14 +1400,14 @@ def fixNonReferencedInputShape(geo): # ========== # - Checks - # ========== - + # Check Geometry Exists if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') # Check Geometry is Referenced if not glTools.utils.reference.isReferenced(geo): raise Exception('Geometry "'+geo+'" is not referenced! No referenced shapes under nonReference parent...') - + # Get Geometry Shapes shapes = mc.listRelatives(geo,s=True,pa=True) if not shapes: @@ -1415,21 +1415,21 @@ def fixNonReferencedInputShape(geo): if len(shapes) == 1: print('Geometry "'+geo+'" has only one shape! Nothing to do here, skipping...') return '' - + # Check for Referenced Shapes refShapes = [shape for shape in shapes if glTools.utils.reference.isReferenced(shape)] if not refShapes: raise Exception('No referenced shapes found under geometry "'+geo+'"!') if len(refShapes) > 1: print('Found multiple referenced shapes under geometry transform "'+geo+'"! Using first shape "'+refShapes[0]+'" for input connections...') - + # Get Output Shape resultShape = mc.listRelatives(geo,s=True,ni=True,pa=True) if not resultShape: raise Exception('No non-intermediate shapes found under geometry "'+geo+'"!') if len(resultShape) != 1: print('Found multiple non-intermediate shapes! Using first shape "'+resultShape[0]+'" for input connections...') - + # Get Input Shape inputShape = glTools.utils.shape.findInputShape(resultShape[0],recursive=True) if not inputShape: @@ -1440,27 +1440,27 @@ def fixNonReferencedInputShape(geo): else: print('Output shape "'+resultShape[0]+'" has no incoming connections! Nothing to do, skipping...') return '' - + # Check Input Shape is Referenced if glTools.utils.reference.isReferenced(inputShape): print('Input shape is referenced! Skipping...') return '' - + # ============================================= # - Replace Input Shape with Referenced Shape - # ============================================= - + # Check Reference Shape is Output if resultShape[0] == refShapes[0]: - + # Swap Input/Output Node Conections print('References shape is output (result) shape! Rearranging geometry graph...') glTools.utils.connection.swap(inputShape,refShapes[0]) - + # Set Intermediate Object Status mc.setAttr(inputShape+'.intermediateObject',0) mc.setAttr(refShapes[0]+'.intermediateObject',1) - + # Fix Shape Names if 'Orig' in inputShape: if 'Deformed' in inputShape: @@ -1468,22 +1468,22 @@ def fixNonReferencedInputShape(geo): else: inputShape = mc.rename(inputShape,inputShape.replace('Orig','Deformed')) else: - + # Check inMesh Connections to Referenced Shape if mc.listConnections(refShapes[0]+'.inMesh',s=True,d=False): - + # Swap Input/Output Node Conections glTools.utils.connection.swap(inputShape,refShapes[0]) - + else: - + # Replace Input/Output Node Conections glTools.utils.connection.replace(inputShape,refShapes[0],inputs=True,outputs=True) - + # ================= # - Return Result - # ================= - + return refShapes[0] def cleanUnusedIntermediateShapes(geo): @@ -1492,7 +1492,7 @@ def cleanUnusedIntermediateShapes(geo): # Check Geometry Exists if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') - + # Get Geometry Shapes shapes = mc.listRelatives(geo,s=True,pa=True) if not shapes: @@ -1500,17 +1500,17 @@ def cleanUnusedIntermediateShapes(geo): if len(shapes) == 1: print('Geometry "'+geo+'" has only one shape! Nothing to do here, skipping...') return None - + # Get Output Shape resultShapes = mc.listRelatives(geo,s=True,ni=True,pa=True) if not resultShapes: raise Exception('No non-intermediate shapes found under geometry "'+geo+'"!') if len(resultShapes) != 1: print('Found multiple non-intermediate shapes!') - + # For Each Output Shape for resultShape in resultShapes: - + # Get Input Shape inputShape = glTools.utils.shape.findInputShape(resultShape,recursive=True) if not inputShape: @@ -1522,39 +1522,39 @@ def cleanUnusedIntermediateShapes(geo): else: print('Output shape "'+resultShape+'" has no incoming connections! Nothing to do, skipping...') continue - + # Replace Unused Intermediate Shapes Connections intermediateShape = glTools.utils.shape.findInputShape(resultShape) while(intermediateShape != inputShape): - + # Store Next Intermediate Shape intShape = intermediateShape intermediateShape = glTools.utils.shape.findInputShape(intShape) - + # MESH if mc.objectType(intShape) == 'mesh': inMeshConn = mc.listConnections(intShape+'.inMesh',s=True,d=False,p=True) if inMeshConn: outMeshConn = mc.listConnections([intShape+'.outMesh',intShape+'.worldMesh'],s=False,d=True,p=True) or [] for outConn in outMeshConn: mc.connectAttr(inMeshConn[0],outConn,f=True) - + # NURBS elif mc.objectType(intShape) in ['nurbsCurve','nurbsSurface']: inNurbConn = mc.listConnections(intShape+'.create',s=True,d=False,p=True) if inNurbConn: outNurbConn = mc.listConnections([intShape+'.local',intShape+'.worldSpace'],s=False,d=True,p=True) or [] for outConn in outNurbConn: mc.connectAttr(inNurbConn[0],outConn,f=True) - + # UNSUPPORTED else: print('Unsupported shape type! ('+mc.objectType(intShape)+')! Skipping geometry...') break - + # Replace Generic Connections #glTools.utils.connection.replace(intShape,inputShape,inputs=True,outputs=True) - + # Delete Unused Intermediate Shape mc.delete(intShape) - + # Print Shape Result print('# DELETED Intermediate Shape: '+intShape) diff --git a/tools/animLib.py b/tools/animLib.py index ae59dd2..c4e76b9 100644 --- a/tools/animLib.py +++ b/tools/animLib.py @@ -12,12 +12,12 @@ def getNodes(filePath,stripNS=False): # Check File if not os.path.isfile(filePath): raise Exception('Invalid file path! No file at location - '+filePath) - + # Get Nodes nodes = [] if filePath.endswith('.pose'): nodes = getPoseNodes(filePath,stripNS) if filePath.endswith('.anim'): nodes = getAnimNodes(filePath,stripNS) - + # Return Result return nodes @@ -27,20 +27,20 @@ def getPoseNodes(poseFile,stripNS=False): # Check File if not os.path.isfile(poseFile): raise Exception('Invalid file path! No file at location - '+poseFile) - + # Read Files f = open(poseFile,'r') - + # Get Nodes nodes = [] for i, line in enumerate(f): node = line.split('.')[0] if stripNS: node = node.split(':')[-1] if not node in nodes: nodes.append(node) - + # Close File f.close() - + # Return Result return nodes @@ -50,10 +50,10 @@ def getAnimNodes(animFile,stripNS=False): # Check File if not os.path.isfile(animFile): raise Exception('Invalid file path! No file at location - '+animFile) - + # Read Files f = open(animFile,'r') - + # Get Nodes nodes = [] for i, line in enumerate(f): @@ -62,10 +62,10 @@ def getAnimNodes(animFile,stripNS=False): node = lineItem[3] if stripNS: node = node.split(':')[-1] if not node in nodes: nodes.append(node) - + # Close File f.close() - + # Return Result return nodes @@ -80,18 +80,18 @@ def loadPose(poseFile,targetNS=''): # Check File if not os.path.isfile(poseFile): raise Exception('Invalid file path! No file at location - '+poseFile) - + # Read Files f = open(poseFile,'r') - + # Read Lines for i, line in enumerate(f): - + # Get Line Data poseData = line.split() poseAttr = targetNS+':'+poseData[0].split(':')[-1] poseVal = float(poseData[1]) - + # Check Target Attribute if not mc.objExists(poseAttr): print('Attribute "'+poseAttr+'" does not exist!! Skipping...') @@ -99,13 +99,13 @@ def loadPose(poseFile,targetNS=''): if not mc.getAttr(poseAttr,se=True): print('Attribute "'+poseAttr+'" is not settable!! Skipping...') return False - + # Apply Static Value mc.setAttr(poseAttr,poseVal) - + # Close File f.close() - + # Return Result return True @@ -126,27 +126,27 @@ def loadAnim(animFile,targetNS,frameOffset=0,infinityOverride=None,applyEulerFil # Check File if not os.path.isfile(animFile): raise Exception('Invalid file path! No file at location - '+animFile) - + # Read Files f = open(animFile,'r') - + # Read Lines for i, line in enumerate(f): - + # Get Channel Mode lineItem = line.split() if not lineItem: continue if lineItem[0] == 'static': loadStaticData(line,targetNS) if lineItem[0] == 'anim': loadAnimData(animFile,i,targetNS,frameOffset,infinityOverride) - + # Close File f.close() - + # Filter Rotation Anim if applyEulerFilter: rotateChannels = mc.ls(targetNS+':*',type='animCurveTA') mc.filterCurve(rotateChannels) - + # Return Result return True @@ -164,7 +164,7 @@ def loadStaticData(line,targetNS): obj = lineItem[3].split(':')[-1] attrPath = targetNS+':'+obj+'.'+attr value = float(lineItem[5]) - + # Check Target Attribute if not mc.objExists(attrPath): print('Attribute "'+attrPath+'" does not exist!! Skipping...') @@ -172,11 +172,11 @@ def loadStaticData(line,targetNS): if not mc.getAttr(attrPath,se=True): print('Attribute "'+attrPath+'" is not settable!! Skipping...') return False - + # Apply Static Value try: mc.setAttr(attrPath,value) except Exception, e: print('AnimLib: Load Static Data: Error setting attribute "'+attrPath+'" to value '+str(value)+'! Exception Msg: '+str(e)) - + # Return Result return True @@ -197,25 +197,25 @@ def loadAnimData(animFile,lineID,targetNS,frameOffset=0,infinityOverride=None): # Initialize Target Attribute attrPath = '' animData = [] - + # ============= # - Read File - # ============= - + f = open(animFile,'r') for i, line in enumerate(f): - + # Skip to relevant line items if i < lineID: continue - + # Get Anim Data Header if i == lineID: - + lineItem = line.split() attr = lineItem[2] obj = lineItem[3].split(':')[-1] attrPath = targetNS+':'+obj+'.'+attr - + # Check Target Attribute if not mc.objExists(attrPath): print('Attribute "'+attrPath+'" does not exist!! Skipping...') @@ -223,44 +223,44 @@ def loadAnimData(animFile,lineID,targetNS,frameOffset=0,infinityOverride=None): if not mc.getAttr(attrPath,se=True): print('Attribute "'+attrPath+'" is not settable!! Skipping...') return False - + # Proceed to Next Line continue - + # Check Anim Data End if '}' in line: break - + # Build Anim Data animData.append(line) - + # =================== # - Apply Anim Data - # =================== - + # Get Curve Data weighted = bool(animData[1].split()[-1][:-1]) preInf = animData[2].split()[-1][:-1] postInf = animData[3].split()[-1][:-1] - + # Check Infinity Mode Override if infinityOverride: - + # Check Valid Infinity Mode if not infinityOverride in ['constant','linear','cycle','cycleRelative','oscillate']: print('Invalid infinity mode "'+infinityOverride+'"! Using stored values...') else: preInf = infinityOverride postInf = infinityOverride - + # Load Animation Data for data in animData[5:]: - + # Clean Data Line data = data.replace(';','') - + # Split Data Items dataItem = data.split() - + # Apply Time Offset time = float(dataItem[0])+frameOffset value = float(dataItem[1]) @@ -268,13 +268,13 @@ def loadAnimData(animFile,lineID,targetNS,frameOffset=0,infinityOverride=None): ottype = dataItem[3] lock = bool(dataItem[4]) bd = bool(int(dataItem[6][0])) - + mc.setKeyframe(attrPath,t=time,v=value) mc.keyTangent(attrPath,e=True,weightedTangents=weighted) mc.keyTangent(attrPath,e=True,t=(time,time),lock=lock,itt=ittype,ott=ottype) mc.keyframe(attrPath,e=True,t=(time,time),breakdown=bd) if weighted: mc.keyTangent(attrPath,weightLock=1) - + if len(dataItem) == 11: inAn = float(dataItem[7]) inWt = float(dataItem[8]) @@ -287,10 +287,10 @@ def loadAnimData(animFile,lineID,targetNS,frameOffset=0,infinityOverride=None): inWeight=inWt, outAngle=otAn, outWeight=otWt ) - + # Set Curve Infinity mc.setInfinity(attrPath,pri=preInf,poi=postInf) - + # Return Result return True @@ -309,30 +309,30 @@ def applyAnim(targetNS,char,animType,anim): # ========== # - Checks - # ========== - + # Check Target Namespace if not mc.namespace(ex=targetNS): raise Exception('Target namespace "'+targetNS+'" does not exist!') - + # Determine Pose animFile = animLibRoot()+'/'+char+'/'+animType+'/'+anim+'.anim' - + # Check Anim File if not os.path.isfile(animFile): raise Exception('Anim clip file "'+animFile+'" does not exist! Unable to load animation.') - + # =================== # - Apply Hand Pose - # =================== - + loaded = loadAnim(animFile,targetNS) if not loaded: raise Exception('Problem applying animation clip "'+anim+'" to namespace "'+targetNS+'"!') - + # ================= # - Return Result - # ================= - + return loaded def applyPose(targetNS,char,poseType,pose,key=False): @@ -352,38 +352,38 @@ def applyPose(targetNS,char,poseType,pose,key=False): # ========== # - Checks - # ========== - + # Check Target Namespace if not mc.namespace(ex=targetNS): raise Exception('Target namespace "'+targetNS+'" does not exist!') - + # Determine Pose poseFile = animLibRoot()+'/'+char+'/'+poseType+'/'+pose+'.pose' - + # Check Pose File if not os.path.isfile(poseFile): raise Exception('Pose file "'+poseFile+'" does not exist! Unable to load pose.') - + # =================== # - Apply Hand Pose - # =================== - + loaded = loadPose(poseFile,targetNS) if not loaded: raise Exception('Problem applying pose "'+pose+'" to namespace "'+targetNS+'"!') - + # ================= # - Set Pose Keys - # ================= - + if key: poseNodes = [targetNS+':'+i for i in getPoseNodes(poseFile,stripNS=True)] mc.setKeyframe(poseNodes) - + # ================= # - Return Result - # ================= - + return loaded def applyHandPose(targetNS,side,char=None,pose=None,key=False): @@ -403,18 +403,18 @@ def applyHandPose(targetNS,side,char=None,pose=None,key=False): # ========== # - Checks - # ========== - + # Check Target Namespace if not mc.namespace(ex=targetNS): raise Exception('Target namespace "'+targetNS+'" does not exist!') - + # Check Character if not char: targetCtx = glTools.utils.reference.contextFromNsReferencePath(targetNS) if not dict(targetCtx).has_key('asset'): raise Exception('Unable to determine asset from reference path') char = targetCtx['asset'] - + # Check Pose poseDir = animLibRoot()+'/'+char+'/Hands' if not pose: @@ -425,31 +425,31 @@ def applyHandPose(targetNS,side,char=None,pose=None,key=False): pose = poseDir+'/'+poseList[poseInd] else: pose = poseDir+'/'+pose+'_'+side+'.pose' - + # Check Pose File if not os.path.isfile(pose): raise Exception('Pose file "'+pose+'" does not exist! Unable to load pose.') - + # =================== # - Apply Hand Pose - # =================== - + loaded = loadPose(pose,targetNS) if not loaded: raise Exception('Problem applying pose "'+pose+'" to namespace "'+targetNS+'"!') - + # ================= # - Set Pose Keys - # ================= - + if key: poseNodes = [targetNS+':'+i for i in getPoseNodes(pose,stripNS=True)] mc.setKeyframe(poseNodes) - + # ================= # - Return Result - # ================= - + return loaded def applyHandAnim(targetNS,side,char=None,anim=None): @@ -467,18 +467,18 @@ def applyHandAnim(targetNS,side,char=None,anim=None): # ========== # - Checks - # ========== - + # Check Target Namespace if not mc.namespace(ex=targetNS): raise Exception('Target namespace "'+targetNS+'" does not exist!') - + # Check Character if not char: targetCtx = glTools.utils.reference.contextFromNsReferencePath(targetNS) if not dict(targetCtx).has_key('asset'): raise Exception('Unable to determine asset from reference path') char = targetCtx['asset'] - + # Check Anim animDir = animLibRoot()+'/'+char+'/Hands' if not anim: @@ -489,21 +489,21 @@ def applyHandAnim(targetNS,side,char=None,anim=None): anim = animDir+'/'+animList[animInd] else: pose = animDir+'/'+anim+'_'+side+'.anim' - + # Check Pose File if not os.path.isfile(anim): raise Exception('Animation file "'+anim+'" does not exist! Unable to load anim.') - + # =================== # - Apply Hand Anim - # =================== - + loaded = loadAnim(anim,targetNS) - + # ================= # - Return Result - # ================= - + return loaded def applyFacePose(targetNS,char=None,pose=None,key=False): @@ -521,18 +521,18 @@ def applyFacePose(targetNS,char=None,pose=None,key=False): # ========== # - Checks - # ========== - + # Check Target Namespace if not mc.namespace(ex=targetNS): raise Exception('Target namespace "'+targetNS+'" does not exist!') - + # Check Character if not char: targetCtx = glTools.utils.reference.contextFromNsReferencePath(targetNS) if not dict(targetCtx).has_key('asset'): raise Exception('Unable to determine asset from reference path') char = targetCtx['asset'] - + # Check Pose poseDir = animLibRoot()+'/'+char+'/Face_Exp' if not pose: @@ -543,31 +543,31 @@ def applyFacePose(targetNS,char=None,pose=None,key=False): pose = poseDir+'/'+poseList[poseInd] else: pose = poseDir+'/'+pose+'.pose' - + # Check Pose File if not os.path.isfile(pose): raise Exception('Pose file "'+pose+'" does not exist! Unable to load pose.') - + # =================== # - Apply Face Pose - # =================== - + loaded = loadPose(pose,targetNS) if not loaded: raise Exception('Problem applying pose "'+pose+'" to namespace "'+targetNS+'"!') - + # ================= # - Set Pose Keys - # ================= - + if key: poseNodes = getPoseNodes(pose) mc.setKeyframe(poseNodes) - + # ================= # - Return Result - # ================= - + return loaded def savePose(poseFile,poseNodes=[],poseNote=None,poseImg=None): @@ -581,37 +581,37 @@ def saveAnim(animFile,animNodes=[],animNote=None,animImg=None): # =================== # - Check Anim Path - # =================== - + # File Extension if not animFile.endswith('.anim'): raise Exception('Incorrect anim file extension! Expected anim file extension ".anim"...') - + # Get Path Directory pathDir = os.path.dirname(animFile) - + # Create File Directory if Needed if not os.path.exists(pathDir): os.makedirs(pathDir) - + # =================== # - Save Anim Notes - # =================== - + if animNote: noteFile = animFile.replace('.anim','.notes') writeNotes(noteFile,note=animNote) - + # ====================== # - Save Anim Snapshot - # ====================== - + if not animImg: pass #animLib_snapShot($path,$name,"anim"); - + # ================== # - Save Anim File - # ================== - + writeAnimFile(animFile,animNodes=animNodes) def writePoseFile(poseFile,poseNodes=[]): @@ -625,30 +625,30 @@ def writePoseFile(poseFile,poseNodes=[]): # Open File for Writing print('\nWriting Animation Curves...\n') f = open(poseFile,'w') - + for poseNode in poseNodes: - + # Get Settable Attrs attrs = [] attrs.extend(mc.listAttr(poseNode,k=True) or []) attrs.extend(mc.listAttr(poseNode,cb=True) or []) - + # Remove Locked Attrs lock_attrs = mc.listAttr(poseNode,l=True) attrs = list(set(attrs)-set(lock_attrs)) - + # Build poseData for at in attrs: - + # Check Settable if not mc.getAttr(poseNode+'.'+at,se=True): continue v = mc.getAttr(poseNode+'.'+at) if v < 0.000001: v = 0 f.write(poseNode+'.'+at+' '+str(v)) - + # Close File f.close() - + # Return Result print '\nDone Writing Pose Data\n' return poseFile @@ -663,52 +663,52 @@ def writeAnimFile(animFile,animNodes=[]): ''' # Initialize First Frame Value firstKeyTime = 1000000 - + # Open File for Writing print('\nWriting Animation Curves...\n') f = open(animFile,'w') f.write('# Generated by VFX animLib\n#\n') f.write('# dkAnim written by Daniel Kramer MOD by Mark Behm\n#\n') f.write('# Source workfile: '+mc.file(q=True,sn=True)+'\n#\n\n') - + for item in animNodes: - + # Get Animated Channels channels = mc.listConnections(item,s=True,d=False,p=True,c=True,type='animCurve') for i in range(0,len(channels),2): - + chan = mc.ls(channels[i],o=True)[0] node = mc.ls(channels[i+1],o=True)[0] attr = channels[i+1].split('.')[-1] attrName = channels[i+1] - + parent = 0 nodeParent = mc.listRelatives(node,p=True) if nodeParent: parent = 1 - + # Infinity infValue = ['constant','linear','constant','cycle','cycleRelative','oscillate'] preIn = infValue[mc.getAttr(chan+'.preInfinity')] postInf = infValue[mc.getAttr(chan+'.postInfinity')] - + # Weighted weighted = int(mc.getAttr(chan+'.weightedTangents')) - + # ==================== # - Write Curve Data - # ==================== - + f.write('anim '+attr+' '+attr+' '+node+' '+parent+' 0 0;\n') f.write('animData {\n') f.write(' weighted '+str(weighted)+';\n') f.write(' preInfinity '+preIn+';\n') f.write(' postInfinity '+postIn+';\n') f.write(' keys {\n') - + # ================== # - Write Key Data - # ================== - + # Get Key Data keys = mc.keyframe(chan,q=True) values = mc.keyframe(chan,q=True,vc=True) @@ -721,13 +721,13 @@ def writeAnimFile(animFile,animNodes=[]): outAngle = mc.keyTangent(chan,q=True,outAngle=True) inWeight = mc.keyTangent(chan,q=True,inWeight=True) outWeight = mc.keyTangent(chan,q=True,outWeight=True) - + # Write Key Data for i in range(len(keys)): - + # Get Breakdown Status bd = int(bool(keys[i] in breakDown)) - + # First Key if keys[i] < firstKeyTime: firstKeyTime = keys[i] @@ -736,42 +736,42 @@ def writeAnimFile(animFile,animNodes=[]): if inTan[i] == 'fixed': f.write(' '+str(inAngle[i])+' '+str(inWeight[i])) if outTan[i] == 'fixed': f.write(' '+str(outAngle[i])+' '+str(outWeight[i])) f.write(';\n') - + f.write(' }\n}\n') - + # ========================= # - Write Static Channels - # ========================= - + staticChans = mc.listAnimatable(item) for staticChan in staticChans: - + node = mc.ls(staticChan,o=True)[0] attr = staticChan.split('.')[-1] parent = 0 nodeParent = mc.listRelatives(node,p=True) if nodeParent: parent = 1 - + #staticChan = node+'.'+attr keys = mc.keyframe(staticChan,q=True) connected = mc.listConnections(staticChan,s=True) - + if not keys and not connected: f.write('static '+attr+' '+attr+' '+node+' '+parent+' '+str(mc.getAttr(staticChan))+'\n') # Record First Key Offset f.write('firstKeyTime '+str(firstKeyTime)) - + # Close File f.close() - + # ================= # - Return Result - # ================= - + print '\nDone Writing Animation Curves\n' - + return animFile def writeNotes(noteFile,note=None): @@ -779,7 +779,7 @@ def writeNotes(noteFile,note=None): ''' # Open File for Writing f = open(noteFile,'w') - + # Write Note to File if not note: f.write('author: '+os.environ['USER']) @@ -788,7 +788,7 @@ def writeNotes(noteFile,note=None): f.write('date: '+day[datetime.datetime.weekday(dt)]+' '+dt.month+' '+dt.day+' '+dt.hour+':'+dt.minute+':'+dt.second+' PST '+dt.year) else: f.write(note) - + # Close File f.close() diff --git a/tools/autoRivet.py b/tools/autoRivet.py index 38e77ea..58e8776 100644 --- a/tools/autoRivet.py +++ b/tools/autoRivet.py @@ -16,37 +16,37 @@ def autoRivet(createRivetTransform=True,suffix='rvt'): # Check Selection if not len(sel) == 2: raise Exception('Select object to rivet and then the target mesh!') - + # Determine rivet object and mesh rvtObj = sel[0] mesh = sel[1] prefix = glTools.utils.stringUtils.stripSuffix(rvtObj) - + # Get rivet object position pos = glTools.utils.base.getPosition(rvtObj) pt = OpenMaya.MPoint(pos[0],pos[1],pos[2],1.0) - + # Get closest face on mesh faceId = glTools.utils.mesh.closestFace(mesh,pos) - + # ========================= # - Determine Rivet Edges - # ========================= - + edgeId1 = -1 edgeId2 = -1 - + # Create MItMeshEdge edgeIter = glTools.utils.mesh.getMeshEdgeIter(mesh) - + # Create edgeId MScriptUtil edgeIdUtil = OpenMaya.MScriptUtil() edgeIdUtil.createFromInt(0) edgeIdPtr = edgeIdUtil.asIntPtr() - + # Get face edges faceEdges = glTools.utils.mesh.getFaceEdgeIndices(mesh,faceId) - + # Get closest edge maxDist = 9999.0 for edgeId in faceEdges: @@ -56,84 +56,84 @@ def autoRivet(createRivetTransform=True,suffix='rvt'): if edgeDist < maxDist: edgeId1 = edgeId maxDist = edgeDist - + # Set current edge edgeIter.setIndex(edgeId1,edgeIdPtr) - + # Get opposing edge faceEdges.remove(edgeId1) for edgeId in faceEdges: edgeId2 = edgeId # Check edge connectivity if not edgeIter.connectedToEdge(edgeId): break - + # ======================== # - Create Utility Nodes - # ======================== - + # Rivet Edge 1 edgeCrv1 = prefix+'_edge'+str(edgeId1)+'_rivet_curveFromMeshEdge' if not mc.objExists(edgeCrv1): edgeCrv1 = mc.createNode('curveFromMeshEdge',n=edgeCrv1) mc.setAttr(edgeCrv1+'.edgeIndex[0]',edgeId1) mc.connectAttr(mesh+'.worldMesh[0]',edgeCrv1+'.inputMesh',f=True) - + # Rivet Edge 2 edgeCrv2 = prefix+'_edge'+str(edgeId2)+'_rivet_curveFromMeshEdge' if not mc.objExists(edgeCrv2): edgeCrv2 = mc.createNode('curveFromMeshEdge',n=edgeCrv2) mc.setAttr(edgeCrv2+'.edgeIndex[0]',edgeId2) mc.connectAttr(mesh+'.worldMesh[0]',edgeCrv2+'.inputMesh',f=True) - + # Rivet Loft rivetLoft = prefix+'_face'+str(faceId)+'_rivet_loft' if not mc.objExists(rivetLoft): rivetLoft = mc.createNode('loft',n=rivetLoft) mc.connectAttr(edgeCrv1+'.outputCurve',rivetLoft+'.inputCurve[0]',f=True) mc.connectAttr(edgeCrv2+'.outputCurve',rivetLoft+'.inputCurve[1]',f=True) - + # Rivet Point on Surface Info rivetPosi = prefix+'_face'+str(faceId)+'_rivet_pointOnSurfaceInfo' rivetPosi = mc.createNode('pointOnSurfaceInfo',n=rivetPosi) mc.connectAttr(rivetLoft+'.outputSurface',rivetPosi+'.inputSurface') - + # =========================== # - Get Rivet UV Parameter - # =========================== - + # Build Temp Surface tmpSrfShape = mc.createNode('nurbsSurface') tmpSrf = mc.listRelatives(tmpSrfShape,p=True,pa=True)[0] mc.connectAttr(rivetLoft+'.outputSurface',tmpSrfShape+'.create',f=True) - + # Get closest point on surface uv = glTools.utils.surface.closestPoint(tmpSrf,pos) - + # Set rivet parameter mc.setAttr(rivetPosi+'.parameterU',uv[0]) mc.setAttr(rivetPosi+'.parameterV',uv[1]) - + # Delete Temp Surface mc.delete(tmpSrf) - + # ========================== # - Attach Rivet Transform - # ========================== - + # Determine rivet transform rvtTransform = rvtObj if createRivetTransform: rvtTransform = mc.group(em=True,n=prefix+'_rvt') - + # Connect rivet transform mc.connectAttr(rivetPosi+'.position',rvtTransform+'.t',f=True) - + # Parent to rivet transform if createRivetTransform: mc.parent(rvtObj,rvtTransform) - + # ================= # - Return Result - # ================= - + return rvtTransform def meshFaceConstraint(face='',transform='',orient=True,prefix=''): @@ -142,9 +142,9 @@ def meshFaceConstraint(face='',transform='',orient=True,prefix=''): # ========== # - Checks - # ========== - + if not prefix: prefix = 'meshFaceConstraint' - + if not face: faceList = mc.filterExpand(sm=34) if not faceList: raise Exception('No mesh face specified for constraint!') @@ -153,15 +153,15 @@ def meshFaceConstraint(face='',transform='',orient=True,prefix=''): transformList = mc.ls(sl=True,type='transform') if not transformList: transformList = mc.spaceLocator(n=prefix+'_locator') transform = transformList[0] - + # ====================== # - Get Face UV Center - # ====================== - + # Get Face Details mesh = mc.ls(face,o=True)[0] faceId = glTools.utils.component.index(face) - + # Get Mesh Face Function Set uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() @@ -170,7 +170,7 @@ def meshFaceConstraint(face='',transform='',orient=True,prefix=''): faceIdPtr = faceIdUtil.asIntPtr() faceIt = glTools.utils.mesh.getMeshFaceIter(mesh) faceIt.setIndex(faceId,faceIdPtr) - + # Get UV Center uvSet = mc.polyUVSet(mesh,q=True,cuv=True) faceIt.getUVs(uArray,vArray) @@ -182,18 +182,18 @@ def meshFaceConstraint(face='',transform='',orient=True,prefix=''): for i in range(uvCount): u += (uArray[i] / uvCount) v += (vArray[i] / uvCount) - + # ===================== # - Create Constraint - # ===================== - + r = mc.getAttr(transform+'.r')[0] - + meshCon = mc.pointOnPolyConstraint(mesh,transform,n=prefix+'_pointOnPolyConstraint')[0] wtAlias = mc.pointOnPolyConstraint(meshCon,q=True,wal=True)[0] mc.setAttr(meshCon+'.'+wtAlias.replace('W0','U0'),u) mc.setAttr(meshCon+'.'+wtAlias.replace('W0','V0'),v) - + # Orient if not orient: rxConn = mc.listConnections(transform+'.rx',s=True,d=False,p=True)[0] @@ -203,22 +203,22 @@ def meshFaceConstraint(face='',transform='',orient=True,prefix=''): rzConn = mc.listConnections(transform+'.rz',s=True,d=False,p=True)[0] mc.disconnectAttr(rzConn,transform+'.rz') mc.setAttr(transform+'.r',*r) - + # ================= # - Return Result - # ================= - + return meshCon - + def meshVertexConstraint(vertex='',transform='',orient=True,prefix=''): ''' ''' # ========== # - Checks - # ========== - + if not prefix: prefix = 'meshVertexConstraint' - + if not vertex: vtxList = mc.filterExpand(sm=31) if not vtxList: raise Exception('No mesh vertex specified for constraint!') @@ -227,15 +227,15 @@ def meshVertexConstraint(vertex='',transform='',orient=True,prefix=''): transformList = mc.ls(sl=True,type='transform') if not transformList: transformList = mc.spaceLocator(n=prefix+'_locator') transform = transformList[0] - + # ================= # - Get Vertex UV - # ================= - + # Get Vertex Details mesh = mc.ls(vertex,o=True)[0] vtxId = glTools.utils.component.index(vertex) - + # Get Mesh Vertex Function Set uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() @@ -245,7 +245,7 @@ def meshVertexConstraint(vertex='',transform='',orient=True,prefix=''): vtxIdPtr = vtxIdUtil.asIntPtr() vtxIt = glTools.utils.mesh.getMeshVertexIter(mesh) vtxIt.setIndex(vtxId,vtxIdPtr) - + # Get UV Center uvSet = mc.polyUVSet(mesh,q=True,cuv=True) vtxIt.getUVs(uArray,vArray,faceArray) @@ -253,18 +253,18 @@ def meshVertexConstraint(vertex='',transform='',orient=True,prefix=''): vArray = list(vArray) u = uArray[0] v = vArray[0] - + # ===================== # - Create Constraint - # ===================== - + r = mc.getAttr(transform+'.r')[0] - + meshCon = mc.pointOnPolyConstraint(mesh,transform,n=prefix+'_pointOnPolyConstraint')[0] wtAlias = mc.pointOnPolyConstraint(meshCon,q=True,wal=True)[0] mc.setAttr(meshCon+'.'+wtAlias.replace('W0','U0'),u) mc.setAttr(meshCon+'.'+wtAlias.replace('W0','V0'),v) - + # Orient if not orient: rxConn = mc.listConnections(transform+'.rx',s=True,d=False,p=True)[0] @@ -274,11 +274,11 @@ def meshVertexConstraint(vertex='',transform='',orient=True,prefix=''): rzConn = mc.listConnections(transform+'.rz',s=True,d=False,p=True)[0] mc.disconnectAttr(rzConn,transform+'.rz') mc.setAttr(transform+'.r',*r) - + # ================= # - Return Result - # ================= - + return meshCon def meshFaceConstraintList(faceList=[],transformList=[],orient=True,prefix=''): @@ -287,34 +287,34 @@ def meshFaceConstraintList(faceList=[],transformList=[],orient=True,prefix=''): # ========== # - Checks - # ========== - + # Face List if not faceList: faceList = mc.filterExpand(sm=34) if not faceList: raise Exception('No mesh face list specified for constraint!') - + # Transform List if not transformList: transformList = ['' for vtx in vtxList] - + # Vertex / Face list length if not len(faceList) == len(transformList): raise Exception('Face and Transform list length mis-match!') - + # ====================== # - Create Constraints - # ====================== - + constraintList = [] for i in range(len(faceList)): mc.select(cl=True) itPrefix = prefix+'_'+str(i) constraintList.append(meshFaceConstraint(faceList[i],transformList[i],orient=orient,prefix=itPrefix)) - + # ================= # - Return Result - # ================= - + return constraintList def meshVertexConstraintList(vtxList=[],transformList=[],orient=True,prefix=''): @@ -323,32 +323,32 @@ def meshVertexConstraintList(vtxList=[],transformList=[],orient=True,prefix=''): # ========== # - Checks - # ========== - + # Vertex List if not vtxList: vtxList = mc.filterExpand(sm=31) if not vtxList: raise Exception('No mesh vertex list specified for constraint!') - + # Transform List if not transformList: transformList = ['' for vtx in vtxList] - + # Vertex / Transform list length if not len(vtxList) == len(transformList): raise Exception('Vertex and Transform list length mis-match!') - + # ====================== # - Create Constraints - # ====================== - + constraintList = [] for i in range(len(vtxList)): mc.select(cl=True) itPrefix = prefix+'_'+str(i) constraintList.append(meshVertexConstraint(vtxList[i],transformList[i],orient=orient,prefix=itPrefix)) - + # ================= # - Return Result - # ================= - + return constraintList diff --git a/tools/barycentricPointWeight.py b/tools/barycentricPointWeight.py index 1235c30..b65b3f7 100644 --- a/tools/barycentricPointWeight.py +++ b/tools/barycentricPointWeight.py @@ -17,18 +17,18 @@ def create(samplePt,pntList,weightCalc=[True,True,True],prefix=None): # ========== # - Checks - # ========== - + # Check Sample Point (Locator) if not mc.objExists(samplePt): raise Exception('Sample point "'+samplePt+'" does not exist!!') - + # Check prefix if not prefix: prefix = 'barycentricPointWeight' - + # ======================== # - Setup Full Area Calc - # ======================== - + # Build pntFace surface pntFace = mc.nurbsPlane(p=(0,0,0),ax=(0,1,0),d=1,ch=False,n=prefix+'_sample_surface')[0] pntLoc = glTools.utils.surface.locatorSurface(pntFace,prefix=prefix) @@ -36,14 +36,14 @@ def create(samplePt,pntList,weightCalc=[True,True,True],prefix=None): mc.delete(mc.pointConstraint(pntList[1],pntLoc[1])) mc.delete(mc.pointConstraint(pntList[2],pntLoc[2])) mc.delete(mc.pointConstraint(pntList[2],pntLoc[3])) - + # Attach follow pt followLoc = mc.spaceLocator(n=prefix+'_follow_locator')[0] follow_cpos = mc.createNode('closestPointOnSurface',n=prefix+'_closestPointOnSurface') mc.connectAttr(samplePt+'.worldPosition[0]',follow_cpos+'.inPosition',f=True) mc.connectAttr(pntFace+'.worldSpace[0]',follow_cpos+'.inputSurface',f=True) mc.connectAttr(follow_cpos+'.position',followLoc+'.translate',f=True) - + # Calculate triArea triEdge1_pma = mc.createNode('plusMinusAverage',n=prefix+'_triEdge1Vec_plusMinusAverage') triEdge2_pma = mc.createNode('plusMinusAverage',n=prefix+'_triEdge2Vec_plusMinusAverage') @@ -53,25 +53,25 @@ def create(samplePt,pntList,weightCalc=[True,True,True],prefix=None): mc.connectAttr(pntLoc[0]+'.worldPosition[0]',triEdge1_pma+'.input3D[1]',f=True) mc.connectAttr(pntLoc[2]+'.worldPosition[0]',triEdge2_pma+'.input3D[0]',f=True) mc.connectAttr(pntLoc[0]+'.worldPosition[0]',triEdge2_pma+'.input3D[1]',f=True) - + triArea_vpn = mc.createNode('vectorProduct',n=prefix+'_triArea_vectorProduct') mc.setAttr(triArea_vpn+'.operation',2) # Cross Product mc.connectAttr(triEdge1_pma+'.output3D',triArea_vpn+'.input1',f=True) mc.connectAttr(triEdge2_pma+'.output3D',triArea_vpn+'.input2',f=True) - + triArea_dist = mc.createNode('distanceBetween',n=prefix+'_triArea_distanceBetween') mc.connectAttr(triArea_vpn+'.output',triArea_dist+'.point1',f=True) - + # ======================= # - Setup Sub Area Calc - # ======================= - + # Calculate triPt weights for i in range(3): - + # Check weight calculation (bool) if weightCalc[i]: - + # Calculate sub-TriArea pntEdge1_pma = mc.createNode('plusMinusAverage',n=prefix+'_pt'+str(i)+'Edge1Vec_plusMinusAverage') pntEdge2_pma = mc.createNode('plusMinusAverage',n=prefix+'_pt'+str(i)+'Edge2Vec_plusMinusAverage') @@ -81,21 +81,21 @@ def create(samplePt,pntList,weightCalc=[True,True,True],prefix=None): mc.connectAttr(followLoc+'.worldPosition[0]',pntEdge1_pma+'.input3D[1]',f=True) mc.connectAttr(pntLoc[(i+2)%3]+'.worldPosition[0]',pntEdge2_pma+'.input3D[0]',f=True) mc.connectAttr(followLoc+'.worldPosition[0]',pntEdge2_pma+'.input3D[1]',f=True) - + pntArea_vpn = mc.createNode('vectorProduct',n=prefix+'_pt'+str(i)+'Area_vectorProduct') mc.setAttr(pntArea_vpn+'.operation',2) # Cross Product mc.connectAttr(pntEdge1_pma+'.output3D',pntArea_vpn+'.input1',f=True) mc.connectAttr(pntEdge2_pma+'.output3D',pntArea_vpn+'.input2',f=True) - + pntArea_dist = mc.createNode('distanceBetween',n=prefix+'_pt'+str(i)+'Area_distanceBetween') mc.connectAttr(pntArea_vpn+'.output',pntArea_dist+'.point1',f=True) - + # Divide ptArea by triArea to get weight pntWeight_mdn = mc.createNode('multiplyDivide',n=prefix+'_pt'+str(i)+'Weight_multiplyDivide') mc.setAttr(pntWeight_mdn+'.operation',2) # Divide mc.connectAttr(pntArea_dist+'.distance',pntWeight_mdn+'.input1X',f=True) mc.connectAttr(triArea_dist+'.distance',pntWeight_mdn+'.input2X',f=True) - + # Add weight attribute to pntLoc mc.addAttr(pntLoc[i],ln='weight',min=0.0,max=1.0,dv=0.0) mc.connectAttr(pntWeight_mdn+'.outputX',pntLoc[i]+'.weight',f=True) @@ -103,24 +103,24 @@ def create(samplePt,pntList,weightCalc=[True,True,True],prefix=None): # ============ # - CLEAN UP - # ============ - + # Group mesh locators pntLoc_grp = mc.group(pntLoc,n=prefix+'_3Point_grp') mc.parent(pntFace,pntLoc_grp) - + # Turn off inheritTransforms for tri point face mc.setAttr(pntFace+'.inheritsTransform',0) - + # Scale follow locator mc.setAttr(followLoc+'.localScale',0.05,0.05,0.05) - + # Parent and hide coincident locator mc.parent(pntLoc[3],pntLoc[2]) mc.setAttr(pntLoc[3]+'.v',0) - + # ================= # - Return Result - # ================= - + # Return result return [pntLoc,pntFace,pntLoc_grp] diff --git a/tools/bestFitPlane.py b/tools/bestFitPlane.py index 93af918..dfa27c8 100644 --- a/tools/bestFitPlane.py +++ b/tools/bestFitPlane.py @@ -15,19 +15,19 @@ def bestFitPlaneNormal(ptList): ''' # Initialize plane normal norm = OpenMaya.MVector() - + # Get Point Positions ptList = [glTools.utils.base.getPosition(p) for p in ptList] - + # Calculate Plane Normal for i in range(len(ptList)): prev = OpenMaya.MVector(ptList[i-1][0],ptList[i-1][1],ptList[i-1][2]) curr = OpenMaya.MVector(ptList[i][0],ptList[i][1],ptList[i][2]) norm += OpenMaya.MVector((prev.z + curr.z) * (prev.y - curr.y), (prev.x + curr.x) * (prev.z - curr.z), (prev.y + curr.y) * (prev.x - curr.x)) - + # Normalize result norm.normalize() - + # Return Result return [norm.x,norm.y,norm.z] @@ -39,24 +39,24 @@ def bestFitPlaneCreate(ptList,upVector=(0,1,0)): @param upVector: Up vector for orientation reference. @type upVector: tuple or list ''' - + # Calculate Plane Center and Normal p = glTools.tools.center.centerPoint_average(ptList) pt = OpenMaya.MVector(p[0],p[1],p[2]) n = bestFitPlaneNormal(ptList) norm = OpenMaya.MVector(n[0],n[1],n[2]) - + # Build rotation matrix mat = glTools.utils.matrix.buildRotation(norm,upVector,'y','x') rot = glTools.utils.matrix.getRotation(mat,'xyz') - + # Create Plane plane = mc.polyPlane(w=1,h=1,sx=1,sy=1,ax=[0,1,0],cuv=2,ch=False)[0] - + # Position Plane mc.rotate(rot[0],rot[1],rot[2],plane,os=True,a=True) mc.move(pt[0],pt[1],pt[2],plane,ws=True,a=True) - + # Return result return plane @@ -71,13 +71,13 @@ def bestFitPlaneMatrix(ptList,upVector=(0,1,0)): # Calculate Plane Center and Normal p = glTools.tools.center.centerPoint_average(ptList) n = bestFitPlaneNormal(ptList) - + # Calculate Cross and Up Vectors crossVector = glTools.utils.mathUtils.crossProduct(n,upVector) upVector = glTools.utils.mathUtils.crossProduct(crossVector,n) - + # Build rotation matrix mat = glTools.utils.matrix.buildMatrix(translate=p,xAxis=upVector,yAxis=n,zAxis=crossVector) - + # Return Result return mat diff --git a/tools/blendShape.py b/tools/blendShape.py index 206a9c6..db8c7aa 100644 --- a/tools/blendShape.py +++ b/tools/blendShape.py @@ -18,20 +18,20 @@ def createFromSelection(origin='local',deformOrder=None,prefix=None): if not sel: print('Empty or invalid selections!') return None - + # Get Base/Target Geometry baseGeo = sel[-1] targetGeo = sel[:-1] - + # Get Prefix if not prefix: prefix = baseGeo # glTools.utils.stringUtils.stripSuffix(baseGeo) - + # Create BlendShape blendShape = glTools.utils.blendShape.create(baseGeo,targetGeo,origin,deformOrder,prefix) - + # Set Default Weight if len(targetGeo) == 1: mc.setAttr(blendShape+'.w[0]',1.0) - + # Return Result return blendShape @@ -45,17 +45,17 @@ def endOfChainBlendShape(geo): # Checks if not mc.objExists(geo): raise Exception('Geometry object "'+geo+'" does not exist!!') - + if not mc.listRelatives(geo,s=True,ni=True): raise Exception('Object "'+geo+'" has no valid shape children!') - + # Create Override BlendShapes blendShape = geo.split(':')[-1]+'_override_blendShape' if mc.objExists(blendShape): print('Override blendShape "'+blendShape+'" already exists! Skipping...') else: blendShape = mc.blendShape(geo,n=blendShape)[0] - + # Return Result return blendShape @@ -74,20 +74,20 @@ def addOverrideTarget(geo,targetGeo,targetWeight=0): raise Exception('Base geometry "'+geo+'" does not exist!!') if not mc.objExists(targetGeo): raise Exception('Target geometry "'+targetGeo+'" does not exist!!') - + # Get Override BlendShape blendShape = geo.split(':')[-1]+'_override_blendShape' if not mc.objExists(blendShape): blendShape = geo+'_override_blendShape' if not mc.objExists(blendShape): raise Exception('Override blendShape "'+blendShape+'" does not exist!!') - + # Add Target targetAttr = glTools.utils.blendShape.addTarget( blendShape=blendShape, target=targetGeo, base=geo, targetWeight=targetWeight, topologyCheck=False ) - + # Return Result return targetAttr @@ -98,35 +98,35 @@ def duplicateAndBlend(obj,parent='',search='',replace='',worldSpace=False): @type obj: str @param parent: Parent transform to place the duplicate object under @type parent: str - @param search: Names search string used to generate the duplicate object name + @param search: Names search string used to generate the duplicate object name @type search: str - @param replace: Names replace string used to generate the duplicate object name + @param replace: Names replace string used to generate the duplicate object name @type replace: str - @param worldSpace: Create the blendShape in local or world space + @param worldSpace: Create the blendShape in local or world space @type worldSpace: bool ''' # Check object exists if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Duplicate object dup = mc.duplicate(obj,rr=True,n=obj.replace(search,replace))[0] - + # Create blendShape from original to duplicate origin = 'local' if worldSpace: origin = 'world' blendShape = mc.blendShape(obj,dup,o=origin)[0] - + # Set blendShape weight blendAlias = mc.listAttr(blendShape+'.w',m=True)[0] mc.setAttr(blendShape+'.'+blendAlias,1.0) - + # Parent if parent and mc.objExists(parent): mc.parent(dup,parent) else: mc.parent(dup,w=True) - + # Return result return blendShape @@ -145,64 +145,64 @@ def regenerateTarget(blendShape,target,base='',connect=False): # ========== # - Checks - # ========== - + if not glTools.utils.blendShape.isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape!') if not glTools.utils.blendShape.hasTarget(blendShape,target): raise Exception('BlendShape "'+blendShape+'" has no target "'+target+'"!') if base and not glTools.utils.blendShape.hasBase(blendShape,base): raise Exception('BlendShape "'+blendShape+'" has no base geometry "'+base+'"!') - + # Check Existing Live Target Geometry if glTools.utils.blendShape.hasTargetGeo(blendShape,target,base=base): targetGeo = glTools.utils.blendShape.getTargetGeo(blendShape,target,baseGeo=base) print('Target "" for blendShape "" already has live target geometry! Returning existing target geometry...') return targetGeo - + # Get Base Geometry - Default to base index [0] if not base: base = glTools.utils.blendShape.getBaseGeo(blendShape)[0] baseIndex = glTools.utils.blendShape.getBaseIndex(blendShape,base) - + # Get Target Index targetIndex = glTools.utils.blendShape.getTargetIndex(blendShape,target) - + # ============================== # - Regenerate Target Geometry - # ============================== - + # Initialize Target Geometry targetGeo = mc.duplicate(base,n=target)[0] - + # Delete Unused Shapes for targetShape in mc.listRelatives(targetGeo,s=True,pa=True): if mc.getAttr(targetShape+'.intermediateObject'): mc.delete(targetShape) - + # Get Target Deltas and Components wtIndex = 6000 targetDelta = mc.getAttr(blendShape+'.inputTarget['+str(baseIndex)+'].inputTargetGroup['+str(targetIndex)+'].inputTargetItem['+str(wtIndex)+'].inputPointsTarget') targetComp = mc.getAttr(blendShape+'.inputTarget['+str(baseIndex)+'].inputTargetGroup['+str(targetIndex)+'].inputTargetItem['+str(wtIndex)+'].inputComponentsTarget') for i in xrange(len(targetComp)): - + # Get Component Delta d = targetDelta[i] # Apply Component Delta mc.move(d[0],d[1],d[2],targetGeo+'.'+targetComp[i],r=True,os=True) - + # Freeze Vertex Transforms mc.polyMoveVertex(targetGeo) mc.delete(targetGeo,ch=True) - + # =========================== # - Connect Target Geometry - # =========================== - + if connect: mc.connectAttr(targetGeo+'.outMesh',blendShape+'.inputTarget['+str(baseIndex)+'].inputTargetGroup['+str(targetIndex)+'].inputTargetItem['+str(wtIndex)+'].inputGeomTarget',f=True) - + # ================= # - Return Result - # ================= - + return targetGeo def regenerateTargetSplits(target,base,targetSplits=[],replace=False): @@ -221,7 +221,7 @@ def regenerateTargetSplits(target,base,targetSplits=[],replace=False): # ========== # - Checks - # ========== - + pass def updateTargets(oldBase,newBase,targetList): @@ -237,7 +237,7 @@ def updateTargets(oldBase,newBase,targetList): # ========== # - Checks - # ========== - + if not mc.objExists(oldBase): raise Exception('Old base geometry "'+oldBase+'" does not exist!') if not mc.objExists(newBase): @@ -246,58 +246,58 @@ def updateTargets(oldBase,newBase,targetList): for target in targetList: if not mc.objExists(target): raise Exception('Target geometry "'+target+'" does not exist!') - + # ================== # - Update Targets - # ================== - + targetList.insert(0,newBase) updateBlendShape = mc.blendShape(targetList,oldBase,n='updateTargets_blendShape')[0] updateBlendAlias = mc.listAttr(updateBlendShape+'.w',m=True) - + # Generate New Targets for i in range(len(updateBlendAlias)): - + if not i: - + # Set New Base Target Weight (1.0) mc.setAttr(updateBlendShape+'.'+updateBlendAlias[i],1) - + else: - + # Set Target Weight mc.setAttr(updateBlendShape+'.'+updateBlendAlias[i],1) - + # Extract New Target from Blended Base newTarget = mc.duplicate(oldBase,n=updateBlendAlias[0]+'NEW')[0] # Delete Unused Shapes for shape in mc.listRelatives(newTarget,s=True,pa=True): if mc.getAttr(shape+'.intermediateObject'): mc.delete(shape) - + # Update Target targetBlendShape = mc.blendShape(newTarget,targetList[i])[0] targetAlias = mc.listAttr(targetBlendShape+'.w',m=True)[0] mc.setAttr(targetBlendShape+'.'+targetAlias,1) mc.delete(targetList[i],ch=True) mc.delete(newTarget) - + # Reset Target Weight mc.setAttr(updateBlendShape+'.'+updateBlendAlias[i],0) - + # =========== # - Cleanup - # =========== - + # Reset New Base Target Weight (0.0) mc.setAttr(updateBlendShape+'.'+updateBlendAlias[0],0) - + # Delete History (Old Base) #mc.delete(oldBase,ch=True) mc.delete(updateBlendShape) - + # ================= # - Return Result - # ================= - + return targetList diff --git a/tools/center.py b/tools/center.py index dcb3a75..0c24819 100644 --- a/tools/center.py +++ b/tools/center.py @@ -18,7 +18,7 @@ def centerPoint_average(ptList): pos = glTools.utils.base.getPosition(pt) avgPt = [avgPt[0]+pos[0],avgPt[1]+pos[1],avgPt[2]+pos[2]] avgPt = [avgPt[0]/numPt,avgPt[1]/numPt,avgPt[2]/numPt] - + # Return Result return avgPt @@ -34,7 +34,7 @@ def centerPoint_geometric(ptList): pos = glTools.utils.base.getPosition(pt) bbox.expand(OpenMaya.MPoint(pos[0],pos[1],pos[2],1.0)) cntPt = bbox.center() - + # Return Result return [cntPt.x,cntPt.y,cntPt.z] @@ -48,11 +48,11 @@ def centerPointLocator(ptList,name=''): ''' # Determine center point avgPt = centerPoint_average(ptList) - + # Create locator if not name: name = 'locator#' loc = mc.spaceLocator(n=name)[0] - + # Position locator mc.move(avgPt[0],avgPt[1],avgPt[2],loc,ws=True,a=True) @@ -66,11 +66,11 @@ def centerToGeometry(geo,obj=None): ''' # Check Object if not obj: obj = mc.spaceLocator(n=geo+'_center')[0] - + # Get Geometry Center geoPts = glTools.utils.component.getComponentStrList(geo) pt = centerPoint_average(geoPts) - + # Move Object to Geometry Center pos = glTools.utils.base.getPosition(obj) offset = glTools.utils.mathUtils.offsetVector(pos,pt) @@ -86,7 +86,7 @@ def centerToPoints(ptList,obj): ''' # Get Geometry Center pt = centerPoint_average(ptList) - + # Move Object to Geometry Center pos = glTools.utils.base.getPosition(obj) offset = glTools.utils.mathUtils.offsetVector(pos,pt) diff --git a/tools/chainRotation.py b/tools/chainRotation.py index a4e0ed5..2bd95de 100644 --- a/tools/chainRotation.py +++ b/tools/chainRotation.py @@ -19,32 +19,32 @@ def multChainRotation(sourceChain,targetChain,multValue=0.5,addMultAttr=True,mul # Check source/target chain sourceChainLen = len(sourceChain) targetChainNum = len(targetChain) - + if sourceChainLen != targetChainNum: raise Exception('Source and Target chain length mis-match! Source and Target chains must have the same number of joints!') - + # For each joint in the chain multNodeList = [] for i in range(sourceChainLen): - + # Generate prefix pre = glTools.utils.stringUtils.stripSuffix(sourceChain[i]) - + # Create taper node - multiplyDivide multNode = mc.createNode('multiplyDivide',n=pre+'_multiplyDivide') multNodeList.append(multNode) - + # Make rotation connections mc.setAttr(multNode+'.input1',multValue,multValue,multValue) mc.connectAttr(sourceChain[i]+'.r',multNode+'.input2',f=True) mc.connectAttr(multNode+'.output',targetChain[i]+'.r',f=True) - + # Check taper attribute if addMultAttr: - + # Add attribute mc.addAttr(targetChain[0],ln=multAttr,min=0,max=1,dv=multValue,k=True) - + # Connect taper attribute to taper nodes for multNode in multNodeList: mc.connectAttr(targetChain[0]+'.'+multAttr,multNode+'.input1X',f=True) @@ -71,35 +71,35 @@ def blendChainRotation(inputChain1,inputChain2,targetChain,blendValue=0.5,addBle input1ChainLen = len(input1Chain) input2ChainLen = len(input2Chain) targetChainNum = len(targetChain) - + if input1ChainLen != input2ChainLen: raise Exception('Input chain length mis-match! Input joint chains must have the same number of joints!') if input1ChainLen != targetChainLen: raise Exception('Input and Target chain length mis-match! Input and Target joint chains must have the same number of joints!') - + # For each joint in the chain blendNodeList = [] for i in range(input1ChainLen): - + # Generate prefix pre = glTools.utils.stringUtils.stripSuffix(input1Chain[i]) - + # Create blend node - blendColors blendNode = mc.createNode('blendColors',n=pre+'_blendColors') blendNodeList.append(blendNode) - + # Make connections mc.setAttr(blendNode+'.blender',blendValue) mc.connectAttr(input1Chain[i]+'.r',blendNode+'.color1',f=True) mc.connectAttr(input2Chain[i]+'.r',blendNode+'.color2',f=True) mc.connectAttr(blendNode+'.output',targetChain[i]+'.r',f=True) - + # Check blend attribute if addBlendAttr: - + # Add blend attribute mc.addAttr(targetChains[0],ln=blendAttr,min=0,max=1,dv=blendValue,k=True) - + # Connect blend attribute to taper nodes for blendNode in blendNodeList: mc.connectAttr(targetChains[0]+'.'+blendAttr,blendNode+'.blender',f=True) @@ -120,57 +120,57 @@ def taperChainRotationMulti(sourceChain,targetChains,useMaxValue=False,addTaperA ''' # Check max value notMax = int(not useMaxValue) - + # Check source chain sourceChainLen = len(sourceChain) - + # Check target chains targetChainNum = len(targetChains) for i in range(targetChainNum): targetChainLen = len(targetChainNum[i]) if targetChainLen != sourceChainLen: raise Exception('Chain length mis-match! Source and target chains must have the same number of joints!') - + # Calculate blend increments blendInc = 1.0 / (targetChainNum + notMax) - + # Blend chains for i in range(targetChainNum): - - # Get chain index (alpha) + + # Get chain index (alpha) chainInd = glTools.utils.stringUtils.alphaIndex(i,upper=True) - + # Calculate taper weight taperWt = 1.0 - (blendInc * (i + notMax)) - + # For each joint in the chain taperNodeList = [] for n in range(sourceChainLen): - + # Generate prefix pre = glTools.utils.stringUtils.stripSuffix(sourceChain[i]) + chainInd - + # Create taper node - multiplyDivide taperNode = mc.createNode('multiplyDivide',n=pre+'_multiplyDivide') taperNodeList.append(taperNode) - + # Make connections mc.setAttr(taperNode+'.input1',taperWt,taperWt,taperWt) mc.connectAttr(sourceChain[n]+'.r',taperNode+'.input2',f=True) mc.connectAttr(taperNode+'.output',targetChains[i][n]+'.r',f=True) - + # Check taper attribute if addTaperAttr: - + # Add attribute mc.addAttr(targetChains[i][0],ln=taperAttr,min=0,max=1,dv=taperWt,k=True) - + # Connect taper attribute to taper nodes for taperNode in taperNodeList: mc.connectAttr(targetChains[i][0]+'.'+taperAttr,taperNode+'.input1X',f=True) mc.connectAttr(targetChains[i][0]+'.'+taperAttr,taperNode+'.input1Y',f=True) mc.connectAttr(targetChains[i][0]+'.'+taperAttr,taperNode+'.input1Z',f=True) - + def blendChainRotationMulti(startChain,endChain,targetChains,useMinValue=False,useMaxValue=False,addBlendAttr=False,blendAttr='blendRotation'): ''' @@ -192,57 +192,57 @@ def blendChainRotationMulti(startChain,endChain,targetChains,useMinValue=False,u # Check min/max values notMin = int(not useMinValue) notMax = int(not useMaxValue) - + # Check start/end chain startChainLen = len(sourceChain) endChainLen = len(sourceChain) if startChainLen != endChainLen: raise Exception('Start and End chain length mis-match! Start and End chains must have the same number of joints!') - + # Check target chains targetChainNum = len(targetChains) for i in range(targetChainNum): targetChainLen = len(targetChainNum[i]) if targetChainLen != startChainLen: raise Exception('Chain length mis-match! Source and target chains must have the same number of joints!') - + # Calculate blend increments blendInc = 1.0 / (targetChainNum + notMin + notMax) - + # Blend chains for i in range(targetChainNum): - - # Get chain index (alpha) + + # Get chain index (alpha) chainInd = glTools.utils.stringUtils.alphaIndex(i,upper=True) - + # Calculate blend weight blendWt = 1.0 - (blendInc * (i + notMax)) - + # For each joint in the chain blendNodeList = [] for n in range(startChainLen): - + # Generate prefix pre = glTools.utils.stringUtils.stripSuffix(sourceChain[i]) + chainInd - + # Create blend node blendNode = mc.createNode('blendColors',n=pre+'_blendColors') blendNodeList.append(blendNode) - + # Make connections mc.setAttr(blendNode+'.blender',blendWt) mc.connectAttr(startChain[n]+'.r',blendNode+'.color1',f=True) mc.connectAttr(endChain[n]+'.r',blendNode+'.color2',f=True) mc.connectAttr(blendNode+'.output',targetChains[i][n]+'.r',f=True) - + # Check taper attribute if addBlendAttr: - + # Add attribute mc.addAttr(targetChains[i][0],ln=blendAttr,min=0,max=1,dv=blendWt,k=True) - + # Connect taper attribute to taper nodes for taperNode in taperNodeList: mc.connectAttr(targetChains[i][0]+'.'+blendAttr,blendNode+'.blender',f=True) - - + + diff --git a/tools/characterSet.py b/tools/characterSet.py index 5a6a626..928bb09 100644 --- a/tools/characterSet.py +++ b/tools/characterSet.py @@ -12,37 +12,37 @@ def charSetSelectUI(): window = 'charSetSelectUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Character Set Selector',wh=[350,500]) - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # =============== # - UI Elements - # =============== - + # Create Character Set List charList = mc.ls(type='character') or [] charListTSL = mc.textScrollList('charSetSelect_charListTSL',ams=False) for char in charList: mc.textScrollList(charListTSL,e=True,a=char) - + # Create List Callback mc.textScrollList(charListTSL,e=True,sc='import glTools.tools.characterSet;reload(glTools.tools.characterSet);glTools.tools.characterSet.setCurrentFromUI()') - + # Pop-up Menu mc.popupMenu(p=charListTSL) mc.menuItem('Set from Selection',c='glTools.tools.characterSet.setCurrentFromSelection()') - + # =============== # - Form Layout - # =============== mc.formLayout(FL,e=True,af=[(charListTSL,'top',5),(charListTSL,'left',5),(charListTSL,'right',5),(charListTSL,'bottom',5)]) - + # =============== # - Show Window - # =============== - + mc.showWindow(window) - + def setCurrentFromUI(): ''' ''' @@ -58,18 +58,18 @@ def setCurrentFromSelection(): NSlist = glTools.utils.namespace.getNSList(sel,topOnly=True) if not NSlist: print('No selected namespaces! Unable to set current character set...') - + # Find Character Sets in Selected Namespace char = mc.ls(NSlist[0]+':*',type='character') if not char: print('No character set in selected namespace! Unable to set current character set...') - + # Get UI Character Set List charListTSL = mc.textScrollList('charSetSelect_charListTSL',q=True,ai=True) if char[0] in charListTSL: mc.textScrollList('charSetSelect_charListTSL',e=True,si=char[0]) else: print('Character set "'+char[0]+'" not found in UI list! Skipping UI selection...') - + # Set Current Character Set glTools.utils.characterSet.setCurrent(char[0]) diff --git a/tools/collideTransform.py b/tools/collideTransform.py index 252da50..c92bc1a 100644 --- a/tools/collideTransform.py +++ b/tools/collideTransform.py @@ -39,37 +39,37 @@ def planeCollideTransform( targetTransform, # ========== # - Checks - # ========== - + # Check Target Transforms if not mc.objExists(targetTransform): raise Exception('Target transform "'+targetTransform+'" does not exist!') if not glTools.utils.transform.isTransform(targetTransform): raise Exception('Object "'+targetTransform+'" is not a valid transform!') - + # Check Collide Plane if collidePlane: if not mc.objExists(str(collidePlane)): raise Exception('Collide plane "'+collidePlane+'" does not exist!') if not glTools.utils.transform.isTransform(collidePlane): raise Exception('Object "'+collidePlane+'" is not a valid transform!') - + # Check Collide Transforms if collideTransform: if not mc.objExists(str(collideTransform)): raise Exception('Collide transform "'+collideTransform+'" does not exist!') if not glTools.utils.transform.isTransform(collideTransform): raise Exception('Object "'+collideTransform+'" is not a valid transform!') - + # Check Distance Axis if distanceAxis: distanceAxis = distanceAxis.upper() - + # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(targetTransform) - + # =================== # - Build Collision - # =================== - + # Build Collide Objects if not collideTransform: collideTransform = mc.spaceLocator(n=prefix+'_collide_loc')[0] @@ -77,11 +77,11 @@ def planeCollideTransform( targetTransform, collidePlaneShape = mc.createNode('renderRect') collidePlane = mc.listRelatives(collidePlaneShape,p=True)[0] collidePlane = mc.rename(collidePlane,prefix+'_collide_plane') - + # Add Collide Attributes if not mc.attributeQuery('collideWeight',n=collidePlane,ex=True): mc.addAttr(collidePlane,ln='collideWeight',min=0,max=1,dv=1,k=True) - + # Build Collide Nodes collideCondition = mc.createNode('condition',n=prefix+'_collide_condition') collideBlend = mc.createNode('blendColors',n=prefix+'_collideWeight_blendColors') @@ -91,11 +91,11 @@ def planeCollideTransform( targetTransform, mc.setAttr(collideToWorld+'.operation',4) # Point Matrix Product worldToLocal = mc.createNode('vectorProduct',n=prefix+'_worldToLocal_vectorProduct') mc.setAttr(worldToLocal+'.operation',4) # Point Matrix Product - + # ========================= # - Build Collide Network - # ========================= - + # World To Collide mc.connectAttr(collidePlane+'.worldInverseMatrix[0]',worldToCollide+'.matrix',f=True) if mc.objExists(targetTransform+'.worldPosition[0]'): @@ -105,7 +105,7 @@ def planeCollideTransform( targetTransform, mc.setAttr(localToWorld+'.operation',4) # Point Matrix Product mc.connectAttr(targetTransform+'.worldMatrix[0]',localToWorld+'.matrix',f=True) mc.connectAttr(localToWorld+'.output',worldToCollide+'.input1',f=True) - + # Collide Condition mc.connectAttr(worldToCollide+'.outputZ',collideCondition+'.firstTerm',f=True) mc.setAttr(collideCondition+'.secondTerm',0) @@ -114,37 +114,37 @@ def planeCollideTransform( targetTransform, mc.connectAttr(worldToCollide+'.outputX',collideCondition+'.colorIfFalseR',f=True) mc.connectAttr(worldToCollide+'.outputY',collideCondition+'.colorIfFalseG',f=True) mc.setAttr(collideCondition+'.colorIfFalseB',0) - + # Collide Weight Blend mc.connectAttr(collideCondition+'.outColor',collideBlend+'.color1',f=True) mc.connectAttr(worldToCollide+'.output',collideBlend+'.color2',f=True) mc.connectAttr(collidePlane+'.collideWeight',collideBlend+'.blender',f=True) - + # Collide To World mc.connectAttr(collideBlend+'.output',collideToWorld+'.input1',f=True) mc.connectAttr(collidePlane+'.worldMatrix[0]',collideToWorld+'.matrix',f=True) - + # World To Local mc.connectAttr(collideToWorld+'.output',worldToLocal+'.input1',f=True) mc.connectAttr(collideTransform+'.parentInverseMatrix[0]',worldToLocal+'.matrix',f=True) - + # Connect Output mc.connectAttr(worldToLocal+'.output',collideTransform+'.translate',f=True) - + # ============================ # - Calculate Offset Falloff - # ============================ - + if offsetFalloff != None: - + # Add Collide Attributes if not mc.attributeQuery('offsetFalloff',n=collidePlane,ex=True): mc.addAttr(collidePlane,ln='offsetFalloff',min=0,dv=0.5,k=True) - + # Build Nodes falloffRemap = mc.createNode('remapValue',n=prefix+'_offsetFalloff_remapValue') falloffMult = mc.createNode('multDoubleLinear',n=prefix+'_offsetFalloff_multDoubleLinear') - + # Falloff Remap mc.connectAttr(worldToCollide+'.outputZ',falloffRemap+'.inputValue',f=True) mc.connectAttr(collidePlane+'.offsetFalloff',falloffRemap+'.inputMax',f=True) @@ -152,31 +152,31 @@ def planeCollideTransform( targetTransform, mc.connectAttr(collidePlane+'.offsetFalloff',falloffMult+'.input1',f=True) mc.setAttr(falloffMult+'.input2',-1) mc.connectAttr(falloffMult+'.output',falloffRemap+'.inputMin',f=True) - + # Override Collide Condition mc.connectAttr(collidePlane+'.offsetFalloff',collideCondition+'.secondTerm',f=True) mc.connectAttr(falloffRemap+'.outValue',collideCondition+'.colorIfFalseB',f=True) - + # Set Offset Falloff mc.setAttr(collidePlane+'.offsetFalloff',abs(offsetFalloff)) - + # ============================== # - Calculate Distance Falloff - # ============================== - + if distanceFalloff != None: - + # Add Collide Attributes if not mc.attributeQuery('distanceFalloff',n=collidePlane,ex=True): mc.addAttr(collidePlane,ln='distanceFalloff',min=0,dv=1,k=True) - + # Distance Remap distRemap = mc.createNode('remapValue',n=prefix+'_collideDist_remapValue') mc.connectAttr(collidePlane+'.distanceFalloff',distRemap+'.inputMax',f=True) mc.setAttr(distRemap+'.outputMin',1) mc.setAttr(distRemap+'.outputMax',0) mc.setAttr(distRemap+'.inputMin',0) - + # Distance Falloff collideDist = mc.createNode('distanceBetween',n=prefix+'_collideDist_distanceBetween') if len(distanceAxis) == 1: @@ -187,20 +187,20 @@ def planeCollideTransform( targetTransform, else: raise Exception('Invalid collision distance axis! ('+str(distanceAxis)+')') mc.connectAttr(collideDist+'.distance',distRemap+'.inputValue',f=True) - + # Distance Weight distMult = mc.createNode('multDoubleLinear',n=prefix+'_distanceWeight_multDoubleLinear') mc.connectAttr(collidePlane+'.collideWeight',distMult+'.input1',f=True) mc.connectAttr(distRemap+'.outValue',distMult+'.input2',f=True) mc.connectAttr(distMult+'.output',collideBlend+'.blender',f=True) - + # Set Distance Falloff mc.setAttr(collidePlane+'.distanceFalloff',abs(distanceFalloff)) - + # ================= # - Return Result - # ================= - + return [collidePlane,collideTransform] def doublePlaneCollideTransform( targetTransform, @@ -233,35 +233,35 @@ def doublePlaneCollideTransform( targetTransform, # ========== # - Checks - # ========== - + # Check Target Transforms if not mc.objExists(targetTransform): raise Exception('Target transform "'+targetTransform+'" does not exist!') if not glTools.utils.transform.isTransform(targetTransform): raise Exception('Object "'+targetTransform+'" is not a valid transform!') - + # Check Collide Transforms if collideTransform and not mc.objExists(str(collideTransform)): raise Exception('Collide transform "'+collideTransform+'" does not exist!') if not glTools.utils.transform.isTransform(collideTransform): raise Exception('Object "'+collideTransform+'" is not a valid transform!') - + # Check Collide Plane if collidePlane and not mc.objExists(str(collidePlane)): raise Exception('Collide plane "'+collidePlane+'" does not exist!') if not glTools.utils.transform.isTransform(collidePlane): raise Exception('Object "'+collidePlane+'" is not a valid transform!') - + # Check Distance Axis if distanceAxis: distanceAxis = distanceAxis.upper() - + # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(targetTransform) - + # =================== # - Build Collision - # =================== - + # Build Collide Objects if not collideTransform: collideTransform = mc.spaceLocator(n=prefix+'_collide_loc')[0] @@ -269,11 +269,11 @@ def doublePlaneCollideTransform( targetTransform, collidePlaneShape = mc.createNode('renderRect') collidePlane = mc.listRelatives(collidePlaneShape,p=True)[0] collidePlane = mc.rename(collidePlane,prefix+'_collide_plane') - + # Add Collide Attributes if not mc.attributeQuery('collideWeight',n=collidePlane,ex=True): mc.addAttr(collidePlane,ln='collideWeight',min=0,max=1,dv=1,k=True) - + # Build Collide Nodes collideCondition = mc.createNode('condition',n=prefix+'_collide_condition') collideBlend = mc.createNode('blendColors',n=prefix+'_collideWeight_blendColors') @@ -283,11 +283,11 @@ def doublePlaneCollideTransform( targetTransform, mc.setAttr(collideToWorld+'.operation',4) # Point Matrix Product worldToLocal = mc.createNode('vectorProduct',n=prefix+'_worldToLocal_vectorProduct') mc.setAttr(worldToLocal+'.operation',4) # Point Matrix Product - + # ========================= # - Build Collide Network - # ========================= - + # World To Collide mc.connectAttr(collidePlane+'.worldInverseMatrix[0]',worldToCollide+'.matrix',f=True) if mc.objExists(targetTransform+'.worldPosition[0]'): @@ -297,7 +297,7 @@ def doublePlaneCollideTransform( targetTransform, mc.setAttr(localToWorld+'.operation',4) # Point Matrix Product mc.connectAttr(targetTransform+'.worldMatrix[0]',localToWorld+'.matrix',f=True) mc.connectAttr(localToWorld+'.output',worldToCollide+'.input1',f=True) - + # Collide Condition mc.connectAttr(worldToCollide+'.outputZ',collideCondition+'.firstTerm',f=True) mc.setAttr(collideCondition+'.secondTerm',0) @@ -306,37 +306,37 @@ def doublePlaneCollideTransform( targetTransform, mc.connectAttr(worldToCollide+'.outputX',collideCondition+'.colorIfFalseR',f=True) mc.connectAttr(worldToCollide+'.outputY',collideCondition+'.colorIfFalseG',f=True) mc.setAttr(collideCondition+'.colorIfFalseB',0) - + # Collide Weight Blend mc.connectAttr(collideCondition+'.outColor',collideBlend+'.color1',f=True) mc.connectAttr(worldToCollide+'.output',collideBlend+'.color2',f=True) mc.connectAttr(collidePlane+'.collideWeight',collideBlend+'.blender',f=True) - + # Collide To World mc.connectAttr(collideBlend+'.output',collideToWorld+'.input1',f=True) mc.connectAttr(collidePlane+'.worldMatrix[0]',collideToWorld+'.matrix',f=True) - + # World To Local mc.connectAttr(collideToWorld+'.output',worldToLocal+'.input1',f=True) mc.connectAttr(collideTransform+'.parentInverseMatrix[0]',worldToLocal+'.matrix',f=True) - + # Connect Output mc.connectAttr(worldToLocal+'.output',collideTransform+'.translate',f=True) - + # ============================ # - Calculate Offset Falloff - # ============================ - + if offsetFalloff != None: - + # Add Collide Attributes if not mc.attributeQuery('offsetFalloff',n=collidePlane,ex=True): mc.addAttr(collidePlane,ln='offsetFalloff',min=0,dv=0.5,k=True) - + # Build Nodes falloffRemap = mc.createNode('remapValue',n=prefix+'_offsetFalloff_remapValue') falloffMult = mc.createNode('multDoubleLinear',n=prefix+'_offsetFalloff_multDoubleLinear') - + # Falloff Remap mc.connectAttr(worldToCollide+'.outputZ',falloffRemap+'.inputValue',f=True) mc.connectAttr(collidePlane+'.offsetFalloff',falloffRemap+'.inputMax',f=True) @@ -344,31 +344,31 @@ def doublePlaneCollideTransform( targetTransform, mc.connectAttr(collidePlane+'.offsetFalloff',falloffMult+'.input1',f=True) mc.setAttr(falloffMult+'.input2',-1) mc.connectAttr(falloffMult+'.output',falloffRemap+'.inputMin',f=True) - + # Override Collide Condition mc.connectAttr(collidePlane+'.offsetFalloff',collideCondition+'.secondTerm',f=True) mc.connectAttr(falloffRemap+'.outValue',collideCondition+'.colorIfFalseB',f=True) - + # Set Offset Falloff mc.setAttr(collidePlane+'.offsetFalloff',abs(offsetFalloff)) - + # ============================== # - Calculate Distance Falloff - # ============================== - + if distanceFalloff != None: - + # Add Collide Attributes if not mc.attributeQuery('distanceFalloff',n=collidePlane,ex=True): mc.addAttr(collidePlane,ln='distanceFalloff',min=0,dv=1,k=True) - + # Distance Remap distRemap = mc.createNode('remapValue',n=prefix+'_collideDist_remapValue') mc.connectAttr(collidePlane+'.distanceFalloff',distRemap+'.inputMax',f=True) mc.setAttr(distRemap+'.outputMin',1) mc.setAttr(distRemap+'.outputMax',0) mc.setAttr(distRemap+'.inputMin',0) - + # Distance Falloff collideDist = mc.createNode('distanceBetween',n=prefix+'_collideDist_distanceBetween') if len(distanceAxis) == 1: @@ -379,20 +379,20 @@ def doublePlaneCollideTransform( targetTransform, else: raise Exception('Invalid collision distance axis! ('+str(distanceAxis)+')') mc.connectAttr(collideDist+'.distance',distRemap+'.inputValue',f=True) - + # Distance Weight distMult = mc.createNode('multDoubleLinear',n=prefix+'_distanceWeight_multDoubleLinear') mc.connectAttr(collidePlane+'.collideWeight',distMult+'.input1',f=True) mc.connectAttr(distRemap+'.outValue',distMult+'.input2',f=True) mc.connectAttr(distMult+'.output',collideBlend+'.blender',f=True) - + # Set Distance Falloff mc.setAttr(collidePlane+'.distanceFalloff',abs(distanceFalloff)) - + # ================= # - Return Result - # ================= - + return def surfaceCollideTransform(targetTransform,slaveTransform,collideSurface,inside=True,prefix=''): @@ -401,7 +401,7 @@ def surfaceCollideTransform(targetTransform,slaveTransform,collideSurface,inside # ========== # - Checks - # ========== - + if not mc.objExists(targetTransform): raise Exception('Target transform "'+targetTransform+'" does not exist!') if not mc.objExists(slaveTransform): @@ -410,43 +410,43 @@ def surfaceCollideTransform(targetTransform,slaveTransform,collideSurface,inside raise Exception('Collide surface "'+collideSurface+'" does not exist!') if not glTools.utils.surface.isSurface(collideSurface): raise Exception('Collide object "'+collideSurface+'" is not a valid NURBS surface!') - + if not prefix: prefix = 'collideSurface' - + # =================== # - Create Locators - # =================== - + slave_loc = mc.spaceLocator(n=slaveTransform+'_loc')[0] target_loc = mc.spaceLocator(n=targetTransform+'_loc')[0] target_ptCon = mc.pointConstraint(targetTransform,target_loc)[0] - + # - Setup - con = mc.createNode('condition',n=prefix+'_condition') vp = mc.createNode('vectorProduct',n=prefix+'_vectorProduct') pma = mc.createNode('plusMinusAverage',n=prefix+'_plusMinusAverage') posi = mc.createNode('pointOnSurfaceInfo',n=prefix+'_pointOnSurfaceInfo') cpos = mc.createNode('closestPointOnSurface',n=prefix+'_closestPointOnSurface') - + # Surface Connect mc.connectAttr(collideSurface+'.worldSpace[0]',posi+'.inputSurface',f=True) mc.connectAttr(collideSurface+'.worldSpace[0]',cpos+'.inputSurface',f=True) mc.connectAttr(target_loc+'.worldPosition[0]',cpos+'.inPosition',f=True) - + # Parameter Connect mc.connectAttr(cpos+'.parameterU',posi+'.parameterU',f=True) mc.connectAttr(cpos+'.parameterV',posi+'.parameterV',f=True) - + # Offset Calc mc.setAttr(pma+'.operation',2) # SUBTRACT mc.connectAttr(target_loc+'.worldPosition[0]',pma+'.input3D[0]',f=True) mc.connectAttr(cpos+'.position',pma+'.input3D[1]',f=True) - + # Dot Product mc.setAttr(vp+'.operation',1) # DOT PRODUCT mc.connectAttr(posi+'.normal',vp+'.input1',f=True) mc.connectAttr(pma+'.output3D',vp+'.input2',f=True) - + # Condition if inside: mc.setAttr(con+'.operation',2) # Greater Than else: mc.setAttr(con+'.operation',4) # Less Than @@ -454,7 +454,7 @@ def surfaceCollideTransform(targetTransform,slaveTransform,collideSurface,inside mc.connectAttr(vp+'.outputX',con+'.secondTerm',f=True) mc.connectAttr(target_loc+'.worldPosition[0]',con+'.colorIfTrue',f=True) mc.connectAttr(cpos+'.position',con+'.colorIfFalse',f=True) - + # Output mc.connectAttr(con+'.outColor',slave_loc+'.t',f=True) diff --git a/tools/connectionAttrStorage.py b/tools/connectionAttrStorage.py index b9f09ce..3a09832 100644 --- a/tools/connectionAttrStorage.py +++ b/tools/connectionAttrStorage.py @@ -7,138 +7,138 @@ def __init__(self): self.nodes = [] self.connectionStorage={} self.storageAttr = 'connectionStorage' - + def storeData(self, nodes=None): - + if nodes: self.addNodes(nodes) - + if not self.nodes: raise Exception('No nodes to store data for.') - + self.getParent() self.getIncomingConnections() self.getOutgoingConnections() self.createAttrs() self.setAttrs() - + def rebuild(self): pass - + def addNodes(self, nodes): for node in nodes: self.nodes.append(node) - + def getParent(self): - + if not self.nodes: raise Exception('No nodes added to get parents of.') - + for node in self.nodes: if not glTools.utils.transform.isTransform(node): continue - + parent = mc.listRelatives(node, allParents=True)[0] - + if not self.connectionStorage.has_key(node): self.connectionStorage[node] = [] - - self.connectionStorage[node].append(['parent', parent]) - - + + self.connectionStorage[node].append(['parent', parent]) + + def getIncomingConnections(self): - + if not self.nodes: raise Exception('No nodes added to get incoming connections on.') - + for node in self.nodes: connections = mc.listConnections(node, plugs=True, source=True, destination=False, connections=True, skipConversionNodes=True) - + if not connections: continue - + if not self.connectionStorage.has_key(node): self.connectionStorage[node] = [] - + count = len(self.connectionStorage[node]) - + # set connection source - for i in range(1, len(connections), 2): self.connectionStorage[node].append([connections[i], None]) - + for i in range(1, len(connections), 2): self.connectionStorage[node].append([connections[i], None]) + # set connection destination for i in range(0, len(connections), 2): - self.connectionStorage[node][count][1] = connections[i] + self.connectionStorage[node][count][1] = connections[i] count+=1 def getOutgoingConnections(self): - + if not self.nodes: raise Exception('No nodes added to get outgoing connections on.') - + for node in self.nodes: connections = mc.listConnections(node, plugs=True, source=False, destination=True, connections=True, skipConversionNodes=True) - + if not connections: continue - + if not self.connectionStorage.has_key(node): self.connectionStorage[node] = [] - + count = len(self.connectionStorage[node]) - + # set connection source - for i in range(0, len(connections), 2): self.connectionStorage[node].append([connections[i], None]) - + for i in range(0, len(connections), 2): self.connectionStorage[node].append([connections[i], None]) + # set connection destination for i in range(1, len(connections), 2): - self.connectionStorage[node][count][1] = connections[i] + self.connectionStorage[node][count][1] = connections[i] count+=1 - + def createAttrs(self): - + if not self.connectionStorage: raise Exception('No nodes added to create attributes on.') - + for node in self.connectionStorage.keys(): if not mc.objExists('%s.%s' % (node, self.storageAttr)): mc.addAttr(node,ln=self.storageAttr,dataType='string',en=':Keyable:NonKeyable:Locked:',m=1) - + def setAttrs(self): if not self.connectionStorage: raise Exception('No connection data stored to set attributes with.') - + for node in self.connectionStorage.keys(): for i, connection in enumerate(self.connectionStorage[node]): mc.setAttr('%s.%s[%s]' % (node, self.storageAttr, i), str(connection), type='string') print 'Set :: %s.%s[%s], To :: %s' % (node, self.storageAttr, i, connection) - + def getAttrs(self): if not self.nodes: raise Exception('No nodes added to get attribute data from.') - + for node in self.nodes: - + if not self.connectionStorage.has_key(node): self.connectionStorage[node] = [] - - if not mc.objExists('%s.%s' % (node, self.storageAttr)): + + if not mc.objExists('%s.%s' % (node, self.storageAttr)): print "Skipping %s because it does not have a %s attribute." % (node, self.storageAttr) continue - + for index in mc.getAttr('%s.%s' % (node, self.storageAttr), multiIndices=True): self.connectionStorage[node].append( eval(mc.getAttr('%s.%s[%s]' % (node, self.storageAttr, index))) ) def rebuildConnections(self): if not self.connectionStorage: - raise Exception('No connection data stored to connect attributes with.') - + raise Exception('No connection data stored to connect attributes with.') + for node in self.connectionStorage: print "Node :: %s" % node for connectionPair in self.connectionStorage[node]: - + if connectionPair[0] == 'parent': try: mc.parent(node, connectionPair[1]) except: print "Could not connect :: %s To :: %s" % (node, connectionPair[1]) - + if not mc.objExists(connectionPair[0]) or not mc.objExists(connectionPair[1]): print '%s or %s are not valid objects, skipping to the next connection' % (connectionPair[0], connectionPair[1]) continue - + print "Connecting :: %s To :: %s" % (connectionPair[0], connectionPair[1]) - + if not mc.isConnected(connectionPair[0], connectionPair[1]): try: mc.connectAttr(connectionPair[0], connectionPair[1], f=True) except: print "Could not connect :: %s To :: %s" % (connectionPair[0], connectionPair[1]) - - + + diff --git a/tools/connectionHub.py b/tools/connectionHub.py index 623d80a..a1cadcd 100644 --- a/tools/connectionHub.py +++ b/tools/connectionHub.py @@ -22,11 +22,11 @@ def connectionHubNode(prefix): ''' # Create Hub Node hub = mc.createNode('transform',n=prefix+'_connectionHub') - + # Add Connection Hub Attribute mc.addAttr(hub,ln='connectionHub',dt='string') mc.setAttr(hub+'.connectionHub',prefix,type='string',l=True,k=False) - + # Return Result return hub @@ -45,33 +45,33 @@ def addConnection(hub,attr,output=True,connect=True): # ========== # - Checks - # ========== - + if not isHub(hub): raise Exception('Object "'+hub+'" is not a valid connection hub node!') - + if not glTools.utils.attribute.isAttr(attr): raise Exception('Object "'+attr+'" is not a valid attribute!') - + # ============================ # - Add Connection Attribute - # ============================ - + # Determine connection attribute name suffix = '' if output: suffix = 'OUT' else: suffix = 'IN' - + connectionAttr = re.sub('\.','__',attr) + suffix - + # Add Attribute mc.addAttr(hub,ln=connectionAttr,k=True) - + # ===================== # - Connect Attribute - # ===================== - + if connect: - + if output: # Connect Output mc.connectAttr(attr,hub+'.'+connectionAttr,f=True) @@ -82,11 +82,11 @@ def addConnection(hub,attr,output=True,connect=True): # Connect Input mc.setAttr(attr,l=False) mc.connectAttr(hub+'.'+connectionAttr,attr,f=True) - + # ================= # - Return Result - # ================= - + return hub+'.'+connectionAttr def connect(hub): @@ -94,7 +94,7 @@ def connect(hub): ''' # Get Hub Attributes for hubAttr in pm.PyNode(hub).listAttr(ud=True): - + # Get Attribute Name Components inout, node, nodeAttr = hubAttr.attrName().split('__') try: @@ -118,60 +118,60 @@ def connectToHub(hub1,hub2): # ========== # - Checks - # ========== - + if not isHub(hub1): raise Exception('Object "'+hub1+'" is not a valid connection hub node!') if not isHub(hub2): raise Exception('Object "'+hub2+'" is not a valid connection hub node!') - + # =========== # - Connect - # =========== - + # Get connection attribute lists hub1_attrs = mc.listAttr(hub1,ud=True,k=True) hub2_attrs = mc.listAttr(hub2,ud=True,k=True) - + # Connect HUB1 >>> HUB2 for attr in hub1_attrs: - + # Check Output if attr.endswith('OUT'): - - # Get connection source/destination attributes + + # Get connection source/destination attributes srcAttr = hub1+'.'+attr dstAttr = hub2+'.'+attr.replace('OUT','IN') # Check destination attribute if not glTools.utils.attribute.isAttr(dstAttr): raise Exception('Destination attribute "'+dstAttr+'" does not exist!') - + # Connect print('Connecting hub attributes:') print('\t'+srcAttr+' >>> '+dstAttr+) mc.connectAttr(srcAttr,dstAttr,f=True) - + # Connect HUB2 >>> HUB1 for attr in hub2_attrs: - + # Check Output if attr.endswith('OUT'): - - # Get connection source/destination attributes + + # Get connection source/destination attributes srcAttr = hub2+'.'+attr dstAttr = hub1+'.'+attr.replace('OUT','IN') # Check destination attribute if not glTools.utils.attribute.isAttr(dstAttr): raise Exception('Destination attribute "'+dstAttr+'" does not exist!') - + # Connect print('Connecting hub attributes:') print('\t'+srcAttr+' >>> '+dstAttr+) mc.connectAttr(srcAttr,dstAttr,f=True) - + # ================= # - Return Result - # ================= - + print('Successfully Connected Hubs: ["'+hub1+'" << >> "'+hub2+'"]') def connectCopy(hub): @@ -180,6 +180,6 @@ def connectCopy(hub): # ========== # - Checks - # ========== - + if not isHub(hub): raise Exception('Object "'+hub+'" is not a valid connection hub node!') diff --git a/tools/constraint.py b/tools/constraint.py index ccd50aa..6fe7e3c 100644 --- a/tools/constraint.py +++ b/tools/constraint.py @@ -13,7 +13,7 @@ import types -def bake( constraint, +def bake( constraint, start = None, end = None, sampleBy = 1, @@ -34,31 +34,31 @@ def bake( constraint, # ========== # - Checks - # ========== - + # Check Constraint if not glTools.utils.constraint.isConstraint(constraint): raise Exception('Object "'+constraint+'" is not a valid constraint node!') - + # Check Start/End Frames if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # ==================================== # - Get Slave Transform and Channels - # ==================================== - + # Get Slave Transform slave = glTools.utils.constraint.slave(constraint) - + # Get Slave Channels attrList = mc.listConnections(constraint,s=False,d=True,p=True) or [] slaveAttrs = [i.split('.')[-1] for i in attrList if i.startswith(slave+'.')] or [] if not slaveAttrs: raise Exception('No slave channels to bake!') - + # =================== # - Bake Constraint - # =================== - + mc.refresh(suspend=True) mc.bakeResults( slave, at = slaveAttrs, @@ -67,11 +67,11 @@ def bake( constraint, simulation = simulation, sampleBy = sampleBy ) mc.refresh(suspend=False) - + # ================= # - Return Result - # ================= - + return [slave+'.'+i for i in slaveAttrs] def aimConstraint( target, @@ -105,34 +105,34 @@ def aimConstraint( target, ''' # Build Axis Dict axis = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # ========== # - Checks - # ========== - + # Check Master if not mc.objExists(target): raise Exception('Constraint target "'+target+'" does not exist!') if not glTools.utils.transform.isTransform(target): raise Exception('Constraint target "'+target+'" is not a valid transform!') - + # Check Slave if not mc.objExists(slave): raise Exception('Constraint slave "'+slave+'" does not exist!') if not glTools.utils.transform.isTransform(slave): raise Exception('Constraint slave "'+slave+'" is not a valid transform!') - + # Check Settable Channels sk = [] if not mc.getAttr(slave+'.rx',se=True): sk.append('x') if not mc.getAttr(slave+'.ry',se=True): sk.append('y') if not mc.getAttr(slave+'.rz',se=True): sk.append('z') if not sk: sk = 'none' - + # ===================== # - Create Constraint - # ===================== - + constraint = '' try: if worldUpObject: @@ -158,11 +158,11 @@ def aimConstraint( target, mo=mo)[0] except Exception, e: raise Exception('Error creating constraint from "'+target+'" to "'+slave+'"! Exception msg: '+str(e)) - + # ================= # - Return Result - # ================= - + return constraint def pointConstraint(master,slave,mo=False,attrList=['tx','ty','tz']): @@ -181,7 +181,7 @@ def pointConstraint(master,slave,mo=False,attrList=['tx','ty','tz']): # ========== # - Checks - # ========== - + # Check Target (Master) if isinstance(master,types.StringTypes): if not mc.objExists(master): @@ -194,38 +194,38 @@ def pointConstraint(master,slave,mo=False,attrList=['tx','ty','tz']): raise Exception('Constraint target "'+target+'" does not exist!') if not glTools.utils.transform.isTransform(target): raise Exception('Constraint target "'+target+'" is not a valid transform!') - + # Check Slave if not mc.objExists(slave): raise Exception('Constraint slave "'+slave+'" does not exist!') if not glTools.utils.transform.isTransform(slave): raise Exception('Constraint slave "'+slave+'" is not a valid transform!') - + # Check Settable Channels st = [] if not 'tx' in attrList or not mc.getAttr(slave+'.tx',se=True): st.append('x') if not 'ty' in attrList or not mc.getAttr(slave+'.ty',se=True): st.append('y') if not 'tz' in attrList or not mc.getAttr(slave+'.tz',se=True): st.append('z') if not st: st = 'none' - + # Skip All Check if len(st) == 3: print('No axis to constrain! Unable to create constraint...') return None - + # ===================== # - Create Constraint - # ===================== - + constraint = '' try: constraint = mc.pointConstraint(master,slave,sk=st,mo=mo)[0] except Exception, e: raise Exception('Error creating constraint from "'+master+'" to "'+slave+'"! Exception msg: '+str(e)) - + # ================= # - Return Result - # ================= - + return constraint def orientConstraint(master,slave,mo=False,attrList=['rx','ry','rz']): @@ -244,7 +244,7 @@ def orientConstraint(master,slave,mo=False,attrList=['rx','ry','rz']): # ========== # - Checks - # ========== - + # Check Target (Master) if isinstance(master,types.StringTypes): if not mc.objExists(master): @@ -257,38 +257,38 @@ def orientConstraint(master,slave,mo=False,attrList=['rx','ry','rz']): raise Exception('Constraint target "'+target+'" does not exist!') if not glTools.utils.transform.isTransform(target): raise Exception('Constraint target "'+target+'" is not a valid transform!') - + # Check Slave if not mc.objExists(slave): raise Exception('Constraint slave "'+slave+'" does not exist!') if not glTools.utils.transform.isTransform(slave): raise Exception('Constraint slave "'+slave+'" is not a valid transform!') - + # Check Settable Channels sr = [] if not 'rx' in attrList or not mc.getAttr(slave+'.rx',se=True): sr.append('x') if not 'ry' in attrList or not mc.getAttr(slave+'.ry',se=True): sr.append('y') if not 'rz' in attrList or not mc.getAttr(slave+'.rz',se=True): sr.append('z') if not st: st = 'none' - + # Skip All Check if len(sr) == 3: print('No axis to constrain! Unable to create constraint...') return None - + # ===================== # - Create Constraint - # ===================== - + constraint = '' try: constraint = mc.orientConstraint(master,slave,sk=sr,mo=mo)[0] except Exception, e: raise Exception('Error creating constraint from "'+master+'" to "'+slave+'"! Exception msg: '+str(e)) - + # ================= # - Return Result - # ================= - + return constraint def parentConstraint(master,slave,mo=False,attrList=['tx','ty','tz','rx','ry','rz']): @@ -307,7 +307,7 @@ def parentConstraint(master,slave,mo=False,attrList=['tx','ty','tz','rx','ry','r # ========== # - Checks - # ========== - + # Check Target (Master) if isinstance(master,types.StringTypes): if not mc.objExists(master): @@ -320,13 +320,13 @@ def parentConstraint(master,slave,mo=False,attrList=['tx','ty','tz','rx','ry','r raise Exception('Constraint target "'+target+'" does not exist!') if not glTools.utils.transform.isTransform(target): raise Exception('Constraint target "'+target+'" is not a valid transform!') - + # Check Slave if not mc.objExists(slave): raise Exception('Constraint slave "'+slave+'" does not exist!') if not glTools.utils.transform.isTransform(slave): raise Exception('Constraint slave "'+slave+'" is not a valid transform!') - + # Check Settable Channels st = [] sr = [] @@ -338,20 +338,20 @@ def parentConstraint(master,slave,mo=False,attrList=['tx','ty','tz','rx','ry','r if not 'rz' in attrList or not mc.getAttr(slave+'.rz',se=True): sr.append('z') if not st: st = 'none' if not sr: sr = 'none' - + # ===================== # - Create Constraint - # ===================== - + constraint = '' try: constraint = mc.parentConstraint(master,slave,st=st,sr=sr,mo=mo)[0] except Exception, e: raise Exception('Error creating constraint from "'+master+'" to "'+slave+'"! Exception msg: '+str(e)) - + # ================= # - Return Result - # ================= - + return constraint def scaleConstraint(master,slave,mo=False,force=False,attrList=['sx','sy','sz']): @@ -372,48 +372,48 @@ def scaleConstraint(master,slave,mo=False,force=False,attrList=['sx','sy','sz']) # ========== # - Checks - # ========== - + # Check Master if not mc.objExists(master): raise Exception('Constraint master "'+master+'" does not exist!') if not glTools.utils.transform.isTransform(master): raise Exception('Constraint master "'+master+'" is not a valid transform!') - + # Check Slave if not mc.objExists(slave): raise Exception('Constraint slave "'+slave+'" does not exist!') if not glTools.utils.transform.isTransform(slave): raise Exception('Constraint slave "'+slave+'" is not a valid transform!') - + # Check Settable Channels sk = [] if not 'sx' in attrList or not mc.getAttr(slave+'.sx',se=True): sk.append('x') if not 'sy' in attrList or not mc.getAttr(slave+'.sy',se=True): sk.append('y') if not 'sz' in attrList or not mc.getAttr(slave+'.sz',se=True): sk.append('z') if not sk: st = 'none' - + # Check All if len(sk) == 3: print('All scale channels locked! Unable to add constraint') return None - + # ===================== # - Create Constraint - # ===================== - + if force: mc.cutKey(slave,at=attrList) - + constraint = '' try: constraint = mc.scaleConstraint(master,slave,sk=sk,mo=mo)[0] except Exception, e: #raise Exception('Error creating constraint from "'+master+'" to "'+slave+'"! Exception msg: '+str(e)) print('Error creating constraint from "'+master+'" to "'+slave+'"! Exception msg: '+str(e)) constraint = None - + # ================= # - Return Result - # ================= - + return constraint def nonReferencedConstraints(slaveNSfilter=None,targetNSfilter=None): @@ -428,21 +428,21 @@ def nonReferencedConstraints(slaveNSfilter=None,targetNSfilter=None): # ========================= # - Get Scene Constraints - # ========================= - + sceneConstraints = mc.ls(type='constraint') if not sceneConstraints: return [] - + # Filter Nonreferenced Constraints nonRefConstraints = [] for constraint in sceneConstraints: if not glTools.utils.reference.isReferenced(constraint): if not constraint in nonRefConstraints: nonRefConstraints.append(constraint) - + # ================= # - Filter Result - # ================= - + # Slave Namespace Filter if slaveNSfilter: for constraint in nonRefConstraints: @@ -454,7 +454,7 @@ def nonReferencedConstraints(slaveNSfilter=None,targetNSfilter=None): if slaveNS in slaveNSfilter: filterOut = False if filterOut: nonRefConstraints.remove(constraint) - + # Master Namespace Filter if targetNSfilter: for constraint in nonRefConstraints: @@ -466,11 +466,11 @@ def nonReferencedConstraints(slaveNSfilter=None,targetNSfilter=None): if targetNS in targetNSfilter: filterOut = False if filterOut: nonRefConstraints.remove(constraint) - + # ================= # - Return Result - # ================= - + return nonRefConstraints def listReferenceDependents(): @@ -500,44 +500,44 @@ def translateOffsetTarget(target,offset,slave,prefix=None): # ========== # - Checks - # ========== - + # Target if not mc.objExists(target): raise Exception('Target transform "'+target+'" does not exist!') if not glTools.utils.transform.isTransform(target): raise Exception('Target object "'+target+'" is not a valid tranform!') - + # Offset if not mc.objExists(offset): raise Exception('Offset transform "'+offset+'" does not exist!') if not glTools.utils.transform.isTransform(offset): raise Exception('Offset object "'+offset+'" is not a valid tranform!') - + # Slave if not mc.objExists(slave): raise Exception('Slave transform "'+slave+'" does not exist!') if not glTools.utils.transform.isTransform(slave): raise Exception('Slave object "'+slave+'" is not a valid tranform!') - + # Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(slave) - + # ==================== # - Build Constraint - # ==================== - + # Parent Slave to Target mc.delete(parentConstraint(target,slave)) mc.parent(slave,target) - + # Create Offset Constraint offsetConstraint = mc.pointConstraint(offset,slave,mo=True)[0] offsetConstraint = mc.rename(offsetConstraint,prefix+'_offset_pointConstraint') - + # ================= # - Return Result - # ================= - + return offsetConstraint def pointOnPolyConstraintCmd(pt): @@ -549,34 +549,34 @@ def pointOnPolyConstraintCmd(pt): # ================== # - Initialize Cmd - # ================== - + cmd = '' - + # =============================== # - Get Mesh from Point on Poly - # =============================== - + fullname = mc.ls(pt,o=True)[0] mesh = fullname.split(':')[-1] meshSN = mesh.split('|')[-1] - + # Get Mesh Component ID meshID = glTools.utils.component.index(pt) - + prevID = OpenMaya.MScriptUtil() prevID.createFromInt(0) prevIDPtr = prevID.asIntPtr() - + # ======================= # - Constrain to Vertex - # ======================= - + if '.vtx[' in pt: - + # Initialize MItMeshVertex meshIt = glTools.utils.mesh.getMeshVertexIter(mesh) meshIt.setIndex(meshID,prevIDPtr) - + # Get Vertex UV uv = OpenMaya.MScriptUtil() uv.createFromDouble(0.0) @@ -584,17 +584,17 @@ def pointOnPolyConstraintCmd(pt): meshIt.getUV(uvPtr) uv = [ OpenMaya.MScriptUtil.getFloat2ArrayItem(uvPtr,0,j) for j in [0,1] ] cmd += '; setAttr ($constraint[0]+".%sU%d") %f; setAttr ($constraint[0]+".%sV%d") %f' % ( meshSN, 0, uv[0], meshSN, 0, uv[1] ) - + # ===================== # - Constrain to Edge - # ===================== - + elif '.e[' in pt: - + # Initialize MItMeshEdge meshIt = glTools.utils.mesh.getMeshEdgeIter(mesh) meshIt.setIndex(meshID,prevIDPtr) - + # Get Edge/Vertices UV vtx = [ meshIt.index( j ) for j in [0,1] ] vtxIt = glTools.utils.mesh.getMeshVertexIter(mesh) @@ -608,27 +608,27 @@ def pointOnPolyConstraintCmd(pt): uvs.append( [ OpenMaya.MScriptUtil.getFloat2ArrayItem(uvPtr,0,j) for j in [0,1] ] ) uv = [ 0.5*(uvs[0][j]+uvs[1][j]) for j in [0,1] ] cmd += '; setAttr ($constraint[0]+".%sU%d") %f; setAttr ($constraint[0]+".%sV%d") %f' % ( meshSN, 0, uv[0], meshSN, 0, uv[1] ) - + # ===================== # - Constrain to Face - # ===================== - + elif '.f[' in pt: - + # Initialize MItMeshface meshIt = glTools.utils.mesh.getMeshFaceIter(mesh) meshIt.setIndex(meshID,prevIDPtr) - + # Get Face UV u, v = OpenMaya.MFloatArray(), OpenMaya.MFloatArray() meshIt.getUVs( u, v ) uv = ( sum(u)/len(u), sum(v)/len(v) ) cmd += '; setAttr ($constraint[0]+".%sU%d") %f; setAttr ($constraint[0]+".%sV%d") %f' % ( meshSN, 0, uv[0], meshSN, 0, uv[1] ) - + # ================= # - Return Result - # ================= - + return cmd diff --git a/tools/controlBuilder.py b/tools/controlBuilder.py index b664666..0b6e15e 100644 --- a/tools/controlBuilder.py +++ b/tools/controlBuilder.py @@ -7,7 +7,7 @@ import glTools.utils.curve class ControlBuilder( object ): - + def __init__(self): ''' ControlBuilder Class Initializer @@ -16,7 +16,7 @@ def __init__(self): self.overrideId = { 'lf':14, 'rt':13, 'cn':17 } - + # Supported Control Types self.controlType = [ 'anchor', 'arch', @@ -43,12 +43,12 @@ def __init__(self): 'tab', 'teardrop', 'text' ] - + # Control LOD list self.controlLod = [ 'primary', 'secondary', 'tertiary' ] - + def create( self, controlType, controlName, @@ -78,22 +78,22 @@ def create( self, # ========== # - Checks - # ========== - + # Check controlName nameInd = 1 origControlName = controlName while mc.objExists(controlName): controlName = origControlName + str(nameInd) nameInd += 1 - + # Check Control Type if not self.controlType.count(controlType): raise Exception('Unsupported control shape type("'+controlType+'")!!') - + # ================== # - Create Control - # ================== - + control = '' if controlType == 'anchor': control = self.anchor() elif controlType == 'arch': control = self.arch() @@ -121,19 +121,19 @@ def create( self, elif controlType == 'teardrop': control = self.teardrop() elif controlType == 'text': control = self.text(text=text) else: raise Exception('Unsupported control shape type("'+controlType+'")!!') - + # Get Controls Shape(s) control = mc.rename(control,controlName) controlShape = mc.listRelatives(control,s=1,ni=1,pa=True) if not controlShape: raise Exception('No control shape found!') for c in range(len(controlShape)): - + # Rename Control Shape ctrlShape = mc.rename(controlShape[c],control+'Shape'+str(c+1)) - + # Reorder mc.reorder(ctrlShape,b=True) - + # Assign Control Shape Colour prefix = controlName.split('_')[0] if colour: @@ -142,31 +142,31 @@ def create( self, elif self.overrideId.has_key(prefix): mc.setAttr(ctrlShape+'.overrideEnabled',1) mc.setAttr(ctrlShape+'.overrideColor',self.overrideId[prefix]) - + # Position Control mc.move(translate[0],translate[1],translate[2],control,r=True) mc.rotate(rotate[0],rotate[1],rotate[2],control) mc.scale(scale,scale,scale,control) - + # Freeze Pivot and Transforms mc.xform(control,ws=True,piv=[0,0,0]) mc.makeIdentity(control,apply=True,translate=True,rotate=True,scale=True,normal=False) - + # Set Channel States glTools.utils.channelState.ChannelState().setFlags([0,0,0,0,0,0,0,0,0,1],[control]) - + # ====================== # - Create Control LOD - # ====================== - + glTools.rig.utils.tagCtrl(control,ctrlLod) - + # ================= # - Return Result - # ================= - + return str(control) - + def anchor(self): ''' Create anchor control object @@ -175,10 +175,10 @@ def anchor(self): pts = [(0.000,0.000,0.000),(0.000,0.826,0.000),(0.087,0.826,0.000),(0.087,1.000,0.000),(-0.087,1.000,0.000),(-0.087,0.826,0.000),(0.000,0.826,0.000)] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def arch(self): ''' Create arch control object @@ -187,10 +187,10 @@ def arch(self): pts = [(0.100,0.000,-0.500),(-0.100,0.000,-0.500),(-0.100,0.250,-0.433),(-0.100,0.433,-0.250),(-0.100,0.500,0.000),(-0.100,0.433,0.250),(-0.100,0.250,0.433),(-0.100,0.000,0.500),(0.100,0.000,0.500),(0.100,0.250,0.433),(0.100,0.433,0.250),(0.100,0.500,0.000),(0.100,0.433,-0.250),(0.100,0.250,-0.433),(0.100,0.000,-0.500)] knots = [0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0] control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def arrow(self): ''' Create arrow control object @@ -200,10 +200,10 @@ def arrow(self): (0.0,0.0,1.0), (-0.666,0.0,0.333), (-0.333,0.0,0.333), (-0.333,0.0,-1.0) ] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def arrowArc(self): ''' Create arrowArc control object @@ -212,10 +212,10 @@ def arrowArc(self): pts = [(0.0,0.414,-0.854),(0.0,0.487,-0.942),(0.0,0.148,-0.941),(0.0,0.226,-0.627),(0.0,0.293,-0.708),(0.0,0.542,-0.542),(0.0,0.708,-0.293),(0.0,0.767,0.0),(0.0,0.708,0.293),(0.0,0.542,0.542),(0.0,0.293,0.708),(0.0,0.235,0.607),(0.0,0.126,0.914),(0.0,0.445,0.967),(0.0,0.389,0.871),(0.0,0.678,0.678),(0.0,0.885,0.367),(0.0,0.958,0.0),(0.0,0.885,-0.367),(0.0,0.678,-0.678),(0.0,0.414,-0.854)] knots = [0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0] control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def arrowCircle(self): ''' Create arrowCircle control object @@ -224,10 +224,10 @@ def arrowCircle(self): pts=[(-0.654,-0.111,-0.000),(-0.639,-0.224,-0.000),(-0.585,-0.343,-0.000),(-0.477,-0.488,-0.000),(-0.353,-0.585,-0.000),(-0.224,-0.637,-0.000),(-0.111,-0.654,-0.000),(-0.111,-0.696,-0.000),(-0.111,-0.738,-0.000),(-0.111,-0.780,-0.000),(-0.148,-0.780,-0.000),(-0.186,-0.780,-0.000),(-0.223,-0.780,-0.000),(-0.148,-0.854,-0.000),(-0.007,-0.996,-0.000),(0.000,-1.003,-0.000),(0.007,-0.996,-0.000),(0.148,-0.854,-0.000),(0.223,-0.780,-0.000),(0.186,-0.780,-0.000),(0.148,-0.780,-0.000),(0.111,-0.780,-0.000),(0.111,-0.738,-0.000),(0.111,-0.696,-0.000),(0.111,-0.654,-0.000),(0.224,-0.639,-0.000),(0.343,-0.585,-0.000),(0.488,-0.477,-0.000),(0.585,-0.353,-0.000),(0.637,-0.224,-0.000),(0.654,-0.111,-0.000),(0.696,-0.111,-0.000),(0.738,-0.111,-0.000),(0.780,-0.111,-0.000),(0.780,-0.148,-0.000),(0.780,-0.186,-0.000),(0.780,-0.223,-0.000),(0.854,-0.148,-0.000),(0.990,-0.013,-0.000),(1.003,0.000,0.000),(0.990,0.013,0.000),(0.854,0.148,0.000),(0.780,0.223,0.000),(0.780,0.186,0.000),(0.780,0.148,0.000),(0.780,0.111,0.000),(0.738,0.111,0.000),(0.696,0.111,0.000),(0.654,0.111,0.000),(0.639,0.224,0.000),(0.585,0.343,0.000),(0.477,0.488,0.000),(0.353,0.585,0.000),(0.224,0.637,0.000),(0.111,0.654,0.000),(0.111,0.696,0.000),(0.111,0.738,0.000),(0.111,0.780,0.000),(0.148,0.780,0.000),(0.186,0.780,0.000),(0.223,0.780,0.000),(0.148,0.854,0.000),(0.013,1.015,0.000),(0.000,1.184,0.000),(-0.013,1.015,0.000),(-0.148,0.854,0.000),(-0.223,0.780,0.000),(-0.186,0.780,0.000),(-0.148,0.780,0.000),(-0.111,0.780,0.000),(-0.111,0.738,0.000),(-0.111,0.696,0.000),(-0.111,0.654,0.000),(-0.224,0.639,0.000),(-0.343,0.585,0.000),(-0.488,0.477,0.000),(-0.585,0.353,0.000),(-0.637,0.224,0.000),(-0.654,0.111,0.000),(-0.696,0.111,0.000),(-0.738,0.111,0.000),(-0.780,0.111,0.000),(-0.780,0.148,0.000),(-0.780,0.186,0.000),(-0.780,0.223,0.000),(-0.854,0.148,0.000),(-0.997,0.006,0.000),(-1.003,0.000,0.000),(-0.997,-0.006,-0.000),(-0.854,-0.148,-0.000),(-0.780,-0.223,-0.000),(-0.780,-0.186,-0.000),(-0.780,-0.148,-0.000),(-0.780,-0.111,-0.000),(-0.738,-0.111,-0.000),(-0.696,-0.111,-0.000),(-0.654,-0.111,-0.000)] knots=[0.0,0.0,0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0,32.0,33.0,34.0,35.0,36.0,37.0,38.0,39.0,40.0,41.0,42.0,43.0,44.0,45.0,46.0,47.0,48.0,49.0,50.0,51.0,52.0,53.0,54.0,55.0,56.0,57.0,58.0,59.0,60.0,61.0,62.0,63.0,64.0,65.0,66.0,67.0,68.0,69.0,70.0,71.0,72.0,73.0,74.0,75.0,76.0,77.0,78.0,79.0,80.0,81.0,82.0,83.0,84.0,85.0,86.0,87.0,88.0,89.0,90.0,91.0,92.0,93.0,94.0,94.0,94.0] control = mc.curve(d=3,p=pts,k=knots) - + # Return control name return control - + def box(self): ''' Create box control object @@ -241,54 +241,54 @@ def box(self): (0.5,0.5,0.5), (0.5,-0.5,0.5), (0.5,-0.5,-0.5) ] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def circle(self): ''' Create circle control object ''' return mc.circle(c=(0,0,0),nr=(0,0,1),sw=360,r=0.5,d=3,ut=0,tol=0.01,s=8,ch=0)[0] - + def corners(self): ''' Create corners control ''' ctrl = mc.createNode('transform') - + pts = [(0.9,0.0,1.0),(1.0,0.0,1.0),(1.0,0.0,0.9)] cnr = mc.curve(d=1,p=pts,k=range(3)) cnrShape = mc.listRelatives(cnr,s=True,ni=True)[0] mc.parent(cnrShape,ctrl,s=True,r=True) - + pts = [(-0.9,0.0,1.0),(-1.0,0.0,1.0),(-1.0,0.0,0.9)] cnr = mc.curve(d=1,p=pts,k=range(3)) cnrShape = mc.listRelatives(cnr,s=True,ni=True)[0] mc.parent(cnrShape,ctrl,s=True,r=True) - + pts = [(0.9,0.0,-1.0),(1.0,0.0,-1.0),(1.0,0.0,-0.9)] cnr = mc.curve(d=1,p=pts,k=range(3)) cnrShape = mc.listRelatives(cnr,s=True,ni=True)[0] mc.parent(cnrShape,ctrl,s=True,r=True) - + pts = [(-0.9,0.0,-1.0),(-1.0,0.0,-1.0),(-1.0,0.0,-0.9)] cnr = mc.curve(d=1,p=pts,k=range(3)) cnrShape = mc.listRelatives(cnr,s=True,ni=True)[0] mc.parent(cnrShape,ctrl,s=True,r=True) - + return ctrl - + def crescent(self): ''' Create Crescent control object ''' # Create control object control = mc.curve(d=3,p=[(0.392,0.392,-0.000),(-0.000,0.554,-0.000),(-0.392,0.392,-0.000),(-0.554,0.000,-0.000),(-0.392,0.228,-0.000),(-0.000,0.323,-0.000),(0.392,0.228,-0.000),(0.554,-0.000,0.000),(0.392,0.392,-0.000),(-0.000,0.554,-0.000),(-0.392,0.392,-0.000)],k=[-0.25,-0.125,0.0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1.0,1.125,1.25]) - + # Return control return control - + def cross(self): ''' ''' @@ -298,10 +298,10 @@ def cross(self): (-0.25,-0.25,0),(-0.75,-0.25,0),(-0.75,0.25,0),(-0.25,0.25,0),(-0.25,0.75,0) ] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def diamond(self): ''' Create diamond control object @@ -310,10 +310,10 @@ def diamond(self): pts = [(0.0,0.5,0.0),(-0.25,0.0,0.0),(0.0,-0.5,0.0),(0.25,0.0,0.0),(0.0,0.5,0.0)] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def eye(self): ''' Create eye control object @@ -322,10 +322,10 @@ def eye(self): pts = [(1.000,0.064,0.000),(-0.000,0.747,0.000),(-1.000,0.064,0.000),(-1.000,0.000,0.000),(-1.000,-0.064,0.000),(-0.000,-0.747,0.000),(1.000,-0.064,0.000),(1.000,-0.000,0.000),(1.000,0.064,0.000),(-0.000,0.747,0.000),(-1.000,0.064,0.000)] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def face(self): ''' Create face control object @@ -334,10 +334,10 @@ def face(self): pts = [(0.573,0.863,0.000),(-0.000,1.047,0.000),(-0.573,0.863,0.000),(-0.770,0.266,0.000),(-0.750,0.000,0.000),(-0.409,-0.656,0.000),(-0.322,-0.953,0.000),(-0.000,-1.020,0.000),(0.322,-0.953,0.000),(0.409,-0.656,0.000),(0.750,-0.000,0.000),(0.770,0.266,0.000),(0.573,0.863,0.000),(-0.000,1.047,0.000),(-0.573,0.863,0.000)] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def gear(self): ''' Create face control object @@ -346,10 +346,10 @@ def gear(self): pts=[(0.160,0.810,-0.000),(0.460,0.685,-0.000),(0.610,0.805,-0.000),(0.805,0.610,-0.000),(0.685,0.460,-0.000),(0.810,0.160,-0.000),(1.000,0.140,-0.000),(1.000,-0.135,0.000),(0.810,-0.160,0.000),(0.685,-0.460,0.000),(0.805,-0.610,0.000),(0.610,-0.805,0.000),(0.460,-0.685,0.000),(0.160,-0.810,0.000),(0.140,-1.000,0.000),(-0.135,-1.000,0.000),(-0.160,-0.810,0.000),(-0.460,-0.685,0.000),(-0.610,-0.805,0.000),(-0.805,-0.610,0.000),(-0.685,-0.460,0.000),(-0.810,-0.160,0.000),(-1.000,-0.140,0.000),(-1.000,0.135,-0.000),(-0.810,0.160,-0.000),(-0.685,0.460,-0.000),(-0.805,0.610,-0.000),(-0.610,0.805,-0.000),(-0.460,0.685,-0.000),(-0.160,0.810,-0.000),(-0.140,1.000,-0.000),(0.135,1.000,-0.000),(0.160,0.810,-0.000)] knots = [0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0,32.0] control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def hex(self): ''' Create hexagonal control object @@ -358,10 +358,10 @@ def hex(self): pts = [(0.0,1.0,0.0),(0.333,0.5,0.0),(0.333,-0.5,0.0),(0.0,-1.0,0.0),(-0.333,-0.5,0.0),(-0.333,0.5,0.0),(0.0,1.0,0.0)] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def line(self): ''' Create line control object @@ -370,10 +370,10 @@ def line(self): pts = [(0,0,0),(0.5,0,0),(1,0,0)] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return Control return control - + def locator(self): ''' Create locator control object @@ -382,10 +382,10 @@ def locator(self): pts = [ (-0.5, 0.0, 0.0), (0.5, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.5, 0.0), (0.0, -0.5, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, -0.5), (0.0, 0.0, 0.5) ] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def pyramid(self): ''' Create pyramid control object @@ -395,10 +395,10 @@ def pyramid(self): (0.0,0.5,0.0), (-0.5,-0.5,-0.5), (0.5,-0.5,-0.5), (0.0,0.5,0.0), (0.5,-0.5,0.5) ] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def sphere(self): ''' Create sphere control object @@ -410,23 +410,23 @@ def sphere(self): (-0.46, 0.0, -0.19), (-0.35, 0.0, -0.35), (-0.19, 0.0, -0.46), (0.0, 0.0, -0.5), (0.19, 0.0, -0.46), (0.35, 0.0, -0.35), (0.46, 0.0, -0.19), (0.5, 0.0, 0.0), (0.46, -0.19, 0.0), - (0.35, -0.35, 0.0), (0.19, -0.46, 0.0), (0.0, -0.5, 0.0), - (-0.19, -0.46, 0.0), (-0.35, -0.35, 0.0), (-0.46, -0.19, 0.0), - (-0.5, 0.0, 0.0), (-0.46, 0.19, 0.0), (-0.35, 0.35, 0.0), - (-0.19, 0.46, 0.0), (0.0, 0.5, 0.0), (0.19, 0.46, 0.0), - (0.35, 0.35, 0.0), (0.46, 0.19, 0.0), (0.5, 0.0, 0.0), - (0.46, 0.0, 0.19), (0.35, 0.0, 0.35), (0.19, 0.0, 0.46), - (0.0, 0.0, 0.5), (0.0, 0.24, 0.44), (0.0, 0.44, 0.24), - (0.0, 0.5, 0.0), (0.0, 0.44, -0.24), (0.0, 0.24, -0.44), - (0.0, 0.0, -0.5), (0.0, -0.24, -0.44), (0.0, -0.44, -0.24), - (0.0, -0.5, 0.0), (0.0, -0.44, 0.24), (0.0, -0.24, 0.44), + (0.35, -0.35, 0.0), (0.19, -0.46, 0.0), (0.0, -0.5, 0.0), + (-0.19, -0.46, 0.0), (-0.35, -0.35, 0.0), (-0.46, -0.19, 0.0), + (-0.5, 0.0, 0.0), (-0.46, 0.19, 0.0), (-0.35, 0.35, 0.0), + (-0.19, 0.46, 0.0), (0.0, 0.5, 0.0), (0.19, 0.46, 0.0), + (0.35, 0.35, 0.0), (0.46, 0.19, 0.0), (0.5, 0.0, 0.0), + (0.46, 0.0, 0.19), (0.35, 0.0, 0.35), (0.19, 0.0, 0.46), + (0.0, 0.0, 0.5), (0.0, 0.24, 0.44), (0.0, 0.44, 0.24), + (0.0, 0.5, 0.0), (0.0, 0.44, -0.24), (0.0, 0.24, -0.44), + (0.0, 0.0, -0.5), (0.0, -0.24, -0.44), (0.0, -0.44, -0.24), + (0.0, -0.5, 0.0), (0.0, -0.44, 0.24), (0.0, -0.24, 0.44), (0.0, 0.0, 0.5) ] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def sphereAnchor(self): ''' Create sphereAnchor control object @@ -451,10 +451,10 @@ def sphereAnchor(self): (0.0, 0.95, 0.0), (0.0, 0.0, 0.0) ] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return control name return control - + def spiral(self): ''' Create spiral control object @@ -470,19 +470,19 @@ def spiral(self): (-0.4, 0.768, -0.09), (-0.336, 0.823, -0.428), (0.0, 0.847, -0.595), (0.425, 0.867, -0.486), (0.589, 0.9, -0.09), (0.435, 0.97, 0.311), (0.158, 0.997, 0.415), (0.0, 1.0, 0.407) ] - + # Build Knot Array knots = [0,0] knots.extend(range(len(pts)-2)) knots.extend([len(pts)-3,len(pts)-3]) degree = 3 - + # Create control object control = mc.curve(d=degree,p=pts,k=knots) - + # Return control name return control - + def square(self): ''' Create square control object @@ -491,10 +491,10 @@ def square(self): pts = [(-0.5,0.5,0.0),(-0.5,-0.5,0.0),(0.5,-0.5,0.0),(0.5,0.5,0.0),(-0.5,0.5,0.0)] knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) - + # Return Control return control - + def tab(self): ''' Create tab control object @@ -502,10 +502,10 @@ def tab(self): pts = [(-0.500,-0.500,0.000),(-0.534,0.356,0.000),(-0.279,0.500,-0.000),(0.279,0.500,-0.000),(0.534,0.356,0.000),(0.500,-0.500,0.000),(0.500,-0.500,0.000),(0.500,-0.500,0.000),(-0.500,-0.500,0.000)] knots = [0.0,0.0,0.0,0.166666666667,0.333333333333,0.5,0.666666666667,0.833333333333,1.0,1.0,1.0] control = mc.curve(d=3,p=pts,k=knots) - + # Return Control return control - + def teardrop(self): ''' Create teardrop control object @@ -515,10 +515,10 @@ def teardrop(self): knots = range(len(pts)) control = mc.curve(d=1,p=pts,k=knots) #control = mc.rebuildCurve(control,ch=False,rt=0,rpo=True,end=True,kr=True,d=3,kcp=True)[0] - + # Return control name return control - + def text(self,text='text'): ''' Create text control object @@ -527,11 +527,11 @@ def text(self,text='text'): ''' # Check text string if not text: raise Exception('Empty string error!') - + # Create Text #textCurve = mc.textCurves(ch=False,f='Arial',t=text) textCurve = mc.textCurves(ch=False,f='Utopia-Bold',t=text) - + # Parent shapes to single treansform textShapes = mc.ls(mc.listRelatives(textCurve,ad=True),type='nurbsCurve') for textShape in textShapes: @@ -540,27 +540,27 @@ def text(self,text='text'): mc.makeIdentity(textXform,apply=True,t=True,r=True,s=True,n=False) mc.parent(textShape,textCurve,r=True,s=True) mc.delete(textXform) - + # Delete unused transforms textChildren = mc.listRelatives(textCurve,c=True,type='transform') if textChildren: mc.delete(textChildren) - + # Position text mc.select(textCurve) mm.eval('CenterPivot') piv = mc.xform(textCurve,q=True,ws=True,rp=True) mc.move(-piv[0],-piv[1],-piv[2],textCurve,ws=True,r=True) - + # Scale text width = (mc.getAttr(textCurve[0]+'.boundingBoxMaxX') - mc.getAttr(textCurve[0]+'.boundingBoxMinX')) height = (mc.getAttr(textCurve[0]+'.boundingBoxMaxY') - mc.getAttr(textCurve[0]+'.boundingBoxMinY')) if width > height: sc = 1.0/ width else: sc = 1.0/ height mc.scale(sc,sc,sc,textCurve) - + # Freeze Transforms mc.makeIdentity(textCurve,apply=True,t=True,r=True,s=True,n=False) - + # Return result return textCurve @@ -590,7 +590,7 @@ def controlShape(self,transform,controlType,translate=(0,0,0),rotate=(0,0,0),sca else: control = self.create(controlType,'temp_control_transform') controlShapeList = mc.listRelatives(control,s=True) - + # Match Control if not orient: mc.setAttr(control+'.rotate',rotate[0],rotate[1],rotate[2]) mc.delete(mc.pointConstraint(transform,control)) @@ -599,19 +599,19 @@ def controlShape(self,transform,controlType,translate=(0,0,0),rotate=(0,0,0),sca if orient: mc.setAttr(control+'.rotate',rotate[0],rotate[1],rotate[2]) mc.setAttr(control+'.scale',scale,scale,scale) mc.makeIdentity(control,apply=True,t=1,r=1,s=1,n=0) - + # Parent Control Shape for i in range(len(controlShapeList)): controlShapeList[i] = mc.parent(controlShapeList[i],transform,r=True,s=True)[0] controlShapeList[i] = mc.rename(controlShapeList[i],transform+'Shape'+str(i+1)) mc.reorder(controlShapeList[i],b=True) - - # Delete temp transform + + # Delete temp transform mc.delete(control) - + # Colour Control self.colourControl(transform,colour) - + # Return result return controlShapeList @@ -630,20 +630,20 @@ def colourControl(self,control,colour=-1): if not controlParent: raise Exception('Unable to determine controls transform!') control = controlParent[0] - + # Determine Colour if colour < 0: if control.startswith('cn') or control.startswith('C'): colour = self.overrideId['cn'] elif control.startswith('lf') or control.startswith('L'): colour = self.overrideId['lf'] elif control.startswith('rt') or control.startswith('R'): colour = self.overrideId['rt'] else: colour = 17 - + # Set Colour controlShapes = mc.listRelatives(control,s=True) for controlShape in controlShapes: mc.setAttr(controlShape+'.overrideEnabled',1) mc.setAttr(controlShape+'.overrideColor',colour) - + # Return result return colour @@ -662,13 +662,13 @@ def anchorCurve(self,control,anchor,template=True,selectable=False): raise Exception('Control "'+control+'" does not exist!') if not mc.objExists(anchor): raise Exception('Anchor transform "'+anchor+'" does not exist!') - + # Create curve shape crv = mc.curve(p=[(0,0,0),(0,1,0)],k=[0,1],d=1,n=control+'Anchor') crvShape = mc.listRelatives(crv,s=True,pa=True) if not crvShape: raise Exception('Unable to determine shape for curve "'+crv+'"!') - + # Create Curve Locators crvLoc = glTools.utils.curve.locatorCurve(crv,locatorScale=0.0,local=True,prefix=control) mc.parent(crvLoc,control) @@ -676,28 +676,28 @@ def anchorCurve(self,control,anchor,template=True,selectable=False): mc.setAttr(crvLoc[1]+'.t',0,0,0) mc.setAttr(crvLoc[0]+'.v',0) mc.setAttr(crvLoc[1]+'.v',0) - + # Rename and Parent curve shape crvShape = mc.parent(crvShape[0],control,r=True,s=True)[0] crvShape = mc.rename(crvShape,control+'Shape0') mc.reorder(crvShape,b=True) - + # Colour Curve Shape - Light Grey mc.setAttr(crvShape+'.overrideEnabled',1) mc.setAttr(crvShape+'.overrideColor',3) # Light Grey - + # Delete Original Curve Transform mc.delete(crv) - + # Connect to anchor mc.pointConstraint(anchor,crvLoc[1]) - + # Template if template: glTools.utils.base.displayOverride(crvShape,overrideEnable=1,overrideDisplay=1) - + # Set channel states glTools.utils.channelState.ChannelState().setFlags([2,2,2,2,2,2,2,2,2,1],crvLoc) - + # Return result return crvShape - + diff --git a/tools/copyChannels.py b/tools/copyChannels.py index 2104f3c..6828c9a 100644 --- a/tools/copyChannels.py +++ b/tools/copyChannels.py @@ -8,58 +8,58 @@ def copyChannels(src,dst,transform=True,joint=True,userDefined=True): raise Exception('Source object "'+src+'" does not exist!!') if not mc.objExists(dst): raise Exception('Destination object "'+dst+'" does not exist!!') - + # ----------------------- # - Copy channel values - # ----------------------- - + # Transform if transform: - + tAttrs = ['tx','ty','tz','rx','ry','rz','sx','sy','sz'] for attr in tAttrs: - + # Get source attribute value attrVal = mc.getAttr(src+'.'+attr) - + # Set destination attribute value if not mc.objExists(dst+'.'+attr): raise Exception('Destination attribute "'+dst+'.'+attr+'" does not exist!!') mc.setAttr(dst+'.'+attr,l=False) mc.setAttr(dst+'.'+attr,attrVal) - + # Joint if joint: - + jAttrs = ['radius','stx','sty','stz','pax','pay','paz','jox','joy','joz'] for attr in jAttrs: - + # Check source attribute if not mc.objExists(src+'.'+attr): continue - - # Get source attribute value + + # Get source attribute value attrVal = mc.getAttr(src+'.'+attr) - + # Set destination attribute value if not mc.objExists(dst+'.'+attr): raise Exception('Destination attribute "'+dst+'.'+attr+'" does not exist!!') mc.setAttr(dst+'.'+attr,l=False) mc.setAttr(dst+'.'+attr,attrVal) - + # User Defined if userDefined: - + uAttrs = mc.listAttr(src,ud=True) for attr in tAttrs: - + # Get source attribute value attrVal = mc.getAttr(src+'.'+attr) - + # Check destination attribute if not mc.objExists(dst+'.'+attr): print('Destination attribute "'+dst+'.'+attr+'" does not exist!! Skipping attribute...') continue - + # Set destination attribute value mc.setAttr(dst+'.'+attr,l=False) mc.setAttr(dst+'.'+attr,attrVal) diff --git a/tools/copyPasteWeights.py b/tools/copyPasteWeights.py index 1fbed11..538af83 100644 --- a/tools/copyPasteWeights.py +++ b/tools/copyPasteWeights.py @@ -17,20 +17,20 @@ def copyPasteWeightsUI(): win = 'copyPasteWeightsUI' # Check Window if mc.window(win,q=True,ex=True): mc.deleteUI(win) - + # Build Window mc.window(win,t='Copy/Paste Skin Weights') - + # layout mc.columnLayout() - + # Buttons mc.button(w=200,l='Copy Weights',c='glTools.tools.copyPasteWeights.copyWeights()') mc.button(w=200,l='Paste Weights',c='glTools.tools.copyPasteWeights.pasteWeights()') mc.button(w=200,l='Average Weights',c='glTools.tools.copyPasteWeights.averageWeights()') mc.button(w=200,l='Auto Average',c='glTools.tools.copyPasteWeights.autoAverageWeights()') mc.button(w=200,l='Close',c=('mc.deleteUI("'+win+'")')) - + # Show Window mc.showWindow(win) @@ -44,34 +44,34 @@ def copyWeights(tol=0.000001): sel = mc.filterExpand(ex=True,sm=[28,31,46]) if not sel: return cv = sel[0] - + # Get Geometry from Component geo = mc.ls(cv,o=True)[0] - + # Get SkinCluster from Geometry skin = glTools.utils.skinCluster.findRelatedSkinCluster(geo) if not skin: raise Exception('Geometry "'+geo+'" is not attached to a valid skinCluster!') - + # Get Influence List joints = mc.skinCluster(skin,q=True,inf=True) - + # Copy Weights wt = mc.skinPercent(skin,cv,q=True,v=True) cmd = 'skinPercent' for jnt in joints: - + # Get Influence Weight wt = mc.skinPercent(skin,cv,q=True,v=True,transform=jnt) - + # Check Weight Tolerance if wt < tol: continue - + # Append skinPercent Command cmd += (' -tv '+jnt+' '+str(round(wt,5))); - + # Finalize skinPercent Command cmd += ' -zri true ###' - + # Set Global Weight Value gl_globals.glCopyPasteWeightCmd = cmd print gl_globals.glCopyPasteWeightCmd @@ -83,42 +83,42 @@ def pasteWeights(showProgress=True): ''' # Global Weight Value wt = gl_globals.glCopyPasteWeightCmd - + # Get Component Selection sel = mc.filterExpand(ex=True,sm=[28,31,46]) if not sel: return - + # Begin Progress Bar gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') if showProgress: mc.progressBar( gMainProgressBar,e=True,bp=True,ii=True,status=('Pasting Skin Weights...'),maxValue=len(sel) ) - + selComp = glTools.utils.selection.componentListByObject(sel) for objComp in selComp: - + # Get Object from Component geo = mc.ls(objComp[0],o=True)[0] - + # Get SkinCluster from Geometry skin = glTools.utils.skinCluster.findRelatedSkinCluster(geo) if not skin: raise Exception('Geometry "'+geo+'" is not attached to a valid skinCluster!') # Disable Weight Normalization mc.setAttr(skin+'.normalizeWeights',0) - + # For Each Component for cv in objComp: - + # Update skinPercent Command cmd = wt.replace('###',skin) - + # Evaluate skinPercent Command - try: + try: mm.eval(cmd) #print(cmd) except Exception, e: if showProgress: mc.progressBar(gMainProgressBar,e=True,endProgress=True) raise Exception(str(s)) - + # Update Progress Bar cvLen = len(mc.ls(cv,fl=True)) if showProgress: @@ -126,11 +126,11 @@ def pasteWeights(showProgress=True): mc.progressBar(gMainProgressBar,e=True,endProgress=True) raise UserInterupted('Operation cancelled by user!') mc.progressBar(gMainProgressBar,e=True,step=cvLen) - + # Normalize Weights mc.setAttr(skin+'.normalizeWeights',1) mc.skinPercent(skin,normalize=True) - + # End Current Progress Bar if showProgress: mc.progressBar(gMainProgressBar,e=True,endProgress=True) @@ -143,12 +143,12 @@ def averageWeights(tol=0.000001): # Get Component Selection sel = mc.filterExpand(ex=True,sm=[28,31,46]) if not sel: return - + # Get Component Selection by Object sel = glTools.utils.selection.componentListByObject(sel) if not sel: return sel = sel[0] - + # Get Object from Components geo = mc.ls(sel[0],o=True)[0] @@ -158,32 +158,32 @@ def averageWeights(tol=0.000001): # Get Influence List joints = mc.skinCluster(skin,q=True,inf=True) - + # Initialize skinPercent Command cmd = 'skinPercent' - + # For Each SkinCluster Influence for jnt in joints: - - # Initialize Average Influence Weight + + # Initialize Average Influence Weight wt = 0.0 - + # For each CV for cv in sel: wt += mc.skinPercent(skin,cv,q=True,transform=jnt) - + # Average Weight wt /= len(joints) - + # Check Weight Tolerance if wt < tol: continue - + # Append to skinPercent Command cmd += (' -tv '+jnt+' '+str(round(wt,5))) # Finalize skinPercent Command cmd += (' -zri true ### ') - + # Return Result gl_globals.glCopyPasteWeightCmd = cmd print gl_globals.glCopyPasteWeightCmd @@ -194,80 +194,80 @@ def autoAverageWeights(): # Get Component Selection sel = mc.filterExpand(ex=True,sm=[28,31,46]) if not sel: return - + # For Each Vertex for vtx in sel: - + # Select Vert mc.select(vtx) - + # Expand Selection mm.eval('PolySelectTraverse 1') mc.select(vtx,d=True) - + # Calculate Average Weights from Neighbours averageWeights() mc.select(vtx) # Paste Average Weights pasteWeights() - + def hotkeySetup(): ''' ''' # ==================== # - Runtime Commands - # ==================== - + # Copy Weights if mm.eval('runTimeCommand -q -ex rt_copyWeights'): mm.eval('runTimeCommand -e -del rt_copyWeights') mm.eval('runTimeCommand -annotation "" -category "User" -commandLanguage "python" -command "import glTools.tools.copyPasteWeights;reload(glTools.tools.copyPasteWeights);glTools.tools.copyPasteWeights.copyWeights()" rt_copyWeights') - + # Paste Weights if mm.eval('runTimeCommand -q -ex rt_pasteWeights'): mm.eval('runTimeCommand -e -del rt_pasteWeights') mm.eval('runTimeCommand -annotation "" -category "User" -commandLanguage "python" -command "import glTools.tools.copyPasteWeights;reload(glTools.tools.copyPasteWeights);glTools.tools.copyPasteWeights.pasteWeights()" rt_pasteWeights') - + # Average Weights if mm.eval('runTimeCommand -q -ex rt_averageWeights'): mm.eval('runTimeCommand -e -del rt_averageWeights') mm.eval('runTimeCommand -annotation "" -category "User" -commandLanguage "python" -command "import glTools.tools.copyPasteWeights;reload(glTools.tools.copyPasteWeights);glTools.tools.copyPasteWeights.averageWeights()" rt_averageWeights') - + # Auto Average Weights if mm.eval('runTimeCommand -q -ex rt_autoAverageWeights'): mm.eval('runTimeCommand -e -del rt_autoAverageWeights') mm.eval('runTimeCommand -annotation "" -category "User" -commandLanguage "python" -command "import glTools.tools.copyPasteWeights;reload(glTools.tools.copyPasteWeights);glTools.tools.copyPasteWeights.autoAverageWeights()" rt_autoAverageWeights') - + # ======================== # - Create Name Commands - # ======================== - + copyWtCmd = mc.nameCommand( 'copyWeightsNameCommand', ann='copyWeightsNameCommand', sourceType='mel', c='rt_copyWeights' ) - + pasteWtCmd = mc.nameCommand( 'pasteWeightsNameCommand', ann='pasteWeightsNameCommand', sourceType='mel', c='rt_pasteWeights' ) - + averageWtCmd = mc.nameCommand( 'averageWeightsNameCommand', ann='averageWeightsNameCommand', sourceType='mel', c='rt_averageWeights' ) - + autoAverageWtCmd = mc.nameCommand( 'autoAverageWeightsNameCommand', ann='autoAverageWeightsNameCommand', sourceType='mel', c='rt_autoAverageWeights' ) - + # ============================= # - Create Hotkey Assignments - # ============================= - + mc.hotkey(keyShortcut='c',alt=True,name=copyWtCmd) mc.hotkey(keyShortcut='v',alt=True,name=pasteWtCmd) mc.hotkey(keyShortcut='x',alt=True,name=averageWtCmd) mc.hotkey(keyShortcut='a',alt=True,name=autoAverageWtCmd) - + diff --git a/tools/correctiveSculpt.py b/tools/correctiveSculpt.py index 63e6d27..fdadc21 100644 --- a/tools/correctiveSculpt.py +++ b/tools/correctiveSculpt.py @@ -13,16 +13,16 @@ def createSculptBase(rigMesh,baseMesh,prefix='sculpt'): raise Exception('Invalid mesh! ("'+rigMesh+'")') if not glTools.utils.mesh.isMesh(baseMesh): raise Exception('Invalid mesh! ("'+baseMesh+'")') - + # Get mesh info buffer = 1.1 meshWidth = buffer * (mc.getAttr(rigMesh+'.boundingBoxMaxX') - mc.getAttr(rigMesh+'.boundingBoxMinX')) meshHeight = buffer * (mc.getAttr(rigMesh+'.boundingBoxMaxY') - mc.getAttr(rigMesh+'.boundingBoxMinY')) - + # ------------------ # - Dulpicate mesh - # ------------------ - + # Generate rigBase mesh rigBase = mc.duplicate(rigMesh)[0] rigBase = mc.rename(rigBase,prefix+'_rigBase') @@ -31,13 +31,13 @@ def createSculptBase(rigMesh,baseMesh,prefix='sculpt'): # Set display type - Reference mc.setAttr(rigBase+'.overrideEnabled',1) mc.setAttr(rigBase+'.overrideDisplayType',2) - + # Generate sculpt mesh sculpt = mc.duplicate(rigMesh)[0] sculpt = mc.rename(sculpt,prefix+'_sculpt') mc.parent(sculpt,w=True) mc.move(meshWidth*2,0,0,sculpt,ws=True,a=True) - + # Generate delta mesh delta = mc.duplicate(baseMesh)[0] delta = mc.rename(delta,prefix+'_delta') @@ -46,7 +46,7 @@ def createSculptBase(rigMesh,baseMesh,prefix='sculpt'): # Set display type - Reference mc.setAttr(delta+'.overrideEnabled',1) mc.setAttr(delta+'.overrideDisplayType',2) - + # Generate result mesh result = mc.duplicate(baseMesh)[0] result = mc.rename(result,prefix+'_result') @@ -55,27 +55,27 @@ def createSculptBase(rigMesh,baseMesh,prefix='sculpt'): # Set display type - Reference mc.setAttr(result+'.overrideEnabled',1) mc.setAttr(result+'.overrideDisplayType',2) - + # -------------------------- # - Add BlendShape Targets - # -------------------------- - + # Create delta blendShape deltaBlendShape = mc.blendShape(sculpt,rigBase,delta,n=delta+'_blendShape')[0] deltaTarget = mc.listAttr(deltaBlendShape+'.w',m=True) mc.setAttr(deltaBlendShape+'.'+deltaTarget[0],1.0) mc.setAttr(deltaBlendShape+'.'+deltaTarget[1],-1.0) - + # Add rig and delta mesh as targets to result mesh resultBlendShape = mc.blendShape(rigMesh,delta,result,n=result+'_blendShape')[0] resultTarget = mc.listAttr(resultBlendShape+'.w',m=True) mc.setAttr(resultBlendShape+'.'+resultTarget[0],1.0) mc.setAttr(resultBlendShape+'.'+resultTarget[1],1.0) - + # ----------------- # - Return Result - # ----------------- - + return [rigBase,sculpt,delta,result] def updateSculptBase(rigMesh,baseMesh,prefix='sculpt'): @@ -84,15 +84,15 @@ def updateSculptBase(rigMesh,baseMesh,prefix='sculpt'): # ---------- # - Checks - # ---------- - + # RigMesh if not glTools.utils.mesh.isMesh(rigMesh): raise Exception('Invalid mesh! ("'+rigMesh+'")') - + # BaseMesh if not glTools.utils.mesh.isMesh(baseMesh): raise Exception('Invalid mesh! ("'+baseMesh+'")') - + # RigBase / Sculpt / Delta rigBase = prefix+'_rigBase' sculpt = prefix+'_sculpt' @@ -103,20 +103,20 @@ def updateSculptBase(rigMesh,baseMesh,prefix='sculpt'): raise Exception('Invalid mesh! ("'+sculpt+'")') if not glTools.utils.mesh.isMesh(delta): raise Exception('Invalid mesh! ("'+delta+'")') - + # ------------------------ # - Update Sculpt Shapes - # ------------------------ - + # Freeze Delta Mesh mc.delete(delta,ch=True) - + # Update rigBase rigBaseBlendShape = mc.blendShape(rigMesh,rigBase)[0] rigBaseTarget = mc.listAttr(rigBaseBlendShape+'.w',m=True) mc.setAttr(rigBaseBlendShape+'.'+rigBaseTarget[0],1.0) mc.delete(rigBase,ch=True) - + # Update sculpt sculptBlendShape = mc.blendShape(baseMesh,sculpt)[0] sculptTarget = mc.listAttr(sculptBlendShape+'.w',m=True) @@ -127,7 +127,7 @@ def updateSculptBase(rigMesh,baseMesh,prefix='sculpt'): mc.setAttr(sculptBlendShape+'.'+sculptTarget[0],1.0) mc.setAttr(sculptBlendShape+'.'+sculptTarget[1],1.0) mc.delete(sculpt,ch=True) - + # Update delta mesh deltaBlendShape = mc.blendShape(baseMesh,delta)[0] deltaTarget = mc.listAttr(deltaBlendShape+'.w',m=True) @@ -137,9 +137,9 @@ def updateSculptBase(rigMesh,baseMesh,prefix='sculpt'): deltaTarget = mc.listAttr(deltaBlendShape+'.w',m=True) mc.setAttr(deltaBlendShape+'.'+deltaTarget[0],1.0) mc.setAttr(deltaBlendShape+'.'+deltaTarget[1],-1.0) - + # ----------------- # - Return Result - # ----------------- - + return [rigBase,sculpt,delta] diff --git a/tools/createAlongCurve.py b/tools/createAlongCurve.py index 23791f3..d38b80d 100644 --- a/tools/createAlongCurve.py +++ b/tools/createAlongCurve.py @@ -36,18 +36,18 @@ def create( curve, @param prefix: Name prefix for builder created nodes. If left at default ("") prefix will be derived from curve name. @type prefix: str ''' - + # Check Path if not glTools.utils.curve.isCurve(curve): raise Exception('Object "'+curve+'" is not a valid nurbs curve!') - + # Check Naming if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) if not suffix: suffix = objType - + # Check Object Count if not objCount: objCount = mc.getAttr(curve+'.spans') + 1 - + # Get Curve Sample Params paramList = glTools.utils.curve.sampleParam( curve = curve, samples = objCount, @@ -55,24 +55,24 @@ def create( curve, minPercent = minPercent, maxPercent = maxPercent, spacing = spacing ) - + # Create Objects Along Curve objList = [] for i in range(objCount): - + # Create Object ind = glTools.utils.stringUtils.alphaIndex(i) obj = createAtParam( curve, param = paramList[i], objType = objType, name = prefix+ind+'_'+suffix ) - + # Parent if parent and i: obj = mc.parent(obj,objList[-1])[0] - + # Append Result objList.append(str(obj)) - + # Return result return objList @@ -94,20 +94,20 @@ def createAtParam( curve, # Check Curve if not glTools.utils.curve.isCurve(curve): raise Exception('Object "'+curve+'" is not a valid nurbs curve!') - + # Check Name if not name: name = glTools.utils.stringUtils.stripSuffix(curve)+'_'+objType - + # Create Object obj = mc.createNode(objType) if not glTools.utils.transform.isTransform(obj): obj = mc.listRelatives(obj,p=True,pa=True)[0] obj = mc.rename(obj,name) - + # Position Object pos = mc.pointOnCurve(curve,pr=param) mc.xform(obj,t=pos,ws=True) - + # Return Result return obj @@ -129,17 +129,17 @@ def createAtPoint( curve, # Check Curve if not glTools.utils.curve.isCurve(curve): raise Exception('Object "'+curve+'" is not a valid nurbs curve!') - + # Get Param at Point point = glTools.utils.base.getPosition(point) param = glTools.utils.curve.closestPoint(curve,pos=point) - + # Create Object obj = createAtParam( curve, param = param, objType = objType, name = None ) - + # Return Result return obj diff --git a/tools/createAlongPath.py b/tools/createAlongPath.py index 71a9b98..367f673 100644 --- a/tools/createAlongPath.py +++ b/tools/createAlongPath.py @@ -22,7 +22,7 @@ def create( path, prefix='' ): ''' Create objects along a curve - + # INPUTS: @input path: Input nurbs curve path @inputType path: str @@ -40,48 +40,48 @@ def create( path, @inputType max: float @input prefix: Name prefix for builder created nodes. If left at default ("") prefix will be derived from path name. @inputType prefix: str - + # OUTPUTS: @output outObjectList: List of objects placed along path @outputType outObjectList: list ''' - + # Check Path if not glTools.utils.curve.isCurve(path): raise Exception('Path object '+path+' is not a valid nurbs curve!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(path) - + # Check object count if not num: num = mc.getAttr(path+'.spans') + 1 - + # Get curve sample points paramList = glTools.utils.curve.sampleParam(path,num,useDist,min,max) - + # Create object along path objList = [] for i in range(num): - + # Get string index ind = glTools.utils.stringUtils.stringIndex(i+1) - + # Create object obj = mc.createNode(objectType,n=prefix+ind+'_'+objectType) if not glTools.utils.base.isTransform(obj): obj = mc.listRelatives(obj,p=True,pa=True)[0] - + # Position pos = mc.pointOnCurve(path,pr=paramList[i]) mc.xform(obj,t=pos,ws=True) - + # Parent if parent and i: obj = mc.parent(obj,objList[-1])[0] - + # Orient Joint if objectType == 'joint' and i: mc.joint(objList[-1],e=True,zso=True,oj='xyz',sao='yup') - + # Append result objList.append( str(obj) ) - + # Return result return objList diff --git a/tools/curveLengthDriver.py b/tools/curveLengthDriver.py index 863905b..4c21c43 100644 --- a/tools/curveLengthDriver.py +++ b/tools/curveLengthDriver.py @@ -14,23 +14,23 @@ def addLengthAttrs(attrObject,length=0.0): # ========== # - Checks - # ========== - + if not mc.objExists(attrObject): raise Exception('Attribute object "'+attrObject+'" does not exist!') - + # =========================== # - Add Distance Attributes - # =========================== - + if not mc.attributeQuery('length',n=attrObject,ex=True): mc.addAttr(attrObject,ln='length',min=0,dv=dist,k=True) if not mc.attributeQuery('restLength',n=attrObject,ex=True): mc.addAttr(attrObject,ln='restLength',min=0,dv=dist,k=True) - + # ================= # - Return Result - # ================= - + return attrObject+'.length' def curveLengthSetup( curve, @@ -48,32 +48,32 @@ def curveLengthSetup( curve, # ========== # - Checks - # ========== - + if not glTools.utils.curve.isCurve(curve): raise Exception('Object "'+curve+'" is not a valid curve!') - + if attrObject: if not mc.objExists(attrObject): raise Exception('Attribute object "'+attrObject+'" does not exist!') else: attrObject = curve - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # ============================ # - Build Curve Length Setup - # ============================ - + curveInfo = mc.createNode('curveInfo',n=prefix+'_curveInfo') mc.connectAttr(curve+'.worldSpace[0]',curveInfo+'.inputCurve',f=True) crvLen = mc.getAttr(curveInfo+'.arcLength') - + # Add Length Attr lengthAttr = addLengthAttrs(attrObject,length=crvLen) - + # ================= # - Return Result - # ================= - + return lengthAttr,curveInfo def curveLengthRemapOutput( curve, @@ -109,25 +109,25 @@ def curveLengthRemapOutput( curve, # ========== # - Checks - # ========== - + # Check Curve if not glTools.utils.curve.isCurve(curve): raise Exception('Object "'+curve+'" is not a vlaid curve!') - + # Check Attribute Object if not attrObject: attrObject = curve - + # Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # Check Curve Length Setup crvLenAttr,lengthNode = curveLengthSetup(curve,attrObject,prefix) length = mc.getAttr(crvLenAttr) - + # ====================== # - Build Length Remap - # ====================== - + # Add Min/Max Length Attrs if minLength == None: minLength = 0 if not mc.objExists(attrObject+'.minLength'): @@ -135,46 +135,46 @@ def curveLengthRemapOutput( curve, if maxLength == None: maxLength = length*2 if not mc.objExists(attrObject+'.maxLength'): mc.addAttr(attrObject,ln='maxLength',min=length,dv=maxLength,k=True) - + # Add Rest Value Attr if not restValue == None: if not mc.objExists(attrObject+'.restValue'): mc.addAttr(attrObject,ln='restValue',dv=restValue,k=True) - + # Add Min/Max Value Attr if not mc.attributeQuery('minValue',n=attrObject,ex=True): mc.addAttr(attrObject,ln='minValue',dv=minValue,k=True) if not mc.attributeQuery('maxValue',n=attrObject,ex=True): mc.addAttr(attrObject,ln='maxValue',dv=maxValue,k=True) - + # Build Remap Value remapNode = mc.createNode('remapValue',n=prefix+'_remapValue') mc.connectAttr(crvLenAttr,remapNode+'.inputValue',f=True) - + mc.setAttr(remapNode+'.value[0].value_Interp',interpType) mc.connectAttr(attrObject+'.minLength',remapNode+'.value[0].value_Position',f=True) mc.connectAttr(attrObject+'.minValue',remapNode+'.value[0].value_FloatValue',f=True) - + mc.setAttr(remapNode+'.value[1].value_Interp',interpType) mc.connectAttr(attrObject+'.maxLength',remapNode+'.value[1].value_Position',f=True) mc.connectAttr(attrObject+'.maxValue',remapNode+'.value[1].value_FloatValue',f=True) - + # Set Rest Value if not restValue == None: mc.setAttr(remapNode+'.value[2].value_Interp',interpType) mc.connectAttr(curve+'.restLength',remapNode+'.value[2].value_Position',f=True) mc.connectAttr(attrObject+'.restValue',remapNode+'.value[2].value_FloatValue',f=True) - + # Connect Output if not mc.objExists(attrObject+'.outValue'): mc.addAttr(attrObject,ln='outValue',dv=0.0,k=True) mc.connectAttr(remapNode+'.outValue',attrObject+'.outValue',f=True) outAttr = attrObject+'.outValue' - + # ================= # - Return Result - # ================= - + return outAttr,distNode,remapNode def curveLengthAttach( curve, @@ -200,44 +200,44 @@ def curveLengthAttach( curve, # ========== # - Checks - # ========== - + # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(targetAttr.replace('.','_')) - + # Check Target Attribute if not mc.objExists(targetAttr): raise Exception('Target attribute "'+targetAttr+'" does not exist!') - + # Check Curve if not glTools.utils.curve.isCurve(curve): raise Exception('Object "'+curve+'" is not a vlaid curve!') - + # Check Curve Length Setup if not mc.objExists(curve+'.length'): curveLengthSetup(curve,prefix) - + # ==================== # - Build Remap Node - # ==================== - + # Build Remap Node remapNode = mc.createNode('remapValue',n=prefix+'_remapValue') - + # Connect Remap Node curveLen = mc.getAttr(curve+'.curveLength') mc.connectAttr(curve+'.curveLength',remapNode+'.inputValue',f=True) - + # SetAttr mc.setAttr(remapNode+'.inputMin',inputMin) mc.setAttr(remapNode+'.inputMax',inputMax) mc.setAttr(remapNode+'.outputMin',outputMin) mc.setAttr(remapNode+'.outputMax',outputMax) - + # Connect Target Attribute mc.connectAttr(remapNode+'.outValue',targetAttr,f=True) - + # ================= # - Return Result - # ================= - + return remapNode diff --git a/tools/cutSkin.py b/tools/cutSkin.py index 9c4d4e8..a0cf43e 100644 --- a/tools/cutSkin.py +++ b/tools/cutSkin.py @@ -21,13 +21,13 @@ def cutSkin(mesh,weightThreshold=0.25,reducePercent=None,parentShape=False): # Initialize startTime = mc.timerX() mc.undoInfo(state=False) - + # Get Skin Info skin = glTools.utils.skinCluster.findRelatedSkinCluster(mesh) if not skin: print('Cut Skin: Mesh "" has no skinCluster! Skipping...') return None - + # Prune Weights glTools.utils.skinCluster.lockSkinClusterWeights(skin,lock=False,lockAttr=False) pruneWts = glTools.utils.mathUtils.distributeValue(10,rangeStart=0.001,rangeEnd=weightThreshold) @@ -37,7 +37,7 @@ def cutSkin(mesh,weightThreshold=0.25,reducePercent=None,parentShape=False): except Exception, e: print('Prune weight FAILED ('+mesh+')! '+str(e)) break - + # Extract Influence Meshes infMeshList = [] infList = mc.skinCluster(skin,q=True,inf=True) @@ -52,12 +52,12 @@ def cutSkin(mesh,weightThreshold=0.25,reducePercent=None,parentShape=False): infMeshList.extend(infMeshShape) else: infMeshList.append(infMesh) - + # Finalize totalTime = mc.timerX(startTime=startTime) print('CutSkin - Total Time: '+str(totalTime)) mc.undoInfo(state=True) - + # Return Result return infMeshList @@ -72,7 +72,7 @@ def cutSkin_extractInfluenceMesh(mesh,influence): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh! Unable to extract influence mesh...') - + # Get SkinCluster skin = glTools.utils.skinCluster.findRelatedSkinCluster(mesh) if not skin: @@ -81,7 +81,7 @@ def cutSkin_extractInfluenceMesh(mesh,influence): infList = mc.skinCluster(skin,q=True,inf=True) if not influence in infList: raise Exception('SkinCluster "'+skin+'" has no influence "'+influence+'"! Unable to extract influence mesh...') - + # Get Influence Faces mc.select(cl=True) mc.skinCluster(skin,e=True,selectInfluenceVerts=influence) @@ -95,7 +95,7 @@ def cutSkin_extractInfluenceMesh(mesh,influence): infFaceList = mc.polyListComponentConversion(infVtxList,fv=True,tf=True,internal=True) or [] if not infFaceList: return None if '*' in infFaceList[0]: return None - + # Duplicate Mesh infMesh = glTools.tools.mesh.reconstructMesh(mesh) infMeshShape = mc.listRelatives(infMesh,s=True,ni=True)[0] @@ -105,14 +105,14 @@ def cutSkin_extractInfluenceMesh(mesh,influence): try: mc.parent(infMesh,w=True) except: pass mc.setAttr(infMesh+'.overrideEnabled',0) - + # Extract Influence Faces infFaceList = [i.replace(mesh,infMesh) for i in infFaceList] mc.select(infFaceList) mm.eval('InvertSelection') mc.delete() mc.delete(infMesh,ch=True) - + # Add Attributes infProxyAttr = 'influenceProxy' meshProxyAttr = 'meshProxy' @@ -120,10 +120,10 @@ def cutSkin_extractInfluenceMesh(mesh,influence): mc.setAttr(infMesh+'.'+infProxyAttr,influence,type='string',l=True) mc.addAttr(infMesh,ln=meshProxyAttr,dt='string') mc.setAttr(infMesh+'.'+meshProxyAttr,mesh,type='string',l=True) - + # Return Result return infMesh - + def cutSkin_reduce(mesh,percent=50): ''' Basic mesh cleanup and reduce. @@ -139,18 +139,18 @@ def cutSkin_reduce(mesh,percent=50): meshProxy = None meshProxyAttr = 'meshProxy' if mc.objExists(mesh+'.'+meshProxyAttr): meshProxy = mc.getAttr(mesh+'.'+meshProxyAttr) - + # Separate to Shells meshItems = [mesh] try: meshItems = mc.polySeparate(mesh,ch=False) except: pass - + # Clean Non-manifold Geometry glTools.utils.mesh.polyCleanup( meshList = meshItems, nonManifold = True, keepHistory = False, fix = True ) - + # Poly Reduce for meshItem in meshItems: try: @@ -173,13 +173,13 @@ def cutSkin_reduce(mesh,percent=50): cachingReduce = 0, constructionHistory = 0 ) except: pass - + # Cleanup if len(meshItems) > 1: meshResult = mc.polyUnite(meshItems,ch=False,mergeUVSets=True) if mc.objExists(mesh): mc.delete(mesh) mesh = mc.rename(meshResult,mesh) - + # Rebuild Influence Mesh Attributes if infProxy and not mc.objExists(mesh+'.'+infProxyAttr): mc.addAttr(mesh,ln=infProxyAttr,dt='string') @@ -187,7 +187,7 @@ def cutSkin_reduce(mesh,percent=50): if meshProxy and not mc.objExists(mesh+'.'+meshProxyAttr): mc.addAttr(mesh,ln=meshProxyAttr,dt='string') mc.setAttr(mesh+'.'+meshProxyAttr,meshProxy,type='string',l=True) - + # Return Result return mesh @@ -200,22 +200,22 @@ def cutSkin_parentShape(infMesh): # Checks Influence Mesh if not mc.objExists(infMesh): raise Exception('Influence mesh "'+infMesh+'" does not exist!') - - # Checks Influence Attr + + # Checks Influence Attr infProxyAttr = 'influenceProxy' if not mc.attributeQuery(infProxyAttr,n=infMesh,ex=True): raise Exception('Influence mesh "'+infMesh+'" has no "'+infProxyAttr+'" attribute! Unable to parent influence shape...') influence = mc.getAttr(infMesh+'.'+infProxyAttr) if not mc.objExists(influence): raise Exception('Influence does not exist! Unable to parent shape...') - + # Get Shape(s) infShapes = [] if glTools.utils.transform.isTransform(infMesh): infShapes = mc.listRelatives(infMesh,s=True,ni=True,pa=True) elif str(mc.objectType(infMesh)) in ['mesh','nurbsSurface']: infShapes = [str(infMesh)] - + # Parent Proxy Shapes to Joint for i in range(len(infShapes)): infShapesParent = mc.listRelatives(infShapes[i],p=True,pa=True)[0] @@ -224,16 +224,16 @@ def cutSkin_parentShape(infMesh): except: pass infShapes[i] = glTools.utils.shape.parent(infShapes[i],influence)[0] glTools.utils.base.displayOverride(infShapes[i],overrideEnable=1,overrideDisplay=2,overrideLOD=0) - + # Delete Original mc.delete(infMesh) - + # Tag Shapes proxyAttr = 'proxyJoint' for shape in infShapes: if not mc.objExists(shape+'.'+proxyAttr): mc.addAttr(shape,ln=proxyAttr,dt='string') mc.setAttr(shape+'.'+proxyAttr,influence,type='string',l=True) - + # Return Result return infShapes diff --git a/tools/dependencyHierarchyNode.py b/tools/dependencyHierarchyNode.py index 6421e8c..12fcdb3 100644 --- a/tools/dependencyHierarchyNode.py +++ b/tools/dependencyHierarchyNode.py @@ -12,13 +12,13 @@ class DependencyHierarchyNode( object ): ''' def __init__(self): - + self.fullName = '' self.shortName = '' self.parent = None self.childList = [] self.childCache = {} - + def buildHierarchyFromNode(self,root): ''' This will map an entire hierarchy from a given root node. @@ -27,17 +27,17 @@ def buildHierarchyFromNode(self,root): ''' # Check root exists if not mc.objExists(root): raise UserInputError('Root object '+root+' does not exists!') - + # Get root information self.fullName = mc.ls(root,l=True)[0] self.shortName = self.fullName.split('|')[1] self.parent = None self.childList = [] self.childCache = {} - + # Traverse all decendant children self.mapDecendants(recursive=True) - + def mapDecendants(self,recursive=True): ''' Finds maya DAG children for the current object and records hierarchy information to class member array types @@ -46,10 +46,10 @@ def mapDecendants(self,recursive=True): ''' # Get dag children children = mc.listRelatives(self.fullName,c=True,pa=True,type=['transform','joint','ikHandle']) - + # Escape if no children if not children: return - + # Build child array for child in children: childNode = DependencyHierarchyNode() @@ -62,7 +62,7 @@ def mapDecendants(self,recursive=True): if recursive: for childNode in self.childList: childNode.mapDecendants(recursive=True) - + def getDependPath(self,delineator='|'): ''' Return the dependency based path for the current node @@ -75,7 +75,7 @@ def getDependPath(self,delineator='|'): path = parent.shortName+delineator+path parent = parent.parent return path - + def getGeneration(self): ''' Return the dependency depth (generation) for the current node @@ -86,7 +86,7 @@ def getGeneration(self): generation += 1 parent = parent.parent return generation - + def findDependNode(self,fullName): ''' Find and return the node representing the specified maya object. @@ -96,7 +96,7 @@ def findDependNode(self,fullName): # Check node exists if not mc.objExists(fullName): raise UserInputError('Object '+fullName+' does not exists!') fullName = mc.ls(fullName,l=True)[0] - + # Search for node in hierarchy dependNode = None if self.fullName == fullName: return self @@ -107,7 +107,7 @@ def findDependNode(self,fullName): dependNode = child.findDependNode(fullName) if dependNode: break return dependNode - + def reparent(self,newParentNode): ''' Reparent the current object node under another object node @@ -117,26 +117,26 @@ def reparent(self,newParentNode): # Check nodes exist if not mc.objExists(self.fullName): raise UserInputError('Child object '+child+' does not exists!') if not mc.objExists(newParentNode.fullName): raise UserInputError('Parent object '+newParentNode.shortName+' does not exists!') - + # Get current parent node currentParentNode = self.parent - + # Check parent is not the current node if self.fullName == newParentNode.fullName: return # Check current node is not already a child of parent if currentParentNode.fullName == newParentNode.fullName: return # Check parent is not a decendant of child if self.findDependNode(newParentNode.fullName): raise UserInputError('Object "'+newParentNode.shortName+'" is a decendant of "'+self.shortName+'"!! Unable to perform reparent!') - + # Break old child/parent connections currentParentNode.childCache.pop(self.fullName) currentParentNode.childList.remove(self) - + # Make new child/parent connections self.parent = newParentNode newParentNode.childList.append(self) newParentNode.childCache[self.fullName] = self - + def flatList(self,longNames=False): ''' Return a dependency node name list from the current hierarchy @@ -148,7 +148,7 @@ def flatList(self,longNames=False): else: flatList.append(self.shortName) flatList.extend(self.listChildren(longNames=longNames,recursive=True)) return flatList - + def flatListNodes(self): ''' Return a dependency node list from the current hierarchy @@ -157,7 +157,7 @@ def flatListNodes(self): nodeList.append(self) nodeList.extend(self.listChildNodes(recursive=True)) return nodeList - + def listChildren(self,longNames=False,recursive=False): ''' Return a flat list of child dependency nodes @@ -173,7 +173,7 @@ def listChildren(self,longNames=False,recursive=False): for child in self.childList: if recursive: childList.extend(child.listChildren(longNames=longNames,recursive=True)) return childList - + def listChildNodes(self,longNames=False,recursive=False): ''' Return a flat list of child dependency nodes @@ -185,7 +185,7 @@ def listChildNodes(self,longNames=False,recursive=False): for child in self.childList: if recursive: childList.extend(child.listChildNodes(recursive=True)) return childList - + def generationDict(self): ''' Create a generation based dictionary of all nodes in the dependency hierarchy. @@ -196,7 +196,7 @@ def generationDict(self): if not generationDict.has_key(gen): generationDict[gen] = [] generationDict[gen].append(node.shortName) return generationDict - + def generationList(self): ''' Create a list of all dependency hierarchy nodes in order of generation. @@ -207,4 +207,4 @@ def generationList(self): generationDictKeys.sort() for key in generationDictKeys: generationList.extend(generationDict[key]) return generationList - + diff --git a/tools/distanceDriver.py b/tools/distanceDriver.py index fe0901b..a7a0f5e 100644 --- a/tools/distanceDriver.py +++ b/tools/distanceDriver.py @@ -14,23 +14,23 @@ def addDistanceAttrs(attrObject,dist=0.0): # ========== # - Checks - # ========== - + if not mc.objExists(attrObject): raise Exception('Attribute object "'+attrObject+'" does not exist!') - + # =========================== # - Add Distance Attributes - # =========================== - + if not mc.attributeQuery('distance',n=attrObject,ex=True): mc.addAttr(attrObject,ln='distance',min=0,dv=dist,k=True) if not mc.attributeQuery('restDistance',n=attrObject,ex=True): mc.addAttr(attrObject,ln='restDistance',min=0,dv=dist,k=True) - + # ================= # - Return Result - # ================= - + return attrObject+'.distance' def buildDistanceNode( pt1, @@ -46,24 +46,24 @@ def buildDistanceNode( pt1, # ========== # - Checks - # ========== - + if not mc.objExists(pt1): raise Exception('Point 1 "'+pt1+'" does not exist!') if not glTools.utils.transform.isTransform(pt1):raise Exception('Point 1 "'+pt1+'" is not a valid tranform!') if not mc.objExists(pt2): raise Exception('Point 2 "'+pt2+'" does not exist!') if not glTools.utils.transform.isTransform(pt2):raise Exception('Point 2 "'+pt2+'" is not a valid tranform!') - + # ======================== # - Build Distance Setup - # ======================== - + distNode = mc.createNode('distanceBetween',n=prefix+'_distanceBetween') mc.connectAttr(pt1+'.worldMatrix[0]',distNode+'.inMatrix1',f=True) mc.connectAttr(pt2+'.worldMatrix[0]',distNode+'.inMatrix2',f=True) - + # ================= # - Return Result - # ================= - + return distNode def distanceSetup( pt1, @@ -84,27 +84,27 @@ def distanceSetup( pt1, # ========== # - Checks - # ========== - + if not mc.objExists(pt1): raise Exception('Point 1 "'+pt1+'" does not exist!') if not glTools.utils.transform.isTransform(pt1):raise Exception('Point 1 "'+pt1+'" is not a valid tranform!') if not mc.objExists(pt2): raise Exception('Point 2 "'+pt2+'" does not exist!') if not glTools.utils.transform.isTransform(pt2):raise Exception('Point 2 "'+pt2+'" is not a valid tranform!') - + if attrObject: if not mc.objExists(attrObject): raise Exception('Attribute object "'+attrObject+'" does not exist!') - + if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(pt1) - + # ======================== # - Build Distance Setup - # ======================== - + distNode = mc.createNode('distanceBetween',n=prefix+'_distanceBetween') mc.connectAttr(pt1+'.worldMatrix[0]',distNode+'.inMatrix1',f=True) mc.connectAttr(pt2+'.worldMatrix[0]',distNode+'.inMatrix2',f=True) dist = mc.getAttr(distNode+'.distance') - + distAttr = None if attrObject: distAttr = addDistanceAttrs(attrObject,dist) @@ -113,11 +113,11 @@ def distanceSetup( pt1, for attrObject in [pt1,pt2]: distAttr = addDistanceAttrs(attrObject,dist) mc.connectAttr(distNode+'.distance',distAttr,f=True) - + # ================= # - Return Result - # ================= - + return distAttr,distNode def remapDistance( distNode, @@ -153,28 +153,28 @@ def remapDistance( distNode, # ========== # - Checks - # ========== - + # Check Attribute Object if attrObject: if not mc.objExists(attrObject): raise Exception('Attribute object "'+attrObject+'" does not exist!') else: attrObject = distNode - + # Min/Max Value if minValue == None: minValue = restValue if maxValue == None: maxValue = restValue - + # ======================== # - Build Distance Remap - # ======================== - + # Get Distance dist = mc.getAttr(distNode+'.distance') distAttr = addDistanceAttrs(attrObject,dist) try: mc.connectAttr(distNode+'.distance',distAttr,f=True) except: print('Distance already connected...skipping!') - + # Add Min/Max Distance Attrs if minDist == None: minDist = 0 if not mc.objExists(attrObject+'.minDistance'): @@ -182,48 +182,48 @@ def remapDistance( distNode, if maxDist == None: maxDist = dist*2 if not mc.objExists(attrObject+'.maxDistance'): mc.addAttr(attrObject,ln='maxDistance',min=dist,dv=maxDist,k=True) - + # Add Rest Value Attr if not restValue == None: if not mc.objExists(attrObject+'.restValue'): mc.addAttr(attrObject,ln='restValue',dv=restValue,k=True) - + # Add Min/Max Value Attr if not mc.attributeQuery('minValue',n=attrObject,ex=True): mc.addAttr(attrObject,ln='minValue',dv=minValue,k=True) if not mc.attributeQuery('maxValue',n=attrObject,ex=True): mc.addAttr(attrObject,ln='maxValue',dv=maxValue,k=True) - + # Build Remap Value remapNode = mc.createNode('remapValue',n=prefix+'_remapValue') mc.connectAttr(distAttr,remapNode+'.inputValue',f=True) - + mc.setAttr(remapNode+'.value[0].value_Interp',interpType) # Spline mc.connectAttr(attrObject+'.minDistance',remapNode+'.value[0].value_Position',f=True) mc.connectAttr(attrObject+'.minValue',remapNode+'.value[0].value_FloatValue',f=True) - + mc.setAttr(remapNode+'.value[1].value_Interp',interpType) # Spline mc.connectAttr(attrObject+'.maxDistance',remapNode+'.value[1].value_Position',f=True) mc.connectAttr(attrObject+'.maxValue',remapNode+'.value[1].value_FloatValue',f=True) - + # Set Rest Value if not restValue == None: mc.setAttr(remapNode+'.value[2].value_Interp',interpType) # Spline mc.connectAttr(attrObject+'.restDistance',remapNode+'.value[2].value_Position',f=True) mc.connectAttr(attrObject+'.restValue',remapNode+'.value[2].value_FloatValue',f=True) - + # Connect Output if not mc.objExists(attrObject+'.outValue'): mc.addAttr(attrObject,ln='outValue',dv=0.0,k=True) mc.connectAttr(remapNode+'.outValue',attrObject+'.outValue',f=True) outAttr = attrObject+'.outValue' - + # ================= # - Return Result - # ================= - + return outAttr,remapNode - + def distanceRemapOutput( pt1, pt2, minDist = None, @@ -260,22 +260,22 @@ def distanceRemapOutput( pt1, # ========== # - Checks - # ========== - + if not mc.objExists(pt1): raise Exception('Point 1 "'+pt1+'" does not exist!') if not glTools.utils.transform.isTransform(pt1):raise Exception('Point 1 "'+pt1+'" is not a valid tranform!') if not mc.objExists(pt2): raise Exception('Point 2 "'+pt2+'" does not exist!') if not glTools.utils.transform.isTransform(pt2):raise Exception('Point 2 "'+pt2+'" is not a valid tranform!') - + # Check Attribute Object if attrObject: if not mc.objExists(attrObject): raise Exception('Attribute object "'+attrObject+'" does not exist!') else: attrObject = pt1 - + # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(attrObject) - + # Check Distance Setup distNode = None distAttr = attrObject+'.length' @@ -284,17 +284,17 @@ def distanceRemapOutput( pt1, else: distNode = mc.listConnections(distAttr,s=True,d=False) if distNode: distNode = distNode[0] - + # Check Values if minDist == None: minDist = 0 if restValue == None: restValue = 0 if minValue == None: minValue = restValue if maxValue == None: maxValue = restValue - + # ======================== # - Build Distance Remap - # ======================== - + outAttr,remapNode = remapDistance( distNode, minDist, maxDist, @@ -304,10 +304,10 @@ def distanceRemapOutput( pt1, attrObject, interpType, prefix ) - + # ================= # - Return Result - # ================= - + return outAttr,distNode,remapNode diff --git a/tools/drivenChannel.py b/tools/drivenChannel.py index d4f2b7b..0ec91f2 100644 --- a/tools/drivenChannel.py +++ b/tools/drivenChannel.py @@ -23,11 +23,11 @@ def setup( targetChannel, # ========== # - Checks - # ========== - + # Method if not method in ['add','average','mult']: raise Exception('Invalid source channel combine method "'+method+'"!') - + # Target Channel if not mc.objExists(targetChannel): raise Exception('Target channel "'+targetChannel+'" does not exist!') @@ -36,107 +36,107 @@ def setup( targetChannel, if not mc.attributeQuery(targetAttr,n=targetNode,ex=True): raise Exception('Target attribute "'+targetAttr+'" not found on node "'+targetNode+'"!') targetAttrLong = mc.attributeQuery(targetAttr,n=targetNode,longName=True) - + # Source Channel for sourceChannel in sourceChannelList: - + if not mc.objExists(sourceChannel): - + # Add Missing Source if addSourceAttrs: sourceNode = sourceChannel.split('.')[0] sourceAttr = sourceChannel.split('.')[-1] - + # Check Source Node if not mc.objExists(sourceNode): raise Exception('Source channel node "'+sourceNode+'" does not exist!') - + # Add Source Attribute mc.addAttr(sourceNode,ln=sourceAttr,k=True) - + else: raise Exception('Source channel "'+sourceChannel+'" does not exist!') - + # Prefix if not prefix: prefix = targetNode+'_'+targetAttr - + # ============================== # - Build Driven Channel Value - # ============================== - + # Initialize outChannel Variable (method return value) outChannel = None - + if method == 'mult': - + multNodeList = [] - + for i in range(len(sourceChannelList)-1): - + # Get Index strInd = glTools.utils.stringUtils.alphaIndex(i) - + # Create Multiply Node multNode = mc.createNode('multDoubleLinear',n=prefix+'_mult'+strInd+'_multDoubleLinear') - + # Define Multiply Inputs multIn1 = sourceChannelList[i] if i: multIn1 = multNodeList[-1] multIn2 = sourceChannelList[i+1] - + # Connect Multiply Inputs mc.connectAttr(multIn1,multNode+'.input1',f=True) mc.connectAttr(multIn2,multNode+'.input2',f=True) - + # Append List multNodeList.append(multNode) - + # Define Output Channel outChannel = multNodeList[-1]+'.output' - + else: - + # Create Combine Node combineNode = mc.createNode('plusMinusAverage',n=prefix+'_'+method+'_plusMinusAverage') - + # Set Combine Mode if method == 'add': mc.setAttr(combineNode+'.operation',1) # Sum elif method == 'average': mc.setAttr(combineNode+'.operation',3) # Averge - + # Connect Source Channels to Combine Node for i in range(len(sourceChannelList)): mc.connectAttr(sourceChannelList[i],combineNode+'.input1D['+str(i)+']',f=True) - + # Connect to Target Channel mc.connectAttr(combineNode+'.output1D',targetChannel,f=True) outChannel = combineNode+'.output1D' - + # =================== # - Multiply Output - # =================== - + if multOutput: - + # Create Output Multiplier Node multOutNode = mc.createNode('multDoubleLinear',n=prefix+'_multOutput_multDoubleLinear') - + # Add Output Multiplier Attribute mc.addAttr(targetNode,ln=targetAttrLong+'_mult') - + # Connect Output Multiplier mc.connectAttr(outChannel,multOutNode+'.input1',f=True) mc.connectAttr(targetNode+'.'+targetAttrLong+'_mult',multOutNode+'.input2',f=True) - + outChannel = multOutNode+'.output' - + # ============================ # - Connect Output to Target - # ============================ - - mc.connectAttr(outChannel,targetChannel,f=True) - + + mc.connectAttr(outChannel,targetChannel,f=True) + # ================= # - Return Result - # ================= - + return outChannel diff --git a/tools/evaluationOrder.py b/tools/evaluationOrder.py index 6e4ec14..b2a669b 100644 --- a/tools/evaluationOrder.py +++ b/tools/evaluationOrder.py @@ -22,10 +22,10 @@ def __init__(self,debug=False): self.root = '' # Initialize dependencyHierarchyNode self.hierarchy = glTools.tools.dependencyHierarchyNode.DependencyHierarchyNode() - + # DEBUG self.debug = debug - + def buildHierarchy(self,root): ''' ''' @@ -36,14 +36,14 @@ def buildHierarchy(self,root): self.root = root # Build Hierarchy from Root self.hierarchy.buildHierarchyFromNode(root) - + def reorder(self): ''' Reorder hierarchy based on ik and constraint relationships ''' self.ikReorder() self.constraintReorder() - + def ikReorder(self): ''' Reorganize the evaluation order based on ikHandle/joint relationships. @@ -55,19 +55,19 @@ def ikReorder(self): # Find ikHandle start joint startJoint = mc.listConnections(ik+'.startJoint',s=True,d=False)[0] startJointNode = self.hierarchy.findDependNode(startJoint) - + # Check ikHandle is in a lower generation than the startJoints current parent if startJointNode.parent: if startJointNode.parent.getGeneration() >= ikNode.getGeneration(): continue - + # Adjust dependency hierarchy if ikNode.getGeneration() > startJointNode.getGeneration(): if self.debug: print('Parent '+startJoint+' under ikHandle '+ik) startJointNode.reparent(ikNode) - + # Print complete message print('EvaluationOrder::ikReorder() completed.') - + def constraintReorder(self,constraintList=[]): ''' Reorganize the evaluation order based on hierarchy constraint dependencies. @@ -77,35 +77,35 @@ def constraintReorder(self,constraintList=[]): # Iterate through all constraints below hierarchy root if not constraintList: constraintList = mc.listRelatives(self.hierarchy.fullName,ad=True,type='constraint') - + if self.debug: print constraintList - + for constraintNode in constraintList: - + if self.debug: print constraintNode - + # Initialize comparison variables lowestNode = None generation = -1 - + # Iterate through constraint targets, to find the target at the lowest generation targetList = glTools.utils.constraint.targetList(constraintNode) if self.debug: print 'targetlist = ' if self.debug: print targetList - for target in targetList: + for target in targetList: targetNode = self.hierarchy.findDependNode(target) targetGeneration = targetNode.getGeneration() - + if self.debug: print 'targetGen = '+str(targetGeneration)+' : gen = '+str(generation) - + if targetGeneration > generation: lowestNode = targetNode generation = targetGeneration - + if self.debug: if lowestNode: print 'Lowest node = '+lowestNode.shortName else: print 'Lowest node = None' - + # Move constraint slaves below the lowest generation constraint target if lowestNode: slaveList = glTools.utils.constraint.slaveList(constraintNode) @@ -116,10 +116,10 @@ def constraintReorder(self,constraintList=[]): if lowestNode.getGeneration() > slaveNode.getGeneration(): if self.debug: print('Parent '+slave+' under constraint target '+lowestNode.shortName) slaveNode.reparent(lowestNode) - + # Print complete message print('EvaluationOrder::constraintReorder() completed.') - + def addAttribute(self,target): ''' Add evaluation order array attribute to a specified maya node. @@ -134,7 +134,7 @@ def addAttribute(self,target): mc.addAttr( target,ln=self.attribute,dt='string',multi=True,h=True) else: print('Attribute "'+target+'.'+self.attribute+'" already exists!') - + def setAttr(self,target,intersectList=[],evalOrderList=[]): ''' Store the calculated evaluation order list as a string array attribute to a specified control. @@ -161,4 +161,4 @@ def setAttr(self,target,intersectList=[],evalOrderList=[]): mc.setAttr(target+'.'+self.attribute+'['+str(i)+']',evalOrderList[i],type='string') # Return evaluation order list return evalOrderList - + diff --git a/tools/exportDeformerData.py b/tools/exportDeformerData.py index bdd1fb3..d750705 100644 --- a/tools/exportDeformerData.py +++ b/tools/exportDeformerData.py @@ -11,33 +11,33 @@ def export(exportPath,deformerList,force=False): ''' # Check export path if not os.path.isdir(exportPath): - + # Create directories if they dont exist os.makedirs(exportPath) - + # Export Deformers for deformer in deformerList: - + # Check deformer if not glTools.utils.deformer.isDeformer(deformer): print('Object "'+deformer+'" is not a valid deformer! Skipping...') continue - + # Initialize Deformer Data deformerData = glTools.data.deformerData.DeformerData(deformer) - + # Build export file path deformerDataPath = (exportPath+'/'+deformer+'.pkl') - + # Check file exists if os.path.isfile(deformerDataPath) and not force: print('File path "'+deformerDataPath+'" exists! Use force=True to overwrite.') continue - + # Export Deformer Data print('Exporting deformer data for "'+deformer+'" to - '+deformerDataPath) deformerData.save(deformerDataPath) - + # Return Result print('Exporting deformers complete!') return 1 @@ -48,7 +48,7 @@ def importData(importPath): # Check import path if not os.path.isdir(importPath): raise Exception('Path "'+importPath+'" does not exist!') - + # Import Deformer Data deformerData = glTools.data.deformerData.DeformerData().load(importPath) deformerData.rebuild() @@ -60,31 +60,31 @@ def exportUI(): window = 'exportDeformerDataUI' if mc.window(window,q=True,ex=True): mc.deleteUI(window) window = mc.window(window,t='Export Deformer Data',s=True) - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # UI Elements pathTBG = mc.textFieldButtonGrp('exportDeformer_pathTBG',label='Export Path',buttonLabel='...',h=30) deformerTSL = mc.textScrollList('exportDeformer_deformerTSL',allowMultiSelection=True) exportB = mc.button('exportDeformer_exportB',label='Export',c='glTools.tools.exportDeformerData.exportFromUI()') closeB = mc.button('exportDeformer_closeB',label='Close',c='mc.deleteUI("'+window+'")') - + # Populate deformer list deformerList = mc.ls(type='weightGeometryFilter') deformerList.sort() for deformer in deformerList: mc.textScrollList(deformerTSL,e=True,a=deformer) - + # UI Callbacks mc.textFieldButtonGrp(pathTBG,e=True,bc='glTools.ui.utils.exportFolderBrowser("'+pathTBG+'")') - + # Form LAYOUT mc.formLayout(FL,e=True,af=[(pathTBG,'top',5),(pathTBG,'left',5),(pathTBG,'right',5)]) # ,ap=[(pathTBG,'bottom',5,10)]) mc.formLayout(FL,e=True,af=[(closeB,'bottom',5),(closeB,'left',5),(closeB,'right',5)]) mc.formLayout(FL,e=True,af=[(exportB,'left',5),(exportB,'right',5)],ac=[(exportB,'bottom',5,closeB)]) mc.formLayout(FL,e=True,af=[(deformerTSL,'left',5),(deformerTSL,'right',5)],ac=[(deformerTSL,'top',5,pathTBG),(deformerTSL,'bottom',5,exportB)]) - + # Show Window mc.window(window,e=True,w=450,h=262) mc.showWindow(window) @@ -95,7 +95,7 @@ def exportFromUI(): # Get export path exportPath = mc.textFieldButtonGrp('exportDeformer_pathTBG',q=True,text=True) deformerList = mc.textScrollList('exportDeformer_deformerTSL',q=True,si=True) - + # Export Deformer Data export(exportPath,deformerList,force=True) @@ -106,26 +106,26 @@ def importUI(): window = 'importDeformerDataUI' if mc.window(window,q=True,ex=True): mc.deleteUI(window) window = mc.window(window,t='Import Deformer Data',s=True) - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # UI Elements pathTBG = mc.textFieldButtonGrp('importDeformer_pathTBG',label='Import Path',buttonLabel='...',h=30) deformerTSL = mc.textScrollList('importDeformer_deformerTSL',allowMultiSelection=True) exportB = mc.button('importDeformer_exportB',label='Import',c='glTools.tools.exportDeformerData.exportFromUI()') closeB = mc.button('importDeformer_closeB',label='Close',c='mc.deleteUI("'+window+'")') - + # UI Callbacks mc.textFieldButtonGrp(pathTBG,e=True,bc='glTools.ui.utils.exportFolderBrowser("'+pathTBG+'")') mc.textFieldButtonGrp(pathTBG,e=True,cc='glTools.tools.exportDeformerData.updateImportList()') - + # Form LAYOUT mc.formLayout(FL,e=True,af=[(pathTBG,'top',5),(pathTBG,'left',5),(pathTBG,'right',5)]) # ,ap=[(pathTBG,'bottom',5,10)]) mc.formLayout(FL,e=True,af=[(closeB,'bottom',5),(closeB,'left',5),(closeB,'right',5)]) mc.formLayout(FL,e=True,af=[(exportB,'left',5),(exportB,'right',5)],ac=[(exportB,'bottom',5,closeB)]) mc.formLayout(FL,e=True,af=[(deformerTSL,'left',5),(deformerTSL,'right',5)],ac=[(deformerTSL,'top',5,pathTBG),(deformerTSL,'bottom',5,exportB)]) - + # Show Window mc.window(window,e=True,w=450,h=262) mc.showWindow(window) @@ -136,7 +136,7 @@ def importFromUI(): # Get import path importPath = mc.textFieldButtonGrp('importDeformer_pathTBG',q=True,text=True) deformerList = mc.textScrollList('importDeformer_deformerTSL',q=True,si=True) - + # Import Deformer Data for deformer in deformerList: importData(importPath+'/'+deformer+'.pkl') @@ -146,10 +146,10 @@ def updateImportList(): # Get import path importPath = mc.textFieldButtonGrp('importDeformer_pathTBG',q=True,text=True) deformerList = [i.split('.')[0] for i in os.listdir(importPath) if i.endswith('.pkl')] - + # Clear deformer list mc.textScrollList('importDeformer_deformerTSL',e=True,ra=True) - + # Populate deformer list for deformer in deformerList: mc.textScrollList('importDeformer_deformerTSL',e=True,a=deformer) diff --git a/tools/exportPointData.py b/tools/exportPointData.py index 4a5b327..9d3ef0a 100644 --- a/tools/exportPointData.py +++ b/tools/exportPointData.py @@ -30,42 +30,42 @@ def export2DPointData(path,pt,cam,start,end,width=2348,height=1152): # Check path dirpath = path.replace(path.split('/')[-1],'') if not os.path.isdir(dirpath): os.makedirs(dirpath) - + # Open file for writing file = open(path,"w") - + # ----------------------- # - Write Position Data - # ----------------------- - + # Cycle through frame range for f in range(start,end+1): - + # Set current frame mc.currentTime(f) - + # Get point world space position pos = glTools.utils.base.getMPoint(pt) - + # Get camera details cam_hfv = mc.camera(cam,q=True,hfv=True) cam_vfv = mc.camera(cam,q=True,vfv=True) cam_mat = glTools.utils.matrix.getMatrix(cam).inverse() - + # Calculate 2D point ssPt = pos * cam_mat ptx = ( ( ( ssPt.x / -ssPt.z ) / math.tan( math.radians(cam_hfv / 2) ) ) / 2.0) + 0.5 pty = ( ( ( ssPt.y / -ssPt.z ) / math.tan( math.radians(cam_vfv / 2) ) ) / 2.0) + 0.5 - + # Write data to file file.write(str(ptx * width) + ' ' + str(pty * height) + '\n') - + # End file with new line file.write('') - + # Close file file.close() - + # Print result print('2D point data exported to '+path) @@ -92,62 +92,62 @@ def export2DOffsetData(path,pt,cam,start,end,width=1,height=1,refFrame=1): # Check path dirpath = path.replace(path.split('/')[-1],'') if not os.path.isdir(dirpath): os.makedirs(dirpath) - + # Open file for writing file = open(path,"w") - + # --------------------- # - Get Base Position - # --------------------- - + # Set current frame mc.currentTime(refFrame) - + # Get point world space position pos = glTools.utils.base.getMPoint(pt) - + # Get camera data cam_hfv = mc.camera(cam,q=True,hfv=True) cam_vfv = mc.camera(cam,q=True,vfv=True) cam_mat = glTools.utils.matrix.getMatrix(cam).inverse() - + # Calculate 2D point ssPt = pos * cam_mat basex = ( ( ( ssPt.x / -ssPt.z ) / math.tan( math.radians(cam_hfv / 2) ) ) / 2.0) + 0.5 basey = ( ( ( ssPt.y / -ssPt.z ) / math.tan( math.radians(cam_vfv / 2) ) ) / 2.0) + 0.5 - + # --------------------- # - Write Offset Data - # --------------------- - + # Cycle through frame range for f in range(start,end+1): - + # Set current frame mc.currentTime(f) - + # Get point world space position pos = glTools.utils.base.getMPoint(pt) - + # Get camera details cam_hfv = mc.camera(cam,q=True,hfv=True) cam_vfv = mc.camera(cam,q=True,vfv=True) cam_mat = glTools.utils.matrix.getMatrix(cam).inverse() - + # Calculate 2D point ssPt = pos * cam_mat ptx = ( ( ( ssPt.x / -ssPt.z ) / math.tan( math.radians(cam_hfv / 2) ) ) / 2.0) + 0.5 pty = ( ( ( ssPt.y / -ssPt.z ) / math.tan( math.radians(cam_vfv / 2) ) ) / 2.0) + 0.5 - + # Write data to file file.write(str((ptx - basex) * width) + ' ' + str((pty - basey) * height) + '\n') - + # End file with new line file.write('') - + # Close file file.close() - + # Print result print('2D point offset data exported to '+path) @@ -166,32 +166,32 @@ def export3DPointData(path,pt,start,end): # Check path dirpath = path.replace(path.split('/')[-1],'') if not os.path.isdir(dirpath): os.makedirs(dirpath) - + # Open file for writing file = open(path,"w") - + # ----------------------- # - Write Position Data - # ----------------------- - + # Cycle through frame range for f in range(start,end+1): - + # Set current frame mc.currentTime(f) - + # Get point world space position pos = glTools.utils.base.getPosition(pt) - + # Write data to file file.write(str(pos[0]) + ' ' + str(pos[1]) + ' ' + str(pos[2]) + '\n') - + # End file with new line file.write('') - + # Close file file.close() - + # Print result print('3D point data exported to '+path) @@ -206,46 +206,46 @@ def export3DRotationData(path,pt,start,end,upVec=(0,1,0),rotateOrder='xyz',absol @type start: int @param end: The last frame of the data sequence @type end: int - @param upVec: Up vector used to contruct rotation matrix for non-transform point. + @param upVec: Up vector used to contruct rotation matrix for non-transform point. @type upVec: list or tuple - @param rotateOrder: Output rotate order. + @param rotateOrder: Output rotate order. @type rotateOrder: str - @param absolute: Output absolute values. + @param absolute: Output absolute values. @type absolute: bool ''' # Check path dirpath = path.replace(path.split('/')[-1],'') if not os.path.isdir(dirpath): os.makedirs(dirpath) - + # Open file for writing file = open(path,"w") - + # ----------------------- # - Write Rotation Data - # ----------------------- - + # Cycle through frame range for f in range(start,end+1): - + # Set current frame mc.currentTime(f) - + if absolute: # Get absolute local rotation values rot = mc.getAttr(pt+'.r')[0] else: # Get object world space rotation rot = getRotation(pt,upVec,rotateOrder) - + # Write data to file file.write(str(rot[0]) + ' ' + str(rot[1]) + ' ' + str(rot[2]) + '\n') - + # End file with new line file.write('') - + # Close file file.close() - + # Print result print('3D rotation data exported to '+path) @@ -257,41 +257,41 @@ def getRotation(obj,upVec=(0,1,0),rotateOrder='xyz'): ''' # Get Rotation Matrix if ['transform','joint'].count(mc.objectType(obj)): - + # Get transform matrix mat = glTools.utils.matrix.getMatrix(obj) - + else: - + # Check polyVert selection mc.select(obj) sel = mc.filterExpand(ex=True,sm=31) if not sel: raise Exception('Invalid object selection! Supply a valid transform or polygon vertex!') - + # Get mesh object and component id mesh = mc.ls(obj,o=True)[0] vtxId = int(obj.split('[')[-1].split(']')[0]) - + # Up Vector upVecVec = OpenMaya.MVector(upVec[0],upVec[1],upVec[2]).normal() - + # Get component normal norm = glTools.utils.mesh.getNormal(mesh,vtxId,worldSpace=True) normVec = OpenMaya.MVector(norm[0],norm[1],norm[2]).normal() - + # Cross Vector crossVec = (normVec * upVecVec).normal() cross = [crossVec.x,crossVec.y,crossVec.z] - + # Allign Up Vector upVecVec = (crossVec * normVec).normal() upVec = [upVecVec.x,upVecVec.y,upVecVec.z] - + # Build rotation matrix mat = glTools.utils.matrix.buildMatrix(xAxis=cross,yAxis=upVec,zAxis=norm) - + # Get matrix rotation based on input rotateOrder rot = glTools.utils.matrix.getRotation(mat,rotateOrder) - + # Return result return rot diff --git a/tools/expressionIntegrate.py b/tools/expressionIntegrate.py index 1175494..c4d2413 100644 --- a/tools/expressionIntegrate.py +++ b/tools/expressionIntegrate.py @@ -22,16 +22,16 @@ def measureAttach(measureList,baseMesh,detachList=[]): ''' # Attach measuremenst for measure in measureList: - + # Constrain to mesh meshConn = glTools.tools.measureMeshDistance.constrainMeasure(measure,baseMesh) - + # Add distance attrs distAttr = glTools.tools.measureMeshDistance.addDistanceAttrs(measure,baseMesh) - + # Delete unused measure attachments for obj in detachList: - + # Get measure point constraint meshCon = mc.listConnections(obj,type='dnMeshConstraint') if meshCon: mc.delete(meshCon) @@ -58,102 +58,102 @@ def extractExpressionRegions(char,deleteHistory=True,rebuildDeltas=False): expressionGrp = 'expressions_grp' region_blend_mesh = 'face_expressionDelta_mesh' region_blendShape = 'face_expressionDelta_blendShape' - + # --------------------- # - Import Components - # --------------------- - + # Face Model glTools.utils.dnpublish.importFaceModel(char) - + # Expression Sculpts glTools.utils.dnpublish.importExpressionSculpts(char) - + # Region Definitions regionPath = '/jobs/JCOM/ldev_'+char.lower()+'/rig/scenes/face/expressionIntegrate/region/'+char.upper()+'_FACE_expressionRegion.mb' mc.file(regionPath,i=True,type='mayaBinary',rpr="_",options='v=0',pr=False) - + # ----------------------------------- # - Get expression and region lists - # ----------------------------------- - + # Identify expression list expressionList = [i.split('_')[0] for i in mc.listRelatives(expressionGrp,c=True)] - + # Identify region list regionList = mc.listRelatives(face_regionExtract_grp,c=True,type='joint') regionList.remove(null_region) - + # -------------------- # - Reconnect Deltas - # -------------------- - + # Check reconnectDeltas and deleteHistory if rebuildDeltas and not deleteHistory: - + # Iterate over expressions for target in expressionList: - + # Reset delata shape reset_blendShape = mc.blendShape(face_mesh,target+'_delta',n=target+'_reset_blendShape')[0] mc.setAttr(reset_blendShape+'.'+face_mesh,1.0) mc.delete(target+'_delta',ch=True) - + # Re-apply deltas as result of rigBase and sculpt delta_blendShape = mc.blendShape([target+'_rigBase',target+'_sculpt'],target+'_delta',n=target+'_delta_blendShape')[0] mc.setAttr(delta_blendShape+'.'+target+'_rigBase',-1.0) mc.setAttr(delta_blendShape+'.'+target+'_sculpt',1.0) - + # ------------------------------ # - Extract Expression Regions - # ------------------------------ - + # Get expression region skinCluster skinCluster = glTools.utils.skinCluster.findRelatedSkinCluster(region_mesh) - + # Perform extraction expressionExtractList = [] for target in expressionList: extractList = glTools.tools.shapeExtract.shapeExtract_skinCluster(face_mesh,target+'_delta',skinCluster,regionList,deleteHistory,prefix=target) expressionExtractList += extractList - + # Group extractin results expressionExtractGrp = mc.ls(mc.listRelatives(expressionExtractList,p=True)) expressionExtractMainGrp = mc.group(expressionExtractGrp,n='expression_extract_grp') - + # ------------------------------------- # - Apply Extracted Expression Deltas - # ------------------------------------- - + region_blendShape = mc.blendShape(expressionExtractList,face_mesh,n=region_blendShape)[0] region_blend_mesh = mc.rename(face_mesh,region_blend_mesh) mc.parent(region_blend_mesh,w=True) - + # ------------ # - Clean up - # ------------ - + # Delete face mesh group mc.delete('*_curveInfo') mc.delete('*_detachCurve') mc.delete(face_mesh_grp) - + # Delete region mesh and joints mc.delete(face_regionExtract_grp) - + # Check deleteHistory if deleteHistory: - + # Delete region extract meshes mc.delete(expressionExtractMainGrp) - + # Delete expression mesh group mc.delete(expressionGrp) - + # ----------------- # - Return Result - # ----------------- - + return region_blend_mesh def buildExpressionRig(char): @@ -165,55 +165,55 @@ def buildExpressionRig(char): # --------------------------- # - Define constant strings - # --------------------------- - + face_mesh = 'face_mesh' face_expressionDelta_mesh = 'face_expressionDelta_mesh' shapeAdd_blendShape = 'shapeAdd_blendShape' targetToSwitchOff = 'shapes_face_mesh' - + base_prefs_null = 'base_prefs_null' base_prefs_attr = 'expressionShape' - + # --------------------- # - Import Components - # --------------------- - + # Expression Sculpts glTools.utils.dnpublish.importExpressionSculpts(char) - + # Expression Regions Deltas print('IMPORTING: '+char.upper()+' Expression Deltas') expressionDeltaPath = '/jobs/JCOM/ldev_'+char.lower()+'/rig/scenes/face/expressionIntegrate/expression/'+char.upper()+'_FACE_expressionDelta.mb' mc.file(expressionDeltaPath,i=True,type='mayaBinary',rpr="_",options='v=0',pr=False) - + # Measurements print('IMPORTING: '+char.upper()+' Face Measurements') measurementPath = '/jobs/JCOM/ldev_'+char.lower()+'/rig/scenes/face/expressionIntegrate/measure/'+char.upper()+'_FACE_measure.mb' mc.file(measurementPath,i=True,type='mayaBinary',rpr="_",options='v=0',pr=False) - + # ------------------------------------------ # - Connect To Expression Delta BlendShape - # ------------------------------------------ - + nextTargetIndex = glTools.utils.blendShape.nextAvailableTargetIndex(shapeAdd_blendShape) mc.blendShape(shapeAdd_blendShape,e=True,t=(face_mesh,nextTargetIndex,face_expressionDelta_mesh,1.0)) mc.setAttr(shapeAdd_blendShape+'.face_expressionDelta_mesh',1) if mc.objExists(shapeAdd_blendShape+'.'+targetToSwitchOff): mc.setAttr(shapeAdd_blendShape+'.'+targetToSwitchOff,0) - + face_mesh_grp = mc.listRelatives(face_mesh,p=True)[0] mc.parent(face_expressionDelta_mesh,face_mesh_grp) mc.setAttr(face_expressionDelta_mesh+'.v',0) - + # ---------------------------- # - Add Detail Switch to Rig - # ---------------------------- - + mc.addAttr(base_prefs_null,ln=base_prefs_attr,dv=1.0,min=0.0,max=1.0) mc.setAttr(base_prefs_null+'.'+base_prefs_attr,1,e=True,cb=True) mc.connectAttr(base_prefs_null+'.'+base_prefs_attr,shapeAdd_blendShape+'.'+face_expressionDelta_mesh,f=True) - + def rebuildExpressionsWithLatestRig(char,rigHighDetail=True): ''' Rebuild expression shapes using the latest published face rig. @@ -222,185 +222,185 @@ def rebuildExpressionsWithLatestRig(char,rigHighDetail=True): @param rigHighDetail: Switch the face rig highDetail attribute on when rebuilding expressions @type rigHighDetail: bool ''' - + # Rig info fRig_info = glTools.utils.dnpublish.faceRigPubInfo(char) fRig_ns = fRig_info['namespace']+'01' - + # Constants conceptGrp = 'concepts_grp' expressionGrp = 'expressions_grp' - + faceMesh = fRig_ns+':face_mesh' addBlendShape = fRig_ns+':shapeAdd_blendShape' basePrefNull = fRig_ns+':base_prefs_null' - + # -------------------------- # - Import Face Components - # -------------------------- - + glTools.utils.dnpublish.importFaceRig(char) glTools.utils.dnpublish.importExpressionSculpts(char) glTools.utils.dnpublish.importConceptSculpts(char) - + # Identify expression list expressionList = [i.split('_')[0] for i in mc.listRelatives(expressionGrp,c=True)] deltaList = [i+'_delta' for i in expressionList] - + # ---------------------- # - Apply Rig Settings - # ---------------------- - + # Check High detail if rigHighDetail: highDetailAttr = basePrefNull+'.highDetail' if mc.objExists(highDetailAttr): mc.setAttr(highDetailAttr,1) - + # Turn Off Expression Detail expressionDetailAttr = basePrefNull+'.expressionShape' if mc.objExists(expressionDetailAttr): mc.setAttr(expressionDetailAttr,0) - + # ------------------------- # - Get Mesh Spacing Info - # ------------------------- - + # Get bounding box width widthMin = mc.getAttr(faceMesh+'.boundingBoxMinX') widthMax = mc.getAttr(faceMesh+'.boundingBoxMaxX') width = (widthMax - widthMin) * 1.1 - + heightMin = mc.getAttr(faceMesh+'.boundingBoxMinY') heightMax = mc.getAttr(faceMesh+'.boundingBoxMaxY') height = (heightMax - heightMin) * 1.1 - + # ------------------------ # - Load Expression Anim - # ------------------------ - + print('LOADING: '+char.upper()+' Expression Animation') animPath = '/jobs/JCOM/ldev_'+char+'/rig/scenes/face/expressionIntegrate/anim/'+char.upper()+'_FACE_animExpression.anm' mm.eval('dnAnim -read -namespace "'+fRig_ns+':" -keyed 1 -unkeyed 1 -stripNamespaces 1 -matchMode "partialPath" -file "'+animPath+'"') - + # ----------------------------- # - Extract Animation Results - # ----------------------------- - + print('EXTRACTING: '+char.upper()+' Animation Results') - + rigBaseList = [] animResultList = [] - + # Duplicate and layout expression results for i in range(len(expressionList)): - + # Go to expression keyframe mc.currentTime(20*(i+1)) - + # Duplicate expression result rigBaseNew = mc.duplicate(faceMesh,rr=True,n=expressionList[i]+'_rigBaseNEW')[0] - + # Shift expression mesh along the X axis mc.move(width*(i+1),0,0,rigBaseNew) - + # Get expression rigBase rigBase = expressionList[i]+'_rigBase' - if mc.objExists(rigBase): rigBase = mc.rename(rigBase,rigBase+'OLD') + if mc.objExists(rigBase): rigBase = mc.rename(rigBase,rigBase+'OLD') else: raise Exception('Cant find RIGBASE for '+expressionList[i]+' expression!!') - + # Move rigBase mc.move(width*(i+1),0,0,rigBase) - + # Append expression result lists rigBaseList.append(rigBase) animResultList.append(rigBaseNew) - + # Group and position expression mesh results rigBaseGrp = mc.group(rigBaseList,n='expression_rigBaseOLD_GRP',w=True) rigBaseNewGrp = mc.group(animResultList,n='expression_rigBaseNEW_GRP',w=True) - + mc.move(0,-height*4,0,rigBaseNewGrp) mc.move(0,-height*3,0,rigBaseGrp) - + # ----------------------- # - Rebuild Expressions - # ----------------------- - + # Add rigBase targets targetIndex = glTools.utils.blendShape.nextAvailableTargetIndex(addBlendShape) for i in range(len(deltaList)): mc.blendShape(addBlendShape,e=True,t=(faceMesh,targetIndex+i,deltaList[i],1.0)) - + # ---------------------------------- # - Set Expression Delta Keyframes - # ---------------------------------- - + for i in range(len(deltaList)): mc.setKeyframe(addBlendShape,attribute=deltaList[i],t=(20*i),v=0.0) mc.setKeyframe(addBlendShape,attribute=deltaList[i],t=(20*(i+1)),v=1.0) mc.setKeyframe(addBlendShape,attribute=deltaList[i],t=(20*(i+2)),v=0.0) - + # ------------------------------ # - Extract Expression Results - # ------------------------------ - + print('EXTRACTING: '+char.upper()+' Expression Results') - + expressionResultList = [] expressionSculptList = [] expressionConceptList = [] - + # Duplicate and layout expression results for i in range(len(deltaList)): - + # Go to expression keyframe mc.currentTime(20*(i+1)) - + # Duplicate expression result expressionResult = mc.duplicate(faceMesh,rr=True,n=expressionList[i]+'_sculptNEW')[0] - + # Shift expression mesh along the X axis mc.move(width*(i+1),0,0,expressionResult) - + # Layout expression sculpt and concept expressionSculpt = expressionList[i]+'_sculpt' mc.move(width*(i+1),0,0,expressionSculpt) expressionConcept = expressionList[i]+'_concept' mc.move(width*(i+1),0,0,expressionConcept) - + # Append expression result lists expressionResultList.append(expressionResult) expressionSculptList.append(expressionSculpt) expressionConceptList.append(expressionConcept) - + # Group and position expression mesh results expressionResultGrp = mc.group(expressionResultList,n='expression_sculptNEW_GRP',w=True) expressionSculptGrp = mc.group(expressionSculptList,n='expression_sculptOLD_GRP',w=True) expressionConceptGrp = mc.group(expressionConceptList,n='expression_concept_GRP',w=True) - + mc.move(0,height,0,expressionConceptGrp) mc.move(0,-height,0,expressionSculptGrp) - + # ------------------------ # - Reapply Rig Settings - # ------------------------ - + # Turn On Expression Detail expressionDetailAttr = basePrefNull+'.expressionShape' if mc.objExists(expressionDetailAttr): mc.setAttr(expressionDetailAttr,1) - + # ----------- # - Cleanup - # ----------- - + # Move and hide expression and concept group mc.move(-width,0,0,expressionGrp) mc.setAttr(expressionGrp+'.v',0) mc.move(-width*2,0,0,conceptGrp) mc.setAttr(conceptGrp+'.v',0) - + print('COMPLETED: '+char.upper()+' Expression Update') @@ -414,24 +414,24 @@ def replaceExpressionDeltaMesh(namespace='TARSFACEa01:'): # -------------------------- # - Define variable values - # -------------------------- - + face_mesh = namespace+'face_mesh' blendShape = namespace+'shapeAdd_blendShape' target = 'face_expressionDelta_mesh' target_mesh = 'face_expressionDelta_mesh' sourceBlendShape = namespace+'face_expressionDelta_blendShape' targetBlendShape = 'face_expressionDelta_blendShape' - + # ----------------------------------------- # - Replace blendShape connection to face - # ----------------------------------------- - + glTools.utils.blendShape.connectToTarget(blendShape,target_mesh,target,face_mesh,1.0,force=True) - + # ---------------------------------- # - Replace blendShape connections - # ---------------------------------- - + connectionList = mc.listConnections(sourceBlendShape+'.w',s=True,p=True,c=True) for i in range(0,len(connectionList),2): targetPlug = connectionList[i].replace(sourceBlendShape,targetBlendShape) @@ -457,7 +457,7 @@ def barycentricPointWeightSetup(samplePt,targetList,calcList=[True,True,True],pr raise Exception('Target mesh "'+target+'" does not exist!!') if not glTools.utils.mesh.isMesh(target): raise Exception('Target object "'+target+'" is not a valid mesh!!') - + # Generate target points vtxId = mc.getAttr(samplePt+'.vtx') targetLoc = [] @@ -466,13 +466,13 @@ def barycentricPointWeightSetup(samplePt,targetList,calcList=[True,True,True],pr targetPos = mc.pointPosition(target+'.vtx['+str(vtxId)+']') targetLoc.append(mc.spaceLocator(n=prefix+'_'+targetSuffix+'_pnt')[0]) mc.setAttr(targetLoc[-1]+'.t',targetPos[0],targetPos[1],targetPos[2]) - + # Create 3PointSampleWeight setup pointSetup = glTools.tools.barycentricPointWeight.create(samplePt,targetLoc,calcList,prefix) - + # Cleanup mc.delete(targetLoc) - + # Return result return pointSetup # [locator list, triFace, locator_grp] @@ -498,32 +498,32 @@ def combinationShape(attr1,attr2,invertAttr1,invertAttr2,driveAttr,prefix): raise Exception('Input attribute "'+attr1+'" does not exist!!') if not mc.objExists(attr2): raise Exception('Input attribute "'+attr2+'" does not exist!!') - + # Check Invert revNode = '' if invertAttr1 or invertAttr2: revNode = mc.createNode('reverse',n=prefix+'_combine_reverse') - + # Create comination multDoubleLinear node multNode = mc.createNode('multDoubleLinear',n=prefix+'_combine_multDoubleLinear') - + # Connect Attr 1 if invertAttr1: mc.connectAttr(attr1,revNode+'.inputX',f=True) mc.connectAttr(revNode+'.outputX',multNode+'.input1',f=True) else: mc.connectAttr(attr1,multNode+'.input1',f=True) - + # Connect Attr 2 if invertAttr2: mc.connectAttr(attr2,revNode+'.inputY',f=True) mc.connectAttr(revNode+'.outputY',multNode+'.input2',f=True) else: mc.connectAttr(attr2,multNode+'.input2',f=True) - + # Connect combined value to blendShape target weight mc.connectAttr(multNode+'.output',driveAttr,f=True) - + # Return result return (multNode+'.output') @@ -541,18 +541,18 @@ def normalizeShapes(blendShape,targetList,prefix): # Check blendShape if not glTools.utils.blendShape.isBlendShape(blendShape): raise UserInputError('Object "'+blendShape+'" is not a valid blendShape deformer!') - + # Check targetList for target in targetList: if not mc.objExists(blendShape+'.'+target): raise Exception('BlendShape target "'+blendShape+'.'+target+'" does not exist!!') - + # Calculate combined value combine_pma = mc.createNode('plusMinusAverage',n=prefix+'_combinedValue_plusMinusAverage') for i in range(len(targetList)): targetConn = mc.listConnections(blendShape+'.'+targetList[i],s=True,d=False,p=True) mc.connectAttr(targetConn[0],combine_pma+'.input1D['+str(i)+']',f=True) - + # Check combined value combine_cond = mc.createNode('condition',n=prefix+'_combinedValue_condition') mc.setAttr(combine_cond+'.operation',2) # Greater Than @@ -561,7 +561,7 @@ def normalizeShapes(blendShape,targetList,prefix): # Set Division Factor mc.setAttr(combine_cond+'.colorIfFalseR',1.0) mc.connectAttr(combine_pma+'.output1D',combine_cond+'.colorIfTrueR',f=True) - + # Divide each target value for i in range(len(targetList)): target_suffix = targetList[i].split('_')[-1] @@ -583,21 +583,21 @@ def cleanBlendShape(blendShape,baseGeometry): # Check blendShape if not glTools.utils.blendShape.isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape deformer!!') - + # Get blendShape target list targetList = mc.listAttr(blendShape+'.w',m=True) - + # Check blendShape target connections deletedTargetList = [] for target in targetList: targetConn = mc.listConnections(blendShape+'.'+target,s=True,d=False) - + # If no incoming connnections, delete target if not targetConn: try:glTools.utils.blendShape.removeTarget(blendShape,target,baseGeometry) except: continue print('Target "'+target+'" deleted!') deletedTargetList.append(target) - + # Return result return deletedTargetList diff --git a/tools/extractCurves.py b/tools/extractCurves.py index f0a46f9..0a246e2 100644 --- a/tools/extractCurves.py +++ b/tools/extractCurves.py @@ -14,37 +14,37 @@ def getConnectedEdges(edgeList): if not edgeList: raise Exception('Invalid or empty edge list!') edgeList = mc.filterExpand(edgeList,ex=True,sm=32) or [] if not edgeList: raise Exception('Invalid edge list! List of polygon edges required...') - + # Get Mesh from Edges mesh = list(set(mc.ls(edgeList,o=True) or [])) if len(mesh) > 1: print mesh raise Exception('Edges from multiple mesh shapes were supplied!') mesh = mesh[0] - + # Get Edge and Vertex IDs edgeIDs = glTools.utils.component.singleIndexList(edgeList) vertIDs = [glTools.utils.mesh.getEdgeVertexIndices(mesh,i) for i in edgeIDs] - + # Sort Edge IDs based on Connectivity connectedEdges = [] connectedVerts = [] escape = 0 while edgeIDs: - + # Move First Edge to Connected List connectedEdges.append([edgeIDs[0]]) connectedVerts.extend([vertIDs[0]]) del edgeIDs[0] del vertIDs[0] - + # Initialize Connected Status connected = True while connected: - + # Reset Connected Status connected = False - + # Add Connected Edges for i in range(len(edgeIDs)): escape += 1 @@ -55,10 +55,10 @@ def getConnectedEdges(edgeList): del edgeIDs[i] del vertIDs[i] break - + # Check Crazy Iteration Count if escape > 100000000: break - + # Return Result return connectedEdges @@ -77,13 +77,13 @@ def extractEdgeCurves(edgeList,form=2,degree=1,keepHistory=True): # Check Edge List if not edgeList: raise Exception('Invalid or empty edge list! Unable to extract edge curves...') - + # Partition Connected Edges connectedEdges = getConnectedEdges(edgeList) - + # Get Mesh from Edges mesh = mc.ls(edgeList,o=True)[0] - + # Extract Edge Curves crvList = [] nodeList = [] @@ -93,7 +93,7 @@ def extractEdgeCurves(edgeList,form=2,degree=1,keepHistory=True): polyToCurve = mc.polyToCurve(form=form,degree=degree,ch=keepHistory) crvList.append(polyToCurve[0]) if keepHistory: nodeList.append(polyToCurve[1]) - + # Return Result mc.select(crvList) return crvList diff --git a/tools/faceForward.py b/tools/faceForward.py index 40b0095..3907889 100644 --- a/tools/faceForward.py +++ b/tools/faceForward.py @@ -33,7 +33,7 @@ def faceForward(transform,aimAxis='z',upAxis='y',upVector=(0,1,0),upVectorType=' # Check upVectorObject if upVectorType=='object' and not mc.objExists(upVectorObject): raise UserInputError('UpVector object "'+upVectorObject+'" does not exist!!') - + # Get Rotate Values rotate = faceForwardRotation(transform,aimAxis,upAxis,upVector,upVectorType,upVectorObject,previousFrameVelocity) # Set Rotate Values @@ -70,33 +70,33 @@ def faceForwardRotation(transform,aimAxis='z',upAxis='y',upVector=(0,1,0),upVect # Check upVectorObject if upVectorType=='object' and not mc.objExists(upVectorObject): raise UserInputError('UpVector object "'+upVectorObject+'" does not exist!!') - + # Get transform parent parent = '' parentList = mc.listRelatives(transform,p=True,pa=True) if parentList: parent = parentList[0] - + # Get frame frame = mc.currentTime(q=True) if time != None: frame = time - + # Get transform matrices for current frame tMatrix = glTools.utils.matrix.getMatrix(transform=transform,time=frame) pMatrix = OpenMaya.MMatrix.identity if parent: pMatrix = glTools.utils.matrix.getMatrix(transform=parent,time=frame) - + # Get position for current frame tx = mc.getAttr(transform+'.tx',t=frame) ty = mc.getAttr(transform+'.ty',t=frame) tz = mc.getAttr(transform+'.tz',t=frame) cPos = OpenMaya.MPoint(tx,ty,tz,1.0) - + # Get position for next frame tx = mc.getAttr(transform+'.tx',t=frame+1) ty = mc.getAttr(transform+'.ty',t=frame+1) tz = mc.getAttr(transform+'.tz',t=frame+1) nPos = OpenMaya.MPoint(tx,ty,tz,1.0) - + # Get aimVector aimVector = (0,0,0) # Check forward velocity @@ -115,7 +115,7 @@ def faceForwardRotation(transform,aimAxis='z',upAxis='y',upVector=(0,1,0),upVect aimVector = (aimVec.x,aimVec.y,aimVec.z) else: return mc.getAttr(transform+'.rotate')[0] - + # Get upVector if upVectorType == 'current': upVec = OpenMaya.MVector(upVector[0],upVector[1],upVector[2]) * tMatrix @@ -130,12 +130,12 @@ def faceForwardRotation(transform,aimAxis='z',upAxis='y',upVector=(0,1,0),upVect upVector = (upVec.x,upVec.y,upVec.z) elif upVectorType == 'vector': pass - + # Build Rotation Matrix rMatrix = glTools.utils.matrix.buildRotation(aimVector,upVector,aimAxis,upAxis) if parent: rMatrix *= pMatrix.inverse() rotate = glTools.utils.matrix.getRotation(rMatrix,mc.getAttr(transform+'.ro')) - + # Return result return rotate @@ -170,12 +170,12 @@ def faceForwardAnim(transform,aimAxis='z',upAxis='y',upVector=(0,1,0),upVectorTy # Check upVectorObject if upVectorType=='object' and not mc.objExists(upVectorObject): raise UserInputError('UpVector object "'+upVectorObject+'" does not exist!!') - + # Get transform parent parent = '' parentList = mc.listRelatives(transform,p=True,pa=True) if parentList: parent = parentList[0] - + # Get sample frames sFrames = [] if frameStart < 0: frameStart = OpenMayaAnim.MAnimControl().minTime().value() @@ -186,7 +186,7 @@ def faceForwardAnim(transform,aimAxis='z',upAxis='y',upVector=(0,1,0),upVectorTy tAnimCurve = mc.listConnections([transform+'.tx',transform+'.ty',transform+'.tz'],s=True,d=True,type='animCurve') if not tAnimCurve: raise UserInputError('Object "'+transform+'" has no translate keys! Set sampleByFrame argument greater than zero!') [sFrames.append(i) for i in mc.keyframe(tAnimCurve,q=True,tc=True,t=(frameStart,frameEnd)) if not sFrames.count(i)] - + # Sample frames for f in sFrames: # Get rotation values @@ -199,6 +199,6 @@ def faceForwardAnim(transform,aimAxis='z',upAxis='y',upVector=(0,1,0),upVectorTy mc.setKeyframe(transform,at='rotateY',t=f,v=rotate[1]) mc.setAttr(transform+'.rotateZ',rotate[2]) mc.setKeyframe(transform,at='rotateZ',t=f,v=rotate[2]) - + # Filter Curves mc.filterCurve([transform+'.rotateX',transform+'.rotateY',transform+'.rotateZ']) diff --git a/tools/findInputShape.py b/tools/findInputShape.py index fbc4caa..b89a0b9 100644 --- a/tools/findInputShape.py +++ b/tools/findInputShape.py @@ -11,12 +11,12 @@ def findInputShape(shape): ''' # Get MObject for shape shapeObj = getMObject(shape) - + # Get inMesh connection inMeshConn = mc.listConnections(shape+'.inMesh') if not inMeshConn: raise Exception('Mesh attribute "'+shape+'.inMesh" has no incoming connections!') - + # Find connected deformer deformerObj = getMObject(inMeshConn[0]) if not deformerObj.hasFn(OpenMaya.MFn.kGeometryFilt): @@ -25,14 +25,14 @@ def findInputShape(shape): raise Exception('Shape node "'+shape+'" is not affected by any valid deformers!') else: deformerObj = getMObject(deformerHist[0]) - + # Get deformer function set deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) - + # Get input shape for deformer geomIndex = deformerFn.indexForOutputShape(shapeObj) inputShapeObj = deformerFn.inputShapeAtIndex(geomIndex) - + # Return result return OpenMaya.MFnDependencyNode(inputShapeObj).name() @@ -45,12 +45,12 @@ def getMObject(object): # Check input object if not mc.objExists(object): raise UserInputError('Object "'+object+'" does not exist!!') - + # Get selection list selectionList = OpenMaya.MSelectionList() OpenMaya.MGlobal.getSelectionListByName(object,selectionList) mObject = OpenMaya.MObject() selectionList.getDependNode(0,mObject) - + # Return result return mObject diff --git a/tools/fixNonReferenceInputShape.py b/tools/fixNonReferenceInputShape.py index 7177c18..0c06d14 100644 --- a/tools/fixNonReferenceInputShape.py +++ b/tools/fixNonReferenceInputShape.py @@ -15,11 +15,11 @@ def checkNonReferenceInputShapes(root,verbose=False): # Check Root Exists if not mc.objExists(root): raise Exception('Root node "'+root+'" does not exist!') - + # Get Transform Descendants (Geometry Only) xforms = mc.ls(mc.listRelatives(root,ad=True),transforms=True) geoList = [geo for geo in xforms if mc.listRelatives(geo,s=True)] - + # Check Non Referenced Input Shapes nonRefInputs = [] hasNonRefInput = False @@ -31,7 +31,7 @@ def checkNonReferenceInputShapes(root,verbose=False): else: if hasNonRefInput: nonRefInputs.append(geo) - + # Print Result if verbose: if nonRefInputs: @@ -44,7 +44,7 @@ def checkNonReferenceInputShapes(root,verbose=False): print('==========================================') print('No nonReference input geometries found...') print('==========================================\n') - + # Return Result return nonRefInputs @@ -59,10 +59,10 @@ def fixNonReferenceInputShapes(root,verbose=False): # Check Root if not mc.objExists(root): raise Exception('Root node "'+root+'" does not exist!') - + # Get Non Reference Input Geometry nonRefInputs = checkNonReferenceInputShapes(root,verbose=verbose) - + # Fix Non Referenced Input Shapes for geo in nonRefInputs: if verbose: print('# ==== Fixing nonReference input shape for geometry "'+geo+'"!') diff --git a/tools/flattenScene.py b/tools/flattenScene.py index 2805c22..ff60ea4 100644 --- a/tools/flattenScene.py +++ b/tools/flattenScene.py @@ -26,35 +26,35 @@ def flatten(verbose=True): print('=================') print('- Flatten Scene -') print('=================') - + # Encode Reference File Path to Nodes encodeReferenceFilePath(verbose) - + # Fix NonReference Inputs fixNonReferenceInputs(verbose) - + # Import References importAllReferences(verbose) - + # Delete Namespaces deleteAllNS(verbose) - + # Delete History deleteHistory(verbose) - + # Delete Nodes deleteNodes(verbose) - + # Reparent Nodes reparentOnFlatten(verbose) - + # Renames Nodes renameShapes(verbose) renameOnFlatten(verbose) - + # Cleanup - Delete and Lock FlattenScene Attributes cleanup(verbose) - + # Print Header if verbose: print('===========================') @@ -70,49 +70,49 @@ def cleanup(verbose=True): # ===================== # - Delete Attributes - # ===================== - + # For Each Attribute attrList = [ 'encodeReferenceFilePath', 'renameOnFlatten', 'reparentOnFlatten', 'deleteHistoryOnFlatten', 'fixNonReferenceInputsRoot' ] - + for attr in attrList: - + # For Each Node attrNodes = mc.ls('*.'+attr,o=True,r=True) for node in attrNodes: - + # Print Msg if verbose: print ('Deleting Attribute "'+node+'.'+attr+'"') - + # Delete Attribute mc.setAttr(node+'.'+attr,l=False) mc.deleteAttr(node+'.'+attr) - + # =================== # - Lock Attributes - # =================== - + # For Each Attribute attrList = ['referenceFilePath'] for attr in attrList: - + # For Each Node attrNodes = mc.ls('*.'+attr,o=True,r=True) for node in attrNodes: - + # Print Msg if verbose: print ('Locking Attribute "'+node+'.'+attr+'"') - + # Lock Attribute mc.setAttr(node+'.'+attr,l=True) - + # ================= # - Return Result - # ================= - + return def importAllReferences(verbose=True): @@ -123,11 +123,11 @@ def importAllReferences(verbose=True): ''' # List all reference nodes refList = glTools.utils.reference.listReferences() - + # Import objects from reference for refNode in refList: glTools.utils.reference.importReference(refNode,verbose) - + def deleteAllNS(verbose=True): ''' Delete all scene namespaces @@ -136,13 +136,13 @@ def deleteAllNS(verbose=True): ''' # Get scene namespace list nsList = glTools.utils.namespace.getAllNS(excludeList=['UI','shared']) - + # For each namespace for ns in nsList: - + # Delete namespace glTools.utils.namespace.deleteNS(ns) - + # Print message if verbose: print('Removed namespace "'+ns+'" from scene!') @@ -154,47 +154,47 @@ def renameShapes(verbose=True): ''' # List all scene transforms xformList = mc.ls(type='transform') - + # Iterate over transforms for xform in xformList: - + # Get Xform Short Name xformSN = xform.split('|')[-1] - + # List all shapes allShapeList = mc.listRelatives(xform,s=True,pa=True) if not allShapeList: continue - + # List all non-intermediate shape children shapeList = mc.listRelatives(xform,s=True,ni=True,pa=True) if not shapeList: continue - + # List all intermediate shapes if len(allShapeList) == len(shapeList): continue intShapeList = list(set(allShapeList)-set(shapeList)) - + # Check shape naming for shape in shapeList: - + # Get Shape Short Name shapeSN = shape.split('|')[-1] - + # Check for ShapeDeformed naming if shapeSN.endswith('Deformed'): - + # Find input shape try: inputShape = glTools.utils.shape.findInputShape(shape) except: inputShape = glTools.utils.shape.findInputShape2(shape) - + # Get InputShape Short Name inputShapeSN = inputShape.split('|')[-1] - + # Check Input Shape if inputShapeSN != shapeSN: # Rename input shape if verbose: print('Renaming: '+inputShapeSN+' -> '+xformSN+'IntermediateShape') inputShape = mc.rename(inputShape,xformSN+'IntermediateShape') - + # Rename current shape if verbose: print('Renaming: '+shapeSN+' -> '+xformSN+'Shape') shape = mc.rename(shape,xformSN+'Shape') @@ -209,23 +209,23 @@ def deleteNodes(verbose=True): # ========== # - Checks - # ========== - + # Check Set Exists if not mc.objExists('nodesToDelete'): return [] - + # Check Nodes nodesToDelete = mc.sets('nodesToDelete',q=True) for node in nodesToDelete: if not mc.objExists(node): raise Exception('Object "" does not exist! Unable to delete') - + # ================ # - Delete Nodes - # ================ - + deletedNodes = [] for node in nodesToDelete: - + try: # Delete Node mc.delete(node) @@ -239,11 +239,11 @@ def deleteNodes(verbose=True): print ('Object "'+node+'" successfully delete!') # Append Return List deletedNodes.append(node) - + # ================= # - Return Result - # ================= - + return deletedNodes def renameOnFlatten(verbose=True): @@ -255,37 +255,37 @@ def renameOnFlatten(verbose=True): # ========== # - Checks - # ========== - + nodeList = mc.ls('*.renameOnFlatten',o=True) if not nodeList: return [] - + # ================ # - Rename Nodes - # ================ - + renameList = [] for node in nodeList: - + # Get Rename String renameStr = mc.getAttr(node+'.renameOnFlatten') # Check Empty String if not renameStr: continue if mc.objExists(renameStr): raise Exception('RenameOnFlatten: Object "'+node+'" cant be renamed to "'+renameStr+'"! Object of that name already exists...') - + # Rename Node renamed = mc.rename(node,renameStr) - + # Print Msg if verbose: print ('Renaming "'+node+'" -> "'+renamed+'"') - + # Append Result renameList.append(renamed) - + # ================= # - Return Result - # ================= - + return renameList def reparentOnFlatten(verbose): @@ -297,40 +297,40 @@ def reparentOnFlatten(verbose): # ========== # - Checks - # ========== - + nodeList = mc.ls('*.reparentOnFlatten',o=True) if not nodeList: return [] - + # ================== # - Reparent Nodes - # ================== - + reparentList = [] for node in nodeList: - + # Get Parent parentConn = mc.listConnections(node+'.reparentOnFlatten',s=True,d=False) if not parentConn: continue parent = parentConn[0] - + # Check Parent if not mc.objExists(parent): raise Exception('Target parent node "'+parent+'" does not exist!') - + # Reparent Node reparented = mc.parent(node,parent)[0] - + # Print Msg if verbose: print ('Reparenting "'+node+'" -> "'+parent+'"') - + # Append Result reparentList.append(reparented) - + # ================= # - Return Result - # ================= - + return reparentList def deleteHistory(verbose): @@ -342,27 +342,27 @@ def deleteHistory(verbose): # ========== # - Checks - # ========== - + nodeList = mc.ls('*.deleteHistoryOnFlatten',o=True,dag=True) if not nodeList: return [] - + # ================== # - Delete History - # ================== - + for node in nodeList: - + # Print Msg if verbose: print ('Deleting Construction History for "'+node+'"') - + # Delete History try: mc.delete(node,ch=True) except: print('Problem deleting construction history on node "'+node+'" during flattenScene!') - + # ================= # - Return Result - # ================= - + return nodeList def fixNonReferenceInputs(verbose=False): @@ -373,16 +373,16 @@ def fixNonReferenceInputs(verbose=False): ''' # Get Root Nodes rootNodes = mc.ls('*.fixNonReferenceInputsRoot',o=True,r=True) or [] - + # For Each Root Node for root in rootNodes: - + # Check Non Reference Inputs if glTools.tools.fixNonReferenceInputShape.checkNonReferenceInputShapes(root,verbose=verbose): - + # Check Non Reference Inputs glTools.tools.fixNonReferenceInputShape.fixNonReferenceInputShapes(root,verbose=verbose) - + # Return Result return rootNodes @@ -395,36 +395,36 @@ def encodeReferenceFilePath(verbose=True): # ========== # - Checks - # ========== - - # Get Node to Encode File Path To + + # Get Node to Encode File Path To nodeList = mc.ls('*.encodeReferenceFilePath',o=True,r=True) if not nodeList: return [] - + # ============================== # - Encode Reference File Path - # ============================== - + attr = 'ABC_referenceFilePath' for node in nodeList: - + # Add File Path Attribute if not mc.objExists(node+'.'+attr): mc.addAttr(node,ln=attr,dt='string') - + # Get Reference File Path refFile = glTools.utils.reference.getReferenceFile(node,withoutCopyNumber=True) realPath = os.path.realpath(refFile) - + # Print Msg if verbose: print ('Encoding Reference File Path to node "'+node+'": ('+realPath+')') - + # Set Reference File Path String mc.setAttr(node+'.'+attr,realPath,type='string') - + # ================= # - Return Result - # ================= - + return nodeList def createNodesToDeleteSet(nodes=[]): @@ -437,10 +437,10 @@ def createNodesToDeleteSet(nodes=[]): nodesToDeleteSet = 'nodesToDelete' if not mc.objExists(nodesToDeleteSet): mc.sets(n=nodesToDeleteSet,empty=True) - + # Add Items to Set if nodes: mc.sets(nodes,fe=nodesToDeleteSet) - + # Return Result return nodesToDeleteSet @@ -454,36 +454,36 @@ def addReferencePathAttr(node): # ========== # - Checks - # ========== - + # Check Node if not mc.objExists(node): raise Exception('Object "'+node+'" does not exist!') - + # Check Reference if not glTools.utils.reference.isReferenced(node): raise Exception('Object "'+node+'" is not a referenced node!') - + # Check Attribute attr = 'encodeReferenceFilePath' if mc.objExists(node+'.'+attr): print('Attribute "'+node+'.'+attr+'" already exists!') return node+'.'+attr - + # ================================ # - Add Reference Path Attribute - # ================================ - + # Add Attribute mc.addAttr(node,ln=attr,at='bool') # Set Rename Value mc.setAttr(node+'.'+attr,1) - + # ================= # - Return Result - # ================= - + print('"'+attr+'" attribute added to node "'+node+'".') - + return node+'.'+attr def addRenameAttr(node,rename=''): @@ -497,31 +497,31 @@ def addRenameAttr(node,rename=''): # ========== # - Checks - # ========== - + if not mc.objExists(node): raise Exception('Object "'+node+'" does not exist!') - + if mc.objExists(node+'.renameOnFlatten'): print('RenameOnFlatten attribute "'+node+'.renameOnFlatten" already exist!') return node+'.renameOnFlatten' - + # ======================== # - Add Rename Attribute - # ======================== - + # Add Attribute attr = 'renameOnFlatten' mc.addAttr(node,ln=attr,dt='string') - + # Set Rename Value if rename: mc.setAttr(node+'.'+attr,rename,type='string') - + # ================= # - Return Result - # ================= - + print('"'+attr+'" attribute added to node "'+node+'".') - + return node+'.'+attr def addReparentAttr(node,parent=''): @@ -529,37 +529,37 @@ def addReparentAttr(node,parent=''): Add reparentOnFlatten (message) attribute to the specified node. @param node: Node to add reparent attribute to. @type node: str - @param rename: Connect an existing node (message attr) to the reparent attribute. + @param rename: Connect an existing node (message attr) to the reparent attribute. @type rename: str ''' # ========== # - Checks - # ========== - + if not mc.objExists(node): raise Exception('Object "'+node+'" does not exist!') - + if parent and not mc.objExists(parent): raise Exception('Parent target "'+node+'" does not exist!') - + # ======================== # - Add Rename Attribute - # ======================== - + # Add Attribute attr = 'reparentOnFlatten' if not mc.attributeQuery(attr,n=node,ex=True): mc.addAttr(node,ln=attr,at='message') - + # Connect Reparent Node if parent: try: mc.connectAttr(parent+'.message',node+'.'+attr,f=True) except: pass - + # ================= # - Return Result - # ================= - + print('"'+attr+'" attribute added to node "'+node+'".') return node+'.'+attr @@ -573,32 +573,32 @@ def addDeleteHistoryAttr(node): # ========== # - Checks - # ========== - + # Check Node if not mc.objExists(node): raise Exception('Object "'+node+'" does not exist!') - + # Check Attribute attr = 'deleteHistoryOnFlatten' if mc.objExists(node+'.'+attr): print('Attribute "'+node+'.'+attr+'" already exists!') return node+'.'+attr - + # ================================ # - Add Reference Path Attribute - # ================================ - + # Add Attribute mc.addAttr(node,ln=attr,at='bool') # Set Rename Value mc.setAttr(node+'.'+attr,1) - + # ================= # - Return Result - # ================= - + print('"'+attr+'" attribute added to node "'+node+'".') - + return node+'.'+attr def addFixNonReferenceInputAttr(node): @@ -611,28 +611,28 @@ def addFixNonReferenceInputAttr(node): # Check Node if not mc.objExists(node): raise Exception('Object "'+node+'" does not exist!') - + # Check Attribute attr = 'fixNonReferenceInputsRoot' if mc.objExists(node+'.'+attr): print('Attribute "'+node+'.'+attr+'" already exists!') return node+'.'+attr - + # ================================ # - Add Reference Path Attribute - # ================================ - + # Add Attribute mc.addAttr(node,ln=attr,at='bool') # Set Rename Value mc.setAttr(node+'.'+attr,1) - + # ================= # - Return Result - # ================= - + print('"'+attr+'" attribute added to node "'+node+'".') - + return node+'.'+attr def addReparentAttrFromSel(): @@ -641,13 +641,13 @@ def addReparentAttrFromSel(): ''' # Get Selection sel = mc.ls(sl=True,transforms=True) - + # Check Selection if len(sel) < 2: raise Exception('Invalid selection for addReparentAttrFromSel()! Select the child and parent object and run again.') - + # Add Reparent Attr for obj in sel[:-1]: addReparentAttr(node=obj,parent=sel[-1]) - + diff --git a/tools/generateParticles.py b/tools/generateParticles.py index 429e3f9..c9a36df 100644 --- a/tools/generateParticles.py +++ b/tools/generateParticles.py @@ -8,7 +8,7 @@ def locatorParticlesUI(): locParticleUI = 'locatorParticleWindow' if mc.window(locParticleUI,q=True,ex=True): mc.deleteUI(locParticleUI) locParticleUI = mc.window(locParticleUI,t='Generate Particles') - + # UI Layout mc.columnLayout(adj=False,cal='left') partiTFG = mc.textFieldGrp('locParticle_particleTFG',label='Particle',text='',cw=[(1,100)]) @@ -16,14 +16,14 @@ def locatorParticlesUI(): rotateLocCBG = mc.checkBoxGrp('locParticle_rotateCBG',label='Add rotatePP',ncb=1,v1=0,cw=[(1,100)]) scaleLocCBG = mc.checkBoxGrp('locParticle_scaleCBG',label='Add scalePP',ncb=1,v1=0,cw=[(1,100)]) selfCollideCBG = mc.checkBoxGrp('locParticle_selfCollideCBG',label='self collide',ncb=1,v1=0,cw=[(1,100)]) - + mc.button(l='Create Particles',c='glTools.tools.generateParticles.locatorParticlesFromUI()') - + # Popup menu mc.popupMenu(parent=partiTFG) for p in mc.ls(type=['particle','nParticle']): mc.menuItem(p,c='mc.textFieldGrp("'+partiTFG+'",e=True,text="'+p+'")') - + # Show Window mc.showWindow(locParticleUI) @@ -33,14 +33,14 @@ def locatorParticlesFromUI(): # Define window locParticleUI = 'locatorParticleWindow' if not mc.window(locParticleUI,q=True,ex=True): return - + # Get user selection sel = mc.ls(sl=True) if len(sel) == 1: if not mc.objExists(sel[0]+'.localScale'): sel = mc.listRelatives(sel[0],c=True,pa=True) locList = [i for i in sel if mc.objExists(i+'.localScale')] - + # Get Particle particle = mc.textFieldGrp('locParticle_particleTFG',q=True,text=True) if not particle: particle = 'nParticle1' @@ -48,53 +48,53 @@ def locatorParticlesFromUI(): selfCollide = mc.checkBoxGrp('locParticle_selfCollideCBG',q=True,v1=True) rt = mc.checkBoxGrp('locParticle_rotateCBG',q=True,v1=True) sc = mc.checkBoxGrp('locParticle_scaleCBG',q=True,v1=True) - + # Execute generate particle command locatorParticles(locList,particle,radius,selfCollide,rotatePP=rt,scalePP=sc) - + def locatorParticles(locList,particle,radius=1,selfCollide=False,rotatePP=False,scalePP=False): ''' ''' # Check locator list if not locList: return - + # Check particles if not particle: particle = 'particle1' if not mc.objExists(particle): particle = mc.nParticle(n=particle)[0] - + # Set Particle Object Attrs mc.setAttr(particle+'.particleRenderType',4) mc.setAttr(particle+'.radius',mc.floatSliderGrp('locParticle_radiusFSG',q=True,v=True)) mc.setAttr(particle+'.selfCollide',mc.checkBoxGrp('locParticle_selfCollideCBG',q=True,v1=True)) - + # Create particles ptList = [mc.pointPosition(i) for i in locList] mc.emit(o=particle,pos=ptList) - + # Add and Set RotatePP/ScalePP Values if rotatePP: - + # Check rotatePP attrs if not mc.objExists(particle+'.rotatePP'): addRotatePP(particle) - + # Set rotatePP attrs for i in range(len(locList)): rot = mc.getAttr(locList[i]+'.r') mc.particle(particle,e=True,at='rotatePP',id=i,vv=rot[0]) - + if scalePP: - + # Check scalePP attrs if not mc.objExists(particle+'.scalePP'): addScalePP(particle) - + # Set scalePP attrs for i in range(len(locList)): scl = mc.getAttr(locList[i]+'.s') mc.particle(particle,e=True,at='scalePP',id=i,vv=scl[0]) - + # Save Initial State mc.saveInitialState(particle) @@ -104,29 +104,29 @@ def particleLocatorsUI(): # Get current frame range start = mc.playbackOptions(q=True,min=True) end = mc.playbackOptions(q=True,max=True) - + # Define window particleLocatorsUI = 'particleLocatorsWindow' if mc.window(particleLocatorsUI,q=True,ex=True): mc.deleteUI(particleLocatorsUI) particleLocatorsUI = mc.window(particleLocatorsUI,t='Generate Locators') - + # UI Layout mc.columnLayout(adj=False,cal='left') partiTFG = mc.textFieldGrp('partiLoc_particleTFG',label='Particle',text='',cw=[(1,120)]) prefixTFG = mc.textFieldGrp('partiLoc_prefixTFG',label='Prefix',text='',cw=[(1,120)]) bakeAnimCBG = mc.checkBoxGrp('partiLoc_bakeAnimCBG',label='Bake Animation',ncb=1,v1=0,cw=[(1,120)]) startEndIFG = mc.intFieldGrp('partiLoc_startEndISG',nf=2,label='Frame Range',v1=start,v2=end,cw=[(1,120)]) - + rotateLocCBG = mc.checkBoxGrp('partiLoc_rotateCBG',label='Rotate (rotatePP)',ncb=1,v1=0,cw=[(1,120)]) scaleLocCBG = mc.checkBoxGrp('partiLoc_scaleCBG',label='Scale (scalePP)',ncb=1,v1=0,cw=[(1,120)]) - + mc.button(l='Create Locators',c='glTools.tools.generateParticles.particleLocatorsFromUI()') - + # Popup menu mc.popupMenu(parent=partiTFG) for p in mc.ls(type=['particle','nParticle']): mc.menuItem(p,c='mc.textFieldGrp("'+partiTFG+'",e=True,text="'+p+'")') - + # Show Window mc.showWindow(particleLocatorsUI) @@ -136,11 +136,11 @@ def particleLocatorsFromUI(): # Define window particleLocatorsUI = 'particleLocatorsWindow' if not mc.window(particleLocatorsUI,q=True,ex=True): return - + # Get Particle particle = mc.textFieldGrp('partiLoc_particleTFG',q=True,text=True) if not particle: raise Exception('Particle "'+particle+'" does not exist!!') - + # Get Options prefix = mc.textFieldGrp('partiLoc_prefixTFG',q=True,text=True) bake = mc.checkBoxGrp('partiLoc_bakeAnimCBG',q=True,v1=True) @@ -148,7 +148,7 @@ def particleLocatorsFromUI(): en = mc.intFieldGrp('partiLoc_startEndISG',q=True,v2=True) rotate = mc.checkBoxGrp('partiLoc_rotateCBG',q=True,v1=True) scale = mc.checkBoxGrp('partiLoc_scaleCBG',q=True,v1=True) - + # Create Locators particleLocators(particle,bakeSimulation=bake,rotate=rotate,scale=scale,start=st,end=en,prefix=prefix) @@ -158,20 +158,20 @@ def particleLocators(particle,bakeSimulation=False,rotate=False,scale=False,star # Check Particle if not mc.objExists(particle): raise Exception('Object "'+nParticle+'" is not a valid particle or nParticle object!') - + # Check Prefix if not prefix: prefix = particle - + # Get particle count count = mc.getAttr(particle+'.count') if not count: raise Exception('Invalid particle count! ('+count+')') - + # Create locators partiLocs = [mc.spaceLocator(n=prefix+'_loc'+str(i))[0] for i in range(count)] partiLocsGrp = prefix+'_locGrp' if not mc.objExists(partiLocsGrp): partiLocsGrp = mc.group(em=True,n=partiLocsGrp) mc.parent(partiLocs,partiLocsGrp) - + # For each particle, set locator position for i in range(count): pt = mc.pointPosition(particle+'.pt['+str(i)+']') @@ -182,10 +182,10 @@ def particleLocators(particle,bakeSimulation=False,rotate=False,scale=False,star if scale: sc = mc.particle(particle,q=True,at='scalePP',id=i) mc.setAttr(partiLocs[i]+'.s',*sc) - + # Bake Simulation if(bakeSimulation): - + # Append particle expression expStr = '\n\n//--\n' expStr += 'int $id = id;\n' @@ -200,13 +200,13 @@ def particleLocators(particle,bakeSimulation=False,rotate=False,scale=False,star expStr += '\tvector $scl = scalePP;\n' expStr += '\t scale -a ($scl.x) ($scl.y) ($scl.z) $loc;\n' expStr += '}' - + # Old expression string oldRadStr = mc.dynExpression(particle,q=True,s=True,rad=True) - + # Apply particle expression mc.dynExpression(particle,s=oldRadStr+expStr,rad=True) - + # Bake to keyframes if end < start: start = mc.playbackOptions(q=True,min=True) @@ -215,7 +215,7 @@ def particleLocators(particle,bakeSimulation=False,rotate=False,scale=False,star if rotate: bakeAttrs.extend(['rx','ry','rz']) if scale: bakeAttrs.extend(['sx','sy','sz']) mc.bakeSimulation(partiLocs,at=bakeAttrs,t=(start,end)) - + # Restore particle expression mc.dynExpression(particle,s=oldRadStr,rad=True) @@ -237,13 +237,13 @@ def addRotatePP(particle): particle = particleShape[0] if (mc.objectType(particle) != 'particle') and (mc.objectType(particle) != 'nParticle'): raise Exception('Object "'+particle+'" is not a valid particle or nParticle object!') - + # Add rotatePP attribute if not mc.objExists(particle+'.rotatePP0'): mc.addAttr(particle,ln='rotatePP0',dt='vectorArray') if not mc.objExists(particle+'.rotatePP'): mc.addAttr(particle,ln='rotatePP',dt='vectorArray') - + # Return Result return particle+'.rotatePP' @@ -265,12 +265,12 @@ def addScalePP(particle): particle = particleShape[0] if (mc.objectType(particle) != 'particle') and (mc.objectType(particle) != 'nParticle'): raise Exception('Object "'+particle+'" is not a valid particle or nParticle object!') - + # Add rotatePP attribute if not mc.objExists(particle+'.scalePP0'): mc.addAttr(particle,ln='scalePP0',dt='vectorArray') if not mc.objExists(particle+'.scalePP'): mc.addAttr(particle,ln='scalePP',dt='vectorArray') - + # Return Result return particle+'.scalePP' diff --git a/tools/generateWeights.py b/tools/generateWeights.py index f5d0998..d52755e 100644 --- a/tools/generateWeights.py +++ b/tools/generateWeights.py @@ -22,7 +22,7 @@ def gradientWeights(geometry,pnt1,pnt2,smooth=0): # Check geometry if not mc.objExists(geometry): raise UserInputError('Object "'+geometry+'" does not exist!') - + # Check points pnt1 = glTools.utils.base.getMPoint(pnt1) pnt2 = glTools.utils.base.getMPoint(pnt2) @@ -30,10 +30,10 @@ def gradientWeights(geometry,pnt1,pnt2,smooth=0): pntVec = pnt2 - pnt1 pntVecNorm = pntVec.normal() pntLen = pntVec.length() - + # Get points to generate weights from pointList = glTools.utils.base.getMPointArray(geometry) - + # Build weight array wtList = [] for i in range(pointList.length()): @@ -44,7 +44,7 @@ def gradientWeights(geometry,pnt1,pnt2,smooth=0): for i in range(int(smooth)): wt = glTools.utils.mathUtils.smoothStep(wt) wtList.append(wt) - + # Return result return wtList @@ -65,13 +65,13 @@ def gradientWeights3Point(geometry,inner,mid,outer,smooth=0): ''' # Get Inner Weight List innerWtList = gradientWeights(geometry,inner,mid,smooth) - + # Get Outer Weight List outerWtList = gradientWeights(geometry,outer,mid,smooth) - + # Calculate Final Weight List wtList = [innerWtList[i]*outerWtList[i] for i in range(len(innerWtList))] - + # Return result return wtList @@ -93,35 +93,35 @@ def radialWeights(geometry,center,radius,innerRadius=0.0,smooth=0): # Check geometry if not mc.objExists(geometry): raise UserInputError('Object "'+geometry+'" does not exist!') - + # Check center point pnt = glTools.utils.base.getMPoint(center) - + # Get points to generate weights from pointList = glTools.utils.base.getMPointArray(geometry) - + # Build weight array wtList = [] for i in range(pointList.length()): - + # Initialize zero weight value wt = 0.0 - + # Calculate distance to radial center dist = (pnt-pointList[i]).length() - + # Generate weight value if dist < radius: wt = (radius-innerRadius-dist)/(radius-innerRadius) for i in range(int(smooth)): wt = glTools.utils.mathUtils.smoothStep(wt) - + # Append weight value to weight list wtList.append(wt) - + # Return result return wtList - + def volumeWeights(geometry,volumeCenter,volumeBoundary,volumeInterior='',smoothValue=0): ''' Generate a volume weight list for a specified geometry. @@ -137,27 +137,27 @@ def volumeWeights(geometry,volumeCenter,volumeBoundary,volumeInterior='',smoothV @param smooth: Number of smoothStep iterations @type smooth: int ''' - + # NOT IMPLEMENTED!! raise Exception('NOT FULLY IMPLEMENTED!!') - + # Check geometry if not mc.objExists(geometry): raise UserInputError('Object "'+geometry+'" does not exist!') - + # Check volumeBoundary if not mc.objExists(volumeBoundary): raise UserInputError('Volume boundary "'+volumeBoundary+'" does not exist!') - + # Check volume center point volumeCenterPt = glTools.utils.base.getMPoint(volumeCenter) - + # Get volume geometry bounding box volumeBBox = glTools.utils.base.getMBoundingBox(volumeBoundary,worldSpace=True) - + # Get geometry point array geometryPtArray = glTools.utils.base.getMPointArray(geometry) - + def geometryVolumeWeights(geometry,volumeCenter,volumeBoundary,volumeCenterCurve='',volumeInterior='',smoothValue=0): ''' Generate a volume weight list for a specified geometry. @@ -176,51 +176,51 @@ def geometryVolumeWeights(geometry,volumeCenter,volumeBoundary,volumeCenterCurve # Check geometry if not mc.objExists(geometry): raise UserInputError('Object "'+geometry+'" does not exist!') - + # Check volumeBoundary if not mc.objExists(volumeBoundary): raise UserInputError('Volume boundary "'+volumeBoundary+'" does not exist!') - + # Check volume center point volumeCenterPt = glTools.utils.base.getMPoint(volumeCenter) - + # Get volume geometry bounding box volumeBBox = glTools.utils.base.getMBoundingBox(volumeBoundary,worldSpace=True) - + # Check Volume Center Curve if volumeCenterCurve: if not mc.objExists(volumeCenterCurve): raise Exception('Volume center curve "'+volumeCenterCurve+'" does not exist!') curveFn = glTools.utils.curve.getCurveFn(volumeCenterCurve) - + # Get geometry point array geometryPtArray = glTools.utils.base.getMPointArray(geometry) - + # Iterate through geometry points wtList = [] for i in range(geometryPtArray.length()): - + # Volume Bounding Box test if volumeBBox.contains(geometryPtArray[i]): - + # Check volume center curve if volumeCenterCurve: volumeCenterPt = curveFn.closestPoint(geometryPtArray[i]) - + # Get offset from volume center offsetVec = geometryPtArray[i] - volumeCenterPt offsetDist = offsetVec.length() - + # Get distance to volume boundary boundaryPt = glTools.utils.mesh.intersect(volumeBoundary,volumeCenterPt,offsetVec,False) boundaryDist = (volumeCenterPt - OpenMaya.MPoint(boundaryPt[0],boundaryPt[1],boundaryPt[2],1.0)).length() - + # Get distance to interior volume boundary intBoundaryDist = 0.0 if volumeInterior: intBoundaryPt = glTools.utils.mesh.intersect(volumeInterior,volumeCenterPt,offsetVec,False) intBoundaryDist = (volumeCenterPt - OpenMaya.MPoint(intBoundaryPt[0],intBoundaryPt[1],intBoundaryPt[2],1.0)).length() - + # Caluculate weight wt = 1.0 if offsetDist > intBoundaryDist: @@ -229,15 +229,15 @@ def geometryVolumeWeights(geometry,volumeCenter,volumeBoundary,volumeCenterCurve for n in range(int(smoothValue)): wt = glTools.utils.mathUtils.smoothStep(wt) else: wt = 0.0 - + # Append to weight list wtList.append(wt) - + else: - + # Point is outside volume bounding box. Append zero weight wtList.append(0.0) - + # Return result return wtList @@ -258,49 +258,49 @@ def curveProximityWeights(geometry,curve,maxDistance,minDistance=0.0,smoothValue # Check geometry if not mc.objExists(geometry): raise UserInputError('Object "'+geometry+'" does not exist!') - + # Check curve if not glTools.utils.curve.isCurve(curve): raise Exception('Curve object "'+curve+'" is not a valid nurbs curve!') - + # Get vertex array geometryPtList = glTools.utils.base.getMPointArray(geometry) geometryPtLen = geometryPtList.length() - + # Get curve function set curveFn = glTools.utils.curve.getCurveFn(curve) - + # Get curve bounding box curveBbox = glTools.utils.base.getMBoundingBox(curve,worldSpace=True) # Expand bounding box curveBbox.expand(curveBbox.min() - OpenMaya.MVector(maxDistance,maxDistance,maxDistance)) curveBbox.expand(curveBbox.max() + OpenMaya.MVector(maxDistance,maxDistance,maxDistance)) - + # Build weight list wtList = [] for i in range(geometryPtLen): - + # Check bounding box if curveBbox.contains(geometryPtList[i]): - + # Get distance to curve dist = curveFn.distanceToPoint(geometryPtList[i],OpenMaya.MSpace.kWorld) - + # Calculate weight value if dist <= minDistance: wt = 1.0 elif dist > maxDistance: wt = 0.0 else: wt = 1.0 - (dist - minDistance)/(maxDistance - minDistance) for n in range(int(smoothValue)): wt = glTools.utils.mathUtils.smoothStep(wt) - + # Append to weight list wtList.append(wt) - + else: - + # Point is outside volume bounding box. Append zero weight wtList.append(0.0) - + # Return result return wtList @@ -324,25 +324,25 @@ def meshOffsetWeights(baseMesh,targetMesh,normalizeWeights=False,normalRayInters raise Exception('BaseMesh object "'+baseMesh+'" is not a valid mesh!') if not glTools.utils.mesh.isMesh(targetMesh): raise Exception('TargetMesh object "'+targetMesh+'" is not a valid mesh!') - + # Get vertex arrays basePtList = glTools.utils.base.getMPointArray(baseMesh) targetPtList = glTools.utils.base.getMPointArray(targetMesh) - + basePtLen = basePtList.length() targetPtLen = targetPtList.length() - + if basePtLen != targetPtLen: raise Exception('Vertex count between the base and target mesh does not match!!') - + # Get base normal array normalArray = glTools.utils.mesh.getNormals(baseMesh,worldSpace=False) - + # Build offset list maxDist = 0.0 distArray = [] for i in range(basePtLen): - + # Determine target distance if normalRayIntersect: targetPt = glTools.utils.mesh.intersect(targetMesh,basePtList[i],normalArray[i],True) @@ -351,21 +351,21 @@ def meshOffsetWeights(baseMesh,targetMesh,normalizeWeights=False,normalRayInters else: offset = targetPtList[i] - basePtList[i] dist = OpenMaya.MVector(normalArray[i]) * offset - + # Smooth if normalizeWeights and smoothValue: for n in range(int(smoothValue)): dist = glTools.utils.mathUtils.smoothStep(dist) - + # Append to target distance array distArray.append(dist) - + # Check maxDistance if abs(dist) > maxDist: maxDist = abs(dist) - + # Normalize distance array if normalizeWeights: distArray = [i/maxDist for i in distArray] - + # Return result return maxDist, distArray diff --git a/tools/geometryCenter.py b/tools/geometryCenter.py index 029de3a..7c9add7 100644 --- a/tools/geometryCenter.py +++ b/tools/geometryCenter.py @@ -8,17 +8,17 @@ def geometryCenterLocator(geo){ ''' # Check geo if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') - + # Create Locator loc = mc.spaceLocator(n = geo+'_center') - + # Determine geometry shape geoShape = mc.listRelatives(geo,s=True,ni=True) if not geoShape: raise Exception('Unable to determine geoemtry shape for "'+geo+'"!') - + # Connect to geometry center mc.connectAttr(geoShape[0]+'.center',loc[0]+'.translate',f=True) - + # Return result return loc[0] @@ -29,22 +29,22 @@ def geometryBoundingBox(geo): ''' # Check geoemtry if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') - + # Create Bounding Box bbox = mc.polyCube(ch=False,n=geo+'_boundingBox') - + # Determine geometry shape geoShape = mc.listRelatives(s=True,ni=True,geo) if not geoShape: raise Exception('Unable to determine geoemtry shape for "'+geo+'"!') - + # Connect to boundingBox mc.connectAttr(geoShape[0]+'.center',bbox[0]+'.translate',f=True) mc.connectAttr(geoShape[0]+'.boundingBoxSize',bbox[0]+'.scale',f=True) - + # Turn off boundingBox shading mc.setAttr(geoShape[0]+'.overrideEnabled',1) mc.setAttr(geoShape[0]+'.overrideShading',0) - + # Return result return bbox[0] diff --git a/tools/getScale.py b/tools/getScale.py index fbcb22f..d6c4de0 100644 --- a/tools/getScale.py +++ b/tools/getScale.py @@ -21,73 +21,73 @@ def getScale(obj,worldSpace=False,method='max',boundingBoxScale=False): # Check geometry if obj and not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check method methodList = ['min','max','average','diagonal'] if not methodList.count(method): raise Exception('Invalid method value! ("'+method+'")') - + # =================== # - Get Scale (XYZ) - # =================== - + scale = [0,0,0] - + # Transform Scale if not boundingBoxScale: - + mat = glTools.utils.matrix.getMatrix(obj,local=not(worldSpace)) scalePtr = OpenMaya.MScriptUtil().asDoublePtr() OpenMaya.MTransformationMatrix(mat).getScale(scalePtr,OpenMaya.MSpace.kObject) scale[0] = OpenMaya.MScriptUtil().getDoubleArrayItem(scalePtr,0) scale[1] = OpenMaya.MScriptUtil().getDoubleArrayItem(scalePtr,1) scale[2] = OpenMaya.MScriptUtil().getDoubleArrayItem(scalePtr,2) - + # Bounding Box Scale else: - + bBox = glTools.utils.base.getMBoundingBox(obj,worldSpace=worldSpace) scale[0] = bBox.width() scale[1] = bBox.height() scale[2] = bBox.depth() - + # =========================== # - Determine Overall Scale - # =========================== - + scaleVal = 0.0 - + # Minimum if method == 'min': scaleVal = scale[0] if scale[1] < scaleVal: scaleVal = scale[1] if scale[2] < scaleVal: scaleVal = scale[2] - + # Maximum elif method == 'max': scaleVal = scale[0] if scale[1] > scaleVal: scaleVal = scale[1] if scale[2] > scaleVal: scaleVal = scale[2] - + # Average elif method == 'average': scaleVal = (scale[0]+scale[1]+scale[2])/3 - + # Diagonal elif method == 'diagonal': scaleVal = math.sqrt((scale[0]*scale[0])+(scale[1]*scale[1])+(scale[2]*scale[2])) - + # X if method == 'x': scaleVal = scale[0] - + # Y if method == 'y': scaleVal = scale[1] - + # Z if method == 'z': scaleVal = scale[2] - + # ================= # - Return Result - # ================= - + return scaleVal diff --git a/tools/graphFilter.py b/tools/graphFilter.py index 6878e3c..280a9bf 100644 --- a/tools/graphFilter.py +++ b/tools/graphFilter.py @@ -8,24 +8,24 @@ def ui(): win = 'graphFilterUI' if mc.window(win,q=True,ex=True): mc.deleteUI(win) win = mc.window(win,t='Graph Editor Filter',mxb=True,mnb=True,s=True,wh=[248,210]) - + # Layout fl = mc.formLayout(numberOfDivisions=100) - + # UI Elements graphFilterAttrListTSL = mc.textScrollList('graphFilter_attrListTSL',w=120,nr=8,ams=True) - + graphFilterModeRBG = mc.radioButtonGrp('graphFilter_modeRBG',label='Mode',labelArray2=['Replace','Append'],nrb=2,sl=1) - + graphEditorB = mc.button(l='Graph Editor',c='mm.eval("GraphEditor")') allCurveB = mc.button(l='All Curves',c='displayAllCurves()') clearViewB = mc.button(l='Clear View',c='mc.selectionConnection("graphEditor1FromOutliner",e=True,clear=True)') - + graphFilterFilterB = mc.button('graphFilter_filterB',l='Filter Selected',c='glTools.tools.graphFilter.filterCurves()') graphFilterSelectB = mc.button('graphFilter_selectB',l='Select All',c='glTools.tools.graphFilter.selectAll()') graphFilterClearB = mc.button('graphFilter_clearB',l='Clear list',c='mc.textScrollList("graphFilter_attrListTSL",e=True,ra=True)') graphFilterUpdateB = mc.button('graphFilter_updateB',l='Update List',c='glTools.tools.graphFilter.updateAttrList()') - + # Form Layout mc.formLayout(fl,e=True,af=[(graphFilterAttrListTSL,'left',5),(graphFilterAttrListTSL,'bottom',5)],ap=[(graphFilterAttrListTSL,'right',5,50)],ac=[(graphFilterAttrListTSL,'top',5,graphFilterModeRBG)]) mc.formLayout(fl,e=True,af=[(graphFilterModeRBG,'left',5),(graphFilterModeRBG,'right',5)],ac=[(graphFilterModeRBG,'top',5,graphEditorB)]) @@ -36,10 +36,10 @@ def ui(): mc.formLayout(fl,e=True,af=[(graphFilterSelectB,'right',5)],ap=[(graphFilterSelectB,'left',5,50)],ac=[(graphFilterSelectB,'top',5,graphFilterFilterB)]) mc.formLayout(fl,e=True,af=[(graphFilterClearB,'right',5)],ap=[(graphFilterClearB,'left',5,50)],ac=[(graphFilterClearB,'top',5,graphFilterSelectB)]) mc.formLayout(fl,e=True,af=[(graphFilterUpdateB,'right',5)],ap=[(graphFilterUpdateB,'left',5,50)],ac=[(graphFilterUpdateB,'top',5,graphFilterClearB)]) - + # Update keyable attribute list updateAttrList() - + # Show window mc.showWindow(win) @@ -48,18 +48,18 @@ def updateAttrList(): ''' # Clear attribute list mc.textScrollList('graphFilter_attrListTSL',e=True,ra=True) - + # Get current selection sel = mc.ls(sl=True) if not sel: return - + # List all keyable attributes attrList = list(set(mc.listAttr(sel,k=True))) attrList.sort() - + # Update textScrollList for attr in attrList: mc.textScrollList('graphFilter_attrListTSL',e=True,a=attr) - + # Return result return attrList @@ -94,15 +94,15 @@ def filterCurves(): ''' # Check attribute list selection if mc.textScrollList('graphFilter_attrListTSL',q=True,nsi=True): - + # Check mode if mc.radioButtonGrp('graphFilter_modeRBG',q=True,sl=True) == 1: mc.selectionConnection('graphEditor1FromOutliner',e=True,clear=True) attrs = mc.textScrollList('graphFilter_attrListTSL',q=True,si=True) for attr in attrs: addCurveToEditor(attr) - + # Update UI mm.eval('GraphEditor') - mm.eval('SelectAllMarkingMenu') + mm.eval('SelectAllMarkingMenu') mm.eval('buildSelectAllMM') mm.eval('SelectAllMarkingMenuPopDown') diff --git a/tools/groom.py b/tools/groom.py index 0ca0faa..d842c35 100644 --- a/tools/groom.py +++ b/tools/groom.py @@ -19,36 +19,36 @@ def buildRig(surface,uValue): # ========== # - Checks - # ========== - + if not glTools.utils.surface.isSurface(surface): raise Exception('Object "'+surface+'" is not a valid surface!') - + # Check Domain if uValue > mc.getAttr(surface+'.maxValueU'): raise Exception('U value "'+str(uValue)+'" is outside the parameter range!') if uValue < mc.getAttr(surface+'.minValueU'): raise Exception('U value "'+str(uValue)+'" is outside the parameter range!') - + # Check SkinCluster skinCluster = glTools.utils.skinCluster.findRelatedSkinCluster(surface) if skinCluster: raise Exception('Surface "'+skinCluster+'" is already attached to an existing skinCluster!') - + # Get Surface Info surfFn = glTools.utils.surface.getSurfaceFn(surface) cvs = surfFn.numCVsInU() - + # ================ # - Build Joints - # ================ - + # Extract IsoParm crv = mc.duplicateCurve(surface+'.u['+str(uValue)+']',ch=False)[0] - + # Get Curve Points pts = glTools.utils.base.getPointArray(crv) mc.delete(crv) - + # Create Joint Chain jnts = [] mc.select(cl=True) @@ -66,13 +66,13 @@ def buildRig(surface,uValue): uv = glTools.utils.surface.closestPoint(surface,pos=pts[i]) uTangent = mc.pointOnSurface(surface,u=uv[0],v=uv[1],ntu=True) glTools.utils.joint.orient(jnts[i],upVec=uTangent) - + # ====================== # - Create SkinCluster - # ====================== - + skinCluster = mc.skinCluster(surface,jnts,tsb=True)[0] - + # Clear Weights glTools.utils.skinCluster.clearWeights(surface) # Set Weights @@ -87,13 +87,13 @@ def buildRig(surface,uValue): wts.append(0.0) # Set Influence Weights glTools.utils.skinCluster.setInfluenceWeights(skinCluster,jnts[i],wts,normalize=False) - + # ================= # - Return Result - # ================= - + return jnts - + def removeRig(surface): ''' Remove groom surface scuplting rig. @@ -103,32 +103,32 @@ def removeRig(surface): # ========== # - Checks - # ========== - + # Check Surface if not glTools.utils.surface.isSurface(surface): raise Exception('Object "'+surface+'" is not a valid surface!') - + # Get SkinCluster skinCluster = glTools.utils.skinCluster.findRelatedSkinCluster(surface) if not glTools.utils.skinCluster.isSkinCluster(skinCluster): raise Exception('Surface "" is not connected to a skinCluster!') - - # Get Influence List + + # Get Influence List influenceList = mc.skinCluster(skinCluster,q=True,inf=True) - + # ============== # - Remove Rig - # ============== - + mc.delete(surface,ch=True) mc.delete(influenceList) - + # ================= # - Return Result - # ================= - + return skinCluster - + def buildRigFromSelection(): ''' Build basic groom surface scuplting rig based on the current selection. @@ -139,52 +139,52 @@ def buildRigFromSelection(): if not iso: iso = [] # Adjust Selection sel = list(set(sel)-set(iso)) - + # Build Surface Rigs for surface in sel: - + # Check Surface if glTools.utils.surface.isSurface(surface): - + minU = mc.getAttr(surface+'.minValueU') maxU = mc.getAttr(surface+'.maxValueU') midU = minU + ((maxU-minU)*0.5) buildRig(surface,uValue=midU) - + # Build Isoparm Rigs for crv in iso: - + surface = mc.ls(crv,o=True)[0] uValue = float(crv.split('[')[-1].split(']')[0]) buildRig(surface,uValue) - + def removeRigFromSelection(): ''' Remove the groom surface scuplting rig based on the current selection. ''' # Get Selection sel = mc.ls(sl=1) - + # Build Surface Rigs for obj in sel: - + # Check Surface if glTools.utils.surface.isSurface(obj): - + # Remove Rig removeRig(obj) - + # Check Joint if glTools.utils.joint.isJoint(obj): - + # Get Connected SkinCluster skinConn = mc.listConnections(obj,type='skinCluster') if not skinConn: continue skin = skinConn[0] - + # Get Connected Geometry surface = glTools.utils.deformer.getAffectedGeometry(skin).keys()[0] - + # Remove Rig removeRig(surface) @@ -194,18 +194,18 @@ def groom_checksum(groomNode): # Check Groom if not mc.objExists(groomNode): raise Exception('Groom node "'+groomNode+'" does not exist!!') - + # Get Groom Curves groom_crvs = mc.ls(mc.listRelatives(groomNode,ad=True) or [],type='nurbsCurve',ni=True) - + # Build CV Count String cvCounts = str([mc.getAttr(crv+'.controlPoints',s=True) for crv in groom_crvs]) - + # Generate Checksum m = hashlib.md5() m.update(cvCounts) hexVal = m.hexdigest() - + # Return Result return hexVal - + diff --git a/tools/ikHandle.py b/tools/ikHandle.py index 4d656ba..2dd00ef 100644 --- a/tools/ikHandle.py +++ b/tools/ikHandle.py @@ -35,34 +35,34 @@ def build( startJoint, # ========== # - Checks - # ========== - + # Check joints if not mc.objExists(startJoint): raise Exception('Joint '+startJoint+' does not exist!!') if not mc.objExists(endJoint): raise Exception('Joint '+endJoint+' does not exist!!') - + # Check solver type ikType = ['ikSplineSolver','ikSCsolver','ikRPsolver','ik2Bsolver'] if not ikType.count(solver): raise Exception('Invalid ikSlover type specified ("'+solver+ '")!!') - + # Check curve createCurve = False if solver == ikType[0]: # solver = ikSplineSolver if not mc.objExists(curve): createCurve = True - + # Extract name prefix from joint name if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(startJoint) - + mc.select(cl=True) - + # =================== # - Create ikHandle - # =================== - + ik = [] if solver == ikType[0]: - + # Spline IK solver ik = mc.ikHandle( sj=startJoint, ee=endJoint, @@ -72,7 +72,7 @@ def build( startJoint, pcv=False, priority=priority ) else: - + # Chain IK solver if sticky: ik = mc.ikHandle( sj=startJoint, @@ -85,21 +85,21 @@ def build( startJoint, ee=endJoint, sol=solver, priority=priority ) - + # Clear selection (to avoid printed warning message) mc.select(cl=True) - + # Rename ikHandle and endEffector ikHandle = str(mc.rename(ik[0],prefix+'_ikHandle')) ikEffector = str(mc.rename(ik[1],prefix+'_ikEffector')) - + # Set ikHandle offset value mc.setAttr(ikHandle+'.offset',ikSplineOffset) - + # ================= # - Return Result - # ================= - + return ikHandle def advancedTwistSetup( ikHandle, @@ -116,11 +116,11 @@ def advancedTwistSetup( ikHandle, twistMult=90 ): ''' Setup IK Spline Advnced Twist - @param ikHandle: IK spline handle to setup advanced twist for + @param ikHandle: IK spline handle to setup advanced twist for @type ikHandle: str @param worldUpType: World Up Type. 0=SceneUp, 1=ObjectUp, 2=ObjectUp(Start/End), 3=ObjectRotationUp, 4=ObjectRotationUp(Start/End), 5=Vector, 6=Vector(Start/End), 7=Relative. @type worldUpType: int - @param upAxis: Joint axis to aim towards the current upVector + @param upAxis: Joint axis to aim towards the current upVector @type upAxis: str @param upVectorBase: Spline IK base (start) upVector @type upVectorBase: str @@ -144,11 +144,11 @@ def advancedTwistSetup( ikHandle, # ========== # - Checks - # ========== - + # Ik Handle if not mc.objExists(ikHandle): raise Exception('IkHandle '+ikHandle+' does not exist!!') - + # World Up Objects if (worldUpType==1) or (worldUpType==2) or (worldUpType==3) or (worldUpType==4): if not upObjectBase: @@ -160,62 +160,62 @@ def advancedTwistSetup( ikHandle, raise Exception('No end worldUp object specified!') if not mc.objExists(upObjectBase): raise Exception('End worldUp object "'+upObjectTip+'" does not exist!') - + # Joint World Up Axis jntWorldUp = {'y':0,'-y':1,'*y':2,'z':3,'-z':4,'*z':5} if not jntWorldUp.has_key(upAxis): raise Exception('Invalid UpAxis value supplied ("'+upAxis+'")! Valid values are "y", "-y", "*y" (closest Y), "z", "-z" and "*z" (closest Z).') - + # World Up Axis worldUp = glTools.utils.lib.axis_dict() if not worldUp.has_key(upVectorBase): raise Exception('Invalid base (start) upVector value supplied ("'+upVectorBase+'")! Valid values are "x", "-x", "y", "-y", "z" and "-z".') if not worldUp.has_key(upVectorTip): raise Exception('Invalid tip (end) upVector value supplied ("'+upVectorTip+'")! Valid values are "x", "-x", "y", "-y", "z" and "-z".') - + # Twist Value Type twistTypeDict = {'total':0,'start/end':1,'ramp':2} if not twistTypeDict.has_key(twistType): raise Exception('Invalid twsit value type ("'+twistType+'")! Valid values are "total", "start/end" and "ramp".') - + # Twist Ramp if twistType=='ramp': if not twistRamp: raise Exception('No valid ramp provided for ramp twist type!') if not mc.objExists(twistRamp+'.outColor'): raise Exception('Ramp "'+twistRamp+'" has no ".outColor" attribute to drive the ikHandle ramp twist value!') - + # =========================== # - Setup Advanced IK Twist - # =========================== - + # Enable Advanced Twist mc.setAttr(ikHandle+'.dTwistControlEnable',1) - + # Set World Up Type mc.setAttr(ikHandle+'.dWorldUpType',worldUpType) - + # Set Joint World Up Axis mc.setAttr(ikHandle+'.dWorldUpAxis',jntWorldUp[upAxis]) - + # World Up Objects mc.connectAttr(upObjectBase+'.worldMatrix[0]',ikHandle+'.dWorldUpMatrix',f=True) mc.connectAttr(upObjectTip+'.worldMatrix[0]',ikHandle+'.dWorldUpMatrixEnd',f=True) - + # World Up Axis' mc.setAttr(ikHandle+'.dWorldUpVector',*worldUp[upVectorBase]) mc.setAttr(ikHandle+'.dWorldUpVectorEnd',*worldUp[upVectorTip]) - + # Twist Value Type mc.setAttr(ikHandle+'.dTwistValueType',twistTypeDict[twistType]) - + # Start/End Twist mc.setAttr(ikHandle+'.dTwistStart',twistStart) mc.setAttr(ikHandle+'.dTwistEnd',twistEnd) - + # Twist Ramp if twistType=='ramp': mc.connectAttr(twistRamp+'.outColor',ikHandle+'.dTwistRamp',f=True) - + # Twist Ramp Multiplier mc.setAttr(ikHandle+'.dTwistRampMult',twistMult) diff --git a/tools/import2dTrack.py b/tools/import2dTrack.py index 9b10543..4e25023 100644 --- a/tools/import2dTrack.py +++ b/tools/import2dTrack.py @@ -12,7 +12,7 @@ def import2dTrackUI(): window = 'import2dTrackUI' if mc.window(window,q=True,ex=True): mc.deleteUI(window) window = mc.window(window,title='Import 2D Track',wh=[500,350]) - + # Build UI Elements mc.columnLayout(adjustableColumn=True) perspCamListTSL = mc.textScrollList('importTrack_camListTSL',numberOfRows=8,ams=False) @@ -23,11 +23,11 @@ def import2dTrackUI(): mc.floatFieldGrp('importTrack_heightFFG',numberOfFields=1,label='Source Pixel Height',value1=1566) mc.button(label='Import Track',c='import glTools.tools.import2dTrack;reload(glTools.tools.import2dTrack);glTools.tools.import2dTrack.import2dTrack()') mc.button(label='Close',c='mc.deleteUI("'+window+'")') - + # Build Camera List camList = mc.listCameras(p=True) for cam in camList: mc.textScrollList(perspCamListTSL,e=True,a=cam) - + # Show Window mc.showWindow(window) @@ -40,40 +40,40 @@ def import2dTrack(): pixelWidthUI = 'importTrack_widthFFG' pixelHeightUI = 'importTrack_heightFFG' pointNameUI = 'importTrack_nameTFG' - + # Get UI Values w = mc.floatFieldGrp(pixelWidthUI,q=True,v1=True) h = mc.floatFieldGrp(pixelHeightUI,q=True,v1=True) cam = mc.textScrollList(perspCamListUI,q=True,si=True)[0] filePath = mc.textFieldButtonGrp(fileUI,q=True,text=True) pointName = mc.textFieldGrp(pointNameUI,q=True,text=True) - + # Ensure Camera Transform is Selected if mc.objectType(cam) == 'camera': cam = mc.listRelatives(cam,p=True)[0] - + # Check Track File Path if not os.path.isfile(filePath): raise Exception('Invalid file path "'+filePath+'"!') - + # Build Track Point Scene Elements point = mc.spaceLocator(n=pointName)[0] plane = mc.nurbsPlane(ax=(0,0,1),w=1,lr=1,d=1,u=1,v=1,ch=1,n=pointName+'Plane')[0] print plane - + # Position Track Plane plane = mc.parent(plane,cam)[0] mc.setAttr(plane+'.translate',0,0,-5) mc.setAttr(plane+'.rotate',0,0,0) for attr in ['.tx','.ty','.rx','.ry','.rz']: mc.setAttr(plane+attr,l=True) - + # Add FOV Attributes if not mc.objExists(cam+'.horizontalFOV'): mc.addAttr(cam,ln='horizontalFOV',at='double') if not mc.objExists(cam+'.verticalFOV'): mc.addAttr(cam,ln='verticalFOV',at='double') - + # Create FOV Expression expStr = '// Get Horizontal and Vertical FOV\r\n\r\n' expStr += 'float $focal ='+cam+'.focalLength;\r\n' @@ -96,11 +96,11 @@ def import2dTrack(): expStr += 'float $scale = ($hyp * $hyp) - ($dist * $dist);\r\n' expStr += plane+'.scaleY = (sqrt($scale)) * 2;' mc.expression(s=expStr,o=plane,n='planeFOV_exp',ae=1,uc='all') - + # Open Track Data File count = 0 f = open(filePath,'r') - + # Build Track Path Curve crvCmd = 'curveOnSurface -d 1 ' for line in f: @@ -110,13 +110,13 @@ def import2dTrack(): crvCmd += plane print crvCmd path = mm.eval(crvCmd) - + # Close Track Data File f.close() - + # Rebuild Curve mc.rebuildCurve(path,fitRebuild=False,keepEndPoints=True,keepRange=True,spans=0,degree=3) - + # Attach Track Point to Path motionPath = mc.pathAnimation(point,path,fractionMode=False,follow=False,startTimeU=1,endTimeU=count) exp = mc.listConnections(motionPath+'.uValue') diff --git a/tools/importFilesFromDir.py b/tools/importFilesFromDir.py index 8612613..c3f3c9e 100644 --- a/tools/importFilesFromDir.py +++ b/tools/importFilesFromDir.py @@ -11,54 +11,54 @@ def importFilesFromDir(path,ext='ma',reference=False,importWithNamespace=True): # ========== # - Checks - # ========== - + # Check Directory if not os.path.isdir(path): raise Exception('Invalid path!!') - + # Build File Extention Map extTypeMap = {} extTypeMap['fbx'] = 'FBX' extTypeMap['ma'] = 'mayaAscii' extTypeMap['mb'] = 'mayaBinary' extTypeMap['obj'] = 'OBJ' - + # Check Extension if not extTypeMap.has_key(ext): raise Exception('Unsupported file extention!') - + # ================= # - Get File List - # ================= - + fileList = os.listdir(path) fileList = [i for i in fileList if i.endswith(ext)] if not fileList: return [] fileList.sort() - + # ================ # - Import Files - # ================ - + for fileName in fileList: - + # Import File filePath = path+'/'+fileName namespace = os.path.splitext(fileName)[0] basename = os.path.splitext(fileName)[0] - + # Check File (isfile) if not os.path.isfile(filePath): continue - + if reference: # REFERENCE ======== - + try: mc.file(filePath,r=True,type=extTypeMap[ext],namespace=namespace,prompt=False,force=True) except: print('Error importing file! ('+filePath+')') continue - + else: # IMPORT ======== - + if importWithNamespace: try: mc.file(filePath,i=True,type=extTypeMap[ext],namespace=namespace,preserveReferences=True,prompt=False,force=True) @@ -71,11 +71,11 @@ def importFilesFromDir(path,ext='ma',reference=False,importWithNamespace=True): except: print('Error importing file! ('+filePath+')') continue - + # ================= # - Return Result - # ================= - + return fileList def importOBJsFromDir(path): @@ -84,42 +84,42 @@ def importOBJsFromDir(path): # ========== # - Checks - # ========== - + ext = 'obj' - + if not os.path.isdir(path): raise Exception('Invalid path!!') - + # ================= # - Get File List - # ================= - + fileList = os.listdir(path) if not fileList: return [] fileList.sort() - + # Get Current Scene List sceneList = mc.ls(assemblies=True) - + # ================ # - Import Files - # ================ - + for fileName in fileList: - + # Check File Extension fileExt = os.path.splitext(fileName)[-1].lower() if fileExt != ext: continue - + # Build Full Path filePath = path+'/'+fileName - + # Import try: mc.file(filePath,i=True,type='OBJ',prompt=False,force=True) except: print('Error importing file! ('+filePath+')') continue - + # Rename Object basename = os.path.splitext(fileName)[0].replace('.','_') newObjList = list(set(mc.ls(assemblies=True)) - set(sceneList)) @@ -134,12 +134,12 @@ def importOBJsFromDir(path): mc.rename(newObjList[0],basename) except: print('Unable to rename "'+newObjList[0]+'" to "'+basename+'"!') - + # Upate scene list sceneList = mc.ls(assemblies=True) # ================= # - Return Result - # ================= - + return fileList diff --git a/tools/importScene.py b/tools/importScene.py index 0933644..d763405 100644 --- a/tools/importScene.py +++ b/tools/importScene.py @@ -15,7 +15,7 @@ def safeImportScene(sceneFile=None): # =========================== # - Open Scene File Browser - # =========================== - + if sceneFile == None: startDir = mc.workspace(q=True,dir=True) sceneFile = mc.fileDialog2( fileFilter='Maya Files (*.ma *.mb)', @@ -24,19 +24,19 @@ def safeImportScene(sceneFile=None): caption='Import Scene File (SAFE)', okCaption='Import', startingDirectory=startDir )[0] - + # =============================== # - Import Scene (into safe NS) - # =============================== - + # Check Scene File Exists if not os.path.isfile(sceneFile): raise Exception('Invalid file path "'+sceneFile+'"! (File not found)') - + # Get File Type fileType = {'.ma':'mayaAscii','.mb':'mayaBinary'} fileName, fileExtension = os.path.splitext(sceneFile) - + # Determine Import Namespace importNS = 'safeImportNS' importNSinc = '' @@ -44,25 +44,25 @@ def safeImportScene(sceneFile=None): if not importNSinc: importNSinc = 0 importNSinc += 1 importNS = importNS+str(importNSinc) - + # Import Scene File importNodes = mc.file(sceneFile,i=True,type=fileType[fileExtension],namespace=importNS,preserveReferences=True,returnNewNodes=True) - + # ========================= # - Check Namespace Clash - # ========================= - + # Get Nested Namespace importNsList = mc.namespaceInfo(importNS,listOnlyNamespaces=True) or [] - + # Check Nested Namespaces mergeNsList = [] for nestedNS in importNsList: - + # Check Namespace Clash NS = nestedNS.split(':')[-1] if mc.namespace(ex=NS): - + # Build Safe Namespace safeNS = NS safeNSsuffix = safeNS.split('_')[-1] @@ -71,7 +71,7 @@ def safeImportScene(sceneFile=None): else: safeNS = safeNS.replace('_'+safeNSsuffix,'') while mc.namespace(ex=safeNS+'_%03d' % safeNSind): safeNSind += 1 safeNS = safeNS+'_%03d' % safeNSind - + # Rename Clashing Namespace print('Renaming clashing namespace "'+NS+'" to "'+safeNS+'"...') try: @@ -82,17 +82,17 @@ def safeImportScene(sceneFile=None): except Exception, e: raise Exception('Error renaming namespace "'+nestedNS+'"!') print('Rename namespace complete!') - + # Append Output List mergeNsList.append(safeNS) - + # Delete Import Namespace glTools.utils.namespace.deleteNS(importNS) - + # ================= # - Return Result - # ================= - + return mergeNsList def fixNamespaceClashes(): @@ -104,14 +104,14 @@ def fixNamespaceClashes(): NSlist = [ x for x in mc.namespaceInfo(listOnlyNamespaces=True,recurse=True) if not x in ['UI','shared'] ] NSshortList = [ x.split(':')[-1] for x in NSlist ] for i in range(len(NSlist)): - + # Check Multiple Instances of Current Namespace NS = NSshortList[i] parentNS = None if ':' in NSlist[i]: parentNS = NSlist[i].replace(NS,'') if NSshortList.count(NS) > 1: - + # Build Safe Namespace safeNS = NS safeNSsuffix = safeNS.split('_')[-1] @@ -120,14 +120,14 @@ def fixNamespaceClashes(): else: safeNS = safeNS.replace('_'+safeNSsuffix,'') while (safeNS+'_%03d' % safeNSind) in NSshortList: safeNSind += 1 safeNS = safeNS+'_%03d' % safeNSind - + # ============================= # - Rename Clashing Namespace - # ============================= - + # Attempting to move a namespace containing referenced nodes will result in an error # Use the 'file -e -namespace' command to change a reference namespace. - + print('Renaming clashing namespace "'+NS+'" to "'+safeNS+'"...') if parentNS: try: @@ -142,10 +142,10 @@ def fixNamespaceClashes(): print('Error renaming namespace "'+NSlist[i]+'"! '+str(e)) #raise Exception('Error renaming namespace "'+NSlist[i]+'"! '+str(e)) print('Rename namespace complete!') - + # Update NS List NSshortList[i] = safeNS NSlist[i] = NSlist[i].replace(NS,safeNS) - + # Return Result return NSshortList diff --git a/tools/interpolateGeometry.py b/tools/interpolateGeometry.py index 31e04bd..29f7fb9 100644 --- a/tools/interpolateGeometry.py +++ b/tools/interpolateGeometry.py @@ -7,7 +7,7 @@ def interpolateGeometry(geoList,numGeo,prefix='interpGeo'): ''' # Initialize outoput list dupGeoList = [] - + # Generate base Geo baseGeo = mc.duplicate(geoList[0],n=prefix+'_baseGeo')[0] baseTargetList = geoList[1:] @@ -16,19 +16,19 @@ def interpolateGeometry(geoList,numGeo,prefix='interpGeo'): baseBlendCount = len(baseBlendAlias) baseBlendWeight = 1.0/baseBlendCount for i in range(baseBlendCount): mc.setAttr(baseBlendShape+'.'+baseBlendAlias[i],baseBlendWeight) - + # Generate interpolated geometry for i in range(numGeo): - + # Duplicate Geo as blended intGeo = mc.duplicate(baseGeo,n=prefix+'#')[0] mc.parent(intGeo,w=True) - + # Blend to source geometry intBlendShape = mc.blendShape(geoList,intGeo)[0] intBlendAlias = mc.listAttr(intBlendShape+'.w',m=True) intBlendCount = len(intBlendAlias) - + # Generate blend weights wt = [] wtTotal = 0.0 @@ -37,16 +37,16 @@ def interpolateGeometry(geoList,numGeo,prefix='interpGeo'): wtTotal += wt[-1] for i in range(len(wt)): wt[i] /= wtTotal - + # Assign blend weights for i in range(intBlendCount): mc.setAttr(intBlendShape+'.'+intBlendAlias[i],wt[i]) - + # Append output list dupGeoList.append(intGeo) - + # Delete base Geo mc.delete(baseGeo) - + # Return result return dupGeoList diff --git a/tools/inverseDistanceWeights.py b/tools/inverseDistanceWeights.py index 37ed038..5b7f5b6 100644 --- a/tools/inverseDistanceWeights.py +++ b/tools/inverseDistanceWeights.py @@ -25,10 +25,10 @@ def buildPointWeights( points, # ========== # - Checks - # ========== - + # Build Influence Points influencePts = [glTools.utils.base.getPosition(i) for i in influenceList] - + # Add Missing Influences skinInfList = mc.skinCluster(skinCluster,q=True,inf=True) missingInfList = list(set(influenceList)-set(skinInfList)) or [] @@ -36,34 +36,34 @@ def buildPointWeights( points, mc.skinCluster(skinCluster,e=True,addInfluence=inf,lockWeights=True) for inf in missingInfList: mc.setAttr(inf+'.liw',0) - + # ======================= # - Build Point Weights - # ======================= - + #glTools.utils.progressBar.init('Beginning Weights', len(points)/10) cmd = '' ptWts = {} for i, pt in enumerate(points): - + ptPos = glTools.utils.base.getPosition(pt) wt, influenceID = calcPointWeights(ptPos,influencePts,maxInfluences) ptWts[pt] = [influenceID, wt] - + cmd += buildSkinPercentCmd(pt, influenceList, wt, skinCluster, ptWts) - + #if not i%10: glTools.utils.progressBar.update(1,'Generating Weights') - + # ================= # - Return Result - # ================= - + #glTools.utils.progressBar.end() - + # Run Cmd mm.eval(cmd) - + def calcPointWeights( pos, influencePts, maxInfluences, @@ -81,20 +81,20 @@ def calcPointWeights( pos, ''' # Get Point Position pt = glTools.utils.base.getPosition(pos) - + # Sort By Distance dist = [glTools.utils.mathUtils.distanceBetween(pt,i) for i in influencePts] distSorted = sorted(dist) closestID = [dist.index(distSorted[i]) for i in range(maxInfluences)] - + # Calculate Inverse Distance Weight ptArray = [influencePts[i] for i in closestID] wt = glTools.utils.mathUtils.inverseDistanceWeight3D(ptArray,pt) if smoothInterp: wt = [ glTools.utils.mathUtils.smoothStep(x) for x in wt ] infWt = [wt[closestID.index(i)] if i in closestID else 0.0 for i in range(len(influencePts))] - - + + # Return Result return infWt, closestID @@ -124,7 +124,7 @@ def buildSkinPercentCmd( pt, transValues += '-transformValue "%s" %s ' % (influenceList[n], ptWts[vertex][1][n]) cmd += 'skinPercent %s "%s" "%s";\n' % (transValues, skinCluster, vertex) x+=1 - + print "vertices :: %s " % len(ptWts) print "influences :: %s" % len(influenceList) print "generated %s skinPercent cmds" % x diff --git a/tools/joint.py b/tools/joint.py index d93f62e..d4da196 100644 --- a/tools/joint.py +++ b/tools/joint.py @@ -10,7 +10,7 @@ def buildChain(ptList,orient=None,secondaryAxisAim='yup'): # ========== # - Checks - # ========== - + if orient: orientList = ['xyz', 'yzx', 'zxy', 'zyx', 'yxz', 'xzy'] aimAxisList = ['xup', 'xdown', 'yup', 'ydown', 'zup', 'zdown'] @@ -18,38 +18,38 @@ def buildChain(ptList,orient=None,secondaryAxisAim='yup'): raise Exception('Invalid joint orient order ('+orient+')!') if not aimAxisList.count(secondaryAxisAim): raise Exception('Invalid secondary aim orient ('+secondaryAxisAim+')!') - + # ===================== # - Build Joint Chain - # ===================== - + # Clear Selection mc.select(cl=True) - + # Build Each Joint from Point List jointList = [] for pt in ptList: - + # Get Point Position pos = glTools.utils.base.getPosition(pt) - + # Create Joint joint = mc.joint(p=pos) - + # Check Orient if jointList and orient: - + # Orient Joint mc.joint(jointList[-1],oj=orient,sao=secondaryAxisAim) - + # Append Joint List jointList.append(joint) - + # Orient End Joint if jointList and orient: mc.setAttr(jointList[-1]+'.jo',0,0,0) - + # ================= # - Return Result - # ================= - + return jointList diff --git a/tools/jointPerVertex.py b/tools/jointPerVertex.py index 21f4989..d4c967f 100644 --- a/tools/jointPerVertex.py +++ b/tools/jointPerVertex.py @@ -11,28 +11,28 @@ def jointPerVertex(ptList,orientSurface='',prefix='',suffix='jnt'): # Generate position list from input point posList = [] for pt in ptList: posList.append(glTools.utils.base.getPosition(pt)) - + # Create joints jntList = [] for i in range(len(posList)): - + # Clear selection mc.select(cl=1) - + # Get string index strInd = glTools.utils.stringUtils.stringIndex(i+1,2) - + # Create joint jnt = mc.joint(n=prefix+'_'+strInd+'_'+suffix) # Position joint mc.move(posList[i][0],posList[i][1],posList[i][2],jnt,ws=True,a=True) - + # Orient joint if mc.objExists(orientSurface): mc.delete(mc.normalConstraint(orientSurface,jnt)) - + # Append return list jntList.append(jnt) - + # Return Result return jntList @@ -44,25 +44,25 @@ def jointPerVertexUI(): win = 'jntPerVtxUI' if mc.window(win,q=True,ex=1): mc.deleteUI(win) win = mc.window(win,t='Create Joint Per Vertex') - + # Layout cl = mc.columnLayout() - + # UI Elements prefixTFG = mc.textFieldGrp('jntPerVtx_prefixTFG',label='Prefix', text='') suffixTFG = mc.textFieldGrp('jntPerVtx_suffixTFG',label='Suffix', text='jnt') oriSurfaceTFB = mc.textFieldButtonGrp('jntPerVtx_oriSurfaceTFB',label='Orient Surface',text='',buttonLabel='Load Selected') - + # Buttons createB = mc.button('jntPerVtx_createB',l='Create',c='glTools.tools.jointPerVertex.jointPerVertexFromUI(False)') cancelB = mc.button('jntPerVtx_cancelB',l='Cancel',c='mc.deleteUI("'+win+'")') - + # UI callbacks mc.textFieldButtonGrp(oriSurfaceTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+oriSurfaceTFB+'","")') - + # Show Window mc.showWindow(win) - + def jointPerVertexFromUI(close=False): ''' Execute jointPerVertex() from UI @@ -70,15 +70,15 @@ def jointPerVertexFromUI(close=False): # Window win = 'jntPerVtxUI' if not mc.window(win,q=True,ex=1): raise UIError('jointPerVertex UI does not exist!!') - + # Get UI data pre = mc.textFieldGrp('jntPerVtx_prefixTFG',q=True,text=True) suf = mc.textFieldGrp('jntPerVtx_suffixTFG',q=True,text=True) oriSurface = mc.textFieldButtonGrp('jntPerVtx_oriSurfaceTFB',q=True,text=True) - + # Execute command ptList = mc.ls(sl=1,fl=True) jointPerVertex(ptList,orientSurface=oriSurface,prefix=pre,suffix=suf) - + # Cleanup if close: mc.deleteUI(win) diff --git a/tools/limbStretch.py b/tools/limbStretch.py index b1540b1..cf10195 100644 --- a/tools/limbStretch.py +++ b/tools/limbStretch.py @@ -20,143 +20,143 @@ def build(ikHandle,ikCtrl,pvCtrl,module,scaleAxis='x',prefix=''): # ========== # - Checks - # ========== - + if not mc.objExists(ikHandle): raise Exception('IK handle "'+ikHandle+'" does not exist!') if not mc.objExists(ikCtrl): raise Exception('IK control "'+ikCtrl+'" does not exist!') if not mc.objExists(module): raise Exception('Module "'+module+'" does not exist!') - + # ==================== # - Configure Module - # ==================== - + upperScaleAttr = 'upperLimbScale' lowerScaleAttr = 'lowerLimbScale' blendAttr = 'stretchToControl' biasAttr = 'stretchBias' - + # ============== # - Get Joints - # ============== - + ikJoints = glTools.utils.ik.getAffectedJoints(ikHandle) - + # ======================== # - Add Joint Attributes - # ======================== - + for ikJoint in ikJoints[:-1]: jntLen = glTools.utils.joint.length(ikJoint) mc.addAttr(ikJoint,ln='restLength',dv=jntLen) - + # ============================= # - Add IK Control Attributes - # ============================= - + # IK Control mc.addAttr(ikCtrl,ln=upperScaleAttr,min=0.01,dv=1.0,k=True) mc.addAttr(ikCtrl,ln=lowerScaleAttr,min=0.01,dv=1.0,k=True) mc.addAttr(ikCtrl,ln=blendAttr,min=0.0,max=1.0,dv=0.0,k=True) mc.addAttr(ikCtrl,ln=biasAttr,min=0.0,max=1.0,dv=0.5,k=True) - + # PV Control mc.addAttr(pvCtrl,ln=blendAttr,min=0.0,max=1.0,dv=0.0,k=True) - + # =============================== # - Create Limb Stretch Network - # =============================== - + # Limb Length - Character Scale limbCharScale = mc.createNode('multiplyDivide',n=prefix+'_characterScale_multiplyDivide') mc.setAttr(limbCharScale+'.operation',2) # Divide mc.connectAttr(module+'.uniformScale',limbCharScale+'.input2X',f=True) mc.connectAttr(module+'.uniformScale',limbCharScale+'.input2Y',f=True) mc.connectAttr(module+'.uniformScale',limbCharScale+'.input2Z',f=True) - + # Rest Length limbRestLenNode = mc.createNode('plusMinusAverage',n=prefix+'_limbRestLength_plusMinusAverage') for i in range(len(ikJoints[:-1])): mc.connectAttr(ikJoints[i]+'.restLength',limbRestLenNode+'.input1D['+str(i)+']',f=True) - + # Limb Length limbDistNode = mc.createNode('distanceBetween',n=prefix+'_limbLength_distanceBetween') mc.connectAttr(ikJoints[0]+'.parentMatrix[0]',limbDistNode+'.inMatrix1',f=True) mc.connectAttr(ikCtrl+'.worldMatrix[0]',limbDistNode+'.inMatrix2',f=True) mc.connectAttr(limbDistNode+'.distance',limbCharScale+'.input1X',f=True) - + # Limb Length Diff limbDiffNode = mc.createNode('plusMinusAverage',n=prefix+'_limbLengthDiff_plusMinusAverage') mc.setAttr(limbDiffNode+'.operation',2) # Subtract mc.connectAttr(limbCharScale+'.outputX',limbDiffNode+'.input1D[0]',f=True) mc.connectAttr(limbRestLenNode+'.output1D',limbDiffNode+'.input1D[1]',f=True) - + # Bias Reverse limbBiasRev = mc.createNode('reverse',n=prefix+'_limbBias_reverse') mc.connectAttr(ikCtrl+'.'+biasAttr,limbBiasRev+'.inputX',f=True) - + # Upper Stretch Diff upperStretchDiff = mc.createNode('multDoubleLinear',n=prefix+'_upperStretchDiff_multDoubleLinear') mc.connectAttr(limbDiffNode+'.output1D',upperStretchDiff+'.input1',f=True) mc.connectAttr(ikCtrl+'.'+biasAttr,upperStretchDiff+'.input2',f=True) - + # Lower Stretch Diff lowerStretchDiff = mc.createNode('multDoubleLinear',n=prefix+'_lowerStretchDiff_multDoubleLinear') mc.connectAttr(limbDiffNode+'.output1D',lowerStretchDiff+'.input1',f=True) mc.connectAttr(limbBiasRev+'.outputX',lowerStretchDiff+'.input2',f=True) - + # Upper Stretch Length upperStretchLen = mc.createNode('addDoubleLinear',n=prefix+'_upperStretchTarget_addDoubleLinear') mc.connectAttr(ikJoints[0]+'.restLength',upperStretchLen+'.input1',f=True) mc.connectAttr(upperStretchDiff+'.output',upperStretchLen+'.input2',f=True) - + # Lower Stretch Length lowerStretchLen = mc.createNode('addDoubleLinear',n=prefix+'_lowerStretchTarget_addDoubleLinear') mc.connectAttr(ikJoints[1]+'.restLength',lowerStretchLen+'.input1',f=True) mc.connectAttr(lowerStretchDiff+'.output',lowerStretchLen+'.input2',f=True) - + # Upper Stretch Scale upperStretchScale = mc.createNode('multiplyDivide',n=prefix+'_upperStretchScale_multiplyDivide') mc.setAttr(upperStretchScale+'.operation',2) # Divide mc.connectAttr(upperStretchLen+'.output',upperStretchScale+'.input1X',f=True) mc.connectAttr(ikJoints[0]+'.restLength',upperStretchScale+'.input2X',f=True) - + # Lower Stretch Scale lowerStretchScale = mc.createNode('multiplyDivide',n=prefix+'_lowerStretchScale_multiplyDivide') mc.setAttr(lowerStretchScale+'.operation',2) # Divide mc.connectAttr(lowerStretchLen+'.output',lowerStretchScale+'.input1X',f=True) mc.connectAttr(ikJoints[1]+'.restLength',lowerStretchScale+'.input2X',f=True) - + # ===================================== # - Create Stretch To Control Network - # ===================================== - + # Shoulder to PV distance upperPvDist = mc.createNode('distanceBetween',n=prefix+'_upperPV_distanceBetween') mc.connectAttr(ikJoints[0]+'.parentMatrix[0]',upperPvDist+'.inMatrix1',f=True) mc.connectAttr(pvCtrl+'.worldMatrix[0]',upperPvDist+'.inMatrix2',f=True) mc.connectAttr(upperPvDist+'.distance',limbCharScale+'.input1Y',f=True) - + # Wrist to PV distance lowerPvDist = mc.createNode('distanceBetween',n=prefix+'_lowerPV_distanceBetween') mc.connectAttr(ikCtrl+'.worldMatrix[0]',lowerPvDist+'.inMatrix1',f=True) mc.connectAttr(pvCtrl+'.worldMatrix[0]',lowerPvDist+'.inMatrix2',f=True) mc.connectAttr(lowerPvDist+'.distance',limbCharScale+'.input1Z',f=True) - + # Upper to PV scale upperPvScale = mc.createNode('multiplyDivide',n=prefix+'_upperPV_multiplyDivide') mc.setAttr(upperPvScale+'.operation',2) # Divide mc.connectAttr(limbCharScale+'.outputY',upperPvScale+'.input1X',f=True) mc.connectAttr(ikJoints[0]+'.restLength',upperPvScale+'.input2X',f=True) - + # Lower to PV scale lowerPvScale = mc.createNode('multiplyDivide',n=prefix+'_lowerPV_multiplyDivide') mc.setAttr(lowerPvScale+'.operation',2) # Divide mc.connectAttr(limbCharScale+'.outputZ',lowerPvScale+'.input1X',f=True) mc.connectAttr(ikJoints[1]+'.restLength',lowerPvScale+'.input2X',f=True) - + # ============================ # - Create Condition Network - # ============================ - + # Limb Stretch - Condition limbStretchCondition = mc.createNode('condition',n=prefix+'_limbStretch_condition') mc.setAttr(limbStretchCondition+'.operation',2) # Greater Than @@ -165,105 +165,105 @@ def build(ikHandle,ikCtrl,pvCtrl,module,scaleAxis='x',prefix=''): mc.setAttr(limbStretchCondition+'.colorIfFalse',1.0,1.0,1.0) mc.connectAttr(upperStretchScale+'.outputX',limbStretchCondition+'.colorIfTrueR',f=True) mc.connectAttr(lowerStretchScale+'.outputX',limbStretchCondition+'.colorIfTrueG',f=True) - + # Limb Stretch - Upper Blend upperLimbStretchBlend = mc.createNode('blendTwoAttr',n=prefix+'_upperLimbSTretch_blendTwoAttr') mc.connectAttr(ikCtrl+'.'+blendAttr,upperLimbStretchBlend+'.attributesBlender',f=True) mc.setAttr(upperLimbStretchBlend+'.input[0]',1.0) mc.connectAttr(limbStretchCondition+'.outColorR',upperLimbStretchBlend+'.input[1]',f=True) - + # Limb Stretch - Lower Blend lowerLimbStretchBlend = mc.createNode('blendTwoAttr',n=prefix+'_lowerLimbSTretch_blendTwoAttr') mc.connectAttr(ikCtrl+'.'+blendAttr,lowerLimbStretchBlend+'.attributesBlender',f=True) mc.setAttr(lowerLimbStretchBlend+'.input[0]',1.0) mc.connectAttr(limbStretchCondition+'.outColorG',lowerLimbStretchBlend+'.input[1]',f=True) - + # Limb Stretch - Upper Scale upperLimbStretchScale = mc.createNode('multDoubleLinear',n=prefix+'_upperStretchScale_multDoubleLinear') mc.connectAttr(upperLimbStretchBlend+'.output',upperLimbStretchScale+'.input1',f=True) mc.connectAttr(ikCtrl+'.upperLimbScale',upperLimbStretchScale+'.input2',f=True) - + # Limb Stretch - Lower Scale lowerLimbStretchScale = mc.createNode('multDoubleLinear',n=prefix+'_lowerStretchScale_multDoubleLinear') mc.connectAttr(lowerLimbStretchBlend+'.output',lowerLimbStretchScale+'.input1',f=True) mc.connectAttr(ikCtrl+'.lowerLimbScale',lowerLimbStretchScale+'.input2',f=True) - + # Stretch To Control - Upper Blend upStretchToCtrlBlend = mc.createNode('blendTwoAttr',n=prefix+'_upperStretchToControl_blendTwoAttr') mc.connectAttr(pvCtrl+'.'+blendAttr,upStretchToCtrlBlend+'.attributesBlender',f=True) mc.connectAttr(upperLimbStretchScale+'.output',upStretchToCtrlBlend+'.input[0]',f=True) mc.connectAttr(upperPvScale+'.outputX',upStretchToCtrlBlend+'.input[1]',f=True) - + # Stretch To Control - Lower Mult stretchToCtrlAllMult = mc.createNode('multDoubleLinear',n=prefix+'_stretchCombineWt_multDoubleLinear') mc.connectAttr(ikCtrl+'.'+blendAttr,stretchToCtrlAllMult+'.input1',f=True) mc.connectAttr(pvCtrl+'.'+blendAttr,stretchToCtrlAllMult+'.input2',f=True) - + # Stretch To Control - Lower Blend loStretchToCtrlBlend = mc.createNode('blendTwoAttr',n=prefix+'_lowerStretchToControl_blendTwoAttr') mc.connectAttr(stretchToCtrlAllMult+'.output',loStretchToCtrlBlend+'.attributesBlender',f=True) mc.connectAttr(lowerLimbStretchScale+'.output',loStretchToCtrlBlend+'.input[0]',f=True) mc.connectAttr(lowerPvScale+'.outputX',loStretchToCtrlBlend+'.input[1]',f=True) - + # ======================= # - End Effector Offset - # ======================= - + # Get End Effector endEffector = mc.listConnections(ikHandle+'.endEffector',s=True,d=False)[0] endEffectorCon = mc.listConnections(endEffector+'.tx',s=True,d=False)[0] - + # Disconnect End Effector mc.disconnectAttr(endEffectorCon+'.tx',endEffector+'.tx') mc.disconnectAttr(endEffectorCon+'.ty',endEffector+'.ty') mc.disconnectAttr(endEffectorCon+'.tz',endEffector+'.tz') - + # End Effector Offset endOffsetReverse = mc.createNode('reverse',n=prefix+'_limbEndOffset_reverse') mc.connectAttr(ikCtrl+'.'+blendAttr,endOffsetReverse+'.inputX',f=True) endOffsetMultiply = mc.createNode('multDoubleLinear',n=prefix+'limbEndOffset_multDoubleLinear') mc.connectAttr(pvCtrl+'.'+blendAttr,endOffsetMultiply+'.input1',f=True) mc.connectAttr(endOffsetReverse+'.outputX',endOffsetMultiply+'.input2',f=True) - + # End Effector Offset Length endEffectorScale = mc.createNode('multDoubleLinear',n=prefix+'_limbEndScale_multDoubleLinear') mc.connectAttr(ikJoints[1]+'.restLength',endEffectorScale+'.input1',f=True) mc.connectAttr(lowerPvScale+'.outputX',endEffectorScale+'.input2',f=True) - + # End Effector Offset Scale endEffectorScaleMD = mc.createNode('multiplyDivide',n=prefix+'_limbEndScale_multiplyDivide') mc.setAttr(endEffectorScaleMD+'.operation',2) # Divide mc.connectAttr(endEffectorScale+'.output',endEffectorScaleMD+'.input1X',f=True) mc.connectAttr(loStretchToCtrlBlend+'.output',endEffectorScaleMD+'.input2X',f=True) - + # End Effector Offset Blend endEffectorBlend = mc.createNode('blendTwoAttr',n=prefix+'_limbEndOffset_blendTwoAttr') mc.connectAttr(endOffsetMultiply+'.output',endEffectorBlend+'.attributesBlender',f=True) mc.connectAttr(ikJoints[1]+'.restLength',endEffectorBlend+'.input[0]',f=True) #mc.connectAttr(endEffectorScale+'.output',endEffectorBlend+'.input[1]',f=True) mc.connectAttr(endEffectorScaleMD+'.outputX',endEffectorBlend+'.input[1]',f=True) - + # ===================== # - Connect To Joints - # ===================== - + mc.connectAttr(upStretchToCtrlBlend+'.output',ikJoints[0]+'.s'+scaleAxis,f=True) mc.connectAttr(loStretchToCtrlBlend+'.output',ikJoints[1]+'.s'+scaleAxis,f=True) - + # =========================== # - Connect To End Effector - # =========================== - + # Check Negative Translate Values if mc.getAttr(endEffectorCon+'.t'+scaleAxis) < 0.0: - + # Negate Result endEffectorNegate = mc.createNode('unitConversion',n=prefix+'_endEffectorNegate_unitConversio') mc.connectAttr(endEffectorBlend+'.output',endEffectorNegate+'.input',f=True) mc.setAttr(endEffectorNegate+'.conversionFactor',-1) mc.connectAttr(endEffectorNegate+'.output',endEffector+'.t'+scaleAxis,f=True) - + else: - + # Direct Connection - mc.connectAttr(endEffectorBlend+'.output',endEffector+'.t'+scaleAxis,f=True) \ No newline at end of file + mc.connectAttr(endEffectorBlend+'.output',endEffector+'.t'+scaleAxis,f=True) diff --git a/tools/loadAgent.py b/tools/loadAgent.py index 7aec86a..4329a58 100644 --- a/tools/loadAgent.py +++ b/tools/loadAgent.py @@ -16,50 +16,50 @@ def loadAgentUI(): window = 'loadAgentUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Load Massive Agent') - + # Layout FL = mc.formLayout() - + # UI Elements callsheetTBG = mc.textFieldButtonGrp('loadAgent_callsheetTBG',label='Callsheet',buttonLabel='...',text='') agentTSL = mc.textScrollList('loadAgent_agentTBG',ams=True) agentInfoSF = mc.scrollField('loadAgent_agentInfoSF',editable=False,wordWrap=False,text='') - + #loadRigCBG = mc.checkBoxGrp('loadAgent_loadRigCBG',numberOfCheckBoxes=1,label='Load Agent Rig',v1=True) #bakeAnimCBG = mc.checkBoxGrp('loadAgent_bakeAnimCBG',numberOfCheckBoxes=1,label='Bake Agent Anim',v1=True) #saveSceneCBG = mc.checkBoxGrp('loadAgent_saveSceneCBG',numberOfCheckBoxes=1,label='Save Workfile',v1=False) - + loadB = mc.button('loadAgent_loadB',label='Load',c='glTools.tools.loadAgent.loadAgentFromUI()') closeB = mc.button('loadAgent_closeB',label='Close',c='mc.deleteUI("'+window+'")') - + # UI Callbacks mc.textFieldButtonGrp(callsheetTBG,e=True,bc='glTools.tools.loadAgent.importCallsheet()') mc.textFieldButtonGrp(callsheetTBG,e=True,cc='glTools.tools.loadAgent.loadCallsheetData()') mc.textScrollList(agentTSL,e=True,sc='glTools.tools.loadAgent.updateAgentInfo()') - + # Form Layout mc.formLayout(FL,e=True,af=[(callsheetTBG,'top',5),(callsheetTBG,'left',5),(callsheetTBG,'right',5)]) mc.formLayout(FL,e=True,ac=[(agentTSL,'top',5,callsheetTBG),(agentTSL,'bottom',5,loadB)],af=[(agentTSL,'left',5)],ap=[(agentTSL,'right',5,50)]) mc.formLayout(FL,e=True,ac=[(agentInfoSF,'top',5,callsheetTBG),(agentInfoSF,'bottom',5,loadB)],af=[(agentInfoSF,'right',5)],ap=[(agentInfoSF,'left',5,50)]) mc.formLayout(FL,e=True,ac=[(loadB,'bottom',5,closeB)],af=[(loadB,'left',5),(loadB,'right',5)]) mc.formLayout(FL,e=True,af=[(closeB,'left',5),(closeB,'right',5),(closeB,'bottom',5)]) - + # Show Window mc.showWindow(window) - + def importCallsheet(): ''' Import a callsheet to the load agent UI ''' # Define textField callsheetTBG = 'loadAgent_callsheetTBG' - + # Load Callsheet glTools.ui.utils.loadFilePath( textField=callsheetTBG, fileFilter='*.txt', caption='Load Callsheet', startDir=None) - + # Load Callsheet Data loadCallsheetData() @@ -69,29 +69,29 @@ def loadCallsheetData(): # Define textField callsheetTBG = 'loadAgent_callsheetTBG' agentTSL = 'loadAgent_agentTBG' - + # Get Callsheet File callsheetFile = mc.textFieldButtonGrp(callsheetTBG,q=True,text=True) if not os.path.isfile(callsheetFile): print('Invalid callsheet file path...') return - + # Get Callsheet Data callsheet = csh.Callsheet() try: callsheet.open(callsheetFile) except: print('Unable to load callsheet!') return - + # Get Agent List agents = callsheet.agents() if not agents: print('No agents found in callsheet data!') return - + # Clear List mc.textScrollList(agentTSL,e=True,ra=True) - + # List Agents for agent in agents: if 'reverse_agent' in agent: continue @@ -105,7 +105,7 @@ def agentVars(callsheetFile,agent): # Get Agent Data callsheet = csh.Callsheet() callsheet.open(callsheetFile) - + # Check Agent agents = callsheet.agents() agent_vars = callsheet.vars() @@ -113,7 +113,7 @@ def agentVars(callsheetFile,agent): raise Exception('Agent "'+agent+'" not found in callsheet ("'+callsheetFile+'")!') if not agent_vars.has_key(agent): raise Exception(' No agent data for "'+agent+'" in callsheet ("'+callsheetFile+'")!') - + # Return Result return agent_vars[agent] @@ -124,26 +124,26 @@ def updateAgentInfo(): agentInfoSF = 'loadAgent_agentInfoSF' # Clear Agent Info mc.scrollField(agentInfoSF,e=True,text='') - + # Get Callsheet File callsheetTBG = 'loadAgent_callsheetTBG' callsheetFile = mc.textFieldButtonGrp(callsheetTBG,q=True,text=True) - + # Get Selected Agents agentTSL = 'loadAgent_agentTBG' agentList = mc.textScrollList(agentTSL,q=True,si=True) - + # Build Agent Info String agentInfo = '' for agent in agentList: - + # Get Agent Variables agentVar = agentVars(callsheetFile,agent) - + agentInfo += '# == '+agent+' ==\n\n' if agentVar.has_key('costume_VAR'): agentInfo += 'Costume Typ: '+str(int(agentVar['costume_VAR']))+'\n' - if agentVar.has_key('costume_colour_VAR'): + if agentVar.has_key('costume_colour_VAR'): agentInfo += 'Costume Col: '+str(int(agentVar['costume_colour_VAR']))+'\n' if agentVar.has_key('hair_colour_VAR'): agentInfo += 'Groom/Hair Col: '+str(int(agentVar['hair_colour_VAR']))+'\n' @@ -156,7 +156,7 @@ def updateAgentInfo(): if agentVar.has_key('prop_R_VAR'): agentInfo += 'Left Hand Prop ID: '+str(int(agentVar['prop_R_VAR']))+'\n' agentInfo += '\n\n' - + # Update Agent Info mc.scrollField(agentInfoSF,e=True,text=agentInfo) @@ -165,7 +165,7 @@ def loadAgentFromUI(): ''' callsheetTBG = 'loadAgent_callsheetTBG' agentTSL = 'loadAgent_agentTBG' - + callsheetFile = mc.textFieldButtonGrp(callsheetTBG,q=True,text=True) agentList = mc.textScrollList(agentTSL,q=True,si=True) animStart = None @@ -175,13 +175,13 @@ def loadAgentFromUI(): saveScene = False exportScenegraph = False bpf = True - + if not os.path.isfile(callsheetFile): raise Exception('Callsheet file "'+callsheetFile+'" does not exist!') - + # Load Agents for agent in agentList: - + # Rebuild Agent agentNS = glTools.tools.crowd.mayaAgentSetupApf( agent, callsheetFile=callsheetFile, diff --git a/tools/lockSurfaceLength.py b/tools/lockSurfaceLength.py index 9ab9381..6831a55 100644 --- a/tools/lockSurfaceLength.py +++ b/tools/lockSurfaceLength.py @@ -9,11 +9,11 @@ def loadPlugin(): ''' # Check if plugin is loaded if not mc.pluginInfo('glCurveUtils',q=True,l=True): - + # Load Plugin try: mc.loadPlugin('glCurveUtils') except: raise Exception('Unable to load glCurveUtils plugin!') - + # Return Result return 1 @@ -22,18 +22,18 @@ def create(surface,spansU=0,spansV=0,prefix=None): ''' # Load Plugins loadPlugin() - + # ========== # - Checks - # ========== - + # Check Surface if not glTools.utils.surface.isSurface(surface): raise Exception('Object "'+surface+'" is not a valid nurbs surface!') - + # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(surface) - + # Get Surface Details if not spansU: spansU = mc.getAttr(surface+'.spansU') if not spansV: spansV = mc.getAttr(surface+'.spansV') @@ -43,20 +43,20 @@ def create(surface,spansU=0,spansV=0,prefix=None): maxV = mc.getAttr(surface+'.maxValueV') incU = (maxU-minU)/spansU incV = (maxV-minV)/spansV - + # ============= # - Rebuild U - # ============= - + crvU = [] for i in range(spansU+1): - + # Duplicate Surface Curve dupCurve = mc.duplicateCurve(surface+'.u['+str(incU*i)+']',ch=True,rn=False,local=False) dupCurveNode = mc.rename(dupCurve[1],prefix+'_spanU'+str(i)+'_duplicateCurve') dupCurve = mc.rename(dupCurve[0],prefix+'_spanU'+str(i)+'_crv') crvU.append(dupCurve) - + # Set Curve Length arcLen = mc.arclen(dupCurve) setLen = mc.createNode('setCurveLength',n=prefix+'_spanU'+str(i)+'_setCurveLength') @@ -69,42 +69,42 @@ def create(surface,spansU=0,spansV=0,prefix=None): mc.connectAttr(dupCurve+'.targetLength',blendLen+'.input[1]',f=True) mc.connectAttr(blendLen+'.output',setLen+'.length',f=True) mc.connectAttr(setLen+'.outputCurve',dupCurve+'.create',f=True) - + # Add Control Attributes mc.addAttr(dupCurve,ln='lockLength',min=0,max=1,dv=1,k=True) mc.addAttr(dupCurve,ln='lengthBias',min=0,max=1,dv=0,k=True) mc.connectAttr(dupCurve+'.lockLength',blendLen+'.attributesBlender',f=True) mc.connectAttr(dupCurve+'.lengthBias',setLen+'.bias',f=True) - + # Loft New Surface srfU = mc.loft(crvU,ch=True,uniform=True,close=False,autoReverse=False,degree=3) srfUloft = mc.rename(srfU[1],prefix+'_rebuildU_loft') srfU = mc.rename(srfU[0],prefix+'_rebuildU_srf') - + # Rebuild 0-1 rebuildSrf = mc.rebuildSurface(srfU,ch=True,rpo=True,rt=0,end=1,kr=0,kcp=1,su=0,du=3,sv=0,dv=3,tol=0) rebuildSrfNode = mc.rename(rebuildSrf[1],prefix+'_rebuildU_rebuildSurface') - + # Add Control Attributes mc.addAttr(srfU,ln='lockLength',min=0,max=1,dv=1,k=True) mc.addAttr(srfU,ln='lengthBias',min=0,max=1,dv=0,k=True) for crv in crvU: mc.connectAttr(srfU+'.lockLength',crv+'.lockLength',f=True) mc.connectAttr(srfU+'.lengthBias',crv+'.lengthBias',f=True) - + # ============= # - Rebuild V - # ============= - + crvV = [] for i in range(spansV+1): - + # Duplicate Surface Curve dupCurve = mc.duplicateCurve(srfU+'.v['+str(incV*i)+']',ch=True,rn=False,local=False) dupCurveNode = mc.rename(dupCurve[1],prefix+'_spanV'+str(i)+'_duplicateCurve') dupCurve = mc.rename(dupCurve[0],prefix+'_spanV'+str(i)+'_crv') crvV.append(dupCurve) - + # Set Curve Length arcLen = mc.arclen(dupCurve) setLen = mc.createNode('setCurveLength',n=prefix+'_spanV'+str(i)+'_setCurveLength') @@ -117,47 +117,47 @@ def create(surface,spansU=0,spansV=0,prefix=None): mc.connectAttr(dupCurve+'.targetLength',blendLen+'.input[1]',f=True) mc.connectAttr(blendLen+'.output',setLen+'.length',f=True) mc.connectAttr(setLen+'.outputCurve',dupCurve+'.create',f=True) - + # Add Control Attribute mc.addAttr(dupCurve,ln='lockLength',min=0,max=1,dv=1,k=True) mc.addAttr(dupCurve,ln='lengthBias',min=0,max=1,dv=0,k=True) mc.connectAttr(dupCurve+'.lockLength',blendLen+'.attributesBlender',f=True) mc.connectAttr(dupCurve+'.lengthBias',setLen+'.bias',f=True) - + # Loft New Surface srfV = mc.loft(crvV,ch=True,uniform=True,close=False,autoReverse=False,degree=3) srfVloft = mc.rename(srfV[1],prefix+'_rebuildV_loft') srfV = mc.rename(srfV[0],prefix+'_rebuildV_srf') - + # Rebuild 0-1 rebuildSrf = mc.rebuildSurface(srfV,ch=True,rpo=True,rt=0,end=1,kr=0,kcp=1,su=0,du=3,sv=0,dv=3,tol=0) rebuildSrfNode = mc.rename(rebuildSrf[1],prefix+'_rebuildV_rebuildSurface') - + # Add Control Attribute mc.addAttr(srfV,ln='lockLength',min=0,max=1,dv=1,k=True) mc.addAttr(srfV,ln='lengthBias',min=0,max=1,dv=0,k=True) for crv in crvV: mc.connectAttr(srfV+'.lockLength',crv+'.lockLength',f=True) mc.connectAttr(srfV+'.lengthBias',crv+'.lengthBias',f=True) - + # =================== # - Build Hierarchy - # =================== - + rebuildUGrp = mc.group(em=True,n=prefix+'_rebuildU_grp') mc.parent(crvU,rebuildUGrp) mc.parent(srfU,rebuildUGrp) - + rebuildVGrp = mc.group(em=True,n=prefix+'_rebuildV_grp') mc.parent(crvV,rebuildVGrp) mc.parent(srfV,rebuildVGrp) - + rebuildGrp = mc.group(em=True,n=prefix+'_lockLength_grp') mc.parent(rebuildUGrp,rebuildGrp) mc.parent(rebuildVGrp,rebuildGrp) - + # ================= # - Return Result - # ================= - + return rebuildGrp diff --git a/tools/lookAt.py b/tools/lookAt.py index 75c9e0b..7a97322 100644 --- a/tools/lookAt.py +++ b/tools/lookAt.py @@ -35,15 +35,15 @@ def create( target, # ========== # - Checks - # ========== - + # Target if not glTools.utils.transform.isTransform(target): raise Exception('LookAt target "'+target+'" is not a valid transform! Unable to create lookAt setup...') - + # Slave List if not slaveList: raise Exception('Invalid lookAt slave list! Unable to create lookAt setup...') - + # Weight List if not weightList: print('Invalid lookAt weight list! Generating default lookAt weight list...') @@ -51,7 +51,7 @@ def create( target, if len(weightList) != len(slaveList): print('Invalid lookAt weight list! Generating default lookAt weight list...') weightList = range(0,101,100.0/len(slaveList))[1:] - + # Slave Aim/Up Vectors if not slaveAimUp: print('Invalid lookAt slave aim/up vector values! Using default lookAt vectors (aim="z",up="y")...') @@ -59,39 +59,39 @@ def create( target, if len(slaveAimUp) != len(slaveList): print('Invalid lookAt slave aim/up vector values! Using default lookAt vectors (aim="z",up="y")...') slaveAimUp = [('z','y') for slave in slaveList] - + # =========== # - Look At - # =========== - + slaveReferenceList = [] slaveLookAtList = [] slaveLookAt_aimList = [] slaveLookAt_orientList = [] - + slaveBakeList = [] - + for i in range(len(slaveList)): - + # Check Slave Object if not mc.objExists(slaveList[i]): print('Slave object "'+slaveList[i]+'" not found! Skipping...') continue - + # Get Slave Short Name slaveSN = slaveList[i].split(':')[0] - + # Duplicate Slave to get Reference and LookAt Targets slaveReference = mc.duplicate(slaveList[i],po=True,n=slaveSN+'_reference')[0] slaveLookAt = mc.duplicate(slaveList[i],po=True,n=slaveSN+'_lookAt')[0] - + # Transfer Anim to Reference slaveKeys = mc.copyKey(slaveList[i]) if slaveKeys: mc.pasteKey(slaveReference) - + # Delete Slave Rotation Anim mc.cutKey(slaveList[i],at=['rx','ry','rz']) - + # Create Slave LookAt slaveLookAt_aim = glTools.tools.constraint.aimConstraint( target=target, slave=slaveLookAt, @@ -100,48 +100,48 @@ def create( target, worldUpType='scene', offset=offset, mo=False )[0] - + # Weighted Orient Constraint slaveLookAt_orient = mc.orientConstraint([slaveReference,slaveLookAt],slaveList[i],mo=False)[0] slaveLookAt_targets = glTools.utils.constraint.targetAliasList(slaveLookAt_orient) - + # Set Constraint Target Weights mc.setAttr(slaveLookAt_orient+'.'+slaveLookAt_targets[0],1.0-(weightList[i]*0.01)) mc.setAttr(slaveLookAt_orient+'.'+slaveLookAt_targets[1],weightList[i]*0.01) mc.setAttr(slaveLookAt_orient+'.interpType',2) # Shortest - + # Add Message Connections mc.addAttr(slaveList[i],ln='lookAtTarget',at='message') mc.addAttr(slaveList[i],ln='lookAtAnmSrc',at='message') mc.connectAttr(slaveLookAt+'.message',slaveList[i]+'.lookAtTarget',f=True) mc.connectAttr(slaveReference+'.message',slaveList[i]+'.lookAtAnmSrc',f=True) - + # Append Lists slaveReferenceList.append(slaveReference) slaveLookAtList.append(slaveLookAt) slaveLookAt_aimList.append(slaveLookAt_aim) slaveLookAt_orientList.append(slaveLookAt_orient) - + slaveBakeList.append(slaveList[i]) - + # ============= # - Bake Anim - # ============= - + if bakeAnim: - + # Get Bake Range start = bakeStartEnd[0] end = bakeStartEnd[1] if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) - + # Bake Results mc.refresh(suspend=True) #for slave in slaveBakeList: mc.bakeResults(slaveBakeList,t=(start,end),at=['rx','ry','rz'],simulation=True) mc.refresh(suspend=False) - + # Post Bake Cleanup if cleanup: try: mc.delete(slaveLookAt_orientList) @@ -152,29 +152,29 @@ def create( target, except: pass try: mc.delete(slaveLookAtList) except: pass - + # ==================== # - Bake Anim Offset - # ==================== - + if offsetAnim != None: - + # For Each Slave Object for slave in slaveList: - + # Check Slave Object if not mc.objExists(slave): print('Slave object "'+slave+'" not found! Skipping...') continue - + # Offset Rotate Channels for r in ['rx','ry','rz']: mc.keyframe(slave+'.'+r,e=True,relative=True,timeChange=offsetAnim) - + # ================= # - Return Result - # ================= - + return slaveList def isApplied(slaveList): diff --git a/tools/match.py b/tools/match.py index 20ffab6..f9abd9d 100644 --- a/tools/match.py +++ b/tools/match.py @@ -21,24 +21,24 @@ def matchAttrs(src,dst,attrList=None): # ========== # - Checks - # ========== - + if not mc.objExists(src): raise Exception('Source object "'+src+'" does not exist!') if not mc.objExists(dst): raise Exception('Destination object "'+dst+'" does not exist!') if not attrList: raise Exception('Invalid or empty attribute list!') - + # Check ChannelBox Selection if attrList == "fromChannelBox": attrList = Match().getCBattrList() - + # ========================== # - Match Attribute Values - # ========================== - + for attr in attrList: - + if not mc.attributeQuery(attr,n=src,ex=True): print('Source attribute "'+src+'.'+attr+'" not found! Skipping...') continue @@ -48,22 +48,22 @@ def matchAttrs(src,dst,attrList=None): if not mc.getAttr(dst+'.'+attr,se=True): print('Destination attribute "'+dst+'.'+attr+'" is not settable! Skipping...') continue - + # Set Destination Value val = mc.getAttr(src+'.'+attr) try: mc.setAttr(dst+'.'+attr,val) except Exception, e: print('Error setting destination attribute "'+dst+'.'+attr+'"! Exception Msg: '+str(e)) - + # ================= # - Return Result - # ================= - + return class Match( object ): - + def __init__(self): - + # Attribute names self.parentAttr = 'poseMirror' self.twinAttr = 'twin' @@ -75,34 +75,34 @@ def __init__(self): self.modeAttr = 'matchMode' self.evalOrderAttr = 'all.evalOrder' self.xform = ['tx','ty','tz','rx','ry','rz','sx','sy','sz'] - + # Axis vectors self.xAxis = (1,0,0) self.yAxis = (0,1,0) self.zAxis = (0,0,1) - + # Axis' self.axisIndex = {'x':0,'y':1,'z':2,'-x':3,'-y':4,'-z':5} # Rotate Order self.rotateOrder = {'xyz':0,'yzx':1,'zxy':2,'xzy':3,'yxz':4,'zyx':5} - + # Side self.leftPrefix = 'lf' self.rightPrefix = 'rt' - + # Mode self.mode = {'world':0,'local':1,'match':2} - + # Constants self.radian = 180.0/math.pi - + # Maya Window Elements self.channelBox = 'mainChannelBox' - + # ========= # - SETUP - # ========= - + def setSelfPivotAttrs(self,pivotList,axis='x',mode=0): ''' Setup self pivot pose matching attributes for the specified controls @@ -115,13 +115,13 @@ def setSelfPivotAttrs(self,pivotList,axis='x',mode=0): ''' # Iterate over pivot list for pivot in pivotList: - + # Check pivot if not mc.objExists(pivot): raise Exception('Pivot object '+pivot+' does not exist!!') else: self.setMatchAttrs(pivot,pivot,pivot,axis,mode) - + def twinMatchAttrSetup(self,ctrlList,twinList,pivot,axis,mode='world'): ''' Set twin match attributes for the specified controls and associated twin controls. @@ -139,20 +139,20 @@ def twinMatchAttrSetup(self,ctrlList,twinList,pivot,axis,mode='world'): # ========== # - Checks - # ========== - + if not ctrlList: raise Exception('Invalid or empty control list!') if not twinList: raise Exception('Invalid or empty twin list!') if len(ctrlList) != len(twinList): raise Exception('Control and twin list length mis-match!') - + # =================== # - Set Match Attrs - # =================== - + for i in range(len(ctrlList)): self.setMatchAttrs(ctrlList[i],twinList[i],pivot,axis,self.mode[mode]) self.setMatchAttrs(twinList[i],ctrlList[i],pivot,axis,self.mode[mode]) - + def setTwinMatchAttrs(self,masterList,pivot,axis='x',mode=0,search='lf_',replace='rt_'): ''' Setup twin pose matching attributes for the specified controls @@ -168,11 +168,11 @@ def setTwinMatchAttrs(self,masterList,pivot,axis='x',mode=0,search='lf_',replace # ========== # - Checks - # ========== - + if not mc.objExists(pivot): raise Exception('Pivot object '+pivot+' does not exist!!') - - + + for master in masterList: if not mc.objExists(master): raise Exception('Control object '+master+' does not exist!!') twin = master @@ -182,7 +182,7 @@ def setTwinMatchAttrs(self,masterList,pivot,axis='x',mode=0,search='lf_',replace twin = master.replace(replace,search) self.setMatchAttrs(master,twin,pivot,axis,mode) self.setMatchAttrs(twin,master,pivot,axis,mode) - + def setModeAttr(self,controlList,mode): ''' Set pose match mode attribute for the specified controls @@ -194,7 +194,7 @@ def setModeAttr(self,controlList,mode): for control in controlList: if mc.objExists(control+'.matchMode'): mc.setAttr(control+'.matchMode',mode) else: print('Control object '+control+' does not have a "matchMode" attribute! Run Match.setMatchAttrs()!!') - + def setMatchAttrs(self,master,twin,pivot,axis,mode=0,twinX='',twinY='',twinZ=''): ''' Set match attribute values. @@ -219,25 +219,25 @@ def setMatchAttrs(self,master,twin,pivot,axis,mode=0,twinX='',twinY='',twinZ='') # ========== # - Checks - # ========== - + # Initialize master = str(master) twin = str(twin) pivot = str(pivot) - + # Check inputs if not mc.objExists(master): raise Exception('Master object '+master+' does not exist') if not mc.objExists(twin): raise Exception('Twin object '+twin+' does not exist') if not mc.objExists(pivot): raise Exception('Pivot object '+pivot+' does not exist') - + # Delete Compound Attr if mc.objExists(master+'.'+self.parentAttr): mc.deleteAttr(master+'.'+self.parentAttr) - + # ================== # - Add Attributes - # ================== - + # Parent Attribute mc.addAttr(master,ln=self.parentAttr,numberOfChildren=7,at='compound') # Twin @@ -248,35 +248,35 @@ def setMatchAttrs(self,master,twin,pivot,axis,mode=0,twinX='',twinY='',twinZ='') mc.addAttr(master,ln=self.axisAttr,at='enum',en="X:Y:Z",p=self.parentAttr) # Mode mc.addAttr(master,ln=self.modeAttr,at='enum',en="World:Local:Match",p=self.parentAttr) - + # - Twin XYZ - - + # X Axis mc.addAttr(master,ln=self.twinXAttr,at='enum',en="X:Y:Z:-X:-Y:-Z",p=self.parentAttr) # Y Axis mc.addAttr(master,ln=self.twinYAttr,at='enum',en="X:Y:Z:-X:-Y:-Z",p=self.parentAttr) # Z Axis mc.addAttr(master,ln=self.twinZAttr,at='enum',en="X:Y:Z:-X:-Y:-Z",p=self.parentAttr) - + # ================== # - Set Attributes - # ================== - + mc.setAttr(master+'.'+self.parentAttr+'.'+self.twinAttr,twin,type='string') mc.setAttr(master+'.'+self.parentAttr+'.'+self.pivotAttr,pivot,type='string') mc.setAttr(master+'.'+self.parentAttr+'.'+self.axisAttr,self.axisIndex[axis]) mc.setAttr(master+'.'+self.parentAttr+'.'+self.modeAttr,mode) - + # - Twin XYZ - twinAttrVal = self.getTwinMirrorAxis(master,twin,pivot,axis) - + if twinX: mc.setAttr(master+'.'+self.parentAttr+'.'+self.twinXAttr,self.axisIndex[twinX]) else: mc.setAttr(master+'.'+self.parentAttr+'.'+self.twinXAttr,twinAttrVal[0]) if twinY: mc.setAttr(master+'.'+self.parentAttr+'.'+self.twinYAttr,self.axisIndex[twinY]) else: mc.setAttr(master+'.'+self.parentAttr+'.'+self.twinYAttr,twinAttrVal[1]) if twinZ: mc.setAttr(master+'.'+self.parentAttr+'.'+self.twinZAttr,self.axisIndex[twinZ]) else: mc.setAttr(master+'.'+self.parentAttr+'.'+self.twinZAttr,twinAttrVal[2]) - + def getTwinMirrorAxis(self,master,twin,pivot,axis): ''' Returns the mirrired twin axis' (XYZ) for a specified slave control, based on a master, pivot and mirror axis @@ -293,10 +293,10 @@ def getTwinMirrorAxis(self,master,twin,pivot,axis): if not mc.objExists(master): raise Exception('Master object '+master+' does not exist') if not mc.objExists(twin): raise Exception('Twin object '+twin+' does not exist') if not mc.objExists(pivot): raise Exception('Pivot object '+pivot+' does not exist') - + # Initialize mirror axis twinMirrorAxis = [0,1,2] - + # X Axis # ------- xAxis = self.vectorTwinSpaceMirror(self.xAxis,master,twin,pivot,axis) @@ -306,7 +306,7 @@ def getTwinMirrorAxis(self,master,twin,pivot,axis): if abs(xAxis[self.axisIndex[axisMirror]]) < abs(xAxis[2]): axisMirror = 'z' if xAxis[self.axisIndex[axisMirror]] < 0: axisMirror = '-'+axisMirror twinMirrorAxis[0] = self.axisIndex[axisMirror] - + # Y Axis # ------- yAxis = self.vectorTwinSpaceMirror(self.yAxis,master,twin,pivot,axis) @@ -316,7 +316,7 @@ def getTwinMirrorAxis(self,master,twin,pivot,axis): if abs(yAxis[self.axisIndex[axisMirror]]) < abs(yAxis[2]): axisMirror = 'z' if yAxis[self.axisIndex[axisMirror]] < 0: axisMirror = '-'+axisMirror twinMirrorAxis[1] = self.axisIndex[axisMirror] - + # Z Axis # ------- zAxis = self.vectorTwinSpaceMirror(self.zAxis,master,twin,pivot,axis) @@ -326,13 +326,13 @@ def getTwinMirrorAxis(self,master,twin,pivot,axis): if abs(zAxis[self.axisIndex[axisMirror]]) < abs(zAxis[2]): axisMirror = 'z' if zAxis[self.axisIndex[axisMirror]] < 0: axisMirror = '-'+axisMirror twinMirrorAxis[2] = self.axisIndex[axisMirror] - + return twinMirrorAxis - + # =========== # - EXECUTE - # =========== - + def twinTransform( self, master, slave = None, @@ -358,11 +358,11 @@ def twinTransform( self, # ========== # - Checks - # ========== - + # Check Master if not mc.objExists(master): raise Exception('Object "'+master+'" does not exist!') - + # Check Twin if not slave: if mc.attributeQuery(self.twinAttr,n=master,ex=True): @@ -370,7 +370,7 @@ def twinTransform( self, else: print('Object "'+master+'" has no "'+self.twinAttr+'" attribute! Unable to twin transform...') return - + # Check Pivot if not pivot: if mc.attributeQuery(self.pivotAttr,n=master,ex=True): @@ -378,7 +378,7 @@ def twinTransform( self, else: print('Object "'+master+'" has no "'+self.pivotAttr+'" attribute! Unable to twin transform...') return - + # Check Mirror Axis if not mirrorAxis: if mc.attributeQuery(self.axisAttr,n=master,ex=True): @@ -388,7 +388,7 @@ def twinTransform( self, return if isinstance(mirrorAxis,str): mirrorAxis = self.axisIndex[mirrorAxis] - + # Check Mirror Mode if not mirrorMode: if mc.attributeQuery(self.modeAttr,n=master,ex=True): @@ -396,11 +396,11 @@ def twinTransform( self, else: print('Object "'+master+'" has no "'+self.modeAttr+'" attribute! Unable to twin transform...') return - + # ====================== # - Get Transform Info - # ====================== - + # Check Parent Transforms masterParent = None try: masterParent = str(mc.listRelatives(master,p=1)[0]) @@ -411,28 +411,28 @@ def twinTransform( self, pivotParent = None try: pivotParent = str(mc.listRelatives(pivot,p=1)[0]) except: pass - + # Get Match Values twinX = mc.getAttr(slave+'.'+self.twinXAttr) twinY = mc.getAttr(slave+'.'+self.twinYAttr) twinZ = mc.getAttr(slave+'.'+self.twinZAttr) slaveRotateOrder = mc.getAttr(slave+'.ro') masterRotateOrder = mc.getAttr(master+'.ro') - + # Get Mater Transform channel values pos = list(mc.getAttr(master+'.translate')[0]) rot = list(mc.getAttr(master+'.rotate')[0]) scl = list(mc.getAttr(master+'.scale')[0]) - + # =================== # - Match Transform - # =================== - + if mirrorMode == 0: # WORLD Match - + # Translate #=============== if xformList[0] or xformList[1] or xformList[2]: - + # Check Self Pivot if master == pivot: pos[mirrorAxis] *= -1 else: @@ -444,13 +444,13 @@ def twinTransform( self, pos = self.transformVector(pos,pivot,transformAsPoint=True,invertTransform=False) # Transform to slave local if slaveParent: pos = self.transformVector(pos,slaveParent,transformAsPoint=True,invertTransform=True) - + # Rotate #=============== if xformList[3] or xformList[4] or xformList[5] or xformList[6] or xformList[7] or xformList[8]: - + # Check self pivot if master == pivot: pivot = str(pivotParent) - + # Build basis vectors twinAxis = [] twinAxis.append(self.vectorTwinSpaceMirror(self.xAxis,master,slave,pivot,mirrorAxis)) @@ -462,7 +462,7 @@ def twinTransform( self, xAxis = twinAxis[twinX] yAxis = twinAxis[twinY] zAxis = twinAxis[twinZ] - + # Create rotation matrix from basis vectors matrix = OpenMaya.MMatrix() OpenMaya.MScriptUtil.setDoubleArray(matrix[0], 0, xAxis[0]) @@ -478,66 +478,66 @@ def twinTransform( self, eulerRotation = xformMatrix.eulerRotation() eulerRotation = eulerRotation.reorder(slaveRotateOrder) rot = (eulerRotation.x*self.radian,eulerRotation.y*self.radian,eulerRotation.z*self.radian) - + # Scale #=============== if xformList[6] or xformList[7] or xformList[8]: - + # Extract scale values from basis vector lengths scl[0] = OpenMaya.MVector(xAxis[0],xAxis[1],xAxis[2]).length() scl[1] = OpenMaya.MVector(yAxis[0],yAxis[1],yAxis[2]).length() scl[2] = OpenMaya.MVector(zAxis[0],zAxis[1],zAxis[2]).length() - + elif mirrorMode == 1: # LOCAL Match - + # Translate #=============== translate = [pos[0],pos[1],pos[2],-pos[0],-pos[1],-pos[2]] pos[0] = translate[twinX] pos[1] = translate[twinY] pos[2] = translate[twinZ] - + # Rotate #=============== - + # Convert Degrees to Radians rot = [(rot[i]/self.radian) for i in range(3)] - + # Reorder to XYZ eulerRotation = OpenMaya.MEulerRotation(rot[0],rot[1],rot[2],masterRotateOrder) eulerRotation.reorderIt(0) rot = [eulerRotation.x,eulerRotation.y,eulerRotation.z] - + # Determine Twin Equivalent rotate = [-rot[0],-rot[1],-rot[2],rot[0],rot[1],rot[2]] rot = [rotate[twinX],rotate[twinY],rotate[twinZ]] - + # Adjust for mis-matched twin axis relationships rotateOrderStr = 'xyz'[twinX%3] + 'xyz'[twinY%3] + 'xyz'[twinZ%3] eulerRotation = OpenMaya.MEulerRotation(rot[0],rot[1],rot[2],self.rotateOrder[rotateOrderStr]) eulerRotation = eulerRotation.reorder(slaveRotateOrder) rot = [eulerRotation.x,eulerRotation.y,eulerRotation.z] - + # Convert Radians to Degrees rot = [(rot[i]*self.radian) for i in range(3)] - + # Scale #=============== scale = [scl[0],scl[1],scl[2]] scl[0] = scale[(twinX%3)] scl[1] = scale[(twinY%3)] scl[2] = scale[(twinZ%3)] - + elif mirrorMode == 2: # EXPICIT Match - + pass - + else: # INVALID Match Mode - + raise Exception('Invalid match mode! ('+str(mirrorMode)+')') - + # ================= # - Return Result - # ================= - + return [pos[0],pos[1],pos[2],rot[0],rot[1],rot[2],scl[0],scl[1],scl[2]] - + def twinCustomAttrs(self,master='',slave='',customAttrList=[]): ''' Twin all non transform attribute values. Results are returned via a dictionary which stores the attribute:value @@ -558,7 +558,7 @@ def twinCustomAttrs(self,master='',slave='',customAttrList=[]): # Store twin attribute value customAttrValues[twinAttr] = mc.getAttr(master+'.'+attr) return customAttrValues - + def twin(self,master='',slave='',pivot='',mirrorAxis='',mirrorMode='',xformList=[1,1,1,1,1,1,1,1,1],customAttrList=[]): ''' Perform twin based on input arguments @@ -580,97 +580,97 @@ def twin(self,master='',slave='',pivot='',mirrorAxis='',mirrorMode='',xformList= # ========== # - Checks - # ========== - + # Check valid arguments if not master: raise Exception('You must specifiy a valid master transform!') if not mc.objExists(master+'.'+self.twinAttr): return if not slave: slave = str(mc.getAttr(master+'.'+self.twinAttr)) if not pivot: pivot = str(mc.getAttr(master+'.'+self.pivotAttr)) - + # Check namespace ns = '' if master.count(':'): try: ns = master.split(':')[0]+':' except: pass - else: + else: if not slave.startswith(ns): slave = ns+slave if not pivot.startswith(ns): pivot = ns+pivot - + # Check objects exist if not mc.objExists(master): raise Exception('Master object '+master+' does not exists!') if not mc.objExists(slave): raise Exception('Slave object '+slave+' does not exists!') if not mc.objExists(pivot): raise Exception('Pivot object '+pivot+' does not exists!') - + # ============= # - Transform - # ============= - + dcXformList = copy.deepcopy(xformList) - + # Check distination attributes settable state for i in range(9): if dcXformList[i]: dcXformList[i] = mc.getAttr(slave+'.'+self.xform[i],se=True) - + # Get twin transform values xform = self.twinTransform(master,slave,pivot,mirrorAxis,mirrorMode,xformList) - + # Set Slave Transforms for i in range(9): if dcXformList[i]: mc.setAttr(slave+'.'+self.xform[i],xform[i]) - + # ===================== # - Custom Attributes - # ===================== - + # Check custom attribute list if not customAttrList: customAttrList = mc.listAttr(master,keyable=True,userDefined=True) - + # Get custom attribute values customAttrVals = {} if customAttrList: customAttrVals = self.twinCustomAttrs(master,slave,customAttrList) - + # Set custom attribute values self.setCustomAttrValues(slave,customAttrVals) #for attr in customAttrVals.iterkeys(): # if mc.objExists(slave+'.'+attr): - # if mc.getAttr(slave+'.'+attr, settable=True): + # if mc.getAttr(slave+'.'+attr, settable=True): # try: mc.setAttr(slave+'.'+attr,customAttrVals[attr]) # except: pass - + # ============ # - WRAPPERS - # ============ - + def twinSelection(self): ''' Twin the current selected objects. ''' # Get selection list selection = mc.ls(sl=1,transforms=True) - + # Get namespace ns = glTools.utils.namespace.getNS(selection[0],topOnly=False) if ns: ns += ':' - + # Get selection list in order of evaluation orderedSel = selection if mc.objExists(ns+self.evalOrderAttr): evalOrderLen = mc.getAttr(ns+self.evalOrderAttr,s=True) evalOrder = [(ns+mc.getAttr(ns+self.evalOrderAttr+'['+str(i)+']')) for i in range(evalOrderLen)] orderedSel = [str(i) for i in evalOrder if selection.count(i)] - + # Get channelBox attribute selection #cbXformList = [] # DISABLED - self.getCBxformList() #cbUserDefList = [] # DISABLED - self.getCBuserDefList() - + # Perform twin for master in orderedSel: #dcXformList = copy.deepcopy(cbXformList) self.twin(master) # DISABLED - ,dcXformList,userDefList) - + def swapSelection(self): ''' Swap the current selected objects. @@ -679,21 +679,21 @@ def swapSelection(self): # - Get Selection - # ================= selection = mc.ls(sl=1,transforms=True) - + # Get namespace ns = glTools.utils.namespace.getNS(selection[0],topOnly=False) if ns: ns += ':' - + # =========================== # - Get Order of Evaluation - # =========================== - + orderedSel = selection if mc.objExists(ns+self.evalOrderAttr): evalOrderLen = mc.getAttr(ns+self.evalOrderAttr,s=True) evalOrder = [(ns+mc.getAttr(ns+self.evalOrderAttr+'['+str(i)+']')) for i in range(evalOrderLen)] orderedSel = [str(i) for i in evalOrder if selection.count(i)] - + # Get list of master and slave controls slaveList = [] masterList = [] @@ -702,74 +702,74 @@ def swapSelection(self): if mc.objExists(twin): masterList.append(obj) slaveList.append(twin) - + # ================ # - Perform Swap - # ================ - + # Get original slave transform values slaveOrigXformList = [] slaveOrigCustomAttrList = [] for slave in slaveList: slaveOrigXformList.append(self.getTransformValues(slave)) slaveOrigCustomAttrList.append(self.getCustomAttrValues(slave)) - + # Perform Master Twin for master in masterList: self.twin(master) - + # Get twined slave transform values slaveTwinXformList = [] slaveTwinCustomAttrList = [] for slave in slaveList: slaveTwinXformList.append(self.getTransformValues(slave)) slaveTwinCustomAttrList.append(self.getCustomAttrValues(slave)) - + # Restore original slave transform values for i in range(len(slaveList)): self.setTransformValues(slaveList[i],slaveOrigXformList[i]) self.setCustomAttrValues(slaveList[i],slaveOrigCustomAttrList[i]) - + # Perform Slave Twin for slave in slaveList: self.twin(slave) - + # Restore twined slave transform values for i in range(len(slaveList)): self.setTransformValues(slaveList[i],slaveTwinXformList[i]) self.setCustomAttrValues(slaveList[i],slaveTwinCustomAttrList[i]) - + def selectTwin(self): ''' Select the twin of the currectly selected object ''' # Get Current Selection selection = mc.ls(sl=1,transforms=True) - + # Find Twin Controls twinList = [] for obj in selection: - + # Check namespace ns = glTools.utils.namespace.getNS(obj,topOnly=False) obj = glTools.utils.namespace.stripNS(obj) if ns: ns += ':' - + # Get Twin twin = self.getTwin(ns+obj) - + # Check Twin if not mc.objExists(twin): print('Match Warning: Twin object "'+twin+'" does not exist! Skipping object...') else: # Append to Twin List twinList.append(twin) - + # Set Selection if twinList: mc.select(twinList,r=True) - + # ============ # - UTILITIY - # ============ - + def getTwin(self,obj): ''' Return the twin for the selected control @@ -777,26 +777,26 @@ def getTwin(self,obj): # Check Object if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!!') - + # Check namespace ns = glTools.utils.namespace.getNS(obj,topOnly=False) obj = glTools.utils.namespace.stripNS(obj) if ns: ns += ':' - + # ============ # - Get Twin - # ============ twin = '' - + # Check Twin Attribute if mc.objExists(ns+obj+'.'+self.twinAttr): - + # Get twin name string twin = str(mc.getAttr(ns+obj+'.'+self.twinAttr)) if not twin.startswith(ns): twin = ns+twin - + else: - + # Determine twin from prefix if obj.startswith(self.leftPrefix): twin = ns+':'+obj.replace(self.leftPrefix,self.rightPrefix) @@ -804,13 +804,13 @@ def getTwin(self,obj): twin = ns+':'+obj.replace(self.rightPrefix,self.leftPrefix) else: print('Match Warning: Unable to determine twin for object "'+ns+obj+'"!') - + # ================= # - Return Result - # ================= - + return twin - + def transformVector(self,vector=[0,0,0],transform=OpenMaya.MMatrix.identity,transformAsPoint=False,invertTransform=False): ''' Transform a vector (or point) by a given transformation matrix. @@ -826,7 +826,7 @@ def transformVector(self,vector=[0,0,0],transform=OpenMaya.MMatrix.identity,tran # Create MPoint/MVector object for transformation if transformAsPoint: vector = OpenMaya.MPoint(vector[0],vector[1],vector[2],1.0) else: vector = OpenMaya.MVector(vector[0],vector[1],vector[2]) - + # Check Local Space transformMatrix = OpenMaya.MMatrix() if type(transform) == str or type(transform) == unicode: @@ -836,15 +836,15 @@ def transformVector(self,vector=[0,0,0],transform=OpenMaya.MMatrix.identity,tran # Check input is of type MMatrix if type(transform) != OpenMaya.MMatrix: raise Exception('"Transform" input variable is not of expected type! Expecting string or MMatrix, received '+str(type(transform))+'!!') - + # Transform vector if transformMatrix != OpenMaya.MMatrix.identity: if invertTransform: vector *= transformMatrix.inverse() else: vector *= transformMatrix - + # Return new vector return [vector.x,vector.y,vector.z] - + def getTransformMatrix(self,transform='',parentSpace=False): ''' Return an MTransformationMatrix of the specified transform @@ -858,21 +858,21 @@ def getTransformMatrix(self,transform='',parentSpace=False): raise Exception('Local space object '+transform+' does not exists!') if not glTools.utils.transform.isTransform(transform): transform = mc.listRelatives(transform,p=True)[0] - + # Get selectionList sel = OpenMaya.MSelectionList() OpenMaya.MGlobal.getSelectionListByName(transform,sel) - + # Get DagPath to localSpace object transformPath = OpenMaya.MDagPath() sel.getDagPath(0,transformPath) - + # Step up to parent path if parentSpace: transformPath.pop(1) - + # Return transformation matrix return transformPath.inclusiveMatrix() - + def vectorTwinSpaceMirror(self,vector,master,twin,pivot,axis): ''' Transform a vector to twin local space after mirroring across the pivot object's specified axis @@ -891,14 +891,14 @@ def vectorTwinSpaceMirror(self,vector,master,twin,pivot,axis): if not mc.objExists(master): raise Exception('Master object '+master+' does not exist') if not mc.objExists(twin): raise Exception('Twin object '+twin+' does not exist') if not mc.objExists(pivot): raise Exception('Pivot object '+pivot+' does not exist') - + # Get Twin Parent twinParent = '' try: twinParent = str(mc.listRelatives(twin,p=1)[0]) except: pass - + if type(axis) == str: axis = self.axisIndex[axis] - + # Get vector in world space vector = self.transformVector(vector,master,transformAsPoint=False,invertTransform=False) # Mirror vector across pivot axis @@ -907,16 +907,16 @@ def vectorTwinSpaceMirror(self,vector,master,twin,pivot,axis): vector = self.transformVector(vector,pivot,transformAsPoint=False,invertTransform=False) # Get axis in local twin local space if twinParent: vector = self.transformVector(vector,twinParent,transformAsPoint=False,invertTransform=True) - + # Compensate for joint orientation if mc.objectType(twin) == 'joint': jointOrient = mc.getAttr(twin+'.jointOrient')[0] jointOrient = [jointOrient[i]/self.radian for i in range(3)] jointOrientMatrix = OpenMaya.MEulerRotation(jointOrient[0],jointOrient[1],jointOrient[2],0).asMatrix() vector = OpenMaya.MVector(vector[0],vector[1],vector[2]) * jointOrientMatrix.inverse() - + return vector - + def getTransformValues(self,obj): ''' Return a list of transform values for the specified maya transform object @@ -924,7 +924,7 @@ def getTransformValues(self,obj): @type obj: str ''' return [mc.getAttr(obj+'.'+self.xform[i]) for i in range(9)] - + def setTransformValues(self,obj,xformList=[0,0,0,0,0,0,1,1,1]): ''' Set transform values for the specified maya transform object from the input value list @@ -933,7 +933,7 @@ def setTransformValues(self,obj,xformList=[0,0,0,0,0,0,1,1,1]): ''' for i in range(9): if mc.getAttr(obj+'.'+self.xform[i],se=True): mc.setAttr(obj+'.'+self.xform[i],xformList[i]) - + def getCustomAttrValues(self,obj): ''' Return a list of custom attribute values for the specified maya transform object @@ -945,7 +945,7 @@ def getCustomAttrValues(self,obj): if customAttrList: for attr in customAttrList: customAttrVals[attr] = mc.getAttr(obj+'.'+attr) return customAttrVals - + def setCustomAttrValues(self,obj,customAttrVals={}): ''' Return a list of custom attribute values for the specified maya transform object @@ -954,10 +954,10 @@ def setCustomAttrValues(self,obj,customAttrVals={}): ''' for attr in customAttrVals.iterkeys(): if mc.objExists(obj+'.'+attr): - if mc.getAttr(obj+'.'+attr, settable=True): + if mc.getAttr(obj+'.'+attr, settable=True): try: mc.setAttr(obj+'.'+attr,customAttrVals[attr]) except: pass - + def getCBattrList(self): ''' Return a list of selected attributes from the channel box. @@ -966,7 +966,7 @@ def getCBattrList(self): cbAttrList = mc.channelBox(self.channelBox,q=True,selectedMainAttributes=True) if not cbAttrList: cbAttrList = [] return cbAttrList - + def getCBxformList(self): ''' Get an (boolean) integer list representing the selected transform attributes from the channel box. @@ -975,7 +975,7 @@ def getCBxformList(self): xformList = [1,1,1,1,1,1,1,1,1] if cbAttrList: xformList = [cbAttrList.count(self.xform[i]) for i in range(9)] return xformList - + def getCBuserDefList(self): ''' Get a list of selected user defined attributes from the channel box. @@ -986,5 +986,5 @@ def getCBuserDefList(self): usedDefList = ['all'] if cbAttrList: usedDefList = [attr for attr in cbAttrList if not xformList.count(attr)] return usedDefList - + diff --git a/tools/measureMeshDistance.py b/tools/measureMeshDistance.py index 5f85114..243097d 100644 --- a/tools/measureMeshDistance.py +++ b/tools/measureMeshDistance.py @@ -16,39 +16,39 @@ def createBasicMeasure(mesh,vtxId1,vtxId2,prefix): ''' # Check prefix if not prefix: prefix = 'measureMeshDistance' - + # Check baseMesh if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # Create nulls pt1 = mc.spaceLocator(n=prefix+'_pt1')[0] pt2 = mc.spaceLocator(n=prefix+'_pt2')[0] - + # Position nulls pos1 = glTools.utils.base.getPosition(mesh+'.vtx['+str(vtxId1)+']') pos2 = glTools.utils.base.getPosition(mesh+'.vtx['+str(vtxId2)+']') mc.setAttr(pt1+'.t',pos1[0],pos1[1],pos1[2]) mc.setAttr(pt2+'.t',pos2[0],pos2[1],pos2[2]) - + # Create measure curve measureCrv = mc.curve(d=1,p=[pos1,pos2],k=[0,1]) measureCrv = mc.rename(measureCrv,prefix+'_measure') mc.parent([pt1,pt2],measureCrv) - + # Connect to measurement null control points mc.connectAttr(pt1+'.t',measureCrv+'.controlPoints[0]') mc.connectAttr(pt2+'.t',measureCrv+'.controlPoints[1]') - + # Add vtx attrs mc.addAttr(pt1,ln='vtx',at='long',dv=vtxId1,k=True) mc.addAttr(pt2,ln='vtx',at='long',dv=vtxId2,k=True) - + # Return result return measureCrv - + def getMeasureDistance(measure,mesh): ''' Calculate the measure distance based on a reference mesh @@ -61,18 +61,18 @@ def getMeasureDistance(measure,mesh): pts = mc.listRelatives(measure,c=True,type='transform') pt1 = pts[0] pt2 = pts[1] - + # Get measure vtxIds vtxId1 = mc.getAttr(pt1+'.vtx') vtxId2 = mc.getAttr(pt2+'.vtx') - + # Get mesh vertex positions vtxPt1 = glTools.utils.base.getMPoint(mesh+'.vtx['+str(vtxId1)+']') vtxPt2 = glTools.utils.base.getMPoint(mesh+'.vtx['+str(vtxId2)+']') - + # Get distance dist = (vtxPt1 - vtxPt2).length() - + # Return result return dist @@ -86,22 +86,22 @@ def addDistanceAttrs(measure,baseMesh): ''' # Get prefix prefix = measure.replace(measure.split('_')[-1],'') - + # Get measure points pts = mc.listRelatives(measure,c=True,type='transform') pt1 = pts[0] pt2 = pts[1] - + # Create distance node distanceNode = mc.createNode('distanceBetween',n=prefix+'distanceBetween') mc.connectAttr(pt1+'.worldMatrix[0]',distanceNode+'.inMatrix1',f=True) mc.connectAttr(pt2+'.worldMatrix[0]',distanceNode+'.inMatrix2',f=True) - + # Add distance attr if not mc.objExists(measure+'.distance'): mc.addAttr(measure,ln='distance',k=True) mc.connectAttr(distanceNode+'.distance',measure+'.distance',f=True) - + # Add base distance attr if not mc.objExists(measure+'.baseDistance'): mc.addAttr(measure,ln='baseDistance',k=True) @@ -109,10 +109,10 @@ def addDistanceAttrs(measure,baseMesh): dist = getMeasureDistance(measure,baseMesh) # Set base distance value mc.setAttr(measure+'.baseDistance',dist,l=True) - + # Return result return (measure+'.distance') - + def addMeasureAttrs(measure,targetMesh,targetName): ''' Add target distance measure attributes @@ -125,7 +125,7 @@ def addMeasureAttrs(measure,targetMesh,targetName): ''' # Get prefix prefix = measure.replace(measure.split('_')[-1],'') - + # Add measure attributes if not mc.objExists(measure+'.'+targetName): mc.addAttr(measure,ln=targetName,min=0.0,max=1.0,dv=0.0,k=True) @@ -135,43 +135,43 @@ def addMeasureAttrs(measure,targetMesh,targetName): mc.addAttr(measure,ln=targetName+'Envelope',min=0.0,max=2.0,dv=1.0,k=True) if not mc.objExists(measure+'.'+targetName+'Offset'): mc.addAttr(measure,ln=targetName+'Offset',dv=0.0,k=True) - + # Create remapValue node remapNode = mc.createNode('remapValue',n=prefix+targetName+'_remapValue') mc.setAttr(remapNode+'.outputMin',0.0) mc.setAttr(remapNode+'.outputMax',1.0) mc.setAttr(remapNode+'.value[0].value_Interp',3) - + # Connect measure distance to remap input if not mc.objExists(measure+'.distance'): raise Exception('Measure "'+measure+'" has no distance attribute! Run addDistanceAttrs() to add necessary attributes!!') mc.connectAttr(measure+'.distance',remapNode+'.inputValue',f=True) - + # Get base distance - minimum input value if not mc.objExists(measure+'.baseDistance'): raise Exception('Measure "'+measure+'" has no baseDistance attribute! Run addDistanceAttrs() to add necessary attributes!!') mc.connectAttr(measure+'.baseDistance',remapNode+'.inputMin',f=True) - + # Get target length - maximum input value if not mc.objExists(targetMesh): raise Exception('Target mesh "'+targetMesh+'" does not exist!') targetDist = getMeasureDistance(measure,targetMesh) mc.setAttr(measure+'.'+targetName+'Length',targetDist,l=True) mc.connectAttr(measure+'.'+targetName+'Length',remapNode+'.inputMax',f=True) - + # Connect target envelope envelopeNode = mc.createNode('multDoubleLinear',n=prefix+targetName+'Envelope_multDoubleLinear') mc.connectAttr(remapNode+'.outValue',envelopeNode+'.input1',f=True) mc.connectAttr(measure+'.'+targetName+'Envelope',envelopeNode+'.input2',f=True) - + # Connect target offset offsetNode = mc.createNode('addDoubleLinear',n=prefix+targetName+'Offset_addDoubleLinear') mc.connectAttr(envelopeNode+'.output',offsetNode+'.input1',f=True) mc.connectAttr(measure+'.'+targetName+'Offset',offsetNode+'.input2',f=True) - + # Connect to measure target value mc.connectAttr(offsetNode+'.output',measure+'.'+targetName,f=True) - + # Return result return (measure+'.'+targetName) @@ -187,7 +187,7 @@ def addMeasureAttrs_old(measure,targetMesh,targetName): ''' # Get prefix prefix = measure.replace(measure.split('_')[-1],'') - + # Add measure attributes if not mc.objExists(measure+'.'+targetName): mc.addAttr(measure,ln=targetName,min=0.0,max=1.0,dv=0.0,k=True) @@ -195,36 +195,36 @@ def addMeasureAttrs_old(measure,targetMesh,targetName): mc.addAttr(measure,ln=targetName+'Length',dv=0.0,k=True) if not mc.objExists(measure+'.'+targetName+'Envelope'): mc.addAttr(measure,ln=targetName+'Envelope',min=0.0,max=2.0,dv=1.0,k=True) - + # Create remapValue node remapNode = mc.createNode('remapValue',n=prefix+targetName+'_remapValue') mc.setAttr(remapNode+'.outputMin',0.0) mc.setAttr(remapNode+'.outputMax',1.0) mc.setAttr(remapNode+'.value[0].value_Interp',3) - + # Connect measure distance to remap input if not mc.objExists(measure+'.distance'): raise Exception('Measure "'+measure+'" has no distance attribute! Run addDistanceAttrs() to add necessary attributes!!') mc.connectAttr(measure+'.distance',remapNode+'.inputValue',f=True) - + # Get base distance - minimum input value if not mc.objExists(measure+'.baseDistance'): raise Exception('Measure "'+measure+'" has no baseDistance attribute! Run addDistanceAttrs() to add necessary attributes!!') mc.connectAttr(measure+'.baseDistance',remapNode+'.inputMin',f=True) - + # Get target length - maximum input value if not mc.objExists(targetMesh): raise Exception('Target mesh "'+targetMesh+'" does not exist!') targetDist = getMeasureDistance(measure,targetMesh) mc.setAttr(measure+'.'+targetName+'Length',targetDist,l=True) mc.connectAttr(measure+'.'+targetName+'Length',remapNode+'.inputMax',f=True) - + # Connect target envelope to ramp mc.connectAttr(measure+'.'+targetName+'Envelope',remapNode+'.value[1].value_FloatValue',f=True) - + # Connect to measure target value mc.connectAttr(remapNode+'.outValue',measure+'.'+targetName,f=True) - + # Return result return (measure+'.'+targetName) @@ -242,7 +242,7 @@ def addCustomMeasureAttrs(measure,targetName,min=0.0,max=1.0): ''' # Get prefix prefix = measure.replace(measure.split('_')[-1],'') - + # Add custom measure attributes if not mc.objExists(measure+'.'+targetName): mc.addAttr(measure,ln=targetName,min=0.0,max=1.0,dv=0.0,k=True) @@ -254,35 +254,35 @@ def addCustomMeasureAttrs(measure,targetName,min=0.0,max=1.0): mc.addAttr(measure,ln=targetName+'Envelope',min=0.0,max=2.0,dv=1.0,k=True) if not mc.objExists(measure+'.'+targetName+'Offset'): mc.addAttr(measure,ln=targetName+'Offset',dv=0.0,k=True) - + # Create remapValue node remapNode = mc.createNode('remapValue',n=prefix+targetName+'_remapValue') mc.setAttr(remapNode+'.outputMin',0.0) mc.setAttr(remapNode+'.outputMax',1.0) mc.setAttr(remapNode+'.value[0].value_Interp',3) - + # Connect measure distance to remap input if not mc.objExists(measure+'.distance'): raise Exception('Measure "'+measure+'" has no distance attribute! Run addDistanceAttrs() to add necessary attributes!!') mc.connectAttr(measure+'.distance',remapNode+'.inputValue',f=True) - + # Connect min/max custom measure inputs mc.connectAttr(measure+'.'+targetName+'MinLength',remapNode+'.inputMin',f=True) mc.connectAttr(measure+'.'+targetName+'MaxLength',remapNode+'.inputMax',f=True) - + # Connect target envelope envelopeNode = mc.createNode('multDoubleLinear',n=prefix+targetName+'Envelope_multDoubleLinear') mc.connectAttr(remapNode+'.outValue',envelopeNode+'.input1',f=True) mc.connectAttr(measure+'.'+targetName+'Envelope',envelopeNode+'.input2',f=True) - + # Connect target offset offsetNode = mc.createNode('addDoubleLinear',n=prefix+targetName+'Offset_addDoubleLinear') mc.connectAttr(envelopeNode+'.output',offsetNode+'.input1',f=True) mc.connectAttr(measure+'.'+targetName+'Offset',offsetNode+'.input2',f=True) - + # Connect to measure target value mc.connectAttr(offsetNode+'.output',measure+'.'+targetName,f=True) - + # Return result return (measure+'.'+targetName) @@ -312,48 +312,48 @@ def addRigAttrs(measure,rigAttr,targetName,remap=False,inputMin=0.0,inputMax=1.0 # Check rig attr if not mc.objExists(rigAttr): raise Exception('Rig attribute "'+rigAttr+'" does not exist!!') - + # Get prefix prefix = measure.replace(measure.split('_')[-1],'') - + # Add compression attributes if mc.objExists(measure+'.'+targetName): raise Exception('Attribute "'+targetName+'" already exists on measure "'+measure+'"!') mc.addAttr(measure,ln=targetName,min=0.0,max=1.0,dv=0.0,k=True) - + # Check remap if remap: - + # Add min/max remap attributes mc.addAttr(measure,ln=targetName+'InputMin',dv=inputMin,k=True) mc.addAttr(measure,ln=targetName+'InputMax',dv=inputMax,k=True) mc.addAttr(measure,ln=targetName+'OutputMin',dv=outputMin,k=True) mc.addAttr(measure,ln=targetName+'OutputMax',dv=outputMax,k=True) - + # Create remapValue node remapNode = mc.createNode('remapValue',n=prefix+targetName+'_remapValue') mc.setAttr(remapNode+'.value[0].value_Interp',3) - + # Connect rig attr to ramp input mc.connectAttr(rigAttr,remapNode+'.inputValue',f=True) - + # Set input/output min and max values mc.connectAttr(measure+'.'+targetName+'InputMin',remapNode+'.inputMin',f=True) mc.connectAttr(measure+'.'+targetName+'InputMax',remapNode+'.inputMax',f=True) mc.connectAttr(measure+'.'+targetName+'OutputMin',remapNode+'.outputMin',f=True) mc.connectAttr(measure+'.'+targetName+'OutputMax',remapNode+'.outputMax',f=True) - + # Connect to measure target value mc.connectAttr(remapNode+'.outValue',measure+'.'+targetName,f=True) - + else: - + # Connect rig attribute to measure target value mc.connectAttr(rigAttr,measure+'.'+targetName,f=True) - + # Return result return (measure+'.'+targetName) - + def snapMeasure(measure,mesh): ''' Snap the measure points to the vertices of the specified mesh. @@ -370,18 +370,18 @@ def snapMeasure(measure,mesh): raise Exception('Mesh "'+mesh+'" does not exist!!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # Get measure points pts = mc.listRelatives(measure,c=True,type='transform') - + # Snap measure points for pt in pts: vtxId = mc.getAttr(pt+'.vtx') glTools.utils.mesh.snapToVertex(mesh,pt,vtxId) - + # Retrun result return pts - + def constrainMeasure(measure,mesh): ''' Constrain the measure points to the vertices of the specified mesh. @@ -393,19 +393,19 @@ def constrainMeasure(measure,mesh): ''' # Get prefix prefix = measure.replace(measure.split('_')[-1],'') - + # Snap measure snapMeasure(measure,mesh) - + # Get measure points pts = mc.listRelatives(measure,c=True,type='transform') pt1 = pts[0] pt2 = pts[1] - + # Constrain measurment nulls pt1Con = mc.dnMeshConstraint(mesh,pt1,kr=True,n=prefix+'pt1_dnMeshConstraint')[0] pt2Con = mc.dnMeshConstraint(mesh,pt2,kr=True,n=prefix+'pt2_dnMeshConstraint')[0] - + # Return result return [pt1Con,pt2Con] @@ -415,37 +415,37 @@ def measureMeshDistanceMulti(baseMesh,vtxId1,vtxId2,inputTargetList,prefix): # ---------- # - Checks - # ---------- - + # Check prefix if not prefix: prefix = 'measureMeshDistance' - + # Check baseMesh if not mc.objExists(baseMesh): raise Exception('Base mesh "'+baseMesh+'" does not exist!!') - + # Check inputTargetList for target in inputTargetList: if not mc.objExists(target): raise Exception('target mesh "'+target+'" does not exist!!') - + # ------------------------ # - Get vertex distances - # ------------------------ - + # Base distance basePt1 = glTools.utils.base.getMPoint(baseMesh+'.vtx['+str(vtxId1)+']') basePt2 = glTools.utils.base.getMPoint(baseMesh+'.vtx['+str(vtxId2)+']') basePos1 = [basePt1.x,basePt1.y,basePt1.z] basePos2 = [basePt2.x,basePt2.y,basePt2.z] baseDist = (basePt1-basePt2).length() - + # ------------------------ # - Get target distances - # ------------------------ - + # Initialize target distance arrays inputTargetDist = [(baseDist,'base')] - + # For each target for target in inputTargetList: # Get target distance @@ -453,46 +453,46 @@ def measureMeshDistanceMulti(baseMesh,vtxId1,vtxId2,inputTargetList,prefix): targetPt2 = glTools.utils.base.getMPoint(target+'.vtx['+str(vtxId2)+']') targetDist = (targetPt1-targetPt2).length() inputTargetDist.append((targetDist,target)) - + # Sort according to target distance inputTargetDist.sort() - + # Generate input target data inputTargetData = {} for i in range(len(inputTargetDist)): # Get current target and distance inputDist = inputTargetDist[i][0] inputTarget = inputTargetDist[i][1] - + # Skip base distance if inputTarget == 'base': continue - + # Add target and distance to inputTargetData inputTargetData[inputTarget] = [] inputTargetData[inputTarget].append(inputDist) - + # Determine bracket values targetBracket = [] if i: targetBracket.append(inputTargetDist[i-1][0]) targetBracket.append(inputDist) if i < (len(inputTargetDist)-1): targetBracket.append(inputTargetDist[i+1][0]) - + # Append bracket values to inputTargetData inputTargetData[inputTarget].append(targetBracket) - + # ---------------------------- # - Create Measurement Nulls - # ---------------------------- - + # Create nulls grp = mc.group(em=True,n=prefix+'_grp') pt1 = mc.group(em=True,n=prefix+'_pt1_null') pt2 = mc.group(em=True,n=prefix+'_pt2_null') - + # Position nulls mc.setAttr(pt1+'.t',basePt1.x,basePt1.y,basePt1.z) mc.setAttr(pt2+'.t',basePt2.x,basePt2.y,basePt2.z) - + # Constrain measurment nulls mc.select(baseMesh,pt1) pt1Con = mm.eval('dnMeshConstraint') @@ -500,7 +500,7 @@ def measureMeshDistanceMulti(baseMesh,vtxId1,vtxId2,inputTargetList,prefix): mc.select(baseMesh,pt2) pt2Con = mm.eval('dnMeshConstraint') mc.rename(pt2Con,prefix+'_pt2_dnMeshConstraint') - + # Create measure curve measureCrv = mc.curve(d=1,p=[basePos1,basePos2],k=[0,1]) measureCrv = mc.rename(measureCrv,prefix+'_measure') @@ -508,53 +508,53 @@ def measureMeshDistanceMulti(baseMesh,vtxId1,vtxId2,inputTargetList,prefix): # Connect to measurement null control points mc.connectAttr(pt1+'.t',measureCrv+'.controlPoints[0]') mc.connectAttr(pt2+'.t',measureCrv+'.controlPoints[1]') - + # ---------------------- # - Calculate distance - # ---------------------- - + # Create distance node distanceNode = mc.createNode('distanceBetween',n=prefix+'_distanceBetween') mc.connectAttr(pt1+'.worldMatrix[0]',distanceNode+'.inMatrix1',f=True) mc.connectAttr(pt2+'.worldMatrix[0]',distanceNode+'.inMatrix2',f=True) - + # --------------------------- # - Add distance attributes - # --------------------------- - + # Current distance mc.addAttr(measureCrv,ln='distance',k=True) mc.connectAttr(distanceNode+'.distance',measureCrv+'.distance',f=True) - + # Base distance mc.addAttr(measureCrv,ln='baseDistance',dv=baseDist,k=True) mc.setAttr(measureCrv+'.baseDistance',l=True) - + # Target distance for target in inputTargetList: targetAttr = target+'TargetDistance' mc.addAttr(measureCrv,ln=targetAttr,dv=inputTargetData[target][0],k=True) mc.setAttr(measureCrv+'.'+targetAttr,l=True) - + # ------------------------------------------- # - Add normalized target weight attributes - # ------------------------------------------- - + for target in inputTargetList: - + # Get input target data targetData = inputTargetData[target] targetDist = targetData[0] targetBracket = targetData[1] - + # Add target attributes mc.addAttr(measureCrv,ln=target,k=True) mc.addAttr(measureCrv,ln=target+'Weight',min=0,max=1,dv=1,k=True) - + # Remap target distance targetRemapNode = mc.createNode('remapValue',n=prefix+'_'+target+'_remapValue') mc.connectAttr(distanceNode+'.distance',targetRemapNode+'.inputValue',f=True) - + # Set input limits mc.setAttr(targetRemapNode+'.outputMin',0.0) mc.setAttr(targetRemapNode+'.outputMax',1.0) @@ -564,7 +564,7 @@ def measureMeshDistanceMulti(baseMesh,vtxId1,vtxId2,inputTargetList,prefix): else: mc.setAttr(targetRemapNode+'.inputMax',targetBracket[0]) mc.setAttr(targetRemapNode+'.inputMin',targetBracket[-1]) - + # Set ramp attributes mc.setAttr(targetRemapNode+'.value[0].value_Position',0) mc.setAttr(targetRemapNode+'.value[0].value_FloatValue',0) @@ -572,17 +572,17 @@ def measureMeshDistanceMulti(baseMesh,vtxId1,vtxId2,inputTargetList,prefix): mc.setAttr(targetRemapNode+'.value[1].value_Position',1) mc.setAttr(targetRemapNode+'.value[1].value_FloatValue',1) mc.setAttr(targetRemapNode+'.value[1].value_Interp',2) - + # Check target fade out if len(targetBracket) == 3: - + print ('bracketed ramp on "'+prefix+'" for target "'+target+'"') - + # Calculate normalized bracket mid point midWeight = (targetBracket[1]-targetBracket[0])/(targetBracket[2]-targetBracket[0]) - + print ('midWeight = '+str(midWeight)) - + # Set ramp attributes mc.setAttr(targetRemapNode+'.value[1].value_Position',midWeight) mc.setAttr(targetRemapNode+'.value[1].value_FloatValue',1) @@ -590,15 +590,15 @@ def measureMeshDistanceMulti(baseMesh,vtxId1,vtxId2,inputTargetList,prefix): mc.setAttr(targetRemapNode+'.value[2].value_Position',1) mc.setAttr(targetRemapNode+'.value[2].value_FloatValue',0) mc.setAttr(targetRemapNode+'.value[2].value_Interp',2) - + # Connect target weight to ramp mc.connectAttr(measureCrv+'.'+target+'Weight',targetRemapNode+'.value[1].value_FloatValue',f=True) - + # Connect to target attribute mc.connectAttr(targetRemapNode+'.outValue',measureCrv+'.'+target,f=True) - + # ----------------- # - Return result - # ----------------- - + return measureCrv diff --git a/tools/mesh.py b/tools/mesh.py index f06b8d2..ab7b4a3 100644 --- a/tools/mesh.py +++ b/tools/mesh.py @@ -18,37 +18,37 @@ def reconstructMesh(mesh,replace=False): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Build Mesh Data meshData = glTools.data.meshData.MeshData(mesh) - + # Rename Mesh meshData._data['name'] = mesh+'_reconstructed' - + # Rebuild Mesh newMesh = meshData.rebuildMesh() - + # Reassign Shader meshShape = mc.ls(mc.listRelatives(mesh,s=True,ni=True),type='mesh')[0] sg = mc.ls(mc.listConnections(meshShape,s=True,d=True,sh=True) or [],type='shadingEngine') if sg: mc.sets(newMesh,fe=sg[0]) - + # Replace if replace: - + # Get Current Mesh Parent meshParent = mc.listRelatives(mesh,p=True) - + # Rename Mesh delMesh = mc.rename(mesh,mesh+'_delete') newMesh = mc.rename(newMesh,mesh) - + # Reparent Mesh if meshParent: mc.parent(newMesh,meshParent[0]) - + # Delete Old Mesh mc.delete(delMesh) - + # Return Result return newMesh @@ -65,25 +65,25 @@ def edgeLoopsToCurve(edgeList,form=2,degree=1): # Filter/Check Edge List edgeList = mc.filterExpand(edgeList,ex=True,sm=32) if not edgeList: raise Exception('Invalid edge list!') - + # For Each Edge edgeCurveList = [] for edge in edgeList: - + # Get Mesh edgeId = glTools.utils.component.index(edge) meshShape = mc.ls(edge,o=True)[0] mesh = mc.listRelatives(meshShape,p=True)[0] prefix = mesh.split(':')[-1] - + # To Edge Loop mc.polySelect(mesh,edgeLoop=edgeId) - + # Edge Loop to Curve edgeCurve = mc.polyToCurve(ch=False,form=form,degree=degree)[0] - + # Append List edgeCurveList.append(edgeCurve) - + # Return Result return edgeCurveList diff --git a/tools/meshCache.py b/tools/meshCache.py index 055ff6a..61d5e43 100644 --- a/tools/meshCache.py +++ b/tools/meshCache.py @@ -33,11 +33,11 @@ def writeGeoCache(path,name,mesh,startFrame,endFrame,pad=4,uvSet='',worldSpace=T ''' # Check path if not os.path.isdir(path): os.makedirs(path) - + # Check mesh if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check UVs uv = False if uvSet: @@ -45,23 +45,23 @@ def writeGeoCache(path,name,mesh,startFrame,endFrame,pad=4,uvSet='',worldSpace=T else: print('UVSet "'+uvSet+'" does not exist for mesh "'+mesh+'"!') else: uvSet = str(mc.polyUVSet(mesh,q=True,cuv=True)[0]) - + # Determine Sample Space if worldSpace: sampleSpace = OpenMaya.MSpace.kWorld else: sampleSpace = OpenMaya.MSpace.kObject - + # Write mesh cache for f in range(startFrame,endFrame+1): - + # Update frame mc.currentTime(f) - + # ------------------------- # - Open file for writing - # ------------------------- - + fPad = glTools.utils.stringUtils.stringIndex(f,pad) - + if gz: filename = path+'/'+name+'.'+fPad+'.geo.gz' print 'Writing '+filename @@ -70,69 +70,69 @@ def writeGeoCache(path,name,mesh,startFrame,endFrame,pad=4,uvSet='',worldSpace=T filename = path+'/'+name+'.'+fPad+'.geo' print 'Writing '+filename FILE = open(filename,"w") - + # Write cache file header FILE.write('PGEOMETRY V5\n') - + # Determine the total number of vertices numVerts = mc.polyEvaluate(mesh,v=True) numFaces = mc.polyEvaluate(mesh,f=True) - + # Write total number pf points/primitives FILE.write('NPoints '+str(numVerts)+' NPrims '+str(numFaces)+'\n') - + # Write Point/Prim Group info FILE.write('NPointGroups 0 NPrimGroups 0\n') - + # Write Point/Vert/Prim/Detail Attribute info if uv: numVtxAttr = 1 else: numVtxAttr = 0 FILE.write('NPointAttrib 1 NVertexAttrib '+str(numVtxAttr)+' NPrimAttrib 0 NAttrib 0\n') - + # ------------------------- # - Write Point Attr Info - # ------------------------- - + FILE.write('PointAttrib\n') FILE.write('N 3 vector 0 0 0\n') - + vtxArray = OpenMaya.MPointArray() normArray = OpenMaya.MFloatVectorArray() meshFn = glTools.utils.mesh.getMeshFn(mesh) meshFn.getPoints(vtxArray,sampleSpace) meshFn.getVertexNormals(False,normArray,sampleSpace) - + # Write vertex array for i in range(vtxArray.length()): FILE.write(str(vtxArray[i].x)+' '+str(vtxArray[i].y)+' '+str(vtxArray[i].z)+' '+str(vtxArray[i].w)+' ('+str(normArray[i].x)+' '+str(normArray[i].y)+' '+str(normArray[i].z)+')\n') - + # ------------------- # - Write Face Data - # ------------------- - + if uv: FILE.write('VertexAttrib\n') FILE.write('uv 3 float 0 0 0\n') - + FILE.write('Run '+str(numFaces)+' Poly\n') - + # Face vertex id array faceVtxArray = OpenMaya.MIntArray() faceUArray = OpenMaya.MFloatArray() faceVArray = OpenMaya.MFloatArray() - + # Get mesh face iterator faceIter = glTools.utils.mesh.getMeshFaceIter(mesh) - + # Iterate over mesh faces faceIter.reset() while not faceIter.isDone(): - + # Get face vertices faceIter.getVertices(faceVtxArray) vtxArray = list(faceVtxArray) vtxArray.reverse() - + # Get face UVs if uv: faceIter.getUVs(faceUArray,faceVArray,uvSet) @@ -140,37 +140,37 @@ def writeGeoCache(path,name,mesh,startFrame,endFrame,pad=4,uvSet='',worldSpace=T vArray = list(faceVArray) uArray.reverse() vArray.reverse() - + # Build face data string faceData = ' '+str(len(vtxArray))+' <' for i in range(len(vtxArray)): faceData += ' '+str(vtxArray[i]) if uv: faceData += ' ( '+str(uArray[i])+' '+str(vArray[i])+' 0.0 )' faceData += '\n' - + # Write face data FILE.write(faceData) - + # Iterate to next face faceIter.next() - + # ----------------------- # - Finalize cache file - # ----------------------- - + FILE.write('beginExtra\n') FILE.write('endExtra\n') - + # Close File FILE.close() - + # Print result print 'Write cache completed!' - + def writeGeoCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',worldSpace=True,gz=False): ''' Write a .geo cache per frame for the specified list of mesh objects. - All meshes in the list will be combined to a single cache, and an 'id' vertex attribute will be added to identify the individual objects. + All meshes in the list will be combined to a single cache, and an 'id' vertex attribute will be added to identify the individual objects. @param path: Destination directory path for the cache files. @type path: str @param name: Cache file output name. @@ -192,40 +192,40 @@ def writeGeoCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',w ''' # Check path if not os.path.isdir(path): os.makedirs(path) - + # Check mesh list fullMeshList = meshList for mesh in meshList: if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check UVs uv = False if uvSet: for mesh in meshList: if mc.polyUVSet(mesh,q=True,auv=True).count(uvSet): uv = True else: print('UVSet "'+uvSet+'" does not exist for mesh "'+mesh+'"!') - + # Determine Sample Space if worldSpace: sampleSpace = OpenMaya.MSpace.kWorld else: sampleSpace = OpenMaya.MSpace.kObject - + # Write mesh cache for f in range(startFrame,endFrame+1): - + # Update frame mc.currentTime(f) - + # Check mesh visibility meshList = [mesh for mesh in fullMeshList if mc.getAttr(mesh+'.v')] if not meshList: continue - + # ------------------------- # - Open file for writing - # ------------------------- - + fPad = glTools.utils.stringUtils.stringIndex(f,pad) - + if gz: filename = path+'/'+name+'.'+fPad+'.geo.gz' print 'Writing '+filename @@ -234,19 +234,19 @@ def writeGeoCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',w filename = path+'/'+name+'.'+fPad+'.geo' print 'Writing '+filename FILE = open(filename,"w") - + # Write cache file header FILE.write('PGEOMETRY V5\n') - + # Determine the total number of vertices numVertList = [] numFaceList = [] totalNumVerts = 0 totalNumFaces = 0 - + # For each mesh for mesh in meshList: - + # Get mesh data numVerts = mc.polyEvaluate(mesh,v=True) numFaces = mc.polyEvaluate(mesh,f=True) @@ -254,73 +254,73 @@ def writeGeoCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',w totalNumFaces += numFaces numVertList.append(numVerts) numFaceList.append(numFaces) - + # Write total number pf points/primitives FILE.write('NPoints '+str(totalNumVerts)+' NPrims '+str(totalNumFaces)+'\n') - + # Write Point/Prim Group info FILE.write('NPointGroups 0 NPrimGroups 0\n') - + # Write Point/Vert/Prim/Detail Attribute info if uv: numVtxAttr = 1 else: numVtxAttr = 0 FILE.write('NPointAttrib 2 NVertexAttrib '+str(numVtxAttr)+' NPrimAttrib 0 NAttrib 0\n') - + # ------------------------- # - Write Point Attr Info - # ------------------------- - + FILE.write('PointAttrib\n') FILE.write('N 3 vector 0 0 0\n') FILE.write('id 1 int 0\n') - + # Write raw point data for m in range(len(meshList)): - + # Get vertex and normal arrays vtxArray = OpenMaya.MPointArray() normArray = OpenMaya.MFloatVectorArray() meshFn = glTools.utils.mesh.getMeshFn(meshList[m]) meshFn.getPoints(vtxArray,sampleSpace) meshFn.getVertexNormals(False,normArray,sampleSpace) - + # Write vertex array for i in range(vtxArray.length()): FILE.write(str(vtxArray[i].x)+' '+str(vtxArray[i].y)+' '+str(vtxArray[i].z)+' '+str(vtxArray[i].w)+' ('+str(normArray[i].x)+' '+str(normArray[i].y)+' '+str(normArray[i].z)+' '+str(m)+')\n') - + # ------------------- # - Write Face Data - # ------------------- - + if uv: FILE.write('VertexAttrib\n') FILE.write('uv 3 float 0 0 0\n') - + FILE.write('Run '+str(totalNumFaces)+' Poly\n') - - # Track per mesh vertex id offsets + + # Track per mesh vertex id offsets vertexOffset = 0 - + # Face vertex id array faceVtxArray = OpenMaya.MIntArray() faceUArray = OpenMaya.MFloatArray() faceVArray = OpenMaya.MFloatArray() - + # Iterate over meshes for m in range(len(meshList)): - + # Get mesh face iterator faceIter = glTools.utils.mesh.getMeshFaceIter(meshList[m]) - + # Iterate over mesh faces faceIter.reset() while not faceIter.isDone(): - + # Get face vertices faceIter.getVertices(faceVtxArray) vtxArray = list(faceVtxArray) #vtxArray.reverse() - + # Get face UVs if uv: faceIter.getUVs(faceUArray,faceVArray,uvSet) @@ -328,33 +328,33 @@ def writeGeoCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',w vArray = list(faceVArray) uArray.reverse() vArray.reverse() - + # Build face data string faceData = ' '+str(len(vtxArray))+' <' for i in range(len(vtxArray)): faceData += ' '+str(vtxArray[i]+vertexOffset) if uv: faceData += ' ( '+str(faceUArray[i])+' '+str(faceVArray[i])+' 0.0 )' faceData += '\n' - + # Write face data FILE.write(faceData) - + # Iterate to next face faceIter.next() - + # Update vertex offset vertexOffset += numVertList[m] - + # ----------------------- # - Finalize cache file - # ----------------------- - + FILE.write('beginExtra\n') FILE.write('endExtra\n') - + # Close File FILE.close() - + # Print result print 'Write cache completed!' @@ -382,11 +382,11 @@ def writeObjCache(path,name,mesh,startFrame,endFrame,pad=4,uvSet='',worldSpace=T ''' # Check path if not os.path.isdir(path): os.makedirs(path) - + # Check mesh if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check UVs uv = False if uvSet: @@ -394,23 +394,23 @@ def writeObjCache(path,name,mesh,startFrame,endFrame,pad=4,uvSet='',worldSpace=T else: print('UVSet "'+uvSet+'" does not exist for mesh "'+mesh+'"!') else: uvSet = str(mc.polyUVSet(mesh,q=True,cuv=True)[0]) - + # Determine Sample Space if worldSpace: sampleSpace = OpenMaya.MSpace.kWorld else: sampleSpace = OpenMaya.MSpace.kObject - + # Write mesh cache for f in range(startFrame,endFrame+1): - + # Update frame mc.currentTime(f) - + # ------------------------- # - Open file for writing - # ------------------------- - + fPad = glTools.utils.stringUtils.stringIndex(f,pad) - + if gz: filename = path+'/'+name+'.'+fPad+'.obj.gz' print 'Writing '+filename @@ -419,101 +419,101 @@ def writeObjCache(path,name,mesh,startFrame,endFrame,pad=4,uvSet='',worldSpace=T filename = path+'/'+name+'.'+fPad+'.obj' print 'Writing '+filename FILE = open(filename,"w") - + # Write cache file header FILE.write('g\n') - + # --------------------- # - Write Vertex Data - # --------------------- - + meshFn = glTools.utils.mesh.getMeshFn(mesh) - + # Vertex Positions vtxArray = OpenMaya.MPointArray() meshFn.getPoints(vtxArray,sampleSpace) for i in range(vtxArray.length()): FILE.write('v '+str(vtxArray[i].x)+' '+str(vtxArray[i].y)+' '+str(vtxArray[i].z)+'\n') - + # Vertex UVs uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() meshFn.getUVs(uArray,vArray,uvSet) for i in range(uArray.length()): FILE.write('vt '+str(uArray[i])+' '+str(vArray[i])+'\n') - + # Vertex Normals normArray = OpenMaya.MFloatVectorArray() meshFn.getVertexNormals(False,normArray,sampleSpace) for i in range(vtxArray.length()): FILE.write('vn '+str(vtxArray[i].x)+' '+str(vtxArray[i].y)+' '+str(vtxArray[i].z)+'\n') - + FILE.write('g\n') - + # ------------------- # - Write Face Data - # ------------------- - + # Initialize face vertex array faceVtxArray = OpenMaya.MIntArray() - + # Build UV Id pointer object uvIdUtil = OpenMaya.MScriptUtil() uvIdUtil.createFromInt(0) uvIdPtr = uvIdUtil.asIntPtr() - + # Get mesh face iterator faceIter = glTools.utils.mesh.getMeshFaceIter(mesh) - + # Iterate over mesh faces faceIter.reset() while not faceIter.isDone(): - + # Get face vertices faceIter.getVertices(faceVtxArray) vtxArray = list(faceVtxArray) vtxCount = len(vtxArray) - + # Build face data string faceData = 'f ' for i in range(vtxCount): - + # Vertex Id faceData += str(vtxArray[i]+1) faceData += '/' - + # UV Id try: faceIter.getUVIndex(i,uvIdPtr,uvSet) except: pass else: faceData += str(OpenMaya.MScriptUtil(uvIdPtr).asInt()+1) faceData += '/' - + # Vertex Normal Id faceData += str(vtxArray[i]+1) faceData += ' ' - + faceData += '\n' - + # Write face data FILE.write(faceData) - + # Iterate to next face faceIter.next() - + # ----------------------- # - Finalize cache file - # ----------------------- - + # Close File FILE.close() - + # Print result print 'Write OBJ cache completed!' def writeObjCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',worldSpace=True,gz=False): ''' Write a .obj cache per frame for the specified list of mesh objects. - All meshes in the list will be combined to a single cache. + All meshes in the list will be combined to a single cache. @param path: Destination directory path for the cache files. @type path: str @param name: Cache file output name. @@ -535,41 +535,41 @@ def writeObjCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',w ''' # Check path if not os.path.isdir(path): os.makedirs(path) - + # Check mesh list fullMeshList = meshList for mesh in meshList: if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check UVs uv = False if uvSet: for mesh in meshList: if mc.polyUVSet(mesh,q=True,auv=True).count(uvSet): uv = True else: print('UVSet "'+uvSet+'" does not exist for mesh "'+mesh+'"!') - + # Determine Sample Space if worldSpace: sampleSpace = OpenMaya.MSpace.kWorld else: sampleSpace = OpenMaya.MSpace.kObject - + # Write mesh cache for f in range(startFrame,endFrame+1): - + # Update frame mc.currentTime(f) mc.dgdirty(a=True) - + # Check mesh visibility meshList = [mesh for mesh in fullMeshList if mc.getAttr(mesh+'.v')] if not meshList: continue - + # ------------------------- # - Open file for writing - # ------------------------- - + fPad = glTools.utils.stringUtils.stringIndex(f,pad) - + if gz: filename = path+'/'+name+'.'+fPad+'.obj.gz' print 'Writing '+filename @@ -578,25 +578,25 @@ def writeObjCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',w filename = path+'/'+name+'.'+fPad+'.obj' print 'Writing '+filename FILE = open(filename,"w") - + # Write cache file header FILE.write('g\n') - + # --------------------- # - Write Vertex Data - # --------------------- - + # Write raw point data for m in range(len(meshList)): - + meshFn = glTools.utils.mesh.getMeshFn(meshList[m]) - + # Vertex Positions vtxArray = OpenMaya.MPointArray() meshFn.getPoints(vtxArray,sampleSpace) for i in range(vtxArray.length()): FILE.write('v '+str(vtxArray[i].x)+' '+str(vtxArray[i].y)+' '+str(vtxArray[i].z)+'\n') - + # Vertex UVs if uvSet: uvSetName = uvSet else: uvSetName = str(mc.polyUVSet(meshList[m],q=True,cuv=True)[0]) @@ -605,85 +605,85 @@ def writeObjCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',w meshFn.getUVs(uArray,vArray,uvSetName) for i in range(uArray.length()): FILE.write('vt '+str(uArray[i])+' '+str(vArray[i])+'\n') - + # Vertex Normals normArray = OpenMaya.MFloatVectorArray() meshFn.getVertexNormals(False,normArray,sampleSpace) for i in range(vtxArray.length()): FILE.write('vn '+str(vtxArray[i].x)+' '+str(vtxArray[i].y)+' '+str(vtxArray[i].z)+'\n') - + # ------------------- # - Write Face Data - # ------------------- - - # Track per mesh vertex id offsets + + # Track per mesh vertex id offsets vertexOffset = 0 uvOffset = 0 - + # Initialize face vertex array faceVtxArray = OpenMaya.MIntArray() - + # Build UV Id pointer object uvIdUtil = OpenMaya.MScriptUtil() uvIdUtil.createFromInt(0) uvIdPtr = uvIdUtil.asIntPtr() - + # Iterate over meshes for m in range(len(meshList)): - + # Write cache file header grp = meshList[m].replace(':','_').lower() FILE.write('g '+grp+'\n') - + # Get mesh face iterator faceIter = glTools.utils.mesh.getMeshFaceIter(meshList[m]) - + # Iterate over mesh faces faceIter.reset() while not faceIter.isDone(): - + # Get face vertices faceIter.getVertices(faceVtxArray) vtxArray = list(faceVtxArray) vtxCount = len(vtxArray) - + # Build face data string faceData = 'f ' for i in range(vtxCount): - + # Vertex Id faceData += str(vtxArray[i]+1+vertexOffset) faceData += '/' - + # UV Id try: faceIter.getUVIndex(i,uvIdPtr) except: pass else: faceData += str(OpenMaya.MScriptUtil(uvIdPtr).asInt()+1+uvOffset) faceData += '/' - + # Vertex Normal Id faceData += str(vtxArray[i]+1+vertexOffset) faceData += ' ' - + faceData += '\n' - + # Write face data FILE.write(faceData) - + # Iterate to next face faceIter.next() - + # Update vertex offset vertexOffset += mc.polyEvaluate(meshList[m],v=True) uvOffset += mc.polyEvaluate(meshList[m],uv=True,uvs=uvSetName) - + # ----------------------- # - Finalize cache file - # ----------------------- - + # Close File FILE.close() - + # Print result print 'Write OBJ cache completed!' @@ -692,18 +692,18 @@ def gzipCache(path,name,deleteOriginal=False): ''' # Check path if not os.path.isdir(path): raise Exception('Path "'+path+'" does not exist!') - + # Get directory file list dirList = os.listdir(path) dirList.sort() - + # Iterate over file list gziplist = [] for fname in dirList: - + # Check name if not fname.startswith(name): continue - + # Gzip file filepath = path+'/'+fname gzippath = filepath+'.gz' @@ -713,15 +713,15 @@ def gzipCache(path,name,deleteOriginal=False): FILE_OUT.writelines(FILE_IN) FILE_OUT.close() FILE_IN.close() - + # Check gzip if not os.path.isfile(gzippath): raise Exception('Gzip of file "'+gzippath+'" failed!') - + # Append to return list gziplist.append(gzippath) - + # Delete original if deleteOriginal: os.remove(filepath) - + # Return result return gziplist diff --git a/tools/meshCombine.py b/tools/meshCombine.py index df22cad..2bab084 100644 --- a/tools/meshCombine.py +++ b/tools/meshCombine.py @@ -2,7 +2,7 @@ import maya.mel as mm class MeshCombineUtilities(object): - + def __init__(self): pass @@ -25,7 +25,7 @@ def combine(self, objs=[], new_name="", keepHistory=0): raise Exception('Object '+obj+' does not exist!') if mc.objExists(new_name): raise Exception('An object of name '+new_name+' already exists! Please choose another name!') - + # Combine multiple mesh objects to a single mesh new_obj = mc.polyUnite(objs, n=new_name) mc.addAttr( new_obj[0], ln='origNames', dt='string', multi=True) @@ -35,9 +35,9 @@ def combine(self, objs=[], new_name="", keepHistory=0): # Delete history if not keepHistory : mc.delete(new_obj[1]) mc.delete(objs) - + return new_obj[0] - + def separate(self, obj): ''' Seperates the geometry that has been combined with the combine method. @@ -48,14 +48,14 @@ def separate(self, obj): # Check origNames attribute if not mc.objExists(obj+'.origNames'): raise Exception('Object '+obj+' does not have a "origNames" attribute!') - + origNamesIsMulti = True if not mc.addAttr(obj+'.origNames',q=True,multi=True): origNamesIsMulti = False # Need to phase out the old format origNames attribute #------------------------------------------------------- #raise Exception(obj+'.origNames attribute is not in the correct format! Please run MeshCombineUtilities.updateOrigNamesFormat().') - + # Deal with scene namespace scene_ns = mm.eval('getOfficialNS') mm.eval('pauseNS') @@ -67,7 +67,7 @@ def separate(self, obj): objs = [] try: objs = mc.polySeparate(obj,ch=1) except: raise Exception('Separate failed on object "'+obj+'"!') - + # Get original names list nameList=[] if origNamesIsMulti: @@ -76,7 +76,7 @@ def separate(self, obj): else: for attr in mc.listAttr(obj+'.origNames')[1:]: nameList.append( mc.getAttr(obj+'.origNames.'+attr) ) - + # Rename separated objects for i in range(len(nameList)): nameList[i] = mc.rename(objs[i],ns+nameList[i]) @@ -87,17 +87,17 @@ def separate(self, obj): mc.parent(nameList[i],ns+'model') else: mc.parent(nameList[i], w=1 ) - + # Cleanup: # Removed rename of original objects: Objects that are referenced can't be renamed # orig_child = mc.listRelatives(obj_fPath, c=1, ni=1, pa=True) - for i in orig_child: + for i in orig_child: if mc.listRelatives(i): mc.delete(i) - + # handle namespace mm.eval('setNS("'+scene_ns+'")') return nameList - + def separateAll(self): ''' This is a wrapper of the 'seperate' command. 'seperateAll' will @@ -109,15 +109,15 @@ def separateAll(self): allSeperatedObjs=[] for ns in all_ns: allSeperatedObjs.extend( self.separateActor(ns) ) - + # Return result return allSeperatedObjs - + def separateActor(self, ns=''): ''' This is a wrapper of the 'separate' command. 'separateActor' will look at the provided namespace in the scene and model node within that for meshes that - have been combined using the 'combine'. Then it will separate the + have been combined using the 'combine'. Then it will separate the found objects. @param ns: Namespace of the actor you want to separate @type ns: str @@ -128,7 +128,7 @@ def separateActor(self, ns=''): if not mc.objExists(ns+'model'): print('Actor "'+ns+'" has no model group!') return [] - + # Iterate through mesh shapes meshList = mc.listRelatives(ns+'model',ad=1,pa=True,type='mesh') if not meshList: return [] @@ -143,16 +143,16 @@ def separateActor(self, ns=''): # Check current mesh against meshParentList if not meshParentList.count(meshParent): meshParentList.append(meshParent) - + # Separate allSeperatedObjs=[] for mesh in meshParentList: print "Separating : "+ mesh allSeperatedObjs.extend( self.separate(mesh) ) - + # Return result return allSeperatedObjs - + def getOriginalNames(self, obj): ''' Get the meshOrigNames stored on an object that has been combined with glTools.common.MeshCombineUtilities.combine() @@ -163,13 +163,13 @@ def getOriginalNames(self, obj): raise Exception('Object '+obj+' does not have a "origNames" attribute!') if not mc.addAttr(obj+'.origNames',q=True,multi=True): raise Exception(obj+'.origNames attribute is not in the correct format! Please run MeshCombineUtilities.updateOrigNamesFormat().') - + origNamesList = [] for i in range(mc.getAttr(obj+'.origNames',s=True)): origNamesList.append(mc.getAttr(obj+'.origNames['+str(i)+']')) - + return origNamesList - + def setOriginalNames(self, name_list, obj): ''' Set the meshOrigNames stored on an object that has been combined with glTools.common.MeshCombineUtilities.combine() @@ -189,7 +189,7 @@ def setOriginalNames(self, name_list, obj): # Set original name values for i in range(len(name_list)): mc.setAttr( obj+'.origNames['+str(i)+']', name_list[i], type='string') - + def updateOrigNamesFormat(self,objectList=[]): ''' Update a combined meshes origNames attribute to the newest format. @@ -199,17 +199,17 @@ def updateOrigNamesFormat(self,objectList=[]): # Confirm list if type(objectList) == str: objectList = [objectList] - + # Iterate through object list for obj in objectList: - + # Check origNames attribute if not mc.objExists(obj+'.origNames'): raise Exception('Object '+obj+' does not have a "origNames" attribute!') if mc.addAttr(obj+'.origNames',q=True,multi=True): print(obj+'.origNames is already in the correct format.') continue - + # Extract original names list from old format origNamesList = [] index = 0 @@ -218,13 +218,13 @@ def updateOrigNamesFormat(self,objectList=[]): origNamesList.append(mc.getAttr(obj+'.origNames.origNames_'+str(index))) index+=1 else: break - + # Re-create the origNames attribute in the new format mc.deleteAttr(obj+'.origNames') mc.addAttr(obj,ln='origNames',dt='string',multi=True) for i in range(len(origNamesList)): mc.setAttr( obj+'.origNames['+str(i)+']', origNamesList[i], type='string') - + def updateActorOrigNames(self,ns=''): ''' Update all combined meshes origNames attribute for a specified actor namespace. @@ -235,7 +235,7 @@ def updateActorOrigNames(self,ns=''): allSeperatedObjs=[] if not mc.objExists(ns+'model'): raise Exception('Object "'+ns+'model" does not exist!') - + # Iterate through mesh shapes meshList = mc.listRelatives(ns+'model',ad=1,ni=1,pa=True,type='mesh') meshParentList = [] @@ -244,4 +244,4 @@ def updateActorOrigNames(self,ns=''): if not mc.objExists(meshParent+".origNames"): continue print "Updating: "+ meshParent self.updateOrigNamesFormat([meshParent]) - + diff --git a/tools/meshToNurbs.py b/tools/meshToNurbs.py index 91d42f0..dba000a 100644 --- a/tools/meshToNurbs.py +++ b/tools/meshToNurbs.py @@ -9,23 +9,23 @@ def meshToNurbs(mesh,rebuild=False,spansU=0,spansV=0,prefix=''): ''' # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(mesh) - + # Convert poly to subdiv subd = mc.polyToSubdiv(mesh,ch=False,preserveVertexOrdering=True)[0] - + # Full crease corner vertices cornerIds = glTools.utils.mesh.getCornerVertexIds(mesh) mc.select([subd+'.vtx['+str(i)+']' for i in cornerIds]) mm.eval('FullCreaseSubdivSurface') - + # Convert subdiv to nurbs nurbsConvert = mc.subdToNurbs(subd,ch=False)[0] nurbs = mc.listRelatives(nurbs,c=True) - + # Cleanup mc.parent(nurbs,w=True) mc.delete(nurbsConvert) mc.delete(subd) - + # Return result return nurbs diff --git a/tools/mirrorDeformerWeights.py b/tools/mirrorDeformerWeights.py index 83c8cb7..8e8e8a4 100644 --- a/tools/mirrorDeformerWeights.py +++ b/tools/mirrorDeformerWeights.py @@ -23,27 +23,27 @@ def mirrorWeights(mesh,deformer,axis='x',posToNeg=True,refMesh=''): # Check deformers if not mc.objExists(deformer): raise Exception('Deformer "'+deformer+'" does not exist!!') - + # Check refMesh if not refMesh: refMesh = mesh - + # Get symmetry table axisIndex = {'x':0,'y':1,'z':2}[axis] sTable = glTools.tools.symmetryTable.SymmetryTable() symTable = sTable.buildSymTable(refMesh,axisIndex) - + # Get current weights wt = glTools.utils.deformer.getWeights(deformer) mem = glTools.utils.deformer.getDeformerSetMemberIndices(deformer,mesh) - + # Mirror weights for i in [sTable.negativeIndexList,sTable.positiveIndexList][int(posToNeg)]: if mem.count(i) and mem.count(symTable[i]): wt[mem.index(symTable[i])] = wt[mem.index(i)] - + # Apply mirrored weights glTools.utils.deformer.setWeights(deformer,wt,mesh) - + def flipWeights(mesh,sourceDeformer,targetDeformer='',axis='x',refMesh=''): ''' Flip deformer weights @@ -65,25 +65,25 @@ def flipWeights(mesh,sourceDeformer,targetDeformer='',axis='x',refMesh=''): raise Exception('Traget deformer '+targetDeformer+' does not exist!!') if not targetDeformer: targetDeformer = sourceDeformer - + # Check refMesh if not refMesh: refMesh = mesh - + # Get mesh shape meshShape = mesh if mc.objectType(meshShape) == 'transform': meshShape = mc.listRelatives(mesh,s=True,ni=True)[0] - + # Get symmetry table axisIndex = {'x':0,'y':1,'z':2}[axis] symTable = glTools.tools.symmetryTable.SymmetryTable().buildSymTable(refMesh,axisIndex) - + # Get current weights wt = glTools.utils.deformer.getWeights(sourceDeformer,mesh) sourceMem = glTools.utils.deformer.getDeformerSetMemberIndices(sourceDeformer,meshShape) targetMem = glTools.utils.deformer.getDeformerSetMemberIndices(targetDeformer,meshShape) targetWt = [0.0 for i in range(len(targetMem))] - + # Mirror weights for i in sourceMem: if targetMem.count(symTable[i]): @@ -93,7 +93,7 @@ def flipWeights(mesh,sourceDeformer,targetDeformer='',axis='x',refMesh=''): pass else: print('Cant find sym index for '+str(i)) - + # Apply mirrored weights glTools.utils.deformer.setWeights(targetDeformer,targetWt,mesh) @@ -115,18 +115,18 @@ def copyWeights(sourceMesh,targetMesh,sourceDeformer,targetDeformer): raise Exception('Source mesh "'+sourceMesh+'" does not exist!!') if not mc.objExists(targetMesh): raise Exception('Target mesh "'+targetMesh+'" does not exist!!') - + # Check deformers if not mc.objExists(sourceDeformer): raise Exception('Source deformer "'+sourceDeformer+'" does not exist!!') if targetDeformer and not mc.objExists(targetDeformer): raise Exception('Target deformer "'+targetDeformer+'" does not exist!!') if not targetDeformer: targetDeformer = sourceDeformer - + # Compare vertex count if mc.polyEvaluate(sourceMesh,v=True) != mc.polyEvaluate(targetMesh,v=True): raise Exception('Source and Target mesh vertex counts do not match!!') - + # Copy weights wtList = glTools.utils.deformer.getWeights(sourceDeformer,sourceMesh) # Paste weights diff --git a/tools/mocapClip.py b/tools/mocapClip.py index 0311f1d..5a7b1e0 100644 --- a/tools/mocapClip.py +++ b/tools/mocapClip.py @@ -28,47 +28,47 @@ def createMocapClipsFromFbxWip(sourceDir,targetDir,skipUpToDate=False,skipExists # ========== # - Checks - # ========== - + # Check Source Directory if not os.path.isdir(sourceDir): raise Exception('Source directory "'+sourceDir+'" does not exist!') - + # ===================== # - Get FBX File List - # ===================== - + # Check Source Dir if not sourceDir.endswith('/'): sourceDir+='/' - + # Get All FBX Files clipFileList = None ####!!! clipFileList.sort() clipFileList.reverse() - + # ================= # - Process Clips - # ================= - + clipPathList = [] for clipFile in clipFileList: - + # Clear Scene mc.file(newFile=True,force=True,prompt=False) - + # Skip Directories if not os.path.isfile(clipFile): print('Invalid path "'+clipFile+'"! Skipping...') continue - + # Get Clip Name clipName = os.path.splitext(os.path.basename(clipFile))[0].split('.')[0] - + # Build New Clip Path clipPath = targetDir+'/'+clipName+'.mb' - + # Check Clip Path if os.path.isfile(clipPath): - + # Check Up To Date if skipUpToDate: if os.stat(clipFile).st_mtime < os.stat(clipPath).st_mtime: @@ -76,18 +76,18 @@ def createMocapClipsFromFbxWip(sourceDir,targetDir,skipUpToDate=False,skipExists continue else: print ('"'+clipName+'" is out of date! Regenerating clip...') - + # Check Existing if skipExistsing: print (clipName+' already exists! Skipping file...') continue - + # Print Status print ('Generating Clip "'+clipName+'" from '+clipFile+'...') - + # Import Clip File mc.file(clipFile,i=True,type="FBX",defaultNamespace=True) - + # Create Character Set mocap = glTools.nrig.rig.bipedMocap.BipedMocapRigRoll() try: @@ -95,32 +95,32 @@ def createMocapClipsFromFbxWip(sourceDir,targetDir,skipUpToDate=False,skipExists except: print('ERROR: Problem creating characterSet for clip "'+clipName+'"!') continue - + # ========================= # - Create Character Clip - # ========================= - + keys = mc.keyframe('Hips',q=True,tc=True) if not keys: print ('No animation on Hips! Skipping...') continue - + start = keys[0] end = keys[-1] clip = glTools.utils.clip.createClip(charSet,startTime=start,endTime=end,name=clipName) if not clip: continue - + # Export Clip print 'Exporting: '+clipName export = glTools.utils.clip.exportClip(clip,clipPath,force=True) - + # Update Result clipPathList.append(clipPath) - + # ================= # - Return Result - # ================= - + return clipPathList def createMocapClips(sourceDir,targetDir='',extList=['fbx'],skipUpToDate=False,skipExistsing=False): @@ -140,44 +140,44 @@ def createMocapClips(sourceDir,targetDir='',extList=['fbx'],skipUpToDate=False,s # ========== # - Checks - # ========== - + # Check Source Directory if not os.path.isdir(sourceDir): raise Exception('Source directory "'+sourceDir+'" does not exist!') - + extTypeMap = {} extTypeMap['fbx'] = 'FBX' extTypeMap['ma'] = 'mayaAscii' extTypeMap['mb'] = 'mayaBinary' - + # ================= # - Process Clips - # ================= - + # New File mc.file(newFile=True,force=True,prompt=False) - + clipPathList = [] clipFileList = os.listdir(sourceDir) clipFileList.sort() for clipFile in clipFileList: - + # Skip Directories if os.path.isdir(sourceDir+'/'+clipFile): continue - + # Get Clip Extension ext = os.path.splitext(clipFile)[1].lower()[1:] if not extList.count(ext): continue - + # Get Clip Name clipName = os.path.splitext(os.path.basename(clipFile))[0] - + # Build New Clip Path clipPath = targetDir+'/'+clipName+'.mb' - + # Check Clip Path if os.path.isfile(clipPath): - + # Check Up To Date if skipUpToDate: if os.stat(sourceDir+'/'+clipFile).st_mtime < os.stat(clipPath).st_mtime: @@ -185,43 +185,43 @@ def createMocapClips(sourceDir,targetDir='',extList=['fbx'],skipUpToDate=False,s continue else: print ('"'+clipName+'" is up out of date! Regenerating up to date clip.') - + # Check Existing if skipExistsing: print (clipName+' already exists! Skipping file...') continue - + # Print Status print ('Generating Clip "'+clipName+'"...') - + # Import Clip File mc.file(sourceDir+'/'+clipFile,i=True,type="FBX",defaultNamespace=True) - + # Create Character Set mocap = glTools.nrig.rig.bipedMocap.BipedMocapRigRoll() try: charSet = mocap.createCharSet('char','') except: print('ERROR: Problem creating characterSet for clip "'+clipName+'"!') - + # Create Character Clip start = mc.keyframe('Hips',q=True,tc=True)[0] end = mc.keyframe('Hips',q=True,tc=True)[-1] clip = glTools.utils.clip.createClip(charSet,startTime=start,endTime=end,name=clipName) if not clip: continue - + # Export Clip print 'Exporting: '+clipName export = glTools.utils.clip.exportClip(clip,clipPath,force=True) - + # Update Result clipPathList.append(clipPath) - + # Clear Scene mc.file(newFile=True,force=True,prompt=False) - + # ================= # - Return Result - # ================= - + return clipPathList def createSourceClipFile(sourceDir,setLatest=False): @@ -230,18 +230,18 @@ def createSourceClipFile(sourceDir,setLatest=False): # ========================== # - Check Source Directory - # ========================== - + if not os.path.isdir(sourceDir): raise Exception('Source directory "'+sourceDir+'" does not exist!') - + # ================= # - Get File List - # ================= - + sourceFileList = os.listdir(sourceDir) sourceClipList = [i for i in sourceFileList if i.startswith('sourceClips')] sourceFileList = [i for i in sourceFileList if not i.startswith('sourceClips')] - + # Get Existing Source Clip Versions if sourceClipList: sourceClipVersions = [int(i.split('.')[-2]) for i in sourceClipList] @@ -249,14 +249,14 @@ def createSourceClipFile(sourceDir,setLatest=False): newSourceVersion = '%03d' % (sourceClipVersions[-1] + 1) else: newSourceVersion = '001' - + # ====================== # - Build Source Scene - # ====================== - + # Clear Scene mc.file(newFile=True,force=True,prompt=False) - + # Import Source Files for sourceFile in sourceFileList: # Get Clip Name @@ -264,19 +264,19 @@ def createSourceClipFile(sourceDir,setLatest=False): print clipName # Import Clip File mc.file(sourceDir+'/'+sourceFile,i=True,type="mayaAscii",defaultNamespace=True) - + # Save Scene mc.file(rename=sourceDir+'/sourceClips.'+newSourceVersion+'.mb') mc.file(save=True,type='mayaBinary') - + # Update Latest if setLatest: mc.file(rename=sourceDir+'/sourceClips.latest.mb') mc.file(save=True,type='mayaBinary') - + # ================= # - Return Result - # ================= - + return diff --git a/tools/motionPath.py b/tools/motionPath.py index b24d98c..9076f8d 100644 --- a/tools/motionPath.py +++ b/tools/motionPath.py @@ -20,67 +20,67 @@ def createCurve(pt,start=None,end=None,inc=1): # ========== # - Checks - # ========== - + if not pt: raise Exception('No valid point provided! Unable to create motion path...') - + # Check Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) if end < start: raise Exception('Invalid time range! Start is greater than end.') - + # Check Increment if inc < 1: inc = 1 if inc > (end-start): raise Exception('Frame increment is greater than the time range!') - + # ===================== # - Build Motion Path - # ===================== - + hasEndPt = False - + # Initialize Motion Paths mc.currentTime(start) pos = glTools.utils.base.getPosition(pt) crv = mc.curve(p=[pos],d=1) crv = mc.rename(crv,pt+'_curve') - + # Track Paths for i in range(start+inc,end+1,inc): mc.currentTime(i) if i == end: hasEndPt = True pos = glTools.utils.base.getPosition(pt) mc.curve(crv,a=True,p=pos) - + # Ensure End Point if not hasEndPt: mc.currentTime(end) pos = glTools.utils.base.getPosition(pt) mc.curve(crv,a=True,p=pos) - + # Rebuild Motion Paths mc.rebuildCurve(crv,ch=False,rpo=True,rt=0,end=1,kr=2,kcp=True,kep=True) - + # ====================== # - Encode Motion Data - # ====================== - + # Encode Source Object Name mc.addAttr(crv,ln='sourceObject',dt='string') mc.setAttr(crv+'.sourceObject',pt,type='string') - + # Encode Motion Start/End mc.addAttr(crv,ln='motionStart') mc.setAttr(crv+'.motionStart',start) mc.addAttr(crv,ln='motionEnd') mc.setAttr(crv+'.motionEnd',end) - + # ================= # - Return Result - # ================= - + return crv def createCurves(ptList,start=None,end=None,inc=1): @@ -98,48 +98,48 @@ def createCurves(ptList,start=None,end=None,inc=1): # ========== # - Checks - # ========== - + if not ptList: raise Exception('No valid point list provided! Unable to creat motion path...') - + # Check Start/End if start == None: start = mc.playbackOptions(q=True,min=True) if end == None: end = mc.playbackOptions(q=True,max=True) if end < start: raise Exception('Invalid time range! Start is greater than end.') - + # Check Increment if inc < 1: inc = 1 if inc > (end-start): raise Exception('Frame increment is greater than the time range!') - + # ====================== # - Build Motion Paths - # ====================== - + hasEndPt = False - + # Initialize Motion Paths crvList = [] mc.currentTime(start) for pt in ptList: - + # Create Motion Path Curves pos = glTools.utils.base.getPosition(pt) crv = mc.curve(p=[pos],d=1) crv = mc.rename(crv,pt+'_curve') crvList.append(crv) - + # Encode Source Object Name mc.addAttr(crv,ln='sourceObject',dt='string') mc.setAttr(crv+'.sourceObject',pt,type='string') - + # Encode Motion Start/End mc.addAttr(crv,ln='motionStart') mc.setAttr(crv+'.motionStart',start) mc.addAttr(crv,ln='motionEnd') mc.setAttr(crv+'.motionEnd',end) - + # Track Paths for i in range(start+inc,end+1,inc): mc.currentTime(i) @@ -147,22 +147,22 @@ def createCurves(ptList,start=None,end=None,inc=1): for n in range(len(ptList)): pos = glTools.utils.base.getPosition(ptList[n]) mc.curve(crvList[n],a=True,p=pos) - + # Ensure End Point if not hasEndPt: mc.currentTime(end) for n in range(len(ptList)): pos = glTools.utils.base.getPosition(ptList[n]) mc.curve(crvList[n],a=True,p=pos) - + # Rebuild Motion Paths for crv in crvList: mc.rebuildCurve(crv,ch=False,rpo=True,rt=0,end=1,kr=2,kcp=True,kep=True) - + # ================= # - Return Result - # ================= - + return crvList def createAverageCurve(xformList,start=None,end=None,inc=1,prefix=''): @@ -181,32 +181,32 @@ def createAverageCurve(xformList,start=None,end=None,inc=1,prefix=''): # ========== # - Checks - # ========== - + # Xform list xformList = mc.ls(xformList,transforms=True) or [] if not xformList: raise Exception('No valid transforms specified!') - + # Prefix if not prefix: prefix = 'motionPath#' - + # ====================== # - Create Motion Path - # ====================== - + # Create Average Locator loc = mc.group(em=True,n=prefix) mc.pointConstraint(xformList,loc,mo=False) - + # Create Motion Path crv = createCurve(loc,start,end,inc) - + # Cleanup mc.delete(loc) - + # ================= # - Return Result - # ================= - + return crv def motionPathToKeys(path,obj=None,start=None,end=None): @@ -215,13 +215,13 @@ def motionPathToKeys(path,obj=None,start=None,end=None): # ========== # - Checks - # ========== - + # Check Path if not mc.objExists(path): raise Exception('Motion path curve "'+path+'" does not exist!') if not glTools.utils.curve.isCurve(path): raise Exception('Motion path curve "'+path+'" is not a valid curve!') - + # Check Keyframe Object if not obj: if not mc.attributeQuery('sourceObject',n=path,ex=True): @@ -230,7 +230,7 @@ def motionPathToKeys(path,obj=None,start=None,end=None): obj = mc.getAttr(path+'.sourceObject') if not mc.objExists(path): raise Exception('Motion path curve "'+path+'" does not exist!') - + # Check Start/End if start == None: if mc.attributeQuery('motionStart',n=path,ex=True): @@ -242,19 +242,19 @@ def motionPathToKeys(path,obj=None,start=None,end=None): end = mc.getAttr(path+'.motionEnd') else: end = mc.playbackOptions(q=True,max=True) - + # ================================== # - Set Keyframes from Motion Path - # ================================== - + # Get Target Space (Matrix) objMatrix = glTools.utils.matrix.fromList(mc.getAttr(obj+'.parentMatrix')) - + for i in range(start,end): - + # === print i - + def motionPathAimRotation(path,obj,upVector=None,start=None,end=None): ''' diff --git a/tools/namingConvention.py b/tools/namingConvention.py index 702021a..6365992 100644 --- a/tools/namingConvention.py +++ b/tools/namingConvention.py @@ -1,9 +1,9 @@ import re class NamingConvention( object ): - + def __init__(self): - + # Base Hierarchy self.base = {} self.base['all'] = 'all' @@ -15,14 +15,14 @@ def __init__(self): self.base['orientOffset'] = 'orientOffset' self.base['supermover'] = 'supermover' self.base['xform'] = 'xform' - + # Valid name elements self.namePattern = ['[a-z]{2}','[a-z]{3}\d{2}','[a-z]{2}\d{2}','[a-z]{3}'] self.elemCount = (3,5) - + # Delineator self.delineator = '_' - + # Side self.side = {} self.side['center'] = 'cn' @@ -37,7 +37,7 @@ def __init__(self): self.side['high'] = 'hi' self.side['low'] = 'lo' self.side['middle'] = 'md' - + # Part self.part = {} self.part['ankle'] = 'ank' @@ -87,7 +87,7 @@ def __init__(self): self.part['whisker'] = 'wsk' self.part['wing'] = 'wng' self.part['wrist'] = 'wst' - + # Sub Part self.subPart = {} self.subPart['ankle'] = 'an' @@ -140,7 +140,7 @@ def __init__(self): self.subPart['wire'] = 'wi' self.subPart['wireBase'] = 'wb' self.subPart['wrist'] = 'wr' - + # Node Type self.node = {} self.node['addDoubleLinear'] = 'adl' @@ -231,7 +231,7 @@ def __init__(self): self.node['vectorProduct'] = 'vpn' self.node['wire'] = 'wir' self.node['wrap'] = 'wrp' - + def getName(self,side='',part='',optSide='',subPart='',node='',optSideIndex=1,partIndex=1,subPartIndex=1): ''' Return a valid control name based on the provided input argument values @@ -260,7 +260,7 @@ def getName(self,side='',part='',optSide='',subPart='',node='',optSideIndex=1,pa if not self.side.has_key(optSide): raise UserInputError('Invalid otional side ("'+optSide+'") provided!') if subPart: if not self.subPart.has_key(subPart): raise UserInputError('Invalid sub-part name ("'+subPart+'") provided!') - + #--------------------- # Get index variables optSideInd = str(optSideIndex) @@ -269,7 +269,7 @@ def getName(self,side='',part='',optSide='',subPart='',node='',optSideIndex=1,pa if partIndex < 10: partInd = '0'+partInd subPartInd = str(subPartIndex) if subPartIndex < 10: subPartInd = '0'+subPartInd - + # Build name string1.00 #------------------- # Side @@ -293,9 +293,9 @@ def getName(self,side='',part='',optSide='',subPart='',node='',optSideIndex=1,pa nameStr += self.delineator # - # Node type if node: nameStr += self.node[node] - + return nameStr - + def isValid(self,name): ''' Compare a name string against the naming convention string patterns @@ -311,7 +311,7 @@ def isValid(self,name): if nameStrCount > self.elemCount[1]: print 'Name element count ('+str(nameStrCount)+') is higher than the maximum ('+str(self.elemCount[1])+') expected by the naming conventions (3-5)!' return False - + # Check prefix if nameElem[0] != re.search(self.namePattern[0],nameElem[0]).group(0): print 'Prefix string ("'+nameElem[0]+'") does not match naming convention pattern (xx)!' @@ -333,7 +333,7 @@ def isValid(self,name): if nameElem[-1] != re.search(self.namePattern[3],nameElem[-1]).group(0): print 'Suffix string ("'+nameElem[-1]+'") does not match naming convention pattern (xxx)!' return False - + # Build regular expression match string regExpStr = self.namePattern[0]+self.delineator # Prefix: Side regExpStr += self.namePattern[1]+self.delineator # Part @@ -342,19 +342,19 @@ def isValid(self,name): if nameStrCount > 4: regExpStr += self.namePattern[2]+self.delineator # OptionalSide / SubPart regExpStr += self.namePattern[-1] # Suffix: NodeType - + # Match name to expression string match = re.search(regExpStr,name) if not name == match.group(0): print 'Name string pattern does not match naming convention!' return False - + # Return result return True - + def appendName(self,name='',appendString='',stripNameSuffix=False,trimName=False): ''' - Return a string name based on an original name and an append string. There are options to + Return a string name based on an original name and an append string. There are options to maintain string element count to satisfy the naming convention rules. @param name: Original name string to append to @type name: str @@ -372,12 +372,12 @@ def appendName(self,name='',appendString='',stripNameSuffix=False,trimName=False # Check append string appendElem = appendString.split(self.delineator) appendStrCount = len(appendElem) - + # Determine string intersection point if trimName and (nameStrCount + appendStrCount) > self.elemCount[1]: maxNameIndex = self.elemCount[1] - appendStrCount else: maxNameIndex = nameStrCount - + # Build new name string newName = '' for i in range(maxNameIndex): @@ -385,10 +385,10 @@ def appendName(self,name='',appendString='',stripNameSuffix=False,trimName=False for i in range(appendStrCount-1): newName += appendElem[i]+self.delineator newName += appendElem[-1] - + # Return new name return newName - + def stripSuffix(self,name,delineator=''): ''' Return the portion of name minus the last element separated by the name delineator. @@ -408,7 +408,7 @@ def stripSuffix(self,name,delineator=''): newName = name.replace(self.delineator+suffix,'') # Return result return newName - + def stringIndex(self,index,padding=2): ''' Return the string equivalent for the specified iteger index. diff --git a/tools/pivotObject.py b/tools/pivotObject.py index ab84e86..0ccade7 100644 --- a/tools/pivotObject.py +++ b/tools/pivotObject.py @@ -4,7 +4,7 @@ import glTools.utils.channelState class PivotObject(object): - + def __init__(self): ''' Initializer for PivotObject class. @@ -20,7 +20,7 @@ def __init__(self): self.translateChannels = ['tx','ty','tz'] self.rotateChannels = ['rx','ry','rz'] self.transformChannels = ['tx','ty','tz','rx','ry','rz'] - + def create(self,ctrlList=[],pivotObj='',orientPivotControl=False,initializeCleanUpJob=True,constrainTranslate=True,constrainRotate=True,maintainPivotInfo=False): ''' This function will setup a pivotObject control, which will allow you to manipulate @@ -42,13 +42,13 @@ def create(self,ctrlList=[],pivotObj='',orientPivotControl=False,initializeClean ''' # Check for existing Pivot Object if mc.objExists(self.pivotControlName): self.kill() - + # Check control list for ctrl in ctrlList: if not mc.objExists(ctrl): raise UserInputError('Control object '+ctrl+' does not exists!') # Check pivot object if not mc.objExists(pivotObj): raise UserInputError('Pivot object '+pivotObj+' does not exists!') - + # Create pivot control pivCtrl = glTools.tools.controlBuilder.create('sphere',self.pivotControlName)['control'] pivGrp = glTools.utils.base.group(pivCtrl,0) @@ -57,12 +57,12 @@ def create(self,ctrlList=[],pivotObj='',orientPivotControl=False,initializeClean # Orient pivot control if orientPivotControl: mc.delete(mc.orientConstraint(pivotObj,pivGrp,mo=False)) - + # Set channelStates for pivot control and group glTools.utils.channelState.ChannelState().setFlags([0,0,0,0,0,0,0,0,0,1],[pivCtrl]) glTools.utils.channelState.ChannelState().setFlags([2,2,2,2,2,2,2,2,2,1],[pivGrp]) glTools.utils.channelState.ChannelState().set(1,[pivCtrl,pivGrp]) - + # Create constraints for ctrl in ctrlList: # Check translate channels @@ -81,13 +81,13 @@ def create(self,ctrlList=[],pivotObj='',orientPivotControl=False,initializeClean else : skipRotate = ['x','y','z'] # Generate parentConstraint mc.parentConstraint(pivCtrl,ctrl,skipTranslate=skipTranslate,skipRotate=skipRotate,mo=True) - + # Select pivot control mc.select(self.pivotControlName) - + # Setup kill scriptJob if initializeCleanUpJob: self.cleanUpJob(maintainPivotInfo) - + def cleanUp(self,maintainPivotInfo=False): ''' This function will remove and cleanup any nodes, controls and constraints generated by PivotObject.create() @@ -96,10 +96,10 @@ def cleanUp(self,maintainPivotInfo=False): ''' # Check pivot control exists if mc.objExists(self.pivotControlName): - + # Check maintain info if maintainPivotInfo: self.pivotLocator() - + # Get constraint/control lists controlList = [] constraintList = [] @@ -113,22 +113,22 @@ def cleanUp(self,maintainPivotInfo=False): controlTransforms[ctrl] = [] controlTransforms[ctrl].extend(mc.getAttr(ctrl+'.t')[0]) controlTransforms[ctrl].extend(mc.getAttr(ctrl+'.r')[0]) - + # Delete constraints and control mc.delete(mc.listConnections('PivotCONTROL',s=False,d=True,type='constraint')) mc.delete(self.pivotControlName) - + # Reapply control transform values transformChannels = self.translateChannels + self.rotateChannels for ctrl in controlTransforms.iterkeys(): for i in range(len(transformChannels)): try: mc.setAttr(ctrl+'.'+transformChannels[i],controlTransforms[ctrl][i]) except: pass - + # Delete control group if mc.objExists(self.pivotControlGrp): mc.delete(self.pivotControlGrp) - + def cleanUpJob(self,maintainPivotInfo=False): ''' Initializes a scriptJob that will run a function that will remove and cleanup any nodes, controls and constraints @@ -137,7 +137,7 @@ def cleanUpJob(self,maintainPivotInfo=False): @type maintainPivotInfo: bool ''' mm.eval('scriptJob -e "SelectionChanged" "python(\\\"PivotObject().cleanUp('+str(maintainPivotInfo)+')\\\")" -runOnce true') - + def pivotLocator(self): ''' Generates a pivotObject locator that will contain all necessary information (via attribute values) @@ -148,7 +148,7 @@ def pivotLocator(self): mc.group(n=self.pivotLocatorGrp,em=True) glTools.utils.channelState.ChannelState().setFlags([2,2,2,2,2,2,2,2,2,1],[self.pivotLocatorGrp]) glTools.utils.channelState.ChannelState().set(1,[self.pivotLocatorGrp]) - + # Create pivot locator #pivLoc = glTools.tools.controlBuilder.create('locator',self.pivotLocatorName) pivLoc = mc.group(n=self.pivotLocatorName,em=True) @@ -166,7 +166,7 @@ def pivotLocator(self): # Set pivot locator channel states glTools.utils.channelState.ChannelState().setFlags([2,2,2,2,2,2,2,2,2,1],[pivLoc,pivLocBuf]) glTools.utils.channelState.ChannelState().set(1,[pivLoc,pivLocBuf]) - + # Record Control List #--------------------- # Get affected control list @@ -189,5 +189,5 @@ def pivotLocator(self): mc.addAttr(pivLoc,ln='frame',at='float') mc.setAttr(pivLoc+'.frame',mc.currentTime(q=True)) mc.setAttr(pivLoc+'.frame',l=True) - + diff --git a/tools/pointFaceMesh.py b/tools/pointFaceMesh.py index f39fef7..f4e3daa 100644 --- a/tools/pointFaceMesh.py +++ b/tools/pointFaceMesh.py @@ -12,7 +12,7 @@ def pointFaceMesh(pointList,scale=0.05,combine=True,prefix='pointFace'): ptList = [] for point in pointList: ptList.append(glTools.utils.base.getPosition(point)) - + # Create face for each point faceList = [] vscale = scale * 0.5 @@ -21,15 +21,15 @@ def pointFaceMesh(pointList,scale=0.05,combine=True,prefix='pointFace'): face = mc.polyCreateFacet(p=[(pt[0],pt[1]+scale,pt[2]),(pt[0]+hscale,pt[1]-vscale,pt[2]),(pt[0]-hscale,pt[1]-vscale,pt[2])])[0] face = mc.rename(face,prefix+'_mesh') faceList.append(face) - + # Define return list mesh = faceList - + # Combine faces to single mesh if combine: mesh = mc.polyUnite(faceList,ch=False) mesh = [mc.rename(mesh[0],prefix+'_mesh')] - + # Return result return mesh @@ -40,7 +40,7 @@ def transformFaceMesh(transformList,faceAxis='y',scale=0.05,combine=True,prefix= faceAxis = faceAxis.lower() if not ['x','y','z'].count(faceAxis): raise Exception('Invalid axis "'+faceAxis+'"! Enter "x", "y" or "z".') - + # Define face vertex list if faceAxis == 'x': vtxList = [OpenMaya.MPoint(0,-scale,scale,1),OpenMaya.MPoint(0,scale,scale,1),OpenMaya.MPoint(0,scale,-scale,1),OpenMaya.MPoint(0,-scale,-scale,1)] @@ -48,28 +48,28 @@ def transformFaceMesh(transformList,faceAxis='y',scale=0.05,combine=True,prefix= vtxList = [OpenMaya.MPoint(-scale,0,scale,1),OpenMaya.MPoint(scale,0,scale,1),OpenMaya.MPoint(scale,0,-scale,1),OpenMaya.MPoint(-scale,0,-scale,1)] elif faceAxis == 'z': vtxList = [OpenMaya.MPoint(-scale,scale,0,1),OpenMaya.MPoint(scale,scale,0,1),OpenMaya.MPoint(scale,-scale,0,1),OpenMaya.MPoint(-scale,-scale,0,1)] - + # Create face for each transform faceList = [] for i in range(len(transformList)): - + # Get world space matrix tMatrix = glTools.utils.transform.getMatrix(transformList[i]) - + # Create face vtx = [v*tMatrix for v in vtxList] pts = [(vtx[0][0],vtx[0][1],vtx[0][2]),(vtx[1][0],vtx[1][1],vtx[1][2]),(vtx[2][0],vtx[2][1],vtx[2][2]),(vtx[3][0],vtx[3][1],vtx[3][2])] face = mc.polyCreateFacet(p=pts)[0] face = mc.rename(face,prefix+'_'+str(i)+'_mesh') faceList.append(face) - + # Define return list mesh = faceList - + # Combine faces to single mesh if combine: mesh = mc.polyUnite(faceList,ch=False) mesh = [mc.rename(mesh[0],prefix+'_mesh')] - + # Return result return mesh diff --git a/tools/pointSampleWeight.py b/tools/pointSampleWeight.py index aa4fcab..5552f9c 100644 --- a/tools/pointSampleWeight.py +++ b/tools/pointSampleWeight.py @@ -7,24 +7,24 @@ def pointSampleWeight(samplePt,pntList,weightCalc=[True,True,True],prefix=''): ''' # Check prefix if not prefix: prefix = 'triSampleWeight' - + # Get tri points posList = [ mc.xform(pntList[0],q=True,ws=True,rp=True), mc.xform(pntList[1],q=True,ws=True,rp=True), mc.xform(pntList[2],q=True,ws=True,rp=True) ] - + # Build pntFace mesh pntFace = mc.polyCreateFacet(p=posList,n=prefix+'_sample_mesh')[0] mc.setAttr(pntFace+'.inheritsTransform',0,l=True) - + # Attach triPt locator to pntFace mesh pntLoc = glTools.utils.mesh.locatorMesh(pntFace,prefix=prefix) - + # Attach follow pt followLoc = mc.spaceLocator(n=prefix+'_follow_locator')[0] followGeoCon = mc.geometryConstraint(pntFace,followLoc) followPntCon = mc.pointConstraint(samplePt,followLoc) - + # Calculate triArea triEdge1_pma = mc.createNode('plusMinusAverage',n=prefix+'_triEdge1Vec_plusMinusAverage') triEdge2_pma = mc.createNode('plusMinusAverage',n=prefix+'_triEdge2Vec_plusMinusAverage') @@ -34,21 +34,21 @@ def pointSampleWeight(samplePt,pntList,weightCalc=[True,True,True],prefix=''): mc.connectAttr(pntLoc[0]+'.worldPosition[0]',triEdge1_pma+'.input3D[1]',f=True) mc.connectAttr(pntLoc[2]+'.worldPosition[0]',triEdge2_pma+'.input3D[0]',f=True) mc.connectAttr(pntLoc[0]+'.worldPosition[0]',triEdge2_pma+'.input3D[1]',f=True) - + triArea_vpn = mc.createNode('vectorProduct',n=prefix+'_triArea_vectorProduct') mc.setAttr(triArea_vpn+'.operation',2) # Cross Product mc.connectAttr(triEdge1_pma+'.output3D',triArea_vpn+'.input1',f=True) mc.connectAttr(triEdge2_pma+'.output3D',triArea_vpn+'.input2',f=True) - + triArea_dist = mc.createNode('distanceBetween',n=prefix+'_triArea_distanceBetween') mc.connectAttr(triArea_vpn+'.output',triArea_dist+'.point1',f=True) - + # Calculate triPt weights for i in range(3): - + # Check weight calculation (bool) if weightCalc[i]: - + # Calculate triArea pntEdge1_pma = mc.createNode('plusMinusAverage',n=prefix+'_pt'+str(i)+'Edge1Vec_plusMinusAverage') pntEdge2_pma = mc.createNode('plusMinusAverage',n=prefix+'_pt'+str(i)+'Edge2Vec_plusMinusAverage') @@ -58,21 +58,21 @@ def pointSampleWeight(samplePt,pntList,weightCalc=[True,True,True],prefix=''): mc.connectAttr(followLoc+'.worldPosition[0]',pntEdge1_pma+'.input3D[1]',f=True) mc.connectAttr(pntLoc[(i+2)%3]+'.worldPosition[0]',pntEdge2_pma+'.input3D[0]',f=True) mc.connectAttr(followLoc+'.worldPosition[0]',pntEdge2_pma+'.input3D[1]',f=True) - + pntArea_vpn = mc.createNode('vectorProduct',n=prefix+'_pt'+str(i)+'Area_vectorProduct') mc.setAttr(pntArea_vpn+'.operation',2) # Cross Product mc.connectAttr(pntEdge1_pma+'.output3D',pntArea_vpn+'.input1',f=True) mc.connectAttr(pntEdge2_pma+'.output3D',pntArea_vpn+'.input2',f=True) - + pntArea_dist = mc.createNode('distanceBetween',n=prefix+'_pt'+str(i)+'Area_distanceBetween') mc.connectAttr(pntArea_vpn+'.output',pntArea_dist+'.point1',f=True) - + # Divide ptArea by triArea to get weight pntWeight_mdn = mc.createNode('multiplyDivide',n=prefix+'_pt'+str(i)+'Weight_multiplyDivide') mc.setAttr(pntWeight_mdn+'.operation',2) # Divide mc.connectAttr(pntArea_dist+'.distance',pntWeight_mdn+'.input1X',f=True) mc.connectAttr(triArea_dist+'.distance',pntWeight_mdn+'.input2X',f=True) - + # Add weight attribute to pntLoc mc.addAttr(pntLoc[i],ln='weight',min=0.0,max=1.0,dv=0.0) mc.connectAttr(pntWeight_mdn+'.outputX',pntLoc[i]+'.weight',f=True) @@ -80,6 +80,6 @@ def pointSampleWeight(samplePt,pntList,weightCalc=[True,True,True],prefix=''): # Group mesh locators pntLoc_grp = mc.group(pntLoc,n=prefix+'_3Point_grp') mc.parent(pntFace,pntLoc_grp) - + # Return result return [pntLoc,pntFace,pntLoc_grp] diff --git a/tools/polyEdgeCurve.py b/tools/polyEdgeCurve.py index 5c38fa2..c6932e6 100644 --- a/tools/polyEdgeCurve.py +++ b/tools/polyEdgeCurve.py @@ -41,22 +41,22 @@ def buildEdgeCurves(edges,name,color=None): # Get Edges edges = mc.filterExpand(ex=True,sm=32) # Poly Edges if not edges: raise Exception('Invalid or empty edge list!') - + # Get Master Group masterGrp = buildMasterCurveGroup('edgeCurveGroup') - + # Get Curve Group curveGrp = buildCurveGroup(name,color) try: mc.parent(curveGrp,masterGrp) except: pass - + # Build Edge Curves crvList = [] for edge in edges: crv = mc.polyToCurve(edge,form=2,degree=1)[0] for at in 'trs': mc.setAttr(crv+'.'+at,l=True,cb=False) mc.parent(crv,curveGrp) - + # Return Result return curveGrp @@ -68,15 +68,15 @@ def buildEdgeCurvesUI(): window = 'buildEdgeCurvesUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Build PolyEdge Curves',s=True) - + # Layout CL = mc.columnLayout() - + # UI Elements mc.textFieldGrp('buildEdgeCurves_nameTFG',label='Curve Group Name',text='',editable=True) mc.colorIndexSliderGrp('buildEdgeCurves_colorCISG',label="Curve Color",min=1,max=32,value=16) mc.button('buildEdgeCurvesB',l='Create',w=390,c='glTools.tools.polyEdgeCurve.buildEdgeCurvesFromUI()') - + # Show Window mc.window(window,e=True,wh=[392,64]) mc.showWindow(window) @@ -91,11 +91,11 @@ def buildEdgeCurvesFromUI(): if not edges: print('Invalid Selection! Select polygon edges and run again...') return - + # Get UI Parameters name = mc.textFieldGrp('buildEdgeCurves_nameTFG',q=True,text=True) color = mc.colorIndexSliderGrp('buildEdgeCurves_colorCISG',q=True,v=True) - 1 - + # Build Edge Curves crvGrp = buildEdgeCurves(edges,name,color) mc.select(crvGrp) diff --git a/tools/poseSpace.py b/tools/poseSpace.py index 987ea3d..53fea3e 100644 --- a/tools/poseSpace.py +++ b/tools/poseSpace.py @@ -32,7 +32,7 @@ def poseDrivenAttr( poseTransform, # ========== # - Checks - # ========== - + axisList = ['x','y','z'] #,'+x','+y','+z','-x','-y','-z'] axisVector = { 'x':[1,0,0], 'y':[0,1,0], @@ -43,20 +43,20 @@ def poseDrivenAttr( poseTransform, #'-x':[-1,0,0], #'-y':[0,-1,0], #'-z':[0,0,-1] } - + # Check pose transform if not mc.objExists(poseTransform): raise Exception('PoseTransform "'+poseTransform+'" does not exist!') - + # Check target attribute if not mc.objExists(targetAttr): raise Exception('Target attribute "'+targetAttr+'" does not exist!') - + # Check reference axis poseAxis = poseAxis.lower() if not poseAxis in axisList: raise Exception('Invalid pose axis! Valid pose axis values are "x" "y" and "z"!!') - + # Check up axis if upAxis: upAxis = upAxis.lower() @@ -64,155 +64,155 @@ def poseDrivenAttr( poseTransform, raise Exception('Invalid up axis! Valid up axis values are "x" "y" and "z"!!') if upAxis == poseAxis: raise Exception('Pose axis and Up axis must be unique!!') - + # Check arclen if arclen: if not mc.pluginInfo('glToolsTools',q=True,l=True): try: mc.loadPlugin('glToolsTools') except: raise Exception('Error loading plugin glToolsTools!!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(poseTransform) - + # ================================== # - Create PoseReference Transform - # ================================== - + if not poseReference: poseReference = mc.duplicate(poseTransform,parentOnly=True,n=prefix+'_poseReference')[0] - + # Add poseTransform message attribute mc.addAttr(poseReference,ln='poseTransform',at='message') mc.connectAttr(poseTransform+'.message',poseReference+'.poseTransform',f=True) - + # ==================================== # - Create vector comparison network - # ==================================== - + poseVector = axisVector[poseAxis] poseResultAttr = '' - + if arclen: - + # Pose vector arc distance pose_arcDist = mc.createNode('arcDistance',n=prefix+'_pose_arcDistance') mc.connectAttr(poseTransform+'.worldMatrix[0]',pose_arcDist+'.matrix1',f=True) mc.connectAttr(poseReference+'.worldMatrix[0]',pose_arcDist+'.matrix2',f=True) mc.setAttr(pose_arcDist+'.vector1',poseVector[0],poseVector[1],poseVector[2]) mc.setAttr(pose_arcDist+'.vector2',poseVector[0],poseVector[1],poseVector[2]) - + # Set Pose Result poseResultAttr = pose_arcDist+'.arcDistance' - + else: - + # - Pose Transform Vector poseVecDotProduct = mc.createNode('vectorProduct',n=prefix+'_poseVector_vectorProduct') mc.setAttr(poseVecDotProduct+'.operation',3) # Vector Matric Product mc.setAttr(poseVecDotProduct+'.input1',poseVector[0],poseVector[1],poseVector[2]) mc.setAttr(poseVecDotProduct+'.normalizeOutput',1) mc.connectAttr(poseTransform+'.worldMatrix[0]',poseVecDotProduct+'.matrix',f=True) - + # - Pose Reference Vector referenceVecDotProduct = mc.createNode('vectorProduct',n=prefix+'_referenceVector_vectorProduct') mc.setAttr(referenceVecDotProduct+'.operation',3) # Vector Matric Product mc.setAttr(referenceVecDotProduct+'.input1',poseVector[0],poseVector[1],poseVector[2]) mc.setAttr(referenceVecDotProduct+'.normalizeOutput',1) mc.connectAttr(poseReference+'.worldMatrix[0]',referenceVecDotProduct+'.matrix',f=True) - + # - Pose Vector Comparison poseVecCompare_dotProduct = mc.createNode('vectorProduct',n=prefix+'_vectorCompare_vectorProduct') mc.setAttr(poseVecCompare_dotProduct+'.operation',1) # Dot Product mc.setAttr(poseVecCompare_dotProduct+'.normalizeOutput',1) mc.connectAttr(poseVecDotProduct+'.output',poseVecCompare_dotProduct+'.input1',f=True) mc.connectAttr(referenceVecDotProduct+'.output',poseVecCompare_dotProduct+'.input2',f=True) - + # Set Pose Result poseResultAttr = poseVecCompare_dotProduct+'.output' - + # =============================== # - Check Pose Twist (UpVector) - # =============================== - + if upAxis: - + upVector = axisVector[upAxis] - + # Multiply Result poseResult_mdl = mc.createNode('multDoubleLinear',n=prefix+'_poseResult_multDoubleLinear') - + if arclen: - + # Up vector arc distance upVec_arcDist = mc.createNode('arcDistance',n=prefix+'_upVec_arcDistance') mc.connectAttr(poseTransform+'.worldMatrix[0]',upVec_arcDist+'.matrix1',f=True) mc.connectAttr(poseReference+'.worldMatrix[0]',upVec_arcDist+'.matrix2',f=True) mc.setAttr(upVec_arcDist+'.vector1',upVector[0],upVector[1],upVector[2]) mc.setAttr(upVec_arcDist+'.vector2',upVector[0],upVector[1],upVector[2]) - + # Invert values mc.connectAttr(upVec_arcDist+'.arcDistance',pose_arcDist_reverse+'.inputY',f=True) - + # Multiply Result mc.connectAttr(poseResultAttr,poseResult_mdl+'.input1',f=True) mc.connectAttr(pose_arcDist_reverse+'.outputY',poseResult_mdl+'.input2',f=True) - + else: - + # - Transform Up Vector poseUpVec_vectorProduct = mc.createNode('vectorProduct',n=prefix+'_upVecPose_vectorProduct') mc.setAttr(poseUpVec_vectorProduct+'.operation',3) # Vector Matric Product mc.setAttr(poseUpVec_vectorProduct+'.input1',upVector[0],upVector[1],upVector[2]) mc.setAttr(poseUpVec_vectorProduct+'.normalizeOutput',1) mc.connectAttr(poseTransform+'.worldMatrix[0]',poseUpVec_vectorProduct+'.matrix',f=True) - + # - Reference Up Vector refUpVec_vectorProduct = mc.createNode('vectorProduct',n=prefix+'_upVecReference_vectorProduct') mc.setAttr(refUpVec_vectorProduct+'.operation',3) # Vector Matric Product mc.setAttr(refUpVec_vectorProduct+'.input1',upVector[0],upVector[1],upVector[2]) mc.setAttr(refUpVec_vectorProduct+'.normalizeOutput',1) mc.connectAttr(poseReference+'.worldMatrix[0]',refUpVec_vectorProduct+'.matrix',f=True) - + # - Up Vector Comparison upVecCompare_dotProduct = mc.createNode('vectorProduct',n=prefix+'_upVecCompare_vectorProduct') mc.setAttr(upVecCompare_dotProduct+'.operation',1) # Dot Product mc.setAttr(upVecCompare_dotProduct+'.normalizeOutput',1) mc.connectAttr(poseUpVec_vectorProduct+'.output',upVecCompare_dotProduct+'.input1') mc.connectAttr(refUpVec_vectorProduct+'.output',upVecCompare_dotProduct+'.input2') - + # Multiply Result mc.connectAttr(poseResultAttr,poseResult_mdl+'.input1',f=True) mc.connectAttr(upVecCompare_dotProduct+'.outputX',poseResult_mdl+'.input2',f=True) - + # Set pose compare attribute poseResultAttr = poseResult_mdl+'.output' - + # ======================= # - Remap output Values - # ======================= - + # Initialize variables remapValueNode = '' - + # Check remapValue node if remapValue: - + # Create remapValue node remapValueNode = mc.createNode('remapValue',n=prefix+'_remapValue') mc.connectAttr(poseResultAttr,remapValueNode+'.inputValue',f=True) poseResultAttr = remapValueNode+'.outValue' - + # ========================== # - Connect to Target Attr - # ========================== - + mc.connectAttr(poseResultAttr,targetAttr,f=True) - + # ================= # - Return Result - # ================= - + return [poseReference,remapValueNode] def addPoseData( poseNode, @@ -250,43 +250,43 @@ def addPoseData( poseNode, # ====================== # - Check Rig All Node - # ====================== - + # Check poseNode if not mc.objExists(poseNode): raise Exception('Pose node "'+poseNode+'" does not exist!') - + # Check PoseAttr if mc.attributeQuery(poseAttr,node=poseNode,exists=True): raise Exception('Pose attribute "'+poseNode+'.'+poseAttr+'" already exists!') - + # ================== # - Check PoseData - # ================== - + # Define PoseData Attribute poseDataAttr = 'poseData' - + # Add PoseData Attribute (multi) if not mc.attributeQuery(poseDataAttr,node=poseNode,exists=True): mc.addAttr(poseNode,ln=poseDataAttr,m=True,dv=-2) - + # ====================== # - Add PoseData Entry - # ====================== - + # Get next available poseData index poseDataIndex = mc.getAttr(poseNode+'.'+poseDataAttr,s=True) - + # Initialize poseData at current index mc.setAttr(poseNode+'.'+poseDataAttr+'['+str(poseDataIndex)+']',0) - + # Alias attribute mc.aliasAttr(poseAttr,poseNode+'.'+poseDataAttr+'['+str(poseDataIndex)+']') - + # ==================== # - Connect PoseData - # ==================== - + pose = glTools.tools.poseSpace.poseDrivenAttr( poseTransform=poseTransform, poseReference=poseReference, poseAxis=poseAxis, @@ -295,9 +295,9 @@ def addPoseData( poseNode, remapValue=remapValue, arclen=arclen, prefix=prefix ) - + # ================= # - Return Result - # ================= - + return poseNode+'.'+poseAttr diff --git a/tools/prankWindow.py b/tools/prankWindow.py index e642f9d..d65079e 100644 --- a/tools/prankWindow.py +++ b/tools/prankWindow.py @@ -9,15 +9,15 @@ def prankWindow(hardcoreMode=0): # Reset UI try: mc.deleteUI("prankWindow") except: pass - + # Create Window window = mc.window("prankWindow") mainLayout = mc.columnLayout("mainLayout", adj=1, p=window) mc.button("Disconnect", c='maya.close(); maya = socket.socket(socket.AF_INET, socket.SOCK_STREAM)', p=mainLayout) - + # Duplicate the following line to create quick connection shortcuts here mc.button("Connect: Nilouco-pc", c='maya.connect(("nilouco-pc or IP address here",12543))', p=mainLayout) - + # Do your stuff! mc.separator(h=10, p=mainLayout) mc.button("minimizeApp", c='maya.send("minimizeApp")', p=mainLayout) @@ -45,13 +45,13 @@ def prankWindow(hardcoreMode=0): mc.button("Open Help (F1)", c="maya.send('Help')", p=mainLayout) mc.button("Play forward timeline", c="maya.send('playButtonForward')", p=mainLayout) mc.button("Play backwards timeline", c="maya.send('playButtonBackward')", p=mainLayout) - + # Hardcore ?! mc.separator(h=10, p=mainLayout) mc.button("NEW SCENE", c='maya.send("file -new -f")', en=hardcoreMode, p=mainLayout) mc.button("CLOSE MAYA", c='maya.send("quit -f")', en=hardcoreMode, p=mainLayout) mc.button("SHOW HOTBOX", c='maya.send("hotBox")', en=hardcoreMode, p=mainLayout) mc.button("OPEN NOTEPAD", c="maya.send('system \"start notepad\"')", en=hardcoreMode, p=mainLayout) - + # Display window mc.showWindow(window) diff --git a/tools/proxyMesh.py b/tools/proxyMesh.py index bf9683c..9390c74 100644 --- a/tools/proxyMesh.py +++ b/tools/proxyMesh.py @@ -28,7 +28,7 @@ def isProxyBound(proxy): if not glTools.utils.mesh.isMesh(proxy): return False # Return Result return True - + def proxyParent(proxyMesh,joint): ''' Parent a proxy mesh shape to a specified parent joint @@ -42,28 +42,28 @@ def proxyParent(proxyMesh,joint): raise Exception('Proxy mesh "'+proxyMesh+'" does not exist!') if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') - + # Get Proxy Shape(s) proxyShapes = [] if glTools.utils.transform.isTransform(proxyMesh): proxyShapes = mc.listRelatives(proxyMesh,s=True,ni=True,pa=True) elif str(mc.objectType(proxyMesh)) in ['mesh','nurbsSurface']: proxyShapes = [str(proxyMesh)] - + # Parent Proxy Shapes to Joint for i in range(len(proxyShapes)): proxyShapes[i] = glTools.utils.shape.parent(proxyShapes[i],joint)[0] glTools.utils.base.displayOverride(proxyShapes[i],overrideEnable=1,overrideDisplay=2,overrideLOD=0) # Delete Old Transform mc.delete(proxyMesh) - + # Tag Shapes proxyAttr = 'proxyJoint' for shape in proxyShapes: if not mc.objExists(shape+'.'+proxyAttr): mc.addAttr(shape,ln=proxyAttr,dt='string') mc.setAttr(shape+'.'+proxyAttr,joint,type='string',l=True) - + # Return Result return proxyShapes @@ -76,16 +76,16 @@ def proxyConstraint(proxyGeo,deleteConstraint=False): # Checks if not isProxyBound(proxyGeo): raise Exception('Object "'+proxyGeo+'" is not a valid proxy bounds object!') - + # Get Target Joint joint = mc.getAttr(proxyGeo+'.jointProxy') # Get Proxy Parent proxyGrp = mc.listRelatives(proxyGeo,p=True,pa=True)[0] - + # Create Constraint pCon = mc.parentConstraint(joint,proxyGrp,n=proxyGeo+'_parentConstraint') if deleteConstraint: mc.delete(pCon) - + # Return Result return pCon @@ -110,26 +110,26 @@ def proxyCylinder(joint,axis='x',radius=1.0,divisions=10,cutGeo=[]): else: jntLen = 0.1 if jntLen < 0.1: jntLen = 0.1 axis = glTools.utils.lib.axis_dict()[axis] - + # Build Cylinder Mesh proxy_cyl = mc.polyCylinder(ch=False,r=radius,h=abs(jntLen)*1.1,sx=divisions,sy=1,sz=0,ax=axis,rcp=0,cuv=0,n=joint+'_PROXY') proxy_cyl = proxy_cyl[0] - + # Adjust Pivot And Freeze Transforms mc.move(axis[0]*jntLen*0.5,axis[1]*jntLen*0.5,axis[2]*jntLen*0.5,proxy_cyl) mc.makeIdentity(proxy_cyl,apply=True,t=True) mc.xform(proxy_cyl,piv=[0,0,0]) - + # Create Proxy Group proxy_grp = glTools.utils.base.group(proxy_cyl) makeProxyBounds(proxy_cyl,joint=joint,cutGeo=cutGeo) - + # Constrain To Joint proxyConstraint(proxy_cyl) - + # Return Result return [proxy_grp,proxy_cyl] - + def proxyCylinder_subDiv(proxy_cyl,numV=5,numU=1): ''' Subdivide proxy cylinder mesh. @@ -151,13 +151,13 @@ def makeProxyBounds(mesh,joint=None,cutGeo=None): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is nat avalid mesh! Unable to create proxy bounds object...') - + # Add Joint Tag jointProxyAttr = 'jointProxy' if not mc.attributeQuery(jointProxyAttr,n=mesh,ex=True): mc.addAttr(mesh,ln=jointProxyAttr,dt='string') if joint: mc.setAttr(mesh+'.jointProxy',joint,type='string') - + # Set Display Override - Shading OFF shadingAttr = 'shading' if not mc.attributeQuery(shadingAttr,n=mesh,ex=True): @@ -166,16 +166,16 @@ def makeProxyBounds(mesh,joint=None,cutGeo=None): mc.setAttr(mesh+'.overrideEnabled',1) mc.setAttr(mesh+'.doubleSided',0) mc.setAttr(mesh+'.opposite',0) - + # Cut Geometry Attribute cutGeoAttr = 'shading' if not mc.attributeQuery(cutGeoAttr,n=mesh,ex=True): mc.addAttr(mesh,ln=cutGeoAttr,dt='string') if cutGeo: mc.setAttr(mesh+'.'+cutGeoAttr,str(cutGeo),type='string') - + # Set Colour glTools.utils.colorize.setColour(mesh) - + # Return Result return mesh @@ -187,19 +187,19 @@ def cutGeoAttr(proxyList): ''' # Define Attribute attr = 'cutGeometry' - + # Check Proxy List if not proxyList: raise Exception('Empty or invalid proxy list!') - + for proxy in proxyList: if mc.attributeQuery(attr,n=proxy,ex=True): print('Proxy bounds object "'+proxy+'" already has a "'+attr+'" attribute! Skipping...') continue - + # Add Cut Geometry Attribute mc.addAttr(proxy,ln=attr,dt='string') - + # Return Result return proxyList @@ -211,19 +211,19 @@ def addGeoAttr(proxyList): ''' # Define Attribute attr = 'addGeometry' - + # Check Proxy List if not proxyList: raise Exception('Empty or invalid proxy list!') - + for proxy in proxyList: if mc.attributeQuery(attr,n=proxy,ex=True): print('Proxy bounds object "'+proxy+'" already has a "'+attr+'" attribute! Skipping...') continue - + # Add Cut Geometry Attribute mc.addAttr(proxy,ln=attr,dt='string') - + # Return Result return proxyList @@ -235,20 +235,20 @@ def initialShadingGroupAttr(proxyList): ''' # Define Attribute attr = 'applyInitialShadingGroup' - + # Check Proxy List if not proxyList: raise Exception('Empty or invalid proxy list!') - + for proxy in proxyList: - + # Add InitialShadingGroup Attribute if not mc.attributeQuery(attr,n=proxy,ex=True): mc.addAttr(proxy,ln=attr,at='bool') - + # Apply InitialShadingGroup Attribute mc.setAttr(proxy+'.'+attr,1) - + # Return Result return proxyList @@ -264,13 +264,13 @@ def skeletonProxyCage(jntList,cutGeo=[]): # ========== # - Checks - # ========== - + # Check Boundary if not jntList: return for jnt in jntList: if not mc.objExists(jnt): raise Exception('Joint "'+jnt+'" does not exist!') - + # Check Cut Geometry if not cutGeo: result = mc.promptDialog( title='Set Cut Geo List', @@ -279,7 +279,7 @@ def skeletonProxyCage(jntList,cutGeo=[]): defaultButton='Set', cancelButton='Cancel', dismissString='Cancel' ) - + if result == 'Set': cutGeoStr = mc.promptDialog(q=True,text=True) if cutGeoStr.count(','): @@ -289,23 +289,23 @@ def skeletonProxyCage(jntList,cutGeo=[]): else: print 'No cut geometry provided! Exiting...' return - + # ======================== # - Build Proxy Geometry - # ======================== - + proxyMainGrp = 'PROXY_grp' if not mc.objExists(proxyMainGrp): proxyMainGrp = mc.group(em=True,n='PROXY_grp') - + # For Each Joint proxyGeoList = [] for jnt in jntList: - + # Check End Joint jntChildren = mc.ls(mc.listRelatives(jnt,ad=True),type='joint') #if not jntChildren: continue - + # Create Proxy Geo proxy = proxyCylinder( joint = jnt, axis = 'x', @@ -314,13 +314,13 @@ def skeletonProxyCage(jntList,cutGeo=[]): cutGeo = cutGeo ) proxyGrp = proxy[0] proxyGeo = proxy[1] - + # Parent to main Proxy Group mc.parent(proxyGrp,proxyMainGrp) - + # Append To Return List proxyGeoList.append(proxyGeo) - + # Return Result return proxyGeoList @@ -328,77 +328,77 @@ def proxyFitJoint(proxyGeo,joint='',axis='x'): ''' Fit the specified proxy geometry (mesh cylinder) to a given joint. If no joint is specified, use the joint specified by the proxy "jointProxy" attribute. - @param proxyGeo: Proxy geometry to to fit to the joint + @param proxyGeo: Proxy geometry to to fit to the joint @type proxyGeo: str - @param joint: Joint to fit the proxy geometry to. If empty, use the "jointProxy" string attribute value. + @param joint: Joint to fit the proxy geometry to. If empty, use the "jointProxy" string attribute value. @type joint: str - @param axis: Length-wise axis of the joint. + @param axis: Length-wise axis of the joint. @type axis: str ''' # ========== # - Checks - # ========== - + # Proxy Geo if not isProxyBound(proxyGeo): raise Exception('Object "'+proxyGeo+'" is not a valid proxy bound object!') - + # Joint if not joint: joint = mc.getAttr(proxyGeo+'.jointProxy') if not glTools.utils.joint.isJoint(joint): raise Exception('Object "'+joint+'" is not a valid joint!') - + # Axis axis = axis.lower() axisList = ['x','y','z'] if not axisList.count(axis): raise Exception('Invalid axis value! ("'+axis+'")') axisInd = axisList.index(axis) - + # ================ # - Fit To Joint - # ================ - + # Get Joint Length jntLen = glTools.utils.joint.length(joint) #jntLen = glTools.utils.mathUtils.mag(mc.getAttr(joint+'.t')[0]) jntEnd = mc.listRelatives(joint,c=True) if jntEnd: jntLen = mc.getAttr(jntEnd[0]+'.t'+axis) jntMat = glTools.utils.matrix.getMatrix(joint,local=False,time=None) - + print(jntLen) - + # For Each Vertex for i in range(mc.polyEvaluate(proxyGeo,v=True)): vtx = proxyGeo+'.vtx['+str(i)+']' - + # Get Position pos = mc.pointPosition(vtx) localPos = glTools.utils.matrix.vectorMatrixMultiply(pos,jntMat,transformAsPoint=True,invertMatrix=True) - - # Check joint relative position + + # Check joint relative position if localPos[axisInd] < (jntLen*0.5): localPos[axisInd] = -jntLen*0.1 elif localPos[axisInd] > (jntLen*0.5): localPos[axisInd] = jntLen*1.1 - + # Get new world position pos = glTools.utils.matrix.vectorMatrixMultiply(localPos,jntMat,transformAsPoint=True,invertMatrix=False) - + # Set Position mc.move(pos[0],pos[1],pos[2],vtx,ws=True,a=True) - + # ================= # - Return Result - # ================= - + return joint def proxyFitMesh(proxyGeo,boundaryMesh,boundaryOffset=0.0): ''' Fit the specified proxy geometry (mesh cylinder) to a given boundary mesh. - @param proxyGeo: Proxy geometry to to fit to mesh + @param proxyGeo: Proxy geometry to to fit to mesh @type proxyGeo: str @param boundaryMesh: Boundary mesh to fit proxy geo to. @type boundaryMesh: str @@ -408,16 +408,16 @@ def proxyFitMesh(proxyGeo,boundaryMesh,boundaryOffset=0.0): # ========== # - Checks - # ========== - + if not isProxyBound(proxyGeo): raise Exception('Object "'+proxyGeo+'" is not a valid proxy bound object!') if not mc.objExists(boundaryMesh): raise Exception('Boundary mesh "'+boundaryMesh+'" does not exist!') - + # Check Vertex Count vtxCount = mc.polyEvaluate(proxyGeo,v=True) #if vtxCount%2: raise Exception('Uneven number of vertices!') - + # Get Joint Details jntSt = mc.getAttr(proxyGeo+'.jointProxy') jntStPos = mc.xform(jntSt,q=True,ws=True,rp=True) @@ -427,24 +427,24 @@ def proxyFitMesh(proxyGeo,boundaryMesh,boundaryOffset=0.0): else: jntAxis = glTools.utils.transform.axisVector(jntSt,'x',normalize=True) jntEnPos = map(sum,zip(jntStPos,jntAxis)) - + # =============== # - Fit To Mesh - # =============== - + # Get Vertex Position List pntList = glTools.utils.base.getPointArray(proxyGeo) - + for i in range(vtxCount): - + # Get intersection source point #srcPt = jntEnPos #if i < (vtxCount/2): srcPt = jntStPos srcPt = glTools.utils.mathUtils.closestPointOnLine(pntList[i],jntStPos,jntEnPos,clampSegment=False) - + # Get intersection direction intersectVec = glTools.utils.mathUtils.normalizeVector(glTools.utils.mathUtils.offsetVector(srcPt,pntList[i])) - + # Get intersection point intersectPnt = glTools.utils.mesh.allIntersections( mesh = boundaryMesh, source = srcPt, @@ -452,20 +452,20 @@ def proxyFitMesh(proxyGeo,boundaryMesh,boundaryOffset=0.0): testBothDirections = False, maxDist = 9999, sort = True ) - + # Get intersection distance intersectDist = glTools.utils.mathUtils.distanceBetween(srcPt,intersectPnt[0]) - + # Offset Point #mc.move( intersectPnt[0][0],intersectPnt[0][1],intersectPnt[0][2],proxyGeo+'.vtx['+str(i)+']',ws=True,a=True ) #continue - + # Check intersection distance if len(intersectPnt) > 1: nextDistance = glTools.utils.mathUtils.distanceBetween(srcPt,intersectPnt[1]) if (nextDistance-intersectDist) < boundaryOffset: intersectDist = (intersectDist+nextDistance)/2 - + # Offset Point mc.move( srcPt[0] + (intersectVec[0]*(intersectDist+boundaryOffset)), srcPt[1] + (intersectVec[1]*(intersectDist+boundaryOffset)), @@ -486,7 +486,7 @@ def splitGeoToProxies(proxyList,meshList=[],close=True,offset=0.0): @type proxyList: list @param meshList: List of meshes that the proxy geometry will be extracted from @type meshList: list - @param close: Close proxy mesh border edges. + @param close: Close proxy mesh border edges. @type close: bool @param offset: The amount of normal offset to apply before creating each cut. @type offset: float @@ -494,7 +494,7 @@ def splitGeoToProxies(proxyList,meshList=[],close=True,offset=0.0): # ===================== # - Combine Mesh List - # ===================== - + combinedMesh = '' if len(meshList) == 1: # Duplicate Mesh @@ -512,53 +512,53 @@ def splitGeoToProxies(proxyList,meshList=[],close=True,offset=0.0): meshIntShapes = glTools.utils.shape.listIntermediates(meshDup) if meshIntShapes: mc.delete(meshIntShapes) meshDupList.append(meshDup) - + # Combine Duplicated Meshes combinedMesh = mc.polyUnite(meshDupList,ch=False,mergeUVSets=True)[0] - + # ==================== # - Split To Proxies - # ==================== - + proxyShapeList = [] for proxy in proxyList: - + # Duplicate Mesh cutMesh = mc.duplicate(combinedMesh,n=proxy+'Geo')[0] meshIntShapes = glTools.utils.shape.listIntermediates(cutMesh) if meshIntShapes: mc.delete(meshIntShapes) - + # Cut Mesh proxyMesh = cutToMesh(cutMesh,proxy,offset) - + # !!! - Boolean Method is Very SLOW, reverting back to cut method - !!! # #proxyDup = mc.duplicate(proxy,n=proxy+'_dup')[0] #proxyMesh = cutMeshBool(cutMesh,proxyDup) - + # Parent Shape to Joint proxyJoint = mc.getAttr(proxy+'.jointProxy') proxyShapes = proxyParent(proxyMesh,proxyJoint) - + # Encode Original Geometry proxyGeoAttr = 'proxyGeometry' for proxyShape in proxyShapes: if not mc.objExists(proxyShape+'.'+proxyGeoAttr): mc.addAttr(proxyShape,ln=proxyGeoAttr,dt='string') mc.setAttr(proxyShape+'.'+proxyGeoAttr,str(meshList),type='string',l=True) - + # Append Return List proxyShapeList.extend(proxyShapes) - + # ============ # - Clean Up - # ============ - + mc.delete(combinedMesh) - + # ================= # - Return Result - # ================= - + return proxyShapeList def addGeoToProxies(proxyList,meshList=[]): @@ -572,9 +572,9 @@ def addGeoToProxies(proxyList,meshList=[]): # ===================== # - Combine Mesh List - # ===================== - + combinedMesh = None - + if len(meshList) == 1: # Duplicate Mesh meshDup = mc.duplicate(meshList[0],n='duplicateMesh')[0] @@ -591,41 +591,41 @@ def addGeoToProxies(proxyList,meshList=[]): meshIntShapes = glTools.utils.shape.listIntermediates(meshDup) if meshIntShapes: mc.delete(meshIntShapes) meshDupList.append(meshDup) - + # Combine Duplicated Meshes combinedMesh = mc.polyUnite(meshDupList,ch=False,mergeUVSets=True)[0] - + # ================== # - Add To Proxies - # ================== - + proxyShapeList = [] for proxy in proxyList: - + # Duplicate Mesh proxyMesh = mc.duplicate(combinedMesh,n=proxy+'Geo')[0] - + # Parent Shape to Joint proxyJoint = mc.getAttr(proxy+'.jointProxy') proxyShapes = proxyParent(proxyMesh,proxyJoint) - + # Encode Original Geometry proxyGeoAttr = 'proxyGeometry' for proxyShape in proxyShapes: if not mc.objExists(proxyShape+'.'+proxyGeoAttr): mc.addAttr(proxyShape,ln=proxyGeoAttr,dt='string') mc.setAttr(proxyShape+'.'+proxyGeoAttr,str(meshList),type='string',l=True) - + # ============ # - Clean Up - # ============ - + mc.delete(combinedMesh) - + # ================= # - Return Result - # ================= - + return proxyShapeList def applyProxies(proxyList,offset=0.0): @@ -639,66 +639,66 @@ def applyProxies(proxyList,offset=0.0): # Check proxy list if not proxyList: proxyList = mc.ls('*.jointProxy',o=True) if not proxyList: return - + # Initialize Return List proxyShapeList = [] - + # Print Opening Message print '# --------- Applying Proxies (Cutting Geometry) -' - + # Build Each Proxy for proxy in proxyList: - + # Check Proxy if not mc.objExists(proxy): raise Exception('Proxy bound object "'+proxy+'" does not exist!') if not isProxyBound(proxy): print ('Object "'+proxy+'" is not a valid proxy bounds object! Skipping...') continue - + # Get Cut Geometry List cutGeo = mc.getAttr(proxy+'.cutGeometry') try: cutGeo = ast.literal_eval(cutGeo) except: pass if not cutGeo: raise Exception('No valid cut geometry list for proxy "'+proxy+'"!') - + # Get Add Geometry List addGeo = None if mc.attributeQuery('addGeometry',n=proxy,ex=True): addGeo = mc.getAttr(proxy+'.addGeometry') try: addGeo = ast.literal_eval(addGeo) except: pass - + # Get Joint Proxy joint = mc.getAttr(proxy+'.jointProxy') if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') - + print '# ------------ Generating Proxy Geometry for Joint "'+joint+'"' print '# --------------- Cutting Geometry: '+str(cutGeo) if addGeo: print '# --------------- Adding Geometry: '+str(addGeo) - + # Cut Geometry and Add Shapes to Joint proxyCutShapes = splitGeoToProxies([proxy],cutGeo,close=True,offset=offset) proxyShapeList.extend(proxyCutShapes) - + # Apply Initial Shading Group sgAttr = 'applyInitialShadingGroup' if mc.attributeQuery(sgAttr,n=proxy,ex=True): mc.sets(proxyCutShapes,fe='initialShadingGroup') - + # Add Geometry Shapes to Joint if addGeo: proxyAddShapes = addGeoToProxies([proxy],addGeo) proxyShapeList.extend(proxyAddShapes) - + if mc.attributeQuery(sgAttr,n=proxy,ex=True): mc.sets(proxyAddShapes,fe='initialShadingGroup') - + # Print Closing Message print '# --------- Proxy Geometry Generation Complete -' - + # Return Result return proxyShapeList @@ -712,15 +712,15 @@ def proxySkinWeights(mesh,tolerance=0.001): # Get mesh vertex list ptArray = glTools.utils.base.getMPointArray(mesh) ptCount = ptArray.length() - + # Get skinCluster skinCluster = glTools.utils.skinCluster.findRelatedSkinCluster(mesh) influenceList = mc.skinCluster(skinCluster,q=True,inf=True) - + # ========================= # - Generate Weights List - # ========================= - + # Initialize progress bar interupt = False gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') @@ -730,99 +730,99 @@ def proxySkinWeights(mesh,tolerance=0.001): isInterruptable=True, status='Generating Skin Weights for skinCluster "'+skinCluster+'"...', maxValue=len(influenceList) ) - + # Initialize Weight Dict infWtList = {} pt = OpenMaya.MPointOnMesh() for influence in influenceList: - + # Check progress escape if mc.progressBar(gMainProgressBar,q=True,isCancelled=True): interupt = True break mc.progressBar( gMainProgressBar,e=True,status='Generating Skin Weights for "'+skinCluster+'" influence: '+influence) - + # Find mesh shapes under influence infShapes = mc.listRelatives(influence,s=True,type='mesh',ni=True,pa=True) if not infShapes: print('No mesh shape found under influence joint "'+influence+'"!') mc.progressBar(gMainProgressBar,e=True,step=1) continue - + # Initialize influence weight array infWtList[influence] = [0.0 for i in range(ptCount)] - + # For Each Shape for infShape in infShapes: - + # Initialize influence shape intersector infIntersector = OpenMaya.MMeshIntersector() - + # Run Intersector create() method meshObj = glTools.utils.base.getMObject(infShape) meshMatrix = glTools.utils.matrix.getMatrix(influence) infIntersector.create(meshObj,meshMatrix) - + # Build influence weight array for p in range(ptCount): - + # Check weight if infWtList[influence][p]: continue - + # Get distance to closest vertex try: infIntersector.getClosestPoint(ptArray[p],pt,tolerance) except: continue - + # Set weight if below tolerance distance infWtList[influence][p] = 1.0 - + # Update progress bar mc.progressBar(gMainProgressBar,e=True,step=1) - + # End pregress bar mc.progressBar(gMainProgressBar,e=True,endProgress=True) - + # ==================== # - Set Skin Weights - # ==================== - + if not interupt: - + # Get component list mc.select(mesh) componentList = glTools.utils.component.getComponentStrList(mesh) componentSel = glTools.utils.selection.getSelectionElement(componentList,0) - + # Build influence index array infIndexArray = OpenMaya.MIntArray() influenceSetList = [i for i in influenceList if infWtList.keys().count(i)] for i in range(len(influenceSetList)): infIndex = glTools.utils.skinCluster.getInfluencePhysicalIndex(skinCluster,influenceSetList[i]) infIndexArray.append(infIndex) - + # Build master weight array wtArray = OpenMaya.MDoubleArray() oldWtArray = OpenMaya.MDoubleArray() for p in range(ptCount): for i in range(len(influenceSetList)): wtArray.append(infWtList[influenceSetList[i]][p]) - + # Get skinCluster function set skinFn = glTools.utils.skinCluster.getSkinClusterFn(skinCluster) - + # Clear Weights glTools.utils.skinCluster.clearWeights(mesh) - + # Set skinCluster weights skinFn.setWeights(componentSel[0],componentSel[1],infIndexArray,wtArray,False,oldWtArray) - + # Normalize Weights mc.skinPercent(skinCluster,normalize=True) - + # ================= # - Return Result - # ================= - + return skinCluster def proxySkinClusters(proxyList=[]): @@ -834,25 +834,25 @@ def proxySkinClusters(proxyList=[]): # ========== # - Checks - # ========== - + # Check Proxy List if not proxyList: proxyList = mc.ls('*.proxyJoint',o=True) - + if not proxyList: raise Exception('Invalid or empty proxy list!') - + # ==================================== # - Build SkinCluster Influence List - # ==================================== - + influenceList = {} - + for proxy in proxyList: - + # Get Influence from Proxy joint = mc.getAttr(proxy+'.proxyJoint') - + # Get Cut Geometry List proxyGeoAttr = 'proxyGeometry' proxyGeo = mc.getAttr(proxy+'.'+proxyGeoAttr) @@ -860,34 +860,34 @@ def proxySkinClusters(proxyList=[]): except: pass if not proxyGeo: raise Exception('No valid proxy geometry list for proxy "'+proxy+'"!') - + # For Each Geometry for geo in proxyGeo: - + # Check Influence List for Geo if not influenceList.has_key(geo): influenceList[geo] = [] - + # Append to Influence List influenceList[geo].append(str(joint)) - + # ====================== # - Build SkinClusters - # ====================== - + # For Each Geometry for geo in influenceList.iterkeys(): - + # Create SkinCluster mc.skinCluster(geo,influenceList[geo],tsb=True,mi=1,omi=False,n=geo+'_skinCluster') - + # Set Initial Weights proxySkinWeights(geo,tolerance=0.001) - + # =========== # - Cleanup - # =========== - + dagPose = mc.ls(type='dagPose') if dagPose: mc.delete(dagPose) @@ -907,7 +907,7 @@ def setCutGeometry(proxyList,cutGeo=[]): if not mc.objExists(proxy+'.cutGeometry'): print('Adding "cutGeometry" attribute to proxy bounds object "'+proxy+'"') cutGeoAttr([proxy]) - + # Check Cut Geometry List if not cutGeo: result = mc.promptDialog( title='Set Cut Geometry', @@ -916,12 +916,12 @@ def setCutGeometry(proxyList,cutGeo=[]): defaultButton='Set', cancelButton='Cancel', dismissString='Cancel' ) - + if result == 'Set': cutGeo = mc.promptDialog(q=True,text=True) if not cutGeo: print('No valid cut geometry list provided!') - + # Set Cut Geometry List for proxy in proxyList: mc.setAttr(proxy+'.cutGeometry',str(cutGeo),type='string') @@ -942,7 +942,7 @@ def setAddGeometry(proxyList,addGeo=[]): if not mc.objExists(proxy+'.addGeometry'): print('Adding "addGeometry" attribute to proxy bounds object "'+proxy+'"') addGeoAttr([proxy]) - + # Check Add Geometry List if not addGeo: result = mc.promptDialog( title='Set Add Geometry', @@ -951,12 +951,12 @@ def setAddGeometry(proxyList,addGeo=[]): defaultButton='Set', cancelButton='Cancel', dismissString='Cancel' ) - + if result == 'Set': addGeo = mc.promptDialog(q=True,text=True) if not addGeo: print('No valid add geometry list provided!') - + # Set Add Geometry List for proxy in proxyList: mc.setAttr(proxy+'.addGeometry',str(addGeo),type='string') @@ -969,7 +969,7 @@ def setCutGeoFromSel(): proxyList = [] cutGeoList = [] sel = mc.ls(sl=True) - + # For Each Object in Selection for obj in sel: # Check Proxy Bounds Object @@ -981,10 +981,10 @@ def setCutGeoFromSel(): cutGeoList.append(str(obj)) else: print ('WARNING: Object "'+obj+'" is not a proxy bounds object or a valid mesh!') - + # Set Cut Geometry setCutGeometry(proxyList,cutGeoList) - + # Return Result print ('Proxy List -') for proxy in proxyList: print ('\t'+proxy) @@ -999,7 +999,7 @@ def setAddGeoFromSel(): proxyList = [] addGeoList = [] sel = mc.ls(sl=True) - + # For Each Object in Selection for obj in sel: # Check Proxy Bounds Object @@ -1011,10 +1011,10 @@ def setAddGeoFromSel(): addGeoList.append(str(obj)) else: print ('WARNING: Object "'+obj+'" is not a proxy bounds object or a valid mesh!') - + # Set Cut Geometry setAddGeometry(proxyList,addGeoList) - + # Return Result print ('Proxy List -') for proxy in proxyList: print ('\t'+proxy) @@ -1029,7 +1029,7 @@ def setApplyInitialSGFromSel(): proxyList = [] addGeoList = [] sel = mc.ls(sl=True) - + # For Each Object in Selection for obj in sel: # Check Proxy Bounds Object @@ -1041,10 +1041,10 @@ def setApplyInitialSGFromSel(): addGeoList.append(str(obj)) else: print ('WARNING: Object "'+obj+'" is not a proxy bounds object or a valid mesh!') - + # Set Cut Geometry initialShadingGroupAttr(proxyList) - + # Return Result print ('Apply initialShadingGroup for -') for proxy in proxyList: print ('\t'+proxy) @@ -1062,31 +1062,31 @@ def cutToBoundingBox(mesh,boundingObject,offset=0.0): # ========== # - Checks - # ========== - + if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + if not mc.objExists(boundingObject): raise Exception('Bounding object "'+boundingObject+'" does not exist!') - + # ========================= # - Get Bounding Box Info - # ========================= - + bBox = glTools.utils.base.getMBoundingBox(boundingObject) - + center = bBox.center() minPt = bBox.min() min = [minPt[0]-offset,minPt[1]-offset,minPt[2]-offset] maxPt = bBox.max() max = [maxPt[0]+offset,maxPt[1]+offset,maxPt[2]+offset] - + # ============ # - Cut Mesh - # ============ - + # -Z mc.polyCut(mesh,ch=False,df=True,pc=[center[0],center[1],min[2]],ro=[0,0,0]) # +Z @@ -1114,49 +1114,49 @@ def cutToMesh(mesh,boundingObject,offset=0.0): # ========== # - Checks - # ========== - + # Check Mesh if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check Bounding Mesh if not mc.objExists(boundingObject): raise Exception('Bounding object "'+boundingObject+'" does not exist!') if not glTools.utils.mesh.isMesh(boundingObject): raise Exception('Bounding object "'+boundingObject+'" is not a valid mesh!') - + # ============ # - Cut Mesh - # ============ - + # Undo OFF mc.undoInfo(state=False) - + # Get face iterator faceIt = glTools.utils.mesh.getMeshFaceIter(boundingObject) - + # Cut Mesh at each Face faceIt.reset() while not faceIt.isDone(): - + # Get Face position and normal pt = faceIt.center(OpenMaya.MSpace.kWorld) n = OpenMaya.MVector() faceIt.getNormal(n,OpenMaya.MSpace.kWorld) - + faceIt.next() - + # Offset Cut Point n.normalize() pt += (n*offset) cutPt = [pt[0],pt[1],pt[2]] - + # ============================== # - Convert Normal to Rotation - # ============================== - + up = OpenMaya.MVector(0,1,0) # Check upVector if abs(n*up) > 0.9: up = OpenMaya.MVector(0,0,1) @@ -1166,21 +1166,21 @@ def cutToMesh(mesh,boundingObject,offset=0.0): aimAxis = '-z', upAxis = 'y' ) rotate = glTools.utils.matrix.getRotation(rotateMatrix) - + # Cut Mesh mc.polyCut(mesh,ch=False,df=True,pc=cutPt,ro=rotate) mc.polyCloseBorder(mesh,ch=False) - + # Set Selection mc.select(mesh) - + # Undo ON mc.undoInfo(state=True) - + # ================= # - Return Result - # ================= - + return mesh def cutMeshBool(mesh,boundingObject): @@ -1194,41 +1194,41 @@ def cutMeshBool(mesh,boundingObject): # ========== # - Checks - # ========== - + # Check Mesh if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check Bounding Mesh if not mc.objExists(boundingObject): raise Exception('Bounding object "'+boundingObject+'" does not exist!') if not glTools.utils.mesh.isMesh(boundingObject): raise Exception('Bounding object "'+boundingObject+'" is not a valid mesh!') - + # ============ # - Cut Mesh - # ============ - + # Get Prefix prefix = glTools.utils.stringUtils.stripSuffix(boundingObject) - + # Triangulate Bounding Mesh mc.polyTriangulate(boundingObject,ch=False) - + # Cut Mesh cutMesh = mc.polyBoolOp(mesh,boundingObject,op=3,n=prefix+'Cut') if not cutMesh: raise Exception('Boolean intersection failed!') cutMesh = mc.rename(cutMesh[0],prefix+'Geo') - + # Cleanup mc.polyCloseBorder(cutMesh,ch=False) - + # ================= # - Return Result - # ================= - + return cutMesh def freezeToJoint(proxyGeo): @@ -1240,24 +1240,24 @@ def freezeToJoint(proxyGeo): # Checks if not isProxyBound(proxyGeo): raise Exception('Object "'+proxyGeo+'" is not a valid proxy bounds object!') - + # Get Target Joint joint = mc.getAttr(proxyGeo+'.jointProxy') # Get Proxy Parent proxyGrp = mc.listRelatives(proxyGeo,p=True,pa=True)[0] - + # Match Joint Pivot piv = mc.xform(joint,q=True,ws=True,rp=True) mc.xform(proxyGrp,ws=True,piv=piv) mc.xform(proxyGeo,ws=True,piv=piv) - + # Freeze Transforms grpParent = mc.listRelatives(proxyGrp,p=True,pa=True) mc.parent(proxyGrp,joint) mc.makeIdentity(proxyGrp,apply=True,t=True,r=True,s=True) if grpParent: mc.parent(proxyGrp,grpParent[0]) else: mc.parent(proxyGrp,w=True) - + # Return Result return joint @@ -1272,7 +1272,7 @@ def mirrorProxy(proxy,axis='x'): # ========== # - Checks - # ========== - + if not mc.objExists(proxy): raise Exception('Proxy object "'+proxy+'" does not exist!') if not isProxyBound(proxy): @@ -1280,16 +1280,16 @@ def mirrorProxy(proxy,axis='x'): # Check Side Prefix if not proxy.startswith('lf') and not proxy.startswith('rt'): raise Exception('Proxy object "'+proxy+'" does not have a valid side prefix! ("lf_" or "rt_")') - + # Check Axis axis = axis.lower()[0] if not ['x','y','z'].count(axis): raise Exception('Invalid mirror axis! ("'+axis+'")') - + # =================== # - Duplicate Proxy - # =================== - + search = '' replace = '' if proxy.startswith('lf'): @@ -1300,14 +1300,14 @@ def mirrorProxy(proxy,axis='x'): replace = 'lf' else: raise Exception('Proxy object "'+proxy+'" does not have a valid side prefix! ("lf_" or "rt_")') - + # Duplicate Proxy mProxy = mc.duplicate(proxy)[0] - + # Duplicate Proxy Group proxyGrp = mc.listRelatives(proxy,p=True)[0] mProxyGrp = mc.duplicate(proxyGrp,po=True)[0] - + # Rename mProxyNew = proxy.replace(search,replace) if mc.objExists(mProxyNew): mc.delete(mProxyNew) @@ -1315,12 +1315,12 @@ def mirrorProxy(proxy,axis='x'): mProxyGrpNew = proxyGrp.replace(search,replace) if mc.objExists(mProxyGrpNew): mc.delete(mProxyGrpNew) mProxyGrp = mc.rename(mProxyGrp,mProxyGrpNew) - + # Retarget Joint joint = mc.getAttr(proxy+'.jointProxy') joint = joint.replace(search,replace) mc.setAttr(mProxy+'.jointProxy',joint,type='string') - + # Retarget Cut and Add Geo cutGeo = mc.getAttr(proxy+'.cutGeometry') addGeo = '[]' @@ -1336,16 +1336,16 @@ def mirrorProxy(proxy,axis='x'): addGeo = [geo.replace(search,replace) for geo in addGeo] if cutGeo: mc.setAttr(mProxy+'.cutGeometry',str(cutGeo),type='string') if addGeo: mc.setAttr(mProxy+'.addGeometry',str(addGeo),type='string') - + # ================ # - Mirror Proxy - # ================ - + # Position Proxy Grp to Joint if mc.objExists(joint): mirrorCon = mc.parentConstraint(joint,mProxyGrp) mc.delete(mirrorCon) - + # Mirror Proxy mProxy = mc.parent(mProxy,w=True)[0] mc.reorder(mProxy,f=True) @@ -1357,21 +1357,21 @@ def mirrorProxy(proxy,axis='x'): mc.setAttr(mProxy+'.opposite',0) piv = mc.xform(mProxyGrp,q=True,ws=True,sp=True) mc.xform(mProxy,ws=True,piv=piv) - + # Reverse Normal mc.polyNormal(mProxy,ch=0,normalMode=0) mc.polyNormalPerVertex(mProxy,unFreezeNormal=True) - + # Set Colour glTools.utils.colorize.setColour(mProxy) - + # Reconnect Shading Toggle mc.connectAttr(mProxy+'.shading',mProxy+'.overrideShading') - + # ================= # - Return Result - # ================= - + return mProxy def activeProxy(geo,joint): @@ -1381,76 +1381,76 @@ def activeProxy(geo,joint): # ========== # - Checks - # ========== - + if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') - + # ====================== # - Duplicate Geometry - # ====================== - + geoName = geo.split(':')[-1] prxGeo = mc.duplicate(geo)[0] prxGeo = mc.rename(prxGeo,geoName+'_proxy') - + # Delete Intermediate Shapes intShapes = glTools.utils.shape.listIntermediates(prxGeo) if intShapes: mc.delete(intShapes) - + # Unlock Attrs attrList = glTools.utils.lib.xform_list() for attr in attrList: mc.setAttr(prxGeo+'.'+attr,l=False) - + # Reset Local Space to Joint mc.parent(prxGeo,joint) mc.makeIdentity(prxGeo,apply=True,t=True,r=True,s=True) mc.parent(prxGeo,w=True) - + # Delete History mc.delete(prxGeo,ch=True) - + # ======================= # - Connect to Original - # ======================= - + proxyBS = mc.blendShape(geo,prxGeo,origin='world',n=prxGeo+'_blendShape')[0] proxyTarget = mc.listAttr(proxyBS+'.w',m=True)[0] mc.setAttr(proxyBS+'.'+proxyTarget,1.0,l=True) - + # ========================= # - Parent Shape to Joint - # ========================= - + proxyShapes = glTools.utils.shape.getShapes(prxGeo) for i in range(len(proxyShapes)): proxyShapes[i] = mc.parent(proxyShapes[i],joint,s=True,r=True)[0] glTools.utils.base.displayOverride(proxyShapes[i],overrideEnable=1,overrideDisplay=2,overrideLOD=0) - + # Delete old transform mc.delete(prxGeo) - + # ====================== # - Tag Proxy Geometry - # ====================== - + # Proxy Joint proxyJntAttr = 'proxyJoint' for proxyShape in proxyShapes: if not mc.objExists(proxyShape+'.'+proxyJntAttr): mc.addAttr(proxyShape,ln=proxyJntAttr,dt='string') mc.setAttr(proxyShape+'.'+proxyJntAttr,joint,type='string',l=True) - + # Proxy Geometry proxyGeoAttr = 'proxyGeometry' for proxyShape in proxyShapes: if not mc.objExists(proxyShape+'.'+proxyGeoAttr): mc.addAttr(proxyShape,ln=proxyGeoAttr,dt='string') mc.setAttr(proxyShape+'.'+proxyGeoAttr,geo,type='string',l=True) - + # ================= # - Return Result - # ================= - + return proxyShapes diff --git a/tools/rayCylinderIntersect.py b/tools/rayCylinderIntersect.py index 78907b4..6c42bd3 100644 --- a/tools/rayCylinderIntersect.py +++ b/tools/rayCylinderIntersect.py @@ -37,15 +37,15 @@ def intersect(c,r): ''' ''' result = 0 - + # Matrix and Inverse T = c.matrix() iT = T.inverse() - + # Point and Ray p = r.p*iT v = r.v*iT - + # Solve the 2D Equation for X and Y radii AapBb = (p.x*v.x) + (p.y*v.y) A2pB2 = (v.x*v.x) + (v.y*v.y) @@ -53,21 +53,21 @@ def intersect(c,r): if disc < 0: print('No intersection with the infinite cylinder!') return result - + s = math.sqrt(disc) inv_A2pB2 = 1.0/A2pB2 t1 = (-AapBb-s)*inv_A2pB2 t2 = (-AapBb+s)*inv_A2pB2 pt1 = p+v*t1 pt2 = p+v*t2 - + # Check Cylinder Bounds pt1v = (pt1.z>0) and (pt1.z<1) and (((pt1-p)*v)>0) pt2v = (pt2.z>0) and (pt2.z<1) and (((pt2-p)*v)>0) if not pt1v and not pt2v: print('No intersection with the finite cylinder!') return result - + # To World Space pt1 *= T pt2 *= T @@ -77,5 +77,5 @@ def intersect(c,r): if pt2v: mc.spaceLocator(p=[pt2.x,pt2.y,pt2.z]) result += 1 - + return result diff --git a/tools/removeReferenceEdits.py b/tools/removeReferenceEdits.py index f9f049e..824c4ab 100644 --- a/tools/removeReferenceEdits.py +++ b/tools/removeReferenceEdits.py @@ -8,37 +8,37 @@ def removeReferenceEditsUI(): ''' # Define Local Command Prefix cmdPrefix = 'import glTools.tools.removeReferenceEdits;reload(glTools.tools.removeReferenceEdits);glTools.tools.removeReferenceEdits.' - + # ================ # - Build Window - # ================ - + window = 'removeReferenceEditsUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Remove Reference Edits') - + # =============== # - UI Elements - # =============== - + # Layout FL = mc.formLayout() - + refListTXT = mc.text(label='Reference List') refListTSL = mc.textScrollList('refEdits_refListTSL',allowMultiSelection=False) nodeListTXT = mc.text(label='Node List') nodeListTSL = mc.textScrollList('refEdits_nodeListTSL',allowMultiSelection=True) nodeSearchTFG = mc.textFieldButtonGrp('refEdits_nodeSearchTFG',label='Node Search',buttonLabel='Clear',text='',cw=(1,80)) - + nodeSearchSEP = mc.separator(style='single') - + showNamespaceCBG = mc.checkBoxGrp('refEdits_showNamespaceCBG',numberOfCheckBoxes=1,label='Show Namespace',v1=False) showLongNamesCBG = mc.checkBoxGrp('refEdits_showLongNamesCBG',numberOfCheckBoxes=1,label='Show Long Names',v1=False) showSuccessEditsCBG = mc.checkBoxGrp('refEdits_showSuccessEditsCBG',numberOfCheckBoxes=1,label='Show Successful Edits',v1=True) showFailedEditsCBG = mc.checkBoxGrp('refEdits_showFailedEditsCBG',numberOfCheckBoxes=1,label='Show Failed Edits',v1=True) - + showDetailsSEP = mc.separator(style='single') - + # Edit Command Check Boxes parentCBG = mc.checkBoxGrp('refEdits_parentCBG',numberOfCheckBoxes=1,label='parent',v1=True) setAttrCBG = mc.checkBoxGrp('refEdits_setAttrCBG',numberOfCheckBoxes=1,label='setAttr',v1=True) @@ -46,49 +46,49 @@ def removeReferenceEditsUI(): delAttrCBG = mc.checkBoxGrp('refEdits_delAttrCBG',numberOfCheckBoxes=1,label='deleteAttr',v1=True) conAttrCBG = mc.checkBoxGrp('refEdits_conAttrCBG',numberOfCheckBoxes=1,label='connectAttr',v1=True) disconAttrCBG = mc.checkBoxGrp('refEdits_disconAttrCBG',numberOfCheckBoxes=1,label='disconnectAttr',v1=True) - + # Buttons printEditsAttrB = mc.button(label='Print Edit Attributes',c=cmdPrefix+'printNodeEditAttributes()') printEditsCmdsB = mc.button(label='Print Edit Commands',c=cmdPrefix+'printNodeEditCommands()') removeEditsB = mc.button(label='Remove Edits',c=cmdPrefix+'removeReferenceEditsFromUI()') closeB = mc.button(label='Close',c='mc.deleteUI("'+window+'")') - + # =============== # - Pop-up Menu - # =============== - + # Reference List mc.popupMenu(parent=refListTSL) mc.menuItem('Reload Reference',c=cmdPrefix+'reloadReferenceFromUI()') mc.menuItem('Unload Reference',c=cmdPrefix+'unloadReferenceFromUI()') mc.menuItem('Remove Reference',c=cmdPrefix+'removeReferenceFromUI()') mc.menuItem('Import Reference',c=cmdPrefix+'importReferenceFromUI()') - + # Node List mc.popupMenu(parent=nodeListTSL) mc.menuItem('Select',c=cmdPrefix+'selectNode()') mc.menuItem('Print Edit Attributes',c=cmdPrefix+'printNodeEditAttributes()') mc.menuItem('Print Edit Commands',c=cmdPrefix+'printNodeEditCommands()') - + # ================ # - UI Callbacks - # ================ - + loadNodesCmd = cmdPrefix+'loadNodeList()' - + # Select Reference mc.textScrollList(refListTSL,e=True,sc=loadNodesCmd) - + # Search Node Field mc.textFieldButtonGrp(nodeSearchTFG,e=True,cc=cmdPrefix+'filterNodeList()') mc.textFieldButtonGrp(nodeSearchTFG,e=True,bc=cmdPrefix+'clearSeachField()') - + # Show Details mc.checkBoxGrp(showNamespaceCBG,e=True,cc=loadNodesCmd) mc.checkBoxGrp(showLongNamesCBG,e=True,cc=loadNodesCmd) mc.checkBoxGrp(showSuccessEditsCBG,e=True,cc=loadNodesCmd) mc.checkBoxGrp(showFailedEditsCBG,e=True,cc=loadNodesCmd) - + # Edit Commands mc.checkBoxGrp(parentCBG,e=True,cc=loadNodesCmd) mc.checkBoxGrp(setAttrCBG,e=True,cc=loadNodesCmd) @@ -96,44 +96,44 @@ def removeReferenceEditsUI(): mc.checkBoxGrp(delAttrCBG,e=True,cc=loadNodesCmd) mc.checkBoxGrp(conAttrCBG,e=True,cc=loadNodesCmd) mc.checkBoxGrp(disconAttrCBG,e=True,cc=loadNodesCmd) - + # =============== # - Form Layout - # =============== - + mc.formLayout(FL,e=True,af=[(refListTXT,'top',5),(refListTXT,'left',5)],ap=[(refListTXT,'right',5,33)]) mc.formLayout(FL,e=True,af=[(refListTSL,'bottom',5),(refListTSL,'left',5)],ac=[(refListTSL,'top',5,refListTXT)],ap=[(refListTSL,'right',5,33)]) mc.formLayout(FL,e=True,af=[(nodeListTXT,'top',5)],ac=[(nodeListTXT,'left',5,refListTXT)],ap=[(nodeListTXT,'right',5,66)]) mc.formLayout(FL,e=True,af=[(nodeListTSL,'bottom',5)],ac=[(nodeListTSL,'left',5,refListTSL),(nodeListTSL,'top',5,nodeListTXT)],ap=[(nodeListTSL,'right',5,66)]) mc.formLayout(FL,e=True,af=[(nodeSearchTFG,'top',5),(nodeSearchTFG,'right',5)],ac=[(nodeSearchTFG,'left',5,nodeListTXT)]) - + mc.formLayout(FL,e=True,af=[(nodeSearchSEP,'right',5)],ac=[(nodeSearchSEP,'top',5,nodeSearchTFG),(nodeSearchSEP,'left',5,nodeListTXT)]) - + mc.formLayout(FL,e=True,af=[(showNamespaceCBG,'right',5)],ac=[(showNamespaceCBG,'top',5,nodeSearchSEP)]) mc.formLayout(FL,e=True,af=[(showLongNamesCBG,'right',5)],ac=[(showLongNamesCBG,'top',5,showNamespaceCBG)]) mc.formLayout(FL,e=True,af=[(showSuccessEditsCBG,'right',5)],ac=[(showSuccessEditsCBG,'top',5,showLongNamesCBG)]) mc.formLayout(FL,e=True,af=[(showFailedEditsCBG,'right',5)],ac=[(showFailedEditsCBG,'top',5,showSuccessEditsCBG)]) - + mc.formLayout(FL,e=True,af=[(showDetailsSEP,'right',5)],ac=[(showDetailsSEP,'top',5,showFailedEditsCBG),(showDetailsSEP,'left',5,nodeListTXT)]) - + mc.formLayout(FL,e=True,af=[(parentCBG,'right',5)],ac=[(parentCBG,'top',5,showDetailsSEP)]) mc.formLayout(FL,e=True,af=[(setAttrCBG,'right',5)],ac=[(setAttrCBG,'top',5,parentCBG)]) mc.formLayout(FL,e=True,af=[(addAttrCBG,'right',5)],ac=[(addAttrCBG,'top',5,setAttrCBG)]) mc.formLayout(FL,e=True,af=[(delAttrCBG,'right',5)],ac=[(delAttrCBG,'top',5,addAttrCBG)]) mc.formLayout(FL,e=True,af=[(conAttrCBG,'right',5)],ac=[(conAttrCBG,'top',5,delAttrCBG)]) mc.formLayout(FL,e=True,af=[(disconAttrCBG,'right',5)],ac=[(disconAttrCBG,'top',5,conAttrCBG)]) - + mc.formLayout(FL,e=True,af=[(printEditsAttrB,'right',5)],ac=[(printEditsAttrB,'bottom',5,printEditsCmdsB),(printEditsAttrB,'left',5,nodeListTSL)]) mc.formLayout(FL,e=True,af=[(printEditsCmdsB,'right',5)],ac=[(printEditsCmdsB,'bottom',5,removeEditsB),(printEditsCmdsB,'left',5,nodeListTSL)]) mc.formLayout(FL,e=True,af=[(removeEditsB,'right',5)],ac=[(removeEditsB,'bottom',5,closeB),(removeEditsB,'left',5,nodeListTSL)]) mc.formLayout(FL,e=True,af=[(closeB,'right',5),(closeB,'bottom',5)],ac=[(closeB,'left',5,nodeListTSL)]) - + # =============== # - Show Window - # =============== - + mc.showWindow(window) - + # Load Reference List loadReferenceList() @@ -181,28 +181,28 @@ def selectNode(): ''' Select node from reference edits UI. ''' - # Get Selected Ref Node + # Get Selected Ref Node refNode = mc.textScrollList('refEdits_refListTSL',q=True,si=True) if not refNode: return refNS = glTools.utils.reference.getNamespace(refNode[0])+':' - + # Get Selected Nodes nodeList = mc.textScrollList('refEdits_nodeListTSL',q=True,si=True) if not nodeList: return - + # Select Nodes selNodes = [] for node in nodeList: - + # Check Node editNode = node if not mc.objExists(node): node = node.split('|')[-1] if not mc.objExists(node): node = refNS+node if not mc.objExists(node): raise Exception('Reference edit node "'+editNode+'" not found!') - + # Append to Selection List selNodes.append(node) - + # Select Node if selNodes: mc.select(selNodes) @@ -217,21 +217,21 @@ def loadReferenceList(): def loadNodeList(): ''' ''' - # Get Selected Ref Node + # Get Selected Ref Node refNode = mc.textScrollList('refEdits_refListTSL',q=True,si=True) or [] - + # Check Ref Node if not refNode: # No Reference Selected, Clear Node List mc.textScrollList('refEdits_nodeListTSL',e=True,ra=True) return - + # Get Show Details showNamespace = mc.checkBoxGrp('refEdits_showNamespaceCBG',q=True,v1=True) showDagPath = mc.checkBoxGrp('refEdits_showLongNamesCBG',q=True,v1=True) successfulEdits = mc.checkBoxGrp('refEdits_showSuccessEditsCBG',q=True,v1=True) failedEdits = mc.checkBoxGrp('refEdits_showFailedEditsCBG',q=True,v1=True) - + # Get Edit Commands editCmd_parent = mc.checkBoxGrp('refEdits_parentCBG',q=True,v1=True) editCmd_setAttr = mc.checkBoxGrp('refEdits_setAttrCBG',q=True,v1=True) @@ -240,10 +240,10 @@ def loadNodeList(): editCmd_conAttr = mc.checkBoxGrp('refEdits_conAttrCBG',q=True,v1=True) editCmd_disconAttr = mc.checkBoxGrp('refEdits_disconAttrCBG',q=True,v1=True) if not (editCmd_parent or editCmd_setAttr or editCmd_addAttr or editCmd_delAttr or editCmd_conAttr or editCmd_disconAttr): - # No Edit Commands Checked, Clear Node List + # No Edit Commands Checked, Clear Node List mc.textScrollList('refEdits_nodeListTSL',e=True,ra=True) return - + # Get Reference Edit Nodes nodeList = glTools.utils.reference.getEditNodes( refNode[0], showNamespace=showNamespace, @@ -256,15 +256,15 @@ def loadNodeList(): deleteAttr=editCmd_delAttr, connectAttr=editCmd_conAttr, disconnectAttr=editCmd_disconAttr ) - + # Remove Duplicates and Sort nodeList = list(set([i for i in nodeList])) or [] nodeList.sort() - + # Apply Node List mc.textScrollList('refEdits_nodeListTSL',e=True,ra=True) for node in nodeList: mc.textScrollList('refEdits_nodeListTSL',e=True,a=node) - + # Filter List filterNodeList() @@ -274,11 +274,11 @@ def filterNodeList(): # Filter List nodeSearchStr = mc.textFieldButtonGrp('refEdits_nodeSearchTFG',q=True,text=True) if not nodeSearchStr: return - + # Get Node List nodeList = mc.textScrollList('refEdits_nodeListTSL',q=True,ai=True) if not nodeList: return - + # Check Negative Filter if nodeSearchStr.startswith('!'): if nodeSearchStr.startswith('!*'): @@ -294,7 +294,7 @@ def filterNodeList(): nodeList = list(set([i for i in nodeList if i.startswith(nodeSearchStr[:-1])])) else: nodeList = list(set([i for i in nodeList if nodeSearchStr in i])) - + # Apply Filtered Node List mc.textScrollList('refEdits_nodeListTSL',e=True,ra=True) for node in sorted(nodeList): mc.textScrollList('refEdits_nodeListTSL',e=True,a=node) @@ -306,13 +306,13 @@ def printNodeEditAttributes(): # Get Reference and Node Selection refList = mc.textScrollList('refEdits_refListTSL',q=True,si=True) or [] nodeList = mc.textScrollList('refEdits_nodeListTSL',q=True,si=True) or [] - + # Get Show Details showNamespace = mc.checkBoxGrp('refEdits_showNamespaceCBG',q=True,v1=True) showDagPath = mc.checkBoxGrp('refEdits_showLongNamesCBG',q=True,v1=True) successfulEdits = mc.checkBoxGrp('refEdits_showSuccessEditsCBG',q=True,v1=True) failedEdits = mc.checkBoxGrp('refEdits_showFailedEditsCBG',q=True,v1=True) - + # Get Edit Commands editCmd_parent = mc.checkBoxGrp('refEdits_parentCBG',q=True,v1=True) editCmd_setAttr = mc.checkBoxGrp('refEdits_setAttrCBG',q=True,v1=True) @@ -320,16 +320,16 @@ def printNodeEditAttributes(): editCmd_delAttr = mc.checkBoxGrp('refEdits_delAttrCBG',q=True,v1=True) editCmd_conAttr = mc.checkBoxGrp('refEdits_conAttrCBG',q=True,v1=True) editCmd_disconAttr = mc.checkBoxGrp('refEdits_disconAttrCBG',q=True,v1=True) - + # Get Edit Commands for refNode in refList: - + # Get Reference Namespace ns = '' if showNamespace: ns = glTools.utils.reference.getNamespace(refNode)+':' - + for node in nodeList: - + # Get Edit Attributes attrList = glTools.utils.reference.getEditAttrs( refNode, node, @@ -343,14 +343,14 @@ def printNodeEditAttributes(): deleteAttr=editCmd_delAttr, connectAttr=editCmd_conAttr, disconnectAttr=editCmd_disconAttr ) - + # Append Output List if attrList: - + # Remove Duplicates and Sort attrList = list(set(attrList)) attrList.sort() - + # Print Result print('\n=== Edit Attributes: '+node+' ===\n') for attr in attrList: print attr @@ -362,13 +362,13 @@ def printNodeEditCommands(): # Get Reference and Node Selection refList = mc.textScrollList('refEdits_refListTSL',q=True,si=True) or [] nodeList = mc.textScrollList('refEdits_nodeListTSL',q=True,si=True) or [] - + # Get Show Details showNamespace = mc.checkBoxGrp('refEdits_showNamespaceCBG',q=True,v1=True) showDagPath = mc.checkBoxGrp('refEdits_showLongNamesCBG',q=True,v1=True) successfulEdits = mc.checkBoxGrp('refEdits_showSuccessEditsCBG',q=True,v1=True) failedEdits = mc.checkBoxGrp('refEdits_showFailedEditsCBG',q=True,v1=True) - + # Get Edit Commands editCmd_parent = mc.checkBoxGrp('refEdits_parentCBG',q=True,v1=True) editCmd_setAttr = mc.checkBoxGrp('refEdits_setAttrCBG',q=True,v1=True) @@ -376,14 +376,14 @@ def printNodeEditCommands(): editCmd_delAttr = mc.checkBoxGrp('refEdits_delAttrCBG',q=True,v1=True) editCmd_conAttr = mc.checkBoxGrp('refEdits_conAttrCBG',q=True,v1=True) editCmd_disconAttr = mc.checkBoxGrp('refEdits_disconAttrCBG',q=True,v1=True) - + # Get Edit Commands for refNode in refList: - + # Get Reference Namespace ns = '' if showNamespace: ns = glTools.utils.reference.getNamespace(refNode)+':' - + for node in nodeList: cmdList = glTools.utils.reference.getEditCommands( refNode, ns+node, @@ -397,13 +397,13 @@ def printNodeEditCommands(): deleteAttr=editCmd_delAttr, connectAttr=editCmd_conAttr, disconnectAttr=editCmd_disconAttr ) - + # Append Output List if cmdList: - + # Remove Duplicates and Sort cmdList = list(set(cmdList)) - + # Print Result print('\n=== Edit Commands: '+node+' ===\n') for cmd in cmdList: print cmd @@ -415,15 +415,15 @@ def removeReferenceEditsFromUI(): # ======================= # - Get Details From UI - # ======================= - + # Get Reference and Node Selection refList = mc.textScrollList('refEdits_refListTSL',q=True,si=True) or [] nodeList = mc.textScrollList('refEdits_nodeListTSL',q=True,si=True) or [] - + # Get Edit Details successfulEdits = mc.checkBoxGrp('refEdits_showSuccessEditsCBG',q=True,v1=True) failedEdits = mc.checkBoxGrp('refEdits_showFailedEditsCBG',q=True,v1=True) - + # Get Edit Commands editCmd_parent = mc.checkBoxGrp('refEdits_parentCBG',q=True,v1=True) editCmd_setAttr = mc.checkBoxGrp('refEdits_setAttrCBG',q=True,v1=True) @@ -431,26 +431,26 @@ def removeReferenceEditsFromUI(): editCmd_delAttr = mc.checkBoxGrp('refEdits_delAttrCBG',q=True,v1=True) editCmd_conAttr = mc.checkBoxGrp('refEdits_conAttrCBG',q=True,v1=True) editCmd_disconAttr = mc.checkBoxGrp('refEdits_disconAttrCBG',q=True,v1=True) - + # Get Show Namespace showNamespace = mc.checkBoxGrp('refEdits_showNamespaceCBG',q=True,v1=True) - + # ========================== # - Remove Reference Edits - # ========================== - + for refNode in refList: - + # Check Reference Loaded refLoaded = glTools.utils.reference.isLoaded(refNode) if refLoaded: mc.file(unloadReference=refNode) - + # Get Reference Namespace ns = '' if not showNamespace: ns = glTools.utils.reference.getNamespace(refNode)+':' - + if not nodeList: - + # Remove All Reference Edits glTools.utils.reference.removeReferenceEdits( refNode, node='', @@ -462,9 +462,9 @@ def removeReferenceEditsFromUI(): deleteAttr=editCmd_delAttr, connectAttr=editCmd_conAttr, disconnectAttr=editCmd_disconAttr ) - + for node in nodeList: - + # Remove Node Edits glTools.utils.reference.removeReferenceEdits( refNode, ns+node, @@ -476,6 +476,6 @@ def removeReferenceEditsFromUI(): deleteAttr=editCmd_delAttr, connectAttr=editCmd_conAttr, disconnectAttr=editCmd_disconAttr ) - + # Reload Reference if refLoaded: mc.file(loadReference=refNode) diff --git a/tools/reorderAttr.py b/tools/reorderAttr.py index 61d8229..7b472b5 100644 --- a/tools/reorderAttr.py +++ b/tools/reorderAttr.py @@ -10,10 +10,10 @@ def reorderAttrUI(): window = 'reorderAttrUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Reorder Attributes') - + # Layout fl = mc.formLayout(numberOfDivisions=100) - + # UI Elements objTFB = mc.textFieldButtonGrp('reorderAttrTFB',label='',text='',buttonLabel='Load Selected',cw=[1,5]) attrTSL = mc.textScrollList('reorderAttrTSL', allowMultiSelection=True ) @@ -22,7 +22,7 @@ def reorderAttrUI(): moveTpB = mc.button(label='Move to Top', c='glTools.tools.reorderAttr.reorderAttrFromUI(2)' ) moveBtB = mc.button(label='Move to Bottom', c='glTools.tools.reorderAttr.reorderAttrFromUI(3)' ) cancelB = mc.button(label='Cancel', c='mc.deleteUI("'+window+'")' ) - + # Form Layout mc.formLayout(fl,e=True,af=[(objTFB,'left',5),(objTFB,'top',5),(objTFB,'right',5)]) mc.formLayout(fl,e=True,af=[(moveUpB,'left',5),(moveUpB,'right',5)],ac=[(moveUpB,'bottom',5,moveDnB)]) @@ -31,32 +31,32 @@ def reorderAttrUI(): mc.formLayout(fl,e=True,af=[(moveBtB,'left',5),(moveBtB,'right',5)],ac=[(moveBtB,'bottom',5,cancelB)]) mc.formLayout(fl,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) mc.formLayout(fl,e=True,af=[(attrTSL,'left',5),(attrTSL,'right',5)],ac=[(attrTSL,'top',5,objTFB),(attrTSL,'bottom',5,moveUpB)]) - + # UI callback commands mc.textFieldButtonGrp('reorderAttrTFB',e=True,bc='glTools.tools.reorderAttr.reorderAttrLoadSelected()') - + # Load selection sel = mc.ls(sl=1) if sel: reorderAttrLoadSelected() - - # Display UI + + # Display UI mc.showWindow(window) - + def reorderAttrLoadSelected(): ''' ''' # Load Selected to Text Field glTools.ui.utils.loadObjectSel('reorderAttrTFB') - + # Refresh attribute list reorderAttrRefreshList() - + def reorderAttrRefreshList(selList=[]): ''' ''' # Get object obj = mc.textFieldButtonGrp('reorderAttrTFB',q=True,text=True) - + # Get attr list udAttrList = mc.listAttr(obj,ud=True) cbAttrList = [] @@ -65,11 +65,11 @@ def reorderAttrRefreshList(selList=[]): tmpAttrList = mc.listAttr(obj,cb=True) if tmpAttrList: cbAttrList.extend(tmpAttrList) allAttrList = [i for i in udAttrList if cbAttrList.count(i)] - + # Update attribute text scroll list mc.textScrollList('reorderAttrTSL',e=True,ra=True) for attr in allAttrList: mc.textScrollList('reorderAttrTSL',e=True,a=attr) - + # Select list items selAttrList = [] if selList: selAttrList = list(set(selList).intersection(set(allAttrList))) @@ -84,19 +84,19 @@ def reorderAttrFromUI(dir): # Get UI info obj = mc.textFieldButtonGrp('reorderAttrTFB',q=True,text=True) attrList = mc.textScrollList('reorderAttrTSL',q=True,si=True) - + # Check object if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check attributes for attr in attrList: if not mc.objExists(obj+'.'+attr): raise Exception('Attribute "'+obj+'.'+attr+'" does not exist!') - + # Reorder Attributes for attr in attrList: - + if dir == 0: # Move Up glTools.utils.attribute.reorder(obj+'.'+attr,'up') if dir == 1: # Move Down @@ -105,10 +105,10 @@ def reorderAttrFromUI(dir): glTools.utils.attribute.reorder(obj+'.'+attr,'top') if dir == 3: # Move to Bottom glTools.utils.attribute.reorder(obj+'.'+attr,'bottom') - + # Refresh attribute list reorderAttrRefreshList(attrList) - + # Refresh UI channelBox = 'mainChannelBox' mc.channelBox(channelBox,e=True,update=True) diff --git a/tools/ribbon.py b/tools/ribbon.py index 13965c5..44491f9 100644 --- a/tools/ribbon.py +++ b/tools/ribbon.py @@ -17,14 +17,14 @@ def spine_ribbon(ptList,spans=0,joints=6,prefix='cn_spine'): # ========== # - Checks - # ========== - + if not ptList: raise Exception('Invalid point list!') if not prefix: prefix = 'cn_spine' - + # ======================== # - Build Spine Locators - # ======================== - + pointList = [glTools.utils.base.getPosition(pt) for pt in ptList] locList = [] lfLocList = [] @@ -39,40 +39,40 @@ def spine_ribbon(ptList,spans=0,joints=6,prefix='cn_spine'): locList.append(loc) lfLocList.append(lfLoc) rtLocList.append(rtLoc) - + # =========================== # - Build Spine Loft Curves - # =========================== - + # Build Curves lfCurve = glTools.utils.curve.createFromLocators(lfLocList,degree=1,attach=True,prefix=prefix+'A') rtCurve = glTools.utils.curve.createFromLocators(rtLocList,degree=1,attach=True,prefix=prefix+'B') - + # Get Curve Shapes lfCurveShape = mc.listRelatives(lfCurve,s=True,pa=True)[0] rtCurveShape = mc.listRelatives(rtCurve,s=True,pa=True)[0] glTools.utils.shape.createIntermediate(lfCurveShape) glTools.utils.shape.createIntermediate(rtCurveShape) - + # Rebuild Curves if not spans: spans = len(ptList) - 1 lfRebuildCrv = mc.rebuildCurve(lfCurve,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=spans,d=3,tol=0) rtRebuildCrv = mc.rebuildCurve(rtCurve,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=spans,d=3,tol=0) lfRebuildCrv = mc.rename(lfRebuildCrv[1],prefix+'A_rebuildCurve') rtRebuildCrv = mc.rename(rtRebuildCrv[1],prefix+'B_rebuildCurve') - + # ========================= # - Generate Loft Surface - # ========================= - + loft = mc.loft([lfCurve,rtCurve],d=1,n=prefix+'_surface') loftSurface = loft[0] loftNode = mc.rename(loft[1],prefix+'_loft') - + # ============================ # - Create and Attach Joints - # ============================ - + jointList = [] inc = 1.0 / (joints - 1) for i in range(joints): @@ -81,27 +81,27 @@ def spine_ribbon(ptList,spans=0,joints=6,prefix='cn_spine'): joint = mc.joint(n=prefix+strInd+'_jnt') glTools.utils.attach.attachToSurface(loftSurface,joint,uValue=.5,vValue=inc*i,orient=True,uAxis='y',vAxis='x',uAttr='uCoord',vAttr='vCoord',alignTo='v',prefix=prefix+strInd) jointList.append(joint) - + # =========== # - Cleanup - # =========== - + jntGrp = mc.group(jointList,n=prefix+'_jnt_grp') rigGrp = mc.group([lfCurve,rtCurve,loftSurface],n=prefix+'_rig_grp') locGrp = mc.group(locList,n=prefix+'_loc_grp') - + # ================= # - Return Result - # ================= - + return [jntGrp,rigGrp,locGrp] def create_basic(length=10.0,width=0.5,mainCtrls=4,subCtrls=10,surface=True,curve=False,prefix=''): ''' Create a basic ribbon rig with a single base control - @param length: Ribbon length + @param length: Ribbon length @type length: float - @param width: Ribbon width + @param width: Ribbon width @type width: float @param mainCtrls: Number of main ribbon controls @type mainCtrls: int @@ -116,212 +116,212 @@ def create_basic(length=10.0,width=0.5,mainCtrls=4,subCtrls=10,surface=True,curv ''' # Check prefix if not prefix: prefix = 'ribbon' - + # ----------------- # - Create Groups - # ----------------- - + ctrl_grp = mc.group(em=True,n=prefix+'_ctrl_grp') hist_grp = mc.group(em=True,n=prefix+'_hist_grp') out_grp = mc.group(em=True,n=prefix+'_out_grp') rig_grp = mc.group([ctrl_grp,hist_grp,out_grp],n=prefix+'_grp') - + mc.setAttr(hist_grp+'.v',0) - + # ---------------------- # - Create Base Ribbon - # ---------------------- - + base_pts = [] base_inc = length / (mainCtrls-1) for i in range(mainCtrls): base_pts.append([width*.5,base_inc*i,0.0]) - + # Curve 0 base_crv_0 = mc.curve(d=1,p=base_pts,k=range(len(base_pts)),n=prefix+'_base0_crv') mc.rebuildCurve(base_crv_0,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) base_crv_0_locs = glTools.utils.curve.locatorCurve(base_crv_0,prefix=prefix+'_base0') glTools.utils.shape.createIntermediate(base_crv_0) mc.rebuildCurve(base_crv_0,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(mainCtrls-1),d=3,tol=0) - + # Flip CV array base_pts = [(-i[0],i[1],i[2]) for i in base_pts] - + # Curve 1 base_crv_1 = mc.curve(d=1,p=base_pts,k=range(len(base_pts)),n=prefix+'_base1_crv') mc.rebuildCurve(base_crv_1,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) base_crv_1_locs = glTools.utils.curve.locatorCurve(base_crv_1,prefix=prefix+'_base1') glTools.utils.shape.createIntermediate(base_crv_1) mc.rebuildCurve(base_crv_1,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(mainCtrls-1),d=3,tol=0) - + # Loft base_loft = mc.loft([base_crv_0,base_crv_1],d=1,n=prefix+'_base_surface') base_surface = base_loft[0] base_loft = mc.rename(base_loft[1],prefix+'_base_loft') - + # Rebuild base_rebuild = mc.rebuildSurface(base_surface,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=1,kc=1,su=0,du=0,sv=0,dv=0,tol=0,fr=0,dir=2,n=prefix+'_base_rebuildSurface') - + mc.parent([base_crv_0,base_crv_1,base_surface],hist_grp) - + # ----------------------- # - Create Base Control - # ----------------------- - + ctrlBuilder = glTools.tools.controlBuilder.ControlBuilder() - + mc.select(cl=True) base_jnt = mc.joint(n=prefix+'_base_jnt',radius=0.0) base_grp = mc.group(base_jnt,n=prefix+'_base_grp') mc.parent(base_grp,ctrl_grp) - + ctrlBuilder.controlShape(base_jnt,'circle',rotate=(90,0,0),scale=0.2*length) - + # ------------------------ # - Create Main Controls - # ------------------------ - + main_ctrl_list = [] main_grp_list = [] main_ctrl_grp = mc.group(em=True,n=prefix+'_mainCtrl_grp') for i in range(mainCtrls): - + # Clear selection mc.select(cl=True) - + # Create main control joint index = glTools.utils.stringUtils.alphaIndex(int(math.floor(i)),True) jnt = mc.joint(n=prefix+'_main'+index+'_jnt',radius=0.0) grp = mc.group(jnt,n=prefix+'_main'+index+'_grp') - + ctrlBuilder.controlShape(jnt,'square',rotate=(90,0,0),scale=0.125*length) - + # Position main control joint locs = [base_crv_0_locs[i],base_crv_1_locs[i]] mc.delete( mc.pointConstraint(locs,grp) ) mc.parent(locs,jnt) mc.makeIdentity(locs,apply=True,t=1,r=1,s=1,n=0) for loc in locs: mc.setAttr(loc+'.v',0) - + # Append list main_ctrl_list.append(jnt) main_grp_list.append(grp) - + mc.parent(main_grp_list,main_ctrl_grp) mc.parent(main_ctrl_grp,base_jnt) - + # ---------------------- # - Build Sub Controls - # ---------------------- - + sub_ctrl_list = [] sub_grp_list = [] sub_ctrl_grp = mc.group(em=True,n=prefix+'_subCtrl_grp') - + sub_inc = length / (subCtrls - 1) - + for i in range(subCtrls): - + # Clear selection mc.select(cl=True) - + # Create sub control joint index = glTools.utils.stringUtils.alphaIndex(i,True) sub_jnt = mc.joint(n=prefix+'_sub'+index+'_jnt',radius=0.0) sub_grp = mc.group(sub_jnt,n=prefix+'_sub'+index+'_grp') - + ctrlBuilder.controlShape(sub_jnt,'box',scale=0.025*length) - + # Position and attach sub controls mc.setAttr(sub_grp+'.t',0.0,(sub_inc*i),0.0) glTools.utils.attach.attachToSurface(base_surface,sub_grp,uValue=0.0,vValue=0.0,useClosestPoint=True,orient=True,uAxis='y',vAxis='x',uAttr='uCoord',vAttr='vCoord',alignTo='v',prefix=prefix+'_sub'+index) - + # Connect scale mc.connectAttr(base_jnt+'.scale',sub_grp+'.scale') - + # Append list sub_ctrl_list.append(sub_jnt) sub_grp_list.append(sub_grp) - + mc.parent(sub_grp_list,sub_ctrl_grp) mc.parent(sub_ctrl_grp,ctrl_grp) - + # ---------------- # - Build Output - # ---------------- - + # Build point array sub_inc = length / (subCtrls - 1) pts = [[0,(sub_inc*i),0] for i in range(subCtrls)] - + # ----- # Curve - + if curve: - + # Build curve ribbon_crv = mc.curve(d=1,p=pts,n=prefix+'_ribbon_curve') mc.rebuildCurve(ribbon_crv,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) - + # Create curve locators crv_locs = glTools.utils.curve.locatorCurve(ribbon_crv,prefix=prefix) glTools.utils.shape.createIntermediate(ribbon_crv) - + # Rebuild ribbon curve mc.rebuildCurve(ribbon_crv,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(subCtrls-1),d=3,tol=0,n=prefix+'_ribbon_rebuildCurve') - + # Parent curve locators for i in range(len(crv_locs)): mc.parent(crv_locs[i],sub_ctrl_list[i]) mc.setAttr(crv_locs[i]+'.v',0) - + mc.parent(ribbon_crv,out_grp) - + # ----------- # - Surface - - + if surface: - + # Offset CV array pts = [(width*.5,i[1],i[2]) for i in pts] - + # Sub Curve 0 sub_crv_0 = mc.curve(d=1,p=pts,k=range(len(pts)),n=prefix+'_sub0_crv') mc.rebuildCurve(sub_crv_0,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) sub_crv_0_locs = glTools.utils.curve.locatorCurve(sub_crv_0,prefix=prefix+'_sub0') glTools.utils.shape.createIntermediate(sub_crv_0) mc.rebuildCurve(sub_crv_0,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(subCtrls-1),d=3,tol=0,n=prefix+'_sub0_rebuildCurve') - + # Flip CV array pts = [(-i[0],i[1],i[2]) for i in pts] - + # Curve 1 sub_crv_1 = mc.curve(d=1,p=pts,k=range(len(pts)),n=prefix+'_sub1_crv') mc.rebuildCurve(sub_crv_1,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) sub_crv_1_locs = glTools.utils.curve.locatorCurve(sub_crv_1,prefix=prefix+'_sub1') glTools.utils.shape.createIntermediate(sub_crv_1) mc.rebuildCurve(sub_crv_1,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(subCtrls-1),d=3,tol=0,n=prefix+'_sub1_rebuildCurve') - + # Loft ribbon_loft = mc.loft([sub_crv_0,sub_crv_1],d=1,n=prefix+'_ribbon_surface') ribbon_surface = ribbon_loft[0] ribbon_loft = mc.rename(ribbon_loft[1],prefix+'_ribbon_loft') - + # Parent curve locators for i in range(len(pts)): locs = [sub_crv_0_locs[i],sub_crv_1_locs[i]] mc.parent(locs,sub_ctrl_list[i]) mc.makeIdentity(locs,apply=True,t=1,r=1,s=1,n=0) for loc in locs: mc.setAttr(loc+'.v',0) - + mc.parent([sub_crv_0,sub_crv_1],hist_grp) mc.parent(ribbon_surface,out_grp) def create(length=10.0,width=0.5,mainCtrls=4,subCtrls=10,surface=True,curve=False,prefix=''): ''' Create a ribbon rig with a primary base and tip controls - @param length: Ribbon length + @param length: Ribbon length @type length: float - @param width: Ribbon width + @param width: Ribbon width @type width: float @param mainCtrls: Number of main ribbon controls @type mainCtrls: int @@ -334,68 +334,68 @@ def create(length=10.0,width=0.5,mainCtrls=4,subCtrls=10,surface=True,curve=Fals @param prefix: Name prefix for created nodes @type prefix: str ''' - + # Check prefix if not prefix: prefix = 'ribbon' - + # ----------------- # - Create Groups - # ----------------- - + ctrl_grp = mc.group(em=True,n=prefix+'_ctrl_grp') hist_grp = mc.group(em=True,n=prefix+'_hist_grp') out_grp = mc.group(em=True,n=prefix+'_out_grp') rig_grp = mc.group([ctrl_grp,hist_grp,out_grp],n=prefix+'_grp') - + mc.setAttr(hist_grp+'.v',0) - + # ---------------------- # - Create Base Ribbon - # ---------------------- - + # Generate point array base_inc = float(length) / (mainCtrls-1) base_pts = [(width*.5,base_inc*i,0.0) for i in range(mainCtrls)] - + # Curve 0 base_crv_0 = mc.curve(d=1,p=base_pts,k=range(len(base_pts)),n=prefix+'_base0_crv') mc.rebuildCurve(base_crv_0,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) base_crv_0_locs = glTools.utils.curve.locatorCurve(base_crv_0,prefix=prefix+'_base0') glTools.utils.shape.createIntermediate(base_crv_0) mc.rebuildCurve(base_crv_0,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(mainCtrls-1),d=3,tol=0) - + # Flip CV array base_pts = [(-i[0],i[1],i[2]) for i in base_pts] - + # Curve 1 base_crv_1 = mc.curve(d=1,p=base_pts,k=range(len(base_pts)),n=prefix+'_base1_crv') mc.rebuildCurve(base_crv_1,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) base_crv_1_locs = glTools.utils.curve.locatorCurve(base_crv_1,prefix=prefix+'_base1') glTools.utils.shape.createIntermediate(base_crv_1) mc.rebuildCurve(base_crv_1,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(mainCtrls-1),d=3,tol=0) - + # Loft base_loft = mc.loft([base_crv_0,base_crv_1],d=1,n=prefix+'_base_surface') base_surface = base_loft[0] base_loft = mc.rename(base_loft[1],prefix+'_base_loft') - + # Rebuild base_rebuild = mc.rebuildSurface(base_surface,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=1,kc=1,su=0,du=0,sv=0,dv=0,tol=0,fr=0,dir=2,n=prefix+'_base_rebuildSurface') - + mc.parent([base_crv_0,base_crv_1,base_surface],hist_grp) - + # ------------------------------- # - Create Base and Tip Control - # ------------------------------- - + # Base Control mc.select(cl=True) base_jnt = mc.joint(n=prefix+'_baseA_jnt',radius=0.0) base_grp = mc.group(base_jnt,n=prefix+'_baseA_grp') mc.parent(base_grp,ctrl_grp) - + ctrlBuilder.controlShape(base_jnt,'circle',rotate=(90,0,0),scale=0.2*length) - + # Tip Control mc.select(cl=True) tip_jnt = mc.joint(n=prefix+'_tipA_jnt',radius=0.0) @@ -403,155 +403,155 @@ def create(length=10.0,width=0.5,mainCtrls=4,subCtrls=10,surface=True,curve=Fals mc.parent(tip_grp,ctrl_grp) # Position Tip mc.move(0,length,0,tip_grp,ws=True,a=True) - + ctrlBuilder.controlShape(tip_jnt,'circle',rotate=(90,0,0),scale=0.2*length) - + # ------------------------ # - Create Main Controls - # ------------------------ - + # Check mid control mid = False if (float(mainCtrls)/2) % 1: mid = True - + # Determine mid point if mid: split = int(math.ceil(float(mainCtrls)/2))-1 else : split = int(mainCtrls/2) - + # Create controls for i in range(mainCtrls): - + # Clear selection mc.select(cl=True) - + # Create main control joint index = glTools.utils.stringUtils.alphaIndex(int(math.floor(i)),True) jnt = mc.joint(n=prefix+'_main'+index+'_jnt',radius=0.0) grp = mc.group(jnt,n=prefix+'_main'+index+'_grp') - + ctrlBuilder.controlShape(jnt,'square',rotate=(90,0,0),scale=0.125*length) - + # Position main control joint locs = [base_crv_0_locs[i],base_crv_1_locs[i]] mc.delete( mc.pointConstraint(locs,grp) ) mc.parent(locs,jnt) mc.makeIdentity(locs,apply=True,t=1,r=1,s=1,n=0) for loc in locs: mc.setAttr(loc+'.v',0) - + # Constrain to base/tip control connBlend = glTools.utils.constraint.blendConstraint([base_jnt,tip_jnt],grp,jnt,blendAttr='bias',maintainOffset=True,prefix='') - + # Set constraint weights if mid and i == split: mc.setAttr(connBlend,0.5) else: if i < split: mc.setAttr(connBlend,0.0) else: mc.setAttr(connBlend,1.0) - + # Parent to main control group mc.parent(grp,ctrl_grp) - + # ---------------------- # - Build Sub Controls - # ---------------------- - + sub_ctrl_list = [] sub_grp_list = [] sub_ctrl_grp = mc.group(em=True,n=prefix+'_subCtrl_grp') # Turn off inheritTransform mc.setAttr(sub_ctrl_grp+'.inheritsTransform',0) - + # Build point array sub_inc = float(length) / (subCtrls - 1) pts = [[0,(sub_inc*i),0] for i in range(subCtrls)] - + for i in range(subCtrls): - + # Clear selection mc.select(cl=True) - + # Create sub control joint index = glTools.utils.stringUtils.alphaIndex(i,True) sub_jnt = mc.joint(n=prefix+'_sub'+index+'_jnt',radius=0.0) sub_grp = mc.group(sub_jnt,n=prefix+'_sub'+index+'_grp') - + ctrlBuilder.controlShape(sub_jnt,'box',scale=0.025*length) - + # Position and attach sub controls mc.setAttr(sub_grp+'.t',pts[i][0],pts[i][1],pts[i][2]) glTools.utils.attach.attachToSurface(base_surface,sub_grp,uValue=0.0,vValue=0.0,useClosestPoint=True,orient=True,uAxis='-x',vAxis='y',uAttr='uCoord',vAttr='vCoord',alignTo='v',prefix=prefix+'_sub'+index) - + # Append list sub_ctrl_list.append(sub_jnt) sub_grp_list.append(sub_grp) - + mc.parent(sub_grp_list,sub_ctrl_grp) mc.parent(sub_ctrl_grp,ctrl_grp) - + # ---------------- # - Build Output - # ---------------- - + # ----- # Curve - + if curve: - + # Build curve ribbon_crv = mc.curve(d=1,p=pts,n=prefix+'_ribbon_curve') mc.rebuildCurve(ribbon_crv,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) - + # Create curve locators crv_locs = glTools.utils.curve.locatorCurve(ribbon_crv,prefix=prefix) glTools.utils.shape.createIntermediate(ribbon_crv) - + # Rebuild ribbon curve mc.rebuildCurve(ribbon_crv,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(subCtrls-1),d=3,tol=0,n=prefix+'_ribbon_rebuildCurve') - + # Parent curve locators for i in range(len(crv_locs)): mc.parent(crv_locs[i],sub_ctrl_list[i]) mc.setAttr(crv_locs[i]+'.v',0) - + mc.parent(ribbon_crv,out_grp) - + # ----------- # - Surface - - + if surface: - + # Offset CV array pts = [(width*.5,i[1],i[2]) for i in pts] - + # Sub Curve 0 sub_crv_0 = mc.curve(d=1,p=pts,k=range(len(pts)),n=prefix+'_sub0_crv') mc.rebuildCurve(sub_crv_0,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) sub_crv_0_locs = glTools.utils.curve.locatorCurve(sub_crv_0,prefix=prefix+'_sub0') glTools.utils.shape.createIntermediate(sub_crv_0) mc.rebuildCurve(sub_crv_0,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(subCtrls-1),d=3,tol=0,n=prefix+'_sub0_rebuildCurve') - + # Flip CV array pts = [(-i[0],i[1],i[2]) for i in pts] - + # Curve 1 sub_crv_1 = mc.curve(d=1,p=pts,k=range(len(pts)),n=prefix+'_sub1_crv') mc.rebuildCurve(sub_crv_1,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=3,tol=0) sub_crv_1_locs = glTools.utils.curve.locatorCurve(sub_crv_1,prefix=prefix+'_sub1') glTools.utils.shape.createIntermediate(sub_crv_1) mc.rebuildCurve(sub_crv_1,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=(subCtrls-1),d=3,tol=0,n=prefix+'_sub1_rebuildCurve') - + # Loft ribbon_loft = mc.loft([sub_crv_0,sub_crv_1],d=1,n=prefix+'_ribbon_surface') ribbon_surface = ribbon_loft[0] ribbon_loft = mc.rename(ribbon_loft[1],prefix+'_ribbon_loft') - + # Parent curve locators for i in range(len(pts)): locs = [sub_crv_0_locs[i],sub_crv_1_locs[i]] mc.parent(locs,sub_ctrl_list[i]) mc.makeIdentity(locs,apply=True,t=1,r=1,s=1,n=0) for loc in locs: mc.setAttr(loc+'.v',0) - + mc.parent([sub_crv_0,sub_crv_1],hist_grp) mc.parent(ribbon_surface,out_grp) diff --git a/tools/rivet.py b/tools/rivet.py index 0931513..6a96ea0 100644 --- a/tools/rivet.py +++ b/tools/rivet.py @@ -5,91 +5,91 @@ def create(prefix=''): ''' # Check prefix if not prefix: prefix = 'rivet' - + # Get selected polygon edges edges = mc.filterExpand(sm=32) - + # Check edge selection if edges: - + # Check selection length if len(edges) != 2: raise Exception('Select 2 poly edges or a nurbs surface point and run again!') - + # Determine object and edge indices obj = mc.ls(edges[0],o=True) edgeIndex1 = int(edges[0].split('.')[-1].strip('e[]')) edgeIndex2 = int(edges[1].split('.')[-1].strip('e[]')) - - # Create curves from poly edges + + # Create curves from poly edges curveEdge1 = mc.createNode('curveFromMeshEdge',n=prefix+'_edge1_curveFromMeshEdge') mc.setAttr(curveEdge1+'.ihi',1) mc.setAttr(curveEdge1+'.ei[0]',edgeIndex1) curveEdge2 = mc.createNode('curveFromMeshEdge',n=prefix+'_edge2_curveFromMeshEdge') mc.setAttr(curveEdge2+'.ihi',1) mc.setAttr(curveEdge2+'.ei[0]',edgeIndex2) - + # Generate loft from edge curves loft = mc.createNode('loft',n=prefix+'_loft') mc.setAttr(loft+'.ic',s=2) mc.setAttr(loft+'.u',1) mc.setAttr(loft+'.rsn',1) - + # Create pointOnSurfaceInfo node pointInfo = mc.createNode('pointOnSurfaceInfo',n=prefix+'_pointOnSurfaceInfo') mc.setAttr(pointInfo+'.turnOnPercentage',1) mc.setAttr(pointInfo+'.parameterU',0.5) mc.setAttr(pointInfo+'.parameterV',0.5) - + # Connect nodes mc.connectAttr(loft+'.os',pointInfo+'.is',f=True) mc.connectAttr(curveEdge1+'.oc',loft+'.ic[0]',f=True) mc.connectAttr(curveEdge2+'.oc',loft+'.ic[1]',f=True) mc.connectAttr(obj+'.w',curveEdge1+'.im',f=True) mc.connectAttr(obj+'.w',curveEdge2+'.im',f=True) - + else: - + # Get surface point selection points = mc.filterExpand(sm=41) - + # Check point selection if not points: if len(points) > 1: raise Exception('Select 2 poly edges or a nurbs surface point and run again!') - + # Determine object and UV parameter obj = mc.ls(edges[0],o=True) uv = points[0].split('.')[-1].strip('uv[]').split(',') u = float(uv[0]) v = float(uv[1]) - + # Create pointOnSurfaceInfo node pointInfo = mc.createNode('pointOnSurfaceInfo',n=prefix+'_pointOnSurfaceInfo') mc.setAttr(pointInfo+'.turnOnPercentage',1) mc.setAttr(pointInfo+'.parameterU',0.5) mc.setAttr(pointInfo+'.parameterV',0.5) - + # Connect nodes mc.connectAttr(obj+'.ws',pointInfo+'.is',f=True) # Create rivet locator loc = mc.createNode('transform',n=prefix+'_locator') - + # Create aim constraint aim = mc.createNode('aimConstraint',p=loc,n=prefix+'_aimConstraint') mc.setAttr(aim+'.tg[0].tw',1) mc.setAttr(aim+'.a',0,1,0) mc.setAttr(aim+'.u',0,0,1) for attr in ['tx','ty','tz','rx','ry','rz','sx','sy','sz','v']: mc.setAttr(aim+'.'+attr,k=0) - + mc.connectAttr(pointInfo+'.position',loc+'.translate',f=True) mc.connectAttr(pointInfo+'.normal',aim+'.tg[0].tt',f=True) mc.connectAttr(pointInfo+'.tv',aim+'.wu',f=True) - + mc.connectAttr(aim+'.crx',loc+'.rx',f=True) mc.connectAttr(aim+'.cry',loc+'.ry',f=True) mc.connectAttr(aim+'.crz',loc+'.rz',f=True) - + # Return result return loc diff --git a/tools/saveXmlPose.py b/tools/saveXmlPose.py index e229b9c..712bbf9 100644 --- a/tools/saveXmlPose.py +++ b/tools/saveXmlPose.py @@ -6,7 +6,7 @@ def save_selectedPose(): pose_dict, namespace = record_selectedPose() exportXml(pose_dict, namespace) - + def save_pose(controls=[], filePath=""): pose_dict, namespace =record_pose(controls) writePoseXmlDoc( pose_dict, namespace, filePath="" ) @@ -14,7 +14,7 @@ def save_pose(controls=[], filePath=""): def record_selectedPose(): sel = mc.ls(sl=1) pose_dict, namespace = record_pose(sel) - + return pose_dict, namespace def record_pose(controls=[]): @@ -38,17 +38,17 @@ def set_Pose(filePath=""): mc.setAttr(namespace+i, pose_dict.get(i)) except: print "Warning : couldn't set "+namespace+i - + def readPoseXmlDoc( filePath=""): doc, root = xml_openDocument( filePath ) elem = xml_getChildElements(root) info = xml_getChildElements(elem[0]) pose = xml_getChildElements(elem[1]) - + #read info info_dict = xml_getAttributeDictionary(info[0]) namespace = info_dict.get("namespace") - + #read pose pose_dict = {} for i in pose: @@ -62,11 +62,11 @@ def writePoseXmlDoc( pose_dict={}, namespace="", filePath="" ): return # create doc doc, root = xml_newDocument("pose") - + poseInfo = xml_addElement(doc, root, "poseInfo") info = xml_addElement(doc, poseInfo, "info") xml_addAttr(info, "namespace", namespace ) - + # add pose objects objects = xml_addElement(doc, root, "objects") for i in pose_dict: @@ -75,9 +75,9 @@ def writePoseXmlDoc( pose_dict={}, namespace="", filePath="" ): xml_addAttr(pose, "object", i ) xml_addAttr(pose, "value", obj ) xml_write(doc, filePath) - + def exportXml(pose_dict={}, namespace=""): - + result = mc.promptDialog( title='File Path to Save Pose', message='Enter Path:', @@ -85,13 +85,13 @@ def exportXml(pose_dict={}, namespace=""): defaultButton='OK', cancelButton='Cancel', dismissString='Cancel') - + if result == 'OK': path = mc.promptDialog(query=True, text=True) writePoseXmlDoc( pose_dict, namespace, path ) - + def importXml(): - + result = mc.promptDialog( title='File Path to Import Pose', message='Enter Path:', @@ -99,7 +99,7 @@ def importXml(): defaultButton='OK', cancelButton='Cancel', dismissString='Cancel') - + if result == 'OK': path = mc.promptDialog(query=True, text=True) pose_dict = readPoseXmlDoc( path ) diff --git a/tools/selectLongestEdges.py b/tools/selectLongestEdges.py index a004ced..97d10d3 100644 --- a/tools/selectLongestEdges.py +++ b/tools/selectLongestEdges.py @@ -10,7 +10,7 @@ def longestEdges(mesh,faceSel=[]): meshFn = glTools.utils.mesh.getMeshFn(mesh) edgeIter = glTools.utils.mesh.getMeshEdgeIter(mesh) faceIter = glTools.utils.mesh.getMeshFaceIter(mesh) - + # Check face selection if faceSel: faceSel = mc.ls(faceSel,fl=1) @@ -20,18 +20,18 @@ def longestEdges(mesh,faceSel=[]): compObj = OpenMaya.MObject() selList.getDagPath(0,meshPath,compObj) faceIter = OpenMaya.MItMeshPolygon(meshPath,compObj) - + # Get edge array wrapper faceEdges = OpenMaya.MIntArray() - + # Initialize longest edge list longEdgeList = [] - + # Build edge ID pointer edgeId = OpenMaya.MScriptUtil() edgeId.createFromInt(0) edgeIdPtr = edgeId.asIntPtr() - + # Iterate through faces while not faceIter.isDone(): # Reset max edge length @@ -48,9 +48,9 @@ def longestEdges(mesh,faceSel=[]): maxEdgeLen = edgeLen longEdgeList.append(longEdge) faceIter.next() - + # Build selection list sel = [mesh+'.e['+str(i)+']' for i in longEdgeList] - + # Return result return sel diff --git a/tools/setDrivenKeyToRemapValue.py b/tools/setDrivenKeyToRemapValue.py index a028024..3255692 100644 --- a/tools/setDrivenKeyToRemapValue.py +++ b/tools/setDrivenKeyToRemapValue.py @@ -24,15 +24,15 @@ def setDrivenKeyToRemapValue(animCurve,remapValueNode='',interpType=3,deleteAnim raise Exception('AnimCurve node "'+animCurve+'" does not exist!!') if remapValueNode and not mc.objExists(remapValueNode): raise Exception('RemapValue node "'+remapValueNode+'" does not exist!!') - + # Get connections to animCurve inConn = mc.listConnections(animCurve+'.input',s=True,d=False,p=True) outConn = mc.listConnections(animCurve+'.output',s=False,d=True,p=True) - + # Get keyframe data valList = mc.keyframe(animCurve,q=True,vc=True) floatList = mc.keyframe(animCurve,q=True,fc=True) - + # Get min/max input and output values orderValList = copy.deepcopy(valList) orderFloatList = copy.deepcopy(floatList) @@ -42,23 +42,23 @@ def setDrivenKeyToRemapValue(animCurve,remapValueNode='',interpType=3,deleteAnim maxVal = orderValList[-1] minFloat = orderFloatList[0] maxFloat = orderFloatList[-1] - + # Create remapValue node if not remapValueNode: remapValueNode = mc.createNode('remapValue',n=animCurve+'_remapValue') - + # Set Remap attribute values mc.setAttr(remapValueNode+'.inputMin',minFloat) mc.setAttr(remapValueNode+'.inputMax',maxFloat) mc.setAttr(remapValueNode+'.outputMin',minVal) mc.setAttr(remapValueNode+'.outputMax',maxVal) - + # Remove existing ramp widgets indexList = range(mc.getAttr(remapValueNode+'.value',s=True)) indexList.reverse() for i in indexList: mc.removeMultiInstance(remapValueNode+'.value['+str(i)+']',b=True) - + # Set ramp widgets based on keys valRange = maxVal - minVal floatRange = maxFloat - minFloat @@ -76,13 +76,13 @@ def setDrivenKeyToRemapValue(animCurve,remapValueNode='',interpType=3,deleteAnim mc.setAttr(remapValueNode+'.value['+str(i)+'].value_Position',l=True) if lockValue: mc.setAttr(remapValueNode+'.value['+str(i)+'].value_FloatValue',l=True) - + # Replace animCurve connections mc.connectAttr(inConn[0],remapValueNode+'.inputValue',f=True) mc.connectAttr(remapValueNode+'.outValue',outConn[0],f=True) - + # Delete unused animCurve if deleteAnimCurve: mc.delete(animCurve) - + # Return result return remapValueNode diff --git a/tools/shapeExtract.py b/tools/shapeExtract.py index aa03f5e..d4c1267 100644 --- a/tools/shapeExtract.py +++ b/tools/shapeExtract.py @@ -25,72 +25,72 @@ def shapeExtract_skinCluster(baseGeo,targetGeo,skinCluster,influenceList=[],dele # --------- # - Check - # --------- - + suffix = '' if prefix: suffix = '_'+prefix - + # Check base geo if not mc.objExists(baseGeo): raise Exception('Base geometry "'+baseGeo+'" does not exist!') - + # Check target geo if not mc.objExists(targetGeo): raise Exception('Target geometry "'+targetGeo+'" does not exist!') - + # Check skinCluster if not mc.objExists(skinCluster): raise Exception('SkinCluster "'+skinCluster+'" does not exist!') - + # --------------------------- # - Get skinCluster details - # --------------------------- - + # Get geometry affected by skinCluster skinGeo = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys()[0] - + # Get skinClusterInfluence list if not influenceList: influenceList = mc.skinCluster(skinCluster,q=True,inf=True) - + # ------------------------------ # - Iterate through influences - # ------------------------------ - + returnList = [] for inf in influenceList: - + # Print progress print('Extracting region: '+inf+suffix) - + # Duplicate shape base dupGeo = mc.duplicate(baseGeo)[0] - + # Create blendShape to target blendShape = mc.blendShape(targetGeo,dupGeo)[0] mc.setAttr(blendShape+'.'+targetGeo,1) - + # Get skinCluster influence weights wt = glTools.utils.skinCluster.getInfluenceWeights(skinCluster,inf) - + # Set belndShape target weights glTools.utils.blendShape.setTargetWeights(blendShape,targetGeo,wt,dupGeo) - + # Delete history on duplicated geometry if deleteHistory: mc.delete(dupGeo,constructionHistory=True) - + # Rename extracted target dupGeo = mc.rename(dupGeo,inf+suffix) - + # Append to return list returnList.append(dupGeo) - + # Create shape group grp = mc.group(returnList,n=prefix+'_extract_grp',w=True) - + # ----------------- # - Return result - # ----------------- - + return returnList def shapeExtract_weights(baseGeo,targetGeo,weightList,deleteHistory=True,name=''): @@ -110,21 +110,21 @@ def shapeExtract_weights(baseGeo,targetGeo,weightList,deleteHistory=True,name='' # ========= # - Check - # ========= - + # Check base geo if not mc.objExists(baseGeo): raise Exception('Base geometry "'+baseGeo+'" does not exist!') - + # Check target geo if not mc.objExists(targetGeo): raise Exception('Target geometry "'+targetGeo+'" does not exist!') - + # ================= # - Extract Shape - # ================= - + if not name: name = targetGeo+'_extract' - + # Determine blendShape geometry if mc.objExists(name): blendGeo = name @@ -134,21 +134,21 @@ def shapeExtract_weights(baseGeo,targetGeo,weightList,deleteHistory=True,name='' mc.delete(blendGeo,ch=True) else: blendGeo = mc.duplicate(baseGeo,n=name)[0] - + # Create blendShape to target blendShape = mc.blendShape(targetGeo,blendGeo)[0] mc.setAttr(blendShape+'.'+targetGeo,1) - + # Set belndShape target weights glTools.utils.blendShape.setTargetWeights(blendShape,targetGeo,weightList,blendGeo) - + # Delete history on duplicated geometry if deleteHistory: mc.delete(blendGeo,constructionHistory=True) - + # ================= # - Return Result - # ================= - + return blendGeo def splitBlendTarget(baseGeo,targetGeo,pt1,pt2,smooth=0,deleteHistory=True,name=''): @@ -169,31 +169,31 @@ def splitBlendTarget(baseGeo,targetGeo,pt1,pt2,smooth=0,deleteHistory=True,name= # ========= # - Check - # ========= - + # Check base geo if not mc.objExists(baseGeo): raise Exception('Base geometry "'+baseGeo+'" does not exist!') - + # Check target geo if not mc.objExists(targetGeo): raise Exception('Target geometry "'+targetGeo+'" does not exist!') - + # ========================== # - Generate Split Weights - # ========================== - + lf_wt = glTools.tools.generateWeights.gradientWeights(baseGeo,pt1,pt2,smooth) rt_wt = [1.0-i for i in lf_wt] - + # ================================= # - Split Shape to Left and Right - # ================================= - + lf_shape = shapeExtract_weights(baseGeo,targetGeo,lf_wt,deleteHistory,'lf_'+name) rt_shape = shapeExtract_weights(baseGeo,targetGeo,rt_wt,deleteHistory,'rt_'+name) - + # ================= # - Return Result - # ================= - + return [lf_shape,rt_shape] diff --git a/tools/skinCluster.py b/tools/skinCluster.py index 1221f7f..028fd63 100644 --- a/tools/skinCluster.py +++ b/tools/skinCluster.py @@ -16,53 +16,53 @@ def loadWorldSpaceData(geo='',search='',replace=''): ''' # Load Data skinData = SkinClusterData().load() - + # Check Geometry if not geo: - + # Check Search/Replace if not search or (not search and not replace): - + # Get Geometry from Selection sel = mc.ls(sl=True) if not sel: print('No target geometry specified! Unable to load skinCluster data...') return geo = sel[0] - + else: - + # Search and Replace Name of Affected Geometry affectedGeo = skinData._data['affectedGeometry'][0] if not search in affectedGeo: print('Search string "'+search+'" not found in original affected geometry name "'+affectedGeo+'"! Unable to load skinCluster data...') return geo = affectedGeo.replace(search,replace) - + # Rebuild SkinCluster Data skinData.rebuildWorldSpaceData(targetGeo=geo) skinData.rebuild() - + def loadWorldSpaceDataUI(): ''' ''' window = 'loadSkinClusterWorldSpaceUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Load SkinCluster Data (World Space)') - + # Layout cl = mc.columnLayout() - + # UI Elements targetGeoTFB = mc.textFieldButtonGrp('loadSkinData_targetGeoTFB',label='Target Geometry',text='',buttonLabel='Load Selected') searchStrTFG = mc.textFieldGrp('loadSkinData_searchStrTFB',label='Search', text='') replaceStrTFG = mc.textFieldGrp('loadSkinData_replaceStrTFB',label='Replace', text='') loadB = mc.button('loadSkinData_loadDataB',l='Load',c='glTools.tools.skinCluster.loadWorldSpaceDataFromUI()') cancelB = mc.button('loadSkinData_cancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # UI callback commands mc.textFieldButtonGrp(targetGeoTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+targetGeoTFB+'",selType="transform")') - + def loadWorldSpaceDataFromUI(): ''' @@ -70,12 +70,12 @@ def loadWorldSpaceDataFromUI(): # Check Window window = 'loadSkinClusterWorldSpaceUI' if not mc.window(window,q=True,ex=1): return - + # Get UI data targetGeo = mc.textFieldButtonGrp('loadSkinData_targetGeoTFB',q=True,text=True) searchStr = mc.textFieldButtonGrp('loadSkinData_searchStrTFB',q=True,text=True) replaceStr = mc.textFieldButtonGrp('loadSkinData_replaceStrTFB',q=True,text=True) - + # Load SkinCluster Data loadWorldSpaceData(geo=targetGeo,search=searchStr,replace=replaceStr) @@ -85,32 +85,32 @@ def copyToMany(sourceGeo,targetGeoList): # ========== # - Checks - # ========== - + if not mc.objExists(sourceGeo): raise Exception('Source geometry "'+sourceGeo+'" does not exist!') if not targetGeoList: raise Exception('Invalid target geometry list!') - + # ========================== # - Get Source SkinCluster - # ========================== - + srcSkin = glTools.utils.skinCluster.findRelatedSkinCluster(sourceGeo) skinData = glTools.data.skinClusterData.SkinClusterData(srcSkin) - + # ======================= # - Transfer to Targets - # ======================= - + for targetGeo in targetGeoList: - + # Copy Source SkinCluster xferData = copy.deepcopy(skinData) - + # Remap Geometry xferData.remapGeometry(targetGeo) xferData.rebuildWorldSpaceData(targetGeo) - + # Rebuild SkinCluster xferData.rebuild() @@ -123,41 +123,41 @@ def skinInsideFaces(insideFaceList): ''' # Get Component List By Object objFaceList = glTools.utils.selection.componentListByObject(insideFaceList) - + # For Each for objFaces in objFaceList: - + # Get Source Mesh mesh = mc.ls(objFaces[0],o=True)[0] - + # Get Face ID List faceIds = glTools.utils.component.getSingleIndexComponentList(objFaces) faceIds = faceIds[faceIds.keys()[0]] - + # Duplicate Original Mesh mesh_dup = mc.duplicate(mesh)[0] mesh_dup_children = mc.ls(mc.listRelatives(mesh_dup,c=True),transforms=True) if mesh_dup_children: mc.delete(mesh_dup_children) - + # Extract Faces from Duplicate faces = [mesh_dup+'.f['+str(i)+']' for i in faceIds] extract = mc.polyChipOff(faces,dup=False,ch=False) separate = mc.polySeparate(mesh_dup,ch=False) - + # Transfer Weights to Extracted Mesh copyToMany(mesh,[separate[0]]) copyToMany(separate[0],[separate[1]]) - + # Transfer Weights from Extracted Mesh srcSkin = glTools.utils.skinCluster.findRelatedSkinCluster(separate[1]) skinData = glTools.data.skinClusterData.SkinClusterData(srcSkin) skinData.remapGeometry(mesh) skinData.rebuildWorldSpaceData(mesh) - + # Apply Transferred Weights vtxList = mc.polyListComponentConversion(objFaces,fromFace=True,toVertex=True,internal=False) skinData.loadWeights(componentList=vtxList) - + # Clean Up mc.delete(mesh_dup) @@ -168,31 +168,31 @@ def edgeLoopWeights(edgeList): if not edgeList: raise Exception('Invalid or empty edge list!') edgeList = mc.filterExpand(edgeList,ex=True,sm=32) or [] if not edgeList: raise Exception('Invalid edge list! List of polygon edges required...') - + # Get Mesh from Edges mesh = list(set(mc.ls(edgeList,o=True) or [])) if len(mesh) > 1: raise Exception('Edges from multiple mesh shapes were supplied! '+str(mesh)) mesh = mesh[0] - + for edge in edgeList: - + # Get Edge ID edgeID = glTools.utils.component.index(edge) - + # Get Vertices from Edge edgeVerts = mc.polyListComponentConversion(edge,fe=True,tv=True) - + # Get Average Vertex Weights mc.select(edgeVerts) glTools.tools.copyPasteWeights.averageWeights() - + # Select Edge Loop Vertices mc.polySelect(mesh,edgeLoop=edgeID) loopEdges = mc.ls(sl=1,fl=1) loopVerts = mc.polyListComponentConversion(loopEdges,fe=True,tv=True) mc.select(loopVerts) glTools.tools.copyPasteWeights.pasteWeights() - + # Return Result return mesh diff --git a/tools/smoothWeights.py b/tools/smoothWeights.py index 214ebf8..e2bbccf 100644 --- a/tools/smoothWeights.py +++ b/tools/smoothWeights.py @@ -25,34 +25,34 @@ def smoothWeights(vtxList=[],faceConnectivity=False,showProgress=False,debug=Fal ''' # Get Main Progress Bar gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') - + # ========================== # - Check Vertex Selection - # ========================== - + if not vtxList: vtxList = mc.ls(sl=1) - + vtxList = mc.filterExpand(vtxList,ex=True,sm=31) vtxSelList = glTools.utils.selection.componentListByObject(vtxList) if not vtxSelList: raise Exception('No valid mesh vertices specified!') - + # ===================================== # - For Each Selection Element (mesh) - # ===================================== - + for vtxSel in vtxSelList: - + vtxSel = mc.ls(vtxSel,fl=True) - + # Get Expanded Vertex Selection expSel = glTools.utils.component.expandVertexSelection(vtxSel,useFace=faceConnectivity) expSelComp = glTools.utils.selection.getSelectionElement(expSel,0) - + # Get Mesh and Connected SkinCluster mesh = mc.ls(vtxSel[0],o=True)[0] skin = glTools.utils.skinCluster.findRelatedSkinCluster(mesh) skinFn = glTools.utils.skinCluster.getSkinClusterFn(skin) - + # Get Vertex IDs and Connectivity vtxIDs = glTools.utils.component.singleIndexList(vtxSel) expIDs = glTools.utils.component.singleIndexList(expSel) @@ -60,18 +60,18 @@ def smoothWeights(vtxList=[],faceConnectivity=False,showProgress=False,debug=Fal vtxIDs=vtxIDs, faceConnectivity=faceConnectivity, showProgress=showProgress ) - + # Get SkinCluster Influence List infList = OpenMaya.MIntArray() influences = mc.skinCluster(skin,q=True,inf=True) for inf in influences: infList.append(glTools.utils.skinCluster.getInfluenceIndex(skin,inf)) infCnt = infList.length() - + # Get SkinCluster Weights wtList = OpenMaya.MDoubleArray() skinFn.getWeights(expSelComp[0],expSelComp[1],infList,wtList) - + # DEBUG if debug: print('Skin Mesh: '+mesh) @@ -79,79 +79,79 @@ def smoothWeights(vtxList=[],faceConnectivity=False,showProgress=False,debug=Fal print('SkinCluster Influence Count: '+str(infCnt)) print('SkinCluster Influence List:') for inf in influences: print('\t'+inf) - + # ================== # - Smooth Weights - # ================== - + # Initialize Smooth Weights Array sWtList = OpenMaya.MDoubleArray(wtList) - + # Begin Progress Bar if showProgress: mc.progressBar( gMainProgressBar,e=True,bp=True,ii=True,status=('Smoothing Weights for "'+mesh+'" ...'),maxValue=len(vtxIDs) ) - + # For Each Vertex for vtxID in vtxIDs: - + # Get Vertex WeightList Index vtxInd = expIDs.index(vtxID) - + # For Each Influence for inf in range(infCnt): - + # Initialize Debug String debugStr = '' - + # Get Current Influence Weight Value wt = wtList[(vtxInd*infCnt)+inf] if debug: debugStr += ('['+str(vtxID)+'] - '+influences[inf]+': '+str(wt)+'\n') - + # For Each Connected Vertex if debug: debugStr += ('['+str(vtxID)+'] - connected vertex IDs:'+str(vtxConnDict[vtxID])+'\n') for connID in vtxConnDict[vtxID]: - + # Get Connected Vertex WeightList Index connInd = expIDs.index(connID) - + # Add Connected Vertex Weight wt += wtList[(connInd*infCnt)+inf] if debug: debugStr += ('\t['+str(connID)+'] - '+influences[inf]+': '+str(wtList[(connInd*infCnt)+inf])+'\n') - + # Normalize Weight Value wt /= len(vtxConnDict[vtxID])+1 - + # Print Debug Message if debug: debugStr += ('['+str(vtxID)+'] - smoothed value: '+str(wt)+'\n') if wt > 0.00001: print(debugStr) - + # Set Smoothed Weight sWtList.set(wt,((vtxInd*infCnt)+inf)) - + # Update Progress Bar if showProgress: if mc.progressBar(gMainProgressBar,q=True,isCancelled=True): mc.progressBar(gMainProgressBar,e=True,endProgress=True) raise UserInterupted('Operation cancelled by user!') mc.progressBar(gMainProgressBar,e=True,step=1) - + # End Current Progress Bar if showProgress: mc.progressBar(gMainProgressBar,e=True,endProgress=True) - + # ========================== # - Apply Smoothed Weights - # ========================== - + # Set SkinCluster Weights try: skinFn.setWeights(expSelComp[0],expSelComp[1],infList,sWtList,True,None) except: setWeights(vtxSel,skin,list(infList),list(sWtList)) - + # ================= # - Return Result - # ================= - + return def setWeights(vtxList,skinCluster,infList,wtList): @@ -169,36 +169,36 @@ def setWeights(vtxList,skinCluster,infList,wtList): ''' # Get Influence List #infList = mc.skinCluster(skinCluster,q=True,inf=True) - + # For Each Vertex for v in range(len(vtxList)): - + # Get Vertex vtx = vtxList[v] - + cmd = 'skinPercent' - + # For Each Influence infCnt = len(infList) for i in range(infCnt): - + # Get Weight Value wt = wtList[(v*infCnt)+i] if wt<0.00001: continue - + # Get Influence inf = glTools.utils.skinCluster.getInfluenceAtIndex(skinCluster,i) - + # Build Weight Command cmd += (' -tv '+inf+' '+str(round(wt,5))) - + # Finalize Weight Command cmd += (' '+skinCluster+' '+vtx) - + # Execute Command mm.eval(cmd) print(cmd) - + # Return Result return @@ -212,27 +212,27 @@ def smoothFlood(skinCluster,iterations=1): ''' # Check zero iterations if not iterations: return - + # Get current tool currentTool = mc.currentCtx() - + # Select geometry geometry = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys() mc.select(geometry) - + # Get skinCluster influence list influenceList = mc.skinCluster(skinCluster,q=True,inf=True) - + # Unlock influence weights for influence in influenceList: mc.setAttr(influence+'.lockInfluenceWeights',0) - + # Initialize paint context skinPaintTool = 'artAttrSkinContext' if not mc.artAttrSkinPaintCtx(skinPaintTool,ex=True): mc.artAttrSkinPaintCtx(skinPaintTool,i1='paintSkinWeights.xpm',whichTool='skinWeights') mc.setToolTo(skinPaintTool) mc.artAttrSkinPaintCtx(skinPaintTool,edit=True,sao='smooth') - + # Smooth Weights for i in range(iterations): print(skinCluster+': Smooth Iteration - '+str(i+1)) @@ -244,7 +244,7 @@ def smoothFlood(skinCluster,iterations=1): mc.artAttrSkinPaintCtx(skinPaintTool,e=True,clear=True) # Unlock current influence weights mc.setAttr(influence+'.lockInfluenceWeights',0) - + # Reset current tool mc.setToolTo(currentTool) @@ -254,23 +254,23 @@ def hotkeySetup(): # ==================== # - Runtime Commands - # ==================== - + # Smooth Weights if mm.eval('runTimeCommand -q -ex rt_smoothWeights'): mm.eval('runTimeCommand -e -del rt_smoothWeights') mm.eval('runTimeCommand -annotation "" -category "User" -commandLanguage "python" -command "import glTools.tools.smoothWeights;reload(glTools.tools.smoothWeights);glTools.tools.smoothWeights.smoothWeights(mc.ls(sl=1),True,True)" rt_smoothWeights') - + # ======================== # - Create Name Commands - # ======================== - + smoothWtCmd = mc.nameCommand( 'smoothWeightsNameCommand', ann='smoothWeightsNameCommand', sourceType='mel', c='rt_smoothWeights' ) - + # ============================= # - Create Hotkey Assignments - # ============================= - + mc.hotkey(keyShortcut='s',alt=True,name=smoothWtCmd) diff --git a/tools/snapToClosestPoint.py b/tools/snapToClosestPoint.py index 31611d5..d620032 100644 --- a/tools/snapToClosestPoint.py +++ b/tools/snapToClosestPoint.py @@ -17,35 +17,35 @@ def snapToClosestPoint(ptList,targetGeo,threshold=0.0001): # Check target mesh if not mc.objExists(targetGeo): raise Exception('Target geoemetry "'+targetGeo+'" does not exist!!') - + # Get target point array targetPtArray = glTools.utils.base.getMPointArray(targetGeo) - + # Flatten input point list ptList = mc.ls(ptList,fl=True) - + # Iterate through input points for pt in ptList: - + # Initialize distance values dist = 0 minDist = 99999 - + # Initialize point values mPt = glTools.utils.base.getMPoint(pt) tPt = mPt - + # Find closest point for i in range(targetPtArray.length()): - + # Get distance to point dist = (mPt - targetPtArray[i]).length() if dist < minDist: minDist = dist tPt = targetPtArray[i] - + # Check thrshold distance if (threshold > 0.0) and (dist < threshold): break - + # Move to target point mc.move(tPt[0],tPt[1],tPt[2],pt,ws=True) diff --git a/tools/softModTool.py b/tools/softModTool.py index 456d49c..0792988 100644 --- a/tools/softModTool.py +++ b/tools/softModTool.py @@ -7,29 +7,29 @@ def create(geo,prefix=''): ''' # Check prefix if not prefix: prefix = geo - + # Create Deformer sMod = mc.softMod(geo,n=prefix+'_softMod') sModHandle = sMod[1] sMod = sMod[0] sModBase = mc.duplicate(sModHandle,po=True,n=prefix+'_softModBase')[0] - + # Get Handle pivot piv = mc.xform(sModHandle,q=True,ws=True,rp=True) - + # Initiate Control Builder ctrlBuilder = glTools.tools.controlBuilder.ControlBuilder() - + # Create Base control base_grp = mc.createNode('transform',n=prefix+'_softModBase_grp') base_ctrl = mc.createNode('transform',n=prefix+'_softModBase_ctrl',p=base_grp) base_ctrlShape = ctrlBuilder.controlShape(base_ctrl,'box',scale=2) - + # Create Offset control offset_grp = mc.createNode('transform',n=prefix+'_softModOffset_grp',p=base_ctrl) offset_ctrl = mc.createNode('transform',n=prefix+'_softModOffset_ctrl',p=offset_grp) offset_ctrlShape = ctrlBuilder.controlShape(offset_ctrl,'sphere',scale=0.25) - + # Create Falloff control falloff_grp = mc.createNode('transform',n=prefix+'_softModFalloff_grp',p=base_ctrl) falloff_ctrl = mc.createNode('transform',n=prefix+'_softModFalloff_ctrl',p=falloff_grp) @@ -38,15 +38,15 @@ def create(geo,prefix=''): mc.parent(falloff_loc,falloff_ctrl) mc.addAttr(falloff_ctrl,ln='radius',min=0.001,dv=1,k=True) mc.setAttr(falloff_loc+'.v',0) - + # Move hierarchy into place mc.move(piv[0],piv[1],piv[2],base_grp,a=True) - + # Connect to deformer mc.connectAttr(falloff_loc+'.worldPosition[0]',sMod+'.falloffCenter',f=True) mc.connectAttr(falloff_ctrl+'.radius',sMod+'.falloffRadius',f=True) mc.connectAttr(sModBase+'.worldInverseMatrix[0]',sMod+'.bindPreMatrix',f=True) - + # Parent and constrain softMod elements mc.parentConstraint(offset_ctrl,sModHandle,mo=True) mc.scaleConstraint(offset_ctrl,sModHandle,mo=True) @@ -54,6 +54,6 @@ def create(geo,prefix=''): mc.scaleConstraint(base_ctrl,sModBase,mo=True) mc.parent(sModHandle,sModBase) mc.parent(sModBase,base_grp) - + # Return result return sMod diff --git a/tools/spaces.py b/tools/spaces.py index f710c65..0fe4173 100644 --- a/tools/spaces.py +++ b/tools/spaces.py @@ -3,7 +3,7 @@ class UserInputError(Exception): pass class Spaces(object): - + def __init__(self): ''' Initializer for Spaces class object @@ -12,18 +12,18 @@ def __init__(self): self.channels = self.allChannels[0:8] self.transform = ['transform','joint'] self.worldNode = 'spaces_wld01_loc' - + self.managerUI = 'spacesUI' self.uiRCL = 'spacesRCL' self.uiKeyCBG = 'spacesKeyCBG' self.uiKeyPreviousCBG = 'spacesKeyPrevCBG' self.uiMaintainPosCBG = 'spacesMaintainPosCBG' self.uiAllOMG = 'spacesAllOMG' - + def create(self,ctrl,targetList=[],abrTargetList=[],nameTag='',worldParent=''): ''' Create a new spaces node - @param targetList: list of target transforms for the space node constraint + @param targetList: list of target transforms for the space node constraint @type targetList: list @param abrTargetList: list of abreviated target names. Used in UI. @type abrTargetList: list @@ -32,14 +32,14 @@ def create(self,ctrl,targetList=[],abrTargetList=[],nameTag='',worldParent=''): @param nameTag: Shortened, descriptive name for control. Used in UI. @type nameTag: str ''' - + if not len(abrTargetList): abrTargetList = targetList - + # Verify target list for target in targetList: if not mc.objExists(target): raise UserInputError('Target object '+target+' does not exists!') - + # Determine SPACE node par = '' try: par = self.getSpacesNode(ctrl) @@ -54,7 +54,7 @@ def create(self,ctrl,targetList=[],abrTargetList=[],nameTag='',worldParent=''): #print('Spaces node already exists. Running Spaces().add() instead!') result = self.add(ctrl,targetList,abrTargetList,nameTag) return result - + # Create spaces WORLD transform if not mc.objExists(self.worldNode): self.worldNode = mc.createNode('transform',n=self.worldNode) @@ -64,24 +64,24 @@ def create(self,ctrl,targetList=[],abrTargetList=[],nameTag='',worldParent=''): if len(worldParent): currentWorldParent = mc.listRelatives(self.worldNode,p=1)[0] print('Spaces WORLD node already exists and is parented to '+currentWorldParent+'!!') - + # Adjust TargetList Arrays targetList.insert(0,self.worldNode) targetList.insert(0,par) abrTargetList.insert(0,'SuperMover') abrTargetList.insert(0,'Default') - + # Create SPACES constraint transform spacesNode = mc.duplicate(par,rr=1,rc=1,n=ctrl+'_spn')[0] mc.delete(mc.listRelatives(spacesNode,ad=1)) - + # Unlock Constraint Offset for ch in self.allChannels: mc.setAttr(spacesNode+'.'+ch,l=False,k=False) - + # Reparent hierarchy mc.parent(spacesNode,par) mc.parent(ctrl,spacesNode) - + # Add targetOffset attributes to link to constraint mc.addAttr(spacesNode,ln='targetOffsetTranslate',sn='tot',at='double3') mc.addAttr(spacesNode,ln='targetOffsetTranslateX',sn='totx',at='double',p='targetOffsetTranslate') @@ -91,10 +91,10 @@ def create(self,ctrl,targetList=[],abrTargetList=[],nameTag='',worldParent=''): mc.addAttr(spacesNode,ln='targetOffsetRotateX',sn='torx',at='double',p='targetOffsetRotate') mc.addAttr(spacesNode,ln='targetOffsetRotateY',sn='tory',at='double',p='targetOffsetRotate') mc.addAttr(spacesNode,ln='targetOffsetRotateZ',sn='torz',at='double',p='targetOffsetRotate') - + # Set targetOffset attributes as keyable for ch in self.channels: mc.setAttr(spacesNode+'.to'+ch,k=True) - + # Add default offset value attributes mc.addAttr(spacesNode,ln='defaultOffset',at='compound',numberOfChildren=2,m=True) mc.addAttr(spacesNode,ln='defaultOffsetTranslate',sn='dot',at='double3',p='defaultOffset') @@ -105,7 +105,7 @@ def create(self,ctrl,targetList=[],abrTargetList=[],nameTag='',worldParent=''): mc.addAttr(spacesNode,ln='defaultOffsetRotateX',sn='dorx',at='doubleAngle',p='defaultOffsetRotate') mc.addAttr(spacesNode,ln='defaultOffsetRotateY',sn='dory',at='doubleAngle',p='defaultOffsetRotate') mc.addAttr(spacesNode,ln='defaultOffsetRotateZ',sn='dorz',at='doubleAngle',p='defaultOffsetRotate') - + # Setup .spaces attribute enumString = '' for abr in abrTargetList: enumString += abr+':' @@ -114,17 +114,17 @@ def create(self,ctrl,targetList=[],abrTargetList=[],nameTag='',worldParent=''): mc.setAttr(spacesNode+'.spaces',k=1) else: mc.addAttr(spacesNode+'.spaces',e=1,en=enumString) - + # Name Tag if not len(nameTag): nameTag = ctrl if not mc.objExists(spacesNode+'.nameTag'): mc.addAttr(spacesNode,ln='nameTag',dt='string') mc.setAttr(spacesNode+'.nameTag',nameTag,type='string') - + # Create constraint spacesNodeConstraint = '' for i in range(len(targetList)): - + # Add target to constraint if not i: # First iteration - Create new constraint @@ -132,28 +132,28 @@ def create(self,ctrl,targetList=[],abrTargetList=[],nameTag='',worldParent=''): else: # Add to existing constraint mc.parentConstraint(targetList[i],spacesNode,mo=True,w=0.0) - + # Unlock target offset attributes for ch in self.channels: mc.setAttr(spacesNodeConstraint+'.target['+str(i)+'].to'+ch,l=False,k=True) - + translateOffset = mc.getAttr(spacesNodeConstraint+'.target['+str(i)+'].targetOffsetTranslate')[0] rotateOffset = mc.getAttr(spacesNodeConstraint+'.target['+str(i)+'].targetOffsetRotate')[0] - + mc.setAttr(spacesNode+'.defaultOffset',l=False) mc.setAttr(spacesNode+'.defaultOffset['+str(i)+'].dot',translateOffset[0],translateOffset[1],translateOffset[2]) mc.setAttr(spacesNode+'.defaultOffset['+str(i)+'].dor',rotateOffset[0],rotateOffset[1],rotateOffset[2]) mc.setAttr(spacesNode+'.defaultOffset',l=True) - + # Connect spacesNode to Constraint weightAliasList = mc.parentConstraint(spacesNodeConstraint,q=True,weightAliasList=True) for i in range(len(targetList)): - + # Create targetWeight attribute on spacesNode mc.addAttr(spacesNode,ln=weightAliasList[i],min=0.0,max=1.0,dv=0.0) mc.setAttr(spacesNode+'.'+weightAliasList[i],l=False,k=True) mc.connectAttr(spacesNode+'.'+weightAliasList[i], spacesNodeConstraint+'.'+weightAliasList[i], f=True) - + # Connect targetOffset attributes translateOffset = mc.getAttr(spacesNode+'.defaultOffset['+str(i)+'].dot')[0] rotateOffset = mc.getAttr(spacesNode+'.defaultOffset['+str(i)+'].dor')[0] @@ -161,17 +161,17 @@ def create(self,ctrl,targetList=[],abrTargetList=[],nameTag='',worldParent=''): mc.setAttr(spacesNode+'.tor',rotateOffset[0],rotateOffset[1],rotateOffset[2],l=False) mc.connectAttr(spacesNode+'.tot', spacesNodeConstraint+'.target['+str(i)+'].tot',f=True) mc.connectAttr(spacesNode+'.tor', spacesNodeConstraint+'.target['+str(i)+'].tor',f=True) - + # Set all spaces to Default self.switch(ctrl,'Default',0) - + # Return result return [spacesNode,spacesNodeConstraint] - + def add(self,ctrl,targetList=[],abrTargetList=[],nameTag=''): ''' add to an existing spaces node - @param targetList: list of target transforms for the space node constraint + @param targetList: list of target transforms for the space node constraint @type targetList: list @param abrTargetList: list of abreviated target names. Used in UI. @type abrTargetList: list @@ -180,9 +180,9 @@ def add(self,ctrl,targetList=[],abrTargetList=[],nameTag=''): @param nameTag: Shortened, descriptive name for control. Used in UI. @type nameTag: str ''' - + if not len(abrTargetList): abrTargetList = targetList - + # Determine SPACE node spacesNode = '' try: @@ -191,56 +191,56 @@ def add(self,ctrl,targetList=[],abrTargetList=[],nameTag=''): #print('Spaces node does not exists. Running Spaces().create() instead!') result = self.create(ctrl,targetList,abrTargetList,nameTag) return result - + # Determine SPACE node constraint spacesNodeConstraint = self.getSpacesConstraint(ctrl) - + # Verify target list for target in targetList: if not mc.objExists(target): raise UserInputError('Target object '+target+' does not exists!') - + # Add Constraint Targets targetListSize = len(mc.parentConstraint(spacesNodeConstraint,q=True,tl=True)) for i in range(len(targetList)): - + mc.parentConstraint(targetList[i],spacesNodeConstraint,mo=True,w=0.0) - + # Unlock target offset attributes for ch in self.channels: mc.setAttr(spacesNodeConstraint+'.target['+str(targetListSize)+'].to'+ch,l=False,k=True) - + # Store Default Offset Values translateOffset = mc.getAttr(spacesNodeConstraint+'.target['+str(targetListSize)+'].targetOffsetTranslate')[0] rotateOffset = mc.getAttr(spacesNodeConstraint+'.target['+str(targetListSize)+'].targetOffsetRotate')[0] - + mc.setAttr(spacesNode+'.defaultOffset',l=False) mc.setAttr(spacesNode+'.defaultOffset['+str(targetListSize)+'].dot',translateOffset[0],translateOffset[1],translateOffset[2]) mc.setAttr(spacesNode+'.defaultOffset['+str(targetListSize)+'].dor',rotateOffset[0],rotateOffset[1],rotateOffset[2]) mc.setAttr(spacesNode+'.defaultOffset',l=True) - + # Connect spacesNode offset to constraintNode offset mc.connectAttr(spacesNode+'.tot', spacesNodeConstraint+'.target['+str(targetListSize)+'].tot',f=True) mc.connectAttr(spacesNode+'.tor', spacesNodeConstraint+'.target['+str(targetListSize)+'].tor',f=True) - + # Increment targetListSize targetListSize += 1 - + # Add and connect new weight attrs weightAliasList = mc.parentConstraint(spacesNodeConstraint,q=True,weightAliasList=True) for i in range(len(weightAliasList)): if not mc.objExists(spacesNode+'.'+weightAliasList[i]): mc.addAttr(spacesNode,ln=weightAliasList[i],k=True,min=0.0,max=1.0,dv=0.0) mc.connectAttr(spacesNode+'.'+weightAliasList[i],spacesNodeConstraint+'.'+weightAliasList[i],f=True) - + # Append .spaces attribute enumString = mc.addAttr(spacesNode +'.spaces',q=True,en=True) + ':' for abr in abrTargetList: enumString += abr+':' mc.addAttr(spacesNode+'.spaces',e=True,en=enumString) - + # Return result return [spacesNode,spacesNodeConstraint] - + def switch(self,ctrl,newTarget,key=0,keyPreviousFrame=0,maintainPos=1): ''' Switch spaces state for specified control. @@ -253,56 +253,56 @@ def switch(self,ctrl,newTarget,key=0,keyPreviousFrame=0,maintainPos=1): @param keyPreviousFrame: Set key on previous frame for spaces state before switch. Only relevant when key is also True. @type keyPreviousFrame: bool ''' - + # Find Space Node and Relevant Constraint spacesNode = self.getSpacesNode(ctrl) spacesNodeConstraint = self.getSpacesConstraint(ctrl) weightAliasList = mc.parentConstraint(spacesNodeConstraint,q=True,weightAliasList=True) targetTransform = mc.parentConstraint(spacesNodeConstraint,q=True,targetList=True) - + # Get newTarget constraint index - validSpaces = mc.addAttr(spacesNode+'.spaces',q=True,en=True).split(':') + validSpaces = mc.addAttr(spacesNode+'.spaces',q=True,en=True).split(':') if not validSpaces.count(newTarget): raise UserInputError('Object '+newTarget+' is not a spaces target for '+ctrl) newTargetIndex = validSpaces.index(newTarget) - + # Key previous frame if keyPreviousFrame: self.key(ctrl,[],mc.currentTime(q=True)-1,) - + # Calculate constraint offsets to maintain control position if maintainPos: # Create temporary constraint transform temp = mc.duplicate(spacesNode,rr=True,rc=True,n='temp_spaceNode') mc.delete(mc.listRelatives(temp[0],ad=True,pa=True)) - + # Unlock channels for ch in self.channels: mc.setAttr(temp[0]+'.'+ch,l=False) - + # Create temporary parent constraint conn = mc.parentConstraint(targetTransform[newTargetIndex],temp[0],mo=True) translateOffset = mc.getAttr(conn[0]+'.target[0].targetOffsetTranslate')[0] rotateOffset = mc.getAttr(conn[0]+'.target[0].targetOffsetRotate')[0] - + # Delete temporary nodes mc.delete(conn) mc.delete(temp) - + # Set Constraint Offsets mc.setAttr(spacesNode+'.tot',translateOffset[0],translateOffset[1],translateOffset[2]) mc.setAttr(spacesNode+'.tor',rotateOffset[0],rotateOffset[1],rotateOffset[2]) - + # Set Constraint Target Weights for i in range(len(validSpaces)): mc.setAttr(spacesNode+'.'+weightAliasList[i],i==newTargetIndex) # Set ".spaces" attribute mc.setAttr(spacesNode+'.spaces',newTargetIndex) - + # Reset to default offset values if not maintainPos: self.reset(ctrl,0,0) - + # Key current frame if key: self.key(ctrl,[],mc.currentTime(q=True)) - + def switchAllTo(self,target,char='',key=0,keyPrevious=0,maintainPos=1): ''' Switch all spaces nodes to the specified target @@ -321,7 +321,7 @@ def switchAllTo(self,target,char='',key=0,keyPrevious=0,maintainPos=1): child = mc.listRelatives(spacesNode,c=1) try: self.switch(child[0],target,key,keyPrevious,maintainPos) except: print('Object '+child[0]+' is not able to be placed in the space of '+target+'! Skipping control!!') - + def key(self,ctrl,targetList=[],frame=None): ''' Set keyframe on spaces relevant attribute for the given control and specified target(s). @@ -334,27 +334,27 @@ def key(self,ctrl,targetList=[],frame=None): ''' # Check default frame value if frame == None: frame = mc.currentTime(q=True) - + # Get spaces info spacesNode = self.getSpacesNode(ctrl) spacesNodeConstraint = self.getSpacesConstraint(ctrl) weightAliasList = mc.parentConstraint(spacesNodeConstraint,q=True,weightAliasList=True) - + # Check target list if not len(targetList): targetList = self.targetList(ctrl) - + # Get target indices targetIndexList = [] for target in targetList: targetIndexList.append(self.targetIndex(ctrl,target)) - + # Set keys for i in targetIndexList: mc.setKeyframe(spacesNode+'.'+weightAliasList[i],t=frame,itt='clamped',ott='step') mc.setKeyframe(spacesNode+'.tot',t=frame,itt='clamped',ott='step') mc.setKeyframe(spacesNode+'.tor',t=frame,itt='clamped',ott='step') mc.setKeyframe(spacesNode+'.spaces',t=frame,itt='clamped',ott='step') - + def reset(self,ctrl,key=0,keyPreviousFrame=0): ''' Reset spaces constraint offsets for the specified control @@ -368,25 +368,25 @@ def reset(self,ctrl,key=0,keyPreviousFrame=0): # Get spaces info spacesNode = self.getSpacesNode(ctrl) spacesNodeConstraint = self.getSpacesConstraint(ctrl) - + # Check spaces attribute if not mc.objExists(spacesNode+'.spaces'): raise UserInputError('Object '+spacesNode+ 'does not contain a ".spaces" attribute!') targetIndex = mc.getAttr(spacesNode+'.spaces') target = self.targetList(ctrl)[targetIndex] - + # Key previous frame if keyPreviousFrame: self.key(ctrl,[],mc.currentTime(q=True)-1,) - + # Reset Offset Values translateOffset = mc.getAttr(spacesNode+'.defaultOffset['+str(targetIndex)+'].dot')[0] rotateOffset = mc.getAttr(spacesNode+'.defaultOffset['+str(targetIndex)+'].dor')[0] mc.setAttr(spacesNode+'.tot',translateOffset[0],translateOffset[1],translateOffset[2]) mc.setAttr(spacesNode+'.tor',rotateOffset[0],rotateOffset[1],rotateOffset[2]) - + # Key current frame if key: self.key(ctrl) - + def targetList(self,ctrl): ''' Return the spaces target list for the specified control or spaces node @@ -398,7 +398,7 @@ def targetList(self,ctrl): # Get target list info spacesList = mc.addAttr(spacesNode+'.spaces',q=True,en=True) return spacesList.split(':') - + def targetIndex(self,ctrl,target): ''' Return the target index for the specified control and spaces target @@ -408,11 +408,11 @@ def targetIndex(self,ctrl,target): @type ctrl: str ''' spacesNode = self.getSpacesNode(ctrl) - validSpaces = mc.addAttr(spacesNode+'.spaces',q=True,en=True).split(':') + validSpaces = mc.addAttr(spacesNode+'.spaces',q=True,en=True).split(':') if not validSpaces.count(target): raise UserInputError('Object '+target+' is not a spaces target for '+ctrl) return validSpaces.index(target) - + def getSpacesNode(self,ctrl): ''' Return the name of the spaces node of the specified control @@ -421,7 +421,7 @@ def getSpacesNode(self,ctrl): ''' # Check control if mc.objExists(ctrl+'.spaces') and mc.objExists(ctrl+'.defaultOffset'): return ctrl - + # Determine spaces node parent = mc.listRelatives(ctrl,p=True) if parent == None: @@ -432,7 +432,7 @@ def getSpacesNode(self,ctrl): if not mc.objExists(parent[0]+'.spaces'): raise UserInputError('Spaces node '+parent[0]+ 'does not contain a ".spaces" attribute!') return parent[0] - + def getSpacesConstraint(self,ctrl): ''' Return the name of the spaces constraint node of the specified control @@ -447,33 +447,33 @@ def getSpacesConstraint(self,ctrl): if spaceTransConst[0] != spaceRotConst[0]: raise UserInputError('Translate and Rotate Constraint Mis-match on '+ctrl) return spaceTransConst[0] - + def updateOld(self): ''' Update old style spaces setup to work with new spaces procedures. ''' - # Get list of existing spaces nodes + # Get list of existing spaces nodes spacesNodeList = mc.ls('*_spn',r=1,et='transform') for spacesNode in spacesNodeList: spacesChild = mc.listRelatives(spacesNode,c=True,type='transform')[0] - + # Transfer .spaces attribute if mc.objExists(spacesChild+'.spaces'): enumString = mc.addAttr(spacesChild+'.spaces',q=True,en=True) mc.addAttr(spacesNode,ln='spaces',at='enum',en=enumString) mc.setAttr(spacesNode+'.spaces',k=1) mc.deleteAttr(spacesChild+'.spaces') - + # Transfer .nameTag attribute if mc.objExists(spacesChild+'.nameTag'): nameTagStr = mc.getAttr(spacesChild+'.nameTag') mc.addAttr(spacesNode,ln='nameTag',dt='string') mc.setAttr(spacesNode+'.nameTag',nameTagStr,type='string') mc.deleteAttr(spacesChild+'.nameTag') - + #===================================== # UI METHODS ========================= - + def ui_embed(self,parentLayout,char=''): ''' @param parentLayout: Parent UI layout to parent spaces UI to. @@ -483,56 +483,56 @@ def ui_embed(self,parentLayout,char=''): ''' # Get Character Prefix if char: char += ':' - + # List all spaces with given prefix spaceNodeList = mc.ls(char+'*_spn',r=True,et='transform') spaceNodeList = [i for i in spaceNodeList if not i.endswith('_con_spn')] - + # Generate target list with default elements targetList = ['SuperMover','Default'] - + # Build Spaces List from eNum attributes for node in spaceNodeList: if mc.objExists(node+'.spaces'): enumList = mc.addAttr(node+'.spaces',q=True,en=True).split(':') [targetList.append(i) for i in enumList if not targetList.count(i)] - + # Begin UI Build if not mc.layout(parentLayout,q=True,ex=True): raise UserInputError('Parent layout '+parentLayout+' does not exists! Unable to embed Spaces UI!') - + mc.setParent(parentLayout) # Clear Layout childArray = mc.layout(parentLayout,q=True,ca=True) if type(childArray) == list: mc.deleteUI(childArray) - + # Add Spaces control layout mc.rowColumnLayout(self.uiRCL,numberOfColumns=5,columnWidth=[(1,160),(2,160),(3,80),(4,80),(5,80)]) - + # Add KeyFrame CheckBoxs mc.checkBoxGrp(self.uiKeyPreviousCBG,numberOfCheckBoxes=1,label="Key Before Switch",v1=0) mc.checkBoxGrp(self.uiKeyCBG,numberOfCheckBoxes=1,label="Key After Switch",v1=0) - + for i in range(3): mc.separator(h=20,style='none') - + mc.checkBoxGrp(self.uiMaintainPosCBG,numberOfCheckBoxes=1,label="Maintain Position",v1=1) - + for i in range(4): mc.separator(h=20,style='none') for i in range(5): mc.separator(h=20,style='single') - + # ALL OptionMenu mc.text(label='ALL') mc.optionMenuGrp(self.uiAllOMG,cw=(1,1),cal=(1,'center'),label='',cc='glTools.tools.spaces.Spaces().switchAllFromUI()') for item in targetList: mc.menuItem(label=item) - + mc.button(w=80,l='Reset',c='glTools.tools.spaces.Spaces().resetAllFromUI("'+char+'")') mc.button(w=80,l='Select',c='mc.select(mc.ls("'+char+'*_spn"))') mc.button(w=80,l='Key',c='glTools.tools.spaces.Spaces().keyAllFromUI("'+char+'")') - + for i in range(5): mc.separator(h=20,style='single') - + # Create attrEnumOptionMenu controls to accurately represent attribute values at all times. - # ie - Update on frame change + # ie - Update on frame change for spacesNode in spaceNodeList: tag = mc.getAttr(spacesNode+'.nameTag') mc.text(label=tag) @@ -541,7 +541,7 @@ def ui_embed(self,parentLayout,char=''): mc.button(w=80,l='Select',c='mc.select("'+spacesNode+'")') mc.button(w=80,l='Key',c='glTools.tools.spaces.Spaces().key("'+spacesNode+'")') #mc.separator(h=20,style='none') - + def ui(self,char=''): ''' Creates the main control interface for manipulating spaces @@ -552,16 +552,16 @@ def ui(self,char=''): win = self.managerUI if mc.window(win,q=True,ex=True): mc.deleteUI(win) win = mc.window(win,t='Spaces UI - '+char.upper()) - + # Create column layout for controls items spacesCL = mc.columnLayout('spacesUI_CL',adjustableColumn=True) - + # Open window mc.showWindow(win) - + # Embed control layout into window self.ui_embed(spacesCL,char) - + def switchFromUI(self,ctrl): ''' Switch a spaces nodes to the specified target from the spaces UI @@ -571,23 +571,23 @@ def switchFromUI(self,ctrl): # Determine spaces node spacesNode = self.getSpacesNode(ctrl) tag = mc.getAttr(spacesNode+'.nameTag') - + # Query Target # !!! optionMenu command no longer allows access to attrEnumOptionMenu !!! #target = mc.optionMenu(tag+'_switchAEO',q=True,v=True) targetIndex = mc.getAttr(mc.attrEnumOptionMenu(tag+'_switchAEO',q=True,dtg=True)) target = self.targetList(spacesNode)[targetIndex] - + # Check keyframe options key = mc.checkBoxGrp(self.uiKeyCBG,q=True,v1=True) keyPrevious = mc.checkBoxGrp(self.uiKeyPreviousCBG,q=True,v1=True) - + # Check offset options maintainPos = mc.checkBoxGrp(self.uiMaintainPosCBG,q=True,v1=True) - + # Do switch self.switch(ctrl,target,key,keyPrevious,maintainPos) - + def switchAllFromUI(self,char=''): ''' Switch all spaces nodes to the specified target from the UI. @@ -598,17 +598,17 @@ def switchAllFromUI(self,char=''): if not mc.optionMenuGrp(self.uiAllOMG,q=True,ex=True): raise UserInputError('OptionMenuGrp '+self.uiAllOMG+' does not exist!') target = mc.optionMenuGrp(self.uiAllOMG,q=True,v=True) - + # Check keyframe options key = mc.checkBoxGrp(self.uiKeyCBG,q=True,v1=True) keyPrevious = mc.checkBoxGrp(self.uiKeyPreviousCBG,q=True,v1=True) - + # Check offset options maintainPos = mc.checkBoxGrp(self.uiMaintainPosCBG,q=True,v1=True) - + # Do switch self.switchAllTo(target,char,key,keyPrevious,maintainPos) - + def resetFromUI(self,ctrl): ''' Reset spaces constraint offsets for the specified control from the spaces UI @@ -618,10 +618,10 @@ def resetFromUI(self,ctrl): # Get reset options key = mc.checkBoxGrp(self.uiKeyCBG,q=True,v1=True) keyPrevious = mc.checkBoxGrp(self.uiKeyPreviousCBG,q=True,v1=True) - + # Reset self.reset(ctrl,key,keyPrevious) - + def resetAllFromUI(self,char): ''' Reset spaces constraint offsets for all controls in the specified character namespace @@ -631,11 +631,11 @@ def resetAllFromUI(self,char): # Get key options key = mc.checkBoxGrp(self.uiKeyCBG,q=True,v1=True) keyPrevious = mc.checkBoxGrp(self.uiKeyPreviousCBG,q=True,v1=True) - + # Reset Spaces Nodes for spacesNode in mc.ls(char+'*_spn'): self.reset(spacesNode,key,keyPrevious) - + def keyAllFromUI(self,char): ''' Key all spaces nodes in the specified character namespace @@ -644,4 +644,4 @@ def keyAllFromUI(self,char): ''' # Key Spaces Nodes for spacesNode in mc.ls(char+'*_spn'): self.key(spacesNode) - \ No newline at end of file + diff --git a/tools/stretchyIkChain.py b/tools/stretchyIkChain.py index 4b0e881..9ccc65d 100644 --- a/tools/stretchyIkChain.py +++ b/tools/stretchyIkChain.py @@ -25,38 +25,38 @@ def build(ikHandle,scaleAxis='x',scaleAttr='',blendControl='',blendAttr='stretch # ========== # - Checks - # ========== - + # IkHandle if not mc.objExists(ikHandle): raise Exception('IK handle '+ikHandle+' does not exist!') - + # Blend blend = mc.objExists(blendControl) if blend and not mc.objExists(blendControl+'.'+blendAttr): mc.addAttr(blendControl,ln=blendAttr,at='double',min=0,max=1,dv=1) mc.setAttr(blendControl+'.'+blendAttr,e=True,k=True) blendAttr = blendControl+'.'+blendAttr - + # Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(ikHandle) - + # ===================== # - Get IkHandle Info - # ===================== - + # Get IK chain information ikJoints = glTools.utils.ik.getAffectedJoints(ikHandle) ikPos = mc.getAttr(ikHandle+'.t')[0] - + # Calculate actual joint lengths lengthNode = mc.createNode('plusMinusAverage',n=prefix+'length_plusMinusAverage') for j in range(len(ikJoints)-1): mc.connectAttr(ikJoints[j+1]+'.t'+scaleAxis,lengthNode+'.input1D['+str(j)+']') - + # Calculate Distance distNode = mc.createNode('distanceBetween',n=prefix+'_distanceBetween') mc.connectAttr(ikJoints[0]+'.parentMatrix[0]',distNode+'.inMatrix1',f=True) mc.connectAttr(ikHandle+'.parentMatrix[0]',distNode+'.inMatrix2',f=True) - + # -------------!!!!!!!!!! # Currently setting the translate attributes instead of connecting. # Direct connection was causing cycle check warnings @@ -66,16 +66,16 @@ def build(ikHandle,scaleAxis='x',scaleAttr='',blendControl='',blendAttr='stretch #mc.connectAttr(ik_joint[0]+'.t',distNode+'.point1',f=True) #mc.connectAttr(ikHandle+'.t',distNode+'.point2',f=True) # ------------- - + # =========== # - Stretch - # =========== - + # Calculate Stretch Scale Factor stretchNode = mc.createNode('multiplyDivide',n=prefix+'_stretch_multiplyDivide') mc.setAttr(stretchNode+'.operation',2) # Divide mc.connectAttr(distNode+'.distance',stretchNode+'.input1X',f=True) - + # Add Scale Compensation scaleNode = '' if mc.objExists(scaleAttr): @@ -85,7 +85,7 @@ def build(ikHandle,scaleAxis='x',scaleAttr='',blendControl='',blendAttr='stretch mc.connectAttr(scaleNode+'.output',stretchNode+'.input2X',f=True) else: mc.connectAttr(lengthNode+'.output1D',stretchNode+'.input2X',f=True) - + # Condition condNode = '' if not shrink: @@ -100,11 +100,11 @@ def build(ikHandle,scaleAxis='x',scaleAttr='',blendControl='',blendAttr='stretch # Set condition results mc.connectAttr(stretchNode+'.outputX',condNode+'.colorIfTrueR',f=True) mc.setAttr(condNode+'.colorIfFalseR',1) - + # ========= # - Blend - # ========= - + blendNode = '' if blend: blendNode = mc.createNode('blendTwoAttr',n=prefix+'_blend_blendTwoAttr') @@ -113,11 +113,11 @@ def build(ikHandle,scaleAxis='x',scaleAttr='',blendControl='',blendAttr='stretch mc.setAttr(blendNode+'.input[0]',1.0) if shrink: mc.connectAttr(stretchNode+'.outputX',blendNode+'.input[1]',f=True) else: mc.connectAttr(condNode+'.outColorR',blendNode+'.input[1]',f=True) - + # ===================== # - Connect To Joints - # ===================== - + # Attach output to joint scale for i in range(len(ikJoints)-1): if blend: @@ -125,13 +125,13 @@ def build(ikHandle,scaleAxis='x',scaleAttr='',blendControl='',blendAttr='stretch else: if shrink: mc.connectAttr(stretchNode+'.outputX',ikJoints[i]+'.s'+scaleAxis,f=True) else: mc.connectAttr(condNode+'.outColorR',ikJoints[i]+'.s'+scaleAxis,f=True) - + # Set ikHandle position. Make sure IK handle evaluates correctly! mc.setAttr(ikHandle+'.t',ikPos[0],ikPos[1],ikPos[2]) - + # ================= # - Return Result - # ================= - + result = [lengthNode,distNode,stretchNode,scaleNode,condNode,blendNode] return result diff --git a/tools/stretchyIkLimb.py b/tools/stretchyIkLimb.py index 3e35a78..bff1aae 100644 --- a/tools/stretchyIkLimb.py +++ b/tools/stretchyIkLimb.py @@ -24,135 +24,135 @@ def build( ikHandle, @param prefix: Name prefix for all builder created nodes. If left as deafult ('') prefix will be derived from ikHandle name. @type prefix: str ''' - + upperScaleAttr = 'upperLimbScale' lowerScaleAttr = 'lowerLimbScale' blendAttr = 'stretchToControl' biasAttr = 'stretchBias' - + # ============== # - Get Joints - # ============== - + ikJoints = glTools.utils.ik.getAffectedJoints(ikHandle) - + # ======================== # - Add Joint Attributes - # ======================== - + for ikJoint in ikJoints[:-1]: jntLen = glTools.utils.joint.length(ikJoint) mc.addAttr(ikJoint,ln='restLength',dv=jntLen) - + # ============================= # - Add IK Control Attributes - # ============================= - + # IK Control mc.addAttr(ikCtrl,ln=upperScaleAttr,min=0.01,dv=1.0,k=True) mc.addAttr(ikCtrl,ln=lowerScaleAttr,min=0.01,dv=1.0,k=True) mc.addAttr(ikCtrl,ln=blendAttr,min=0.0,max=1.0,dv=0.0,k=True) mc.addAttr(ikCtrl,ln=biasAttr,min=0.0,max=1.0,dv=0.5,k=True) - + # PV Control mc.addAttr(pvCtrl,ln=blendAttr,min=0.0,max=1.0,dv=0.0,k=True) - + # =============================== # - Create Limb Stretch Network - # =============================== - + # Limb Length - Character Scale limbCharScale = mc.createNode('multiplyDivide',n=prefix+'_characterScale_multiplyDivide') mc.setAttr(limbCharScale+'.operation',2) # Divide mc.connectAttr(scaleAttr,limbCharScale+'.input2X',f=True) mc.connectAttr(scaleAttr,limbCharScale+'.input2Y',f=True) mc.connectAttr(scaleAttr,limbCharScale+'.input2Z',f=True) - + # Rest Length limbRestLenNode = mc.createNode('plusMinusAverage',n=prefix+'_limbRestLength_plusMinusAverage') for i in range(len(ikJoints[:-1])): mc.connectAttr(ikJoints[i]+'.restLength',limbRestLenNode+'.input1D['+str(i)+']',f=True) - + # Limb Length limbDistNode = mc.createNode('distanceBetween',n=prefix+'_limbLength_distanceBetween') mc.connectAttr(ikJoints[0]+'.parentMatrix[0]',limbDistNode+'.inMatrix1',f=True) mc.connectAttr(ikCtrl+'.worldMatrix[0]',limbDistNode+'.inMatrix2',f=True) mc.connectAttr(limbDistNode+'.distance',limbCharScale+'.input1X',f=True) - + # Limb Length Diff limbDiffNode = mc.createNode('plusMinusAverage',n=prefix+'_limbLengthDiff_plusMinusAverage') mc.setAttr(limbDiffNode+'.operation',2) # Subtract mc.connectAttr(limbCharScale+'.outputX',limbDiffNode+'.input1D[0]',f=True) mc.connectAttr(limbRestLenNode+'.output1D',limbDiffNode+'.input1D[1]',f=True) - + # Bias Reverse limbBiasRev = mc.createNode('reverse',n=prefix+'_limbBias_reverse') mc.connectAttr(ikCtrl+'.'+biasAttr,limbBiasRev+'.inputX',f=True) - + # Upper Stretch Diff upperStretchDiff = mc.createNode('multDoubleLinear',n=prefix+'_upperStretchDiff_multDoubleLinear') mc.connectAttr(limbDiffNode+'.output1D',upperStretchDiff+'.input1',f=True) mc.connectAttr(ikCtrl+'.'+biasAttr,upperStretchDiff+'.input2',f=True) - + # Lower Stretch Diff lowerStretchDiff = mc.createNode('multDoubleLinear',n=prefix+'_lowerStretchDiff_multDoubleLinear') mc.connectAttr(limbDiffNode+'.output1D',lowerStretchDiff+'.input1',f=True) mc.connectAttr(limbBiasRev+'.outputX',lowerStretchDiff+'.input2',f=True) - + # Upper Stretch Length upperStretchLen = mc.createNode('addDoubleLinear',n=prefix+'_upperStretchTarget_addDoubleLinear') mc.connectAttr(ikJoints[0]+'.restLength',upperStretchLen+'.input1',f=True) mc.connectAttr(upperStretchDiff+'.output',upperStretchLen+'.input2',f=True) - + # Lower Stretch Length lowerStretchLen = mc.createNode('addDoubleLinear',n=prefix+'_lowerStretchTarget_addDoubleLinear') mc.connectAttr(ikJoints[1]+'.restLength',lowerStretchLen+'.input1',f=True) mc.connectAttr(lowerStretchDiff+'.output',lowerStretchLen+'.input2',f=True) - + # Upper Stretch Scale upperStretchScale = mc.createNode('multiplyDivide',n=prefix+'_upperStretchScale_multiplyDivide') mc.setAttr(upperStretchScale+'.operation',2) # Divide mc.connectAttr(upperStretchLen+'.output',upperStretchScale+'.input1X',f=True) mc.connectAttr(ikJoints[0]+'.restLength',upperStretchScale+'.input2X',f=True) - + # Lower Stretch Scale lowerStretchScale = mc.createNode('multiplyDivide',n=prefix+'_lowerStretchScale_multiplyDivide') mc.setAttr(lowerStretchScale+'.operation',2) # Divide mc.connectAttr(lowerStretchLen+'.output',lowerStretchScale+'.input1X',f=True) mc.connectAttr(ikJoints[1]+'.restLength',lowerStretchScale+'.input2X',f=True) - + # ===================================== # - Create Stretch To Control Network - # ===================================== - + # Shoulder to PV distance upperPvDist = mc.createNode('distanceBetween',n=prefix+'_upperPV_distanceBetween') mc.connectAttr(ikJoints[0]+'.parentMatrix[0]',upperPvDist+'.inMatrix1',f=True) mc.connectAttr(pvCtrl+'.worldMatrix[0]',upperPvDist+'.inMatrix2',f=True) mc.connectAttr(upperPvDist+'.distance',limbCharScale+'.input1Y',f=True) - + # Wrist to PV distance lowerPvDist = mc.createNode('distanceBetween',n=prefix+'_lowerPV_distanceBetween') mc.connectAttr(ikCtrl+'.worldMatrix[0]',lowerPvDist+'.inMatrix1',f=True) mc.connectAttr(pvCtrl+'.worldMatrix[0]',lowerPvDist+'.inMatrix2',f=True) mc.connectAttr(lowerPvDist+'.distance',limbCharScale+'.input1Z',f=True) - + # Upper to PV scale upperPvScale = mc.createNode('multiplyDivide',n=prefix+'_upperPV_multiplyDivide') mc.setAttr(upperPvScale+'.operation',2) # Divide mc.connectAttr(limbCharScale+'.outputY',upperPvScale+'.input1X',f=True) mc.connectAttr(ikJoints[0]+'.restLength',upperPvScale+'.input2X',f=True) - + # Lower to PV scale lowerPvScale = mc.createNode('multiplyDivide',n=prefix+'_lowerPV_multiplyDivide') mc.setAttr(lowerPvScale+'.operation',2) # Divide mc.connectAttr(limbCharScale+'.outputZ',lowerPvScale+'.input1X',f=True) mc.connectAttr(ikJoints[1]+'.restLength',lowerPvScale+'.input2X',f=True) - + # ============================ # - Create Condition Network - # ============================ - + # Limb Stretch - Condition limbStretchCondition = mc.createNode('condition',n=prefix+'_limbStretch_condition') mc.setAttr(limbStretchCondition+'.operation',2) # Greater Than @@ -162,116 +162,116 @@ def build( ikHandle, mc.setAttr(limbStretchCondition+'.colorIfFalse',1.0,1.0,1.0) mc.connectAttr(upperStretchScale+'.outputX',limbStretchCondition+'.colorIfTrueR',f=True) mc.connectAttr(lowerStretchScale+'.outputX',limbStretchCondition+'.colorIfTrueG',f=True) - + # Limb Stretch - Upper Blend upperLimbStretchBlend = mc.createNode('blendTwoAttr',n=prefix+'_upperLimbSTretch_blendTwoAttr') mc.connectAttr(ikCtrl+'.'+blendAttr,upperLimbStretchBlend+'.attributesBlender',f=True) mc.setAttr(upperLimbStretchBlend+'.input[0]',1.0) mc.connectAttr(limbStretchCondition+'.outColorR',upperLimbStretchBlend+'.input[1]',f=True) - + # Limb Stretch - Lower Blend lowerLimbStretchBlend = mc.createNode('blendTwoAttr',n=prefix+'_lowerLimbSTretch_blendTwoAttr') mc.connectAttr(ikCtrl+'.'+blendAttr,lowerLimbStretchBlend+'.attributesBlender',f=True) mc.setAttr(lowerLimbStretchBlend+'.input[0]',1.0) mc.connectAttr(limbStretchCondition+'.outColorG',lowerLimbStretchBlend+'.input[1]',f=True) - + # Limb Stretch - Upper Scale upperLimbStretchScale = mc.createNode('multDoubleLinear',n=prefix+'_upperStretchScale_multDoubleLinear') mc.connectAttr(upperLimbStretchBlend+'.output',upperLimbStretchScale+'.input1',f=True) mc.connectAttr(ikCtrl+'.upperLimbScale',upperLimbStretchScale+'.input2',f=True) - + # Limb Stretch - Lower Scale lowerLimbStretchScale = mc.createNode('multDoubleLinear',n=prefix+'_lowerStretchScale_multDoubleLinear') mc.connectAttr(lowerLimbStretchBlend+'.output',lowerLimbStretchScale+'.input1',f=True) mc.connectAttr(ikCtrl+'.lowerLimbScale',lowerLimbStretchScale+'.input2',f=True) - + # Stretch To Control - Upper Blend upStretchToCtrlBlend = mc.createNode('blendTwoAttr',n=prefix+'_upperStretchToControl_blendTwoAttr') mc.connectAttr(pvCtrl+'.'+blendAttr,upStretchToCtrlBlend+'.attributesBlender',f=True) mc.connectAttr(upperLimbStretchScale+'.output',upStretchToCtrlBlend+'.input[0]',f=True) mc.connectAttr(upperPvScale+'.outputX',upStretchToCtrlBlend+'.input[1]',f=True) - + # Stretch To Control - Lower Mult stretchToCtrlAllMult = mc.createNode('multDoubleLinear',n=prefix+'_stretchCombineWt_multDoubleLinear') mc.connectAttr(ikCtrl+'.'+blendAttr,stretchToCtrlAllMult+'.input1',f=True) mc.connectAttr(pvCtrl+'.'+blendAttr,stretchToCtrlAllMult+'.input2',f=True) - + # Stretch To Control - Lower Blend loStretchToCtrlBlend = mc.createNode('blendTwoAttr',n=prefix+'_lowerStretchToControl_blendTwoAttr') mc.connectAttr(stretchToCtrlAllMult+'.output',loStretchToCtrlBlend+'.attributesBlender',f=True) mc.connectAttr(lowerLimbStretchScale+'.output',loStretchToCtrlBlend+'.input[0]',f=True) mc.connectAttr(lowerPvScale+'.outputX',loStretchToCtrlBlend+'.input[1]',f=True) - + # ======================= # - End Effector Offset - # ======================= - + # Get End Effector endEffector = mc.listConnections(ikHandle+'.endEffector',s=True,d=False)[0] endEffectorCon = mc.listConnections(endEffector+'.tx',s=True,d=False)[0] - + # Disconnect End Effector mc.disconnectAttr(endEffectorCon+'.tx',endEffector+'.tx') mc.disconnectAttr(endEffectorCon+'.ty',endEffector+'.ty') mc.disconnectAttr(endEffectorCon+'.tz',endEffector+'.tz') - + # End Effector Offset endOffsetReverse = mc.createNode('reverse',n=prefix+'_limbEndOffset_reverse') mc.connectAttr(ikCtrl+'.'+blendAttr,endOffsetReverse+'.inputX',f=True) endOffsetMultiply = mc.createNode('multDoubleLinear',n=prefix+'limbEndOffset_multDoubleLinear') mc.connectAttr(pvCtrl+'.'+blendAttr,endOffsetMultiply+'.input1',f=True) mc.connectAttr(endOffsetReverse+'.outputX',endOffsetMultiply+'.input2',f=True) - + # End Effector Offset Length endEffectorScale = mc.createNode('multDoubleLinear',n=prefix+'_limbEndScale_multDoubleLinear') mc.connectAttr(ikJoints[1]+'.restLength',endEffectorScale+'.input1',f=True) mc.connectAttr(lowerPvScale+'.outputX',endEffectorScale+'.input2',f=True) - + # End Effector Offset Scale endEffectorScaleMD = mc.createNode('multiplyDivide',n=prefix+'_limbEndScale_multiplyDivide') mc.setAttr(endEffectorScaleMD+'.operation',2) # Divide mc.connectAttr(endEffectorScale+'.output',endEffectorScaleMD+'.input1X',f=True) mc.connectAttr(loStretchToCtrlBlend+'.output',endEffectorScaleMD+'.input2X',f=True) - + # End Effector Offset Blend endEffectorBlend = mc.createNode('blendTwoAttr',n=prefix+'_limbEndOffset_blendTwoAttr') mc.connectAttr(endOffsetMultiply+'.output',endEffectorBlend+'.attributesBlender',f=True) mc.connectAttr(ikJoints[1]+'.restLength',endEffectorBlend+'.input[0]',f=True) #mc.connectAttr(endEffectorScale+'.output',endEffectorBlend+'.input[1]',f=True) mc.connectAttr(endEffectorScaleMD+'.outputX',endEffectorBlend+'.input[1]',f=True) - + # ===================== # - Connect To Joints - # ===================== - + mc.connectAttr(upStretchToCtrlBlend+'.output',ikJoints[0]+'.s'+scaleAxis,f=True) mc.connectAttr(loStretchToCtrlBlend+'.output',ikJoints[1]+'.s'+scaleAxis,f=True) - + # =========================== # - Connect To End Effector - # =========================== - + # Check Negative Translate Values endEffectorNegate = '' if mc.getAttr(endEffectorCon+'.t'+scaleAxis) < 0.0: - + # Negate Result endEffectorNegate = mc.createNode('unitConversion',n=prefix+'_endEffectorNegate_unitConversio') mc.connectAttr(endEffectorBlend+'.output',endEffectorNegate+'.input',f=True) mc.setAttr(endEffectorNegate+'.conversionFactor',-1) mc.connectAttr(endEffectorNegate+'.output',endEffector+'.t'+scaleAxis,f=True) - + else: - + # Direct Connection mc.connectAttr(endEffectorBlend+'.output',endEffector+'.t'+scaleAxis,f=True) - + # ================= # - Return Result - # ================= - + result = {} - + result['ikHandle'] = ikHandle result['endEffector'] = endEffector result['ikCtrl'] = ikCtrl @@ -305,6 +305,6 @@ def build( ikHandle, result['endEffectorScaleMult'] = endEffectorScaleMD result['endEffectorBlend'] = endEffectorBlend result['endEffectorNegate'] = endEffectorNegate - + return result diff --git a/tools/stretchyIkSpline.py b/tools/stretchyIkSpline.py index 23a3082..1447e96 100644 --- a/tools/stretchyIkSpline.py +++ b/tools/stretchyIkSpline.py @@ -55,7 +55,7 @@ def stretchyIkSpline( ikHandle, blendControl=blendControl, blendAttr=blendAttr, prefix=prefix) - + # Return Result return result @@ -91,23 +91,23 @@ def stretchyIkSpline_parametric( ikHandle, ''' # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(ikHandle) - + # Check objects if not mc.objExists(ikHandle): raise UserInputError('IK handle '+ikHandle+' does not exist!') - + # Check scaleAttr scale = mc.objExists(scaleAttr) - + # Check blendControl blend = mc.objExists(blendControl) if blend and not mc.objExists(blendControl+'.'+blendAttr): mc.addAttr(blendControl,ln=blendAttr,at='double',min=0,max=1,dv=1,k=True) blendAttr = blendControl+'.'+blendAttr - + # Get IK spline information ik_joints = glTools.utils.ik.getAffectedJoints(ikHandle) ik_curve = mc.listConnections(ikHandle+'.inCurve',s=True,d=False,sh=True)[0] - + # Get curve parameter information minu = mc.getAttr(ik_curve+'.minValue') maxu = mc.getAttr(ik_curve+'.maxValue') @@ -117,7 +117,7 @@ def stretchyIkSpline_parametric( ikHandle, if maxPercent < 1.0: maxu -= udist * (1.0-maxPercent) udist = maxu - minu inc = udist / (len(ik_joints)-1) - + # Create pointOnCurveInfo and attach to curve pointOnCurveList = [] for i in range(len(ik_joints)): @@ -135,7 +135,7 @@ def stretchyIkSpline_parametric( ikHandle, mc.setAttr(poc+'.parameter',minu+inc*i) # Append To Return List pointOnCurveList.append(poc) - + # Create distanceBetween and connect to curvePoints distNodeList = [] for i in range(len(ik_joints)-1): @@ -145,7 +145,7 @@ def stretchyIkSpline_parametric( ikHandle, distNodeList.append(dist) mc.connectAttr(pointOnCurveList[i]+'.position',dist+'.point1',f=True) mc.connectAttr(pointOnCurveList[i+1]+'.position',dist+'.point2',f=True) - + # Create multiply node and connect to joints multNodeList = [] scaleNodeList = [] @@ -157,14 +157,14 @@ def stretchyIkSpline_parametric( ikHandle, mc.setAttr(md+'.operation',2) # Divide mc.connectAttr(distNodeList[i]+'.distance',md+'.input1X',f=True) mc.connectAttr(ik_joints[i+1]+'.t'+scaleAxis,md+'.input2X',f=True) - + # Create blend node blendNode = '' if blend: blendNode = mc.createNode('blendTwoAttr',n=prefix+ind+'_blendTwoAttr') mc.connectAttr(blendAttr,blendNode+'.attributesBlender',f=True) mc.setAttr(blendNode+'.input[0]',1.0) - + # Setup scale compensation if scale: # Add global scale contribution @@ -186,7 +186,7 @@ def stretchyIkSpline_parametric( ikHandle, mc.connectAttr(blendNode+'.output',ik_joints[i]+'.s'+scaleAxis,f=True) else: mc.connectAttr(md+'.outputX',ik_joints[i]+'.s'+scaleAxis,f=True) - + # Return result return [pointOnCurveList,distNodeList,multNodeList,scaleNodeList] @@ -213,25 +213,25 @@ def stretchyIkSpline_arcLength( ikHandle, ''' # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(ikHandle) - + # Check objects if not mc.objExists(ikHandle): raise UserInputError('IK handle '+ikHandle+' does not exist!') - + # Check blendControl blend = mc.objExists(blendControl) if blend and not mc.objExists(blendControl+'.'+blendAttr): mc.addAttr(blendControl,ln=blendAttr,at='double',min=0,max=1,dv=1,k=True) blendAttr = blendControl+'.'+blendAttr - + # Get IK spline information ik_joints = glTools.utils.ik.getAffectedJoints(ikHandle) ik_curve = mc.listConnections(ikHandle+'.inCurve',s=1,d=0,sh=1)[0] ik_length = mc.arclen(ik_curve) - + # Setup multily node multDbl = mc.createNode('multDoubleLinear',n=prefix+'_multDoubleLinear') mc.setAttr(multDbl+'.input2',1.0/ik_length) - + # Setup blend blendNode = '' if blend: @@ -239,7 +239,7 @@ def stretchyIkSpline_arcLength( ikHandle, mc.addAttr(blendNode,ln=self.defaultScaleAttr,at='double',min=1,max=1,dv=1) mc.connectAttr(blendAttr,blendNode+'.attributesBlender',f=True) mc.connectAttr(blendNode+'.'+self.defaultScaleAttr,blendNode+'.input[0]',f=True) - + # Create curveInfo crvInfo = mc.createNode('curveInfo',n=prefix+'_curveInfo') mc.connectAttr(ik_curve+'.worldSpace[0]',crvInfo+'.inputCurve',f=True) @@ -254,6 +254,6 @@ def stretchyIkSpline_arcLength( ikHandle, else: for i in range(len(ik_joints)-1): mc.connectAttr(multDbl+'.output',ik_joints[i]+'.s'+scaleAxis,f=True) - + # Return result return [crvInfo,multDbl,blendNode] diff --git a/tools/subCurve.py b/tools/subCurve.py index ffa42e0..3fbd290 100644 --- a/tools/subCurve.py +++ b/tools/subCurve.py @@ -8,32 +8,32 @@ def fromRefCurve(curve,refCurve,rebuildToRef=True): # Get start and end reference points stRef = mc.pointOnCurve(refCurve,top=True,pr=0.0,p=True) enRef = mc.pointOnCurve(refCurve,top=True,pr=1.0,p=True) - + # Get boundary parameters stParam = glTools.utils.curve.closestPoint(curve,stRef) enParam = glTools.utils.curve.closestPoint(curve,enRef) - + # SubCurve subCurve = mc.detachCurve(curve,p=[stParam,enParam],replaceOriginal=False,ch=False) mc.delete(subCurve[0],subCurve[2]) subCurve = mc.rename(subCurve[1],curve+'_subCurve') - + if rebuildToRef: degree = mc.getAttr(refCurve+'.degree') spans = mc.getAttr(refCurve+'.spans') mc.rebuildCurve(subCurve,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=0,s=spans,d=degree,tol=0) - + # Return result return subCurve - + def fromPoint(curve,pnt=[0.0,0.0,0.0],replaceOrig=False,keepHistory=True): ''' ''' # Get subCurve parameter param = glTools.utils.curve.closestPoint(curve,pnt) - + # Detach curve subCurve = mc.detachCurve(curve,p=param,replaceOriginal=replaceOrig,ch=keepHistory) - + # Return result return subCurve diff --git a/tools/surfaceConstrainedTransform.py b/tools/surfaceConstrainedTransform.py index b993ef1..54b491c 100644 --- a/tools/surfaceConstrainedTransform.py +++ b/tools/surfaceConstrainedTransform.py @@ -10,13 +10,13 @@ def surfaceConstraint(obj,surface,point=True,orient=True,normalAxis='x',upAxis=' @type point: bool @param orient: Constrain orient (rotate) @type orient: bool - @param normalAxis: Constrained transform axis to align with surface normal + @param normalAxis: Constrained transform axis to align with surface normal @type normalAxis: str @param upAxis: Constrained transform axis to align with defined upVector @type upAxis: str - @param upMode: Constraint upVector mode. Valid values are 'scene', 'object', 'objectrotation', 'vector' or 'none'. + @param upMode: Constraint upVector mode. Valid values are 'scene', 'object', 'objectrotation', 'vector' or 'none'. @type upMode: str - @param upVector: Constraint upVector. + @param upVector: Constraint upVector. @type upVector: list or tuple @param upObject: Constraint upVector object. Only needed for 'object' or 'objectrotation' upVector modes. @type upObject: str @@ -27,111 +27,111 @@ def surfaceConstraint(obj,surface,point=True,orient=True,normalAxis='x',upAxis=' ''' # Build axis dictionary axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # ========== # - Checks - # ========== - + if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + if not mc.objExists(surface): raise Exception('Surface "'+surface+'" does not exist!') - + if not axisDict.keys().count(normalAxis): raise Exception('Invalid normal axis specified "'+normalAxis+'"!') - + if not axisDict.keys().count(upAxis): raise Exception('Invalid up axis specified "'+upAxis+'"!') - + if ((upMode == 'object') or (upMode == 'objectrotation')) and not mc.objExists(upObject): raise Exception('Invalid up object specified "'+upObject+'"!') - + # =============================== # - Create Constraint Transform - # =============================== - + surfConnNode = mc.createNode('transform',n=prefix+'_surfConn_grp') - + # ================================ # - Constraint point (translate) - # ================================ - + if point: - + if pointMode == 0: - + # Geometry Constraint pntConn = mc.pointConstraint(obj,surfConnNode,n=prefix+'_pointConstraint') geoConn = mc.geometryConstraint(surface,surfConnNode,n=prefix+'_geometryConstraint') - + else: - + # ======================= # - Boundary Constraint - # ======================= - + # World Position (vectorProduct) vecProduct = mc.createNode('vectorProduct',n=prefix+'_worldPos_vectorProduct') mc.setAttr(vecProduct+'.operation',4) # Point Matrix Product mc.connectAttr(obj+'.worldMatrix',vecProduct+'.matrix',f=True) - + # Closest Point On Surface cposNode = mc.createNode('closestPointOnSurface',n=prefix+'_surfacePos_closestPointOnSurface') mc.connectAttr(surface+'.worldSpace[0]',cposNode+'.inputSurface',f=True) mc.connectAttr(vecProduct+'.output',cposNode+'.inPoint',f=True) - + # Point On Surface Info posiNode = mc.createNode('pointOnSurfaceInfo',n=prefix+'_surfacePt_pointOnSurfaceInfo') mc.connectAttr(surface+'.worldSpace[0]',cposNode+'.inputSurface',f=True) mc.connectAttr(cposNode+'.parameterU',posiNode+'.parameterU',f=True) mc.connectAttr(cposNode+'.parameterV',posiNode+'.parameterV',f=True) - + # Calculate Offset offsetNode = mc.createNode('plusMinusAverage',n=prefix+'_surfaceOffset_plusMinusAverage') mc.setAttr(offsetNode+'.operation',2) # Subtract mc.connectAttr(vecProduct+'.output',offsetNode+'.input3D[0]',f=True) mc.connectAttr(cposNode+'.position',offsetNode+'.input3D[1]',f=True) - + # Offset * Normal (dotProduct) dotProduct = mc.createNode('vectorProduct',n=prefix+'_dotProduct_vectorProduct') mc.setAttr(dotProduct+'.operation',1) # Dot Product mc.connectAttr(offsetNode+'.ouput3D',dotProduct+'.input1',f=True) mc.connectAttr(posiNode+'.normal',dotProduct+'.input2',f=True) - + # Boundary Condition condition = mc.createNode('condition',n=prefix+'_condition') mc.setAttr(condition+'.operation',2) # Greater Than mc.connectAttr(dotProduct+'.outputX',condition+'.firstTerm',f=True) mc.connectAttr(vecProduct+'.output',condition+'.colorIfTrue',f=True) mc.connectAttr(cposNode+'.position',condition+'.colorIfFalse',f=True) - + # Connect to transform mc.connectAttr(condition+'.outColor',surfConnNode+'.t',f=True) - + else: - + # Point Constraint pntConn = mc.pointConstraint(obj,surfConnNode,n=prefix+'_pointConstraint') - + # ============================= # - Constrain Orient (rotate) - # ============================= - + if orient: - + # Normal Constraint normConn = mc.normalConstraint(surface,surfConnNode,aim=axisDict[normalAxis],u=axisDict[upAxis],wut=upMode,wu=upVector,wuo=upObject,n=prefix+'_normalConstraint') - + else: - + # Orient Constraint oriConn = mc.normalConstraint(obj,surfConnNode,n=prefix+'_orientConstraint') - + # ================= # - Return Result - # ================= - + return surfConnNode def blendTarget(slaveTransform,driverAttr,attrMin=0.0,attrMax=1.0,translate=True,rotate=False,scale=False,prefix=''): @@ -142,23 +142,23 @@ def blendTarget(slaveTransform,driverAttr,attrMin=0.0,attrMax=1.0,translate=True raise Exception('Slave transform "'+slaveTransform+'" does not exist!') if not mc.objExists(driverAttr): raise Exception('Driver attribute "'+driverAttr+'" does not exist!') - + # Check blendTarget node if mc.objExists(slaveTransform): pass - + # Create target locator targetLoc = mc.spaceLocator(n=prefix+'_loc')[0] - + # Parent target locator slaveParent = mc.listRelatives(slaveTransform,p=True,pa=True) if not slaveParent: raise Exception('Slave transform has no transform parent!') mc.parent(targetLoc,slaveParent[0]) - + # Check blendCombine nodes slaveTransConn = mc.listConnections(slaveTransform+'.t',s=True,d=False) slaveRotateConn = mc.listConnections(slaveTransform+'.r',s=True,d=False) slaveScaleConn = mc.listConnections(slaveTransform+'.s',s=True,d=False) - + # - + diff --git a/tools/switchControlAttr.py b/tools/switchControlAttr.py index 0775ba5..039d904 100644 --- a/tools/switchControlAttr.py +++ b/tools/switchControlAttr.py @@ -30,11 +30,11 @@ def create( switchObject, # ========== # - Checks - # ========== - + # Check switchObject if not mc.objExists(switchObject): raise Exception('Switch object "'+switchObject+'" does not exist!') - + # Compare Target and Enum List if not targetAttrList or not targetEnumList: raise Exception('Visibility target or enum list has zero elements!') @@ -44,21 +44,21 @@ def create( switchObject, if targetIndexList: if len(targetAttrList) != len(targetIndexList): raise Exception('Visibility target and index list length mis-match!') - + # ================================= # - Create Visibility Switch Attr - # ================================= - + # Check Visibility Switch Attr if not mc.objExists(switchObject+'.'+switchAttr): - + # Build Enum Value targetEnum = '' for i in targetEnumList: targetEnum += i+':' # Add switch attr mc.addAttr(switchObject,ln=switchAttr,nn=switchName,at='enum',en=targetEnum) mc.setAttr(switchObject+'.'+switchAttr,e=True,cb=True) - + # Create Custom Visibility Index (choice) target_choice = '' if targetIndexList: @@ -68,30 +68,30 @@ def create( switchObject, for i in range(len(targetIndexList)): mc.setAttr(target_choice+'.targetIndex['+str(i)+']',targetIndexList[i]) mc.connectAttr(target_choice+'.targetIndex['+str(i)+']',target_choice+'.input['+str(i)+']',f=True) - + # ====================== # - Connect Visibility - # ====================== - + for i in range(len(targetEnumList)): - + # Check targetAttrList if not targetAttrList[i]: continue - + # Create Condition Node conditionNode = mc.createNode('condition',n=prefix+'_'+targetEnumList[i]+'Target_condition') mc.setAttr(conditionNode+'.firstTerm',i) mc.setAttr(conditionNode+'.colorIfTrue',1,0,1) mc.setAttr(conditionNode+'.colorIfFalse',0,1,0) - + # Connect Condition Node conditionInput = switchObject+'.'+switchAttr if targetIndexList: conditionInput = target_choice+'.output' mc.connectAttr(conditionInput,conditionNode+'.secondTerm',f=True) - + # Connect Each Item in List - Vis ON for targetAttr in targetAttrList[i]: - + # Check Target Attribute if not mc.objExists(targetAttr): raise Exception('Attribute "'+targetAttr+'" does not exist!') @@ -99,13 +99,13 @@ def create( switchObject, raise Exception('Object "'+targetAttr+'" is not a valid attribute!') if not mc.getAttr(targetAttr,se=True): raise Exception('Attribute "'+targetAttr+'" is locked or has incoming connections!') - + # Connect attribute mc.connectAttr(conditionNode+'.outColorR',targetAttr,f=True) - + # ================= # - Return Result - # ================= - + return (switchObject+'.'+switchAttr) diff --git a/tools/symmetryTable.py b/tools/symmetryTable.py index 9f329b5..5c21d77 100644 --- a/tools/symmetryTable.py +++ b/tools/symmetryTable.py @@ -2,16 +2,16 @@ import copy class SymmetryTable(object): - + def __init__(self): - + self.symTable = [] self.asymTable = [] self.positiveVertexList = [] self.positiveIndexList = [] self.negativeVertexList = [] self.negativeIndexList = [] - + def buildSymTable(self,mesh,axis=0,tol=0.001,usePivot=False): ''' Build symmetry table for specified mesh @@ -34,16 +34,16 @@ def buildSymTable(self,mesh,axis=0,tol=0.001,usePivot=False): aPosVertTrans=[] aVtxTrans=[] aVtx2Trans=[] - + # Set constants mAxisInd = axis axis2Ind = (mAxisInd + 1) % 3 axis3Ind = (mAxisInd + 2) % 3 midOffsetTol = -0.0000001 - + # Reset counter vertCounter = 0 - + # Check pivot if usePivot: aVtxTrans = mc.xform(mesh,q=True,ws=True,rp=True) @@ -54,12 +54,12 @@ def buildSymTable(self,mesh,axis=0,tol=0.001,usePivot=False): meshParent = mc.listRelatives(mesh,p=True)[0] bBox = mc.xform(meshParent,q=True,ws=True,boundingBox=True) mid = bBox[mAxisInd] + ((bBox[mAxisInd+3] - bBox[mAxisInd])/2) - + # Get total verts totVtx = mc.polyEvaluate(mesh,v=True) # Initialize abSymTable abSymTable = range(int(totVtx)) - + # Determin pos and neg verts for i in range(totVtx): vtx = mesh+'.vtx['+str(i)+']' @@ -75,13 +75,13 @@ def buildSymTable(self,mesh,axis=0,tol=0.001,usePivot=False): aNegVerts.append(vtx) aNegVertsInt.append(i) aNegVertTrans.append(aVtxTrans[mAxisInd]) - + # Update class member variabels self.positiveVertexList = copy.deepcopy(aPosVerts) self.positiveIndexList = copy.deepcopy(aPosVertsInt) self.negativeVertexList = copy.deepcopy(aNegVerts) self.negativeIndexList = copy.deepcopy(aNegVertsInt) - + # Find Non-Symmetrical verts for i in range(len(aPosVerts)): vtx = aPosVerts[i] @@ -90,7 +90,7 @@ def buildSymTable(self,mesh,axis=0,tol=0.001,usePivot=False): aPosVerts[i] = 'm' vertCounter+=1 continue - + for j in range(len(aNegVerts)): if aNegVerts[j] == 'm': continue negOffset = mid - aNegVertTrans[j] @@ -98,7 +98,7 @@ def buildSymTable(self,mesh,axis=0,tol=0.001,usePivot=False): aNegVerts[j] = 'm' vertCounter+=1 continue - + if abs(posOffset-negOffset) <= tol: aVtxTrans = mc.xform(vtx,q=True,ws=True,t=True) aVtx2Trans = mc.xform(aNegVerts[j],q=True,ws=True,t=True) @@ -111,21 +111,21 @@ def buildSymTable(self,mesh,axis=0,tol=0.001,usePivot=False): vertCounter += 2 aPosVerts[i] = aNegVerts[j] = 'm' break - + # Determine asymmetrical vertices aNonSymVerts = [] [aNonSymVerts.append(i) for i in aPosVerts if i != 'm'] [aNonSymVerts.append(i) for i in aNegVerts if i != 'm'] - + if vertCounter != totVtx: print 'Warning: Mesh object "'+mesh+'" is not symmetrical!' - + # Update class member variabels self.symTable = abSymTable self.asymTable = aNonSymVerts - + # ================= # - Return Result - # ================= - + return self.symTable diff --git a/tools/tendon.py b/tools/tendon.py index 881889d..52f7d22 100644 --- a/tools/tendon.py +++ b/tools/tendon.py @@ -8,21 +8,21 @@ def build(startPt=[-1,0,0],endPt=[1,0,0],attachments=2,outputMesh=False,radius=0 ''' ''' # - + # Get points startPt = glTools.utils.base.getMPoint(startPt) endPt = glTools.utils.base.getMPoint(endPt) - + # Get offset offsetVec = endPt - startPt offsetInc = 1.0/(attachments-1) - + # Get Point List ptList = [] for i in range(attachments-1): pt = startPt + (offsetVec * offsetInc) ptList.append(pt[0],pt[1],pt[2]) - + # Build tendon curve base tendonCrv = glTools.utils.curve.createFromPointList(ptList,1,prefix) # Generate tendon curve locators @@ -30,21 +30,21 @@ def build(startPt=[-1,0,0],endPt=[1,0,0],attachments=2,outputMesh=False,radius=0 # Rebuild tendon curve if attachments > 2: tendonRebuild = mc.rebuildCurve(tendonCrv,ch=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=0,d=3,tol=0.01) - - + + def crvTendon(curve,geo,precision=4,prefix='tendon'): ''' ''' # rebuildCurve degree 1 baseCurve = mc.rebuildCurve(curve,ch=0,s=1,d=1,rpo=1,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1) - + # create cv locators baseLocs = glTools.utils.curve.locatorCurve(baseCurve,prefix=prefix+'_baseCrv') - + # generate geo constraint curve geoCurve = mc.rebuildCurve(baseCurve,ch=1,s=precsion,d=1,rpo=0,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1) geoCurveLocs = glTools.utils.curve.locatorCurve(geoCurve,prefix=prefix+'_geoCrv') - + # generate reference curve refCurve = mc.rebuildCurve(baseCurve,ch=1,s=precsion,d=1,rpo=0,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1) refCurveInfo = mc.createNode('curveInfo',n=prefix+'_ref_curveInfo') @@ -54,11 +54,11 @@ def crvTendon(curve,geo,precision=4,prefix='tendon'): refNull = mc.group(em=True,n=prefix+'_ref'+str(i)+'_null') mc.connectAttr(refCurveInfo+'.controlPoints['+str(i)+']',refNull+'.t') refCurveLocs.append(refNull) - + # Locator Constraints for i in range(precsion+1): mc.pointConstraint(refCurveLocs[i],geoCurveLocs[i]) mc.geometryConstraint(geo,geoCurveLocs[i]) - + # fitBspline bSpline = mc.fitBspline(geoCurve,ch=1) diff --git a/tools/timeWarp.py b/tools/timeWarp.py index 26d5381..7d5c4e8 100644 --- a/tools/timeWarp.py +++ b/tools/timeWarp.py @@ -5,19 +5,19 @@ def timeWarp(animCurves,prefix): ''' # Check anim curves if not animCurves: return - + # Get anim playback start and end st = mc.playbackOptions(q=True,min=True) en = mc.playbackOptions(q=True,max=True) - + # Create time warp curve timeWarpCrv = mc.createNode('animCurveTT',n=prefix+'_timeWarp') mc.setKeyframe(timeWarpCrv,t=st,v=st) mc.setKeyframe(timeWarpCrv,t=en,v=en) - + # Attach timeWarp for animCurve in animCurves: - + # Check curve type crvType = mc.objectType(animCurve) if crvType == 'animCurveTL' or crvType == 'animCurveTA' or crvType == 'animCurveTU': diff --git a/tools/transferComponentSelection.py b/tools/transferComponentSelection.py index 88fb679..b3e7ebc 100644 --- a/tools/transferComponentSelection.py +++ b/tools/transferComponentSelection.py @@ -9,35 +9,35 @@ def transferComponentSelection(sourceSelection,targetMesh,threshold=0.0001): # Check selection target mesh if not mc.objExists(targetMesh): raise Exception('Target mesh "'+targetMesh+'" does not exist!') - + # Flatten selection sourceSelection = mc.ls(sourceSelection,fl=True) - + # Get mesh points tPtArray = glTools.utils.base.getMPointArray(targetMesh) tPtLen = tPtArray.length() - + # Initialize component selection transfer list tPtBool = [False for i in range(tPtLen)] - + # Initialize selection list tSel = [] - + # Transfer selection for sel in sourceSelection: - + # Get selection point pt = mc.pointPosition(sel) pt = OpenMaya.MPoint(pt[0],pt[1],pt[2],1.0) - + # Find closest component cDist = 99999 cIndex = -1 for i in range(tPtLen): - + # Check component selection transfer list if tPtBool[i]: continue - + # Check distance to current point dist = (pt-tPtArray[i]).length() if dist < cDist: @@ -45,12 +45,12 @@ def transferComponentSelection(sourceSelection,targetMesh,threshold=0.0001): cIndex = i # Test threshold if dist < threshold: break - + # Append selection tSel.append(targetMesh+'.vtx['+str(cIndex)+']') - + # Update component selection transfer list tPtBool[i] = True - + # Return result return tSel diff --git a/tools/transferDeformerWeights.py b/tools/transferDeformerWeights.py index 500506b..a19ab7b 100644 --- a/tools/transferDeformerWeights.py +++ b/tools/transferDeformerWeights.py @@ -20,10 +20,10 @@ def closestPointWeights(pts,mesh,tol=0.001): # ========== # - Checks - # ========== - + if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + if glTools.utils.transform.isTransform(mesh): meshShape = mc.listRelatives(mesh,s=True,ni=True,pa=True) if not meshShape: raise Exception('Unable to get shape from mesh!') @@ -31,46 +31,46 @@ def closestPointWeights(pts,mesh,tol=0.001): else: meshShape = mesh mesh = mc.listRelatives(meshShape,p=True)[0] - + # ========================= # - Build MeshIntersector - # ========================= - + meshPt = OpenMaya.MPointOnMesh() meshIntersector = OpenMaya.MMeshIntersector() meshObj = glTools.utils.base.getMObject(meshShape) meshMat = glTools.utils.transform.getMatrix(mesh) meshFn = OpenMaya.MFnMesh(meshObj) meshIntersector.create(meshObj,meshMat) - + # ======================= # - Build Point Weights - # ======================= - + # Initialize Float Pointers for Barycentric Coords uUtil = OpenMaya.MScriptUtil() vUtil = OpenMaya.MScriptUtil() uPtr = uUtil.asFloatPtr() vPtr = vUtil.asFloatPtr() - + wt = [] for i in range(len(pts)): - + # Get Target Point pt = glTools.utils.base.getMPoint(pts[i]) - + # Get Closest Point Data meshIntersector.getClosestPoint(pt,meshPt) meshPt.getBarycentricCoords(uPtr,vPtr) u = OpenMaya.MScriptUtil(uPtr).asFloat() v = OpenMaya.MScriptUtil(vPtr).asFloat() baryWt = [u,v,1.0-(u+v)] - + # Get Triangle Vertex IDs idUtil = OpenMaya.MScriptUtil() idPtr = idUtil.asIntPtr() meshFn.getPolygonTriangleVertices(meshPt.faceIndex(),meshPt.triangleIndex(),idPtr) - + # Remove Small Values (Tolerance) for n in range(3): if baryWt[n] > (1.0-tol): @@ -82,18 +82,18 @@ def closestPointWeights(pts,mesh,tol=0.001): if baryWt[n-1] > baryWt[n-2]: baryWt[n-1] += baryWt[n] else: baryWt[n-2] += baryWt[n] baryWt[n] = 0.0 - + # Build Point Weights ptWt = {} for n in range(3): if baryWt[n] > tol: ptWt[OpenMaya.MScriptUtil().getIntArrayItem(idPtr,n)] = baryWt[n] wt.append(ptWt) - + # ================= # - Return Result - # ================= - + return wt def mirrorWeights( wts, @@ -123,37 +123,37 @@ def mirrorWeights( wts, # ========== # - Checks - # ========== - + # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Check Axis if not axis in 'xyz': raise Exception('Invalid axis value!') - + # =================== # - Get Mesh Points - # =================== - + pts = glTools.utils.mesh.getPoints(mesh) - + # Check Point Count if len(pts) != len(wts): raise Exception('Weights/points mis-match!') - + # Mirror Points if axis == 'x': pts = [[-i[0],i[1],i[2]] for i in pts] if axis == 'y': pts = [[i[0],-i[1],i[2]] for i in pts] if axis == 'z': pts = [[i[0],i[1],-i[2]] for i in pts] - + # ================== # - Mirror Weights - # ================== - + m_wts = [] pt_wts = closestPointWeights(pts,mesh,tol=0.001) for i in range(len(wts)): - + # Check Skipped Mirror Weights if not flip: axisVal = pts['xyz'.index(axis)]*-1 @@ -163,22 +163,22 @@ def mirrorWeights( wts, if not posToNeg and (axisVal < 0): m_wts.append(wts[i]) continue - + # Calculate Mirror Weight m_wts.append(0.0) for n in pt_wts[i]: m_wts[-1] += wts[n] * pt_wts[i][n] - + # ================= # - Apply Weights - # ================= - + if deformer: glTools.utils.deformer.setWeights(deformer,m_wts,deformedGeo) - + # ================= # - Return Result - # ================= - + return m_wts def transferWeights( wts, @@ -202,39 +202,39 @@ def transferWeights( wts, # ========== # - Checks - # ========== - + # Check Mesh if not glTools.utils.mesh.isMesh(srcGeo): raise Exception('Source geometry '+srcGeo+' is not a polygon mesh!') if not glTools.utils.mesh.isMesh(dstGeo): raise Exception('Destination geometry '+dstGeo+' is not a polygon mesh!') - + # =================== # - Get Mesh Points - # =================== - + pts = glTools.utils.mesh.getPoints(dstGeo) - + # ==================== # - Transfer Weights - # ==================== - + t_wts = [] pt_wts = closestPointWeights(pts,srcGeo,tol=0.001) for i in range(len(pt_wts)): t_wts.append(0) for n in pt_wts[i]: t_wts[-1] += wts[n] * pt_wts[i][n] - + # ================= # - Apply Weights - # ================= - + if deformer: glTools.utils.deformer.setWeights(deformer,t_wts,deformedGeo) - + # ================= # - Return Result - # ================= - + return t_wts diff --git a/tools/transformDrivenBlend.py b/tools/transformDrivenBlend.py index 515db2f..8d7d038 100644 --- a/tools/transformDrivenBlend.py +++ b/tools/transformDrivenBlend.py @@ -10,20 +10,20 @@ def freezeCtrlScale(ctrl): mc.setAttr(mdn+'.input1',1.0,1.0,1.0) mc.setAttr(mdn+'.operation',2) mc.connectAttr(mdn+'.output',ctrl+'.s',f=True) - + def unfreezeCtrlScale(ctrl): ''' ''' mdn = mc.listConnections(ctrl+'.s',s=True,d=False) if mdn: mc.delete(mdn) - + def setTranslateLimits(ctrl,tx=True,ty=True,tz=True): ''' ''' if(tx): mc.transformLimits(ctrl,tx=(-1.0,1.0),etx=(1,1)) if(ty): mc.transformLimits(ctrl,ty=(-1.0,1.0),ety=(1,1)) if(tz): mc.transformLimits(ctrl,tz=(-1.0,1.0),etz=(1,1)) - + def driveShape(blendShape,target,driveAttr,minValue=-1.5,maxValue=1.5,prefix=''): ''' @param blendShape: The blendShape node to drive @@ -47,22 +47,22 @@ def driveShape(blendShape,target,driveAttr,minValue=-1.5,maxValue=1.5,prefix='') driveAttr = driveAttr.replace(driveObj+'.','') if not mc.objExists(driveObj+'.'+driveAttr): mc.addAttr(driveObj,ln=driveAttr,min=minValue,max=maxValue,dv=0,k=True) - + # Create remapValue node remapNode = mc.createNode('remapValue',n=prefix+'_remapValue') - + # Connect drive attribute mc.connectAttr(driveObj+'.'+driveAttr,remapNode+'.inputValue') - + # Remap input value to target limits mc.setAttr(remapNode+'.inputMin',minValue) mc.setAttr(remapNode+'.inputMax',maxValue) mc.setAttr(remapNode+'.outputMin',minValue) mc.setAttr(remapNode+'.outputMax',maxValue) - + # Connect to blendShape target attributes mc.connectAttr(remapNode+'.outValue',blendShape+'.'+target) - + # Return result return remapNode @@ -93,30 +93,30 @@ def drive2Shapes(blendShape,target1,target2,driveAttr,minValue=-1.5,maxValue=1.5 driveAttr = driveAttr.replace(driveObj+'.','') if not mc.objExists(driveObj+'.'+driveAttr): mc.addAttr(driveObj,ln=driveAttr,min=minValue,max=maxValue,dv=0,k=True) - + # Create remapValue nodes remapNode1 = mc.createNode('remapValue',n=prefix+'_target1neg_remapValue') remapNode2 = mc.createNode('remapValue',n=prefix+'_target2pos_remapValue') - + # Connect drive attribute mc.connectAttr(driveObj+'.'+driveAttr,remapNode1+'.inputValue') mc.connectAttr(driveObj+'.'+driveAttr,remapNode2+'.inputValue') - + # Remap input value to target limits mc.setAttr(remapNode1+'.inputMin',minValue) mc.setAttr(remapNode1+'.inputMax',overlap) mc.setAttr(remapNode1+'.outputMin',-minValue) mc.setAttr(remapNode1+'.outputMax',0.0) - + mc.setAttr(remapNode2+'.inputMin',-overlap) mc.setAttr(remapNode2+'.inputMax',maxValue) mc.setAttr(remapNode2+'.outputMin',0.0) mc.setAttr(remapNode2+'.outputMax',maxValue) - + # Connect to blendShape target attributes mc.connectAttr(remapNode1+'.outValue',blendShape+'.'+target1) mc.connectAttr(remapNode2+'.outValue',blendShape+'.'+target2) - + # Return result return [remapNode1,remapNode2] diff --git a/tools/transformGeometry.py b/tools/transformGeometry.py index 4cfac7c..7d8347d 100644 --- a/tools/transformGeometry.py +++ b/tools/transformGeometry.py @@ -15,47 +15,47 @@ def create(geo,transform,prefix=None): # ========== # - Checks - # ========== - + if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist! Unable to transform geometry...') if not mc.objExists(transform): raise Exception('Transform "'+transform+'" does not exist! Unable to transform geometry...') if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(geo) - + # ====================== # - Transform Geometry - # ====================== - + # Find Geometry Shapes to Transform geoShapes = mc.ls(mc.listRelatives(geo,s=True,ni=True) or [],type=['mesh','nurbsCurve','nurbsSurface']) or [] if not geoShapes: raise Exception('Object "'+geo+'" has no geometry shape! Unable to transform geometry...') - + # Transform Geometry Shapes transformGeoList = [] for i in range(len(geoShapes)): - + # Create Transform Geometry Node ind = glTools.utils.stringUtils.alphaIndex(i) transformGeo = mc.createNode('transformGeometry',n=prefix+'_'+ind+'_transformGeometry') mc.connectAttr(transform+'.worldMatrix[0]',transformGeo+'.transform',f=True) - + # Check Shape Input shapeType = mc.objectType(geoShapes[i]) shapeInputSrc = glTools.utils.shape.shapeInputSrc(geoShapes[i]) shapeInputAttr = glTools.utils.shape.shapeInputAttr(geoShapes[i]) shapeOutputAttr = glTools.utils.shape.shapeOutputAttr(geoShapes[i]) - + # Connect Transform Geometry Node if shapeInputSrc: - + # -- Existing Input Source mc.connectAttr(shapeInputSrc,transformGeo+'.inputGeometry',f=True) mc.connectAttr(transformGeo+'.outputGeometry',geoShapes[i]+'.'+shapeInputAttr,f=True) - + else: - + # -- No Input Source geoShapeOrig = mc.rename(geoShapes[i],geoShapes[i]+'Orig') geoShape = mc.createNode(shapeType,n=geoShapes[i],p=geo) @@ -63,7 +63,7 @@ def create(geo,transform,prefix=None): mc.connectAttr(geoShapeOrig+'.'+shapeOutputAttr,transformGeo+'.inputGeometry',f=True) mc.connectAttr(transformGeo+'.outputGeometry',geoShape+'.'+shapeInputAttr,f=True) mc.setAttr(geoShapeOrig+'.intermediateObject',True) - + # Apply Overrides overrideAttrs = [ 'template', 'overrideEnabled', @@ -73,13 +73,13 @@ def create(geo,transform,prefix=None): 'overrideColor' ] for overrideAttr in overrideAttrs: mc.setAttr(geoShape+'.'+overrideAttr,mc.getAttr(geoShapeOrig+'.'+overrideAttr)) - - + + # Append Output List transformGeoList.append(transformGeo) - + # ================= # - Return Result - # ================= - + return transformGeoList diff --git a/tools/transformWire.py b/tools/transformWire.py index 02dc1e0..96f5ef3 100644 --- a/tools/transformWire.py +++ b/tools/transformWire.py @@ -8,17 +8,17 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers # ========== # - Checks - # ========== - + if srcNS: srcNS += ':' if dstNS: dstNS += ':' - + # Duplicate Wire to Generate Base if not baseCrv: baseCrv = mc.duplicate(wireCrv,n=wireCrv+'Base')[0] - + # ======================== # - Target (IK) Locators - # ======================== - + # Create Locators (Source) hip_src = mc.spaceLocator(n='hip_src')[0] lf_foot_src = mc.spaceLocator(n='lf_foot_src')[0] @@ -30,7 +30,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers rt_hand_src = mc.spaceLocator(n='rt_hand_src')[0] lf_elbow_src = mc.spaceLocator(n='lf_elbow_src')[0] rt_elbow_src = mc.spaceLocator(n='rt_elbow_src')[0] - + # Create Locators (Destination) hip_dst = mc.spaceLocator(n='hip_dst')[0] lf_foot_dst = mc.spaceLocator(n='lf_foot_dst')[0] @@ -42,7 +42,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers rt_hand_dst = mc.spaceLocator(n='rt_hand_dst')[0] lf_elbow_dst = mc.spaceLocator(n='lf_elbow_dst')[0] rt_elbow_dst = mc.spaceLocator(n='rt_elbow_dst')[0] - + # Position Locators (Source) mc.delete(mc.parentConstraint(srcNS+'Hips',hip_src)) mc.delete(mc.parentConstraint(srcNS+'LeftFoot',lf_foot_src)) @@ -54,7 +54,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers mc.delete(mc.parentConstraint(srcNS+'RightHand',rt_hand_src)) mc.delete(mc.parentConstraint(srcNS+'LeftForeArm',lf_elbow_src)) mc.delete(mc.parentConstraint(srcNS+'RightForeArm',rt_elbow_src)) - + # Position Locators (Destination) mc.delete(mc.parentConstraint(dstNS+'Hips',hip_dst)) mc.delete(mc.parentConstraint(dstNS+'LeftFoot',lf_foot_dst)) @@ -66,7 +66,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers mc.delete(mc.parentConstraint(dstNS+'RightHand',rt_hand_dstc)) mc.delete(mc.parentConstraint(dstNS+'LeftLeg',lf_elbow_dst)) mc.delete(mc.parentConstraint(dstNS+'RightLeg',rt_elbow_dst)) - + # Parent Locators (Source) mc.parent(hip_src,srcNS+'Hips') mc.parent(lf_foot_src,srcNS+'LeftFoot') @@ -78,66 +78,66 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers mc.parent(rt_hand_loc,srcNS+'RightHand') mc.parent(lf_elbow_loc,srcNS+'LeftForeArm') mc.parent(rt_elbow_loc,srcNS+'RightForeArm') - + # ===================== # - Connect To Source - # ===================== - + # Hip Constraint hip_con = mc.parentConstraint(hip_dst,dstNS+'Hips')[0] - + # ------------- # - Legs (IK) - # ------------- - + lf_leg_ik = mc.ikHandle(startJoint=dstNS+'LeftUpLeg',endEffector=dstNS+'LeftFoot',solver='ikRPsolver',n='lf_leg_ik')[0] rt_leg_ik = mc.ikHandle(startJoint=dstNS+'RightUpLeg',endEffector=dstNS+'RightFoot',solver='ikRPsolver',n='rt_leg_ik')[0] - + # Limit Roll Bones mc.transformLimits(dstNS+'LeftLegRoll',ry=(0,0),rz=(0,0),ery=(1,1),erz=(1,1)) mc.transformLimits(dstNS+'RightLegRoll',ry=(0,0),rz=(0,0),ery=(1,1),erz=(1,1)) mc.transformLimits(dstNS+'LeftUpLegRoll',ry=(0,0),rz=(0,0),ery=(1,1),erz=(1,1)) mc.transformLimits(dstNS+'RightUpLegRoll',ry=(0,0),rz=(0,0),ery=(1,1),erz=(1,1)) - + # Constrain IK lf_leg_ik_con = mc.parentConstraint(lf_foot_dst,lf_leg_ik) rt_leg_ik_con = mc.parentConstraint(rt_foot_dst,rt_leg_ik) lf_leg_pv_con = mc.poleVectorConstraint(lf_knee_dst,lf_leg_ik) rt_leg_pv_con = mc.poleVectorConstraint(rt_knee_dst,rt_leg_ik) - + # Constrain Foot lf_foot_con = mc.orientConstraint(lf_foot_dst,dstNS+'LeftFoot') rt_foot_con = mc.orientConstraint(rt_foot_dst,dstNS+'RightFoot') - + # ------------- # - Arms (IK) - # ------------- - + if addArmIk: - + lf_arm_ik = mc.ikHandle(startJoint=dstNS+'LeftArm',endEffector=dstNS+'LeftHand',solver='ikRPsolver',n='lf_arm_ik')[0] rt_arm_ik = mc.ikHandle(startJoint=dstNS+'RightArm',endEffector=dstNS+'RightHand',solver='ikRPsolver',n='rt_arm_ik')[0] - + # Limit Roll Bones mc.transformLimits(dstNS+'LeftArmRoll',ry=(0,0),rz=(0,0),ery=(1,1),erz=(1,1)) mc.transformLimits(dstNS+'RightArmRoll',ry=(0,0),rz=(0,0),ery=(1,1),erz=(1,1)) mc.transformLimits(dstNS+'LeftForeArmRoll',ry=(0,0),rz=(0,0),ery=(1,1),erz=(1,1)) mc.transformLimits(dstNS+'RightForeArmRoll',ry=(0,0),rz=(0,0),ery=(1,1),erz=(1,1)) - + # Constrain IK lf_arm_ik_con = mc.parentConstraint(lf_hand_dst,lf_arm_ik) rt_arm_ik_con = mc.parentConstraint(rt_hand_dst,rt_arm_ik) lf_arm_pv_con = mc.poleVectorConstraint(lf_elbow_dst,lf_leg_ik) rt_arm_pv_con = mc.poleVectorConstraint(rt_elbow_dst,rt_leg_ik) - + # Constrain Hand lf_hand_con = mc.orientConstraint(lf_hand_dst,dstNS+'LeftHand') rt_hand_con = mc.orientConstraint(rt_hand_dst,dstNS+'RightHand') - + # ----------------------- # - Upper Body Rotation - # ----------------------- - + body_jnts = [ 'Spine', 'Spine1', 'Spine2', @@ -145,13 +145,13 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers 'RightShoulder', 'Neck', 'Head' ] - + arm_jnts = [ 'Arm', 'ArmRoll', 'ForeArm', 'ForeArmRoll', 'Hand' ] - + hand_jnts = [ 'HandThumb1', 'HandThumb2', 'HandThumb3', @@ -171,34 +171,34 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers 'HandRing3', 'HandMiddle3', 'HandIndex3' ] - + foot_jnts = [ 'ToeBase' ] - + # Connect Body for jnt in body_jnts: mc.connectAttr(srcNS+jnt+'.r',dstNS+jnt+'.r',f=True) - + # Connect Feet for side in ['Left','Right']: for jnt in foot_jnts: mc.connectAttr(srcNS+side+jnt+'.r',dstNS+side+jnt+'.r',f=True) - + # Connect Arms if not addArmIk: for side in ['Left','Right']: for jnt in arm_jnts: mc.connectAttr(srcNS+side+jnt+'.r',dstNS+side+jnt+'.r',f=True) - + # Connect Fingers if connectFingers: for side in ['Left','Right']: for jnt in hand_jnts: mc.connectAttr(srcNS+side+jnt+'.r',dstNS+side+jnt+'.r',f=True) - + # ======================== # - Transform Wire Setup - # ======================== - + # Hips glTools.utils.transformWire.create( wireCrv = wireCrv, baseCrv = baseCrv, @@ -212,7 +212,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers connectRot=True, orientList=[], prefix='') - + # Legs (lf_foot) glTools.utils.transformWire.create( wireCrv = wireCrv, baseCrv = baseCrv, @@ -226,7 +226,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers connectRot=True, orientList=[], prefix='') - + # Legs (rt_foot) glTools.utils.transformWire.create( wireCrv = wireCrv, baseCrv = baseCrv, @@ -240,7 +240,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers connectRot=True, orientList=[], prefix='') - + # Legs (lf_knee) glTools.utils.transformWire.create( wireCrv = wireCrv, baseCrv = baseCrv, @@ -254,7 +254,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers connectRot=True, orientList=[], prefix='') - + # Legs (rt_knee) glTools.utils.transformWire.create( wireCrv = wireCrv, baseCrv = baseCrv, @@ -268,10 +268,10 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers connectRot=True, orientList=[], prefix='') - + # Arms if addArmIk: - + # Arms (lf_hand) glTools.utils.transformWire.create( wireCrv = wireCrv, baseCrv = baseCrv, @@ -285,7 +285,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers connectRot=True, orientList=[], prefix='') - + # Arms (rt_hand) glTools.utils.transformWire.create( wireCrv = wireCrv, baseCrv = baseCrv, @@ -299,7 +299,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers connectRot=True, orientList=[], prefix='') - + # Arms (lf_elbow) glTools.utils.transformWire.create( wireCrv = wireCrv, baseCrv = baseCrv, @@ -313,7 +313,7 @@ def connectToSource(srcNS,dstNS,wireCrv,baseCrv='',addArmIk=False,connectFingers connectRot=True, orientList=[], prefix='') - + # Arms (rt_elbow) glTools.utils.transformWire.create( wireCrv = wireCrv, baseCrv = baseCrv, diff --git a/tools/tube.py b/tools/tube.py index 598671b..5be90dd 100644 --- a/tools/tube.py +++ b/tools/tube.py @@ -33,17 +33,17 @@ def buildSubCurveDetach(crv): ''' # Get Prefix prefix = glTools.utils.stringUtils.stripSuffix(crv) - + # Prep Curve mc.rebuildCurve(crv,ch=False,rpo=True,rt=0,end=1,kr=0,kcp=1,kep=1,kt=0,s=0,d=3) mc.delete(crv,ch=True) - + # Detach Curve detach = mc.detachCurve(crv,p=(0.001,0.999),k=(0,1,0),rpo=False) detachCrv = detach[1] detachNode = detach[-1] mc.delete(detach[0],detach[2]) - + # Connect Detach Min/Max mc.addAttr(subCrv,ln='min',min=0,max=0.999,dv=0,k=True) mc.addAttr(subCrv,ln='max',min=0.001,max=1,dv=1,k=True) @@ -61,7 +61,7 @@ def buildSubCurveDetach(crv): mc.setAttr(minMaxClamp+'.max',0.9999,0,0) mc.connectAttr(minMaxClamp+'.outputR',detachNode+'.parameter[0]',f=True) mc.connectAttr(minMaxClamp+'.outputB',detachNode+'.parameter[1]',f=True) - + # Return Result return detachCrv @@ -70,10 +70,10 @@ def buildCurveRig(crv): ''' # Get Prefix prefix = glTools.utils.stringUtils.stripSuffix(crv) - + # Build Joints pts = glTools.utils.base.getPointArray(crv) - + jnts = [] mc.select(cl=True) for i in range(len(pts)): @@ -81,11 +81,11 @@ def buildCurveRig(crv): jnt = mc.joint(p=pts[i],n=prefix+'_fk'+ind+'_jnt') mc.joint() mc.select(jnt) - + # Orient Joints - + # Build FK - + # Build Offset def buildSubCurve(crv): @@ -96,28 +96,28 @@ def buildSubCurve(crv): subCrvShape = mc.createNode('nurbsCurve',n=prefix+'_subCrvShape') subCrv = mc.listRelatives(subCrvShape,p=True,pa=True)[0] subCrvNode = mc.createNode('subCurve',n=prefix+'_subCurve') - + # Connect Sub Curve mc.connectAttr(crv+'.worldSpace[0]',subCrvNode+'.inputCurve',f=True) mc.connectAttr(subCrvNode+'.outputCurve',subCrvShape+'.create',f=True) - + # Connect Sub Curve Min/Max mc.addAttr(subCrv,ln='min',min=0,max=0.999,dv=0,k=True) mc.addAttr(subCrv,ln='max',min=0.001,max=1,dv=1,k=True) mc.connectAttr(subCrv+'.min',subCrvNode+'.minValue',f=True) mc.connectAttr(subCrv+'.max',subCrvNode+'.maxValue',f=True) mc.setAttr(subCrvNode+'.relative',1) - + # Return Result return subCrv - + def resetCV(cvs): ''' ''' # Check CVs if not cvs: return None cvList = mc.filterExpand(cvs,ex=True,sm=28) - + # Reset CVs for cv in cvList: crv = mc.ls(cv,o=True)[0] @@ -132,22 +132,22 @@ def attachCurve(base,crv,cleanup=True): # Get Spans spans = mc.getAttr(crv+'.spans') mc.setAttr(base+'.spans',spans) - + # Match Shape shapeOrig = base+'ShapeOrig' mc.setAttr(shapeOrig+'.intermediateObject',0) mc.rebuildCurve(shapeOrig,ch=True,rpo=True,rt=0,end=1,kr=0,kcp=0,kep=1,kt=0,s=spans,d=3) bs = mc.blendShape(crv,shapeOrig)[0] mc.setAttr(bs+'.w[0]',1) - + # Delete Orig if cleanup: mc.delete(shapeOrig,ch=True) mc.delete(crv) - + # Restore Intermediate Shape mc.setAttr(shapeOrig+'.intermediateObject',1) - + # Return Result return @@ -175,7 +175,7 @@ def addDropoffControls(locs,prefix): mc.addAttr(ctrl,ln='bulge',min=-1,dv=0,k=True) mc.connectAttr(ctrl+'.param',locs[i]+'.param['+str(ind)+']',f=True) mc.connectAttr(ctrl+'.bulge',wire+'.wireLocatorEnvelope['+str(ind)+']',f=True) - + def buildTube( crv @@ -197,7 +197,7 @@ def buildTube( crv scale = 1, rsp = 1 ) - + # Polygon Tube mc.extrude( ch = True, diff --git a/tools/validateAttr.py b/tools/validateAttr.py index 29c364a..3968a0b 100644 --- a/tools/validateAttr.py +++ b/tools/validateAttr.py @@ -11,16 +11,16 @@ def validatePoints(obj): ''' # Initiate check check = 0 - + # Get points pArray = glTools.utils.base.getMPointArray(obj,worldSpace=False) - + # Check points for i in range(pArray.length()): - + # Check point values for val in [pArray[i].x,pArray[i].y,pArray[i].z,pArray[i].w]: - + # Check NaN if math.isnan(val): print('Found NaN : '+obj+'.p['+str(i)+']') @@ -29,7 +29,7 @@ def validatePoints(obj): if math.isinf(val): print('Found INF : '+obj+'.p['+str(i)+']') check += 1 - + # Return result return check @@ -38,16 +38,16 @@ def validateNormals(mesh): ''' # Initiate check check = 0 - + # Get points nArray = glTools.utils.mesh.getNormals(mesh,worldSpace=False) - + # Check points for i in range(nArray.length()): - + # Check point values for val in [nArray[i].x,nArray[i].y,nArray[i].z]: - + # Check NaN if math.isnan(val): print('Found NaN : '+mesh+'.n['+str(i)+']') @@ -56,7 +56,7 @@ def validateNormals(mesh): if math.isinf(val): print('Found INF : '+mesh+'.n['+str(i)+']') check += 1 - + # Return result return check @@ -65,28 +65,28 @@ def validateUVs(mesh): ''' # Initiate check check = 0 - + # Get meshFn meshFn = glTools.utils.mesh.getMeshFn(mesh) - + # Get UV Sets uvSetList = mc.polyUVSet(mesh,q=True,allUVSets=True) if not uvSetList: print('No UV Set : '+mesh) check += 1 - + for uvSet in uvSetList: - + # Get UV values uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() meshFn.getUVs(uArray,vArray,uvSet) - + # Check empty UV set if not uArray.length() and not vArray.length(): print('Empty UV Set : '+mesh+' - '+uvSet) check += 1 - + # Check U values for i in range(uArray.length()): if math.isnan(uArray[i]): @@ -95,7 +95,7 @@ def validateUVs(mesh): if math.isinf(uArray[i]): print('Found INF : '+mesh+'.uv['+str(i)+']') check += 1 - + # Check V values for i in range(vArray.length()): if math.isnan(vArray[i]): @@ -104,7 +104,7 @@ def validateUVs(mesh): if math.isinf(vArray[i]): print('Found INF : '+mesh+'.uv['+str(i)+']') check += 1 - + # Return result return check @@ -113,19 +113,19 @@ def validateAttr(attr): ''' # Initiate check check = 0 - + # Check Attr if not mc.objExists(attr): raise Exception('Attribute "'+attr+'" does not exist!') - + # Get Attribute type val = mc.getAttr(attr) - + # Check value if type(val) == list: - + for i in val: - + if type(i) == list or type(i) == tuple: for n in i: if math.isnan(n): diff --git a/tools/visibilitySwitch.py b/tools/visibilitySwitch.py index e96d393..0fa8ad2 100644 --- a/tools/visibilitySwitch.py +++ b/tools/visibilitySwitch.py @@ -9,7 +9,7 @@ def create( switchObject, prefix = '' ): ''' Create a enumerated visibility switch based on the input arguments - @param switchObject: Object to add switch attribute to + @param switchObject: Object to add switch attribute to @type switchObject: str @param switchAttr: Switch attribute name @type switchAttr: str @@ -28,11 +28,11 @@ def create( switchObject, # ========== # - Checks - # ========== - + # Check switchObject if not mc.objExists(switchObject): raise Exception('Switch object "'+switchObject+'" does not exist!') - + # Compare target and enum list if not visTargetList or not visEnumList: raise Exception('Visibility target or enum list has zero elements!') @@ -42,21 +42,21 @@ def create( switchObject, if visIndexList: if len(visTargetList) != len(visIndexList): raise Exception('Visibility target and index list length mis-match!') - + # ================================= # - Create Visibility Switch Attr - # ================================= - + # Check Visibility Switch Attr if not mc.objExists(switchObject+'.'+switchAttr): - + # Build Enum Value visEnum = '' for i in visEnumList: visEnum += i+':' # Add switch attr mc.addAttr(switchObject,ln=switchAttr,nn=switchName,at='enum',en=visEnum) mc.setAttr(switchObject+'.'+switchAttr,e=True,cb=True) - + # Create Custom Visibility Index (choice) vis_choice = '' if visIndexList: @@ -66,43 +66,43 @@ def create( switchObject, for i in range(len(visIndexList)): mc.setAttr(vis_choice+'.visIndex['+str(i)+']',visIndexList[i]) mc.connectAttr(vis_choice+'.visIndex['+str(i)+']',vis_choice+'.input['+str(i)+']',f=True) - + # ====================== # - Connect Visibility - # ====================== - + for i in range(len(visEnumList)): - + # Check visTargetList if not visTargetList[i]: continue - + # Create Condition Node conditionNode = mc.createNode('condition',n=prefix+'_'+visEnumList[i]+'Vis_condition') mc.setAttr(conditionNode+'.firstTerm',i) mc.setAttr(conditionNode+'.colorIfTrue',1,0,1) mc.setAttr(conditionNode+'.colorIfFalse',0,1,0) - + # Connect Condition Node conditionInput = switchObject+'.'+switchAttr if visIndexList: conditionInput = vis_choice+'.output' mc.connectAttr(conditionInput,conditionNode+'.secondTerm',f=True) - + # Connect Each Item in List - Vis ON for obj in visTargetList[i]: - + # Check visibility attr if not mc.objExists(obj+'.v'): raise Exception('Object "'+obj+'" has no visibility attribute!') if not mc.getAttr(obj+'.v',se=True): raise Exception('Attribute "'+obj+'.v" is locked or has incoming connections!') - + # Connect attribute mc.connectAttr(conditionNode+'.outColorR',obj+'.v',f=True) - + # ================= # - Return Result - # ================= - + return (switchObject+'.'+switchAttr) def createEmpty( switchObject, @@ -112,7 +112,7 @@ def createEmpty( switchObject, prefix = '' ): ''' Create a enumerated visibility switch based on the input arguments - @param switchObject: Object to add switch attribute to + @param switchObject: Object to add switch attribute to @type switchObject: str @param switchAttr: Switch attribute name @type switchAttr: str @@ -126,27 +126,27 @@ def createEmpty( switchObject, # ========== # - Checks - # ========== - + # Check switchObject if not mc.objExists(switchObject): raise Exception('Switch object "'+switchObject+'" does not exist!') - + # ================================= # - Create Visibility Switch Attr - # ================================= - + # Check Visibility Switch Attr if not mc.objExists(switchObject+'.'+switchAttr): - + # Build Enum Value visEnum = '' for i in visEnumList: visEnum += i+':' # Add switch attr mc.addAttr(switchObject,ln=switchAttr,nn=switchName,at='enum',en=visEnum) mc.setAttr(switchObject+'.'+switchAttr,e=True,cb=True) - + # ================= # - Return Result - # ================= - + return (switchObject+'.'+switchAttr) diff --git a/tools/volumeSelection.py b/tools/volumeSelection.py index 49c265d..2eda96e 100644 --- a/tools/volumeSelection.py +++ b/tools/volumeSelection.py @@ -19,31 +19,31 @@ def radialComponentSelection(mesh,center,radius=1.0): # ========== # - Checks - # ========== - + # Check Mesh if not mc.objExists(mesh): raise Exception('Mesh object "'+mesh+'" does not exist!!') - + # Get Point pt = glTools.utils.base.getMPoint(center) - + # ========================== # - Build Radial Selection - # ========================== - + # Get Component List ptList = glTools.utils.base.getMPointArray(mesh) - + # Build Selection sel = [] for i in range(ptList.length()): dist = (pt - ptList[i]).length() if dist <= radius: sel.append(mesh+'.vtx['+str(i)+']') - + # ================= # - Return Result - # ================= - + return sel def volumeComponentSelection(mesh,volume): @@ -57,15 +57,15 @@ def volumeComponentSelection(mesh,volume): # ========== # - Checks - # ========== - + # Check Mesh if not mc.objExists(mesh): raise Exception('Mesh object "'+mesh+'" does not exist!!') - + # Check Volume if not mc.objExists(volume): raise Exception('Volume object "'+volume+'" does not exist!!') - + # Get Volume Type volumeShape = volume if mc.objectType(volumeShape) == 'transform': @@ -73,27 +73,27 @@ def volumeComponentSelection(mesh,volume): if not volumeShape: raise Exception('Volume object "'+mesh+'" does not exist!!') else: volumeShape = volumeShape[0] volumeType = mc.objectType(volumeShape) - + # Convert to Polygon Volume (if necessary) nurbsToPolyConvert = None if volumeType == 'nurbsSurface': nurbsToPolyConvert = mc.nurbsToPoly(volumeShape,ch=0,f=1,pt=1,ft=0.01,mel=0.001,d=0.1) nurbsToPolyShape = mc.listRelatives(nurbsToPolyConvert,s=True,ni=True) volumeShape = nurbsToPolyShape[0] - + # ========================== # - Build Volume Selection - # ========================== - + # Create Funtion Set for Volume Mesh volumeFn = glTools.utils.mesh.getMeshFn(volume) - + # Get Bounding Box volumeBBox = glTools.utils.base.getMBoundingBox(volume) - + # Get Vertices pntList = glTools.utils.base.getMPointArray(mesh) - + # Build Selection List sel = [] point = OpenMaya.MPoint() @@ -103,15 +103,15 @@ def volumeComponentSelection(mesh,volume): volumeFn.getClosestPointAndNormal(pntList[i],point,normal) dotVal = normal * (point-pntList[i]).normal() if dotVal > 0.0: sel.append(mesh+'.vtx['+str(i)+']') - + # =========== # - Cleanup - # =========== - + if nurbsToPolyConvert: mc.delete(nurbsToPolyConvert) - + # ================= # - Return Result - # ================= - + return sel diff --git a/tools/volumeWeights.py b/tools/volumeWeights.py index d1234b6..ad48a7f 100644 --- a/tools/volumeWeights.py +++ b/tools/volumeWeights.py @@ -8,9 +8,9 @@ class VolumeWeights(object): - + def __init__(self): - + self._operationAttrName = 'weightOperation' self._operationAttrModes = 'add:subtract:multiply' self.radiusAttrName = 'influenceRadius' @@ -20,119 +20,119 @@ def __init__(self): self.smooth = True self.weights = {} self.results = {} - - + + #============================= # Create Input Transforms #============================= def createRadiusLocator(self, prefix='', operationMode=0): - + falloffLoc = mc.spaceLocator(n='%s_falloffLoc' % prefix)[0] influenceVolume = mc.createNode('renderSphere',n='%s_templateFalloffShape' % prefix, p=falloffLoc) - + # add attr self.addOperationAttr(transform=falloffLoc, operationMode=operationMode) - + # Add Radius Control locAttrName = '%s.%s' % (falloffLoc, self.radiusAttrName) mc.connectAttr(locAttrName, influenceVolume+'.radius',f=True) mc.connectAttr(locAttrName, falloffLoc+'.localScaleX',f=True) mc.connectAttr(locAttrName, falloffLoc+'.localScaleY',f=True) mc.connectAttr(locAttrName, falloffLoc+'.localScaleZ',f=True) - + self.weightTransforms.append(falloffLoc) - - - - + + + + #============================= # Utilities #============================= def addOperationAttr(self, transform, operationMode=0): - + # radius attr if not mc.objExists('%s.%s' % (transform,self.radiusAttrName)): mc.addAttr(transform,ln=self.radiusAttrName,min=0.0001,dv=0.5,k=True) - + # operation attr if not mc.objExists('%s.%s' % (transform,self._operationAttrName)): mc.addAttr(transform,ln=self._operationAttrName, attributeType='enum', enumName=self._operationAttrModes,dv=operationMode, keyable=True) - + # affect attr if not mc.objExists('%s.%s' % (transform,self.affectAttrName)): mc.addAttr(transform,ln=self.affectAttrName, attributeType='float', dv=1, keyable=True) - + def addGeometry(self, geometry): # geometry checks self.geometry.append(geometry) - + def addTransform(self, transform): # transform checks self.weightTransforms.append(transform) - + def getOperation(self, transform ): # attr check return mc.getAttr('%s.%s' % (transform, self._operationAttrName)) - + def getKeyNames(self, geometry): return self.weights[geometry].keys() - + def normalize(self, geometry, normalizeMin=0, normalizeMax=1): if geometry: self.weights[geometry].normalize() else: for geometry in self.geometry: self.weights[geometry].normalize() - - - - - + + + + + #============================= # Weights #============================= def getWeights(self): - + for geometry in self.geometry: - + self.weights[geometry] = {} - + for transform in self.weightTransforms: - + self.weights[geometry][transform] = WeightList(glTools.tools.generateWeights.radialWeights( geometry = geometry, center = transform, radius = mc.getAttr('%s.%s' % (transform, self.radiusAttrName)), smooth = self.smooth )) - + affect = mc.getAttr('%s.%s' % (transform, self.affectAttrName)) self.weights[geometry][transform] *= affect - + def calculateWeights(self, normalize=False, clamp=True): - + addWeights = WeightList([]) subWeights = WeightList([]) mulWeights = WeightList([]) for geometry in self.weights.keys(): - + for transform in self.weights[geometry].keys(): opNum = self.getOperation(transform) if opNum == 0: addWeights += self.weights[geometry][transform] - elif opNum == 1: subWeights += self.weights[geometry][transform] - elif opNum == 2: mulWeights += self.weights[geometry][transform] - + elif opNum == 1: subWeights += self.weights[geometry][transform] + elif opNum == 2: mulWeights += self.weights[geometry][transform] + self.results[geometry] = ( addWeights - subWeights ) * mulWeights - + if normalize: self.results[geometry] = self.results[geometry].normalize() if clamp: self.results[geometry] = self.results[geometry].clamp() - - + + def apply(self, deformer, influence): - + deformType='deformer' if mc.nodeType(deformer) == 'skinCluster': deformType='skinCluster' - + for geometry in self.geometry: - + if deformType == 'skinCluster': glTools.utils.skinCluster.setInfluenceWeights(skinCluster=deformer, influence =influence, @@ -143,18 +143,18 @@ def apply(self, deformer, influence): glTools.utils.deformer.setWeights( deformer = deformer, weights = self.results[geometry], geometry = geometry) - - - + + + #============================= # High Level Methods #============================= - + def getCalculateAndApply(self, deformer, influence=None, normalize=False, clamp=True): - + self.getWeights() self.calculateWeights(normalize=normalize, clamp=clamp) self.apply(deformer=deformer, influence=influence) - - - + + + diff --git a/tools/workfileBatch.py b/tools/workfileBatch.py index 079a5fa..f93d218 100644 --- a/tools/workfileBatch.py +++ b/tools/workfileBatch.py @@ -13,49 +13,49 @@ def workfileBatchUI(): window = 'workfileBatchUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Workfile Batch Manager') - + # Layout FL = mc.formLayout() - + # =============== # - UI Elements - # =============== - + cw = 100 - + # WorkFile List workfileTXT = mc.text(label='Workfile List') workfileTSL = mc.textScrollList('workfileBatchTSL',allowMultiSelection=True) workfileAddB = mc.button(label='Add',c='glTools.tools.workfileBatch.workfileBatchUI_addFiles("'+workfileTSL+'")') workfileDelB = mc.button(label='Remove',c='glTools.ui.utils.removeFromTSL("'+workfileTSL+'")') - + workfileListSep = mc.separator(style='single') - + pyCmdFileTFB = mc.textFieldButtonGrp('wfBatch_pyCmdFileTFB',label='PyCmdFile',text='',buttonLabel='...',cw=(1,cw)) mc.textFieldButtonGrp(pyCmdFileTFB,e=True,bc='glTools.tools.workfileBatch.workfileBatchUI_addPyCmd("'+pyCmdFileTFB+'")') - + pyCmdFileSep = mc.separator(style='single') - + versionUpCBG = mc.checkBoxGrp('wfBatch_versionUpCBG',numberOfCheckBoxes=1,label='Version Up',v1=False,cw=(1,cw)) snapshotCBG = mc.checkBoxGrp('wfBatch_snapshotCBG',numberOfCheckBoxes=1,label='Snapshot',v1=False,cw=(1,cw)) publishCBG = mc.checkBoxGrp('wfBatch_publishCBG',numberOfCheckBoxes=1,label='Publish',v1=False,cw=(1,cw),en=False) - + publishNotesTXT = mc.text(label='Snapshot/Publish Notes') publishNotesSF = mc.scrollField('wfBatch_publishNoteSF',editable=True,wordWrap=True,text='Snapshot generated from workfile batch process.',en=False) - + workfileBatchB = mc.button(label='Batch',c='glTools.tools.workfileBatch.workfileBatchFromUI()') workfileCloseB = mc.button(label='Close',c='mc.deleteUI("'+window+'")') - + # ======================== # - UI Callback Commands - # ======================== - + mc.checkBoxGrp(snapshotCBG,e=True,cc='glTools.tools.workfileBatch.workfileBatchUI_toggleSnapshot()') - + # ================ # - Form Layouts - # ================ - + mc.formLayout(FL,e=True,af=[(workfileTXT,'top',5),(workfileTXT,'left',5),(workfileTXT,'right',5)]) mc.formLayout(FL,e=True,af=[(workfileTSL,'left',5),(workfileTSL,'right',5)],ac=[(workfileTSL,'top',5,workfileTXT),(workfileTSL,'bottom',5,workfileAddB)]) mc.formLayout(FL,e=True,af=[(workfileAddB,'left',5)],ac=[(workfileAddB,'bottom',5,workfileListSep)],ap=[(workfileAddB,'right',5,50)]) @@ -70,11 +70,11 @@ def workfileBatchUI(): mc.formLayout(FL,e=True,af=[(publishNotesSF,'left',5),(publishNotesSF,'right',5)],ac=[(publishNotesSF,'bottom',5,workfileBatchB)]) mc.formLayout(FL,e=True,af=[(workfileBatchB,'left',5),(workfileBatchB,'bottom',5)],ap=[(workfileBatchB,'right',5,50)]) mc.formLayout(FL,e=True,af=[(workfileCloseB,'right',5),(workfileCloseB,'bottom',5)],ap=[(workfileCloseB,'left',5,50)]) - + # =============== # - Show Window - # =============== - + mc.showWindow(window) def workfileBatchUI_addFiles(TSL): @@ -85,11 +85,11 @@ def workfileBatchUI_addFiles(TSL): ''' # Get Existing Workfile List workfileList = mc.textScrollList(TSL,q=True,ai=True) or [] - + # Get Workfile List fileFilter = 'Maya Files (*.ma *.mb);;Maya ASCII (*.ma);;Maya Binary (*.mb)' workfileSel = mc.fileDialog2(fileFilter=fileFilter,dialogStyle=2,fileMode=4,cap='Workfile Batch - Add Files') - + # Add Files to List for workfile in workfileSel: if not workfile in workfileList: @@ -103,7 +103,7 @@ def workfileBatchUI_addPyCmd(TFB): ''' # Get Python Command File pyCmdFile = mc.fileDialog2(fileFilter='*.py',dialogStyle=2,fileMode=1,cap='Workfile Batch - Select Command File') - + # Update textFieldButtonGrp if pyCmdFile: mc.textFieldButtonGrp(TFB,e=True,text=pyCmdFile[0]) @@ -120,24 +120,24 @@ def workfileBatchFromUI(): ''' # Get Workfile List workfileList = mc.textScrollList('workfileBatchTSL',q=True,ai=True) - + # Get Workfile Batch Data cmdsFile = mc.textFieldButtonGrp('wfBatch_pyCmdFileTFB',q=True,text=True) versionUp = mc.checkBoxGrp('wfBatch_versionUpCBG',q=True,v1=True) snapshot = mc.checkBoxGrp('wfBatch_snapshotCBG',q=True,v1=True) publish = mc.checkBoxGrp('wfBatch_publishCBG',q=True,v1=True) publishNote = mc.scrollField('wfBatch_publishNoteSF',q=True,text=True) - + # For Each Workfile for workfile in workfileList: - + workfileBatch( workfile=workfile, cmdsFile=cmdsFile, versionUp=versionUp, snapshot=snapshot, publish=publish, publishNote=publishNote ) - + def workfileBatch(workfile,cmdsFile='',versionUp=False,snapshot=False,publish=False,publishNote=''): ''' @@ -163,10 +163,10 @@ def workfileBatch(workfile,cmdsFile='',versionUp=False,snapshot=False,publish=Fa workfileBatchCmd += " "+str(int(snapshot)) workfileBatchCmd += " "+str(int(publish)) workfileBatchCmd += " '"+publishNote+"'" - + # Get Workfile Basename fileName = os.path.basename(workfile) - + # Execute Workfile Batch Command os.system('xterm -hold -T "'+fileName+'" -e "'+workfileBatchCmd+'" &') @@ -194,6 +194,6 @@ def workfileBatchSubmit(workfile,cmdsFile='',versionUp=False,snapshot=False,publ workfileBatchCmd += " "+str(int(snapshot)) workfileBatchCmd += " "+str(int(publish)) workfileBatchCmd += " '"+publishNote+"'" - + # Submit Workfile Batch Command to Qube os.system('qbsub --name maya_workfile_batch --shell /bin/tcsh --cluster /ent/hbm/vfx -e "'+workfileBatchCmd) diff --git a/tools/writeBurlyWeights.py b/tools/writeBurlyWeights.py index ff4b694..956bdd0 100644 --- a/tools/writeBurlyWeights.py +++ b/tools/writeBurlyWeights.py @@ -15,7 +15,7 @@ def writeBurlyWeights(mesh,skinCluster,influence,filePath): burly = 'dnBurlyDeformer1' vtxCount = mc.polyEvaluate(mesh,v=True) inf = mc.ls(influence,l=True) - + # Check skinCluster if not glTools.utils.skinCluster.isSkinCluster(skinCluster): raise Exception('Object "'+skinCluster+'" is not a valid skinCluster!') @@ -23,7 +23,7 @@ def writeBurlyWeights(mesh,skinCluster,influence,filePath): skinFn = glTools.utils.skinCluster.getSkinClusterFn(skinCluster) # Get influence dag path influencePath = glTools.utils.base.getMDagPath(influence) - + # Get points affected by influence infSelectionList = OpenMaya.MSelectionList() infWeightList = OpenMaya.MFloatArray() @@ -31,13 +31,13 @@ def writeBurlyWeights(mesh,skinCluster,influence,filePath): infObjectPath = OpenMaya.MDagPath() infComponentList = OpenMaya.MObject() infSelectionList.getDagPath(0,infObjectPath,infComponentList) - + # Get affect point indices infComponentIndex = OpenMaya.MIntArray() infComponentIndexFn = OpenMaya.MFnSingleIndexedComponent(infComponentList) infComponentIndexFn.getElements(infComponentIndex) infComponentIndex = list(infComponentIndex) - + # Get affect point position and normal arrays infComponentPosArray = OpenMaya.MPointArray() infComponentNormArray = OpenMaya.MVectorArray() @@ -48,17 +48,17 @@ def writeBurlyWeights(mesh,skinCluster,influence,filePath): infComponentVtxIt.getNormal(normal) infComponentNormArray.append(normal) infComponentVtxIt.next() - + # Open file fileId = open(filePath, "w") - + # Header header = [ '\n', '\n', '\t\n', '\t\t\n' ] fileId.writelines(header) - + # Weights weights = ['\t\t\n'] for i in range(len(infComponentIndex)): @@ -67,7 +67,7 @@ def writeBurlyWeights(mesh,skinCluster,influence,filePath): if i%5 == 4: weights.append('\n') weights.append('\n\t\t\n') fileId.writelines(weights) - + # Indices indices = ['\t\t\n'] for i in range(len(infComponentIndex)): @@ -76,7 +76,7 @@ def writeBurlyWeights(mesh,skinCluster,influence,filePath): if i%10 == 9: indices.append('\n') indices.append('\n\t\t\n') fileId.writelines(indices) - + # Position pos = ['\t\t\n'] for i in range(len(infComponentIndex)): @@ -85,7 +85,7 @@ def writeBurlyWeights(mesh,skinCluster,influence,filePath): if i%2: pos.append('\n') pos.append('\n\t\t\n') fileId.writelines(pos) - + # Normals norm = ['\t\t\n'] for i in range(len(infComponentIndex)): @@ -94,7 +94,7 @@ def writeBurlyWeights(mesh,skinCluster,influence,filePath): if i%2: norm.append('\n') norm.append('\n\t\t\n') fileId.writelines(norm) - + # Radii radii = ['\t\t\n'] for i in range(len(infComponentIndex)): @@ -103,51 +103,51 @@ def writeBurlyWeights(mesh,skinCluster,influence,filePath): if i%6 == 5: radii.append('\n') radii.append('\n\t\t\n') fileId.writelines(radii) - + # Footer footer = ['\t','\n'] fileId.writelines(footer) - + # Close file fileId.close() - + def writeBurlyWeights_allInfluences(mesh,skinCluster,directoryPath): ''' ''' # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" contains no valid polygon mesh!') - + # Check skinCluster if not glTools.utils.skinCluster.isSkinCluster(skinCluster): raise Exception('Object "'+skinCluster+'" is not a valid skinCluster!') - + # Check directory if not os.path.isdir(directoryPath): raise Exception('Directory path "'+directoryPath+'" does not exist!') - + # Get skinCluster influences influenceList = mc.skinCluster(skinCluster,q=True,inf=True) - + # Write weights for influence in influenceList: writeBurlyWeights(mesh,skinCluster,influence,directoryPath+influence+'.xml') - + def loadBurlyWeights(burlyDeformer,directoryPath): ''' ''' # Check burly deformer if not mc.objExists(burlyDeformer): raise Exception('Burly deformer "'+burlyDeformer+'" does not exist!') - + # Check directory path if not directoryPath.endswith('/'): directoryPath+='/' if not os.path.isdir(directoryPath): raise Exception('Directory path "'+directoryPath+'" does not exist!') - + # Get directory listing fileList = [i for i in os.listdir(directoryPath) if i.endswith('.xml')] - + # Load weights for filePath in fileList: fileId = directoryPath+filePath @@ -162,18 +162,18 @@ def convertToBurly(skinCluster,burlyDeformerName=''): raise Exception('SkinCluster "'+skinCluster+'" does not exist!') if not glTools.utils.skinCluster.isSkinCluster(skinCluster): raise Exception('Object "'+skinCluster+'" is not a valid skinCluster deformer!') - + # Get affected mesh - #mesh = - + #mesh = + # Designate temporary path for exported weight files dirPath = '/usr/tmp/' - + # Export skinCluster weight files influenceList = mc.skinCluster(skinCluster,q=True,inf=True) writeBurlyWeights_allInfluences(mesh,skinCluster,dirPath) - - + + # Create burly deformer mm.eval('dnBurlyDeformer_createNamed("'+geo+'","'+burlyDeformerName+'")') diff --git a/tools/xformToParticles.py b/tools/xformToParticles.py index fee39bf..123edd0 100644 --- a/tools/xformToParticles.py +++ b/tools/xformToParticles.py @@ -21,7 +21,7 @@ def xformToNParticles(xformList=[]): ptList = [mc.xform(i,q=True,ws=True,rp=True) for i in xformList] particle = mc.nParticle(p=ptList) return particle - + def xformToPoly(xformList=[],scale=0.1): ''' Create poly planes from the specified list of transforms diff --git a/ui/attrPreset.py b/ui/attrPreset.py index 71c6853..b9fed00 100644 --- a/ui/attrPreset.py +++ b/ui/attrPreset.py @@ -9,69 +9,69 @@ def ui(): win = 'attrPresetUI' if mc.window(win,ex=True): mc.deleteUI(win) win = mc.window(win,t='Attribute Presets',s=True,mb=False,wh=[570,330]) - + # --------------- # - Main Window - # --------------- - + # FormLayout fl = mc.formLayout(numberOfDivisions=100) - - # UI Elements + + # UI Elements nodeListTXT = mc.text(l='Node List:',al='left') nodeListTSL = mc.textScrollList('attrPreset_nodeListTSL', allowMultiSelection=True ) - + nodeList_addB = mc.button(label='Add', c='glTools.ui.attrPreset.nodeListAddFromUI()' ) nodeList_delB = mc.button(label='Remove', c='glTools.ui.attrPreset.nodeListDelFromUI()' ) - + presetListTXT = mc.text(l='Preset List:',al='left') presetListTSL = mc.textScrollList('attrPreset_presetListTSL', allowMultiSelection=False ) - + presetAmountFSG = mc.floatSliderGrp('attrPreset_amountFSG',label='Amount',field=True,minValue=0.0,maxValue=1.0,fieldMinValue=0.0,fieldMaxValue=1.0,value=1.0,cw=[1,60]) - + presetApplySelB = mc.button(label='Apply to Selected', c='glTools.ui.attrPreset.presetApplyFromUI(1)' ) presetApplyAllB = mc.button(label='Apply to All', c='glTools.ui.attrPreset.presetApplyFromUI(0)' ) - + sep = mc.separator(style='in',hr=False) - + # --------------- # - Form Layout - # --------------- - + mc.formLayout(fl,e=True,af=[(nodeListTXT,'left',5),(nodeListTXT,'top',5)],ap=[(nodeListTXT,'right',5,40)]) mc.formLayout(fl,e=True,af=[(nodeListTSL,'left',5)],ap=[(nodeListTSL,'right',5,40)],ac=[(nodeListTSL,'top',5,nodeListTXT),(nodeListTSL,'bottom',5,nodeList_addB)]) mc.formLayout(fl,e=True,af=[(nodeList_addB,'left',5),(nodeList_addB,'bottom',5)],ap=[(nodeList_addB,'right',5,20)]) mc.formLayout(fl,e=True,af=[(nodeList_delB,'bottom',5)],ap=[(nodeList_delB,'right',5,40)],ac=[(nodeList_delB,'left',5,nodeList_addB)]) - + mc.formLayout(fl,e=True,af=[(presetListTXT,'right',5),(presetListTXT,'top',5)],ap=[(presetListTXT,'left',5,45)]) mc.formLayout(fl,e=True,af=[(presetListTSL,'right',5)],ap=[(presetListTSL,'left',5,45)],ac=[(presetListTSL,'top',5,presetListTXT),(presetListTSL,'bottom',5,presetAmountFSG)]) mc.formLayout(fl,e=True,af=[(presetAmountFSG,'right',5)],ap=[(presetAmountFSG,'left',5,45)],ac=[(presetAmountFSG,'bottom',5,presetApplySelB)]) mc.formLayout(fl,e=True,af=[(presetApplySelB,'bottom',5)],ap=[(presetApplySelB,'left',5,45),(presetApplySelB,'right',5,74)]) mc.formLayout(fl,e=True,af=[(presetApplyAllB,'right',5),(presetApplyAllB,'bottom',5)],ac=[(presetApplyAllB,'left',5,presetApplySelB)]) - + mc.formLayout(fl,e=True,af=[(sep,'top',5),(sep,'bottom',5)],ac=[(sep,'left',5,nodeListTSL),(sep,'right',5,presetListTSL)]) - + # ---------------- # - UI Callbacks - # ---------------- - + mc.textScrollList(nodeListTSL,e=True,dcc='glTools.ui.utils.selectFromTSL("'+nodeListTSL+'")') mc.textScrollList(nodeListTSL,e=True,dkc='glTools.ui.utils.removeFromTSL("'+nodeListTSL+'")') - + # -------------- # - Popup Menu - # -------------- - + nodeListPUM = mc.popupMenu(parent=nodeListTSL) mc.menuItem(l='Add Selected',c='glTools.ui.attrPreset.nodeListAddFromUI()') mc.menuItem(l='Remove Hilited',c='glTools.ui.attrPreset.nodeListDelFromUI()') mc.menuItem(l='Clear List',c='glTools.ui.attrPreset.nodeListClearFromUI()') mc.menuItem(l='Select Hilited',c='glTools.ui.utils.selectFromTSL("'+nodeListTSL+'")') - + # -------------- # - Display UI - # -------------- - + mc.showWindow(win) def updatePresetList(): @@ -79,25 +79,25 @@ def updatePresetList(): ''' # Clear preset list mc.textScrollList('attrPreset_presetListTSL',e=True,ra=True) - + # Get list of nodes nodes = mc.textScrollList('attrPreset_nodeListTSL',q=True,ai=True) if not nodes: return - + # Get node types nodeTypes = [mc.objectType(node) for node in nodes] nodeTypes = list(set(nodeTypes)) - + # Get list of available presets presets = [] for nodeType in nodeTypes: presets.extend(glTools.utils.attrPreset.listNodePreset(nodeType)) presets = list(set(presets)) - + # Update preset list for preset in presets: mc.textScrollList('attrPreset_presetListTSL',e=True,a=preset) - + # Select first item in list if presets: mc.textScrollList('attrPreset_presetListTSL',e=True,sii=1) @@ -107,11 +107,11 @@ def nodeListAddFromUI(): ''' # Add selected items to TSL glTools.ui.utils.addToTSL('attrPreset_nodeListTSL') - + # Select first item in list if mc.textScrollList('attrPreset_presetListTSL',q=True,ni=1): mc.textScrollList('attrPreset_presetListTSL',e=True,sii=1) - + # Update preset list updatePresetList() @@ -120,20 +120,20 @@ def nodeListDelFromUI(): ''' # Removed selected items from TSL glTools.ui.utils.removeFromTSL('attrPreset_nodeListTSL') - + # Select first item in list if mc.textScrollList('attrPreset_presetListTSL',q=True,ni=1): mc.textScrollList('attrPreset_presetListTSL',e=True,sii=1) - + # Update preset list updatePresetList() - + def nodeListClearFromUI(): ''' ''' # Clear node list mc.textScrollList('attrPreset_nodeListTSL',e=True,ra=True) - + # Update preset list updatePresetList() @@ -145,10 +145,10 @@ def presetApplyFromUI(selectedOnly): nodes = mc.textScrollList('attrPreset_nodeListTSL',q=True,si=True) else: nodes = mc.textScrollList('attrPreset_nodeListTSL',q=True,ai=True) - + # Get selected preset preset = mc.textScrollList('attrPreset_presetListTSL',q=True,si=True) if not preset: raise Exception('No preset specified!') - + # Apply preset glTools.utils.attrPreset.apply(nodes,preset[0],1.0) diff --git a/ui/base.py b/ui/base.py index 75e9cec..9a1f023 100644 --- a/ui/base.py +++ b/ui/base.py @@ -10,53 +10,53 @@ def parentListUI(): window = 'parentListUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Parent List') - + # Layout fl = mc.formLayout(numberOfDivisions=100) - + # UI Elements childTXT = mc.text(l='Child List:',al='left') childTSL = mc.textScrollList('parentList_childListTSL', allowMultiSelection=True ) - + parentTXT = mc.text(l='Parent List:',al='left') parentTSL = mc.textScrollList('parentList_parentListTSL', allowMultiSelection=True ) - + parentB = mc.button(label='Parent', c='glTools.ui.base.parentListFromUI()' ) cancelB = mc.button(label='Cancel', c='mc.deleteUI("'+window+'")' ) - + # Layout mc.formLayout(fl,e=True,af=[(childTXT,'left',5),(childTXT,'top',5)],ap=[(childTXT,'right',5,50)]) mc.formLayout(fl,e=True,af=[(childTSL,'left',5)],ap=[(childTSL,'right',5,50)],ac=[(childTSL,'top',5,childTXT),(childTSL,'bottom',5,parentB)]) - + mc.formLayout(fl,e=True,af=[(parentTXT,'right',5),(parentTXT,'top',5)],ap=[(parentTXT,'left',5,50)]) mc.formLayout(fl,e=True,af=[(parentTSL,'right',5)],ap=[(parentTSL,'left',5,50)],ac=[(parentTSL,'top',5,parentTXT),(parentTSL,'bottom',5,cancelB)]) - + mc.formLayout(fl,e=True,af=[(parentB,'left',5),(parentB,'bottom',5)],ap=[(parentB,'right',5,50)]) mc.formLayout(fl,e=True,af=[(cancelB,'right',5),(cancelB,'bottom',5)],ap=[(cancelB,'left',5,50)]) - + # UI Callbacks - + mc.textScrollList(childTSL,e=True,dcc='glTools.ui.utils.selectFromTSL("'+childTSL+'")') mc.textScrollList(childTSL,e=True,dkc='glTools.ui.utils.removeFromTSL("'+childTSL+'")') - + mc.textScrollList(parentTSL,e=True,dcc='glTools.ui.utils.selectFromTSL("'+parentTSL+'")') mc.textScrollList(parentTSL,e=True,dkc='glTools.ui.utils.removeFromTSL("'+parentTSL+'")') - + # Popup menu - + childPUM = mc.popupMenu(parent=childTSL) mc.menuItem(l='Add Selected',c='glTools.ui.utils.addToTSL("'+childTSL+'")') mc.menuItem(l='Remove Selected',c='glTools.ui.utils.removeFromTSL("'+childTSL+'")') mc.menuItem(l='Clear List',c='mc.textScrollList("'+childTSL+'",e=True,ra=True)') mc.menuItem(l='Select Hilited',c='glTools.ui.utils.selectFromTSL("'+childTSL+'")') - + parentPUM = mc.popupMenu(parent=parentTSL) mc.menuItem(l='Add Selected',c='glTools.ui.utils.addToTSL("'+parentTSL+'")') mc.menuItem(l='Remove Selected',c='glTools.ui.utils.removeFromTSL("'+parentTSL+'")') mc.menuItem(l='Clear List',c='mc.textScrollList("'+parentTSL+'",e=True,ra=True)') mc.menuItem(l='Select Hilited',c='glTools.ui.utils.selectFromTSL("'+parentTSL+'")') - - # Display UI + + # Display UI mc.showWindow(window) def parentListFromUI(): @@ -68,7 +68,7 @@ def parentListFromUI(): parentList = mc.textScrollList('parentList_parentListTSL',q=True,ai=True) # Parent child list to parent list glTools.utils.base.parentList(childList,parentList) - + def renameHistoryNodesUI(): ''' UI for parentList() @@ -77,49 +77,49 @@ def renameHistoryNodesUI(): window = 'renameHistoryNodesUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Rename History Nodes') - + # Layout cl = mc.columnLayout() - + # UI Elements nodeTypeTFG = mc.textFieldGrp('renameHist_nodeTypeTFG',label='Node Type') nodeSuffixTFG = mc.textFieldGrp('renameHist_nodeSuffixTFG',label='Node Suffix') stripSuffixCBG = mc.checkBoxGrp('renameHist_stripSuffixCBG',l='Strip Old Suffix',ncb=1,v1=True) - + renameB = mc.button(label='Rename', c='glTools.ui.base.renameHistoryNodesFromUI()' ) cancelB = mc.button(label='Cancel', c='mc.deleteUI("'+window+'")' ) - - # Display UI + + # Display UI mc.showWindow(window) def renameHistoryNodesFromUI(): ''' ''' - # Get node type and suffix lists + # Get node type and suffix lists nodeType = mc.textFieldGrp('renameHist_nodeTypeTFG',q=True,text=True) nodeSuffix = mc.textFieldGrp('renameHist_nodeSuffixTFG',q=True,text=True) stripSuffix = mc.checkBoxGrp('renameHist_stripSuffixCBG',q=True,v1=True) - + nodeTypeList = nodeType.split(' ') nodeSuffixList = nodeSuffix.split(' ') - + if len(nodeTypeList) != len(nodeSuffixList): if nodeSuffixList: raise Exception('Node type and suffix list length mis-match!') - + # Get scene selection sel = mc.ls(sl=1) - + # For each object in selection for obj in sel: - + # For each node type for i in range(len(nodeTypeList)): - + # Determine suffix nodeSuffix = '' if nodeSuffixList: nodeSuffix = nodeSuffixList[i] - + # Rename nodes glTools.utils.base.renameHistoryNodes(obj,nodeTypeList[i],suffix=nodeSuffix,stripOldSuffix=stripSuffix) - + diff --git a/ui/blendShape.py b/ui/blendShape.py index 349ed89..ea6f939 100644 --- a/ui/blendShape.py +++ b/ui/blendShape.py @@ -12,16 +12,16 @@ def blendShapeManagerUI(): window = 'blendShapeManagerUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='BlendShape Manager') - + # Layout FL = mc.formLayout() - + # =============== # - UI Elements - # =============== - + cw = 100 - + # TextScrollList blendShapeTXT = mc.text(label='BlendShape') blendShapeTSL = mc.textScrollList('bsMan_blendShapeTSL',allowMultiSelection=False) @@ -30,84 +30,84 @@ def blendShapeManagerUI(): targetListTXT = mc.text(label='Target List') targetListTSL = mc.textScrollList('bsMan_targetsTSL',allowMultiSelection=True) closeB = mc.button(label='Close',c='mc.deleteUI("'+window+'")') - + # Scroll Layout scrollLayout = mc.scrollLayout(horizontalScrollBarThickness=16,verticalScrollBarThickness=16,cr=1) scrollFL = mc.formLayout(numberOfDivisions=100) - + # Info Box infoFRL = mc.frameLayout(label='BlendShape Info',collapsable=True,cl=False,p=scrollFL) infoFL = mc.formLayout(numberOfDivisions=100) infoSF = mc.scrollField('bsMan_infoSF',wordWrap=False,ed=False,text='',nl=6,h=105) - + # Add Target addTargetFRL = mc.frameLayout(label='Add Target',collapsable=True,cl=True,p=scrollFL) addTargetCL = mc.columnLayout() addTargetGeoTFB = mc.textFieldButtonGrp('bsMan_addTargetGeoTFB',label='Target Geo',text='',buttonLabel='<<<',cw=(1,cw)) addTargetNameTFG = mc.textFieldGrp('bsMan_addTargetNameTFG',label='Target Name',text='',cw=(1,cw)) addTargetB = mc.button(label='Add Target',c='glTools.ui.blendShape.addTargetFromUI()') - + # Add Inbetween addInbetweenFRL = mc.frameLayout(label='Add Target Inbetween',collapsable=True,cl=True,p=scrollFL) addInbetweenCL = mc.columnLayout() addInbetweenTFB = mc.textFieldButtonGrp('bsMan_addInbetweenTFB',label='Inbetween Geo',text='',buttonLabel='<<<',cw=(1,cw)) addInbetweenFSG = mc.floatSliderGrp('bsMan_addInbetweenFSG',label='Target Weight',field=True,minValue=0.0,maxValue=1.0,pre=2,fieldMinValue=-100.0,fieldMaxValue=100.0,value=0.5,cw=(1,cw)) addInbetweenB = mc.button(label='Add Target Inbetween',c='glTools.ui.blendShape.addTargetInbetweenFromUI()') - + # Connect To Target connectTargetFRL = mc.frameLayout(label='Connect To Target',collapsable=True,cl=True,p=scrollFL) connectTargetCL = mc.columnLayout() connectTargetTFB = mc.textFieldButtonGrp('bsMan_connectTargetTFB',label='Target Geo',text='',buttonLabel='<<<',cw=(1,cw)) connectTargetFSG = mc.floatSliderGrp('bsMan_connectTargetFSG',label='Target Weight',field=True,minValue=0.0,maxValue=1.0,pre=2,fieldMinValue=-100.0,fieldMaxValue=100.0,value=1.0,cw=(1,cw)) connectTargetB = mc.button(label='Connect To Target',c='glTools.ui.blendShape.connectToTargetFromUI()') - + # Remove Target removeTargetFRL = mc.frameLayout(label='Remove Targets',collapsable=True,cl=True,p=scrollFL) removeTargetCL = mc.columnLayout() removeTargetB = mc.button(label='Remove Targets',c='glTools.ui.blendShape.removeTargetFromUI()') - + # Rename Target renameTargetFRL = mc.frameLayout(label='Rename Target',collapsable=True,cl=True,p=scrollFL) renameTargetCL = mc.columnLayout() renameTargetTFG = mc.textFieldGrp('bsMan_renameTargetTFB',label='Target Name',text='',cw=(1,cw)) renameTargetB = mc.button(label='Rename Target',c='glTools.ui.blendShape.renameTargetFromUI()') - + # Update Targets updateTargetFRL = mc.frameLayout(label='Update Targets',collapsable=True,cl=True,p=scrollFL) updateTargetCL = mc.columnLayout() updateTargetTFB = mc.textFieldButtonGrp('bsMan_updateTargetTFB',label='New Base Geo',text='',buttonLabel='<<<',cw=(1,cw)) updateTargetB = mc.button(label='Update Selected Targets',c='glTools.ui.blendShape.bsManUpdateTargetsFromUI()') - + # Regenerate Targets regenerateTargetFRL = mc.frameLayout(label='Regenerate Targets',collapsable=True,cl=True,p=scrollFL) regenerateTargetCL = mc.columnLayout() regenerateTargetCBG = mc.checkBoxGrp('bsMan_regenerateTargetCBG',numberOfCheckBoxes=1,label='Reconnect Targets',v1=True,cw=(1,cw)) regenerateTargetB = mc.button(label='Regenerate Targets',c='glTools.ui.blendShape.regenerateTargetsFromUI()') - + # ======================== # - UI Callback Commands - # ======================== - + reloadCmd = 'import glTools.ui.blendShape;reload(glTools.ui.blendShape);glTools.ui.blendShape.reloadUI()' mc.textScrollList(blendShapeTSL,e=True,sc=reloadCmd) mc.textScrollList(baseGeomTSL,e=True,sc=reloadCmd) mc.textScrollList(targetListTSL,e=True,sc=reloadCmd) - + mc.textFieldButtonGrp(addTargetGeoTFB,e=True,bc='glTools.ui.utils.loadObjectSel(textField="'+addTargetGeoTFB+'")') mc.textFieldButtonGrp(addInbetweenTFB,e=True,bc='glTools.ui.utils.loadObjectSel(textField="'+addInbetweenTFB+'")') mc.textFieldButtonGrp(connectTargetTFB,e=True,bc='glTools.ui.utils.loadObjectSel(textField="'+connectTargetTFB+'")') mc.textFieldButtonGrp(updateTargetTFB,e=True,bc='glTools.ui.utils.loadObjectSel(textField="'+updateTargetTFB+'")') - + # Auto apply (WIP) #mc.textFieldButtonGrp(updateTargetTFB,e=True,cc=glTools.ui.blendShape.renameTargetFromUI()) - + # ================ # - Form Layouts - # ================ - + cw1 = 25 cw2 = 50 - + mc.formLayout(FL,e=True,af=[(closeB,'bottom',5),(closeB,'left',5),(closeB,'right',5)]) mc.formLayout(FL,e=True,af=[(blendShapeTXT,'top',5),(blendShapeTXT,'left',5)],ap=[(blendShapeTXT,'right',5,cw1)]) mc.formLayout(FL,e=True,ac=[(blendShapeTSL,'top',5,blendShapeTXT)],af=[(blendShapeTSL,'left',5)],ap=[(blendShapeTSL,'right',5,cw1),(blendShapeTSL,'bottom',5,50)]) @@ -116,7 +116,7 @@ def blendShapeManagerUI(): mc.formLayout(FL,e=True,af=[(targetListTXT,'top',5)],ap=[(targetListTXT,'left',5,cw1),(targetListTXT,'right',5,cw2)]) mc.formLayout(FL,e=True,ac=[(targetListTSL,'top',5,targetListTXT),(targetListTSL,'bottom',5,closeB)],ap=[(targetListTSL,'left',5,cw1),(targetListTSL,'right',5,cw2)]) mc.formLayout(FL,e=True,ac=[(scrollLayout,'bottom',5,closeB)],af=[(scrollLayout,'top',5),(scrollLayout,'right',5)],ap=[(scrollLayout,'left',5,cw2)]) - + mc.formLayout(scrollFL,e=True,af=[(infoFRL,'top',5),(infoFRL,'left',5),(infoFRL,'right',5)]) mc.formLayout(scrollFL,e=True,ac=[(addTargetFRL,'top',5,infoFRL)],af=[(addTargetFRL,'left',5),(addTargetFRL,'right',5)]) mc.formLayout(scrollFL,e=True,ac=[(addInbetweenFRL,'top',5,addTargetFRL)],af=[(addInbetweenFRL,'left',5),(addInbetweenFRL,'right',5)]) @@ -125,15 +125,15 @@ def blendShapeManagerUI(): mc.formLayout(scrollFL,e=True,ac=[(renameTargetFRL,'top',5,removeTargetFRL)],af=[(renameTargetFRL,'left',5),(renameTargetFRL,'right',5)]) mc.formLayout(scrollFL,e=True,ac=[(updateTargetFRL,'top',5,renameTargetFRL)],af=[(updateTargetFRL,'left',5),(updateTargetFRL,'right',5)]) mc.formLayout(scrollFL,e=True,ac=[(regenerateTargetFRL,'top',5,updateTargetFRL)],af=[(regenerateTargetFRL,'left',5),(regenerateTargetFRL,'right',5)]) - + mc.formLayout(infoFL,e=True,af=[(infoSF,'top',5),(infoSF,'bottom',5),(infoSF,'left',5),(infoSF,'right',5)]) - + # =============== # - Show Window - # =============== - + reloadUI() - + mc.showWindow(window) def reloadUI(): @@ -143,7 +143,7 @@ def reloadUI(): reloadBlendShapeList() reloadBaseGeoList() reloadTargetList() - + # Reload Info reloadInfo() @@ -152,16 +152,16 @@ def reloadBlendShapeList(): ''' # Get Current List Selection bsSel = mc.textScrollList('bsMan_blendShapeTSL',q=True,si=True) - + # Build BlendShape List bsList = mc.ls(type='blendShape') - + # Clear List mc.textScrollList('bsMan_blendShapeTSL',e=True,ra=True) - + # Rebuild List for bs in bsList: mc.textScrollList('bsMan_blendShapeTSL',e=True,a=bs) - + # Rebuild List Selection if bsSel: if bsSel[0] in bsList: @@ -173,18 +173,18 @@ def reloadBaseGeoList(): ''' # Get BlendShape Selection blendShape = mc.textScrollList('bsMan_blendShapeTSL',q=True,si=True) - + # Get Current List Selection baseSel = mc.textScrollList('bsMan_baseGeomTSL',q=True,si=True) - + # Clear List mc.textScrollList('bsMan_baseGeomTSL',e=True,ra=True) if not blendShape: return - + # Populate List baseGeo = glTools.utils.blendShape.getBaseGeo(blendShape[0]) for base in baseGeo: mc.textScrollList('bsMan_baseGeomTSL',e=True,a=base) - + # Rebuild List Selection if baseSel: baseSel = list(set(baseSel)&set(baseGeo)) if baseSel: mc.textScrollList('bsMan_baseGeomTSL',e=True,si=baseSel) @@ -195,18 +195,18 @@ def reloadTargetList(): ''' # Get BlendShape Selection blendShape = mc.textScrollList('bsMan_blendShapeTSL',q=True,si=True) - + # Get Current List Selection targetSel = mc.textScrollList('bsMan_targetsTSL',q=True,si=True) - + # Clear List mc.textScrollList('bsMan_targetsTSL',e=True,ra=True) if not blendShape: return - + # Populate List targetList = glTools.utils.blendShape.getTargetList(blendShape[0]) for target in targetList: mc.textScrollList('bsMan_targetsTSL',e=True,a=target) - + # Rebuild List Selection if targetSel: targetSel = list(set(targetSel)&set(targetList)) if targetSel: mc.textScrollList('bsMan_targetsTSL',e=True,si=targetSel) @@ -222,7 +222,7 @@ def reloadInfo(): if not base: base = [''] target = mc.textScrollList('bsMan_targetsTSL',q=True,si=True) if not target: target = [''] - + # Get Derived Data baseIndex = '' targetGeo = '' @@ -230,14 +230,14 @@ def reloadInfo(): if base[0]: baseIndex = glTools.utils.blendShape.getBaseIndex(blendShape[0],base[0]) if target[0]: targetGeo = glTools.utils.blendShape.getTargetGeo(blendShape[0],target[0],base[0]) if target[0]: targetIndex = glTools.utils.blendShape.getTargetIndex(blendShape[0],target[0]) - + infoTxt = 'BlendShape: '+blendShape[0]+'\n' infoTxt += 'Base Geometry: '+base[0]+'\n' infoTxt += 'Base Index: '+str(baseIndex)+'\n' infoTxt += 'Target Name: '+target[0]+'\n' infoTxt += 'Target Geometry: '+targetGeo+'\n' infoTxt += 'Target Index: '+str(targetIndex) - + mc.scrollField('bsMan_infoSF',e=True,text=infoTxt) def addTargetFromUI(): @@ -252,7 +252,7 @@ def addTargetFromUI(): if not base: base = [''] targetGeo = mc.textFieldButtonGrp('bsMan_addTargetGeoTFB',q=True,text=True) targetName = mc.textFieldGrp('bsMan_addTargetNameTFG',q=True,text=True) - + # Checks if not glTools.utils.blendShape.isBlendShape(blendShape[0]): raise Exception('BlendShape "'+blendShape[0]+'" does not exist!') @@ -260,7 +260,7 @@ def addTargetFromUI(): raise Exception('Base geometry "'+base[0]+'" does not exist!') if not mc.objExists(targetGeo): raise Exception('Target geometry "'+targetGeo+'" does not exist!') - + # Add BlendShape Target glTools.utils.blendShape.addTarget( blendShape=blendShape[0], target=targetGeo, @@ -269,7 +269,7 @@ def addTargetFromUI(): targetAlias=targetName, targetWeight=0.0, topologyCheck=False ) - + # Reload reloadUI() @@ -289,7 +289,7 @@ def addTargetInbetweenFromUI(): return targetGeo = mc.textFieldButtonGrp('bsMan_addInbetweenTFB',q=True,text=True) targetWt = mc.floatSliderGrp('bsMan_addInbetweenFSG',q=True,v=True) - + # Checks if not glTools.utils.blendShape.isBlendShape(blendShape[0]): raise Exception('BlendShape "'+blendShape[0]+'" does not exist!') @@ -297,14 +297,14 @@ def addTargetInbetweenFromUI(): raise Exception('Base geometry "'+base[0]+'" does not exist!') if not mc.objExists(targetGeo): raise Exception('Target geometry "'+targetGeo+'" does not exist!') - + # Add BlendShape Target Inbetween glTools.utils.blendShape.addTargetInbetween( blendShape=blendShape[0], targetGeo=targetGeo, targetName=targetName[0], base=base[0], targetWeight=targetWt ) - + # Reload reloadUI() @@ -324,7 +324,7 @@ def connectToTargetFromUI(): return targetGeo = mc.textFieldButtonGrp('bsMan_connectTargetTFB',q=True,text=True) targetWt = mc.floatSliderGrp('bsMan_connectTargetFSG',q=True,v=True) - + # Checks if not glTools.utils.blendShape.isBlendShape(blendShape[0]): raise Exception('BlendShape "'+blendShape[0]+'" does not exist!') @@ -332,14 +332,14 @@ def connectToTargetFromUI(): raise Exception('Base geometry "'+base[0]+'" does not exist!') if not mc.objExists(targetGeo): raise Exception('Target geometry "'+targetGeo+'" does not exist!') - + # Add BlendShape Target Inbetween glTools.utils.blendShape.connectToTarget( blendShape=blendShape[0], targetGeo=targetGeo, targetName=targetName[0], baseGeo=base[0], weight=1.0 ) - + # Reload reloadUI() @@ -357,20 +357,20 @@ def removeTargetFromUI(): if not targetList: print('No blendShape targets selected!') return - + # Checks if not glTools.utils.blendShape.isBlendShape(blendShape[0]): raise Exception('BlendShape "'+blendShape[0]+'" does not exist!') if base[0] and not mc.objExists(base[0]): raise Exception('Base geometry "'+base[0]+'" does not exist!') - + # Remove BlendShape Targets for target in targetList: if not glTools.utils.blendShape.hasTarget(blendShape[0],target): print('BlendShape "'+blendShape[0]+'" has no target "'+target+'"! Skipping...') continue glTools.utils.blendShape.removeTarget(blendShape=blendShape[0],target=target,baseGeo=base[0]) - + # Reload reloadUI() @@ -390,16 +390,16 @@ def renameTargetFromUI(): if not targetName: print('No target name specified!') return - + # Checks if not glTools.utils.blendShape.isBlendShape(blendShape[0]): raise Exception('BlendShape "'+blendShape[0]+'" does not exist!') if not glTools.utils.blendShape.hasTarget(blendShape[0],target[0]): raise Exception('BlendShape "" has not target "'+target+'"!') - + # Rename BlendShape Target glTools.utils.blendShape.renameTarget(blendShape=blendShape[0],target=target[0],newName=targetName) - + # Reload reloadUI() @@ -416,7 +416,7 @@ def bsManUpdateTargetsFromUI(): oldBase = base[0] newBase = mc.textFieldButtonGrp('bsMan_updateTargetTFB',q=True,text=True) targetList = mc.textScrollList('bsMan_targetsTSL',q=True,si=True) - + # Checks if not glTools.utils.blendShape.isBlendShape(blendShape[0]): raise Exception('BlendShape "'+blendShape[0]+'" does not exist!') @@ -425,7 +425,7 @@ def bsManUpdateTargetsFromUI(): if not mc.objExists(newBase): raise Exception('New base geometry "'+newBase+'" does not exist!') if not targetList: raise Exception('Empty target list!') - + # Get Target Geometry targetGeoList = [] for target in targetList: @@ -434,7 +434,7 @@ def bsManUpdateTargetsFromUI(): print('No target geometry found for target name"'+target+'"! Skipping') continue targetGeoList.append(targetGeo) - + # Update Targets glTools.tools.blendShape.updateTargets(oldBase,newBase,targetGeoList) @@ -444,39 +444,39 @@ def regenerateTargetsFromUI(): # =============== # - Get UI Data - # =============== - + # BlendShape blendShape = mc.textScrollList('bsMan_blendShapeTSL',q=True,si=True) if not blendShape: print('No blendShape node selected!') return - + # Base Geo base = mc.textScrollList('bsMan_baseGeomTSL',q=True,si=True) if not base: base = [''] - + # Target List targetList = mc.textScrollList('bsMan_targetsTSL',q=True,si=True) if not targetList: print('No blendShape targets selected!') return - + # Reconnect Targets connect = mc.checkBoxGrp('bsMan_regenerateTargetCBG',q=True,v1=True) - + # ========== # - Checks - # ========== - + if not glTools.utils.blendShape.isBlendShape(blendShape[0]): raise Exception('BlendShape "'+blendShape[0]+'" does not exist!') if base[0] and not mc.objExists(base[0]): raise Exception('Base geometry "'+base[0]+'" does not exist!') - + # ============================== # - Regenerate Target Geometry - # ============================== - + for target in targetList: if not glTools.utils.blendShape.hasTarget(blendShape[0],target): print('BlendShape "'+blendShape[0]+'" has no target "'+target+'"! Skipping...') @@ -492,10 +492,10 @@ def updateTargetsUI(): window = 'updateTargetsUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Update BlendShape Targets') - + # Layout FL = mc.formLayout() - + # UI Elements oldBaseTFB = mc.textFieldButtonGrp('updateTarget_oldBaseTFB',label='Old Base',text='',buttonLabel='<<<') newBaseTFB = mc.textFieldButtonGrp('updateTarget_newBaseTFB',label='New Base',text='',buttonLabel='<<<') @@ -503,16 +503,16 @@ def updateTargetsUI(): targetListTSL = mc.textScrollList('updateTarget_targetsTSL',allowMultiSelection=True) updateB = mc.button(label='Update Targets',c='glTools.ui.blendShape.updateTargetsFromUI()') cancelB = mc.button(label='Cancel',c='mc.deleteUI("'+window+'")') - + # PopUp Menu Items mc.popupMenu(parent=targetListTSL) mc.menuItem(label='Add Selected',c='glTools.ui.utils.addToTSL(TSL="'+targetListTSL+'")') mc.menuItem(label='Remove Selected',c='glTools.ui.utils.removeFromTSL(TSL="'+targetListTSL+'")') - + # UI Callback Commands mc.textFieldButtonGrp(oldBaseTFB,e=True,bc='glTools.ui.utils.loadObjectSel(textField="'+oldBaseTFB+'")') mc.textFieldButtonGrp(newBaseTFB,e=True,bc='glTools.ui.utils.loadObjectSel(textField="'+newBaseTFB+'")') - + # Form Layouts mc.formLayout(FL,e=True,af=[(oldBaseTFB,'top',5),(oldBaseTFB,'left',5),(oldBaseTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(newBaseTFB,'top',5,oldBaseTFB)],af=[(newBaseTFB,'left',5),(newBaseTFB,'right',5)]) @@ -520,7 +520,7 @@ def updateTargetsUI(): mc.formLayout(FL,e=True,af=[(cancelB,'bottom',5),(cancelB,'left',5),(cancelB,'right',5)]) mc.formLayout(FL,e=True,ac=[(updateB,'bottom',5,cancelB)],af=[(updateB,'left',5),(updateB,'right',5)]) mc.formLayout(FL,e=True,ac=[(targetListTSL,'top',5,targetListTXT),(targetListTSL,'bottom',5,updateB)],af=[(targetListTSL,'left',5),(targetListTSL,'right',5)]) - + # Show Window mc.showWindow(window) @@ -531,7 +531,7 @@ def updateTargetsFromUI(): oldBase = mc.textFieldButtonGrp('updateTarget_oldBaseTFB',q=True,text=True) newBase = mc.textFieldButtonGrp('updateTarget_newBaseTFB',q=True,text=True) targetList = mc.textScrollList('updateTarget_targetsTSL',q=True,ai=True) - + # Checks if not mc.objExists(oldBase): raise Exception('Old base geometry "'+oldBase+'" does not exist!') @@ -541,6 +541,6 @@ def updateTargetsFromUI(): for target in targetList: if not mc.objExists(target): raise Exception('Target geometry "'+target+'" does not exist!') - + # Update Targets glTools.tools.blendShape.updateTargets(oldBase,newBase,targetList) diff --git a/ui/controlBuilder.py b/ui/controlBuilder.py index d4e02a7..728ec32 100644 --- a/ui/controlBuilder.py +++ b/ui/controlBuilder.py @@ -37,20 +37,20 @@ def controlBuilderFromUI(close=True): # Window window = 'controlBuilderUI' if not mc.window(window,q=True,ex=1): raise UIError('Control Builder UI does not exist!!') - + # Get UI data cName = mc.textFieldGrp('controlNameTFG',q=True,text=True) cType = mc.optionMenuGrp('controlTypeOMG',q=True,v=True) cType = str.lower(str(cType[0]))+cType[1:] cBuffer = mc.checkBoxGrp('controlBufferCBG',q=True,v1=True) - + # Get Active Selection tSel = [] sel = mc.ls(sl=1) for obj in sel: if glTools.utils.transform.isTransform(obj): tSel.append(obj) - + # Execute if tSel: for obj in tSel: @@ -60,6 +60,6 @@ def controlBuilderFromUI(close=True): # Buffer if cBuffer: glTools.utils.base.group(ctrl,groupType=1,center=1,orient=1) - + # Cleanup if close: mc.deleteUI(window) diff --git a/ui/curve.py b/ui/curve.py index 91ab4f5..2a81011 100644 --- a/ui/curve.py +++ b/ui/curve.py @@ -34,10 +34,10 @@ def locatorCurveUI(): # Buttons createB = mc.button('locatorCurveCreateB',l='Create',c='glTools.ui.curve.locatorCurveFromUI(False)') cancelB = mc.button('locatorCurveCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # TFB commands mc.textFieldButtonGrp(curveTFB,e=True,bc='glTools.ui.utils.loadCurveSel("'+curveTFB+'","'+prefixTFG+'")') - + # Show Window mc.showWindow(window) @@ -98,13 +98,13 @@ def attachToCurveUI(): # Buttons createB = mc.button('attachToCurveCreateB',l='Create',c='glTools.ui.curve.attachToCurveFromUI(False)') cancelB = mc.button('attachToCurveCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # UI callback commands mc.textFieldButtonGrp(curveTFB,e=True,bc='glTools.ui.utils.loadCurveSel("'+curveTFB+'")') mc.textFieldButtonGrp(transformTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+transformTFB+'","'+prefixTFG+'")') mc.textFieldButtonGrp(upVectorObjectTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+upVectorObjectTFB+'")') mc.checkBoxGrp(closestPointCBG,e=True,cc='glTools.ui.utils.checkBoxToggleControl("'+closestPointCBG+'","'+parameterFSG+'",invert=True)') - + # Show Window mc.showWindow(window) @@ -156,7 +156,7 @@ def curveToLocatorsUI(): # Buttons createB = mc.button('attachToCurveCreateB',l='Create',c='glTools.ui.curve.curveToLocatorsFromUI(False)') cancelB = mc.button('attachToCurveCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # Form Layout mc.formLayout(fl,e=True,af=[(curveTFB,'top',5),(curveTFB,'left',5),(curveTFB,'right',5)]) mc.formLayout(fl,e=True,ac=[(locListTSL,'top',5,curveTFB),(locListTSL,'bottom',5,locAddB)]) @@ -168,10 +168,10 @@ def curveToLocatorsUI(): mc.formLayout(fl,e=True,ac=[(createB,'bottom',1,cancelB)]) mc.formLayout(fl,e=True,af=[(createB,'left',5),(createB,'right',5)]) mc.formLayout(fl,e=True,af=[(cancelB,'bottom',5),(cancelB,'left',5),(cancelB,'right',5)]) - + # TFB commands mc.textFieldButtonGrp(curveTFB,e=True,bc='glTools.ui.utils.loadCurveSel("'+curveTFB+'")') - + # Show Window mc.showWindow(window) @@ -202,7 +202,7 @@ def createAlongCurveUI(): window = 'createAlongCurveUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Create Along Curve') - + # Layout cl = mc.columnLayout() # Curve @@ -221,15 +221,15 @@ def createAlongCurveUI(): # Min/Max Percent minPercentFFG = mc.floatSliderGrp('createAlongCurveMinFSG',label='Min Percent',field=True,minValue=0.0,maxValue=1.0,fieldMinValue=0.0,fieldMaxValue=1.0,value=0.0) maxPercentFFG = mc.floatSliderGrp('createAlongCurveMaxFSG',label='Max Percent',field=True,minValue=0.0,maxValue=1.0,fieldMinValue=0.0,fieldMaxValue=1.0,value=1.0) - + # Buttons createB = mc.button('createAlongCurveCreateB',l='Create',c='glTools.ui.curve.createAlongCurveFromUI(False)') createCloseB = mc.button('createAlongCurveCreateCloseB',l='Create and Close',c='glTools.ui.curve.createAlongCurveFromUI(True)') cancelB = mc.button('createAlongCurveCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # TFB commands mc.textFieldButtonGrp(curveTFB,e=True,bc='glTools.ui.utils.loadCurveSel("'+curveTFB+'","'+prefixTFG+'")') - + # Show Window mc.showWindow(window) @@ -248,10 +248,10 @@ def createAlongCurveFromUI(close=False): useDist = mc.checkBoxGrp('createAlongCurveDistCBG',q=True,v1=True) minVal = mc.floatSliderGrp('createAlongCurveMinFSG',q=True,v=True) maxVal = mc.floatSliderGrp('createAlongCurveMaxFSG',q=True,v=True) - + # Execute command glTools.tools.createAlongCurve.create(curve,objType,objCount,parent,useDist,minVal,maxVal,prefix) - + # Cleanup if close: mc.deleteUI(window) @@ -265,7 +265,7 @@ def edgeLoopCurveUI(): window = 'edgeLoopCurveUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Edge Loop Curve') - + # Layout CL = mc.columnLayout() # Prefix @@ -274,15 +274,15 @@ def edgeLoopCurveUI(): rebuildCBG = mc.checkBoxGrp('edgeLoopCurveRebuildCBG',numberOfCheckBoxes=1,label='Rebuild Curve',v1=True) # Span Count spanISG = mc.intSliderGrp('edgeLoopCurveSpanISG',field=True,label='Rebuild Spans',minValue=0,maxValue=10,fieldMinValue=0,fieldMaxValue=100,value=0,en=1) - + # Toggle UI element mc.checkBoxGrp('edgeLoopCurveRebuildCBG',e=True,cc='mc.intSliderGrp("edgeLoopCurveSpanISG",e=1,en=(not mc.intSliderGrp("edgeLoopCurveSpanISG",q=1,en=1)))') - + # Buttons createB = mc.button('edgeLoopCurveCreateB',l='Create',c='glTools.ui.curve.edgeLoopCurveFromUI(False)') createCloseB = mc.button('edgeLoopCurveCreateCloseB',l='Create and Close',c='glTools.ui.curve.edgeLoopCurveFromUI(True)') cancelB = mc.button('edgeLoopCurveCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # Show Window mc.showWindow(window) @@ -299,10 +299,10 @@ def edgeLoopCurveFromUI(close=False): prefix = str(mc.textFieldGrp('edgeLoopCurvePrefixTFG',q=True,text=True)) rebuildCrv = mc.checkBoxGrp('edgeLoopCurveRebuildCBG',q=True,v1=True) spans = mc.intSliderGrp('edgeLoopCurveSpanISG',q=True,v=True) - + # Execute command glTools.utils.curve.edgeLoopCrv(selection,rebuild=rebuildCrv,rebuildSpans=spans,prefix=prefix) - + # Cleanup if close: mc.deleteUI(window) @@ -316,7 +316,7 @@ def uniformRebuildCurveUI(): window = 'uniformRebuildCurveUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Uniform Rebuild Curve') - + # Layout cl = mc.columnLayout() # Curve @@ -327,15 +327,15 @@ def uniformRebuildCurveUI(): replaceCBG = mc.checkBoxGrp('uniformRebuildCurveReplaceCBG',numberOfCheckBoxes=1,label='Replace Original',v1=False) # Spans spanISG = mc.intSliderGrp('uniformRebuildCurveSpansISG',field=True,label='Rebuild Spans',minValue=2,maxValue=10,fieldMinValue=2,fieldMaxValue=100,value=6) - + # Buttons createB = mc.button('uniformRebuildCurveCreateB',l='Create',c='glTools.ui.curve.uniformRebuildCurveFromUI(False)') createCloseB = mc.button('uniformRebuildCurveCreateCloseB',l='Create and Close',c='glTools.ui.curve.uniformRebuildCurveFromUI(True)') cancelB = mc.button('uniformRebuildCurveCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # TFB commands mc.textFieldButtonGrp(curveTFB,e=True,bc='glTools.ui.utils.loadCurveSel("'+curveTFB+'","'+prefixTFG+'")') - + # Show Window mc.showWindow(window) @@ -352,10 +352,10 @@ def uniformRebuildCurveFromUI(close=False): prefix = str(mc.textFieldGrp('uniformRebuildCurvePrefixTFG',q=True,text=True)) replace = mc.checkBoxGrp('uniformRebuildCurveReplaceCBG',q=True,v1=True) spans = mc.intSliderGrp('uniformRebuildCurveSpansISG',q=True,v=True) - + # Execute command glTools.utils.curve.uniformRebuild(curve=curve,spans=spans,replaceOriginal=replace,prefix=prefix) - + # Cleanup if close: mc.deleteUI(window) @@ -368,13 +368,13 @@ def mirrorCurveFromSel(): # Get Selection sel = mc.ls(sl=1,type=['transform','joint','nurbsCurve']) if not sel: return - + # For Each Item in Selection for item in sel: - + # Define Curve Shape crv = '' - + # Check Transform if glTools.utils.transform.isTransform(item): # Get Shapes @@ -395,13 +395,13 @@ def mirrorCurveFromSel(): else: # Set Curve crv = item - + # Find Mirror mirrorCrv = '' if crv.startswith('lf_'): mirrorCrv = crv.replace('lf_','rt_') elif crv.startswith('rt_'): mirrorCrv = crv.replace('rt_','lf_') else: print('Unable to determine mirror curve for "'+crv+'"! Skipping...') - + # Mirror Curve glTools.utils.curve.mirrorCurve(crv,mirrorCrv) diff --git a/ui/exportPointData.py b/ui/exportPointData.py index d1da856..fda0046 100644 --- a/ui/exportPointData.py +++ b/ui/exportPointData.py @@ -9,18 +9,18 @@ def exportPointDataUI(): ''' Main UI for the exportPointData module ''' - # Get current frame range + # Get current frame range startFrame = mc.playbackOptions(q=True,min=True) endFrame = mc.playbackOptions(q=True,max=True) - + # Window window = 'exportPointDataUI' if mc.window(window,q=True,ex=True): mc.deleteUI(window) window = mc.window(window,t='Export Point Data',s=False) - + # Layout CL = mc.columnLayout(adj=True) - + # UI Elements pathTBG = mc.textFieldButtonGrp('exportPoint_pathTBG',label='Path',buttonLabel='...') camTBG = mc.textFieldButtonGrp('exportPoint_camTBG',label='Camera (2D only)',buttonLabel='Select') @@ -33,25 +33,25 @@ def exportPointDataUI(): export3DB = mc.button('exportPoint_export3DB',label='Export 3D Point Data',c='glTools.ui.exportPointData.export3DFromUI()') export3DRotB = mc.button('exportPoint_export3DRotB',label='Export 3D Rotate Data',c='glTools.ui.exportPointData.export3DRotationFromUI()') closeB = mc.button('exportPoint_closeB',label='Close',c='mc.deleteUI("'+window+'")') - + # Resolution presets mc.setParent(resOMG) mc.menuItem(label='WIDE(full)') mc.menuItem(label='WIDE(half)') mc.menuItem(label='WIDE(quarter)') - + # UI Callbacks mc.textFieldButtonGrp(pathTBG,e=True,bc='glTools.ui.utils.exportFolderBrowser("'+pathTBG+'")') mc.textFieldButtonGrp(camTBG,e=True,bc='glTools.ui.utils.loadTypeSel("'+camTBG+'",selType="transform")') mc.optionMenuGrp(resOMG,e=True,cc='glTools.tools.exportPointData.setResolution()') - + # Popup menu mc.popupMenu(parent=camTBG) for cam in mc.ls(type='camera'): if mc.camera(cam,q=True,orthographic=True): continue camXform = mc.listRelatives(cam,p=True,pa=True)[0] mc.menuItem(l=camXform,c='mc.textFieldButtonGrp("exportPoint_camTBG",e=True,text="'+camXform+'")') - + # Show Window mc.window(window,e=True,w=435,h=275) mc.showWindow(window) @@ -74,7 +74,7 @@ def export2DFromUI(): if not sel: print 'No points selected for export!!' return - + # Get UI data path = mc.textFieldButtonGrp('exportPoint_pathTBG',q=True,text=True) cam = mc.textFieldButtonGrp('exportPoint_camTBG',q=True,text=True) @@ -82,7 +82,7 @@ def export2DFromUI(): end = mc.intFieldGrp('exportPoint_rangeIFG',q=True,v2=True) xRes = mc.intFieldGrp('exportPoint_resIFG',q=True,v1=True) yRes = mc.intFieldGrp('exportPoint_resIFG',q=True,v2=True) - + # Check UI data if not cam or not mc.objExists(cam): print('No valid camera specified!') @@ -91,25 +91,25 @@ def export2DFromUI(): print('Invalid range specified!') return if not path.endswith('/'): path += '/' - + # For each point for pt in sel: - + # Generate export file path sel_name = pt.split(':')[-1].replace('.','_').replace('[','_').replace(']','') filepath = path + sel_name + '_2D.txt' - + # Check path if os.path.isfile(filepath): chk = mc.confirmDialog(t='Warning: File exists',message='File "'+filepath+'" already exist! Overwrite?',button=['Yes','No'],defaultButton='Yes',cancelButton='No',dismissString='No') if chk == 'No': continue - + # Isolate Select - ON setIsolateSelect(pt,1) - + # Export data glTools.tools.exportPointData.export2DPointData(filepath,pt,cam,start,end,xRes,yRes) - + # Isolate Select - OFF setIsolateSelect(pt,0) @@ -122,7 +122,7 @@ def export2DOffsetFromUI(): if not sel: print 'No points selected for export!!' return - + # Get UI data path = mc.textFieldButtonGrp('exportPoint_pathTBG',q=True,text=True) cam = mc.textFieldButtonGrp('exportPoint_camTBG',q=True,text=True) @@ -131,7 +131,7 @@ def export2DOffsetFromUI(): ref = mc.intFieldGrp('exportPoint_refIFG',q=True,v1=True) xRes = mc.intFieldGrp('exportPoint_resIFG',q=True,v1=True) yRes = mc.intFieldGrp('exportPoint_resIFG',q=True,v2=True) - + # Check UI data if not cam or not mc.objExists(cam): print('No valid camera specified!') @@ -140,28 +140,28 @@ def export2DOffsetFromUI(): print('Invalid range specified!') return if not path.endswith('/'): path += '/' - + # For each point for pt in sel: - + # Generate export file path sel_name = pt.split(':')[-1].replace('.','_').replace('[','_').replace(']','') filepath = path + sel_name + '_2DOffset.txt' - + # Check path if os.path.isfile(filepath): chk = mc.confirmDialog(t='Warning: File exists',message='File "'+filepath+'" already exist! Overwrite?',button=['Yes','No'],defaultButton='Yes',cancelButton='No',dismissString='No') if chk == 'No': continue - + # Isolate Select - ON setIsolateSelect(pt,1) - + # Export data glTools.tools.exportPointData.export2DOffsetData(filepath,pt,cam,start,end,xRes,yRes,ref) - + # Isolate Select - OFF setIsolateSelect(pt,0) - + def export3DFromUI(): ''' export3DPointData from UI @@ -171,36 +171,36 @@ def export3DFromUI(): if not sel: print 'No points selected for export!!' return - + # Get UI data path = mc.textFieldButtonGrp('exportPoint_pathTBG',q=True,text=True) start = mc.intFieldGrp('exportPoint_rangeIFG',q=True,v1=True) end = mc.intFieldGrp('exportPoint_rangeIFG',q=True,v2=True) - + # Check UI data if start > end: print('Invalid range specified!') return if not path.endswith('/'): path += '/' - + # For each point for pt in sel: - + # Generate export file path sel_name = pt.split(':')[-1].replace('.','_').replace('[','_').replace(']','') filepath = path + sel_name + '_3D.txt' - + # Check path if os.path.isfile(filepath): chk = mc.confirmDialog(t='Warning: File exists',message='File "'+filepath+'" already exist! Overwrite?',button=['Yes','No'],defaultButton='Yes',cancelButton='No',dismissString='No') if chk == 'No': continue - + # Isolate Select - ON setIsolateSelect(pt,1) - + # Export data glTools.tools.exportPointData.export3DPointData(filepath,pt,start,end) - + # Isolate Select - OFF setIsolateSelect(pt,0) @@ -213,36 +213,36 @@ def export3DRotationFromUI(): if not sel: print 'No valid transform selected for export!!' return - + # Get UI data path = mc.textFieldButtonGrp('exportPoint_pathTBG',q=True,text=True) start = mc.intFieldGrp('exportPoint_rangeIFG',q=True,v1=True) end = mc.intFieldGrp('exportPoint_rangeIFG',q=True,v2=True) - + # Check UI data if start > end: print('Invalid range specified!') return if not path.endswith('/'): path += '/' - + # For each point for pt in sel: - + # Generate export file path sel_name = pt.split(':')[-1].replace('.','_').replace('[','_').replace(']','') filepath = path + sel_name + '_3Drot.txt' - + # Check path if os.path.isfile(filepath): chk = mc.confirmDialog(t='Warning: File exists',message='File "'+filepath+'" already exist! Overwrite?',button=['Yes','No'],defaultButton='Yes',cancelButton='No',dismissString='No') if chk == 'No': continue - + # Isolate Select - ON setIsolateSelect(pt,1) - + # Export data glTools.tools.exportPointData.export3DRotationData(filepath,pt,start,end,rotateOrder='zxy') - + # Isolate Select - OFF setIsolateSelect(pt,0) @@ -252,13 +252,13 @@ def setIsolateSelect(pt,state): # Check point if not mc.objExists(pt): raise Exception('Object "'+pt+'" does not exist!') - + # Select point mc.select(pt) - + # Get panel list panelList = mc.getPanel(type='modelPanel') - + # For each panel for panel in panelList: mc.isolateSelect(panel,state=state) diff --git a/ui/faceForward.py b/ui/faceForward.py index c22ebd7..7c41a96 100644 --- a/ui/faceForward.py +++ b/ui/faceForward.py @@ -12,39 +12,39 @@ def faceForwardUI(): win = 'faceForwardUI' if mc.window(win,q=True,ex=True): mc.deleteUI(win) win = mc.window(win,t='Face Forward') - + # Layout formLayout = mc.formLayout(numberOfDivisions=100) - + # Transform transformTFB = mc.textFieldButtonGrp('faceForwardTransformTFB',label='Transform',text='',buttonLabel='Load Selected') - + # Axis' axisList = ['X','Y','Z','-X','-Y','-Z'] aimOMG = mc.optionMenuGrp('faceForwardAimOMG',label='Aim Axis') for axis in axisList: mc.menuItem(label=axis) upOMG = mc.optionMenuGrp('faceForwardUpOMG',label='Up Axis') for axis in axisList: mc.menuItem(label=axis) - + # Up Vector upVecFFG = mc.floatFieldGrp('faceForwardUpVecFFG',label='Up Vector',numberOfFields=3,value1=0.0,value2=1.0,value3=0.0) upVecTypeOMG = mc.optionMenuGrp('faceForwardUpVecTypeOMG',label='Up Vector Type') for method in ['Current','Vector','Object','ObjectUp']: mc.menuItem(label=method) upVecObjTFB = mc.textFieldButtonGrp('faceForwardUpVecObjTFB',label='Up Vector Object',text='',buttonLabel='Load Selected') - + # Previous Frame prevFrameCBG = mc.checkBoxGrp('faceForwardPrevFrameCBG',label='Prev Frame Velocity',numberOfCheckBoxes=1) # Key keyframeCBG = mc.checkBoxGrp('faceForwardKeyCBG',label='Set Keyframe',numberOfCheckBoxes=1) - + # Buttons faceForwardB = mc.button(label='Face Forward',c='glTools.ui.faceForward.faceForwardFromUI()') cancelB = mc.button(label='Cancel',c='mc.deleteUI("'+win+'")') - + # UI Callbacks mc.textFieldButtonGrp(transformTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+transformTFB+'","","transform")') mc.textFieldButtonGrp(upVecObjTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+upVecObjTFB+'","","transform")') - + # Form Layout - MAIN mc.formLayout(formLayout,e=True,af=[(transformTFB,'left',5),(transformTFB,'top',5),(transformTFB,'right',5)]) mc.formLayout(formLayout,e=True,af=[(aimOMG,'left',5),(aimOMG,'right',5)]) @@ -61,15 +61,15 @@ def faceForwardUI(): mc.formLayout(formLayout,e=True,ac=[(prevFrameCBG,'top',5,upVecObjTFB)]) mc.formLayout(formLayout,e=True,af=[(keyframeCBG,'left',5),(keyframeCBG,'right',5)]) mc.formLayout(formLayout,e=True,ac=[(keyframeCBG,'top',5,prevFrameCBG)]) - + mc.formLayout(formLayout,e=True,af=[(faceForwardB,'right',5),(faceForwardB,'bottom',5)]) mc.formLayout(formLayout,e=True,ac=[(faceForwardB,'top',5,keyframeCBG)]) mc.formLayout(formLayout,e=True,ap=[(faceForwardB,'left',5,50)]) - + mc.formLayout(formLayout,e=True,af=[(cancelB,'left',5),(cancelB,'bottom',5)]) mc.formLayout(formLayout,e=True,ac=[(cancelB,'top',5,keyframeCBG)]) mc.formLayout(formLayout,e=True,ap=[(cancelB,'right',5,50)]) - + # Show Window mc.showWindow(win) @@ -85,43 +85,43 @@ def faceForwardAnimUI(): win = 'faceForwardAnimUI' if mc.window(win,q=True,ex=True): mc.deleteUI(win) win = mc.window(win,t='Face Forward Anim') - + # Layout formLayout = mc.formLayout(numberOfDivisions=100) - + # Transform transformTFB = mc.textFieldButtonGrp('faceForwardAnimTransformTFB',label='Transform',text='',buttonLabel='Load Selected') - + # Axis' axisList = ['X','Y','Z','-X','-Y','-Z'] aimOMG = mc.optionMenuGrp('faceForwardAnimAimOMG',label='Aim Axis') for axis in axisList: mc.menuItem(label=axis) upOMG = mc.optionMenuGrp('faceForwardAnimUpOMG',label='Up Axis') for axis in axisList: mc.menuItem(label=axis) - + # Up Vector upVecFFG = mc.floatFieldGrp('faceForwardAnimUpVecFFG',label='Up Vector',numberOfFields=3,value1=0.0,value2=1.0,value3=0.0) upVecTypeOMG = mc.optionMenuGrp('faceForwardAnimUpVecTypeOMG',label='Up Vector Type') for method in ['Current','Vector','Object','ObjectUp']: mc.menuItem(label=method) upVecObjTFB = mc.textFieldButtonGrp('faceForwardAnimUpVecObjTFB',label='Up Vector Object',text='',buttonLabel='Load Selected') - + # Start / End Frame rangeFFG = mc.floatFieldGrp('faceForwardAnimRangeFFG',label='Start/End Frame',numberOfFields=2,value1=-1.0,value2=-1.0) - + # Samples samplesIFG = mc.intFieldGrp('faceForwardAnimSampleIFG',label='Samples',numberOfFields=1) - + # Previous Frame prevFrameCBG = mc.checkBoxGrp('faceForwardAnimPrevFrameCBG',label='Prev Frame Velocity',numberOfCheckBoxes=1) - + # Buttons faceForwardAnimB = mc.button(label='Face Forward',c='glTools.ui.faceForward.faceForwardAnimFromUI()') cancelB = mc.button(label='Cancel',c='mc.deleteUI("'+win+'")') - + # UI Callbacks mc.textFieldButtonGrp(transformTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+transformTFB+'","","transform")') mc.textFieldButtonGrp(upVecObjTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+upVecObjTFB+'","","transform")') - + # Form Layout - MAIN mc.formLayout(formLayout,e=True,af=[(transformTFB,'left',5),(transformTFB,'top',5),(transformTFB,'right',5)]) mc.formLayout(formLayout,e=True,af=[(aimOMG,'left',5),(aimOMG,'right',5)]) @@ -140,15 +140,15 @@ def faceForwardAnimUI(): mc.formLayout(formLayout,e=True,ac=[(samplesIFG,'top',5,rangeFFG)]) mc.formLayout(formLayout,e=True,af=[(prevFrameCBG,'left',5),(prevFrameCBG,'right',5)]) mc.formLayout(formLayout,e=True,ac=[(prevFrameCBG,'top',5,samplesIFG)]) - + mc.formLayout(formLayout,e=True,af=[(faceForwardAnimB,'right',5),(faceForwardAnimB,'bottom',5)]) mc.formLayout(formLayout,e=True,ac=[(faceForwardAnimB,'top',5,prevFrameCBG)]) mc.formLayout(formLayout,e=True,ap=[(faceForwardAnimB,'left',5,50)]) - + mc.formLayout(formLayout,e=True,af=[(cancelB,'left',5),(cancelB,'bottom',5)]) mc.formLayout(formLayout,e=True,ac=[(cancelB,'top',5,prevFrameCBG)]) mc.formLayout(formLayout,e=True,ap=[(cancelB,'right',5,50)]) - + # Show Window mc.showWindow(win) diff --git a/ui/generateWeights.py b/ui/generateWeights.py index 2ea38a1..214c686 100644 --- a/ui/generateWeights.py +++ b/ui/generateWeights.py @@ -10,24 +10,24 @@ def generateWeightsUI(): win = 'generateWeightsUI' if mc.window(win,ex=True): mc.deleteUI(win) win = mc.window(win,t='Generate Weights',wh=[560,285],s=True) - + # FormLayout fl = mc.formLayout(numberOfDivisions=100) - - # UI Elements + + # UI Elements genWt_targetAttrTFG = mc.textFieldGrp('genWt_targetAttrTFG',label='Target Attribute') - + genWt_targetGeoTFG = mc.textFieldButtonGrp('genWt_targetGeoTFG',l='Target Geometry',bl='Select') mc.textFieldButtonGrp(genWt_targetGeoTFG,e=True,bc='glTools.ui.utils.loadObjectSel("'+genWt_targetGeoTFG+'")') - + genWt_smoothISG = mc.intSliderGrp('genWt_smoothWeightTFG',label='Smooth',f=True,minValue=0,maxValue=5,fieldMinValue=0,fieldMaxValue=100,value=0) - + genWt_generateB = mc.button(label='Generate Weights', c='glTools.ui.generateWeights.generateWeightsFromUI()' ) genWt_cancelB = mc.button(label='Cancel', c='mc.deleteUI("'+win+'")' ) - + # TabLayout genWt_tabLayout = mc.tabLayout('genWt_tabLayout', innerMarginWidth=5, innerMarginHeight=5 ) - + # Layout mc.formLayout(fl,e=True,af=[(genWt_targetAttrTFG,'left',5),(genWt_targetAttrTFG,'top',5),(genWt_targetAttrTFG,'right',5)]) mc.formLayout(fl,e=True,af=[(genWt_targetGeoTFG,'left',5),(genWt_targetGeoTFG,'right',5)],ac=[(genWt_targetGeoTFG,'top',5,genWt_targetAttrTFG)]) @@ -35,185 +35,185 @@ def generateWeightsUI(): mc.formLayout(fl,e=True,af=[(genWt_tabLayout,'left',5),(genWt_tabLayout,'right',5)],ac=[(genWt_tabLayout,'top',5,genWt_smoothISG),(genWt_tabLayout,'bottom',5,genWt_generateB)]) mc.formLayout(fl,e=True,af=[(genWt_generateB,'left',5),(genWt_generateB,'bottom',5)],ap=[(genWt_generateB,'right',5,50)]) mc.formLayout(fl,e=True,af=[(genWt_cancelB,'right',5),(genWt_cancelB,'bottom',5)],ap=[(genWt_cancelB,'left',5,50)]) - + # --------------------------- # - Gradient Weights Layout - # --------------------------- - + mc.setParent(genWt_tabLayout) - + # Layout gradWt_columnLayout = mc.columnLayout(dtg='gradient') - + # UI Elements gradWt_pt1TFB = mc.textFieldButtonGrp('genWt_gradWtPt1_TFB',l='Point 1', text='', bl='Select') mc.textFieldButtonGrp(gradWt_pt1TFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+gradWt_pt1TFB+'")') - + gradWt_pt2TFB = mc.textFieldButtonGrp('genWt_gradWtPt2_TFB',l='Point 2', text='', bl='Select') mc.textFieldButtonGrp(gradWt_pt2TFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+gradWt_pt2TFB+'")') - + mc.setParent('..') - + # ------------------------- # - Radial Weights Layout - # ------------------------- - + mc.setParent(genWt_tabLayout) - + # Layout radWt_columnLayout = mc.columnLayout(dtg='radial') - + # UI Elements mc.floatSliderGrp('genWt_radWtRadiusFSG',label='Radius',f=True,minValue=0.001,maxValue=10.0,fieldMinValue=0.001,fieldMaxValue=1000000,value=1.0) mc.floatSliderGrp('genWt_radWtInRadiusFSG',label='Inner Radius',f=True,minValue=0.0,maxValue=10.0,fieldMinValue=0.0,fieldMaxValue=1000000,value=0.0) - + mc.separator(style='single',w=1000,h=20) - + radWt_centFFG = mc.floatFieldGrp('genWt_radWtCent_TFB', numberOfFields=3, label='Center', value1=0.0, value2=0.0, value3=0.0 ) radWt_centB = mc.button( label='Get Point', c='glTools.ui.utils.setPointValue("'+radWt_centFFG+'")' ) - + mc.setParent('..') - + # ------------------------- # - Volume Weights Layout - # ------------------------- - + mc.setParent(genWt_tabLayout) - + # Layout volWt_columnLayout = mc.columnLayout(dtg='volume') - + # UI Elements genWt_volBoundaryTFB = mc.textFieldButtonGrp('genWt_volBoundaryTFB',l='Volume Boundary',bl='Select') mc.textFieldButtonGrp(genWt_volBoundaryTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+genWt_volBoundaryTFB+'")') - + genWt_volInteriorTFB = mc.textFieldButtonGrp('genWt_volInteriorTFB',l='Volume Interior',bl='Select') mc.textFieldButtonGrp(genWt_volInteriorTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+genWt_volInteriorTFB+'")') - + mc.separator(style='single',w=1000,h=20) - + volWt_centFFG = mc.floatFieldGrp('genWt_volWtCent_TFB', numberOfFields=3, label='Volume Center', value1=0.0, value2=0.0, value3=0.0 ) volWt_centB = mc.button( label='Get Point', c='glTools.ui.utils.setPointValue("'+volWt_centFFG+'")' ) - + mc.setParent('..') - + # ---------------------------------- # - Geometry Volume Weights Layout - # ---------------------------------- - + mc.setParent(genWt_tabLayout) - + # Layout geoVolWt_columnLayout = mc.columnLayout(dtg='geometryVolume') - + # UI Elements genWt_geoBoundaryTFB = mc.textFieldButtonGrp('genWt_geoBoundaryTFB',l='Volume Boundary',bl='Select') mc.textFieldButtonGrp(genWt_geoBoundaryTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+genWt_geoBoundaryTFB+'")') - + genWt_geoInteriorTFB = mc.textFieldButtonGrp('genWt_geoInteriorTFB',l='Volume Interior',bl='Select') mc.textFieldButtonGrp(genWt_geoInteriorTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+genWt_geoInteriorTFB+'")') - + mc.separator(style='single',w=1000,h=20) - + geoVolWt_centFFG = mc.floatFieldGrp('genWt_geoVolWtCent_TFB', numberOfFields=3, label='Volume Center', value1=0.0, value2=0.0, value3=0.0 ) geoVolWt_centB = mc.button( label='Get Point', c='glTools.ui.utils.setPointValue("'+volWt_centFFG+'")' ) - + mc.setParent('..') - + # ---------------------------------- # - Curve Proximity Weights Layout - # ---------------------------------- - + mc.setParent(genWt_tabLayout) - + # Layout curveWt_columnLayout = mc.columnLayout(dtg='curveProximity') - + # UI Elements genWt_curveWtCurveTFB = mc.textFieldButtonGrp('genWt_curveWtCurveTFB',l='Curve',bl='Select') mc.textFieldButtonGrp(genWt_curveWtCurveTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+genWt_curveWtCurveTFB+'")') - + mc.floatSliderGrp('genWt_curveWtMinDistFSG',label='Min Distance',f=True,minValue=0.0,maxValue=10.0,fieldMinValue=0.0,fieldMaxValue=1000000,value=0.0) mc.floatSliderGrp('genWt_curveWtMaxDistFSG',label='Max Distance',f=True,minValue=0.001,maxValue=10.0,fieldMinValue=0.001,fieldMaxValue=1000000,value=1.0) - + mc.setParent('..') - + # ------------------------------ # - Mesh Offset Weights Layout - # ------------------------------ - + mc.setParent(genWt_tabLayout) - + # Layout meshOffsetWt_columnLayout = mc.columnLayout(dtg='meshOffset') - + # UI Elements genWt_meshOffsetBaseTFB = mc.textFieldButtonGrp('genWt_meshOffsetBaseTFB',l='Base Mesh',bl='Select') mc.textFieldButtonGrp(genWt_meshOffsetBaseTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+genWt_meshOffsetBaseTFB+'")') - + genWt_meshOffsetTargetTFB = mc.textFieldButtonGrp('genWt_meshOffsetTargetTFB',l='Target Mesh',bl='Select') mc.textFieldButtonGrp(genWt_meshOffsetTargetTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+genWt_meshOffsetTargetTFB+'")') - + genWt_meshOffsetNormalizeCBG = mc.checkBoxGrp('genWt_meshOffsetNormalizeCBG',numberOfCheckBoxes=1,label='Normalize') genWt_meshOffsetNormalRayCBG = mc.checkBoxGrp('genWt_meshOffsetNormalRayCBG',numberOfCheckBoxes=1,label='Normal Ray Intersect') - + mc.setParent('..') - + # -------------- # - End Layout - # -------------- - + # Set TabLayout Labels mc.tabLayout(genWt_tabLayout,e=True,tabLabel=((gradWt_columnLayout,'Gradient'),(radWt_columnLayout,'Radial'),(volWt_columnLayout,'Volume'),(geoVolWt_columnLayout,'Geometry Volume'),(curveWt_columnLayout,'Curve Proximity'),(meshOffsetWt_columnLayout,'Mesh Offset')) ) - - # Display UI + + # Display UI mc.showWindow(win) mc.window(win,e=True,wh=[560,285]) - + def generateWeightsFromUI(): ''' ''' # Get source geometry geometry = mc.textFieldGrp('genWt_targetGeoTFG',q=True,tx=True) - + # Get smooth value smoothVal = mc.intSliderGrp('genWt_smoothWeightTFG',q=True,v=True) - + # ------------------------ # - Get Target Attribute - # ------------------------ - + targetAttr = mc.textFieldGrp('genWt_targetAttrTFG',q=True,tx=True) - + # Check target attr if not targetAttr: raise Exception('No target attribute specified!') if not mc.objExists(targetAttr): raise Exception('Attribute "'+targetAttr+'" does not exist!') - + # Determine target attribute type targetNode = targetAttr.split('.')[0] targetType = mc.objectType(targetNode) - #attrIsMulti = mc.attributeQuery('') - + #attrIsMulti = mc.attributeQuery('') + # -------------------- # - Generate Weights - # -------------------- - + wt = [] - + # Determine weight generation type selLayout = mc.tabLayout('genWt_tabLayout',q=True,st=True) layoutTag = mc.columnLayout(selLayout,q=True,dtg=True) - + if layoutTag == 'gradient': - + # Gradient pnt1 = mc.textFieldButtonGrp('genWt_gradWtPt1_TFB',q=True,tx=True) pnt2 = mc.textFieldButtonGrp('genWt_gradWtPt2_TFB',q=True,tx=True) wt = glTools.tools.generateWeights.gradientWeights(geometry,pnt1,pnt2,smoothVal) - + elif layoutTag == 'radial': - + # Radial radius = mc.floatSliderGrp('genWt_radWtRadiusFSG',q=True,v=True) inRadius = mc.floatSliderGrp('genWt_radWtInRadiusFSG',q=True,v=True) @@ -221,9 +221,9 @@ def generateWeightsFromUI(): mc.floatFieldGrp('genWt_radWtCent_TFB',q=True,v2=True), mc.floatFieldGrp('genWt_radWtCent_TFB',q=True,v3=True) ) wt = glTools.tools.generateWeights.radialWeights(geometry,center,radius,inRadius,smoothVal) - + elif layoutTag == 'volume': - + # Volume volBoundary = mc.textFieldButtonGrp('genWt_volBoundaryTFB',q=True,tx=True) volInterior = mc.textFieldButtonGrp('genWt_volInteriorTFB',q=True,tx=True) @@ -231,9 +231,9 @@ def generateWeightsFromUI(): mc.floatFieldGrp('genWt_volWtCent_TFB',q=True,v2=True), mc.floatFieldGrp('genWt_volWtCent_TFB',q=True,v3=True) ) wt = glTools.tools.generateWeights.volumeWeights(geometry,volCenter,volBoundary,volInterior,smoothVal) - + elif layoutTag == 'geometryVolume': - + # Geometry Volume geoBoundary = mc.textFieldButtonGrp('genWt_geoBoundaryTFB',q=True,tx=True) geoInterior = mc.textFieldButtonGrp('genWt_geoInteriorTFB',q=True,tx=True) @@ -241,26 +241,26 @@ def generateWeightsFromUI(): mc.floatFieldGrp('genWt_geoVolWtCent_TFB',q=True,v2=True), mc.floatFieldGrp('genWt_geoVolWtCent_TFB',q=True,v3=True) ) wt = glTools.tools.generateWeights.geometryVolumeWeights(geometry,geoCenter,geoBoundary,geoInterior,smoothVal) - + elif layoutTag == 'curveProximity': - + # Curve Proximity proximityCurve = mc.textFieldButtonGrp('genWt_curveWtCurveTFB',q=Tru,tx=True) minDist = mc.floatSliderGrp('genWt_curveWtMinDistFSG',q=True,v=True) maxDist = mc.floatSliderGrp('genWt_curveWtMaxDistFSG',q=True,v=True) wt = glTools.tools.generateWeights.curveProximityWeights(geometry,proximityCurve,minDist,maxDist,smoothVal) - + elif layoutTag == 'meshOffset': - + # Mesh Offset meshBase = mc.textFieldButtonGrp('genWt_meshOffsetBaseTFB',q=True,tx=True) meshTarget = mc.textFieldButtonGrp('genWt_meshOffsetTargetTFB',q=True,tx=True) normalize = mc.checkBoxGrp('genWt_meshOffsetNormalizeCBG',q=True,v1=True) useNormal = mc.checkBoxGrp('genWt_meshOffsetNormalRayCBG',q=True,v1=True) wt = glTools.tools.generateWeights.meshOffsetWeights(meshBase,meshTarget,normalize,useNormal,smoothVal) - + # ----------------------- # - Set Attribute Value - # ----------------------- - - + + diff --git a/ui/ik.py b/ui/ik.py index 5452b63..f9bf69f 100644 --- a/ui/ik.py +++ b/ui/ik.py @@ -26,33 +26,33 @@ def ikHandleUI(): eJointTFB = mc.textFieldButtonGrp('ikHandleEndJointTFB',label='End Joint',text='',buttonLabel='Load Selected') # Prefix prefixTFG = mc.textFieldGrp('ikHandlePrefixTFG',label='Prefix', text='') - + # IK Solver solverList = ['ikSplineSolver','ikSCsolver','ikRPsolver','ik2Bsolver'] solverOMG = mc.optionMenuGrp('ikHandleSolverOMG',label='IK Solver') for solver in solverList: mc.menuItem(label=solver) mc.optionMenuGrp(solverOMG,e=True,sl=3) - + # Spline IK splineFrameL = mc.frameLayout('ikHandleSplineFL',l='Spline IK Options',cll=0,en=0) splineFormL = mc.formLayout(numberOfDivisions=100) # Curve curveTFB = mc.textFieldButtonGrp('ikHandleCurveTFB',label='Curve',text='',buttonLabel='Load Selected',en=0) offsetFSG = mc.floatSliderGrp('ikHandleOffsetFSG',label='Offset',field=True,minValue=0.0,maxValue=1.0,fieldMinValue=0.0,fieldMaxValue=1.0,value=0,en=0) - + mc.setParent('..') mc.setParent('..') - + # Buttons createB = mc.button('ikHandleCreateB',l='Create',c='glTools.ui.ik.ikHandleFromUI(False)') cancelB = mc.button('ikHandleCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # UI callback commands mc.optionMenuGrp(solverOMG,e=True,cc='mc.frameLayout("'+splineFrameL+'",e=True,en=not(mc.optionMenuGrp("'+solverOMG+'",q=True,sl=True)-1))') mc.textFieldButtonGrp(sJointTFB,e=True,bc='glTools.ui.ik.ikHandleUI_autoComplete("'+sJointTFB+'","'+eJointTFB+'","'+prefixTFG+'")') mc.textFieldButtonGrp(eJointTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+eJointTFB+'",selType="joint")') mc.textFieldButtonGrp(curveTFB,e=True,bc='glTools.ui.utils.loadCurveSel("'+curveTFB+'")') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(sJointTFB,'top',5),(sJointTFB,'left',5),(sJointTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(eJointTFB,'top',5,sJointTFB)]) @@ -67,12 +67,12 @@ def ikHandleUI(): mc.formLayout(FL,e=True,af=[(createB,'left',5),(createB,'right',5)]) mc.formLayout(FL,e=True,ac=[(createB,'bottom',5,cancelB)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Form Layout - Spline mc.formLayout(splineFormL,e=True,af=[(curveTFB,'top',5),(curveTFB,'left',5),(curveTFB,'right',5)]) mc.formLayout(splineFormL,e=True,ac=[(offsetFSG,'top',5,curveTFB)]) mc.formLayout(splineFormL,e=True,af=[(offsetFSG,'left',5),(offsetFSG,'right',5)]) - + # Show Window mc.showWindow(window) @@ -81,7 +81,7 @@ def ikHandleUI_autoComplete(sJointTFB,eJointTFB,prefixTFG): ''' # Load selection to UI field glTools.ui.utils.loadTypeSel(sJointTFB,prefixTFG,selType="joint") - + # Get start joint and determine end joint sJoint = mc.textFieldButtonGrp(sJointTFB,q=True,text=True) sJointChain = mc.listRelatives(sJoint,ad=True) @@ -89,7 +89,7 @@ def ikHandleUI_autoComplete(sJointTFB,eJointTFB,prefixTFG): eJointList = mc.ls(sJointChain,type='joint') if not eJointList: return eJoint = str(eJointList[0]) - + # Set End joint field value mc.textFieldButtonGrp(eJointTFB,e=True,text=eJoint) @@ -100,7 +100,7 @@ def ikHandleFromUI(close=False): # Window window = 'ikHandleUI' if not mc.window(window,q=True,ex=1): raise UIError('IkHandle UI does not exist!!') - + # Get UI data startJ = mc.textFieldButtonGrp('ikHandleStartJointTFB',q=True,text=True) endJ = mc.textFieldButtonGrp('ikHandleEndJointTFB',q=True,text=True) @@ -108,10 +108,10 @@ def ikHandleFromUI(close=False): solver = mc.optionMenuGrp('ikHandleSolverOMG',q=True,v=True) curve = mc.textFieldButtonGrp('ikHandleCurveTFB',q=True,text=True) offset = mc.floatSliderGrp('ikHandleOffsetFSG',q=True,v=True) - + # Execute command glTools.tools.ikHandle.build(startJoint=startJ,endJoint=endJ,solver=solver,curve=curve,ikSplineOffset=offset,prefix=pre) - + # Cleanup if close: mc.deleteUI(window) @@ -145,19 +145,19 @@ def stretchyIkChainUI(): # Blend blendCtrlTFB = mc.textFieldButtonGrp('stretchyIkChainBlendCtrlTFB',label='Blend Control',text='',buttonLabel='Load Selected') blendAttrTFG = mc.textFieldGrp('stretchyIkChainBlendAttrTFB',label='Blend Attribute',text='stretchScale') - + # Separator SEP = mc.separator(height=10,style='single') - + # Buttons createB = mc.button('stretchyIkChainCreateB',l='Create',c='glTools.ui.ik.stretchyIkChainFromUI(False)') cancelB = mc.button('stretchyIkChainCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # UI callback commands mc.textFieldButtonGrp(handleTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+handleTFB+'","'+prefixTFG+'",selType="ikHandle")') mc.textFieldButtonGrp(blendCtrlTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+blendCtrlTFB+'")') mc.textFieldButtonGrp(scaleAttrTFB,e=True,bc='glTools.ui.utils.loadChannelBoxSel("'+scaleAttrTFB+'")') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(handleTFB,'top',5),(handleTFB,'left',5),(handleTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(prefixTFG,'top',5,handleTFB)]) @@ -180,7 +180,7 @@ def stretchyIkChainUI(): mc.formLayout(FL,e=True,ac=[(cancelB,'top',5,SEP)]) mc.formLayout(FL,e=True,af=[(cancelB,'right',5),(cancelB,'bottom',5)]) mc.formLayout(FL,e=True,ap=[(cancelB,'left',5,50)]) - + # Show Window mc.showWindow(window) @@ -191,7 +191,7 @@ def stretchyIkChainFromUI(close=False): # Window window = 'stretchyIkChainUI' if not mc.window(window,q=True,ex=1): raise UIError('StretchyIkChain UI does not exist!!') - + # Get UI data ik = mc.textFieldButtonGrp('stretchyIkChainTFB',q=True,text=True) pre = mc.textFieldGrp('stretchyIkChainPrefixTFG',q=True,text=True) @@ -200,10 +200,10 @@ def stretchyIkChainFromUI(close=False): scaleAttr = mc.textFieldButtonGrp('stretchyIkChainScaleAttrTFB',q=True,text=True) blendCtrl = mc.textFieldButtonGrp('stretchyIkChainBlendCtrlTFB',q=True,text=True) blendAttr = mc.textFieldGrp('stretchyIkChainBlendAttrTFB',q=True,text=True) - + # Execute command glTools.tools.stretchyIkChain.build(ikHandle=ik,scaleAttr=scaleAttr,scaleAxis=scaleAxis,blendControl=blendCtrl,blendAttr=blendAttr,shrink=shrink,prefix=pre) - + # Cleanup if close: mc.deleteUI(window) @@ -232,19 +232,19 @@ def stretchyIkLimbUI(): mc.optionMenuGrp(scaleAxisOMG,e=True,sl=1) # Scale Attr scaleAttrTFB = mc.textFieldButtonGrp('stretchyIkLimbScaleAttrTFB',label='Scale Attribute',text='',buttonLabel='Load Selected') - + # Separator SEP = mc.separator(height=10,style='single') - + # Buttons createB = mc.button('stretchyIkLimbCreateB',l='Create',c='glTools.ui.ik.stretchyIkLimbFromUI(False)') cancelB = mc.button('stretchyIkLimbCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # UI callback commands mc.textFieldButtonGrp(handleTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+handleTFB+'","'+prefixTFG+'",selType="ikHandle")') mc.textFieldButtonGrp(controlTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+controlTFB+'")') mc.textFieldButtonGrp(scaleAttrTFB,e=True,bc='glTools.ui.utils.loadChannelBoxSel("'+scaleAttrTFB+'")') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(handleTFB,'top',5),(handleTFB,'left',5),(handleTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(prefixTFG,'top',5,handleTFB)]) @@ -263,7 +263,7 @@ def stretchyIkLimbUI(): mc.formLayout(FL,e=True,ac=[(cancelB,'top',5,SEP)]) mc.formLayout(FL,e=True,af=[(cancelB,'right',5),(cancelB,'bottom',5)]) mc.formLayout(FL,e=True,ap=[(cancelB,'left',5,50)]) - + # Show Window mc.showWindow(window) @@ -274,17 +274,17 @@ def stretchyIkLimbFromUI(close=False): # Window window = 'stretchyIkLimbUI' if not mc.window(window,q=True,ex=1): raise UIError('StretchyIkChain UI does not exist!!') - + # Get UI data ik = mc.textFieldButtonGrp('stretchyIkLimbTFB',q=True,text=True) pre = mc.textFieldGrp('stretchyIkLimbPrefixTFG',q=True,text=True) ctrl = mc.textFieldButtonGrp('stretchyIkLimbControlTFB',q=True,text=True) scaleAxis = str.lower(str(mc.optionMenuGrp('stretchyIkLimbAxisOMG',q=True,v=True))) scaleAttr = mc.textFieldButtonGrp('stretchyIkLimbScaleAttrTFB',q=True,text=True) - + # Execute command glTools.tools.stretchyIkLimb.StretchyIkLimb().build(ikHandle=ik,control=ctrl,scaleAttr=scaleAttr,scaleAxis=scaleAxis,prefix=pre) - + # Cleanup if close: mc.deleteUI(window) @@ -314,35 +314,35 @@ def stretchyIkSplineUI(): # Blend blendCtrlTFB = mc.textFieldButtonGrp('stretchyIkSplineBlendCtrlTFB',label='Blend Control',text='',buttonLabel='Load Selected') blendAttrTFG = mc.textFieldGrp('stretchyIkSplineBlendAttrTFG',label='Blend Attribute',text='stretchScale') - + # Stretch Method methodList = ['Arc Length','Parametric'] methodOMG = mc.optionMenuGrp('stretchyIkSplineMethodOMG',label='Stretch Method') for method in methodList: mc.menuItem(label=method) mc.optionMenuGrp(methodOMG,e=True,sl=2) - + # Parametric Layout paramFrameL = mc.frameLayout('stretchyIkSplineParamFL',l='Parametric Bounds',cll=0) paramFormL = mc.formLayout(numberOfDivisions=100) - + # Min/Max Percent minPercentFSG = mc.floatSliderGrp('stretchyIkSplineMinPFSG',label='Min Percent',field=True,minValue=0.0,maxValue=1.0,fieldMinValue=0.0,fieldMaxValue=1.0,value=0.0) maxPercentFSG = mc.floatSliderGrp('stretchyIkSplineMaxPFSG',label='Max Percent',field=True,minValue=0.0,maxValue=1.0,fieldMinValue=0.0,fieldMaxValue=1.0,value=1.0) closestPointCBG = mc.checkBoxGrp('stretchyIkSplineClosestPointCBG',l='Use Closest Point',ncb=1,v1=True) - + mc.setParent('..') mc.setParent('..') - + # Buttons createB = mc.button('stretchyIkSplineCreateB',l='Create',c='glTools.ui.ik.stretchyIkSplineFromUI(False)') cancelB = mc.button('stretchyIkSplineCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # UI callback commands mc.textFieldButtonGrp(handleTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+handleTFB+'","'+prefixTFG+'",selType="ikHandle")') mc.textFieldButtonGrp(scaleAttrTFB,e=True,bc='glTools.ui.utils.loadChannelBoxSel("'+scaleAttrTFB+'")') mc.textFieldButtonGrp(blendCtrlTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+blendCtrlTFB+'")') mc.optionMenuGrp(methodOMG,e=True,cc='mc.frameLayout("'+paramFrameL+'",e=True,en=mc.optionMenuGrp("'+methodOMG+'",q=True,sl=True)-1)') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(handleTFB,'top',5),(handleTFB,'left',5),(handleTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(prefixTFG,'top',5,handleTFB)]) @@ -363,14 +363,14 @@ def stretchyIkSplineUI(): mc.formLayout(FL,e=True,ap=[(createB,'right',5,50)]) mc.formLayout(FL,e=True,af=[(cancelB,'right',5),(cancelB,'bottom',5)]) mc.formLayout(FL,e=True,ap=[(cancelB,'left',5,50)]) - + # Form Layout - Parametric mc.formLayout(paramFormL,e=True,af=[(minPercentFSG,'top',5),(minPercentFSG,'left',5),(minPercentFSG,'right',5)]) mc.formLayout(paramFormL,e=True,ac=[(maxPercentFSG,'top',5,minPercentFSG)]) mc.formLayout(paramFormL,e=True,af=[(maxPercentFSG,'left',5),(maxPercentFSG,'right',5)]) mc.formLayout(paramFormL,e=True,ac=[(closestPointCBG,'top',5,maxPercentFSG)]) mc.formLayout(paramFormL,e=True,af=[(closestPointCBG,'left',5),(closestPointCBG,'right',5)]) - + # Show Window mc.showWindow(window) @@ -380,7 +380,7 @@ def stretchyIkSplineFromUI(close=False): # Window window = 'stretchyIkSplineUI' if not mc.window(window,q=True,ex=1): raise UIError('StretchyIkSpline UI does not exist!!') - + # Get UI data ik = mc.textFieldButtonGrp('stretchyIkSplineTFB',q=True,text=True) pre = mc.textFieldGrp('stretchyIkSplinePrefixTFG',q=True,text=True) @@ -392,7 +392,7 @@ def stretchyIkSplineFromUI(close=False): method = mc.optionMenuGrp('stretchyIkSplineMethodOMG',q=True,sl=True)-1 minPercent = mc.floatSliderGrp('stretchyIkSplineMinPFSG',q=True,v=True) maxPercent = mc.floatSliderGrp('stretchyIkSplineMaxPFSG',q=True,v=True) - + # Execute command if method: # Parametric glTools.tools.stretchyIkSpline.stretchyIkSpline_parametric( ikHandle=ik, @@ -411,6 +411,6 @@ def stretchyIkSplineFromUI(close=False): blendControl=blendCtrl, blendAttr=blendAttr, prefix=pre) - + # Cleanup if close: mc.deleteUI(window) diff --git a/ui/joint.py b/ui/joint.py index 8e731fb..e6ab07b 100644 --- a/ui/joint.py +++ b/ui/joint.py @@ -15,7 +15,7 @@ def jointOrientUI(): window = 'jointOrientUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Joint Orient Tool') - + # UI Elements #--- width = 272 @@ -24,51 +24,51 @@ def jointOrientUI(): cw2 = 60 cw3 = 60 cw4 = 50 - + # Layout CL = mc.columnLayout(w=width,adj=True) - + # Aim Method aimRBG = mc.radioButtonGrp('jointOrientAimRBG',nrb=3,l='Aim Method',la3=['Axis','Object','Cross'],sl=1,cc='glTools.ui.joint.jointOrientRefreshUI_aimMethod()',cw=[(1,cw1),(2,cw2),(3,cw3)]) - + # Aim Axis Direction Layout axisFL = mc.frameLayout('jointOrientAxisFL',l='Orientation Axis',w=(width-8),h=90,cll=0) axisCL = mc.columnLayout(adj=True) - + primAxisPosRBG = mc.radioButtonGrp('jointOrientPrimAxisRBG',nrb=3,l='Primary Axis',la3=['X','Y','Z'],sl=1,cc='glTools.ui.joint.jointOrientRefreshUI_aimAxis()',cw=[(1,cw1),(2,cw2),(3,cw3),(4,cw4)]) primAxisNegRBG = mc.radioButtonGrp('jointOrientPrimAxisNegRBG',nrb=3,scl=primAxisPosRBG,l='',la3=['-X','-Y','-Z'],cc='glTools.ui.joint.jointOrientRefreshUI_aimAxis()',cw=[(1,cw1),(2,cw2),(3,cw3),(4,cw4)]) aimAxisRBG = mc.radioButtonGrp('jointOrientAimAxisRBG',nrb=2,l='Aim Axis',la2=['Y','Z'],sl=1,cw=[(1,cw1),(2,cw2)]) - + mc.setParent('..') mc.setParent('..') - + # Aim Axis Direction Layout aimAxisFL = mc.frameLayout('jointOrientAimAxisFL',l='Orientation Aim Axis',w=(width-8),h=70,cll=0) aimAxisCL = mc.columnLayout(adj=True) - + oriAxisPosRBG = mc.radioButtonGrp('jointOrientOriAxisPosRBG',nrb=3,l='Aim Direction',la3=['+X','+Y','+Z'],sl=1,cw=[(1,cw1),(2,cw2),(3,cw3),(4,cw4)]) oriAxisNegRBG = mc.radioButtonGrp('jointOrientOriAxisNegRBG',nrb=3,scl=oriAxisPosRBG,l='',la3=['-X','-Y','-Z'],cw=[(1,cw1),(2,cw2),(3,cw3),(4,cw4)]) - + mc.setParent('..') mc.setParent('..') - + # Aim Object Layout aimObjFL = mc.frameLayout('jointOrientAimObjFL',l='Aim Object',w=(width-8),h=55,cll=0) aimObjCL = mc.columnLayout(adj=True) aimObjCreateB = mc.button(l='Create Aim Object',w=(width-12),c='glTools.ui.joint.jointOrientCreateControl()') - + mc.setParent('..') mc.setParent('..') - + # Cross Product Layout crossProdFL = mc.frameLayout('jointOrientCrossProdFL',l='Cross Product',w=(width-8),h=70,cll=0) crossProdCL = mc.columnLayout(adj=True) crossProdCBG = mc.checkBoxGrp('jointOrientCrossProdCBG',l='Invert Result',ncb=1,cw=[(1,cw1),(2,cw2)]) crossProdRBG = mc.radioButtonGrp('jointOrientCrossProdRBG',l='Joint As',nrb=3,la3=['Base','Apex','Tip'],sl=2,cw=[(1,cw1),(2,cw2),(3,cw3),(4,cw4)]) - + mc.setParent('..') mc.setParent('..') - + # Rotate Joint Orientation #rotJointOriFL = mc.frameLayout('jointOrientRotOriFL',l='Rotate Joint Orientation',w=(width-8),h=55,cll=0) rotJointOriFL = mc.frameLayout('jointOrientRotOriFL',l='Rotate Joint Orientation',cll=0) @@ -85,22 +85,22 @@ def jointOrientUI(): mc.button(w=80,l='+90',c='glTools.ui.joint.jointOrientRotateOrient(90,0,0)') mc.button(w=80,l='+90',c='glTools.ui.joint.jointOrientRotateOrient(0,90,0)') mc.button(w=80,l='+90',c='glTools.ui.joint.jointOrientRotateOrient(0,0,90)') - + mc.setParent('..') mc.setParent('..') - + # Toggle Axis View mc.button(l='Toggle Local Axis Display',w=(width-8),c='mc.toggle(localAxis=True)') # Orient Joint mc.button(l='Orient Joint',w=(width-8),c='glTools.ui.joint.jointOrientFromUI()') # Close UI mc.button(l='Close',c='mc.deleteUI("'+window+'")') - + # Prepare Window mc.window(window,e=True,w=width,h=height) mc.frameLayout(aimObjFL,e=True,en=False) mc.frameLayout(crossProdFL,e=True,en=False) - + # Show Window mc.showWindow(window) @@ -111,34 +111,34 @@ def jointOrientFromUI(close=False): # Window window = 'jointOrientUI' if not mc.window(window,q=True,ex=1): raise UIError('JointOrient UI does not exist!!') - + # Build Axis List axisList = ['x','y','z','-x','-y','-z'] - + # Build UpAxis List upAxisList = [('y','z'),('x','z'),('x','y')] - + # Build Axis Dictionary axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # Get joint selection jntList = mc.ls(sl=True,type='joint') if not jntList: return - + # Aim Method aimMethod = mc.radioButtonGrp('jointOrientAimRBG',q=True,sl=True) - + # Get Axis Selection aimAx = mc.radioButtonGrp('jointOrientPrimAxisRBG',q=True,sl=True) upAx = mc.radioButtonGrp('jointOrientAimAxisRBG',q=True,sl=True) # Build Axis Values aimAxis = axisList[aimAx-1] upAxis = upAxisList[aimAx-1][upAx-1] - + # Axis upVector = (0,1,0) if aimMethod == 1: - + # Check joint selection if not jntList: raise UserInputError('Invalid joint selection!!') # Get UpVector Selection @@ -146,14 +146,14 @@ def jointOrientFromUI(close=False): if not upVec: upVec = mc.radioButtonGrp('jointOrientOriAxisNegRBG',q=True,sl=True) + 3 # Build UpAxis Value upVector = axisDict[axisList[upVec-1]] - + # Execute Command for jnt in jntList: glTools.utils.joint.orient(jnt,aimAxis=aimAxis,upAxis=upAxis,upVec=upVector) - + # Object elif aimMethod == 2: - + # Check for orient control selection cccList = mc.ls('*_ori01_orientControl',sl=True) for ccc in cccList: @@ -161,7 +161,7 @@ def jointOrientFromUI(close=False): cJnt = mc.listConnections(ccc+'.joint',s=True,d=False,type='joint') if not cJnt: continue if not jntList.count(cJnt[0]): jntList.append(cJnt[0]) - + # Determine orient control for jnt in jntList: prefix = glTools.utils.stringUtils.stripSuffix(jnt) @@ -175,24 +175,24 @@ def jointOrientFromUI(close=False): jPos = mc.xform(jnt,q=True,ws=True,rp=True) upPos = mc.xform(upLoc,q=True,ws=True,rp=True) upVector = glTools.utils.mathUtils.offsetVector(upPos,jPos) - + # Execute Command glTools.utils.joint.orient(jnt,aimAxis=aimAxis,upAxis=upAxis,upVec=upVector) - + # Delete orient control mc.delete(ctrlGrp) - + # Cross elif aimMethod == 3: - + # Invert invert = mc.checkBoxGrp('jointOrientCrossProdCBG',q=True,v1=True) # Joint As jointAs = mc.radioButtonGrp('jointOrientCrossProdRBG',q=True,sl=True) - + # Get Cross vector for jnt in jntList: - + # Check for child joint if not mc.listRelatives(jnt,c=True): glTools.utils.joint.orient(jnt) @@ -221,7 +221,7 @@ def jointOrientFromUI(close=False): bJnt = mc.listRelatives(aJnt,p=True,pa=True,type='joint') if not bJnt: raise UserInputError('Insufficient joint connectivity to determine base from apex "'+aJnt+'"!!') bJnt = bJnt[0] - + # Get joint positions bPos = mc.xform(bJnt,q=True,ws=True,rp=True) aPos = mc.xform(aJnt,q=True,ws=True,rp=True) @@ -232,13 +232,13 @@ def jointOrientFromUI(close=False): cross = glTools.utils.mathUtils.crossProduct(vec1,vec2) # Invert if invert: cross = (-cross[0],-cross[1],-cross[2]) - + # Execute Command glTools.utils.joint.orient(jnt,aimAxis=aimAxis,upAxis=upAxis,upVec=cross) - + # Select Joint Children mc.select(mc.listRelatives(jntList,c=True,type='joint')) - + # Cleanup if close: mc.deleteUI(window) @@ -287,7 +287,7 @@ def jointOrientCreateControl(): window = 'jointOrientUI' upAxis = (0,1,0) if mc.window(window,q=True,ex=1): - + # Build UpAxis List upAxisList = [((0,1,0),(0,0,1)),((1,0,0),(0,0,1)),((1,0,0),(0,1,0))] # Get Axis Selection @@ -295,58 +295,58 @@ def jointOrientCreateControl(): upAx = mc.radioButtonGrp('jointOrientAimAxisRBG',q=True,sl=True) # Build Axis Values upAxis = upAxisList[aimAx-1][upAx-1] - + # Create control jntList = mc.ls(sl=True,type='joint') - ctrlList = [] + ctrlList = [] for jnt in jntList: - + # Get child joint cJnt = mc.listRelatives(jnt,c=True,pa=True) if not cJnt: continue - + # Generate control prefix prefix = glTools.utils.stringUtils.stripSuffix(jnt) - + # Check for existing orien control if mc.objExists(prefix+'_ori01_orientGrp'): print('Orient control already exists for joint "'+jnt+'"!!') continue - + # Create orient control circle = mc.circle(c=(0,0,0),nr=(0,1,0),sw=360,r=1,d=3,ut=0,tol=0.01,s=8,ch=1,n=prefix+'_ori01_orientControl') for ch in ['tx','ty','tz','rx','rz','sx','sy','sz']: mc.setAttr(circle[0]+'.'+ch,l=True,k=False) - + # Create orient UP locator upLoc = mc.spaceLocator(n=prefix+'_up01_orientLoc') mc.parent(upLoc[0],circle[0]) mc.setAttr(upLoc[0]+'.tz',1.0) mc.connectAttr(upLoc[0]+'.tz',circle[1]+'.radius',f=True) for ch in ['tx','ty','rx','ry','rz','sx','sy','sz']: mc.setAttr(upLoc[0]+'.'+ch,l=True,k=False) - + # Create orient control group ctrlGrp = mc.group(em=True,n=prefix+'_ori01_orientGrp') mc.parent(circle[0],ctrlGrp) - + # Position control group mc.delete(mc.pointConstraint(jnt,ctrlGrp)) mc.delete(mc.aimConstraint(cJnt[0],ctrlGrp,aimVector=(0,1,0),upVector=(0,0,1),wu=upAxis,wuo=jnt,wut='objectrotation')) - + # Scale control elements dist = glTools.utils.mathUtils.distanceBetween(mc.xform(jnt,q=True,ws=True,rp=True),mc.xform(cJnt[0],q=True,ws=True,rp=True)) mc.setAttr(upLoc[0]+'.tz',dist*0.5) - + # Lock orient control group mc.parent(ctrlGrp,jnt) for ch in ['tx','ty','tz','rx','ry','rz','sx','sy','sz']: mc.setAttr(ctrlGrp+'.'+ch,l=True,k=False) - + # Add message connection form joint to orient control mc.addAttr(circle[0],ln='joint',at='message') mc.connectAttr(jnt+'.message',circle[0]+'.joint',f=True) - + # Append control list ctrlList.append(circle[0]) - + # Select controls mc.select(ctrlList) diff --git a/ui/lidRails.py b/ui/lidRails.py index 374a342..b09d4ab 100644 --- a/ui/lidRails.py +++ b/ui/lidRails.py @@ -15,39 +15,39 @@ def lidSurfaceCreateUI(): win = 'lidSurfaceCreateUI' if mc.window(win,q=True,ex=True): mc.deleteUI(win) win = mc.window(win,t='Create LidSurface') - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # Curve List crvListTXT = mc.text(l='Curve List') crvListTSL = mc.textScrollList('lidSurface_crvListTSL',ams=True) crvListAddB = mc.button(l='Add',c='glTools.ui.utils.addToTSL("'+crvListTSL+'")') crvListRemB = mc.button(l='Remove',c='glTools.ui.utils.removeFromTSL("'+crvListTSL+'")') - + # Prefix prefixTFG = mc.textFieldGrp('lidSurface_prefixTFG',l='Prefix',tx='') # Side sideTFG = mc.textFieldGrp('lidSurface_sideTFG',l='Side',tx='lf') - + # Spans spansFSG = mc.intSliderGrp('lidSurface_spansFSG',label='Spans',field=True,minValue=2,maxValue=10,fieldMinValue=0,fieldMaxValue=100,value=4) - + # Attribute Object attrObjTFB = mc.textFieldButtonGrp('lidSurface_attrObjTFB',l='Attribute Object',bl='Load Sel') # Collision Object collObjTFB = mc.textFieldButtonGrp('lidSurface_collObjTFB',l='Collision Object',bl='Load Sel') - + # Create / Close createB = mc.button(l='Create',c='') closeB = mc.button(l='Close',c='mc.deleteUI("'+win+'")') - + # UI Callbacks mc.textScrollList(crvListTSL,e=True,dkc='glTools.ui.utils.removeFromTSL("'+crvListTSL+'")') mc.textFieldGrp(prefixTFG,e=True,cc='glTools.ui.lidSurface.lidSurfaceCreate_updateSide()') mc.textFieldButtonGrp(attrObjTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+attrObjTFB+'")') mc.textFieldButtonGrp(collObjTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+collObjTFB+'")') - + # FormLayout - MAIN mc.formLayout(FL,e=True,af=[(crvListTXT,'left',5),(crvListTXT,'top',5)],ap=[(crvListTXT,'right',5,30)]) mc.formLayout(FL,e=True,af=[(crvListRemB,'left',5),(crvListRemB,'bottom',5)],ap=[(crvListRemB,'right',5,30)]) @@ -60,7 +60,7 @@ def lidSurfaceCreateUI(): mc.formLayout(FL,e=True,af=[(collObjTFB,'right',5)],ap=[(collObjTFB,'left',5,30)],ac=[(collObjTFB,'top',5,attrObjTFB)]) mc.formLayout(FL,e=True,af=[(closeB,'right',5),(closeB,'bottom',5)],ap=[(closeB,'left',5,30)]) mc.formLayout(FL,e=True,af=[(createB,'right',5)],ap=[(createB,'left',5,30)],ac=[(createB,'bottom',5,closeB)]) - + # Show Window mc.showWindow(win) @@ -70,7 +70,7 @@ def lidSurfaceCreateFromUI(): # Check window win = 'lidSurfaceCreateUI' if mc.window(win,q=True,ex=True): raise UIError('LidSurface Create UI does not exist!') - + # Get UI values crvList = mc.textScrollList('lidSurface_crvListTSL',q=True,ai=True) spans = mc.intSliderGrp('lidSurface_spansFSG',q=True,v=True) @@ -78,7 +78,7 @@ def lidSurfaceCreateFromUI(): collObj = mc.textFieldButtonGrp('lidSurface_collObjTFB',q=True,tx=True) side = mc.textFieldGrp('lidSurface_sideTFG',q=True,tx=True) prefix = mc.textFieldGrp('lidSurface_prefixTFG',q=True,tx=True) - + # Execute command glTools.utils.lidSurface.lidSurface_create(curveList=crvList,spans=spans,attributeObject=attrObj,collisionObject=collObj,side=side,prefix=prefix) diff --git a/ui/menu.py b/ui/menu.py index aebdab1..8d59b87 100644 --- a/ui/menu.py +++ b/ui/menu.py @@ -8,47 +8,47 @@ def create(): # This is a temporary hack to get maya to evaluate $gMainWindow gMainWindow = mm.eval('string $temp = $gMainWindow') if mc.menu('rigToolsMenu',q=True,ex=True): mc.deleteUI('rigToolsMenu') - + if (len(gMainWindow)): mc.setParent(gMainWindow) mc.menu('rigToolsMenu', label='Rig Tools', tearOff=True, allowOptionBoxes=True) - + #----------------------------------------# - + # > CHECKS mc.menuItem(label='Checks', subMenu=True, tearOff=True) - + mc.menuItem(label='Run Checks', command='import glTools.spotcheck.runChecks;reload(glTools.spotcheck.runChecks);glTools.spotcheck.runChecks.run(envKey="IKA_RIG_SPOTCHECKS",checkTitle="Rig Checks",selectedNodes=False)') mc.menuItem(label='Run Checks On Selected', command='import glTools.spotcheck.runChecks;reload(glTools.spotcheck.runChecks);glTools.spotcheck.runChecks.run(envKey="IKA_RIG_SPOTCHECKS",checkTitle="Rig Checks",selectedNodes=True)') mc.menuItem(divider=True) mc.menuItem(label='Check NonReference Geo Inputs', command='import glTools.tools.fixNonReferenceInputShape;reload(glTools.tools.fixNonReferenceInputShape);glTools.tools.fixNonReferenceInputShape.checkNonReferenceInputShapes(mc.ls(sl=1)[0],verbose=True)') - + mc.setParent('..', menu=True) - + #----------------------------------------# - + # > FIXES mc.menuItem(label='Fixes', subMenu=True, tearOff=True) - + mc.menuItem(label='Fix NonReference Geo Inputs', command='import glTools.tools.fixNonReferenceInputShape;reload(glTools.tools.fixNonReferenceInputShape);glTools.tools.fixNonReferenceInputShape.fixNonReferenceInputShapes(mc.ls(sl=1)[0],verbose=True)') - + mc.setParent('..', menu=True) - + # > MENU - + mc.menuItem(label='Menu', subMenu=True, tearOff=True) - + mc.menuItem(label='Create Surface Skin Menu', command='import glTools.surfaceSkin; glTools.surfaceSkin.SurfaceSkinUI().menu()') - + mc.setParent('..', menu=True) - + #----------------------------------------# - + mc.menuItem(divider=True) - + # > GENERAL mc.menuItem(allowOptionBoxes=True, label='General', subMenu=True, tearOff=True) - + mc.menuItem(label='Renamer', command='mm.eval("renamer")',ann='Open Renamer UI') mc.menuItem(label='Colorize UI', command='mm.eval("colorize")',ann='Open Colorizer UI') mc.menuItem(label='Set Colour', command='import glTools.utils.colorize;reload(glTools.utils.colorize);[glTools.utils.colorize.setColour(i) for i in mc.ls(sl=1)]',ann='Set colours based on object naming') @@ -67,90 +67,90 @@ def create(): mc.menuItem(label='Attribute Presets', command='glTools.ui.attrPreset.ui()',ann='Open attribute presets UI') mc.menuItem(label='Swap Nodes', command='import glTools.utils.connection;reload(glTools.utils.connection);glTools.utils.connection.swap(mc.ls(sl=1)[0],mc.ls(sl=1)[1])',ann='Swap Node Connections') mc.menuItem(label='Delete Unknown Nodes',command='import glTools.utils.cleanup;reload(glTools.utils.cleanup);glTools.utils.cleanup.deleteUnknownNodes()',ann='Delete all "unknown" nodes') - + mc.menuItem(label='Match Transform', command='import glTools.utils.transform;reload(glTools.utils.transform);sel=mc.ls(sl=1);glTools.utils.transform.match(sel[0],sel[1])',ann='Match first selected transform to second selected transform') mc.menuItem(label='Match Bounding Box', command='import glTools.utils.boundingBox;reload(glTools.utils.boundingBox);sel=mc.ls(sl=1);glTools.utils.boundingBox.match(sel[0],sel[1])',ann='Match first selected transform to second selected transform based on bounding box comparison') #mc.menuItem(label='Match Position', command='import glTools.utils.transform;reload(glTools.utils.transform);sel=mc.ls(sl=1);glTools.utils.transform.match(sel[0],sel[1])',ann='Match first selected object position to second selected object') #mc.menuItem(label='Match Orientation', command='import glTools.utils.transform;reload(glTools.utils.transform);sel=mc.ls(sl=1);glTools.utils.transform.match(sel[0],sel[1])',ann='Match first selected object orientation/rotation to second selected object') #mc.menuItem(label='Match Scale', command='import glTools.utils.transform;reload(glTools.utils.transform);sel=mc.ls(sl=1);glTools.utils.transform.match(sel[0],sel[1])',ann='Match first selected object scale to second selected object') - + # >> MATCH ATTRIBUTES mc.menuItem(allowOptionBoxes=True, label='Match Attrs', subMenu=True, tearOff=True) - + mc.menuItem(label='Match All', command='import glTools.tools.match;reload(glTools.tools.match);sel=mc.ls(sl=1);glTools.tools.match.matchAttrs(sel[0],sel[1],["tx","ty","tz","rx","ry","rz","sx","sy","sz"])',ann='Match all local transform values') mc.menuItem(label='Match Translate', command='import glTools.tools.match;reload(glTools.tools.match);sel=mc.ls(sl=1);glTools.tools.match.matchAttrs(sel[0],sel[1],["tx","ty","tz"])',ann='Match local translate values') mc.menuItem(label='Match Rotate', command='import glTools.tools.match;reload(glTools.tools.match);sel=mc.ls(sl=1);glTools.tools.match.matchAttrs(sel[0],sel[1],["rx","ry","rz"])',ann='Match local rotate values') mc.menuItem(label='Match Scale', command='import glTools.tools.match;reload(glTools.tools.match);sel=mc.ls(sl=1);glTools.tools.match.matchAttrs(sel[0],sel[1],["sx","sy","sz"])',ann='Match local scale values') mc.menuItem(label='Match From CB', command='import glTools.tools.match;reload(glTools.tools.match);sel=mc.ls(sl=1);glTools.tools.match.matchAttrs(sel[0],sel[1],"fromChannelBox")',ann='Match all values based on channel selection (channelBox)') - + mc.setParent('..', menu=True) - + mc.menuItem(label='Graph Profiler', command='import glTools.ui.qt.graphProfiler;reload(glTools.ui.qt.graphProfiler);glTools.ui.qt.graphProfiler.GraphProfiler().show()',ann='Tools to Collect and Display Dependency Graph Data') - + mc.setParent('..', menu=True) - + # > TOOLS mc.menuItem(allowOptionBoxes=True, label='Tools', subMenu=True, tearOff=True) - + mc.menuItem(label='Center Pt Locator', command='import glTools.tools.center;reload(glTools.tools.center);glTools.tools.center.centerPointLocator(mc.ls(sl=True,fl=True))',ann='Create locator at center of point selection.') mc.menuItem(label='Center to Geometry', command='import glTools.tools.center;reload(glTools.tools.center);sel = mc.ls(sl=True,fl=True);glTools.tools.center.centerToGeometry(sel[0],sel[1])',ann='Select the geometry and the object to position.') mc.menuItem(label='Center to Points', command='import glTools.tools.center;reload(glTools.tools.center);sel = mc.ls(sl=True,fl=True);glTools.tools.center.centerToPoints(sel[:-1],sel[-1])',ann='Select the points and the object to position.') mc.menuItem(label='Point Face Mesh', command='import glTools.tools.pointFaceMesh;reload(glTools.tools.pointFaceMesh);glTools.tools.pointFaceMesh.pointFaceMesh(mc.ls(sl=True,fl=True),combine=False)',ann='Create single mesh face at each point in selection.') - + mc.menuItem(label='Slide Deformer', command='import glTools.model.utils;reload(glTools.model.utils);[glTools.model.utils.slideDeformer(i) for i in mc.ls(sl=1)]') mc.menuItem(label='Strain Relaxer', command='import glTools.model.utils;reload(glTools.model.utils);[glTools.model.utils.strainRelaxer(i) for i in mc.ls(sl=1)]') mc.menuItem(label='Directional Smooth', command='import glTools.model.utils;reload(glTools.model.utils);[glTools.model.utils.directionalSmooth(i) for i in mc.ls(sl=1)]') mc.menuItem(label='Delta Mush', command='import glTools.model.utils;reload(glTools.model.utils);[glTools.model.utils.deltaMush(i) for i in mc.ls(sl=1)]') - + mc.setParent('..', menu=True) - + # > SELECTION mc.menuItem(allowOptionBoxes=True, label='Select', subMenu=True, tearOff=True) - + mc.menuItem(label='Select Hierarchy', command='mm.eval("SelectHierarchy")') - + mc.menuItem(allowOptionBoxes=True, label='Select All Below (by type)', subMenu=True, tearOff=True) mc.menuItem(label='constraint', command='mc.select(mc.ls(mc.listRelatives(ad=True,pa=True) or [],type="constraint"))') mc.menuItem(label='ikHandle', command='mc.select(mc.ls(mc.listRelatives(ad=True,pa=True) or [],type="ikHandle"))') mc.menuItem(label='joint', command='mc.select(mc.ls(mc.listRelatives(ad=True,pa=True) or [],type="joint"))') - + mc.setParent('..', menu=True) - + mc.menuItem(allowOptionBoxes=True, label='Select Directly Below (by type)', subMenu=True, tearOff=True) mc.menuItem(label='constraint', command='mc.select(mc.ls(mc.listRelatives(c=True,pa=True) or [],type="constraint"))') mc.menuItem(label='ikHandle', command='mc.select(mc.ls(mc.listRelatives(c=True,pa=True) or [],type="ikHandle"))') mc.menuItem(label='joint', command='mc.select(mc.ls(mc.listRelatives(c=True,pa=True) or [],type="joint"))') - + mc.setParent('..', menu=True) mc.menuItem(label='Mirror Polygon Selection', command='import glTools.utils.edgeFlowMirror;reload(glTools.utils.edgeFlowMirror);glTools.utils.edgeFlowMirror.mirrorSelection()') - + mc.setParent('..', menu=True) - + mc.setParent('..', menu=True) - + # > REFERENCE mc.menuItem(allowOptionBoxes=True, label='Reference', subMenu=True, tearOff=True) - + mc.menuItem(label='Reload Reference', command='import glTools.anim.reference_utils;reload(glTools.anim.reference_utils);glTools.anim.reference_utils.reloadSelected()') mc.menuItem(label='Unload Reference', command='import glTools.anim.reference_utils;reload(glTools.anim.reference_utils);glTools.anim.reference_utils.unloadSelected()') mc.menuItem(label='Remove Reference', command='import glTools.anim.reference_utils;reload(glTools.anim.reference_utils);glTools.anim.reference_utils.removeSelected(removeNS=False)') mc.menuItem(label='Remove Reference and NS', command='import glTools.anim.reference_utils;reload(glTools.anim.reference_utils);glTools.anim.reference_utils.removeSelected(removeNS=True)') mc.menuItem(label='Remove Unloaded References', command='import glTools.utils.reference;reload(glTools.utils.reference);glTools.utils.reference.removeUnloadedReferences()') mc.menuItem(label='Remove Reference Edits', command='import glTools.tools.removeReferenceEdits;reload(glTools.tools.removeReferenceEdits);glTools.tools.removeReferenceEdits.removeReferenceEditsUI()') - + mc.setParent('..', menu=True) - + # > SHADER mc.menuItem(allowOptionBoxes=True, label='Shader', subMenu=True, tearOff=True) - + mc.menuItem(label='Apply Reference Shader', command='import glTools.utils.shader;reload(glTools.utils.shader);[glTools.utils.shader.applyReferencedShader(i) for i in mc.ls(sl=1)]') mc.menuItem(label='Reconnect Shader', command='import glTools.utils.shader;reload(glTools.utils.shader);[glTools.utils.shader.reconnectShader(i) for i in mc.ls(sl=1)]') - + mc.setParent('..', menu=True) - + # > RIG mc.menuItem(allowOptionBoxes=True, label= 'Rig', subMenu=True, tearOff=True) - + #mc.menuItem(label='Create Base Rig', command='glTools.builder.BaseRig().build()') mc.menuItem(label='Rename Chain', command='import glTools.utils.base;reload(glTools.utils.base);glTools.utils.base.renameChain(mc.ls(sl=1,l=False)[0])',ann='Rename the selected joint hierarchy') mc.menuItem(label='Control Builder', command='glTools.ui.controlBuilder.controlBuilderUI()',ann='Open ControlBuilder UI') @@ -159,10 +159,10 @@ def create(): mc.menuItem(label='Replace Geometry', command='glTools.ui.replaceGeometry.replaceGeometryFromUI()', ann='First select the replacement geometry and then the geometry to be replaced.') mc.menuItem(label='Create Bind Joint Set', command='mc.sets(mc.ls("*.bindJoint",o=True),n="bindJoints")', ann='Create a bindJoints set for all tagged bind joints. ("*.bindJoint")') mc.menuItem(label='Clean Rig', command='import glTools.rig.cleanup;reload(glTools.rig.cleanup);glTools.rig.cleanup.clean()',ann='Clean Rig Workfile') - + # > > Flatten Scene mc.menuItem(allowOptionBoxes=True, label= 'Flatten Scene', subMenu=True, tearOff=True) - + mc.menuItem(label='Flatten Scene', command='import glTools.tools.flattenScene;reload(glTools.tools.flattenScene);glTools.tools.flattenScene.flatten()',ann='Flatten Scene - Import all references and delete all namespaces etc.') #----------------------------------------# mc.menuItem(divider =True) @@ -173,12 +173,12 @@ def create(): mc.menuItem(label='Add Delete History Attr', command='import glTools.tools.flattenScene;reload(glTools.tools.flattenScene);[glTools.tools.flattenScene.addDeleteHistoryAttr(i) for i in mc.ls(sl=True,dag=True)]',ann='Add "deleteHistoryOnFlatten" attribute based on current selection.') mc.menuItem(label='Add Reference Path Attr', command='import glTools.tools.flattenScene;reload(glTools.tools.flattenScene);[glTools.tools.flattenScene.addReferencePathAttr(i) for i in mc.ls(sl=True)]',ann='Add "fixNonReferenceInputsRoot" attribute based on current selection.') mc.menuItem(label='Add Fix NonReference Inputs Attr', command='import glTools.tools.flattenScene;reload(glTools.tools.flattenScene);[glTools.tools.flattenScene.addFixNonReferenceInputAttr(i) for i in mc.ls(sl=True)]',ann='Add "encodeReferenceFilePath" attribute based on current selection.') - + mc.setParent('..', menu=True) - + # > > Channel State mc.menuItem(allowOptionBoxes=True, label= 'Channel State', subMenu=True, tearOff=True) - + mc.menuItem(label='Channel State', command='import glTools.utils.channelState; reload(glTools.utils.channelState); glTools.utils.channelState.ChannelState().ui()',ann='Open ChannelState UI') mc.menuItem(divider=True) mc.menuItem(label='Record Visibility State', command='import glTools.utils.defaultAttrState;reload(glTools.utils.defaultAttrState);glTools.utils.defaultAttrState.recordVisibility(mc.listRelatives("all",ad=True))',ann='Record default visibility state for all nodes under rig root node ("all").') @@ -189,24 +189,24 @@ def create(): mc.menuItem(divider=True) mc.menuItem(label='Restore Visibility State', command='import glTools.utils.defaultAttrState;reload(glTools.utils.defaultAttrState);glTools.utils.defaultAttrState.setVisibilityState(visibilityState=1)',ann='Restore visibility state for all nodes with recorded default visibility state.') mc.menuItem(label='Restore Display Override State', command='import glTools.utils.defaultAttrState;reload(glTools.utils.defaultAttrState);glTools.utils.defaultAttrState.setDisplayOverridesState(displayOverrideState=1)',ann='Restore display override state for all nodes with recorded default display override state.') - + mc.setParent('..', menu=True) - + # > > Export Attrs mc.menuItem(allowOptionBoxes=True, label= 'Export Attrs', subMenu=True, tearOff=True) - + mc.menuItem(label='Rest Cache Name',command='import glTools.snapshot.utils;reload(glTools.snapshot.utils);[glTools.snapshot.utils.restCacheName(i) for i in mc.ls(sl=1)]',ann='Add "restCacheName" attribute to the selected components') mc.menuItem(label='Include in Snapshot',command='import glTools.snapshot.utils;reload(glTools.snapshot.utils);[glTools.snapshot.utils.includeInSnapshot(i) for i in mc.ls(sl=1)]',ann='Add "includeInSnapshot" attribute to the selected objects') mc.menuItem(label='Distance To Camera',command='import glTools.snapshot.utils;reload(glTools.snapshot.utils);sel = mc.ls(sl=1);glTools.snapshot.utils.distToCamObjAttr(sel[0],sel[1])',ann='Add "distToCamObj" attribute to the first selected object, and connect to the second selected object') mc.menuItem(divider=True) mc.menuItem(label='Set NonRenderable Faces',command='import glTools.rig.utils;reload(glTools.rig.utils);glTools.rig.utils.nonRenderableFaceSet(facelist=mc.ls(sl=1))',ann='Add a non-renderable faceset attribute to a mesh(es) based on the selected polygon faces.') mc.menuItem(label='Select NonRenderable Faces',command='import glTools.rig.utils;reload(glTools.rig.utils);sel = mc.ls(sl=1);glTools.rig.utils.selectNonRenderableFaces(sel[0])',ann='Select non-renderable faces on the first selected mesh.') - + mc.setParent('..', menu=True) - + # > > Proxy Mesh mc.menuItem(allowOptionBoxes=True, label= 'Proxy Mesh', subMenu=True, tearOff=True) - + mc.menuItem(label='Joint Proxy Bounds', command='import glTools.tools.proxyMesh;reload(glTools.tools.proxyMesh);glTools.tools.proxyMesh.skeletonProxyCage(mc.ls(sl=1,type="joint"))') mc.menuItem(label='Joint Proxy Mirror', command='import glTools.tools.proxyMesh;reload(glTools.tools.proxyMesh);[glTools.tools.proxyMesh.mirrorProxy(i) for i in mc.ls(sl=True)]') mc.menuItem(label='Make Proxy Bounds', command='import glTools.tools.proxyMesh;reload(glTools.tools.proxyMesh);[glTools.tools.proxyMesh.makeProxyBounds(i) for i in mc.ls(sl=True)]') @@ -220,32 +220,32 @@ def create(): mc.menuItem(label='Set Apply Initial SG', command='import glTools.tools.proxyMesh;reload(glTools.tools.proxyMesh);glTools.tools.proxyMesh.setApplyInitialSGFromSel()') mc.menuItem(label='Apply Proxies', command='import glTools.tools.proxyMesh;reload(glTools.tools.proxyMesh);glTools.tools.proxyMesh.applyProxies(mc.ls(sl=True,type="transform"))') mc.menuItem(label='Create SkinClusters', command='import glTools.tools.proxyMesh;reload(glTools.tools.proxyMesh);glTools.tools.proxyMesh.proxySkinClusters()') - + mc.setParent('..', menu=True) - + # > > AUTO MODULE mc.menuItem(allowOptionBoxes=True, label= 'Auto Module', subMenu=True, tearOff=True) - + mc.menuItem(label='Base Template', command='import glTools.rig.autoModuleTemplate;reload(glTools.rig.autoModuleTemplate);glTools.rig.autoModuleTemplate.moduleTemplateDialog(glTools.rig.autoModuleTemplate.baseModuleTemplate)') mc.menuItem(label='FK Chain Template', command='import glTools.rig.autoModuleTemplate;reload(glTools.rig.autoModuleTemplate);glTools.rig.autoModuleTemplate.moduleTemplateDialog(glTools.rig.autoModuleTemplate.fkChainModuleTemplate)') mc.menuItem(label='IK Chain Template', command='import glTools.rig.autoModuleTemplate;reload(glTools.rig.autoModuleTemplate);glTools.rig.autoModuleTemplate.moduleTemplateDialog(glTools.rig.autoModuleTemplate.ikChainModuleTemplate)') mc.menuItem(divider=True) mc.menuItem(label='Build Selected Module(s)', command='import glTools.rig.autoModuleBuild;reload(glTools.rig.autoModuleBuild);[glTools.rig.autoModuleBuild.moduleBuild(i) for i in mc.ls(sl=True,type="transform")]') mc.menuItem(label='Build All Modules', command='import glTools.rig.autoModuleBuild;reload(glTools.rig.autoModuleBuild);glTools.rig.autoModuleBuild.moduleBuildAll()') - + mc.setParent('..', menu=True) - + # > PROP mc.menuItem(allowOptionBoxes=True, label= 'Prop', subMenu=True, tearOff=True) mc.menuItem(label='Build Basic Prop', command='import glTools.nrig.rig.prop;reload(glTools.nrig.rig.prop);glTools.nrig.rig.prop.PropRig().build(clean=True)') - + mc.setParent('..', menu=True) - + mc.setParent('..', menu=True) - + # Animation mc.menuItem(allowOptionBoxes=True, label='Animation', subMenu=True, tearOff=True) - + mc.menuItem(label='Set To Default', command='import glTools.rig.utils;reload(glTools.rig.utils);[glTools.rig.utils.setToDefault(i) for i in mc.ls(sl=True)]') mc.menuItem(label='Mirror Selected', command='import glTools.tools.match;reload(glTools.tools.match);glTools.tools.match.Match().twinSelection()') mc.menuItem(label='Swap Selected', command='import glTools.tools.match;reload(glTools.tools.match);glTools.tools.match.Match().swapSelection()') @@ -253,9 +253,9 @@ def create(): mc.menuItem(label='IK/FK Match', command='import glTools.rig.ikFkMatch;reload(glTools.rig.ikFkMatch);[glTools.rig.ikFkMatch.match(i) for i in mc.ls(sl=True)]') mc.menuItem(label='Dk Anim', command='mm.eval("dkAnim")') mc.menuItem(label='Graph Editor Filter', command='glTools.tools.graphFilter.ui()') - + mc.setParent('..', menu=True) - + # > JOINT mc.menuItem(allowOptionBoxes=True, label='Joint', subMenu=True, tearOff=True) mc.menuItem(label='Joint Group', command='import glTools.utils.joint;reload(glTools.utils.joint);[glTools.utils.joint.group(joint=i,indexStr="") for i in mc.ls(sl=1,type="joint")]') @@ -265,21 +265,21 @@ def create(): mc.menuItem(label='Zero Joint Orient', command='[mc.setAttr(jnt+".jo",0,0,0) for jnt in mc.ls(sl=1,type="joint")]') mc.menuItem(label='Freeze Joint Transform', command='mc.makeIdentity(mc.ls(sl=True,type="joint"),apply=True,t=True,r=True,s=True,n=False)') mc.menuItem(label='Draw Style (Bone)', command='import glTools.utils.joint;reload(glTools.utils.joint);jnts = mc.ls(sl=1);glTools.utils.joint.setDrawStyle(jnts,drawStyle="bone")') - + mc.setParent('..', menu=True) - + # > IK mc.menuItem(allowOptionBoxes=True, label='IK', subMenu=True, tearOff=True) mc.menuItem(label='Create IK Handle', command='glTools.ui.ik.ikHandleUI()') mc.menuItem(label='Stretchy IK Chain', command='glTools.ui.ik.stretchyIkChainUI()') mc.menuItem(label='Stretchy IK Limb', command='glTools.ui.ik.stretchyIkLimbUI()') mc.menuItem(label='Stretchy IK Spline', command='glTools.ui.ik.stretchyIkSplineUI()') - + mc.setParent('..', menu=True) - + # > CURVE mc.menuItem(allowOptionBoxes=True, label='Curve', subMenu=True, tearOff=True) - + mc.menuItem(label='Mirror Curve', command='import glTools.ui.curve;reload(glTools.ui.curve);glTools.ui.curve.mirrorCurveFromSel()') mc.menuItem(label='Locator Curve', command='import glTools.ui.curve;reload(glTools.ui.curve);glTools.ui.curve.locatorCurveUI()') mc.menuItem(label='Attach To Curve', command='import glTools.ui.curve;reload(glTools.ui.curve);glTools.ui.curve.attachToCurveUI()') @@ -288,7 +288,7 @@ def create(): mc.menuItem(label='Curve From Edge Loop', command='import glTools.ui.curve;reload(glTools.ui.curve);glTools.ui.curve.edgeLoopCurveUI()') mc.menuItem(label='Build Curve Command', command='import glTools.utils.curve;reload(glTools.utils.curve);print glTools.utils.curve.buildCmd(mc.ls(sl=1)[0],True)') mc.menuItem(label='Uniform Rebuild', command='import glTools.utils.curve;reload(glTools.utils.curve);glTools.ui.curve.uniformRebuildCurveUI()') - + #mc.menuItem(allowOptionBoxes=True, label='LidRails', subMenu=True, tearOff=True) # #mc.menuItem(label='Create LidSurface', command='glTools.ui.lidRails.lidSurfaceCreateUI()') @@ -296,34 +296,34 @@ def create(): #mc.menuItem(label='4 Control Setup', command='glTools.ui.lidRails.fourCtrlSetupUI()') # #mc.setParent('..', menu=True) - + mc.setParent('..', menu=True) - + # > SURFACE mc.menuItem(allowOptionBoxes=True, label='Surface', subMenu=True, tearOff=True) - + mc.menuItem(label='Locator Surface', command='glTools.ui.surface.locatorSurfaceUI()') mc.menuItem(label='Snap To Surface', command='glTools.ui.surface.snapToSurfaceUI()') mc.menuItem(label='Attach To Surface', command='glTools.ui.surface.attachToSurfaceUI()') mc.menuItem(label='Surface Points', command='glTools.ui.surface.surfacePointsUI()') - + mc.setParent('..', menu=True) - + # > MESH mc.menuItem(allowOptionBoxes=True, label='Mesh', subMenu=True, tearOff=True) - + mc.menuItem(label='Snap To Mesh', command='glTools.ui.mesh.snapToMeshUI()') mc.menuItem(label='Interactive Snap Tool', command='glTools.ui.mesh.interactiveSnapToMeshUI()') mc.menuItem(label='Attach To Mesh', command='glTools.ui.mesh.attachToMeshUI()') mc.menuItem(label='Mirror (select middle edge)', command='import glTools.utils.edgeFlowMirror;reload(glTools.utils.edgeFlowMirror);glTools.utils.edgeFlowMirror.mirrorGeo(mc.ls(sl=True,fl=True)[0])') mc.menuItem(label='Reconstruct Mesh', command='import glTools.tools.mesh;reload(glTools.tools.mesh);sel = mc.ls(sl=1);[glTools.tools.mesh.reconstructMesh(i,False) for i in sel]') mc.menuItem(label='Reconstruct and Replace', command='import glTools.tools.mesh;reload(glTools.tools.mesh);sel = mc.ls(sl=1);[glTools.tools.mesh.reconstructMesh(i,True) for i in sel]') - + mc.setParent('..', menu=True) - + # > SKINCLUSTER mc.menuItem(allowOptionBoxes=True, label='SkinCluster', subMenu=True, tearOff=True) - + mc.menuItem(label='Reset', command='glTools.ui.skinCluster.resetFromUI()') mc.menuItem(label='Clean', command='glTools.ui.skinCluster.cleanFromUI()') mc.menuItem(label='Rename', command='for i in mc.ls(sl=1): glTools.utils.skinCluster.rename(i)') @@ -339,24 +339,24 @@ def create(): mc.menuItem(label='Remove Multiple Base Infs', command='import glTools.utils.skinCluster;reload(glTools.utils.skinCluster);sel = mc.ls(sl=1);glTools.utils.skinCluster.removeMultipleInfluenceBases(sel[0],sel[1:])') mc.menuItem(label='SkinCluster Data UI', command='import glTools.ui.skinClusterData;reload(glTools.ui.skinClusterData);glTools.ui.skinClusterData.skinClusterDataUI()') mc.menuItem(label='Weights Manager', command='import glTools.ui.qt.weightsManager;reload(glTools.ui.qt.weightsManager);glTools.ui.qt.weightsManager.WeightsManager().show()') - + mc.setParent('..', menu=True) - + # > BLENDSHAPE mc.menuItem(allowOptionBoxes=True, label='BlendShape', subMenu=True, tearOff=True) - + mc.menuItem(label='Create BlendShape',command='import glTools.tools.blendShape;reload(glTools.tools.blendShape);glTools.tools.blendShape.createFromSelection()',ann='Create basic blendShape from selection') mc.menuItem(label='BlendShape Manager',command='import glTools.ui.blendShape;reload(glTools.ui.blendShape);glTools.ui.blendShape.blendShapeManagerUI()',ann='Open BlendShape Manager UI') mc.menuItem(label='Update Targets',command='import glTools.ui.blendShape;reload(glTools.ui.blendShape);glTools.ui.blendShape.updateTargetsUI()',ann='Open Update BlendShape Targets UI') mc.menuItem(divider=True) mc.menuItem(label='Override BlendShape',command='import glTools.tools.blendShape;reload(glTools.tools.blendShape);[glTools.tools.blendShape.endOfChainBlendShape(i) for i in mc.ls(sl=1)]',ann='Create override (end of chain) blendShape deformers on the selected geometry') mc.menuItem(label='Add Override Target',command='import glTools.tools.blendShape;reload(glTools.tools.blendShape);glTools.tools.blendShape.addOverrideTarget(mc.ls(sl=1)[1],mc.ls(sl=1)[0])',ann='Add override blendShape target based on the selected geometry') - + mc.setParent('..', menu=True) - + # > NDYNAMICS mc.menuItem(allowOptionBoxes=True, label='nDynamics', subMenu=True, tearOff=True) - + mc.menuItem(label='UI', command='glTools.ui.nDynamics.create()') mc.menuItem(divider=True) mc.menuItem(label='Create nucleus', command='glTools.utils.nDynamics.createNucleus()') @@ -364,27 +364,27 @@ def create(): mc.menuItem(label='Create nRigid', command='for i in mc.ls(sl=1): glTools.utils.nDynamics.createNRigid(i)') mc.menuItem(divider=True) mc.menuItem(label='Delete nCloth', command='for i in mc.ls(sl=1): glTools.utils.nDynamics.deleteNCloth(i)') - + mc.setParent('..', menu=True) - + # > SPACES #mc.menuItem(allowOptionBoxes=True, label='Spaces', subMenu=True, tearOff=True) #mc.menuItem(label='Create/Add', command='glTools.ui.spaces.createAddUI()') #mc.menuItem(label='Spaces UI', command='glTools.tools.spaces.Spaces().ui()') #mc.menuItem(ob=True, command='glTools.ui.spaces.charUI()') #mc.setParent('..', menu=True) - + # > POSE MATCH mc.menuItem(allowOptionBoxes=True, label='Pose Match Setup', subMenu=True, tearOff=True) mc.menuItem(label='Evaluation Order', command='glTools.ui.poseMatch.evaluationOrderUI()') mc.menuItem(label='Match Rules', command='glTools.ui.poseMatch.matchRulesUI()') - + mc.setParent('..', menu=True) - + #----------------------------------------# mc.menuItem(divider =True) #----------------------------------------# - + mc.menuItem(label='Refresh Menu', command='import glTools.ui.menu;reload(glTools.ui.menu);glTools.ui.menu.create()') - + mc.setParent('..') diff --git a/ui/mesh.py b/ui/mesh.py index ff73e20..b61b239 100644 --- a/ui/mesh.py +++ b/ui/mesh.py @@ -17,34 +17,34 @@ def interactiveSnapToMeshUI(): window = 'interactiveSnapUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Snap To Mesh - Interactive') - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # UI Elements #--- - + # Target Mesh snapMeshTFB = mc.textFieldButtonGrp('interactiveSnapMeshTFB',label='Target Mesh',text='',buttonLabel='Load Selected') - + # Slider snapFSG = mc.floatSliderGrp('interactiveSnapFSG', label='Drag:',field=False, minValue=0.0, maxValue=1.0,value=0 ) snapRangeFFG = mc.floatFieldGrp('interactiveSnapRangeFSG', numberOfFields=2, label='Slider Min/Max', value1=0.0, value2=1.0) - + # UI Callbacks mc.textFieldButtonGrp(snapMeshTFB,e=True,bc='glTools.ui.utils.loadMeshSel("'+snapMeshTFB+'")') mc.floatSliderGrp('interactiveSnapFSG',e=True,cc='glTools.ui.mesh.interactiveSnapChangeCommand()') mc.floatSliderGrp('interactiveSnapFSG',e=True,dc='glTools.ui.mesh.interactiveSnapDragCommand()') - + # Buttons cancelB = mc.button('interactiveSnapCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(snapMeshTFB,'top',5),(snapMeshTFB,'left',5),(snapMeshTFB,'right',5)]) mc.formLayout(FL,e=True,af=[(snapFSG,'left',5),(snapFSG,'right',5)],ac=[(snapFSG,'top',5,snapMeshTFB)]) mc.formLayout(FL,e=True,af=[(snapRangeFFG,'left',5),(snapRangeFFG,'right',5)],ac=[(snapRangeFFG,'top',5,snapFSG)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Show Window mc.showWindow(window) @@ -53,18 +53,18 @@ def interactiveSnapUpdateCommand(): ''' global interactiveSnapSrcList global interactiveSnapDstList - + # Clear global lists interactiveSnapSrcList = [] interactiveSnapDstList = [] - + # Get current selection sel = mc.ls(sl=1,fl=1) if not sel: return - + # Get target mesh mesh = mc.textFieldGrp('interactiveSnapMeshTFB',q=True,text=True) - + # Rebuild global lists for i in sel: pnt = glTools.utils.base.getPosition(i) @@ -77,7 +77,7 @@ def interactiveSnapChangeCommand(): ''' global interactiveSnapSrcList global interactiveSnapDstList - + # Clear global lists interactiveSnapSrcList = [] interactiveSnapDstList = [] @@ -87,27 +87,27 @@ def interactiveSnapDragCommand(): ''' global interactiveSnapSrcList global interactiveSnapDstList - + # Get current selection sel = mc.ls(sl=1,fl=1) if not sel: return - + # Check global list validity if not interactiveSnapSrcList or not interactiveSnapDstList: interactiveSnapUpdateCommand() - + # Get Snap amount amount = mc.floatSliderGrp('interactiveSnapFSG',q=True,v=True) - + # Move points pos = [0,0,0] for i in range(len(sel)): - + # Calculate new position pos[0] = interactiveSnapSrcList[i][0] + ((interactiveSnapDstList[i][0] - interactiveSnapSrcList[i][0]) * amount) pos[1] = interactiveSnapSrcList[i][1] + ((interactiveSnapDstList[i][1] - interactiveSnapSrcList[i][1]) * amount) pos[2] = interactiveSnapSrcList[i][2] + ((interactiveSnapDstList[i][2] - interactiveSnapSrcList[i][2]) * amount) - + # Set position mc.move(pos[0],pos[1],pos[2],sel[i],ws=True,a=True) @@ -119,27 +119,27 @@ def snapToMeshUI(): window = 'snapToMeshUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Snap To Mesh') - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # UI Elements #--- - + # Mesh meshTFB = mc.textFieldButtonGrp('snapToMeshTFB',label='Target Mesh',text='',buttonLabel='Load Selected') - + # Orient orientCBG = mc.checkBoxGrp('snapToMeshOrientCBG',label='Orient To Face',ncb=1,v1=False) - + # ---------- # - Orient - # ---------- - + # Orient Frame orientFrameL = mc.frameLayout('snapToMeshOriFL',l='Orient Options',cll=0,en=0) orientFormL = mc.formLayout(numberOfDivisions=100) - + # OptionMenuGrp axList = ['X','Y','Z','-X','-Y','-Z'] orientNormAxisOMG = mc.optionMenuGrp('snapToMeshNormOMG',label='Normal Axis',en=False) @@ -148,24 +148,24 @@ def snapToMeshUI(): for ax in axList: mc.menuItem(label=ax) # Set Default Value mc.optionMenuGrp('snapToMeshUpVecOMG',e=True,sl=2) - + # Up Vector upVectorFFG = mc.floatFieldGrp('snapToMeshUpVecFFG',label='UpVector',nf=3,v1=0,v2=1,v3=0,en=0) upVectorObjectTFB = mc.textFieldButtonGrp('snapToMeshUpVecObjTFG',label='WorldUpObject',text='',buttonLabel='Load Selected',en=0) - + mc.setParent('..') mc.setParent('..') - + # UI callback commands mc.textFieldButtonGrp(meshTFB,e=True,bc='glTools.ui.utils.loadMeshSel("'+meshTFB+'")') mc.checkBoxGrp(orientCBG,e=True,cc='glTools.ui.utils.checkBoxToggleLayout("'+orientCBG+'","'+orientFrameL+'")') mc.textFieldButtonGrp(upVectorObjectTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+upVectorObjectTFB+'")') - + # Buttons snapB = mc.button('snapToMeshSnapB',l='Snap!',c='glTools.ui.mesh.snapToMeshFromUI(False)') snapCloseB = mc.button('snapToMeshSnapCloseB',l='Snap and Close',c='glTools.ui.mesh.snapToMeshFromUI(True)') cancelB = mc.button('snapToMeshCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(meshTFB,'top',5),(meshTFB,'left',5),(meshTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(orientCBG,'top',5,meshTFB)],af=[(orientCBG,'left',5),(orientCBG,'right',5)]) @@ -173,18 +173,18 @@ def snapToMeshUI(): mc.formLayout(FL,e=True,ac=[(snapB,'bottom',5,snapCloseB)],af=[(snapB,'left',5),(snapB,'right',5)]) mc.formLayout(FL,e=True,ac=[(snapCloseB,'bottom',5,cancelB)],af=[(snapCloseB,'left',5),(snapCloseB,'right',5)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Form Layout - Orient mc.formLayout(orientFormL,e=True,af=[(orientNormAxisOMG,'top',5),(orientNormAxisOMG,'left',5),(orientNormAxisOMG,'right',5)]) mc.formLayout(orientFormL,e=True,ac=[(orientUpVecAxisOMG,'top',5,orientNormAxisOMG)]) mc.formLayout(orientFormL,e=True,af=[(orientUpVecAxisOMG,'left',5),(orientUpVecAxisOMG,'right',5)]) - + mc.formLayout(orientFormL,e=True,ac=[(upVectorFFG,'top',5,orientUpVecAxisOMG)]) mc.formLayout(orientFormL,e=True,af=[(upVectorFFG,'left',5),(upVectorFFG,'right',5)]) - + mc.formLayout(orientFormL,e=True,ac=[(upVectorObjectTFB,'top',5,upVectorFFG)]) mc.formLayout(orientFormL,e=True,af=[(upVectorObjectTFB,'left',5),(upVectorObjectTFB,'right',5)]) - + # Show Window mc.showWindow(window) @@ -195,12 +195,12 @@ def snapToMeshFromUI(close=False): # Window window = 'snapToMeshUI' if not mc.window(window,q=True,ex=1): raise UIError('SnapToSurface UI does not exist!!') - + # Get UI data mesh = mc.textFieldGrp('snapToMeshTFB',q=True,text=True) if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # Orient orient = mc.checkBoxGrp('snapToMeshOrientCBG',q=True,v1=True) # Orient Options @@ -209,10 +209,10 @@ def snapToMeshFromUI(close=False): # Up Vector upVec = (mc.floatFieldGrp('snapToMeshUpVecFFG',q=True,v1=True),mc.floatFieldGrp('snapToMeshUpVecFFG',q=True,v2=True),mc.floatFieldGrp('snapToMeshUpVecFFG',q=True,v3=True)) upVecObj = mc.textFieldButtonGrp('snapToMeshUpVecObjTFG',q=True,text=True) - + # Get User Selection sel = mc.ls(sl=True,fl=True) - + # Execute Command glTools.utils.mesh.snapPtsToMesh(mesh,sel) # Orient @@ -222,7 +222,7 @@ def snapToMeshFromUI(close=False): glTools.utils.mesh.orientToMesh(mesh=mesh,transform=obj,upVector=upVec,upVectorObject=upVecObj,normalAxis=normAx,upAxis=upVecAx) except: raise Exception('Object "'+obj+'" is not a valid transform!! Unable to orient!') - + # Cleanup if close: mc.deleteUI(window) @@ -234,29 +234,29 @@ def snapToClosestVertexUI(): window = 'snapToClosestVtxUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Snap To Closest Vertex') - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # =============== # - UI Elements - # =============== - + # Mesh meshTFB = mc.textFieldButtonGrp('snapToMeshVtxTFB',label='Target Mesh',text='',buttonLabel='Load Selected') - + # UI callback commands mc.textFieldButtonGrp(meshTFB,e=True,bc='glTools.ui.utils.loadMeshSel("'+meshTFB+'")') - + # Buttons snapB = mc.button('snapToMeshSnapB',l='Snap To Vertex',c='glTools.ui.mesh.snapToClosestVertexFromUI(False)') cancelB = mc.button('snapToMeshCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(meshTFB,'top',5),(meshTFB,'left',5),(meshTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(snapB,'bottom',5,cancelB)],af=[(snapB,'left',5),(snapB,'right',5)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Show Window mc.showWindow(window) @@ -267,10 +267,10 @@ def snapToClosestVertexFromUI(close=False): window = 'snapToClosestVtxUI' if not mc.window(window,q=True,ex=1): raise UIError('SnapToClosestVertex UI does not exist!!') - + # Get UI data mesh = mc.textFieldGrp('snapToMeshVtxTFB',q=True,text=True) - + for i in mc.ls(sl=1,fl=1): #pt = mc.pointPosition(i) pt = glTools.utils.base.getPosition(i) @@ -298,7 +298,7 @@ def attachToMeshUI(): prefixTFG = mc.textFieldGrp('attachToMeshPrefixTFG',label='Prefix',text='') # Orient orientCBG = mc.checkBoxGrp('attachToMeshOrientCBG',label='Orient To Face',ncb=1,v1=False) - + # Orient Frame orientFrameL = mc.frameLayout('attachToMeshOriFL',l='Orient Options',cll=0,en=0) orientFormL = mc.formLayout(numberOfDivisions=100) @@ -310,20 +310,20 @@ def attachToMeshUI(): for ax in axList: mc.menuItem(label=ax) # Set Default Value mc.optionMenuGrp(orientTanAxisOMG,e=True,sl=2) - + mc.setParent('..') mc.setParent('..') - + # UI callback commands mc.textFieldButtonGrp(meshTFB,e=True,bc='glTools.ui.utils.loadMeshSel("'+meshTFB+'")') mc.textFieldButtonGrp(transformTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+transformTFB+'","'+prefixTFG+'")') mc.checkBoxGrp(orientCBG,e=True,cc='glTools.ui.utils.checkBoxToggleLayout("'+orientCBG+'","'+orientFrameL+'")') - + # Buttons snapB = mc.button('attachToMeshAttachB',l='Attach',c='glTools.ui.mesh.attachToMeshFromUI(False)') snapCloseB = mc.button('attachToMeshAttachCloseB',l='Attach and Close',c='glTools.ui.mesh.attachToMeshFromUI(True)') cancelB = mc.button('attachToMeshCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(meshTFB,'top',5),(meshTFB,'left',5),(meshTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(transformTFB,'top',5,meshTFB)]) @@ -340,12 +340,12 @@ def attachToMeshUI(): mc.formLayout(FL,e=True,ac=[(snapCloseB,'bottom',5,cancelB)]) mc.formLayout(FL,e=True,af=[(snapCloseB,'left',5),(snapCloseB,'right',5)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Form Layout - Orient mc.formLayout(orientFormL,e=True,af=[(orientNormAxisOMG,'top',5),(orientNormAxisOMG,'left',5),(orientNormAxisOMG,'right',5)]) mc.formLayout(orientFormL,e=True,ac=[(orientTanAxisOMG,'top',5,orientNormAxisOMG)]) mc.formLayout(orientFormL,e=True,af=[(orientTanAxisOMG,'left',5),(orientTanAxisOMG,'right',5)]) - + # Show Window mc.showWindow(window) @@ -370,9 +370,9 @@ def attachToMeshFromUI(close=False): # Orient Options normAx = str.lower(str(mc.optionMenuGrp('attachToMeshNormOMG',q=True,v=True))) tanAx = str.lower(str(mc.optionMenuGrp('attachToMeshTanOMG',q=True,v=True))) - + # Execute command glTools.utils.attach.attachToMesh(mesh=mesh,transform=obj,useClosestPoint=True,orient=orient,normAxis=normAx,tangentAxis=tanAx,prefix=pre) - + # Cleanup if close: mc.deleteUI(window) diff --git a/ui/meshCache.py b/ui/meshCache.py index 6daa750..c2a41d4 100644 --- a/ui/meshCache.py +++ b/ui/meshCache.py @@ -7,18 +7,18 @@ def meshCacheUI(): ''' Main UI for the meshCache module ''' - # Get current frame range + # Get current frame range startFrame = mc.playbackOptions(q=True,min=True) endFrame = mc.playbackOptions(q=True,max=True) - + # Window window = 'meshCacheUI' if mc.window(window,q=True,ex=True): mc.deleteUI(window) window = mc.window(window,t='Export Mesh Cache',s=True) - + # Layout CL = mc.columnLayout(adj=True) - + # UI Elements pathTBG = mc.textFieldButtonGrp('meshCache_pathTBG',label='Path',buttonLabel='...') nameTFG = mc.textFieldGrp('meshCache_nameTFG',label='Combine Cache Name',text='') @@ -32,17 +32,17 @@ def meshCacheUI(): exportObjB = mc.button('meshCache_exportObjB',label='Export OBJ',c='glTools.ui.meshCache.exportObjFromUI()') exportObjCombineB = mc.button('meshCache_exportObjCombineB',label='Export OBJ Combined',c='glTools.ui.meshCache.exportObjCombinedFromUI()') closeB = mc.button('meshCache_closeB',label='Close',c='mc.deleteUI("'+window+'")') - + # UI Callbacks mc.textFieldButtonGrp(pathTBG,e=True,bc='glTools.ui.utils.exportFolderBrowser("'+pathTBG+'")') - + # Show Window mc.window(window,e=True,w=450,h=262) mc.showWindow(window) def exportGeoFromUI(): ''' - writeGeoCache from UI + writeGeoCache from UI ''' # Get UI info path = mc.textFieldButtonGrp('meshCache_pathTBG',q=True,text=True) @@ -52,22 +52,22 @@ def exportGeoFromUI(): uvSet = mc.textFieldGrp('meshCache_uvSetTFG',q=True,text=True) worldSpace = bool(mc.radioButtonGrp('meshCache_spaceRBG',q=True,sl=True)-1) gz = mc.checkBoxGrp('meshCache_gzipCBG',q=True,v1=True) - + # Check UV Set if uvSet == 'default': uvSet = '' - + # Get selection sel = [i for i in mc.ls(sl=True,fl=True,o=True) if glTools.utils.mesh.isMesh(i)] if not sel: print 'No valid mesh objects selected for export!!' return - + # Export each mesh for mesh in sel: - + # Generate file name mesh_name = mesh.replace(':','_') - + # Export glTools.tools.meshCache.writeGeoCache(path,mesh_name,mesh,start,end,pad,uvSet,worldSpace,gz) @@ -84,21 +84,21 @@ def exportGeoCombinedFromUI(): uvSet = mc.textFieldGrp('meshCache_uvSetTFG',q=True,text=True) worldSpace = bool(mc.radioButtonGrp('meshCache_spaceRBG',q=True,sl=True)-1) gz = mc.checkBoxGrp('meshCache_gzipCBG',q=True,v1=True) - + # Check Name if not name: print 'Provide valid cache name and try again!' return - + # Check UV Set if uvSet == 'default': uvSet = '' - + # Get selection sel = [i for i in mc.ls(sl=True,fl=True,o=True) if glTools.utils.mesh.isMesh(i)] if not sel: print 'No valid mesh objects selected for export!!' return - + # Write Combine Cache glTools.tools.meshCache.writeGeoCombineCache(path,name,sel,start,end,pad,uvSet,worldSpace,gz) @@ -114,22 +114,22 @@ def exportObjFromUI(): uvSet = mc.textFieldGrp('meshCache_uvSetTFG',q=True,text=True) worldSpace = bool(mc.radioButtonGrp('meshCache_spaceRBG',q=True,sl=True)-1) gz = mc.checkBoxGrp('meshCache_gzipCBG',q=True,v1=True) - + # Check UV Set if uvSet == 'default': uvSet = '' - + # Get selection sel = [i for i in mc.ls(sl=True,fl=True,o=True) if glTools.utils.mesh.isMesh(i)] if not sel: print 'No valid mesh objects selected for export!!' return - + # Export each mesh for mesh in sel: - + # Generate file name mesh_name = mesh.replace(':','_') - + # Export glTools.tools.meshCache.writeObjCache(path,mesh_name,mesh,start,end,pad,uvSet,worldSpace,gz) @@ -146,21 +146,21 @@ def exportObjCombinedFromUI(): uvSet = mc.textFieldGrp('meshCache_uvSetTFG',q=True,text=True) worldSpace = bool(mc.radioButtonGrp('meshCache_spaceRBG',q=True,sl=True)-1) gz = mc.checkBoxGrp('meshCache_gzipCBG',q=True,v1=True) - + # Check Name if not name: print 'Provide valid cache name and try again!' return - + # Check UV Set if uvSet == 'default': uvSet = None - + # Get selection sel = [i for i in mc.ls(sl=True,fl=True,o=True) if glTools.utils.mesh.isMesh(i)] if not sel: print 'No valid mesh objects selected for export!!' return - + # Write Combine Cache glTools.tools.meshCache.writeObjCombineCache(path,name,sel,start,end,pad,uvSet,worldSpace,gz) diff --git a/ui/mirrorDeformerWeights.py b/ui/mirrorDeformerWeights.py index 2145024..e00e94a 100644 --- a/ui/mirrorDeformerWeights.py +++ b/ui/mirrorDeformerWeights.py @@ -5,10 +5,10 @@ def ui(): ''' ''' - # + # win = 'mirrorDeformerWeightsUI' if mc.window(win,q=True,ex=True): mc.deleteUI(win) win = mc.window(win,l=win) - + FL = mc.formLayout() diff --git a/ui/mocapTransfer.py b/ui/mocapTransfer.py index 515a02a..4d17b6c 100644 --- a/ui/mocapTransfer.py +++ b/ui/mocapTransfer.py @@ -10,107 +10,107 @@ def create(): # ============ # - Build UI - # ============ - + # Window window = 'mocapTransferUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,title='Mocap/Anim Transfer',sizeable=True) - + # FormLayout FL = mc.formLayout(numberOfDivisions=100) - + # Buttons transferB = mc.button(label='Transfer',c='glTools.ui.mocapTransfer.transferFromUI()') closeB = mc.button(label='Close',c='mc.deleteUI("'+window+'")') - + # FrameLayout mc.setParent(FL) rangeLayout = mc.frameLayout(label='Bake Range',borderStyle='in') - + # TabLayout mc.setParent(FL) tabLayout = mc.tabLayout('mocapXferTabLayout',innerMarginWidth=5,innerMarginHeight=5) - + mc.formLayout(FL,e=True,af=[(closeB,'left',5),(closeB,'right',5),(closeB,'bottom',5)]) mc.formLayout(FL,e=True,af=[(transferB,'left',5),(transferB,'right',5)],ac=[(transferB,'bottom',5,closeB)]) mc.formLayout(FL,e=True,af=[(tabLayout,'left',5),(tabLayout,'right',5),(tabLayout,'top',5)]) mc.formLayout(FL,e=True,af=[(rangeLayout,'left',5),(rangeLayout,'right',5)],ac=[(rangeLayout,'top',5,tabLayout),(rangeLayout,'bottom',5,transferB)]) - + # ---------------- # - Range Layout - # ---------------- - + mc.setParent(rangeLayout) - + # FormLayout bakeRangeFL = mc.formLayout(numberOfDivisions=100) - + mocap_rangeCBG = mc.checkBoxGrp('xferMocap_bakeRangeCBG',label='Specify Bake Range:',numberOfCheckBoxes=1,value1=0) mocap_startEndIFG = mc.intFieldGrp('xferMocap_startEndCBG',label='Bake Range Start/End:',numberOfFields=2,value1=0,value2=0,en=False) mocap_staticChanCBG = mc.checkBoxGrp('xferMocap_staticChanCBG',label='Delete Static Channels:',numberOfCheckBoxes=1,value1=0) - + mc.formLayout(bakeRangeFL,e=True,af=[(mocap_rangeCBG,'left',5),(mocap_rangeCBG,'right',5),(mocap_rangeCBG,'top',5)]) mc.formLayout(bakeRangeFL,e=True,af=[(mocap_startEndIFG,'left',5),(mocap_startEndIFG,'right',5)],ac=[(mocap_startEndIFG,'top',5,mocap_rangeCBG)]) mc.formLayout(bakeRangeFL,e=True,af=[(mocap_staticChanCBG,'left',5),(mocap_staticChanCBG,'right',5)],ac=[(mocap_staticChanCBG,'top',5,mocap_startEndIFG)]) - + # UI Element Callbacks mc.checkBoxGrp(mocap_rangeCBG,e=True,cc='glTools.ui.mocapTransfer.toggleBakeRange()') - + # --------------------- # - FROM Mocap Layout - # --------------------- - + mc.setParent(tabLayout) - + # FormLayout fromMocapFL = mc.formLayout(numberOfDivisions=100) - + # Layout Elements fromMocap_mocapTFB = mc.textFieldButtonGrp('fromMocap_mocapTFB',label='Mocap NS:',text='',buttonLabel='<<<') fromMocap_rigTFB = mc.textFieldButtonGrp('fromMocap_rigTFB',label='Rig NS:',text='',buttonLabel='<<<') fromMocap_SEP = mc.separator(height=10,style='single') fromMocap_xferToRBG = mc.radioButtonGrp('fromMocap_xferToRBG',label='Transfer To:',numberOfRadioButtons=2,labelArray2=['Controls','Overrides'],select=2) fromMocap_xferHandCBG = mc.checkBoxGrp('fromMocap_xferHandCBG',label='Transfer Fingers:',numberOfCheckBoxes=1,value1=0) - + mc.formLayout(fromMocapFL,e=True,af=[(fromMocap_mocapTFB,'left',5),(fromMocap_mocapTFB,'right',5),(fromMocap_mocapTFB,'top',5)]) mc.formLayout(fromMocapFL,e=True,af=[(fromMocap_rigTFB,'left',5),(fromMocap_rigTFB,'right',5)],ac=[(fromMocap_rigTFB,'top',5,fromMocap_mocapTFB)]) mc.formLayout(fromMocapFL,e=True,af=[(fromMocap_SEP,'left',5),(fromMocap_SEP,'right',5)],ac=[(fromMocap_SEP,'top',5,fromMocap_rigTFB)]) mc.formLayout(fromMocapFL,e=True,af=[(fromMocap_xferToRBG,'left',5),(fromMocap_xferToRBG,'right',5)],ac=[(fromMocap_xferToRBG,'top',5,fromMocap_SEP)]) mc.formLayout(fromMocapFL,e=True,af=[(fromMocap_xferHandCBG,'left',5),(fromMocap_xferHandCBG,'right',5)],ac=[(fromMocap_xferHandCBG,'top',5,fromMocap_xferToRBG)]) - + # UI Element Callbacks mc.textFieldButtonGrp(fromMocap_mocapTFB,e=True,bc='glTools.ui.utils.loadNsSel("'+fromMocap_mocapTFB+'",topOnly=False)') mc.textFieldButtonGrp(fromMocap_rigTFB,e=True,bc='glTools.ui.utils.loadNsSel("'+fromMocap_rigTFB+'",topOnly=False)') - + # ------------------- # - TO Mocap Layout - # ------------------- - + mc.setParent(tabLayout) - + # FormLayout toMocapFL = mc.formLayout(numberOfDivisions=100) - + # Layout Elements toMocap_rigTFB = mc.textFieldButtonGrp('toMocap_rigTFB',label='Rig NS:',text='',buttonLabel='<<<') toMocap_mocapTFB = mc.textFieldButtonGrp('toMocap_mocapTFB',label='Mocap NS:',text='',buttonLabel='<<<') - + mc.formLayout(toMocapFL,e=True,af=[(toMocap_rigTFB,'left',5),(toMocap_rigTFB,'right',5),(toMocap_rigTFB,'top',5)]) mc.formLayout(toMocapFL,e=True,af=[(toMocap_mocapTFB,'left',5),(toMocap_mocapTFB,'right',5)],ac=[(toMocap_mocapTFB,'top',5,toMocap_rigTFB)]) - + # UI Element Callbacks mc.textFieldButtonGrp(toMocap_rigTFB,e=True,bc='glTools.ui.utils.loadNsSel("'+toMocap_rigTFB+'",topOnly=False)') mc.textFieldButtonGrp(toMocap_mocapTFB,e=True,bc='glTools.ui.utils.loadNsSel("'+toMocap_mocapTFB+'",topOnly=False)') - + # --------------------- # - Rig TO Rig Layout - # --------------------- - + mc.setParent(tabLayout) - + # FormLayout rigToRigFL = mc.formLayout(numberOfDivisions=100) - + # Layout Elements rigToRig_srcTFB = mc.textFieldButtonGrp('rigToRig_srcTFB',label='Source Rig NS:',text='',buttonLabel='<<<') rigToRig_dstTFB = mc.textFieldButtonGrp('rigToRig_dstTFB',label='Destination Rig NS:',text='',buttonLabel='<<<') @@ -118,30 +118,30 @@ def create(): rigToRig_xferToRBG = mc.radioButtonGrp('rigToRig_xferToRBG',label='Transfer To:',numberOfRadioButtons=2,labelArray2=['Controls','Overrides'],select=1) rigToRig_xferHandCBG = mc.checkBoxGrp('rigToRig_xferHandCBG',label='Transfer Fingers:',numberOfCheckBoxes=1,value1=0) rigToRig_xferAllTransCBG = mc.checkBoxGrp('rigToRig_xferAllTransCBG',label='Transfer AllTrans:',numberOfCheckBoxes=1,value1=0) - + mc.formLayout(rigToRigFL,e=True,af=[(rigToRig_srcTFB,'left',5),(rigToRig_srcTFB,'right',5),(rigToRig_srcTFB,'top',5)]) mc.formLayout(rigToRigFL,e=True,af=[(rigToRig_dstTFB,'left',5),(rigToRig_dstTFB,'right',5)],ac=[(rigToRig_dstTFB,'top',5,rigToRig_srcTFB)]) mc.formLayout(rigToRigFL,e=True,af=[(rigToRig_SEP,'left',5),(rigToRig_SEP,'right',5)],ac=[(rigToRig_SEP,'top',5,rigToRig_dstTFB)]) mc.formLayout(rigToRigFL,e=True,af=[(rigToRig_xferToRBG,'left',5),(rigToRig_xferToRBG,'right',5)],ac=[(rigToRig_xferToRBG,'top',5,rigToRig_SEP)]) mc.formLayout(rigToRigFL,e=True,af=[(rigToRig_xferHandCBG,'left',5),(rigToRig_xferHandCBG,'right',5)],ac=[(rigToRig_xferHandCBG,'top',5,rigToRig_xferToRBG)]) mc.formLayout(rigToRigFL,e=True,af=[(rigToRig_xferAllTransCBG,'left',5),(rigToRig_xferAllTransCBG,'right',5)],ac=[(rigToRig_xferAllTransCBG,'top',5,rigToRig_xferHandCBG)]) - + # UI Element Callbacks mc.textFieldButtonGrp(rigToRig_srcTFB,e=True,bc='glTools.ui.utils.loadNsSel("'+rigToRig_srcTFB+'",topOnly=False)') mc.textFieldButtonGrp(rigToRig_dstTFB,e=True,bc='glTools.ui.utils.loadNsSel("'+rigToRig_dstTFB+'",topOnly=False)') - + # --------------------- # - Label Layout Tabs - # --------------------- - + mc.tabLayout(tabLayout,e=True,tabLabel=((fromMocapFL,'From Mocap'),(toMocapFL,'To Mocap'),(rigToRigFL,'Rig To Rig'))) - + # ============== # - Display UI - # ============== - + initializeBakeRange() - + mc.window(window,e=True,wh=[445,330]) mc.showWindow(window) @@ -151,7 +151,7 @@ def transferFromUI(): ''' # Get Selected Tab selTab = mc.tabLayout('mocapXferTabLayout',q=True,selectTabIndex=True) - + # Get Bake Range start = mc.intFieldGrp('xferMocap_startEndCBG',q=True,v1=True) end = mc.intFieldGrp('xferMocap_startEndCBG',q=True,v2=True) @@ -159,16 +159,16 @@ def transferFromUI(): if not mc.checkBoxGrp('xferMocap_bakeRangeCBG',q=True,value1=True): start = mc.playbackOptions(q=True,min=True) end = mc.playbackOptions(q=True,max=True) - + # FROM Mocap if selTab == 1: - + # Get Mocap to Rig Input mocapNS = mc.textFieldButtonGrp('fromMocap_mocapTFB',q=True,text=True) rigNS = mc.textFieldButtonGrp('fromMocap_rigTFB',q=True,text=True) toCtrls = mc.radioButtonGrp('fromMocap_xferToRBG',q=True,select=True) == 1 toHands = mc.checkBoxGrp('fromMocap_xferHandCBG',q=True,value1=True) - + # Transfer Mocap to Rig glTools.anim.mocap_utils.transferMocapToRig( mocapNS = mocapNS, rigNS = rigNS, @@ -178,21 +178,21 @@ def transferFromUI(): start = start, end = end, deleteStaticChannels = deleteStaticChannels ) - + if toHands: glTools.anim.mocap_utils.transferHandAnim( mocapNS = mocapNS, rigNS = rigNS, start = start, end = end, deleteStaticChannels = deleteStaticChannels ) - + # TO Mocap elif selTab == 2: - + # Get Anim to Mocap Input rigNS = mc.textFieldButtonGrp('toMocap_rigTFB',q=True,text=True) mocapNS = mc.textFieldButtonGrp('toMocap_mocapTFB',q=True,text=True) - + # Transfer Anim to Mocap glTools.anim.mocap_utils.transferAnimToMocap( rigNS = rigNS, mocapNS = mocapNS, @@ -201,17 +201,17 @@ def transferFromUI(): start = start, end = end, deleteStaticChannels = deleteStaticChannels ) - + # Rig TO Rig elif selTab == 3: - + # Get Anim to Mocap Input srcNS = mc.textFieldButtonGrp('rigToRig_srcTFB',q=True,text=True) dstNS = mc.textFieldButtonGrp('rigToRig_dstTFB',q=True,text=True) toCtrls = mc.radioButtonGrp('rigToRig_xferToRBG',q=True,select=True) == 1 toHands = mc.checkBoxGrp('rigToRig_xferHandCBG',q=True,value1=True) toAllTrans = mc.checkBoxGrp('rigToRig_xferAllTransCBG',q=True,value1=True) - + # Transfer Anim to Mocap glTools.anim.mocap_utils.transferAnimToRig( srcNS = srcNS, dstNS = dstNS, @@ -221,10 +221,10 @@ def transferFromUI(): start = start, end = end, deleteStaticChannels = deleteStaticChannels ) - + # Invalid Tab else: raise Exception('Invalid tab index!') - + # Return Result return @@ -235,7 +235,7 @@ def initializeBakeRange(): start = mc.playbackOptions(q=True,min=True) end = mc.playbackOptions(q=True,max=True) mc.intFieldGrp('xferMocap_startEndCBG',e=True,v1=start,v2=end) - + def toggleBakeRange(): ''' Toggle bake anim range input. diff --git a/ui/nDynamics.py b/ui/nDynamics.py index d3f5d64..fa8ef7e 100644 --- a/ui/nDynamics.py +++ b/ui/nDynamics.py @@ -19,54 +19,54 @@ def create(): win = 'nDynamicsUI' if mc.window(win,ex=True): mc.deleteUI(win) win = mc.window(win,t='nDynamics',s=True,mb=True,wh=[650,390]) - + # --------------- # - Main Window - # --------------- - + # Menu mc.menu(label='Edit',tearOff=1) mc.menuItem(label='Reset',c='glTools.ui.nDynamics.create()') - + # FormLayout FL = mc.formLayout(numberOfDivisions=100) - - # UI Elements + + # UI Elements nucleusTXT = mc.text(l='Nucleus List:',al='left') nucleusTSL = mc.textScrollList('nDyn_nucleusTSL', allowMultiSelection=False ) - + nucleus_createB = mc.button(label='Create', c='glTools.ui.nDynamics.createNucleusFromUI()' ) nucleus_deleteB = mc.button(label='Delete', c='glTools.ui.nDynamics.deleteNucleusFromUI()' ) nucleus_enableB = mc.button(label='Enable', c='glTools.ui.nDynamics.toggleNucleusFromUI(1)' ) nucleus_disableB = mc.button(label='Disable', c='glTools.ui.nDynamics.toggleNucleusFromUI(0)' ) - + nDyn_refreshB = mc.button(label='Refresh', c='glTools.ui.nDynamics.create()' ) nDyn_closeB = mc.button(label='Close', c='mc.deleteUI("'+win+'")' ) - + # TabLayout nDynTabLayout = mc.tabLayout('nDynTabLayout', innerMarginWidth=5, innerMarginHeight=5 ) - + # Layout mc.formLayout(FL,e=True,af=[(nucleusTXT,'left',5),(nucleusTXT,'top',5)],ap=[(nucleusTXT,'right',5,35)]) mc.formLayout(FL,e=True,af=[(nucleusTSL,'left',5)],ap=[(nucleusTSL,'right',5,35)],ac=[(nucleusTSL,'top',5,nucleusTXT),(nucleusTSL,'bottom',5,nucleus_createB)]) - + mc.formLayout(FL,e=True,af=[(nucleus_createB,'left',5)],ap=[(nucleus_createB,'right',5,18)],ac=[(nucleus_createB,'bottom',5,nucleus_enableB)]) mc.formLayout(FL,e=True,ac=[(nucleus_deleteB,'left',5,nucleus_createB),(nucleus_deleteB,'right',5,nDynTabLayout),(nucleus_deleteB,'bottom',5,nucleus_disableB)]) - + mc.formLayout(FL,e=True,af=[(nucleus_enableB,'left',5)],ap=[(nucleus_enableB,'right',5,18)],ac=[(nucleus_enableB,'bottom',5,nDyn_refreshB)]) mc.formLayout(FL,e=True,ac=[(nucleus_disableB,'left',5,nucleus_enableB),(nucleus_disableB,'right',5,nDynTabLayout),(nucleus_disableB,'bottom',5,nDyn_refreshB)]) - + mc.formLayout(FL,e=True,af=[(nDyn_refreshB,'left',5),(nDyn_refreshB,'bottom',5)],ap=[(nDyn_refreshB,'right',5,50)]) mc.formLayout(FL,e=True,af=[(nDyn_closeB,'right',5),(nDyn_closeB,'bottom',5)],ap=[(nDyn_closeB,'left',5,50)]) - + mc.formLayout(FL,e=True,af=[(nDynTabLayout,'top',5),(nDynTabLayout,'right',5)],ac=[(nDynTabLayout,'left',5,nucleusTSL),(nDynTabLayout,'bottom',5,nDyn_closeB)]) - + # UI Callbacks - + mc.textScrollList(nucleusTSL,e=True,sc='glTools.ui.nDynamics.setCurrentNucleus()') mc.textScrollList(nucleusTSL,e=True,dcc='glTools.ui.utils.selectFromTSL("'+nucleusTSL+'")') mc.textScrollList(nucleusTSL,e=True,dkc='glTools.ui.nDynamics.deleteNucleusFromUI()') - + # Popup menu nClothPUM = mc.popupMenu(parent=nucleusTSL) mc.menuItem(l='Select Hilited Nodes',c='glTools.ui.utils.selectFromTSL("'+nucleusTSL+'")') @@ -78,17 +78,17 @@ def create(): mc.menuItem(allowOptionBoxes=False, label='Apply Preset',subMenu=True,tearOff=False) for nucleusPreset in nucleusPresetList: mc.menuItem(l=nucleusPreset,c='glTools.ui.nDynamics.applyPreset("'+nucleusTSL+'","'+nucleusPreset+'")') - + # ----------------- # - nCloth Layout - # ----------------- - + mc.setParent(nDynTabLayout) - + # FormLayout nClothFL = mc.formLayout(numberOfDivisions=100) - - # UI Elements + + # UI Elements nClothVisRB = mc.radioButtonGrp( 'nClothVisRB', cw=[(1,60),(2,60),(3,80)], label='Display:', labelArray2=['All','Current'], numberOfRadioButtons=2, sl=1, cc='glTools.ui.nDynamics.toggleNClothVis()' ) nClothTSL = mc.textScrollList('nDyn_nClothTSL', allowMultiSelection=True ) @@ -99,28 +99,28 @@ def create(): nCloth_disableB = mc.button( label = 'Disable', c='glTools.ui.nDynamics.toggleNClothStateFromUI(0)' ) nCloth_saveCacheB = mc.button( label = 'Save Cache', c='glTools.ui.nDynamics.saveNClothCacheFromUI()' ) nCloth_loadCacheB = mc.button( label = 'Load Cache', c='glTools.ui.nDynamics.loadNClothCacheFromUI()' ) - + # Layout mc.formLayout(nClothFL,e=True,af=[(nClothVisRB,'top',5),(nClothVisRB,'left',5),(nClothVisRB,'right',5)]) mc.formLayout(nClothFL,e=True,af=[(nClothTSL,'left',5),(nClothTSL,'bottom',5)],ap=[(nClothTSL,'right',5,55)],ac=[(nClothTSL,'top',5,nClothVisRB)]) - + mc.formLayout(nClothFL,e=True,af=[(nCloth_createB,'right',5)],ac=[(nCloth_createB,'left',5,nClothTSL),(nCloth_createB,'top',5,nClothVisRB)]) mc.formLayout(nClothFL,e=True,af=[(nCloth_deleteB,'right',5)],ac=[(nCloth_deleteB,'left',5,nClothTSL),(nCloth_deleteB,'top',5,nCloth_createB)]) mc.formLayout(nClothFL,e=True,af=[(nCloth_addToNucleusB,'right',5)],ac=[(nCloth_addToNucleusB,'left',5,nClothTSL),(nCloth_addToNucleusB,'top',5,nCloth_deleteB)]) - + mc.formLayout(nClothFL,e=True,af=[(nCloth_enableB,'right',5)],ac=[(nCloth_enableB,'left',5,nClothTSL),(nCloth_enableB,'top',5,nCloth_addToNucleusB)]) mc.formLayout(nClothFL,e=True,af=[(nCloth_disableB,'right',5)],ac=[(nCloth_disableB,'left',5,nClothTSL),(nCloth_disableB,'top',5,nCloth_enableB)]) - + mc.formLayout(nClothFL,e=True,af=[(nCloth_saveCacheB,'right',5)],ac=[(nCloth_saveCacheB,'left',5,nClothTSL),(nCloth_saveCacheB,'top',5,nCloth_disableB)]) mc.formLayout(nClothFL,e=True,af=[(nCloth_loadCacheB,'right',5)],ac=[(nCloth_loadCacheB,'left',5,nClothTSL),(nCloth_loadCacheB,'top',5,nCloth_saveCacheB)]) - + # UI Callbacks mc.textScrollList(nClothTSL,e=True,dcc='glTools.ui.utils.selectFromTSL("'+nClothTSL+'")') mc.textScrollList(nClothTSL,e=True,dkc='glTools.ui.nDynamics.deleteNClothFromUI()') mc.radioButtonGrp(nClothVisRB,e=True,cc='glTools.ui.nDynamics.refreshNodeList("'+nClothTSL+'","nCloth","'+nClothVisRB+'")') - + mc.setParent('..') - + # Popup menu nClothPUM = mc.popupMenu(parent=nClothTSL) mc.menuItem(l='Select Hilited Nodes',c='glTools.ui.utils.selectFromTSL("'+nClothTSL+'")') @@ -132,45 +132,45 @@ def create(): mc.menuItem(allowOptionBoxes=False, label='Apply Preset',subMenu=True,tearOff=False) for nClothPreset in nClothPresetList: mc.menuItem(l=nClothPreset,c='glTools.ui.nDynamics.applyPreset("'+nClothTSL+'","'+nClothPreset+'")') - + # ----------------- # - nRigid Layout - # ----------------- - + mc.setParent(nDynTabLayout) - + # FormLayout nRigidFL = mc.formLayout(numberOfDivisions=100) - - # UI Elements + + # UI Elements nRigidVisRB = mc.radioButtonGrp( 'nRigidVisRB', cw=[(1,60),(2,60),(3,80)], label='Display:', labelArray2=['All','Current'], numberOfRadioButtons=2, sl=1, cc='glTools.ui.nDynamics.toggleNClothVis()' ) nRigidTSL = mc.textScrollList('nDyn_nRigidTSL', allowMultiSelection=True ) nRigid_createB = mc.button( label = 'Create from Mesh', c='glTools.ui.nDynamics.createNRigidFromUI()' ) nRigid_deleteB = mc.button( label = 'Delete Selected', c='glTools.ui.nDynamics.deleteNRigidFromUI()' ) nRigid_addToNucleusB = mc.button( label = 'Add to Nucleus', c='glTools.ui.nDynamics.addNRigidToNucleusFromUI()' ) - + nRigid_enableB = mc.button( label = 'Enable', c='glTools.ui.nDynamics.toggleNRigidStateFromUI(1)' ) nRigid_disableB = mc.button( label = 'Disable', c='glTools.ui.nDynamics.toggleNRigidStateFromUI(0)' ) - + # Layout mc.formLayout(nRigidFL,e=True,af=[(nRigidVisRB,'top',5),(nRigidVisRB,'left',5),(nRigidVisRB,'right',5)]) mc.formLayout(nRigidFL,e=True,af=[(nRigidTSL,'left',5),(nRigidTSL,'bottom',5)],ap=[(nRigidTSL,'right',5,55)],ac=[(nRigidTSL,'top',5,nRigidVisRB)]) - + mc.formLayout(nRigidFL,e=True,af=[(nRigid_createB,'right',5)],ac=[(nRigid_createB,'left',5,nRigidTSL),(nRigid_createB,'top',5,nRigidVisRB)]) mc.formLayout(nRigidFL,e=True,af=[(nRigid_deleteB,'right',5)],ac=[(nRigid_deleteB,'left',5,nRigidTSL),(nRigid_deleteB,'top',5,nRigid_createB)]) mc.formLayout(nRigidFL,e=True,af=[(nRigid_addToNucleusB,'right',5)],ac=[(nRigid_addToNucleusB,'left',5,nRigidTSL),(nRigid_addToNucleusB,'top',5,nRigid_deleteB)]) - + mc.formLayout(nRigidFL,e=True,af=[(nRigid_enableB,'right',5)],ac=[(nRigid_enableB,'left',5,nRigidTSL),(nRigid_enableB,'top',5,nRigid_addToNucleusB)]) mc.formLayout(nRigidFL,e=True,af=[(nRigid_disableB,'right',5)],ac=[(nRigid_disableB,'left',5,nRigidTSL),(nRigid_disableB,'top',5,nRigid_enableB)]) - + # UI Callbacks mc.textScrollList(nRigidTSL,e=True,dcc='glTools.ui.utils.selectFromTSL("'+nRigidTSL+'")') mc.textScrollList(nRigidTSL,e=True,dkc='glTools.ui.nDynamics.deleteNRigidFromUI()') mc.radioButtonGrp(nRigidVisRB,e=True,cc='glTools.ui.nDynamics.refreshNodeList("'+nRigidTSL+'","nRigid","'+nRigidVisRB+'")') - + mc.setParent('..') - + # Popup menu nRigidPUM = mc.popupMenu(parent=nRigidTSL) mc.menuItem(l='Select Hilited Nodes',c='glTools.ui.utils.selectFromTSL("'+nRigidTSL+'")') @@ -182,39 +182,39 @@ def create(): mc.menuItem(allowOptionBoxes=False, label='Apply Preset',subMenu=True,tearOff=False) for nRigidPreset in nRigidPresetList: mc.menuItem(l=nRigidPreset,c='glTools.ui.nDynamics.applyPreset("'+nRigidTSL+'","'+nRigidPreset+'")') - + # -------------------- # - nParticle Layout - # -------------------- - + mc.setParent(nDynTabLayout) - + # FormLayout nParticleFL = mc.formLayout(numberOfDivisions=100) - - # UI Elements + + # UI Elements nParticleVisRB = mc.radioButtonGrp( 'nParticleVisRB', cw=[(1,60),(2,60),(3,80)], label='Display:', labelArray2=['All','Current'], numberOfRadioButtons=2, sl=1, cc='glTools.ui.nDynamics.toggleNClothVis()' ) nParticleTSL = mc.textScrollList('nDyn_nParticleTSL', allowMultiSelection=True ) nParticle_createB = mc.button( label = 'Fill Mesh', c='glTools.ui.nDynamics.createNParticleFromUI()' ) nParticle_deleteB = mc.button( label = 'Delete Selected', c='glTools.ui.nDynamics.deleteNParticleFromUI()' ) nParticle_addToNucleusB = mc.button( label = 'Add to Nucleus', c='glTools.ui.nDynamics.addNParticleToNucleusFromUI()' ) - + # Layout mc.formLayout(nParticleFL,e=True,af=[(nParticleVisRB,'top',5),(nParticleVisRB,'left',5),(nParticleVisRB,'right',5)]) mc.formLayout(nParticleFL,e=True,af=[(nParticleTSL,'left',5),(nParticleTSL,'bottom',5)],ap=[(nParticleTSL,'right',5,55)],ac=[(nParticleTSL,'top',5,nParticleVisRB)]) - + mc.formLayout(nParticleFL,e=True,af=[(nParticle_createB,'right',5)],ac=[(nParticle_createB,'left',5,nParticleTSL),(nParticle_createB,'top',5,nParticleVisRB)]) mc.formLayout(nParticleFL,e=True,af=[(nParticle_deleteB,'right',5)],ac=[(nParticle_deleteB,'left',5,nParticleTSL),(nParticle_deleteB,'top',5,nParticle_createB)]) mc.formLayout(nParticleFL,e=True,af=[(nParticle_addToNucleusB,'right',5)],ac=[(nParticle_addToNucleusB,'left',5,nParticleTSL),(nParticle_addToNucleusB,'top',5,nParticle_deleteB)]) - + # UI Callbacks mc.textScrollList(nParticleTSL,e=True,dcc='glTools.ui.utils.selectFromTSL("'+nParticleTSL+'")') mc.textScrollList(nParticleTSL,e=True,dkc='glTools.ui.nDynamics.deleteNParticleFromUI()') mc.radioButtonGrp(nParticleVisRB,e=True,cc='glTools.ui.nDynamics.refreshNodeList("'+nParticleTSL+'","nParticle","'+nParticleVisRB+'")') - + mc.setParent('..') - + # Popup menu nParticlePUM = mc.popupMenu(parent=nParticleTSL) mc.menuItem(l='Select Hilited Nodes',c='glTools.ui.utils.selectFromTSL("'+nParticleTSL+'")') @@ -226,26 +226,26 @@ def create(): mc.menuItem(allowOptionBoxes=False, label='Apply Preset',subMenu=True,tearOff=False) for nParticlePreset in nParticlePresetList: mc.menuItem(l=nParticlePreset,c='glTools.ui.nDynamics.applyPreset("'+nParticleTSL+'","'+nParticlePreset+'")') - + # ----------------- # - nCache Layout - # ----------------- - + mc.setParent(nDynTabLayout) - + # FormLayout nCacheFL = mc.formLayout(numberOfDivisions=100) - + mc.setParent('..') - + # -------------- # - End Layout - # -------------- - + # Set TabLayout Labels mc.tabLayout( nDynTabLayout,e=True,tabLabel=((nClothFL,'nCloth'),(nRigidFL,'nRigid'),(nParticleFL,'nParticle'),(nCacheFL,'nCache')) ) - - # Display UI + + # Display UI mc.showWindow(win) refreshUI() @@ -262,19 +262,19 @@ def refreshUI(): ''' # Check UI checkUI() - + # Resize UI - force refresh elements win = 'nDynamicsUI' [w,h] = mc.window(win,q=True,wh=True) mc.window(win,e=True,wh=[w+1,h+1]) mc.window(win,e=True,wh=[w,h]) - + # Refresh UI Elements refreshNodeList('nDyn_nucleusTSL','nucleus') refreshNodeList('nDyn_nClothTSL','nCloth','nClothVisRB') refreshNodeList('nDyn_nRigidTSL','nRigid','nRigidVisRB') refreshNodeList('nDyn_nParticleTSL','nParticle','nParticleVisRB') - + def refreshNodeList(TSL,nodeType,RB=''): ''' Refresh the nucleus node textScrollList @@ -285,18 +285,18 @@ def refreshNodeList(TSL,nodeType,RB=''): ''' # Check UI checkUI() - + # Check visibility mode # - Value is 1 based, subtract 1 to get 0 or 1 value visMode = 0 if RB: visMode = mc.radioButtonGrp(RB,q=True,sl=True) - 1 - + # Get current nucleus nucleus = mc.textScrollList('nDyn_nucleusTSL',q=True,si=True) - + # Clear textScrollList mc.textScrollList(TSL,e=True,ra=True) - + # Check visibility if visMode and nucleus: # Get connected nDynamics nodes @@ -304,13 +304,13 @@ def refreshNodeList(TSL,nodeType,RB=''): else: # Get all existing nDynamics nodes nNodeList = mc.ls(type=nodeType) - + # Sort list nNodeList.sort() - + # Refresh List for node in nNodeList: mc.textScrollList(TSL,e=True,a=node) - + # Update current nucleus if nodeType == 'nucleus': nucleus = glTools.utils.nDynamics.getActiveNucleus() @@ -327,10 +327,10 @@ def setCurrentNucleus(): nucleus = mc.textScrollList('nDyn_nucleusTSL',q=True,si=True) if not nucleus: nucleus = glTools.utils.nDynamics.getActiveNucleus() else: nucleus = nucleus[0] - + # Set active nucleus glTools.utils.nDynamics.setActiveNucleus(nucleus) - + # Refresh UI Elements refreshNodeList('nDyn_nClothTSL','nCloth','nClothVisRB') refreshNodeList('nDyn_nRigidTSL','nRigid','nRigidVisRB') @@ -346,7 +346,7 @@ def applyPreset(TSL,preset): ''' # Get node list nodeList = mc.textScrollList(TSL,q=True,si=True) - + # Apply Preset glTools.utils.attrPreset.apply(nodeList,preset,1.0) @@ -358,22 +358,22 @@ def selectConnectedSolver(TSL): ''' # Get node list nodeList = mc.textScrollList(TSL,q=True,si=True) - + # Get list of connected nucleus nucleusList = [] for node in nodeList: nucleus = glTools.utils.nDynamics.getConnectedNucleus(node) if nucleus: nucleusList.append(nucleus) - + # Select connected nucleus mc.select(nucleusList) - + # Hilite items in nucleus textScrollList nucleusItemList = mc.textScrollList('nDyn_nucleusTSL',q=True,ai=True) nucleusList = [n for n in nucleusList if nucleusItemList.count(n)] mc.textScrollList('nDyn_nucleusTSL',e=True,da=True) mc.textScrollList('nDyn_nucleusTSL',e=True,si=nucleusList) - + # Return result return nucleusList @@ -385,16 +385,16 @@ def selectConnectedMesh(TSL): ''' # Get node list nodeList = mc.textScrollList(TSL,q=True,si=True) - + # Get list of connected meshes meshList = [] for node in nodeList: mesh = glTools.utils.nDynamics.getConnectedMesh(node,returnShape=False) if mesh: meshList.append(mesh) - + # Select connected meshes mc.select(meshList) - + # Return result return meshList @@ -407,10 +407,10 @@ def createNucleusFromUI(): ''' # Check UI checkUI() - + # Create nucleus nucleus = glTools.utils.nDynamics.createNucleus('') - + # Set as current refreshNodeList('nDyn_nucleusTSL','nucleus') @@ -420,19 +420,19 @@ def deleteNucleusFromUI(): # Check UI checkUI() tsl = 'nDyn_nucleusTSL' - + # Get selected nucleus nodeSel = mc.textScrollList(tsl,q=True,si=True) if not nodeSel: return - + # Check current nucleus for node in nodeSel: if not mc.objExists(node): raise Exception('Nucleus node "'+node+'" does not exist!') - + # Select nucleus mc.delete(nodeSel) - + # Refresh Nucleus List refreshNodeList(tsl,'nucleus') @@ -442,20 +442,20 @@ def toggleNucleusFromUI(state): # Check UI checkUI() nucleus_tsl = 'nDyn_nucleusTSL' - + # Get selected nucleus nucleusSel = mc.textScrollList(nucleus_tsl,q=True,si=True) if not nucleusSel: raise Exception('No valid nucleus node selected!') - + # Enable/Disable nucleus nodes for nucleus in nucleusSel: mc.setAttr(nucleus+'.enable',state) - + # ==================== # - nCloth functions - # ==================== - + def createNClothFromUI(): ''' ''' @@ -463,7 +463,7 @@ def createNClothFromUI(): checkUI() nucleus_tsl = 'nDyn_nucleusTSL' nCloth_tsl = 'nDyn_nClothTSL' - + # Get selected mesh objSel = mc.ls(sl=1) if not objSel: @@ -471,18 +471,18 @@ def createNClothFromUI(): meshList = [obj for obj in objSel if glTools.utils.mesh.isMesh(obj)] if not meshList: raise Exception('No valid mesh in selection!') - + # Get selected nucleus nucleusSel = mc.textScrollList(nucleus_tsl,q=True,si=True) if not nucleusSel: raise Exception('No valid nucleus node selected!') nucleus = nucleusSel[0] - + # Create nCloth # !!!!!!!!!!!! Always in Local Space until option is added!!!!!!!!!!! for mesh in meshList: glTools.utils.nDynamics.createNCloth(mesh,nucleus,worldSpace=False,prefix='') - + # Refresh UI refreshNodeList(nCloth_tsl,'nCloth') refreshNodeList(nucleus_tsl,'nucleus') @@ -493,19 +493,19 @@ def deleteNClothFromUI(): # Check UI checkUI() tsl = 'nDyn_nClothTSL' - + # Get nCloth selection nClothSel = mc.textScrollList(tsl,q=True,si=True) if not nClothSel: raise Exception('No nCloth specified!') - + # Delete nCloth for nCloth in nClothSel: glTools.utils.nDynamics.deleteNCloth(nCloth) - + # Refresh UI refreshNodeList(tsl,'nCloth') - + def addNClothToNucleusFromUI(): ''' ''' @@ -513,18 +513,18 @@ def addNClothToNucleusFromUI(): checkUI() nucleus_tsl = 'nDyn_nucleusTSL' nCloth_tsl = 'nDyn_nClothTSL' - + # Get selected nucleus nucleusSel = mc.textScrollList(nucleus_tsl,q=True,si=True) if not nucleusSel: raise Exception('No valid nucleus node selected!') nucleus = nucleusSel[0] - + # Get selected nCloth nClothSel = mc.textScrollList(nCloth_tsl,q=True,si=True) if not nClothSel: raise Exception('No nCloth specified!') - + # Connect to nucleus for nCloth in nClothSel: #glTools.utils.nDynamics.connect_nClothToNucleus(nCloth,nucleus) @@ -536,11 +536,11 @@ def toggleNClothStateFromUI(state): # Check UI checkUI() tsl = 'nDyn_nClothTSL' - + # Get selected nucleus nClothSel = mc.textScrollList(tsl,q=True,si=True) if not nClothSel: raise Exception('No valid nCloth node selected!') - + # Enable/Disable nCloth nodes for nCloth in nClothSel: mc.setAttr(nCloth+'.isDynamic',state) @@ -573,7 +573,7 @@ def createNRigidFromUI(): checkUI() nucleus_tsl = 'nDyn_nucleusTSL' nRigid_tsl = 'nDyn_nRigidTSL' - + # Get selected mesh objSel = mc.ls(sl=1) if not objSel: @@ -581,21 +581,21 @@ def createNRigidFromUI(): meshList = [obj for obj in objSel if glTools.utils.mesh.isMesh(obj)] if not meshList: raise Exception('No valid mesh in selection!') - + # Get selected nucleus nucleusSel = mc.textScrollList(nucleus_tsl,q=True,si=True) if not nucleusSel: raise Exception('No valid nucleus node selected!') nucleus = nucleusSel[0] - + # Create nRigid for mesh in meshList: glTools.utils.nDynamics.createNRigid(mesh,nucleus) - + # Refresh UI refreshNodeList(nRigid_tsl,'nRigid') refreshNodeList(nucleus_tsl,'nucleus') - + def deleteNRigidFromUI(): ''' ''' @@ -603,17 +603,17 @@ def deleteNRigidFromUI(): checkUI() nucleus_tsl = 'nDyn_nucleusTSL' nRigid_tsl = 'nDyn_nRigidTSL' - + # Get selected nRigid nodes nRigidSel = mc.textScrollList(nRigid_tsl,q=True,si=True) - + # Delete nRigid nodes for nRigid in nRigidSel: glTools.utils.nDynamics.deleteNCloth(nRigid) - + # Refresh UI refreshNodeList(nRigid_tsl,'nRigid') - + def addNRigidToNucleusFromUI(): ''' ''' @@ -621,34 +621,34 @@ def addNRigidToNucleusFromUI(): checkUI() nucleus_tsl = 'nDyn_nucleusTSL' nRigid_tsl = 'nDyn_nRigidTSL' - + # Get selected nucleus nucleusSel = mc.textScrollList(nucleus_tsl,q=True,si=True) if not nucleusSel: raise Exception('No valid nucleus node selected!') nucleus = nucleusSel[0] - + # Get selected nRigid nRigidSel = mc.textScrollList(nRigid_tsl,q=True,si=True) if not nRigidSel: raise Exception('No nCloth specified!') - + # Connect to nucleus for nRigid in nRigidSel: #glTools.utils.nDynamics.connect_nRigidToNucleus(nRigid,nucleus) glTools.utils.nDynamics.connectToNucleus(nRigid,nucleus) - + def toggleNRigidStateFromUI(state): ''' ''' # Check UI checkUI() tsl = 'nDyn_nRigidTSL' - + # Get selected nucleus nRigidSel = mc.textScrollList(tsl,q=True,si=True) if not nRigidSel: raise Exception('No valid nCloth node selected!') - + # Enable/Disable nCloth nodes for nRigid in nRigidSel: mc.setAttr(nRigid+'.isDynamic',state) diff --git a/ui/poseMatch.py b/ui/poseMatch.py index 47107f7..c379945 100644 --- a/ui/poseMatch.py +++ b/ui/poseMatch.py @@ -16,10 +16,10 @@ def evaluationOrderUI(): win = mc.window(win,t='Evaluation Order') # Form Layout evaluationOrderFL = mc.formLayout(numberOfDivisions=100) - + # Evaluation Order List evalOrderTSL = mc.textScrollList('evalOrderTSL',allowMultiSelection=True) - + # Buttons evalOrderRootB = mc.button(label='Set Selected As Root',c='glTools.ui.poseMatch.evalOrderUIsetRoot()') evalOrderBuildB = mc.button(label='Build Root Hierarchy',c='glTools.ui.poseMatch.evalOrderUIbuildHierarchy()') @@ -30,13 +30,13 @@ def evaluationOrderUI(): evalOrderMoveDnB = mc.button(label='Move Down',c='glTools.ui.utils.moveDownTSLPosition("'+evalOrderTSL+'")') evalOrderMoveToBottomB = mc.button(label='Move To Bottom',c='glTools.ui.utils.moveToTSLPosition("'+evalOrderTSL+'",-1)') evalOrderAddAttrB = mc.button(label='Add "evalOrder" attribute',c='glTools.ui.poseMatch.evalOrderUIaddAttr()') - + # Separators evalOrderReorderSEP = mc.separator(h=10,style='single') evalOrderReduceSEP = mc.separator(h=10,style='single') evalOrderMoveSEP = mc.separator(h=10,style='single') evalOrderAddAttrSEP = mc.separator(h=10,style='single') - + # Form Layout - MAIM #- # evalOrderTSL @@ -49,11 +49,11 @@ def evaluationOrderUI(): mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderBuildB,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderBuildB,'top',5,evalOrderRootB)]) mc.formLayout(evaluationOrderFL,e=True,ap=[(evalOrderBuildB,'left',5,50)]) - + mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderReorderSEP,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderReorderSEP,'top',5,evalOrderBuildB)]) mc.formLayout(evaluationOrderFL,e=True,ap=[(evalOrderReorderSEP,'left',5,50)]) - + # evalOrderIKB mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderIKB,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderIKB,'top',5,evalOrderReorderSEP)]) @@ -62,20 +62,20 @@ def evaluationOrderUI(): mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderConstraintB,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderConstraintB,'top',5,evalOrderIKB)]) mc.formLayout(evaluationOrderFL,e=True,ap=[(evalOrderConstraintB,'left',5,50)]) - + mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderReduceSEP,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderReduceSEP,'top',5,evalOrderConstraintB)]) mc.formLayout(evaluationOrderFL,e=True,ap=[(evalOrderReduceSEP,'left',5,50)]) - + # evalOrderReduceB mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderReduceB,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderReduceB,'top',5,evalOrderReduceSEP)]) mc.formLayout(evaluationOrderFL,e=True,ap=[(evalOrderReduceB,'left',5,50)]) - + mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderMoveSEP,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderMoveSEP,'top',5,evalOrderReduceB)]) mc.formLayout(evaluationOrderFL,e=True,ap=[(evalOrderMoveSEP,'left',5,50)]) - + # evalOrderMoveUpB mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderMoveUpB,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderMoveUpB,'top',5,evalOrderMoveSEP)]) @@ -88,19 +88,19 @@ def evaluationOrderUI(): mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderMoveToBottomB,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderMoveToBottomB,'top',5,evalOrderMoveDnB)]) mc.formLayout(evaluationOrderFL,e=True,ap=[(evalOrderMoveToBottomB,'left',5,50)]) - + mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderAddAttrSEP,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderAddAttrSEP,'top',5,evalOrderMoveToBottomB)]) mc.formLayout(evaluationOrderFL,e=True,ap=[(evalOrderAddAttrSEP,'left',5,50)]) - + # evalOrderAddAttrB mc.formLayout(evaluationOrderFL,e=True,af=[(evalOrderAddAttrB,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(evalOrderAddAttrB,'top',5,evalOrderAddAttrSEP)]) mc.formLayout(evaluationOrderFL,e=True,ap=[(evalOrderAddAttrB,'left',5,50)]) - + # Show Window mc.showWindow(win) - + def evalOrderUIrefreshList(evalOrderList=[]): ''' UI method for Evaluation Order setup tools @@ -121,11 +121,11 @@ def evalOrderUIsetRoot(): win = 'evaluationOrderUI' if not mc.window(win,q=True,ex=True): raise UserInputError('Evaluation Order UI is not open!!') - + # Get Selection sel = mc.ls(sl=True,type='transform') if not sel: return - + # Add first selected item as root of evaluation order list mc.textScrollList('evalOrderTSL',e=True,ra=True) mc.textScrollList('evalOrderTSL',e=True,a=sel[0]) @@ -136,37 +136,37 @@ def evalOrderUIbuildHierarchy(): Build evaluation order list from hierarchy root object ''' global gEvalOrder - + # Check window win = 'evaluationOrderUI' if not mc.window(win,q=True,ex=True): raise UserInputError('Evaluation Order UI is not open!!') - + # Get root object rootList = mc.textScrollList('evalOrderTSL',q=True,ai=True) if not rootList: raise UserInputError('Specify a hierarchy root!') - + # Build hierarchy list gEvalOrder = glTools.tools.evaluationOrder.EvaluationOrder(rootList[0],debug=True) - + # Display evaluation order list in UI evalOrderUIrefreshList() - + def evalOrderUIreorderIK(): ''' UI method for Evaluation Order setup tools Reorder the evaluation order based on IK dependencies ''' global gEvalOrder - + # Check window win = 'evaluationOrderUI' if not mc.window(win,q=True,ex=True): raise UserInputError('Evaluation Order UI is not open!!') - + # Reorder using IK gEvalOrder.ikReorder() - + # Display evaluation order list in UI evalOrderUIrefreshList() @@ -176,15 +176,15 @@ def evalOrderUIreorderConstraints(): Reorder the evaluation order based on constraint dependencies ''' global gEvalOrder - + # Check window win = 'evaluationOrderUI' if not mc.window(win,q=True,ex=True): raise UserInputError('Evaluation Order UI is not open!!') - + # Reorder using IK gEvalOrder.constraintReorder() - + # Display evaluation order list in UI evalOrderUIrefreshList() @@ -194,20 +194,20 @@ def evalOrderUIreduceToSelection(): Reduce the evaluation order list to the selected objects ''' global gEvalOrder - + # Check window win = 'evaluationOrderUI' if not mc.window(win,q=True,ex=True): raise UserInputError('Evaluation Order UI is not open!!') - + # Get selection sel = mc.ls(sl=True) if not sel: return - + # Get evalOrder list evalOrderList = gEvalOrder.hierarchy.generationList() evalIntersectList = [i for i in evalOrderList if sel.count(i)] - + # Display evaluation order list in UI evalOrderUIrefreshList(evalIntersectList) @@ -217,22 +217,22 @@ def evalOrderUIaddAttr(): Add the evaluation order list as an attribute to the root object ''' global gEvalOrder - + # Check window win = 'evaluationOrderUI' if not mc.window(win,q=True,ex=True): raise UserInputError('Evaluation Order UI is not open!!') - + # Get evaluation order list evalOrderList = gEvalOrder.hierarchy.generationList() if not evalOrderList: raise UserInputError('Evaluation order list invalid!!') # Determine hierarchy root evalOrderRoot = evalOrderList[0] - + # Get intersectionList intersectList = mc.textScrollList('evalOrderTSL',q=True,ai=True) if not intersectList: return - + # Add list attribute to root object gEvalOrder.setAttr(evalOrderRoot,intersectList=intersectList,evalOrderList=evalOrderList) @@ -244,38 +244,38 @@ def matchRulesUI(): win = 'matchRulesUI' if mc.window(win,q=True,ex=True): mc.deleteUI(win) win = mc.window(win,t='Pose Match Rules') - + # Form Layout evaluationOrderFL = mc.formLayout(numberOfDivisions=100) - + # Pivot Object pivotTFB = mc.textFieldButtonGrp('matchRulesPivotTFB',label='Pivot Object',text='',buttonLabel='Load Selected') - + # Mirror Axis axisList = ['X','Y','Z'] axisOMG = mc.optionMenuGrp('matchRulesAxisOMG',label='Mirror Axis') for axis in axisList: mc.menuItem(label=axis) - + # Mirror Mode modeList = ['World','Local'] modeOMG = mc.optionMenuGrp('matchRulesModeOMG',label='Mirror Mode') for mode in modeList: mc.menuItem(label=mode) - + # Search/Replace Field searchTFG = mc.textFieldGrp('matchRulesSearchTFG',label='Search',text='lf_') replaceTFG = mc.textFieldGrp('matchRulesReplaceTFG',label='Replace',text='rt_') - + # Separator sep = mc.separator(height=10,style='single') - + # Buttons twinMatchB = mc.button('matchRulesTwinMatchB',l='Setup Twin Match',c='glTools.ui.poseMatch.setTwinMatchAttrsFromUI()') selfPivotB = mc.button('matchRulesSelfPivotB',l='Setup Self Pivot',c='glTools.ui.poseMatch.setSelfPivotAttrsFromUI()') closeB = mc.button('matchRulesCloseB',l='Close',c='mc.deleteUI("'+win+'")') - + # UI Callbacks mc.textFieldButtonGrp(pivotTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+pivotTFB+'","","transform")') - + # Form Layout - MAIN mc.formLayout(evaluationOrderFL,e=True,af=[(pivotTFB,'left',5),(pivotTFB,'top',5),(pivotTFB,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,af=[(axisOMG,'left',5),(axisOMG,'right',5)]) @@ -294,10 +294,10 @@ def matchRulesUI(): mc.formLayout(evaluationOrderFL,e=True,ac=[(selfPivotB,'top',5,sep)]) mc.formLayout(evaluationOrderFL,e=True,af=[(closeB,'left',5),(closeB,'right',5)]) mc.formLayout(evaluationOrderFL,e=True,ac=[(closeB,'top',5,selfPivotB)]) - + # Show Window mc.showWindow(win) - + def setTwinMatchAttrsFromUI(): ''' UI method for Pose Match setup tools @@ -306,27 +306,27 @@ def setTwinMatchAttrsFromUI(): # Get selection sel = mc.ls(sl=True,type=['transform','joint']) if not sel: return - + # Window win = 'matchRulesUI' if not mc.window(win,q=True,ex=True): raise UserInputError('Pose Match UI does not exist!!') - + # Pivot pivotObj = str(mc.textFieldButtonGrp('matchRulesPivotTFB',q=True,text=True)) - + # Axis axis = str(mc.optionMenuGrp('matchRulesAxisOMG',q=True,v=True)).lower() - + # Mode mode = mc.optionMenuGrp('matchRulesModeOMG',q=True,sl=True) - 1 - + # Search/Replace search = str(mc.textFieldGrp('matchRulesSearchTFG',q=True,text=True)) replace = str(mc.textFieldGrp('matchRulesReplaceTFG',q=True,text=True)) - + # Set match rules attributes glTools.tools.match.Match().setTwinMatchAttrs(sel,pivotObj,axis,mode,search,replace) - + def setSelfPivotAttrsFromUI(): ''' UI method for Pose Match setup tools @@ -335,16 +335,16 @@ def setSelfPivotAttrsFromUI(): # Get selection sel = mc.ls(sl=True,type=['transform','joint']) if not sel: return - + # Window win = 'matchRulesUI' if not mc.window(win,q=True,ex=True): raise UserInputError('Pose Match UI does not exist!!') - + # Axis axis = str(mc.optionMenuGrp('matchRulesAxisOMG',q=True,v=True)).lower() - + # Mode mode = mc.optionMenuGrp('matchRulesModeOMG',q=True,sl=True) - 1 - + # Set match rules attributes glTools.tools.match.Match().setSelfPivotAttrs(sel,axis,mode) diff --git a/ui/replaceGeometry.py b/ui/replaceGeometry.py index 178042f..715cee3 100644 --- a/ui/replaceGeometry.py +++ b/ui/replaceGeometry.py @@ -10,6 +10,6 @@ def replaceGeometryFromUI(): if len(sel) != 2: print('Incorrect selection! First select the replacement geometry and then the geometry to be replaced!!') return - + # Replace geometry glTools.utils.geometry.replace(sel[0],sel[1]) diff --git a/ui/skinCluster.py b/ui/skinCluster.py index d75ec06..edb02fb 100644 --- a/ui/skinCluster.py +++ b/ui/skinCluster.py @@ -13,27 +13,27 @@ def makeRelativeUI(): win = mc.window(win,t='SkinCluster - Make Relative') # Form Layout makeRelativeFL = mc.formLayout(numberOfDivisions=100) - + # SkinCluster option menu skinClusterOMG = mc.optionMenuGrp('makeRelativeSkinClusterOMG',label='SkinCluster') for skin in mc.ls(type='skinCluster'): mc.menuItem(label=skin) - + # Relative To TextField makeRelativeTFB = mc.textFieldButtonGrp('makeRelativeToTFB',label='RelativeTo',text='',buttonLabel='Load Selected') - + # Button makeRelativeBTN = mc.button(l='Make Relative',c='glTools.ui.skinCluster.makeRelativeFromUI()') - + # UI Callbacks mc.textFieldButtonGrp(makeRelativeTFB,e=True,bc='glTools.ui.utils.loadTypeSel("'+makeRelativeTFB+'","transform")') - + # Form Layout - MAIN mc.formLayout(makeRelativeFL,e=True,af=[(skinClusterOMG,'left',5),(skinClusterOMG,'top',5),(skinClusterOMG,'right',5)]) mc.formLayout(makeRelativeFL,e=True,af=[(makeRelativeTFB,'left',5),(makeRelativeTFB,'right',5)]) mc.formLayout(makeRelativeFL,e=True,ac=[(makeRelativeTFB,'top',5,skinClusterOMG)]) mc.formLayout(makeRelativeFL,e=True,af=[(makeRelativeBTN,'left',5),(makeRelativeBTN,'right',5),(makeRelativeBTN,'bottom',5)]) mc.formLayout(makeRelativeFL,e=True,ac=[(makeRelativeBTN,'top',5,makeRelativeTFB)]) - + # Open window mc.showWindow(win) diff --git a/ui/skinClusterData.py b/ui/skinClusterData.py index 76f2a21..b170d25 100644 --- a/ui/skinClusterData.py +++ b/ui/skinClusterData.py @@ -14,39 +14,39 @@ def skinClusterDataUI(): win = 'skinClusterDataUI' if mc.window(win,q=True,ex=True): mc.deleteUI(win) win = mc.window(win,t='SkinClusterData') - + # =============== # - UI Elements - # =============== - + cw1=(1,120) - + # Form Layout mainFL = mc.formLayout(numberOfDivisions=100) - + # Load/Buld Buttons loadB = mc.button(label='Load Data...',c='glTools.ui.skinClusterData.loadData()') buildB = mc.button(label='Build Data (from selected)',c='glTools.ui.skinClusterData.buildData()') rebuildB = mc.button(label='Rebuild SkinCluster',c='glTools.ui.skinClusterData.rebuildSkinCluster()') saveB = mc.button(label='Save Data',c='glTools.ui.skinClusterData.saveData()') closeB = mc.button(label='Close',c='mc.deleteUI("'+win+'")') - + # Scroll Layout scrollLayout = mc.scrollLayout(horizontalScrollBarThickness=16,verticalScrollBarThickness=16,cr=1) - + # SkinCluster Name skinClusterNameTFG = mc.textFieldGrp('skinCluster_nameTFG',label='SkinCluster',text='',cw=cw1) - + # Scroll FL scrollFL = mc.formLayout(numberOfDivisions=100) - + # ============== # - Basic Data - # ============== - + basicDataFRL = mc.frameLayout(label='SkinCluster Data',collapsable=True,p=scrollFL) basicDataFL = mc.formLayout(numberOfDivisions=100) - + # Affected Geometry skinClusterGeoTFB = mc.textFieldButtonGrp('skinCluster_geoTFB',label='Geometry',text='',editable=False,buttonLabel='Remap',cw=cw1) skinClusterMethodOMG = mc.optionMenuGrp('skinCluster_methodOMG',label='Skinning Method',cw=cw1) @@ -59,64 +59,64 @@ def skinClusterDataUI(): mc.menuItem('Interactive') mc.menuItem('Post') skinClusterDeformNormCBG = mc.checkBoxGrp('skinCluster_deformNormCBG',label='Deform User Normals',cw=cw1) - + mc.formLayout(basicDataFL,e=True,af=[(skinClusterGeoTFB,'top',5),(skinClusterGeoTFB,'left',5),(skinClusterGeoTFB,'right',5)]) mc.formLayout(basicDataFL,e=True,ac=[(skinClusterMethodOMG,'top',5,skinClusterGeoTFB)],af=[(skinClusterMethodOMG,'left',5),(skinClusterMethodOMG,'right',5)]) mc.formLayout(basicDataFL,e=True,ac=[(skinClusterComponentCBG,'top',5,skinClusterMethodOMG)],af=[(skinClusterComponentCBG,'left',5),(skinClusterComponentCBG,'right',5)]) mc.formLayout(basicDataFL,e=True,ac=[(skinClusterNormalizeOMG,'top',5,skinClusterComponentCBG)],af=[(skinClusterNormalizeOMG,'left',5),(skinClusterNormalizeOMG,'right',5)]) mc.formLayout(basicDataFL,e=True,ac=[(skinClusterDeformNormCBG,'top',5,skinClusterNormalizeOMG)],af=[(skinClusterDeformNormCBG,'left',5),(skinClusterDeformNormCBG,'right',5)]) - + # ================== # - Influence Data - # ================== - + influenceDataFRL = mc.frameLayout(label='Influence Data',collapsable=True,p=scrollFL) influenceDataFL = mc.formLayout(numberOfDivisions=100) - + skinCluster_infTXT = mc.text( label='Influence List' ) skinCluster_infTSL = mc.textScrollList('skinCluster_infTSL',numberOfRows=15,allowMultiSelection=True) skinCluster_wtTXT = mc.text( label='Influence Weights' ) skinCluster_wtTSL = mc.textScrollList('skinCluster_wtTSL',numberOfRows=15,allowMultiSelection=True) - + mc.formLayout(influenceDataFL,e=True,af=[(skinCluster_infTXT,'top',5),(skinCluster_infTXT,'left',5),(skinCluster_infTXT,'right',5)]) mc.formLayout(influenceDataFL,e=True,ac=[(skinCluster_infTSL,'top',5,skinCluster_infTXT)],af=[(skinCluster_infTSL,'left',5),(skinCluster_infTSL,'right',5)]) mc.formLayout(influenceDataFL,e=True,ac=[(skinCluster_wtTXT,'top',5,skinCluster_infTSL)],af=[(skinCluster_wtTXT,'left',5),(skinCluster_wtTXT,'right',5)]) mc.formLayout(influenceDataFL,e=True,ac=[(skinCluster_wtTSL,'top',5,skinCluster_wtTXT)],af=[(skinCluster_wtTSL,'left',5),(skinCluster_wtTSL,'right',5)]) - + # ==================== # - World Space Data - # ==================== - + worldSpaceDataFRL = mc.frameLayout(label='World Space Data',collapsable=True,p=scrollFL) worldSpaceDataFL = mc.formLayout(numberOfDivisions=100) - + buildWorldSpaceMeshB = mc.button(label='Build World Space Mesh',c='glTools.ui.skinClusterData.buildWorldSpaceMesh()') storeWorldSpaceMeshB = mc.button(label='Store World Space Mesh',c='glTools.ui.skinClusterData.storeWorldSpaceMesh()') rebuildWorldSpaceDataB = mc.button(label='Rebuild World Space Data',c='glTools.ui.skinClusterData.rebuildWorldSpaceData()') worldSpaceMeshTFG = mc.textFieldGrp('skinCluster_wsMeshTFG',label='World Space Mesh',text='',editable=False,cw=cw1) - + mc.formLayout(worldSpaceDataFL,e=True,af=[(buildWorldSpaceMeshB,'top',5),(buildWorldSpaceMeshB,'left',5),(buildWorldSpaceMeshB,'right',5)]) mc.formLayout(worldSpaceDataFL,e=True,ac=[(storeWorldSpaceMeshB,'top',5,buildWorldSpaceMeshB)],af=[(storeWorldSpaceMeshB,'left',5),(storeWorldSpaceMeshB,'right',5)]) mc.formLayout(worldSpaceDataFL,e=True,ac=[(rebuildWorldSpaceDataB,'top',5,storeWorldSpaceMeshB)],af=[(rebuildWorldSpaceDataB,'left',5),(rebuildWorldSpaceDataB,'right',5)]) mc.formLayout(worldSpaceDataFL,e=True,ac=[(worldSpaceMeshTFG,'top',5,rebuildWorldSpaceDataB)],af=[(worldSpaceMeshTFG,'left',5),(worldSpaceMeshTFG,'right',5)]) - + # ==================== # - PopUp Menu Items - # ==================== - + # Influence Menu mc.popupMenu(parent=skinCluster_infTSL) mc.menuItem(label='Remap Influence',c='glTools.ui.skinClusterData.remapSelectedInfluence()') mc.menuItem(label='Combine Influences',c='glTools.ui.skinClusterData.combineSelectedInfluences()') mc.menuItem(label='Swap Weights',c='glTools.ui.skinClusterData.swapInfluenceWeights()') mc.menuItem(label='Move Weights',c='glTools.ui.skinClusterData.moveInfluenceWeights()') - + mc.popupMenu(parent=skinCluster_wtTSL) - + # ======================== # - UI Callback Commands - # ======================== - + mc.textFieldGrp(skinClusterNameTFG,e=True,cc='glTools.ui.skinClusterData.renameSkinCluster()') mc.textFieldButtonGrp(skinClusterGeoTFB,e=True,bc='glTools.ui.skinClusterData.remapGeometry()') mc.optionMenuGrp(skinClusterMethodOMG,e=True,cc='glTools.ui.skinClusterData.updateBasicData()') @@ -124,26 +124,26 @@ def skinClusterDataUI(): mc.optionMenuGrp(skinClusterNormalizeOMG,e=True,cc='glTools.ui.skinClusterData.updateBasicData()') mc.checkBoxGrp(skinClusterDeformNormCBG,e=True,cc='glTools.ui.skinClusterData.updateBasicData()') mc.textScrollList(skinCluster_infTSL,e=True,sc='glTools.ui.skinClusterData.selectInfluencesFromUI();glTools.ui.skinClusterData.displayWeightList()') - + # ================ # - Form Layouts - # ================ - + mc.formLayout(mainFL,e=True,af=[(loadB,'top',5),(loadB,'left',5)],ap=[(loadB,'right',5,50)]) mc.formLayout(mainFL,e=True,af=[(buildB,'top',5),(buildB,'right',5)],ap=[(buildB,'left',5,50)]) mc.formLayout(mainFL,e=True,af=[(saveB,'bottom',5),(saveB,'left',5)],ap=[(saveB,'right',5,50)]) mc.formLayout(mainFL,e=True,af=[(closeB,'bottom',5),(closeB,'right',5)],ap=[(closeB,'left',5,50)]) mc.formLayout(mainFL,e=True,ac=[(rebuildB,'bottom',5,closeB)],af=[(rebuildB,'right',5),(rebuildB,'left',5)]) mc.formLayout(mainFL,e=True,ac=[(scrollLayout,'top',5,loadB),(scrollLayout,'bottom',5,rebuildB)],af=[(scrollLayout,'left',5),(scrollLayout,'right',5)]) - + mc.formLayout(scrollFL,e=True,af=[(basicDataFRL,'top',5),(basicDataFRL,'left',5),(basicDataFRL,'right',5)]) mc.formLayout(scrollFL,e=True,ac=[(influenceDataFRL,'top',5,basicDataFRL)],af=[(influenceDataFRL,'left',5),(influenceDataFRL,'right',5)]) mc.formLayout(scrollFL,e=True,ac=[(worldSpaceDataFRL,'top',5,influenceDataFRL)],af=[(worldSpaceDataFRL,'left',5),(worldSpaceDataFRL,'right',5)]) - + # =============== # - Show Window - # =============== - + reloadUI() mc.showWindow(win) @@ -153,7 +153,7 @@ def loadData(): # Load SkinCluster Data skinData = data.Data().load() glTools.gl_global.glSkinClusterData = skinData - + # Rebuild UI reloadUI() @@ -165,7 +165,7 @@ def buildData(): if not sel: print('Nothing selected! Unable to load skinCluster data...') return - + # Get SkinCluster of First Selected Geometry geo = sel[0] # Check Geometry @@ -173,17 +173,17 @@ def buildData(): if not shapes: print('Selected object "'+geo+'" has no shape children! Unable to load skinCluster data...') return - + # Get SkinCluster skinCluster = glTools.utils.skinCluster.findRelatedSkinCluster(geo) if not skinCluster: print('Selected geometry "'+geo+'" has no skinCluster! Unable to load skinCluster data...') return - + # Build Data skinData = skinClusterData.SkinClusterData(skinCluster) glTools.gl_global.glSkinClusterData = skinData - + # Rebuild UI reloadUI() @@ -193,7 +193,7 @@ def saveData(): # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Save SkinClusterData to File skinData.saveAs() @@ -203,7 +203,7 @@ def rebuildSkinCluster(): # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Rebuild SkinCluster skinData.rebuild() @@ -213,23 +213,23 @@ def renameSkinCluster(): # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Check Window win = 'skinClusterDataUI' if not mc.window(win,q=True,ex=True): return - + # Get New SkinCluster Name skinName = mc.textFieldGrp('skinCluster_nameTFG',q=True,text=True) if not skinName: skinName = glTools.gl_global.glSkinClusterData._data['name'] mc.textFieldGrp('skinCluster_nameTFG',e=True,text=skinName) - + # Update skinClusterData glTools.gl_global.glSkinClusterData._data['name'] = skinName - + # Refresh UI reloadUI() - + # Return Result return skinName @@ -239,11 +239,11 @@ def remapGeometry(): # Check Window win = 'skinClusterDataUI' if not mc.window(win,q=True,ex=True): return - + # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Get User Selections geo = '' sel = mc.ls(sl=1,dag=True) @@ -256,13 +256,13 @@ def remapGeometry(): return else: geo = sel[0] - + # Remap Geometry skinData.remapGeometry(geometry=geo) - + # Refresh UI reloadUI() - + # Return Result return geo @@ -274,13 +274,13 @@ def updateBasicData(): if not skinData: print('No SkinClusterData to load...') return - + # Get Basic Data from UI skinMethod = mc.optionMenuGrp('skinCluster_methodOMG',q=True,sl=True) useComponents = mc.checkBoxGrp('skinCluster_componentCBG',q=True,v1=True) normalizeWt = mc.optionMenuGrp('skinCluster_normalizeOMG',q=True,sl=True) deformNormal = mc.checkBoxGrp('skinCluster_deformNormCBG',q=True,v1=True) - + # Update Basic SkinCluster Data skinData._data['attrValueDict']['skinningMethod'] = skinMethod-1 skinData._data['attrValueDict']['useComponents'] = useComponents @@ -300,17 +300,17 @@ def swapInfluenceWeights(): # Check Window win = 'skinClusterDataUI' if not mc.window(win,q=True,ex=True): return - + # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Get Influence Selection influenceSel = mc.textScrollList('skinCluster_infTSL',q=True,si=True) if len(influenceSel) < 2: print('Select 2 influences to swap weights between!') return - + # Swap Influence Weights skinData.swapWeights(influenceSel[0],influenceSel[1]) @@ -334,23 +334,23 @@ def displayWeightList(): # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Check Window win = 'skinClusterDataUI' if not mc.window(win,q=True,ex=True): return - + # Clear Weight List mc.textScrollList('skinCluster_wtTSL',e=True,ra=True) - + # Get Influence Selection influenceSel = mc.textScrollList('skinCluster_infTSL',q=True,si=True) if not influenceSel: return inf = influenceSel[0] - + # Check Weights if not skinData._influenceData.has_key(inf): return wt = skinData._influenceData[inf]['wt'] - + # Display Weights for i in range(len(wt)): mc.textScrollList('skinCluster_wtTSL',e=True,a='['+str(i)+']: '+str(wt[i])) @@ -360,18 +360,18 @@ def selectInfluencesFromUI(): # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Check Window win = 'skinClusterDataUI' if not mc.window(win,q=True,ex=True): return - + # Clear Weight List mc.textScrollList('skinCluster_wtTSL',e=True,ra=True) - + # Get Influence Selection influenceSel = mc.textScrollList('skinCluster_infTSL',q=True,si=True) if not influenceSel: return - + # Select Influences mc.select(cl=True) for inf in influenceSel: @@ -384,7 +384,7 @@ def buildWorldSpaceMesh(): # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Get Affected Geometry if not skinData._data.has_key('affectedGeometry'): raise Exception('No skin geometry data! Unable to rebuild worldSpace mesh...') @@ -395,14 +395,14 @@ def buildWorldSpaceMesh(): raise Exception('Skin geometry "'+skinGeo+'" is not a mesh! Unable to rebuild worldSpace mesh...') if not skinData._data[skinGeo].has_key('mesh'): raise Exception('No world space data for "'+skinGeo+'"! Unable to rebuild worldSpace mesh...') - + # Rebuild Mesh mesh = skinData._data[skinGeo]['mesh'].rebuildMesh() if not mesh.endswith('_worldSpaceMesh'): mesh = mc.rename(mesh,skinGeo+'_worldSpaceMesh') - + # Update TextFieldGrp mc.textFieldGrp('skinCluster_wsMeshTFG',e=True,text=mesh) - + # Return Result return mesh @@ -412,7 +412,7 @@ def storeWorldSpaceMesh(): # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Get Affected Geometry if not skinData._data.has_key('affectedGeometry'): raise Exception('No skin geometry data! Unable to rebuild worldSpace mesh...') @@ -421,19 +421,19 @@ def storeWorldSpaceMesh(): raise Exception('No skin geometry data for "'+skinGeo+'"! Unable to rebuild worldSpace mesh...') if skinData._data[skinGeo]['geometryType'] != 'mesh': raise Exception('Skin geometry "'+skinGeo+'" is not a mesh! Unable to rebuild worldSpace mesh...') - + # Initialize MeshData if not skinData._data[skinGeo].has_key('mesh'): skinData._data[skinGeo]['mesh'] = meshData.MeshData() - + # Store MeshData worldSpaceMesh = mc.textFieldGrp('skinCluster_wsMeshTFG',q=True,text=True) if not mc.objExists(worldSpaceMesh): raise Exception('World space mesh "'+worldSpaceMesh+'" doesn`t exist!') skinData._data[skinGeo]['mesh'].buildData(worldSpaceMesh) - + # Delete World Space Mesh mc.delete(worldSpaceMesh) - + # Update TextFieldGrp mc.textFieldGrp('skinCluster_wsMeshTFG',e=True,text='') @@ -443,7 +443,7 @@ def rebuildWorldSpaceData(): # Check SkinClusterData skinData = glTools.gl_global.glSkinClusterData if not skinData: return - + # Rebuild World Space Data skinData.rebuildWorldSpaceData() @@ -457,35 +457,35 @@ def reloadUI(): mc.textFieldButtonGrp('skinCluster_geoTFB',e=True,text='') mc.textScrollList('skinCluster_infTSL',e=True,ra=True) mc.textScrollList('skinCluster_wtTSL',e=True,ra=True) - + mc.optionMenuGrp('skinCluster_methodOMG',e=True,sl=1) mc.checkBoxGrp('skinCluster_componentCBG',e=True,v1=0) mc.optionMenuGrp('skinCluster_normalizeOMG',e=True,sl=1) mc.checkBoxGrp('skinCluster_deformNormCBG',e=True,v1=0) - + mc.textFieldGrp('skinCluster_wsMeshTFG',e=True,text='') - + # ===================================== # - Get Global SkinClusterData Object - # ===================================== - + skinData = glTools.gl_global.glSkinClusterData # Check SkinClusterData if not skinData: print('No SkinClusterData to load...') return - + # ================= # - Repopulate UI - # ================= - + skinName = skinData._data['name'] mc.textFieldGrp('skinCluster_nameTFG',e=True,text=skinName) skinGeo = skinData._data['affectedGeometry'][0] mc.textFieldGrp('skinCluster_geoTFB',e=True,text=skinGeo) influenceList = skinData._influenceData.keys() for inf in sorted(influenceList): mc.textScrollList('skinCluster_infTSL',e=True,a=inf) - + attrValues = skinData._data['attrValueDict'] if attrValues.has_key('skinningMethod'): mc.optionMenuGrp('skinCluster_methodOMG',e=True,sl=(attrValues['skinningMethod']+1)) @@ -495,4 +495,4 @@ def reloadUI(): mc.optionMenuGrp('skinCluster_normalizeOMG',e=True,sl=(attrValues['normalizeWeights']+1)) if attrValues.has_key('deformUserNormals'): mc.checkBoxGrp('skinCluster_deformNormCBG',e=True,v1=attrValues['deformUserNormals']) - + diff --git a/ui/spaces.py b/ui/spaces.py index 2ea850c..85469e5 100644 --- a/ui/spaces.py +++ b/ui/spaces.py @@ -12,21 +12,21 @@ def charUI(): win = mc.window(win,t='Spaces - Character UI') # Form Layout spacesCharFL = mc.formLayout(numberOfDivisions=100) - + # UI Elements #- # Character Prefix charTFG = mc.textFieldGrp('spacesCharTFG',label='Character Prefix', text='',cw=[(1,120),(2,150)]) # Button openB = mc.button(l='Open',c='glTools.ui.spaces.charUIFromUI()') - + mc.formLayout(spacesCharFL, e=True, af=[(charTFG,'left',5),(charTFG,'top',5),(charTFG,'right',5)]) mc.formLayout(spacesCharFL, e=True, ac=[(openB,'top',5,charTFG)]) mc.formLayout(spacesCharFL, e=True, af=[(openB,'left',5),(openB,'bottom',5),(openB,'right',5)]) - + # Open window mc.showWindow(win) - + def charUIFromUI(): ''' ''' @@ -46,7 +46,7 @@ def createAddUI(): win = mc.window(win,t='Spaces - Create/Add UI') # Form Layout spacesFL = mc.formLayout(numberOfDivisions=100) - + # UI Elements #- # Text Field Grps @@ -61,47 +61,47 @@ def createAddUI(): createBTN = mc.button(l='Create / Add',c='glTools.ui.spaces.createAddFromUI()') # Separator controlSEP = mc.separator(h=5,style='single') - + # Form Layout - MAIM #- # controlTFG mc.formLayout(spacesFL, e=True, af=[(controlTFG,'left',5),(controlTFG,'top',5)]) mc.formLayout(spacesFL, e=True, ap=[(controlTFG,'right',5,50)]) - + # controlTagTFG mc.formLayout(spacesFL, e=True, af=[(controlTagTFG,'right',5),(controlTagTFG,'top',5)]) mc.formLayout(spacesFL, e=True, ap=[(controlTagTFG,'left',5,50)]) - + # controlSEP mc.formLayout(spacesFL, e=True, af=[(controlSEP,'left',5),(controlSEP,'right',5)]) mc.formLayout(spacesFL, e=True, ac=[(controlSEP,'top',5,controlTFG)]) - + # targetListTXT mc.formLayout(spacesFL, e=True, af=[(targetListTXT,'left',5)]) mc.formLayout(spacesFL, e=True, ac=[(targetListTXT,'top',5,controlSEP)]) mc.formLayout(spacesFL, e=True, ap=[(targetListTXT,'right',5,50)]) - + # targetTSL mc.formLayout(spacesFL, e=True, af=[(targetTSL,'left',5),(targetTSL,'bottom',5)]) mc.formLayout(spacesFL, e=True, ap=[(targetTSL,'right',5,50)]) mc.formLayout(spacesFL, e=True, ac=[(targetTSL,'top',5,targetListTXT)]) - + # targetTagTFG mc.formLayout(spacesFL, e=True, af=[(targetTagTFG,'right',5)]) mc.formLayout(spacesFL, e=True, ap=[(targetTagTFG,'left',5,50),(targetTagTFG,'top',5,50)]) - + # createBTN mc.formLayout(spacesFL, e=True, af=[(createBTN,'bottom',5),(createBTN,'right',5)]) mc.formLayout(spacesFL, e=True, ap=[(createBTN,'left',5,66)]) - + # Poup menus targetListPUM = mc.popupMenu(parent=targetTSL) mc.menuItem('Add selected objects',c='glTools.ui.spaces.addSelectedToList()') mc.menuItem('Remove Highlighted objects',c='glTools.ui.spaces.removeFromList()') - + controlPUM = mc.popupMenu(parent=controlTFG) mc.menuItem('Get selected object',c='glTools.ui.spaces.getControlNameFromSel()') - + # Open window mc.showWindow(win) diff --git a/ui/surface.py b/ui/surface.py index 7d78f04..c5167be 100644 --- a/ui/surface.py +++ b/ui/surface.py @@ -27,7 +27,7 @@ def locatorSurfaceUI(): scaleFSG = mc.floatSliderGrp('locatorSurfaceScaleFSG',label='Locator Scale',field=True,minValue=0.0,maxValue=1.0,fieldMinValue=0.0,fieldMaxValue=10.0,value=0.75,pre=3) # Use Control Points useCvCBG = mc.checkBoxGrp('locatorSurfaceUseCvCBG',l='Specify CVs',ncb=1,v1=False) - + # Control Points layout cvFrameL = mc.frameLayout('locatorSurfaceCvFL',l='Control Points',cll=0,en=0) cvFormL = mc.formLayout(numberOfDivisions=100) @@ -35,20 +35,20 @@ def locatorSurfaceUI(): # TSL Buttons cvAddB = mc.button('locatorSurfaceAddCvB',l='Add',c='glTools.ui.utils.addCvsToTSL("'+controlPointTSL+'")',en=False) cvRemB = mc.button('locatorSurfaceRemCvB',l='Remove',c='glTools.ui.utils.removeFromTSL("'+controlPointTSL+'")',en=False) - + mc.setParent('..') mc.setParent('..') - + # Separator SEP = mc.separator(height=10,style='single') # Buttons createB = mc.button('locatorSurfaceCreateB',l='Create',c='glTools.ui.surface.locatorSurfaceFromUI()') cancelB = mc.button('locatorSurfaceCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # UI callback commands mc.textFieldButtonGrp(surfaceTFB,e=True,bc='glTools.ui.utils.loadSurfaceSel("'+surfaceTFB+'","'+prefixTFG+'")') mc.checkBoxGrp('locatorSurfaceUseCvCBG',e=True,cc='glTools.ui.utils.checkBoxToggleLayout("'+useCvCBG+'","'+cvFrameL+'")') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(surfaceTFB,'top',5),(surfaceTFB,'left',5),(surfaceTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(prefixTFG,'top',5,surfaceTFB)]) @@ -65,7 +65,7 @@ def locatorSurfaceUI(): mc.formLayout(FL,e=True,ac=[(createB,'bottom',5,cancelB)]) mc.formLayout(FL,e=True,af=[(createB,'left',5),(createB,'right',5)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Form Layout - Control Points mc.formLayout(cvFormL,e=True,af=[(controlPointTSL,'top',5),(controlPointTSL,'left',5),(controlPointTSL,'right',5)]) mc.formLayout(cvFormL,e=True,ac=[(controlPointTSL,'bottom',5,cvAddB)]) @@ -73,7 +73,7 @@ def locatorSurfaceUI(): mc.formLayout(cvFormL,e=True,ap=[(cvAddB,'right',5,50)]) mc.formLayout(cvFormL,e=True,af=[(cvRemB,'right',5),(cvRemB,'bottom',5)]) mc.formLayout(cvFormL,e=True,ap=[(cvRemB,'left',5,50)]) - + # Show Window mc.showWindow(window) @@ -95,10 +95,10 @@ def locatorSurfaceFromUI(): cvList = mc.textScrollList('locatorSurfaceCpTSL',q=True,ai=True) if useCvs and not cvList: raise UserInputError('No control points specified!!') - + # Execute command glTools.utils.surface.locatorSurface(surface=surface,controlPoints=cvList,locatorScale=scale*0.1,prefix=prefix) - + # Cleanup mc.deleteUI(window) @@ -120,7 +120,7 @@ def snapToSurfaceUI(): surfaceTFB = mc.textFieldButtonGrp('snapToSurfaceTFB',label='Source Surface',text='',buttonLabel='Load Selected') # Orient orientCBG = mc.checkBoxGrp('snapToSurfaceOrientCBG',label='Orient To Surface',ncb=1,v1=False) - + # Orient Frame orientFrameL = mc.frameLayout('snapToSurfaceOriFL',l='Orient Options',cll=0,en=0) orientFormL = mc.formLayout(numberOfDivisions=100) @@ -134,19 +134,19 @@ def snapToSurfaceUI(): for ax in ['U','V']: mc.menuItem(label=ax) # Set Default Value mc.optionMenuGrp('snapToSurfaceVAxisOMG',e=True,sl=2) - + mc.setParent('..') mc.setParent('..') - + # UI callback commands mc.textFieldButtonGrp(surfaceTFB,e=True,bc='glTools.ui.utils.loadSurfaceSel("'+surfaceTFB+'")') mc.checkBoxGrp(orientCBG,e=True,cc='glTools.ui.utils.checkBoxToggleLayout("'+orientCBG+'","'+orientFrameL+'")') - + # Buttons snapB = mc.button('snapToSurfaceSnapB',l='Snap!',c='glTools.ui.surface.snapToSurfaceFromUI(False)') snapCloseB = mc.button('snapToSurfaceSnapCloseB',l='Snap and Close',c='glTools.ui.surface.snapToSurfaceFromUI(True)') cancelB = mc.button('snapToSurfaceCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # Form Layout - MAIN mc.formLayout(FL,e=True,af=[(surfaceTFB,'top',5),(surfaceTFB,'left',5),(surfaceTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(orientCBG,'top',5,surfaceTFB)]) @@ -159,14 +159,14 @@ def snapToSurfaceUI(): mc.formLayout(FL,e=True,ac=[(snapCloseB,'bottom',5,cancelB)]) mc.formLayout(FL,e=True,af=[(snapCloseB,'left',5),(snapCloseB,'right',5)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Form Layout - Orient mc.formLayout(orientFormL,e=True,af=[(orientUAxisOMG,'top',5),(orientUAxisOMG,'left',5),(orientUAxisOMG,'right',5)]) mc.formLayout(orientFormL,e=True,ac=[(orientVAxisOMG,'top',5,orientUAxisOMG)]) mc.formLayout(orientFormL,e=True,af=[(orientVAxisOMG,'left',5),(orientVAxisOMG,'right',5)]) mc.formLayout(orientFormL,e=True,ac=[(orientAlignToOMG,'top',5,orientVAxisOMG)]) mc.formLayout(orientFormL,e=True,af=[(orientAlignToOMG,'left',5),(orientAlignToOMG,'right',5)]) - + # Show Window mc.showWindow(window) @@ -188,10 +188,10 @@ def snapToSurfaceFromUI(close=False): tanU = str.lower(str(mc.optionMenuGrp('snapToSurfaceUAxisOMG',q=True,v=True))) tanV = str.lower(str(mc.optionMenuGrp('snapToSurfaceVAxisOMG',q=True,v=True))) align = str.lower(str(mc.optionMenuGrp('snapToSurfaceAlignToOMG',q=True,v=True))) - + # Get User Selection sel = mc.ls(sl=True,fl=True) - + # Execute Command glTools.utils.surface.snapPtsToSurface(surface,sel) # Orient @@ -201,7 +201,7 @@ def snapToSurfaceFromUI(close=False): glTools.utils.surface.orientToSurface(surface=surface,obj=obj,useClosestPoint=True,tangentUAxis=tanU,tangentVAxis=tanV,alignTo=align) except: print('Object "'+obj+'" is not a valid transform!! Unable to orient!') - + # Cleanup if close: mc.deleteUI(window) @@ -234,7 +234,7 @@ def attachToSurfaceUI(): vParamAttrTFG = mc.textFieldGrp('attachToSurfaceVAttrTFG',label='V Param Attribute', text='vCoord') # Orient orientCBG = mc.checkBoxGrp('attachToSurfaceOrientCBG',label='Orient To Surface',ncb=1,v1=False) - + # Orient Frame orientFrameL = mc.frameLayout('attachToSurfaceOriFL',l='Orient Options',cll=0,en=0) orientFormL = mc.formLayout(numberOfDivisions=100) @@ -248,20 +248,20 @@ def attachToSurfaceUI(): for ax in ['U','V']: mc.menuItem(label=ax) # Set Default Value mc.optionMenuGrp('attachToSurfaceVAxisOMG',e=True,sl=2) - + mc.setParent('..') mc.setParent('..') - + # Buttons attachB = mc.button('attachToSurfaceAttachB',l='Attach',c='glTools.ui.surface.attachToSurfaceFromUI(False)') cancelB = mc.button('snapToSurfaceCancelB',l='Cancel',c='mc.deleteUI("'+window+'")') - + # UI callback commands mc.textFieldButtonGrp(surfaceTFB,e=True,bc='glTools.ui.utils.loadSurfaceSel("'+surfaceTFB+'")') mc.textFieldButtonGrp(transformTFB,e=True,bc='glTools.ui.utils.loadObjectSel("'+transformTFB+'","'+prefixTFG+'")') mc.checkBoxGrp(closePointCBG,e=True,cc='glTools.ui.utils.checkBoxToggleControl("'+closePointCBG+'","'+uvParamFFG+'",invert=True)') mc.checkBoxGrp(orientCBG,e=True,cc='glTools.ui.utils.checkBoxToggleLayout("'+orientCBG+'","'+orientFrameL+'")') - + # Form Layout - Main mc.formLayout(FL,e=True,af=[(surfaceTFB,'top',5),(surfaceTFB,'left',5),(surfaceTFB,'right',5)]) mc.formLayout(FL,e=True,ac=[(transformTFB,'top',5,surfaceTFB)]) @@ -283,14 +283,14 @@ def attachToSurfaceUI(): mc.formLayout(FL,e=True,af=[(attachB,'left',5),(attachB,'right',5)]) mc.formLayout(FL,e=True,ac=[(attachB,'bottom',5,cancelB)]) mc.formLayout(FL,e=True,af=[(cancelB,'left',5),(cancelB,'right',5),(cancelB,'bottom',5)]) - + # Form Layout - Orient mc.formLayout(orientFormL,e=True,af=[(orientUAxisOMG,'top',5),(orientUAxisOMG,'left',5),(orientUAxisOMG,'right',5)]) mc.formLayout(orientFormL,e=True,ac=[(orientVAxisOMG,'top',5,orientUAxisOMG)]) mc.formLayout(orientFormL,e=True,af=[(orientVAxisOMG,'left',5),(orientVAxisOMG,'right',5)]) mc.formLayout(orientFormL,e=True,ac=[(orientAlignToOMG,'top',5,orientVAxisOMG)]) mc.formLayout(orientFormL,e=True,af=[(orientAlignToOMG,'left',5),(orientAlignToOMG,'right',5)]) - + # Show Window mc.showWindow(window) @@ -319,10 +319,10 @@ def attachToSurfaceFromUI(close=True): tanU = str.lower(str(mc.optionMenuGrp('attachToSurfaceUAxisOMG',q=True,v=True))) tanV = str.lower(str(mc.optionMenuGrp('attachToSurfaceVAxisOMG',q=True,v=True))) align = str.lower(str(mc.optionMenuGrp('attachToSurfaceAlignToOMG',q=True,v=True))) - + # Execute command result = glTools.utils.attach.attachToSurface(surface=surf,transform=trans,uValue=uParam,vValue=vParam,useClosestPoint=closePnt,orient=orient,uAxis=tanU,vAxis=tanV,uAttr=uAttr,vAttr=vAttr,alignTo=align,prefix=pre) - + # Cleanup if close: mc.deleteUI(window) diff --git a/ui/transformDrivenBlend.py b/ui/transformDrivenBlend.py index 6e831c0..258be2d 100644 --- a/ui/transformDrivenBlend.py +++ b/ui/transformDrivenBlend.py @@ -10,10 +10,10 @@ def ui(): window = 'transformDrivenBlendUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Transform Driven Blend') - + # Layout cl = mc.columnLayout() - + # UI Elements driveAttrTFG = mc.textFieldGrp('tdb_driveAttrTFG',label='Drive Attr', text='') blendShapeTFG = mc.textFieldGrp('tdb_blendShapeTFG',label='BlendShape', text='') @@ -26,18 +26,18 @@ def ui(): createB = mc.button('tdb_createB',label='Create',c='glTools.ui.transformDrivenBlend.executeFromUI()') refreshB = mc.button('tdb_refreshB',label='Refresh',c='glTools.ui.transformDrivenBlend.refreshUI()') cancelB = mc.button('tdb_cancelB',label='Cancel',c='mc.deleteUI('+window+')') - + # Popup Menus mc.popupMenu('tdb_blendShapePUM',p=blendShapeTFG) mc.popupMenu('tdb_target1PUM',p=target1TFG) mc.popupMenu('tdb_target2PUM',p=target2TFG) mc.popupMenu('tdb_driveAttrPUM',p=driveAttrTFG) mc.menuItem(label='Set from selected',c='glTools.ui.utils.loadChannelBoxSel("'+driveAttrTFG+'")') - + # Show Window refreshUI() mc.showWindow(window) - + def refreshUI(): ''' ''' @@ -45,14 +45,14 @@ def refreshUI(): blendShape = mc.textFieldGrp('tdb_blendShapeTFG',q=True,text=True) target1 = mc.textFieldGrp('tdb_target1TFG',q=True,text=True) target2 = mc.textFieldGrp('tdb_target1TFG',q=True,text=True) - + # Update blendShape menu list blendShapeList = mc.ls(type='blendShape') mc.popupMenu('tdb_blendShapePUM',e=True,deleteAllItems=True) mc.setParent('tdb_blendShapePUM',m=True) for item in blendShapeList: mc.menuItem(label=item,c='mc.textFieldGrp("tdb_blendShapeTFG",e=True,text="'+item+'");glTools.ui.transformDrivenBlend.refreshUI()') - + # Check BlendShape if blendShape and mc.objExists('blendShape') and (mc.objectType(blendShape) == 'blendShape'): targetList = mc.listAttr(blendShape+'.w',m=True) @@ -66,14 +66,14 @@ def refreshUI(): mc.menuItem(label=target,c='mc.textFieldGrp("tdb_target1TFG",e=True,text="'+target+'");glTools.ui.transformDrivenBlend.refreshUI()',en=not bool(targetCon)) mc.setParent('tdb_target2PUM',m=True) mc.menuItem(label=target,c='mc.textFieldGrp("tdb_target1TFG",e=True,text="'+target+'");glTools.ui.transformDrivenBlend.refreshUI()',en=not bool(targetCon)) - + def executeFromUI(): ''' ''' - # Set Default Values + # Set Default Values minValue = 0.0 maxValue = 1.0 - + # Get UI input values driveAttr = mc.textFieldGrp('tdb_driveAttrTFG',q=True,text=True) blendShape = mc.textFieldGrp('tdb_blendShapeTFG',q=True,text=True) @@ -83,7 +83,7 @@ def executeFromUI(): weight2 = mc.floatFieldGrp('tdb_weight2FFG',q=True,v1=True) overlap = mc.floatFieldGrp('tdb_overlapFFG',q=True,v1=True) prefix = mc.textFieldGrp('tdb_prefixTFG',q=True,text=True) - + # Check Arguments if not blendShape: raise Exception('No blendShape specified!') if not target1: raise Exception('Target 1 not specified!') @@ -92,7 +92,7 @@ def executeFromUI(): maxValue = weight2 else: maxValue = weight1 - + # Execute Command if target1 and target2: glTools.tools.transformDrivenBlend.drive2Shapes(blendShape,target1,target2,driveAttr,minValue,maxValue,overlap,prefix) diff --git a/ui/utils.py b/ui/utils.py index 5c7313b..69681e3 100644 --- a/ui/utils.py +++ b/ui/utils.py @@ -37,12 +37,12 @@ def loadFilePath(textField,fileFilter=None,caption='Load File',startDir=None): caption=caption, okCaption='Load', startingDirectory=startDir ) - + # Check File Path if not filePath: print('Invalid file path!') return - + # Load File Path to TextField if mc.textField(textField,q=True,ex=True): mc.textField(textField,e=True,text=filePath[0]) @@ -53,7 +53,7 @@ def loadFilePath(textField,fileFilter=None,caption='Load File',startDir=None): else: print('UI element "" is not a valid textField, textFieldGrp or textFieldButtonGrp!') return - + # Return Result return filePath[0] @@ -73,12 +73,12 @@ def loadDirectoryPath(textField,caption='Load Directory',startDir=None): caption=caption, okCaption='Load', startingDirectory=startDir ) - + # Check File Path if not dirPath: print('Invalid directory path!') return - + # Load File Path to TextField if mc.textField(textField,q=True,ex=True): mc.textField(textField,e=True,text=dirPath[0]) @@ -89,7 +89,7 @@ def loadDirectoryPath(textField,caption='Load Directory',startDir=None): else: print('UI element "'+textField+'" is of type "'+mc.objectTypeUI(textField)+'"! Expected textField, textFieldGrp or textFieldButtonGrp.') return - + # Return Result return dirPath[0] @@ -99,7 +99,7 @@ def importFolderBrowser(textField): # ,caption='Import',startingDirectory=None): ''' mm.eval('global proc importGetFolder(string $textField,string $path,string $type){ textFieldButtonGrp -e -text $path $textField; deleteUI projectViewerWindow; }') mm.eval('fileBrowser "importGetFolder '+textField+'" Import "" 4') - + #dirPath = mc.fileDialog2(dialogStyle=2,fileMode=3,caption='Load Scenegraph XML',okCaption='Load',startingDirectory=startingDirectory) def exportFolderBrowser(textField): @@ -120,11 +120,11 @@ def loadNsSel(textField,topOnly=True): # Get Selection sel = mc.ls(sl=True) if not sel: return - + # Get Selected Namespace NS = '' NS = glTools.utils.namespace.getNS(sel[0],topOnly) - + # Update UI mc.textFieldButtonGrp(textField,e=True,text=NS) @@ -239,7 +239,7 @@ def loadChannelBoxSel(textField,fullName=True): ''' # Get channelBox channelBox = 'mainChannelBox' - + # Check main object channels nodeList = mc.channelBox(channelBox,q=True,mol=True) channelList = mc.channelBox(channelBox,q=True,sma=True) @@ -255,12 +255,12 @@ def loadChannelBoxSel(textField,fullName=True): if not channelList: channelList = mc.channelBox(channelBox,q=True,soa=True) nodeList = mc.channelBox(channelBox,q=True,ool=True) - + # Check selection if not channelList: print('No channel selected in the channelBox!') return - + # Update UI attr = '' if fullName: attr += str(nodeList[0]+'.') @@ -287,19 +287,19 @@ def copyTSLselToTSL(sourceTSL,targetTSL,removeFromSource=False,replaceTargetCont # Get source selection srcItems = mc.textScrollList(sourceTSL,q=True,si=True) if not srcItems: return - + # Clear target list if replaceTragetContents: mc.textScrollList(targetTSL,e=True,ra=True) - + # Get current target items tgtItems = mc.textScrollList(targetTSL,q=True,si=True) - + # Copy to target list for src in srcItems: - + # Check existing target items if tgtItems.count(src): continue - + # Append to target list mc.textScrollList(targetTSL,e=True,a=src) tgtItems.append(src) @@ -366,27 +366,27 @@ def selectFromTSL(TSL,mode='replace',safeFail=True): # Check Mode if not mode in ['add','replace','toggle','remove']: raise Exception('Invalid selection mode! ("'+mode+'")') - + # Get Items to Select listItems = mc.textScrollList(TSL,q=True,si=True) if not listItems: return - + # Clear Selection if mode.lower() == 'replace': mc.select(cl=True) - + # Select Items for item in listItems: - + # Check Object Exists if not mc.objExists(item): - + # Check Safe Fail if safeFail: print('Object "'+item+'" does not exist! Skipping...') continue else: raise Exception('Object "'+item+'" does not exist!') - + # Add Item to Selection if (mode == 'add') or (mode == 'replace'): mc.select(listItems,add=True,noExpand=True) @@ -396,7 +396,7 @@ def selectFromTSL(TSL,mode='replace',safeFail=True): # Remove Item Selection if (mode == 'remove'): mc.select(listItems,d=True,noExpand=True) - + def moveToTSLPosition(TSL,index): ''' @@ -408,34 +408,34 @@ def moveToTSLPosition(TSL,index): ''' # Get all list entries listLen = len(mc.textScrollList(TSL,q=True,ai=True)) - + # Get selected item indices listItems = mc.textScrollList(TSL,q=True,si=True) listIndex = mc.textScrollList(TSL,q=True,sii=True) listItems.reverse() listIndex.reverse() - + # Check position value if not index or index > listLen: raise UserInputError('Invalid position ('+str(index)+') provided for textScrollList!!') if index < 0: index = 2 + listLen + index - + # Remove items for i in range(len(listIndex)): if listIndex[i] < index: index -= 1 mc.textScrollList(TSL,e=True,rii=listIndex) - + # Append items to position for i in range(len(listIndex)): mc.textScrollList(TSL,e=True,ap=(index,listItems[i])) listIndex[i] = index + i - + # Select list items mc.textScrollList(TSL,e=True,da=True) mc.textScrollList(TSL,e=True,sii=listIndex) mc.textScrollList(TSL,e=True,shi=listIndex[0]) - + def moveUpTSLPosition(TSL): ''' Move the selected textScrollList items up by one position @@ -444,11 +444,11 @@ def moveUpTSLPosition(TSL): ''' # Method variables minIndex = 1 - + # Get selected item indices listItems = mc.textScrollList(TSL,q=True,si=True) listIndex = mc.textScrollList(TSL,q=True,sii=True) - + # Iterate through list items for i in range(len(listIndex)): # Check minIndex @@ -458,12 +458,12 @@ def moveUpTSLPosition(TSL): mc.textScrollList(TSL,e=True,sii=listIndex[i]) listIndex[i] -= 1 moveToTSLPosition(TSL,listIndex[i]) - + # Select list items mc.textScrollList(TSL,e=True,da=True) mc.textScrollList(TSL,e=True,sii=listIndex) mc.textScrollList(TSL,e=True,shi=listIndex[0]) - + def moveDownTSLPosition(TSL): ''' Move the selected textScrollList items down by one position @@ -473,14 +473,14 @@ def moveDownTSLPosition(TSL): # Get list length listLen = len(mc.textScrollList(TSL,q=True,ai=True)) maxIndex = listLen - + # Get selected item indices listItems = mc.textScrollList(TSL,q=True,si=True) listIndex = mc.textScrollList(TSL,q=True,sii=True) # Reverse lists listItems.reverse() listIndex.reverse() - + # Iterate through list items for i in range(len(listItems)): # Check maxIndex @@ -493,7 +493,7 @@ def moveDownTSLPosition(TSL): moveToTSLPosition(TSL,-1) else: moveToTSLPosition(TSL,listIndex[i]+1) - + # Select list items mc.textScrollList(TSL,e=True,da=True) mc.textScrollList(TSL,e=True,sii=listIndex) @@ -509,7 +509,7 @@ def loadFileSelection(TSL,fileFilter='*.*',startDir=None,caption='Load Files'): caption=caption, okCaption='Load', startingDirectory=startDir ) - + # Add File Selection if fileList: for item in fileList: @@ -531,22 +531,22 @@ def loadFileList(TSL,path,filesOnly=False,filterStr='',sort=False): ''' # Get File List fileList = glTools.utils.osUtils.getFileList(path,filesOnly=filesOnly) - + # Filter (regex) if filterStr: reFilter = re.compile(filterStr) fileList = filter(reFilter.search, fileList) - + # Sort if sort: fileList.sort() - + # Add File List to textScrollList addToTSL(TSL,fileList) - + # ============= # - Check Box - # ============= - + def checkBoxToggleLayout(CBG,layout,invert=False): ''' Toggle the enabled state of a UI layout based on a checkBoxGrp @@ -563,11 +563,11 @@ def checkBoxToggleLayout(CBG,layout,invert=False): # Check layout if not mc.layout(layout,q=True,ex=True): raise UIError('Layout "'+layout+'" does not exist!!') - + # Get checkBoxGrp state state = mc.checkBoxGrp(CBG,q=True,v1=True) if invert: state = not state - + # Toggle Layout mc.layout(layout,e=True,en=state) @@ -587,11 +587,11 @@ def checkBoxToggleControl(CBG,control,invert=False): # Check control if not mc.control(control,q=True,ex=True): raise UIError('Control "'+control+'" does not exist!!') - + # Get checkBoxGrp state state = mc.checkBoxGrp(CBG,q=True,v1=True) if invert: state = not state - + # Toggle Layout mc.control(control,e=True,en=state) @@ -612,20 +612,20 @@ def setOptionMenuList(OMG,itemList,add=False): # Check optionMenuGrp if not mc.optionMenuGrp(OMG,q=True,ex=True): raise UIError('OptionMenu "'+OMG+'" does not exist!') - + # Get existing items exItemList = mc.optionMenuGrp(OMG,q=True,ill=True) - + # Add items for item in itemList: mc.setParent(OMG) mc.menuItem(l=item) - + # Remove previous items if exItemList: for item in exItemList: mc.deleteUI(item) - + # ===================== # - Float Field Group - # ===================== @@ -641,19 +641,19 @@ def setPointValue(FFG,point=''): # Check point if point and not mc.objExists(point): raise Exception('Point object "'+point+'" does not exist!') - + # Get object selection sel = mc.ls(sl=1) if not point and not sel: raise Exception('No point specified for floatFieldGrp values!') - + # Get point if point: pos = glTools.utils.base.getPosition(point) else: pos = glTools.utils.base.getPosition(sel[0]) - + # Set float field values mc.floatFieldGrp(FFG,e=True,v1=pos[0],v2=pos[1],v3=pos[2]) - + # ============= # - Custom UI - # ============= @@ -670,32 +670,32 @@ def displayListWindow(itemList,title,enableSelect=False): if not itemList: mc.confirmDialog(t=title,m='No items to display!',ma='center',b='Close') return - + # Window window = 'displayListWindowUI' if mc.window(window,q=True,ex=True): mc.deleteUI(window) window = mc.window(window,t=title,s=True) - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # =============== # - UI Elements - # =============== - + # TextScrollList TSL = mc.textScrollList('displayListWindowTSL',allowMultiSelection=True) for item in itemList: mc.textScrollList(TSL,e=True,a=item) if enableSelect: mc.textScrollList(TSL,e=True,sc='glTools.ui.utils.selectFromTSL("'+TSL+'")') - + # Close Button closeB = mc.button('displayListWindowB',l='Close',c='mc.deleteUI("'+window+'")') - + # Form Layout mc.formLayout(FL,e=True,af=[(TSL,'top',5),(TSL,'left',5),(TSL,'right',5)]) mc.formLayout(FL,e=True,af=[(closeB,'bottom',5),(closeB,'left',5),(closeB,'right',5)]) mc.formLayout(FL,e=True,ac=[(TSL,'bottom',5,closeB)]) - + # Display Window mc.showWindow(window) @@ -709,23 +709,23 @@ def displayMessageWindow(msg,title): ''' # Check message if not msg: return - + # Window window = 'messageWindowUI' if mc.window(window,q=True,ex=True): mc.deleteUI(window) window = mc.window(window,t=title,s=True) - + # Layout FL = mc.formLayout(numberOfDivisions=100) - + # UI Elements reportSF = mc.scrollField('messageWindowSF',editable=False,wordWrap=True,text=msg) closeB = mc.button('messageWindowB',l='Close',c='mc.deleteUI("'+window+'")') - + # Form Layout mc.formLayout(FL,e=True,af=[(reportSF,'top',5),(reportSF,'left',5),(reportSF,'right',5)]) mc.formLayout(FL,e=True,af=[(closeB,'bottom',5),(closeB,'left',5),(closeB,'right',5)]) mc.formLayout(FL,e=True,ac=[(reportSF,'bottom',5,closeB)]) - + # Display Window mc.showWindow(window) diff --git a/utils/arrayUtils.py b/utils/arrayUtils.py index 44b46e3..6f97193 100644 --- a/utils/arrayUtils.py +++ b/utils/arrayUtils.py @@ -21,7 +21,7 @@ def dict_orderedKeyListFromValues(d): @type d: dict ''' return [ i[0] for i in sorted(d.items(), key=lambda (k, v): v) ] - + def dict_orderedValueListFromKeys(d): ''' Return a list of dictionary values, ordered based on their keys diff --git a/utils/attach.py b/utils/attach.py index 9c5517e..5335424 100644 --- a/utils/attach.py +++ b/utils/attach.py @@ -41,7 +41,7 @@ def attachToCurve( curve, @type upType: string @param upObject: Object whose local space will be used to calculate the orient upVector @type upObject: str - @param uAttr: Attribute name on the constrained transform that will be connected to the target curve U parameter. + @param uAttr: Attribute name on the constrained transform that will be connected to the target curve U parameter. @type uAttr: str @param prefix: Name prefix for created nodes @type prefix: str @@ -49,21 +49,21 @@ def attachToCurve( curve, # =========================== # - Build Data Dictionaries - # =========================== - + # Build axis dictionary axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # Build upType dictionary upTypeDict = {'scene':0, 'object':1, 'objectUp':2, 'vector':3, 'none': 4} - + # ========== # - Checks - # ========== - + # Check curve if not glTools.utils.curve.isCurve(curve): raise Exception('Object '+curve+' is not a valid curve!!') - + # Check curve shape curveShape='' if mc.objectType(curve) == 'transform': @@ -71,88 +71,88 @@ def attachToCurve( curve, else: curveShape = curve curve = mc.listRelatives(curve,p=1)[0] - + # Check uValue minu = mc.getAttr(curve+'.minValue') maxu = mc.getAttr(curve+'.maxValue') if not useClosestPoint: if uValue < minu or uValue > maxu: raise Exception('U paramater '+str(uValue)+' is not within the parameter range for '+curve+'!!') - + # Check object if not mc.objExists(transform): raise Exception('Object '+transform+' does not exist!!') if not glTools.utils.transform.isTransform(transform): raise Exception('Object '+transform+' is not a valid transform!!') - + # Check constraint axis' if not axisDict.has_key(tangentAxis): raise Exception('Invalid tangent axis "'+tangentAxis+'"!') if not axisDict.has_key(upAxis): raise Exception('Invalid up axis "'+upAxis+'"!') - + # Check constraint upType if not upTypeDict.has_key(upType): raise Exception('Invalid upVector type "'+upType+'"!') - + # Check worldUp object if upObject: if not mc.objExists(upObject): raise Exception('WorldUp object '+upObject+' does not exist!!') if not glTools.utils.transform.isTransform(upObject): raise Exception('WorldUp object '+upObject+' is not a valid transform!!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(transform) - + # =================== # - Attach to Curve - # =================== - + # Get closest curve point if useClosestPoint: uPos = mc.xform(transform,q=True,ws=True,rp=True) uValue = glTools.utils.curve.closestPoint(curve,uPos) - + # Add U parameter attribute if not mc.objExists(transform+'.'+uAttr): mc.addAttr(transform,ln=uAttr,at='float',min=minu,max=maxu,dv=uValue,k=True) else: try: mc.setAttr(transform+'.'+uAttr,uValue) except: print('Unable to set existing attr "'+transform+'.'+uAttr+'" to specified value ('+str(uValue)+')!') - + # Create pointOnCurveInfo node poc = prefix+'_pointOnCurveInfo' poc = mc.createNode('pointOnCurveInfo',n=poc) - + # Attach pointOnCurveInfo node mc.connectAttr(curve+'.worldSpace[0]',poc+'.inputCurve',f=True) mc.connectAttr(transform+'.'+uAttr,poc+'.parameter',f=True) - + # Create pointConstraint node pntCon = mc.createNode('pointConstraint',n=prefix+'_pointConstraint') - + # Attach pointConstraint node mc.connectAttr(poc+'.position',pntCon+'.target[0].targetTranslate',f=True) mc.connectAttr(transform+'.parentInverseMatrix[0]',pntCon+'.constraintParentInverseMatrix',f=True) mc.connectAttr(transform+'.rotatePivot',pntCon+'.constraintRotatePivot',f=True) mc.connectAttr(transform+'.rotatePivotTranslate',pntCon+'.constraintRotateTranslate',f=True) - + # Attach to constrained transform mc.connectAttr(pntCon+'.constraintTranslateX',transform+'.tx',f=True) mc.connectAttr(pntCon+'.constraintTranslateY',transform+'.ty',f=True) mc.connectAttr(pntCon+'.constraintTranslateZ',transform+'.tz',f=True) - + # Parent constraint node mc.parent(pntCon,transform) - + # ========== # - Orient - # ========== - + aimCon = '' if orient: - + # Create aimConstraint node aimCon = prefix+'aimConstraint' aimCon = mc.createNode('aimConstraint',n=aimCon) - + # Attach aimConstraint node mc.connectAttr(poc+'.tangent',aimCon+'.target[0].targetTranslate',f=True) mc.setAttr(aimCon+'.aimVector',*axisDict[tangentAxis]) @@ -160,15 +160,15 @@ def attachToCurve( curve, mc.setAttr(aimCon+'.worldUpVector',*upVector) mc.setAttr(aimCon+'.worldUpType',upTypeDict[upType]) if upObject: mc.connectAttr(upObject+'.worldMatrix[0]',aimCon+'.worldUpMatrix',f=True) - + # Attach to constrained transform mc.connectAttr(aimCon+'.constraintRotateX',transform+'.rx',f=True) mc.connectAttr(aimCon+'.constraintRotateY',transform+'.ry',f=True) mc.connectAttr(aimCon+'.constraintRotateZ',transform+'.rz',f=True) - + # Parent constraint node mc.parent(aimCon,transform) - + # Return result return [poc,pntCon,aimCon] @@ -201,37 +201,37 @@ def attachToMesh( mesh, ''' # Create axis value dictionary axis = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object '+mesh+' is not a valid mesh!!') - + # Check transform if not mc.objExists(transform): raise Exception('Object '+transform+' does not exist!!') if not glTools.utils.transform.isTransform(transform): raise Exception('Object '+transform+' is not a valid transform!!') pos = mc.xform(transform,q=True,ws=True,rp=True) - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(transform) - + # Create int pointer for mesh iter classes indexUtil = OpenMaya.MScriptUtil() indexUtil.createFromInt(0) indexUtilPtr = indexUtil.asIntPtr() - + # Check closest face if useClosestPoint: faceId = glTools.utils.mesh.closestFace(mesh,pos) - + # Get MItMeshPolygon faceIter = glTools.utils.mesh.getMeshFaceIter(mesh) - + # Get face faceIter.setIndex(faceId,indexUtilPtr) - + # Get face edge list edgeIntList = OpenMaya.MIntArray() faceIter.getEdges(edgeIntList) edgeList = list(edgeIntList) - + # Get opposing edges edgeIter = glTools.utils.mesh.getMeshEdgeIter(mesh) edge1 = edgeList[0] @@ -246,10 +246,10 @@ def attachToMesh( mesh, if eDist > dist: edge2 = i dist = eDist - + # Check opposing edge if not (edge2+1): raise Exception('Unable to determine opposing face edges!!') - + # Create mesh edge loft edge1_cme = prefix+'_edge01_curveFromMeshEdge' edge1_cme = mc.createNode('curveFromMeshEdge',n=edge1_cme) @@ -264,7 +264,7 @@ def attachToMesh( mesh, mc.connectAttr(edge1_cme+'.outputCurve',mesh_lft+'.inputCurve[0]',f=True) mc.connectAttr(edge2_cme+'.outputCurve',mesh_lft+'.inputCurve[1]',f=True) mc.setAttr(mesh_lft+'.degree',1) - + # Create temporary surface tempSrf = mc.createNode('nurbsSurface') mc.connectAttr(mesh_lft+'.outputSurface',tempSrf+'.create') @@ -276,12 +276,12 @@ def attachToMesh( mesh, if len(tangentAxis)==2: offsetVal = 90.0 offsetAx = str.upper(tangentAxis[-1]) mc.setAttr(surfAttach[2]+'.offset'+offsetAx,offsetVal) - + # Bypass temporary nurbsSurface node mc.connectAttr(mesh_lft+'.outputSurface',surfAttach[0]+'.inputSurface',f=True) # Delete temporary surface mc.delete(tempSrf) - + # Return result return (surfAttach[0],surfAttach[1],surfAttach[2],mesh_lft,edge1_cme,edge2_cme) @@ -326,7 +326,7 @@ def attachToSurface( surface, ''' # Create axis value dictionary axis = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # Check surface if not glTools.utils.surface.isSurface(surface): raise Exception('Surface '+surface+' is not a valid nurbsSurface!!') @@ -337,7 +337,7 @@ def attachToSurface( surface, else: surfaceShape = surface surface = mc.listRelatives(surface,p=1)[0] - + # Check uValue minu = mc.getAttr(surface+'.minValueU') maxu = mc.getAttr(surface+'.maxValueU') @@ -346,35 +346,35 @@ def attachToSurface( surface, if not useClosestPoint: if uValue < minu or uValue > maxu: raise Exception('U paramater '+str(uValue)+' is not within the parameter range for '+surface+'!!') if vValue < minv or vValue > maxv: raise Exception('V paramater '+str(vValue)+' is not within the parameter range for '+surface+'!!') - + # Check transform if not mc.objExists(transform): raise Exception('Object '+transform+' does not exist!!') if not glTools.utils.transform.isTransform(transform): raise Exception('Object '+transform+' is not a valid transform!!') # Check closest point - if useClosestPoint: + if useClosestPoint: uv = glTools.utils.surface.closestPoint(surface,mc.xform(transform,q=True,ws=True,rp=True)) uValue = uv[0] vValue = uv[1] - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(transform) - + # Attach to surface # == - + # Add parameter attributes if not mc.objExists(transform+'.'+uAttr): mc.addAttr(transform,ln=uAttr,at='float',min=minu,max=maxu,dv=uValue,k=True) if not mc.objExists(transform+'.'+vAttr): mc.addAttr(transform,ln=vAttr,at='float',min=minv,max=maxv,dv=vValue,k=True) - + # Create pointOnSurfaceInfo node pos = mc.createNode('pointOnSurfaceInfo',n=prefix+'_pointOnSurfaceInfo') # Attach pointOnSurfaceInfo node mc.connectAttr(surface+'.worldSpace[0]',pos+'.inputSurface',f=True) mc.connectAttr(transform+'.'+uAttr,pos+'.parameterU',f=True) mc.connectAttr(transform+'.'+vAttr,pos+'.parameterV',f=True) - + # Create pointConstraint node pntCon = mc.createNode('pointConstraint',n=prefix+'_pointConstraint') # Attach pointConstraint node @@ -386,7 +386,7 @@ def attachToSurface( surface, mc.connectAttr(pntCon+'.constraintTranslateY',transform+'.ty',f=True) mc.connectAttr(pntCon+'.constraintTranslateZ',transform+'.tz',f=True) mc.parent(pntCon,transform) - + # Orient aimCon = '' if orient: @@ -410,6 +410,6 @@ def attachToSurface( surface, mc.connectAttr(aimCon+'.constraintRotateY',transform+'.ry',f=True) mc.connectAttr(aimCon+'.constraintRotateZ',transform+'.rz',f=True) mc.parent(aimCon,transform) - + # Return result return [pos,pntCon,aimCon] diff --git a/utils/attrPreset.py b/utils/attrPreset.py index 6e22c41..515c217 100644 --- a/utils/attrPreset.py +++ b/utils/attrPreset.py @@ -13,7 +13,7 @@ def presetExists(nodeType,preset): ''' # Create temp node node = mc.createNode(nodeType,n='temp_'+nodeType) - + # Check if preset is available try: mm.eval('applyAttrPreset '+node+' '+preset+' 1.0') @@ -21,7 +21,7 @@ def presetExists(nodeType,preset): if p: mc.delete(p) else: mc.delete(node) except: - print + print return False else: return True @@ -33,29 +33,29 @@ def listNodePreset(nodeType): presetPathList = [] presetPathList.extend(os.getenv('MAYA_PRESET_PATH').split(':')) presetPathList.extend(os.getenv('MAYA_SCRIPT_PATH').split(':')) - + # Check available presets presetList = [] for presetPath in presetPathList: - + # Get attrPreset subdirectory path = presetPath+'/attrPresets/' if not os.path.isdir(path): continue - + # Get node type subdirectories nodeDirList = os.listdir(path) if nodeDirList.count(nodeType): - + # Get nodeType subdirectory path += '/'+nodeType+'/' if not os.path.isdir(path): continue - + # Get attrPreset file list attrPresetList = os.listdir(path) for attrPreset in attrPresetList: if attrPreset.endswith('.mel'): presetList.append(attrPreset.replace('.mel','')) - + # Return result return list(set(presetList)) @@ -64,25 +64,25 @@ def apply(nodeList,preset,amount=1.0): ''' # Check nodeList argument type if type(nodeList) == str or type(nodeList) == unicode: nodeList = [nodeList] - + # Check nodes exist nodeTypeList = [] for node in nodeList: if not mc.objExists(node): raise Exception('Node "'+node+'" does not exist!!') nodeTypeList.append(mc.objectType(node)) - + # Check preset is available for node types nodeTypeList = list(set(nodeTypeList)) for nodeType in nodeTypeList: if not presetExists(nodeType,preset): raise Exception('No preset "'+preset+'" available for nodeType "'+nodeType+'"!') - + # Apply preset for node in nodeList: #mm.eval('applyPresetToNode "'+node+'" "" "" "'+preset+'" '+str(amount)) mm.eval('applyAttrPreset '+node+' '+preset+' '+str(amount)) - + # Select nodeList mc.select(nodeList) @@ -92,19 +92,19 @@ def save(node,preset,replaceExisting=False): # Check node if not mc.objExists(node): raise Exception('Node "'+node+'" does not exist!') - + # Get ndoe type nodeType = mc.objectType(node) - + # Check preset if presetExists(nodeType,preset): if not replaceExisting: raise Exception('Attr preset "'+preset+'" for node type "'+nodeType+'" already exists! Set replaceExisting=True to overwrite!') else: print('Overwritting existing "'+preset+'" preset for node type "'+nodeType+'"!') - + # Save preset mm.eval('saveAttrPreset '+node+' '+preset+' false') - + # Return result return preset diff --git a/utils/attribute.py b/utils/attribute.py index fbfbbe7..d1a5c69 100644 --- a/utils/attribute.py +++ b/utils/attribute.py @@ -40,33 +40,33 @@ def getAttrMPlug(attr): # Check attribute if not mc.objExists(attr): raise Exception('Attribute "'+attr+'" does not exist!') - + # Split attr name to elements attrElemList = attr.split('.') - + # Get node function class attrObj = glTools.utils.base.getMObject(attrElemList[0]) attrObjFn = OpenMaya.MFnDependencyNode(attrObj) - + # Get attr element components (name, index) attrElem = re.findall(r'\w+', attrElemList[1]) - + # Get MPlug to top level attribute attrMPlug = attrObjFn.findPlug(attrElem[0],True) if len(attrElem) == 2: attrMPlug = attrMPlug.elementByLogicalIndex(int(attrElem[1])) - + # Traverse to lowest child attribute for i in range(2,len(attrElemList)): - + # Get attr element components (name, index) attrElem = re.findall(r'\w+', attrElemList[i]) - + # Get child attributes childIndex = -1 for n in range(attrMPlug.numChildren()): childPlug = attrMPlug.child(n) print 'Looking for "'+attrElem[0]+'", found "'+childPlug.partialName()+'"' - + # Return result return attrMPlug @@ -78,15 +78,15 @@ def multiIndexList(attr): ''' # Get attribute MPlug attrMPlug = getAttrMPlug(attr) - + # Check multi if not attrMPlug.isArray(): raise Exception('Attribute "'+attr+'" is not a multi!') - + # Check existing indices exIndexList = OpenMaya.MIntArray() attrMPlug.getExistingArrayAttributeIndices(exIndexList) - + # Return Result return list(exIndexList) @@ -95,14 +95,14 @@ def getConnectionIndex(attr,asSource=True,connectedTo=None): ''' # Get MPlug attrPlug = getAttrMPlug(attr) - + # Get Connected Plugs attrPlugConnections = OpenMaya.MPlugArray() connected = attrPlug.connectedTo(attrPlugConnections,not(asSource),asSource) if not connected: connectionType = 'outgoing' if asSource else 'incoming' raise Exception('No '+connectionType+' connections found for attribute "'+attr+'"!') - + # Get Connected Index for i in range(attrPlugConnections.length()): connectedPlug = attrPlugConnections[i] @@ -111,7 +111,7 @@ def getConnectionIndex(attr,asSource=True,connectedTo=None): #print(connectedTo+' != '+connectedNode) continue return connectedPlug.logicalIndex() - + # Return Result return -1 @@ -127,29 +127,29 @@ def nextAvailableMultiIndex(attr,start=0,useConnectedOnly=True,maxIndex=10000000 @param maxIndex: The maximum index search value @type maxIndex: int ''' - # Initialize next index + # Initialize next index nextIndex = -1 - + if useConnectedOnly: - + # Check array indices for i in range(start,maxIndex): - + # Check connections conn = mc.connectionInfo(attr+'['+str(i)+']',sourceFromDestination=True) if not conn: nextIndex = i break else: - + # Check existing indices exIndexList = multiIndexList(attr) indexCount = len(exIndexList) - + # Determin next available if indexCount: nextIndex = list(exIndexList)[-1] + 1 else: nextIndex = 0 - + # Return result return nextIndex @@ -162,26 +162,26 @@ def default(attr): # Check attr if not mc.objExists(attr): raise Exception('Attribute "'+attr+'" does not exist!') - + # Get object from attribute obj = mc.ls(attr,o=True)[0] at = attr.replace(obj+'.','') - + # Build default attribute lists xformAttrList = ['translateX','translateY','translateZ','rotateX','rotateY','rotateZ'] xformAttrList.extend(['tx','tx','tx','rx','rx','rx']) scaleAttrList = ['scaleX','scaleY','scaleZ'] scaleAttrList.extend(['sx','sx','sx']) visAttrList = ['visibility','v'] - + # Query attribute default value if xformAttrList.count(at): return 0.0 if scaleAttrList.count(at): return 1.0 if visAttrList.count(at): return 1.0 - + # Query default for user defined attribute val = mc.addAttr(attr,q=True,dv=True) - + # Return result return val @@ -205,10 +205,10 @@ def distributeAttrValue(targetList,targetAttr,rangeStart=0.0,rangeEnd=1.0,smooth raise Exception('Object "'+targetList[i]+'" does not exist!') if not mc.objExists(targetList[i]+'.'+targetAttr): raise Exception('Object "'+targetList[i]+'" has no ".'+targetAttr+'" attribute!') - + # Get value list vList = glTools.utils.mathUtils.distributeValue(len(targetList),1.0,rangeStart,rangeEnd) - + # Apply values to target list for i in range(len(targetList)): val = vList[i] @@ -229,57 +229,57 @@ def randomizeAttrValues(objectList,attr,minValue=0.0,maxValue=1.0): ''' # Verify list type argument if type(objectList) == str: objectList = [objectList] - + # Iterate through object list for i in range(len(objectList)): # Append abject and attribute names objAttr = objectList[i]+'.'+attr - + # Check attribute extists if not mc.objExists(objAttr): raise Exception('Attribute "'+objAttr+'" does not exist!!') - + # Generate random attribute value rnd = random.random() attrVal = minValue + (maxValue - minValue) * rnd - + # Set Attribute value mc.setAttr(objAttr, attrVal) def deleteUserAttrs(obj,attrList=[],keepIfConnected=False): ''' Delete user defined attrs from a specified object - @param obj: The source objects to copy the attributes from + @param obj: The source objects to copy the attributes from @type obj: str - @param attrList: A list of attributes to delete. If empty, defaults to all. + @param attrList: A list of attributes to delete. If empty, defaults to all. @type attrList: list ''' # Check object if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!!') - + # Get attribute list if not attrList: attrList = mc.listAttr(obj,ud=True) if not attrList: attrList = [] - + # Delete attributes for attr in attrList: - + # Check Attribute Exists if mc.objExists(obj+'.'+attr): - + # Check Connections if keepIfConnected: conns = mc.listConnections(obj+'.'+attr,s=True,d=True) if conns: continue - + # Delete Attribute try: mc.setAttr(obj+'.'+attr,l=False) mc.deleteAttr(obj,at=attr) except: print('Problem removing attribute "'+obj+'.'+attr+'". Skipping to next attribute.') - + # Return result return attrList @@ -296,26 +296,26 @@ def copyAttr(src,dst,attr): # ========== # - Checks - # ========== - + # Check Source and Destination if not mc.objExists(src): raise Exception('Source object "'+src+'" does not exist!!') if not mc.objExists(dst): raise Exception('Destination object "'+dst+'" does not exist!!') - + # Check Source Attribute if not mc.attributeQuery(attr,n=src,ex=True): raise Exception('Source attribute "'+src+'.'+attr+'" does not exist!!') - + # ================== # - Copy Attribute - # ================== - + # Check/Skip Multi if mc.attributeQuery(attr,n=src,m=True): print('Skipping multi attribute "'+src+'.'+attr+'"...') return src+'.'+attr - + # Get Attribute Details attrVal = mc.getAttr(src+'.'+attr) attrType = mc.addAttr(src+'.'+attr,q=True,at=True) @@ -323,46 +323,46 @@ def copyAttr(src,dst,attr): attrVisible = mc.getAttr(src+'.'+attr,cb=True) attrKeyable = mc.getAttr(src+'.'+attr,k=True) attrLocked = mc.getAttr(src+'.'+attr,l=True) - + # Get Attribute Data Type dataType = attrType if attrType == 'typed': dataType = str(mc.addAttr(src+'.'+attr,q=True,dt=True)[0]) - + # Check Destination Attribute if not mc.attributeQuery(attr,n=dst,ex=True): - + # Add Destination Attribute if attrType == 'typed': - mc.addAttr(dst,ln=attr,dt=dataType) + mc.addAttr(dst,ln=attr,dt=dataType) else: mc.addAttr(dst,ln=attr,at=attrType,dv=defaultVal) - + # Set Destination Attribute if attrType == 'typed': mc.setAttr(dst+'.'+attr,attrVal,type=dataType) else: mc.setAttr(dst+'.'+attr,attrVal) - + # Attribute Visibile if attrVisible: try: mc.setAttr(dst+'.'+attr,cb=True) except: pass - + # Attribute Keyable if attrKeyable: try: mc.setAttr(dst+'.'+attr,k=True) except: pass - + # Lock Attribute if attrLocked: try: mc.setAttr(dst+'.'+attr,l=True) except: pass - + # ================= # - Return Result - # ================= - + return dst+'.'+attr def copyUserAttrs(src,dst,attrList=[],search='',replace='',copyConnections=False): @@ -384,26 +384,26 @@ def copyUserAttrs(src,dst,attrList=[],search='',replace='',copyConnections=False # ========== # - Checks - # ========== - + # Check Source and Destination if not mc.objExists(src): raise Exception('Source object "'+src+'" does not exist!!') if not mc.objExists(dst): raise Exception('Destination object "'+dst+'" does not exist!!') - + # Check Attribute List if not attrList: attrList = mc.listAttr(src,ud=True) if not attrList: return [] - + # =================== # - Copy Attributes - # =================== - + for attr in attrList: - + srcAttr = src+'.'+attr dstAttr = copyAttr(src,dst,attr) - + # Search and Replace Attr Value attrType = mc.addAttr(srcAttr,q=True,at=True) if attrType == 'typed': @@ -412,10 +412,10 @@ def copyUserAttrs(src,dst,attrList=[],search='',replace='',copyConnections=False attrVal = mc.getAttr(srcAttr) attrVal = attrVal.replace(search,replace) mc.setAttr(dstAttr,attrVal,type='string') - + # Copy connections if copyConnections: - + # Incoming connections inConnList = mc.listConnections(srcAttr,s=True,d=False,p=True) if inConnList: @@ -423,7 +423,7 @@ def copyUserAttrs(src,dst,attrList=[],search='',replace='',copyConnections=False if search or replace: inConn = inConn.replace(search,replace) mc.connectAttr(inConn,dstAttr,f=True) - + # Outgoing connections outConnList = mc.listConnections(srcAttr,d=True,s=False,p=True) if outConnList: @@ -431,70 +431,70 @@ def copyUserAttrs(src,dst,attrList=[],search='',replace='',copyConnections=False if search or replace: outConn = inConn.replace(search,replace) mc.connectAttr(dstAttr,outConn,f=True) - + # ================= # - Return Result - # ================= - + return attrList - + def copyAttrList(src,dst,connect=False,srcAsMaster=True,attrList=[]): ''' Copy user defined attrs from a source object to a destination object - @param src: The source objects to copy the attributes from + @param src: The source objects to copy the attributes from @type src: str - @param dst: The destination objects to copy the attributes to + @param dst: The destination objects to copy the attributes to @type dst: str - @param connect: Connect the copied attribute to the original + @param connect: Connect the copied attribute to the original @type connect: bool - @param srcAsMaster: Specifies the direction of the attribute connection. + @param srcAsMaster: Specifies the direction of the attribute connection. @type srcAsMaster: bool - @param attrList: List of attributes to copy. If empty, use channelbox selection + @param attrList: List of attributes to copy. If empty, use channelbox selection @type attrList: list ''' # ========== # - Checks - # ========== - + # Check Source and Destination if not mc.objExists(src): raise Exception('Source object "'+src+'" does not exist!!') if not mc.objExists(dst): raise Exception('Destination object "'+dst+'" does not exist!!') - + # Check Attribute List if not attrList: channelBox = 'mainChannelBox' attrList = mc.channelBox(channelBox,q=True,selectedMainAttributes=True) if not attrList: return [] - + # =================== # - Copy Attributes - # =================== - + dstAttrList = [] for attr in attrList: - + # Check Source Attributes srcAttr = src+'.'+attr if not mc.attributeQuery(attr,n=src,ex=True): raise Exception('Source attribute "'+src+'.'+attr+'" does not exist!') - + # Check Destination Attribute dstAttr = copyAttr(src,dst,attr) dstAttrList.append(dstAttr) - + # Connect attributes if connect: if srcAsMaster: mc.connectAttr(srcAttr,dstAttr,f=True) else: mc.connectAttr(dstAttr,srcAttr,f=True) - + # ================= # - Return Result - # ================= - + return dstAttrList def attributeSeparator(control,attr): @@ -508,16 +508,16 @@ def attributeSeparator(control,attr): # Check control if not mc.objExists(control): raise Exception('Control object "'+control+'" does not exist!') - + # Check attribute if mc.objExists(control+'.'+attr): raise Exception('Control attribute "'+control+'.'+attr+'" already exists!') - + # Create attribute mc.addAttr(control,ln=attr,at='enum',en=':-:') mc.setAttr(control+'.'+attr,cb=True) mc.setAttr(control+'.'+attr,l=True) - + # Return result return (control+'.'+attr) @@ -528,10 +528,10 @@ def moveToBottom(attribute): # Determine object and attribute names from input argument obj = attribute.split('.')[0] attr = attribute.split('.')[-1] - + # Delete attribute temporarily mc.deleteAttr(obj,attribute=attr) - + # Undo deletion mc.undo() @@ -546,16 +546,16 @@ def reorder(attr,pos='bottom'): # Checks if not mc.objExists(attr): raise Exception('Attribute "'+attr+'" does not exist!') - + if not attr.count('.'): raise Exception('Unable to determine object from attribute"'+attr+'"!') - + # Get attribute info obj = mc.ls(attr,o=True) if not obj: raise Exception('Unable to determine object from attribute"'+attr+'"!') obj = obj[0] at = attr.replace(obj+'.','') - + # Get attribute lists udAttrList = mc.listAttr(obj,ud=True) if not udAttrList: udAttrList = [] @@ -565,41 +565,41 @@ def reorder(attr,pos='bottom'): if not cbAttrList: cbAttrList = [] allAttrList = [i for i in udAttrList if keyAttrList.count(i) or cbAttrList.count(i)] allAttrLen = len(allAttrList) - - # Get relative attribute index + + # Get relative attribute index attrInd = allAttrList.index(at) - + # Move UP if pos == 'up': - - if not attrInd: return + + if not attrInd: return moveToBottom(obj+'.'+allAttrList[attrInd-1]) for i in allAttrList[attrInd+1:]: moveToBottom(obj+'.'+i) - + # Move DOWN if pos == 'down': - + if attrInd == (allAttrLen-1): return moveToBottom(obj+'.'+allAttrList[attrInd]) - + if attrInd >= (allAttrLen-1): return - + for i in allAttrList[attrInd+2:]: moveToBottom(obj+'.'+i) - + # Move to TOP if pos == 'top': - + for i in range(len(allAttrList)): if i == attrInd: return moveToBottom(obj+'.'+allAttrList[i]) - + # Move to BOTTOM if pos == 'bottom': - + moveToBottom(obj+'.'+allAttrList[attrInd]) - + # Refresh UI mc.channelBox('mainChannelBox',e=True,update=True) @@ -610,9 +610,9 @@ def rename(attr,name): # Check attribute if not mc.objExists(attr): raise Exception('Attribute "'+attr+'" does not exist!') - + # Rename (alias) attribute result = mc.aliasAttr(name,attr) - + # Return result return result diff --git a/utils/base.py b/utils/base.py index 41f4363..a2a1487 100644 --- a/utils/base.py +++ b/utils/base.py @@ -30,7 +30,7 @@ def verifyNode(node,nodeType): # Check Node Exists if not mc.objExists(node): raise Exception('Object "'+node+'" does not exists!') - + # Check Node Type objType = mc.objectType(node) if objType != nodeType: @@ -51,22 +51,22 @@ def isVisible(node,checkLodVis=True,checkDrawOverride=True): raise Exception('Object "'+node+'" does not exist!') if not mc.ls(node,dag=True): raise Exception('Object "'+node+'" is not a valid DAG node!') - + # Get Full Path fullPath = mc.ls(node,l=True)[0] pathPart = fullPath.split('|') pathPart.reverse() - + # Check Visibility isVisible=True for part in pathPart: - + # Skip Unknown Nodes if not part: continue if not mc.objExists(part): print('Unable to find ancestor node "'+part+'"!') continue - + # Check Visibility if not mc.getAttr(part+'.visibility'): isVisible=False @@ -79,7 +79,7 @@ def isVisible(node,checkLodVis=True,checkDrawOverride=True): if mc.getAttr(part+'.overrideEnabled'): if not mc.getAttr(part+'.overrideVisibility'): isVisible=False - + # Return Result return isVisible @@ -99,7 +99,7 @@ def getMObject(object): selectionList.getDependNode(0,mObject) # Return result return mObject - + def getMDagPath(object): ''' Return an MDagPath for the input scene object @@ -109,13 +109,13 @@ def getMDagPath(object): # Check input object if not mc.objExists(object): raise Exception('Object "'+object+'" does not exist!!') - + # Get selection list selectionList = OpenMaya.MSelectionList() OpenMaya.MGlobal.getSelectionListByName(object,selectionList) mDagPath = OpenMaya.MDagPath() selectionList.getDagPath(0,mDagPath) - + # Return result return mDagPath @@ -127,36 +127,36 @@ def getPosition(point): ''' # Initialize point value pos = [] - + # Determine point type if (type(point) == list) or (type(point) == tuple): if len(point) < 3: raise Exception('Invalid point value supplied! Not enough list/tuple elements!') pos = point[0:3] elif (type(point) == str) or (type(point) == unicode): - + # Check Transform mObject = getMObject(point) if mObject.hasFn(OpenMaya.MFn.kTransform): try: pos = mc.xform(point,q=True,ws=True,rp=True) except: pass - + # pointPosition query if not pos: try: pos = mc.pointPosition(point) except: pass - + # xform - rotate pivot query if not pos: try: pos = mc.xform(point,q=True,ws=True,rp=True) except: pass - + # Unknown type if not pos: raise Exception('Invalid point value supplied! Unable to determine type of point "'+str(point)+'"!') else: raise Exception('Invalid point value supplied! Invalid argument type!') - + # Return result return pos @@ -174,7 +174,7 @@ def getMPoint(point): mPoint = OpenMaya.MPoint(pos[0],pos[1],pos[2],1.0) # Return result return mPoint - + def getMPointArray(geometry,worldSpace=True): ''' Return an MPointArray containing the component positions for the specified geometry @@ -186,13 +186,13 @@ def getMPointArray(geometry,worldSpace=True): # Check geometry if geometry and not mc.objExists(geometry): raise Exception('Object "'+geometry+'" does not exist!') - + # Get points to generate weights from pointList = OpenMaya.MPointArray() if getMObject(geometry).hasFn(OpenMaya.MFn.kTransform): try: geometry = mc.listRelatives(geometry,s=True,ni=True,pa=True)[0] except: raise Exception('Object "'+geometry+'" contains no valid geometry!') - + # Check worldSpace if worldSpace: shapeObj = getMDagPath(geometry) @@ -200,7 +200,7 @@ def getMPointArray(geometry,worldSpace=True): else: shapeObj = getMObject(geometry) mSpace = OpenMaya.MSpace.kObject - + # Check shape type shapeType = mc.objectType(geometry) if shapeType == 'mesh': @@ -212,7 +212,7 @@ def getMPointArray(geometry,worldSpace=True): if shapeType == 'nurbsSurface': surfaceFn = OpenMaya.MFnNurbsSurface(shapeObj) surfaceFn.getCVs(pointList,mSpace) - + # Return result return pointList @@ -227,11 +227,11 @@ def getPointArray(geometry,worldSpace=True): # Initialize arrays ptArray = [] mPtArray = getMPointArray(geometry,worldSpace) - + # Convert to python list for i in range(mPtArray.length()): ptArray.append([mPtArray[i][0],mPtArray[i][1],mPtArray[i][2]]) - + # Return Result return ptArray @@ -246,19 +246,19 @@ def getMBoundingBox(geometry,worldSpace=True): # Check geometry if geometry and not mc.objExists(geometry): raise Exception('Object "'+geometry+'" does not exist!') - + # Get MBoundingBox geoPath = getMDagPath(geometry) geoNodeFn = OpenMaya.MFnDagNode(geoPath) geoBBox = geoNodeFn.boundingBox() - + # Transform to world space if worldSpace: geoBBox.transformUsing(geoPath.exclusiveMatrix()) else: print('!!!Local space bounding box is not reliable with current code!!!') geoBBox.transformUsing(geoNodeFn.transformationMatrix().inverse()) - + # Return result return geoBBox @@ -270,16 +270,16 @@ def getCenter(ptList): ''' # Initialize Result avgPt = [0,0,0] - + # Get Center Point numPt = len(ptList) for pt in ptList: ptPos = glTools.utils.base.getPosition(pt) avgPt = [avgPt[0]+ptPos[0],avgPt[1]+ptPos[1],avgPt[2]+ptPos[2]] - + # Calculate Average Position avgPt = [avgPt[0]/numPt,avgPt[1]/numPt,avgPt[2]/numPt] - + # Return Result return avgPt @@ -288,15 +288,15 @@ def displayOverride(obj,overrideEnable=0,overrideDisplay=0,overrideLOD=0,overrid Set display override for the specified object. @param obj: Object to set display overrides for @type obj: str - @param overrideEnable: Sets the display override enable state for the specified DAG object + @param overrideEnable: Sets the display override enable state for the specified DAG object @type overrideEnable: int @param overrideDisplay: Sets the display override type for the specified DAG object. 0=Normal, 1=Template, 2=Reference @type overrideDisplay: int @param overrideLOD: Sets the display override level of detail value for the specified DAG object. 0=Full, 1=BoundingBox @type overrideLOD: int - @param overrideVisibility: Sets the display override visibility value for the specified DAG object + @param overrideVisibility: Sets the display override visibility value for the specified DAG object @type overrideVisibility: int - @param overrideShading: Sets the display override shading value for the specified DAG object + @param overrideShading: Sets the display override shading value for the specified DAG object @type overrideShading: int ''' # Checks @@ -321,20 +321,20 @@ def setNodeState(nodeList,state=1): ''' # Check input type if type(nodeList) == str or type(nodeList) == unicode: nodeList = [str(nodeList)] - + # For each node in the input list for node in nodeList: - + # Check node if not mc.objExists(node): raise Exception('Node "'+node+'" does not exist!') - + # Check nodeState attr if state and mc.getAttr(node+'.nodeState') == 0: continue if not state and mc.getAttr(node+'.nodeState') == 1: continue if not mc.getAttr(node+'.nodeState',se=True): print('nodeState attribute for node "'+node+'" is not settable! Skipping node...') - + # Set nodeState value if state: mc.setAttr(node+'.nodeState',0) else: mc.setAttr(node+'.nodeState',1) @@ -353,33 +353,33 @@ def renameChain(root,renameStr='',useAlpha=True): # ======================= # - Check Rename String - # ======================= - + # Check Rename String if not renameStr: - + result = mc.promptDialog( title='Rename Chain', message='Enter Rename String:', button=['Rename', 'Cancel'], defaultButton='Rename', cancelButton='Cancel', dismissString='Cancel' ) - + if result == 'Rename': - renameStr = mc.promptDialog(q=True,text=True) - + renameStr = mc.promptDialog(q=True,text=True) + # Check "#" Characters numHash = renameStr.count('#') substring = '#' * numHash if not renameStr.count(substring): raise Exception('Invalid rename string! Pound characters must be consecutive!') - + # ================== # - Get Chain List - # ================== - + root = str(root) - - chainList = [] + + chainList = [] chainNode = str(mc.ls(mc.listRelatives(root,ad=True,pa=True),type='joint')[0]) while(True): chainList.append(chainNode) @@ -387,33 +387,33 @@ def renameChain(root,renameStr='',useAlpha=True): chainNode = str(mc.listRelatives(chainList[-1],p=True,pa=True)[0]) chainList.reverse() chainLen = len(chainList) - + # ====================== # - Rename Chain Nodes - # ====================== - + # Temp Rename to Avoid Name Clash for i in range(chainLen): indStr = 'XXX'+str(i) chainList[i] = mc.rename(chainList[i],renameStr.replace(substring,indStr)) - + for i in range(chainLen-1): - + # Get instance string indStr = '' if useAlpha: indStr = glTools.utils.stringUtils.alphaIndex(i,upper=True) else: indStr = glTools.utils.stringUtils.stringIndex(i+1,len(substring)) - + # Rename chainList[i] = mc.rename(chainList[i],renameStr.replace(substring,indStr)) - + # Rename Chain End chainList[-1] = mc.rename(chainList[-1],renameStr.replace(substring,'End')) - + # ================= # - Retrun Result - # ================= - + return chainList def group(obj,center=True,orient=True,groupType='transform',name=''): @@ -459,19 +459,19 @@ def group_old(control,groupType=1,center=True,orient=True): # Check groupType if not range(3).count(groupType): raise Exception('Invalid groupType value supplied!!('+str(groupType)+')') - + # Generate group name prefix = glTools.utils.stringUtils.stripSuffix(control) grp = prefix+'_'+groupType - + # Create Group if groupType == 2: grp = mc.createNode('joint',n=grp) else: grp = mc.createNode('transform',n=grp) - + # Align to object grp = mc.parent(grp,control)[0] mc.makeIdentity(grp,apply=True,t=1,r=orient,s=1,jo=1,n=0) - + # Correct heirarchy parent = mc.listRelatives(control,p=True,pa=True) if parent: grp = mc.parent(grp,parent[0])[0] @@ -479,15 +479,15 @@ def group_old(control,groupType=1,center=True,orient=True): # Reset transform scale values mc.makeIdentity(grp,apply=True,t=0,r=0,s=1,n=0) control = mc.parent(control,grp)[0] - + # Center pivot if center: piv = mc.xform(control,q=True,ws=True,rp=True) mc.xform(grp,piv=piv,ws=True) - + # Return group name as result string return grp - + def getHierarchyList(start,end): ''' Return an ordered hierarchy object list between a specified start and end object @@ -501,21 +501,21 @@ def getHierarchyList(start,end): raise Exception('Start object "'+start+'" does not exist!') if not mc.objExists(end): raise Exception('End object "'+end+'" does not exist!') - + # Check end is in start hierarchy start_hier = mc.listRelatives(start,ad=True) if not start_hier.count(end): raise Exception('End object "'+end+'" is not a decendant of start object "'+start+'"!') - + # Build hierarchy list heir = [end] while heir[-1] != start: par = mc.listRelatives(heir[-1],p=True)[0] heir.append(par) - + # Reverse hierarchy list for correct order heir.reverse() - + # Return result return heir @@ -530,15 +530,15 @@ def dagSort(objectList=[]): objectList = mc.ls(sl=1) objectList = mc.listRelatives(objectList,ad=True) objectList = mc.ls(objectList,transforms=True) - + # Sort Object List objectList.sort() objectList.reverse() - + # Reorder Objects for i in objectList: mc.reorder(i,f=True) - + # Return Result return objectList @@ -570,31 +570,31 @@ def renameHistoryNodes(obj,nodeType,prefix='',suffix='',stripOldSuffix=True): # Check object if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check prefix if not prefix: if stripOldSuffix: prefix = glTools.utils.stringUtils.stripSuffix(obj) else: prefix = obj - + # Get object history if nodeType.lower() == 'all': nodeHist = mc.ls(mc.listHistory(obj)) else: nodeHist = mc.ls(mc.listHistory(obj),type=nodeType) nodeHist.sort() - + # For each history node nodeCount = len(nodeHist) for n in range(nodeCount): - + # Check suffix if not suffix: nodeSuffix = mc.objectType(nodeHist[n]) else: nodeSuffix = suffix - + # Check index if nodeCount > 1: nodeSuffix = glTools.utils.stringUtils.stringIndex(n,1) + '_' + nodeSuffix - + # Rename node nodeHist[n] = mc.rename(nodeHist[n],prefix+'_'+nodeSuffix) - + # Return result return nodeHist @@ -608,12 +608,12 @@ def renameDuplicates(padding=3): badXforms = [f for f in mc.ls() if '|' in f] badXformsUnlock = [f for f in badXforms if mc.lockNode(f,q=1,lock=1)[0] == False] count = 0 - + # Sort list by the number of '|' appearing in each name. # This way we can edit names from the bottom of the hierarchy up, and not worry about losing child objects from the list. countDict = {} for f in badXformsUnlock: countDict[f] = f.count('|') - + # Sort the dictionary by value, in reverse, and start renaming. renamed = [] for key,value in sorted(countDict.iteritems(),reverse=True, key=lambda (key,value): (value,key)): @@ -630,7 +630,7 @@ def renameDuplicates(padding=3): renamed.append(newObj) print 'renamed %s to %s' % (key,newObj) count = count+1 - + # Return Result if count < 1: print 'No duplicate names found.' @@ -650,14 +650,14 @@ def closestPointIndex(pt,ptList): # Initialize dist = 99999999999 ind = -1 - + # Iterate over target points for p in range(len(ptList)): d = glTools.utils.mathUtils.distanceBetween(pt,ptList[p]) if d < dist: dist = d ind = p - + # Return Result return ind @@ -678,39 +678,39 @@ def unitConversion(plug,conversionFactor=1.0,conversionFactorSourcePlug='',plugI # Check plug if not mc.objExists(plug): raise Exception('Plug '+plug+' does not exist!!') if not plug.count('.'): raise Exception('Object '+plug+' is not a valid plug (node.attr)!!') - + # Check conversionFactorSourcePlug if conversionFactorSourcePlug: if not mc.objExists(conversionFactorSourcePlug): raise Exception('Conversion factor source plug '+conversionFactorSourcePlug+' does not exist!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(control.split('.')[0]) - + # Get existing plug connections conns = mc.listConnections(plug,s=not plugIsSource,d=plugIsSource,p=True) - + # Create unitConversion node unitConversion = mc.createNode('unitConversion',n=prefix+'_unitConversion') mc.setAttr(unitConversion+'.conversionFactor',conversionFactor) - + # Connect conversion factor if conversionFactorSourcePlug: mc.connectAttr(conversionFactorSourcePlug,unitConversion+'.conversionFactor',f=True) - + # Connect plug if plugIsSource: mc.connectAttr(plug,unitConversion+'.input',f=True) else: if conns: mc.connectAttr(conns[0],unitConversion+'.input',f=True) - + # Connect to destination plugs if plugIsSource: if conns: for conn in conns: mc.connectAttr(unitConversion+'.output',conn,f=True) else: mc.connectAttr(unitConversion+'.output',plug,f=True) - + # Return result return unitConversion @@ -739,66 +739,66 @@ def remapValue(inputAttr,targetAttr='',inputMin=0,inputMax=1,outputMin=0,outputM # ========== # - Checks - # ========== - + # Input Attributes if not mc.objExists(inputAttr): raise Exception('Input attribute "'+inputAttr+'" does not exist!') try: mc.getAttr(inputAttr,l=True) except: raise Exception('Input attribute argument "'+inputAttr+'" is not a valid attribute!') - + # Target if targetAttr: if not mc.objExists(targetAttr): raise Exception('Target attribute "'+targetAttr+'" does not exist!') try: mc.getAttr(targetAttr,l=True) except: raise Exception('Target attribute argument "'+targetAttr+'" is not a valid attribute!') - + # Interp Type interpTypeList = ['none','linear','smooth','spline'] if not interpTypeList.count(interpType): raise Exception('Invalid interpolation type specified! ("'+interpType+'")') - + # Prefix if not prefix: prefix = inputAttr.replace('.','_') - + # ========================== # - Create RemapValue Node - # ========================== - + remapValueNode = mc.createNode('remapValue',n=prefix+'_remapValue') - + # Connect Input mc.connectAttr(inputAttr,remapValueNode+'.inputValue',f=True) - + # Set Input/Output Min/Max mc.setAttr(remapValueNode+'.inputMin',inputMin) mc.setAttr(remapValueNode+'.inputMax',inputMax) mc.setAttr(remapValueNode+'.outputMin',outputMin) mc.setAttr(remapValueNode+'.outputMax',outputMax) - + # Interp Type interpTypeInd = interpTypeList.index(interpType) mc.setAttr(remapValueNode+'.value[0].value_Interp',interpTypeInd) mc.setAttr(remapValueNode+'.value[1].value_Interp',interpTypeInd) - + # ==================== # - Plot Ramp Values - # ==================== - + for i in range(len(rampValues)): - + mc.setAttr(remapValueNode+'.value['+str(i)+'].value_Position',rampValues[i][0]) mc.setAttr(remapValueNode+'.value['+str(i)+'].value_FloatValue',rampValues[i][1]) mc.setAttr(remapValueNode+'.value['+str(i)+'].value_Interp',interpTypeInd) - + # =============================== # - Connect to Target Attribute - # =============================== - + if targetAttr: mc.connectAttr(remapValueNode+'.outValue',targetAttr,f=True) - + # ================= # - Return Result - # ================= - + return remapValueNode diff --git a/utils/blendShape.py b/utils/blendShape.py index 5d80ac6..fe6f45e 100644 --- a/utils/blendShape.py +++ b/utils/blendShape.py @@ -34,24 +34,24 @@ def create(baseGeo,targetGeo=[],origin='local',deformOrder=None,prefix=None): # ========== # - Checks - # ========== - + # Check Base Geometry if not mc.objExists(baseGeo): raise Exception('Base geometry "'+baseGeo+'" does not exist!') - + # Check Prefix if not prefix: prefix = baseGeo.split(':')[-1] - + # Check BlendShape blendShape = prefix+'_blendShape' if glTools.utils.blendShape.isBlendShape(blendShape): print('BlendShape "'+blendShape+'" already exist!') return blendShape - + # ===================== # - Create BlendShape - # ===================== - + if deformOrder == 'after': blendShape = mc.blendShape(baseGeo,name=blendShape,origin=origin,after=True)[0] elif deformOrder == 'before': @@ -64,23 +64,23 @@ def create(baseGeo,targetGeo=[],origin='local',deformOrder=None,prefix=None): blendShape = mc.blendShape(baseGeo,name=blendShape,origin=origin,foc=True)[0] else: blendShape = mc.blendShape(baseGeo,name=blendShape,origin=origin)[0] - + # =============== # - Add Targets - # =============== - + for target in targetGeo: addTarget(blendShape=blendShape,target=target,base=baseGeo) - + # ================= # - Return Result - # ================= - + return blendShape def hasBase(blendShape,base): ''' - Check if the a blendShape has a specific base geometry + Check if the a blendShape has a specific base geometry @param blendShape: BlendShape node to query @type blendShape: str @param base: Base geometry to query @@ -89,16 +89,16 @@ def hasBase(blendShape,base): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Check target if base in getBaseGeo(blendShape): return True - + # Return Result return False def hasTarget(blendShape,target): ''' - Specify if the a named target exists on a blendShape node + Specify if the a named target exists on a blendShape node @param blendShape: Name of blendShape to query @type blendShape: str @param target: BlendShape target to query @@ -107,16 +107,16 @@ def hasTarget(blendShape,target): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Check target if target in getTargetList(blendShape): return True - + # Return Result return False def hasTargetGeo(blendShape,target,base=''): ''' - Check if the specified blendShape target has live target geometry. + Check if the specified blendShape target has live target geometry. @param blendShape: Name of blendShape to query @type blendShape: str @param target: BlendShape target to query @@ -127,14 +127,14 @@ def hasTargetGeo(blendShape,target,base=''): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Check target if not target in getTargetList(blendShape): raise Exception('BlendShape "'+blendShape+'" has no target "'+target+'"!') - + # Check Target Geometry targetGeo = getTargetGeo(blendShape,target,baseGeo=base) - + # Return Result return bool(targetGeo) @@ -147,7 +147,7 @@ def addTarget(blendShape,target,base='',targetIndex=-1,targetAlias='',targetWeig @type target: str @param base: BlendShape base geometry. If empty, use first connected base geomtry @type base: str - @param targetIndex: Specify the target index. If less than 0, use next available index. + @param targetIndex: Specify the target index. If less than 0, use next available index. @type targetIndex: str @param targetAlias: Override the default blendShape target alias with this string @type targetAlias: str @@ -157,50 +157,50 @@ def addTarget(blendShape,target,base='',targetIndex=-1,targetAlias='',targetWeig # ========== # - Checks - # ========== - + # BlendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Target if not mc.objExists(target): raise Exception('Target geometry "'+target+'" does not exist!') - + # Base if base and not mc.objExists(base): raise Exception('Base geometry "'+base+'" does not exist!') - + # ============== # - Add Target - # ============== - + # Get Base Geometry if not base: base = getBaseGeo(blendShape)[0] - # Get Target Index + # Get Target Index if targetIndex < 0: targetIndex = nextAvailableTargetIndex(blendShape) - + # Add Target mc.blendShape(blendShape,e=True,t=(base,targetIndex,target,1.0),topologyCheck=topologyCheck) - + # Get Target Name targetName = getTargetName(blendShape,target) - + # Override Target Alias if targetAlias: targetIndex = getTargetIndex(blendShape,targetName) mc.aliasAttr(targetAlias,blendShape+'.weight['+str(targetIndex)+']') targetName = targetAlias - + # ===================== # - Set Target Weight - # ===================== - + if targetWeight: mc.setAttr(blendShape+'.'+targetName,targetWeight) - + # ================= # - Return Result - # ================= - + return (blendShape+'.'+targetName) def addTargetInbetween(blendShape,targetGeo,targetName,base='',targetWeight='0.5'): @@ -220,38 +220,38 @@ def addTargetInbetween(blendShape,targetGeo,targetName,base='',targetWeight='0.5 # ========== # - Checks - # ========== - + # BlendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Target if not mc.objExists(targetGeo): raise Exception('Target geometry "'+target+'" does not exist!') if not hasTarget(blendShape,targetName): raise Exception('BlendShape "'+blendShape+'" has no target "'+targetName+'"!') - + # Base if base and not mc.objExists(base): raise Exception('Base geometry "'+base+'" does not exist!') - + # ======================== # - Add Target Inbetween - # ======================== - + # Get Base Geometry if not base: base = getBaseGeo(blendShape)[0] - + # Get Target Index targetIndex = getTargetIndex(blendShape,targetName) - + # Add Target mc.blendShape(blendShape,e=True,t=(base,targetIndex,targetGeo,targetWeight)) - + # ================= # - Return Result - # ================= - + return (blendShape+'.'+targetName) def getBaseGeo(blendShape): @@ -263,24 +263,24 @@ def getBaseGeo(blendShape): # ========== # - Checks - # ========== - + # BlendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # ===================== # - Get Base Geometry - # ===================== - + baseGeo = glTools.utils.deformer.getAffectedGeometry(blendShape) baseGeoList = zip(baseGeo.values(),baseGeo.keys()) baseGeoList.sort() baseGeoList = [i[1] for i in baseGeoList] - + # ================= # - Return Result - # ================= - + return baseGeoList def getBaseIndex(blendShape,base): @@ -296,13 +296,13 @@ def getBaseIndex(blendShape,base): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') if not hasBase(blendShape,base): raise Exception('Obejct "'+base+'" is not a base geometry for blendShape "'+blendShape+'"!') - + # Get Base Index baseGeo = glTools.utils.deformer.getAffectedGeometry(blendShape) if not baseGeo.has_key(base): raise Exception('Unable to determine base index for "'+base+'" on blendShape "'+blendShape+'"!') baseGeo[base] - + # Return Result return baseGeo[base] @@ -315,11 +315,11 @@ def getTargetList(blendShape): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Get attribute alias targetList = mc.listAttr(blendShape+'.w',m=True) if not targetList: targetList = [] - + # Return result return targetList @@ -333,15 +333,15 @@ def getTargetGeoList(blendShape,baseGeo=''): ''' # Get blendShape Target List targetList = getTargetList(blendShape) - + # Get Target Geo List targetGeoList = [] for target in targetList: - + # Get Target Source Geo targetGeo = getTargetGeo(blendShape,target,baseGeo) targetGeoList.append(targetGeo) - + # Return Result return targetGeoList @@ -357,22 +357,22 @@ def getTargetGeo(blendShape,target,baseGeo=''): ''' # Get Target Index targetIndex = getTargetIndex(blendShape,target) - + # Get Geometry Index geomIndex = 0 if baseGeo: geomIndex = glTools.utils.deformer.getGeomIndex(baseGeo,blendShape) - + # Get Weight Index # !!! Hardcoded to check "inputTargetItem" index 6000. This could be more robust by check all existing multi indexes. wtIndex = 6000 - + # Get Connected Target Geometry targetGeoAttr = blendShape+'.inputTarget['+str(geomIndex)+'].inputTargetGroup['+str(targetIndex)+'].inputTargetItem['+str(wtIndex)+'].inputGeomTarget' targetGeoConn = mc.listConnections(targetGeoAttr,s=True,d=False) - + # Check Target Geometry if not targetGeoConn: targetGeoConn = [''] - + # Return Result return targetGeoConn[0] @@ -387,24 +387,24 @@ def getTargetName(blendShape,targetGeo): # ========== # - Checks - # ========== - + # BlendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Target if not mc.objExists(targetGeo): raise Exception('Target geometry "'+targetGeo+'" does not exist!') - + # =================== # - Get Target Name - # =================== - + # Get Target Shapes targetShape = glTools.utils.shape.getShapes(targetGeo,nonIntermediates=True,intermediates=False) if not targetShape: targetShape = mc.ls(mc.listRelatives(targetGeo,ad=True,pa=True),shapes=True,noIntermediate=True) if not targetShape: raise Exception('No shapes found under target geometry "'+targetGeo+'"!') - + # Find Target Connection targetConn = mc.listConnections(targetShape,sh=True,d=True,s=False,p=False,c=True) if not targetConn.count(blendShape): @@ -412,16 +412,16 @@ def getTargetName(blendShape,targetGeo): targetConnInd = targetConn.index(blendShape) targetConnAttr = targetConn[targetConnInd-1] targetConnPlug = mc.listConnections(targetConnAttr,sh=True,p=True,d=True,s=False)[0] - + # Get Target Index targetInd = int(targetConnPlug.split('.')[2].split('[')[1].split(']')[0]) # Get Target Alias targetAlias = mc.aliasAttr(blendShape+'.weight['+str(targetInd)+']',q=True) - + # ================= # - Return Result - # ================= - + return targetAlias def getTargetIndex(blendShape,target): @@ -435,19 +435,19 @@ def getTargetIndex(blendShape,target): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Check target if not mc.objExists(blendShape+'.'+target): raise Exception('Blendshape "'+blendShape+'" has no target "'+target+'"!') - + # Get attribute alias aliasList = mc.aliasAttr(blendShape,q=True) aliasIndex = aliasList.index(target) aliasAttr = aliasList[aliasIndex+1] - + # Get index targetIndex = int(aliasAttr.split('[')[-1].split(']')[0]) - + # Return result return targetIndex @@ -460,15 +460,15 @@ def nextAvailableTargetIndex(blendShape): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Get blendShape target list targetList = getTargetList(blendShape) if not targetList: return 0 - + # Get last index lastIndex = getTargetIndex(blendShape,targetList[-1]) nextIndex = lastIndex + 1 - + # Return result return nextIndex @@ -485,31 +485,31 @@ def getTargetWeights(blendShape,target,geometry=''): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Check target if not mc.objExists(blendShape+'.'+target): raise Exception('blendShape "'+blendShape+'" has no "'+target+'" target attribute!') - + # Check geometry if geometry and not mc.objExists(geometry): raise Exception('Object "'+geometry+'" does not exist!') - + # Get target index aliasList = mc.aliasAttr(blendShape,q=True) aliasTarget = aliasList[(aliasList.index(target)+1)] targetIndex = aliasTarget.split('[')[-1] targetIndex = int(targetIndex.split(']')[0]) - + # Get geometry index into blendShape geomIndex = 0 if geometry: geomIndex = glTools.utils.deformer.getGeomIndex(geometry,blendShape) - + # Get weights wt = mc.getAttr(blendShape+'.it['+str(geomIndex)+'].itg['+str(targetIndex)+'].tw')[0] - + # Return result return list(wt) - + def setTargetWeights(blendShape,target,wt,geometry=''): ''' Set per vertex target weights for the specified blendShape target @@ -525,27 +525,27 @@ def setTargetWeights(blendShape,target,wt,geometry=''): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Check target if not mc.objExists(blendShape+'.'+target): raise Exception('blendShape "'+blendShape+'" has no "'+target+'" target attribute!') - + # Check geometry if geometry and not mc.objExists(geometry): raise Exception('Object "'+geometry+'" does not exist!') - + # Get target index aliasList = mc.aliasAttr(blendShape,q=True) aliasTarget = aliasList[(aliasList.index(target)+1)] targetIndex = aliasTarget.split('[')[-1] targetIndex = int(targetIndex.split(']')[0]) - + # Get geometry index into blendShape geomIndex = 0 if geometry: geomIndex = glTools.utils.deformer.getGeomIndex(geometry,blendShape) # Get number of geometry components compCount = glTools.utils.component.getComponentCount(geometry) - + # Set target weights mc.setAttr(blendShape+'.it['+str(geomIndex)+'].itg['+str(targetIndex)+'].tw[0:'+str(compCount-1)+']',*wt) @@ -568,29 +568,29 @@ def connectToTarget(blendShape,targetGeo,targetName,baseGeo,weight=1.0,force=Fal # ========== # - Checks - # ========== - + # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Check target if not hasTarget(blendShape,targetName): raise Exception('Blendshape "'+blendShape+'" has no target "'+target+'"!') - + # Check Target Geometry if not mc.objExists(targetGeo): raise Exception('Target geometry "'+targetGeo+'" does not exist!') - + # ===================== # - Connect To Target - # ===================== - + # Get target index targetIndex = getTargetIndex(blendShape,targetName) - + # FORCE connection if force: - + # Get geometry details geomIndex = glTools.utils.deformer.getGeomIndex(baseGeo,blendShape) geomShape = mc.listRelatives(targetGeo,s=True,ni=True) @@ -600,21 +600,21 @@ def connectToTarget(blendShape,targetGeo,targetName,baseGeo,weight=1.0,force=Fal else: geomShape = targetGeo geomType = 'none' - + # Get geometry type output attribute. # Non dict values allow specific node attributes to be connected!! geomDict = {'mesh':'.worldMesh[0]','nurbsSurface':'.worldSpace[0]','nurbsCurve':'.worldSpace[0]'} if geomDict.has_key(geomType): geomAttr = geomDict[geomType] else: geomAttr = '' - + # Get weight index wtIndex = int(weight*6000) - + # Connect geometry to target input mc.connectAttr(geomShape+geomAttr,blendShape+'.inputTarget['+str(geomIndex)+'].inputTargetGroup['+str(targetIndex)+'].inputTargetItem['+str(wtIndex)+'].inputGeomTarget',f=True) - + else: - + # Check InBetween if hasTarget(blendShape,targetName) and weight != 1.0: # Connect geometry to target input as inbetween @@ -622,7 +622,7 @@ def connectToTarget(blendShape,targetGeo,targetName,baseGeo,weight=1.0,force=Fal else: # Connect geometry to target input mc.blendShape(blendShape,e=True,t=[baseGeo,targetIndex,targetGeo,weight]) - + def renameTarget(blendShape,target,newName): ''' Rename the specified blendShape target @@ -636,14 +636,14 @@ def renameTarget(blendShape,target,newName): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Check target if not hasTarget(blendShape,target): raise Exception('BlendShape "'+blendShape+'" has no target "'+target+'"!') - + # Rename target attribute mc.aliasAttr(newName,blendShape+'.'+target) - + # Return Result return newName @@ -660,14 +660,14 @@ def removeTarget(blendShape,target,baseGeo): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape node!') - + # Check target if not hasTarget(blendShape,target): raise Exception('BlendShape "'+blendShape+'" has no target "'+target+'"!') - + # Get target index targetIndex = getTargetIndex(blendShape,target) - + # Connect null duplicate targetGeo = getTargetGeo(blendShape,target,baseGeo) if not targetGeo: @@ -675,7 +675,7 @@ def removeTarget(blendShape,target,baseGeo): targetGeo = mc.duplicate(baseGeo)[0] mc.setAttr(blendShape+'.envelope',1.0) connectToTarget(blendShape,targetGeo,target,baseGeo,1.0,force=True) - + # Remove target mc.blendShape(blendShape,e=True,rm=True,t=[baseGeo,targetIndex,targetGeo,1.0]) @@ -690,15 +690,15 @@ def removeUnconnectedTargets(blendShape,base): # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "'+blendShape+'" is not a valid blendShape deformer!!') - + # Get blendShape target list targetList = getTargetList(blendShape) - + # Check blendShape target connections deletedTargetList = [] for target in targetList: targetConn = mc.listConnections(blendShape+'.'+target,s=True,d=False) - + # If no incoming connnections, delete target if not targetConn: try: @@ -708,6 +708,6 @@ def removeUnconnectedTargets(blendShape,base): else: print('Target "'+target+'" deleted!') deletedTargetList.append(target) - + # Return result return deletedTargetList diff --git a/utils/boundingBox.py b/utils/boundingBox.py index 8faaa13..0e0b9a0 100644 --- a/utils/boundingBox.py +++ b/utils/boundingBox.py @@ -12,13 +12,13 @@ def geometryBoundingBox(geometry,worldSpace=True,noIntermediate=True,visibleOnly # Initialize Object Classes geoDagPath = OpenMaya.MDagPath() selectionList = OpenMaya.MSelectionList() - + # Initialize empty bounding box bbox = OpenMaya.MBoundingBox() - + # Get Visible Geometry (Shapes) geoShapes = mc.ls(mc.listRelatives(geometry,ad=True,pa=True),noIntermediate=noIntermediate,geometry=True,visible=visibleOnly) - + # Expand Bounding Box for shape in geoShapes: selectionList.clear() @@ -27,7 +27,7 @@ def geometryBoundingBox(geometry,worldSpace=True,noIntermediate=True,visibleOnly bboxShape = OpenMaya.MFnDagNode(geoDagPath).boundingBox() if worldSpace: bboxShape.transformUsing(geoDagPath.inclusiveMatrix()) bbox.expand(bboxShape) - + # Get Bounding Box Min/Max (as MPoint) mn = bbox.min() mx = bbox.max() @@ -43,16 +43,16 @@ def calcBoundingBox(ptList): ''' # Initialize Bounding Box bbox = OpenMaya.MBoundingBox() - + # Add Points for pt in ptList: - + # Get MPoint mpt = glTools.utils.base.getMPoint(pt) - + # Expand BoundingBox if not bbox.contains(mpt): bbox.expand(mpt) - + # Return Result return bbox @@ -76,10 +76,10 @@ def getBoundingBoxMin(geometry,worldSpace=True): ''' # Get MBoundingBox bbox = getBoundingBox(geometry,worldSpace=worldSpace) - + # Get Min mn = bbox.min() - + # Return Result return [mn[0],mn[1],mn[2]] @@ -93,10 +93,10 @@ def getBoundingBoxMax(geometry,worldSpace=True): ''' # Get MBoundingBox bbox = getBoundingBox(geometry,worldSpace=worldSpace) - + # Get Max mx = bbox.max() - + # Return Result return [mx[0],mx[1],mx[2]] @@ -110,10 +110,10 @@ def getBoundingBoxCenter(geometry,worldSpace=True): ''' # Get MBoundingBox bbox = getBoundingBox(geometry,worldSpace=worldSpace) - + # Get Min/Max ct = bbox.center() - + # Return Result return [ct[0],ct[1],ct[2]] @@ -128,10 +128,10 @@ def getBoundingBoxScale(geometry,worldSpace=True): # Get Bounding Box Min/Max minPt = getBoundingBoxMin(geometry,worldSpace=worldSpace) maxPt = getBoundingBoxMax(geometry,worldSpace=worldSpace) - + # Calculate Scale scale = [maxPt[i]-minPt[i] for i in range(3)] - + # Return Result return scale @@ -149,26 +149,26 @@ def match(geometry,targetGeometry,worldSpace=True): # ========== # - Checks - # ========== - + if not geometry: raise Exception('Invalid or empty geometry argument value! (geometry)') if not targetGeometry: raise Exception('Invalid or empty target geometry argument value! (targetGeometry)') if not mc.objExists(geometry): raise Exception('Geometry object "'+geometry+'" does not exist!') if not mc.objExists(targetGeometry): raise Exception('Target geometry object "'+targetGeometry+'" does not exist!') - + # ======================== # - Match Bounding Boxes - # ======================== - + # Get Current Position and Scale sourcePt = getBoundingBoxCenter(geometry) sourceSc = getBoundingBoxScale(geometry) - + # Get Target Position and Scale targetPt = getBoundingBoxCenter(targetGeometry) targetSc = getBoundingBoxScale(targetGeometry) - + # Calc/Apply New Position and Scale mc.scale(targetSc[0]/sourceSc[0],targetSc[1]/sourceSc[1],targetSc[2]/sourceSc[2],geometry,pivot=sourcePt,relative=True) mc.move(targetPt[0]-sourcePt[0],targetPt[1]-sourcePt[1],targetPt[2]-sourcePt[2],geometry,relative=True) diff --git a/utils/camera.py b/utils/camera.py index 16fc832..ed0df5f 100644 --- a/utils/camera.py +++ b/utils/camera.py @@ -13,18 +13,18 @@ def isCamera(obj): ''' # Check object exists if not mc.objExists(obj): return False - + # Get Shapes objShapes = [obj] if glTools.utils.transform.isTransform(obj): objShapes = mc.listRelatives(obj,s=True,pa=True) if not objShapes: return False - + # Check Shapes for shape in objShapes: if mc.objectType(shape) == 'camera': return True - + # Return Result return False @@ -41,13 +41,13 @@ def getEyePoint(camera): # Check Camera if not isCamera(camera): raise Exception('Object "'+camera+'" is not a valid camera!') - + # Get Eye Point cameraShape = mc.ls(mc.listRelatives(camera,s=True,pa=True),type='camera')[0] cameraDagPath = glTools.utils.base.getMDagPath(cameraShape) cameraFn = OpenMaya.MFnCamera(cameraDagPath) cameraPt = cameraFn.eyePoint(OpenMaya.MSpace.kWorld) - + # Return Result return [cameraPt.x,cameraPt.y,cameraPt.z] @@ -68,11 +68,11 @@ def distToCam(node,cam): raise Exception('Camera "'+cam+'" does not exist!') if not isCamera(cam): raise Exception('Object "'+cam+'" is not a valid camera!') - + # Get Dist to Camera camPt = getEyePoint(cam) nodePt = mc.xform(node,q=True,ws=True,rp=True) dist = glTools.utils.mathUtils.distanceBetween(camPt,nodePt) - + # Return Result return dist diff --git a/utils/channelState.py b/utils/channelState.py index 35be583..2b18b4c 100644 --- a/utils/channelState.py +++ b/utils/channelState.py @@ -4,7 +4,7 @@ import glTools.utils.transform class ChannelState(object): - + def __init__(self): ''' ChannelState class initializer @@ -12,7 +12,7 @@ def __init__(self): self.channel = ['tx','ty','tz','rx','ry','rz','sx','sy','sz','v'] self.window = 'channelStateUI' self.labelArray = ['No Change','Keyable','NonKeyable','Locked'] - + def add(self,objectList): ''' Adds the channel state attr to all specified objects @@ -21,7 +21,7 @@ def add(self,objectList): ''' # Add Channel State Attrs for obj in objectList: - + # Check obj if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') @@ -29,11 +29,11 @@ def add(self,objectList): raise Exception('Object "'+obj+'" is not a valid transform!') if mc.objExists(obj+'.channelState'): print ('Object "'+obj+'" already has a "channelState" attribute! Skipping...') - + # Add channelState attr #mc.addAttr(obj,ln='channelState',at='enum',en=':Keyable:NonKeyable:Locked:',m=1,dv=-1) mc.addAttr(obj,ln='channelState',at='enum',en=':Keyable:NonKeyable:Locked:',m=1) - + # Set channelState flag values for i in range(len(self.channel)): if mc.getAttr(obj+'.'+self.channel[i],l=1): @@ -47,7 +47,7 @@ def add(self,objectList): mc.setAttr(obj+'.channelState['+str(i)+']',0) # Alias Attribute mc.aliasAttr(self.channel[i]+'_state',obj+'.channelState['+str(i)+']') - + def setFlags(self,flags=[0,0,0,0,0,0,0,0,0,1],objectList=[]): ''' Sets the channelState attributes on all specified objects @@ -58,7 +58,7 @@ def setFlags(self,flags=[0,0,0,0,0,0,0,0,0,1],objectList=[]): ''' # For each object for obj in objectList: - + # Check Obj if not obj: continue if not mc.objExists(obj): @@ -72,7 +72,7 @@ def setFlags(self,flags=[0,0,0,0,0,0,0,0,0,1],objectList=[]): for i in range(len(self.channel)): if flags[i] != -1: mc.setAttr(obj+'.channelState['+str(i)+']',flags[i]) - + def get(self,obj): ''' Get the channel state values from an object and return them in an list. @@ -86,7 +86,7 @@ def get(self,obj): for i in range(len(self.channel)): channelState.append(mc.getAttr(obj+'.channelState['+str(i)+']')) return channelState - + def set(self,state,objectList=[]): ''' Set channel states based on channelState multi attribute @@ -98,19 +98,19 @@ def set(self,state,objectList=[]): # Check objectList if type(objectList) == str: objectList = [objectList] if not objectList: objectList = mc.ls('*.channelState',o=True) - + # For each object in list for obj in objectList: - + # Check Object if not obj: continue - + # Get/Check Channel State Values channelState = self.get(obj) if not channelState: continue if len(channelState) != len(self.channel): raise Exception('Attribute "'+obj+'.channelState" is not the expected length ('+str(len(self.channel))+')!') - + if state: for i in range(len(self.channel)): if channelState[i] == 0: # KEYABLE @@ -121,19 +121,19 @@ def set(self,state,objectList=[]): mc.setAttr(obj+'.'+self.channel[i],l=True,k=False,cb=False) else: # INVALID OPTION raise Exception('Invalid channel state value ('+str(channelState[i])+')!') - + # Joint Radius if mc.objExists(obj+'.radius'): mc.setAttr(obj+'.radius',l=False,k=False) - + else: # Unlock Channel State for attr in self.channel: mc.setAttr(obj+'.'+attr,l=False,k=True,cb=True) - + # Joint Radius if mc.objectType == 'joint' and mc.objExists(obj+'.radius'): mc.setAttr(obj+'.radius',l=False,k=True,cb=True) - + def toggleSelected(self,state): ''' Set channel states on all selected objects @@ -141,11 +141,11 @@ def toggleSelected(self,state): @type state: int ''' self.set(state,mc.ls(sl=1)) - + # ============== # - UI Methods - # ============== - + def ui(self): ''' Main UI function @@ -154,16 +154,16 @@ def ui(self): # Create Window if mc.window(self.window,q=1,ex=1): mc.deleteUI(self.window) mc.window(self.window,t='Channel State Editor',w=630,h=445,rtf=1,mnb=1,mb=1) - + mc.columnLayout(adj=1,w=500) - + mc.separator(style='none',h=10) mc.text(l=' SET CHANNEL FLAGS',font='boldLabelFont',align='left') mc.separator(style='none',h=10) # SET ALL mc.radioButtonGrp('rbgSetAll',numberOfRadioButtons=4,label='SET ALL',labelArray4=self.labelArray,sl=1) mc.radioButtonGrp('rbgSetAll',e=1,on1='glTools.utils.channelState.ChannelState().uiSetAll(1)',on2='glTools.utils.channelState.ChannelState().uiSetAll(2)',on3='glTools.utils.channelState.ChannelState().uiSetAll(3)',on4='glTools.utils.channelState.ChannelState().uiSetAll(4)') - + mc.separator(style='in',h=10) # Transform attrs mc.radioButtonGrp('rbgTX',numberOfRadioButtons=4,label='Translate X',labelArray4=self.labelArray,sl=1) @@ -179,7 +179,7 @@ def ui(self): mc.radioButtonGrp('rbgSZ',numberOfRadioButtons=4,label='Scale Z',labelArray4=self.labelArray,sl=1) mc.separator(style='none',h=5) mc.radioButtonGrp('rbgV',numberOfRadioButtons=4,label='Visibility',labelArray4=self.labelArray,sl=1) - + # Object Selection mc.separator(style='in',h=20) mc.text(l=' SET FLAGS/STATE ON',font='boldLabelFont',align='left') @@ -191,7 +191,7 @@ def ui(self): mc.textField('tfType',visible=0) mc.setParent('..') mc.separator(style='in',h=30) - + # Buttons mc.rowColumnLayout(nc=4,cw=[(1,60),(2,175),(3,175),(4,175)]) mc.text(l='') @@ -200,11 +200,11 @@ def ui(self): mc.button(l='Set State OFF',ann='Same as making all channels keyable and visible.',c='glTools.utils.channelState.ChannelState().uiState(0)') mc.setParent('..') mc.setParent('..') - + # Show Window mc.showWindow(self.window) mc.window(self.window,e=1,w=630,h=445) - + def uiSetAll(self,select): ''' Function used by ChannelState.ui(). @@ -215,7 +215,7 @@ def uiSetAll(self,select): for attr in self.channel: # Set RadioButton Selection mc.radioButtonGrp('rbg'+attr.upper(),e=1,sl=select) - + def uiSetFlags(self): ''' Gets the channel state data from the UI and then sets the flags. @@ -224,14 +224,14 @@ def uiSetFlags(self): channelState = [] for attr in self.channel: channelState.append(mc.radioButtonGrp('rbg'+attr.upper(),q=1,sl=1)-2) - + # Get list of objects to set flags for objType = mc.radioButtonGrp('rbgObjType',q=1,sl=1) objectList = [] - + if objType == 1: objectList = mc.ls(sl=1) elif objType == 2: - doit = mc.confirmDialog(title='Confirm Set Flags on ALL Transforms', + doit = mc.confirmDialog(title='Confirm Set Flags on ALL Transforms', m='Are you sure you want to mass edit all the channel state attributes?', button=('Yes','No'), defaultButton='No', @@ -242,10 +242,10 @@ def uiSetFlags(self): elif objType == 3: selType = mc.textField('tfType',q=1,text=1) objectList = mc.ls(type=selType) - + # Set Flags self.setFlags(channelState,objectList) - + def uiState(self,state): ''' This is a button wrapper for UI state diff --git a/utils/characterSet.py b/utils/characterSet.py index 1623b54..9374a9a 100644 --- a/utils/characterSet.py +++ b/utils/characterSet.py @@ -48,22 +48,22 @@ def create( objectList, # ========== # - Checks - # ========== - + # Check Character Set if isCharSet(name): raise Exception('Character set "'+name+'" already exists!') - + # Check Root if root and not mc.objExists(root): raise Exception('Root object "'+root+'" does not exists!') - + # ======================== # - Create Character Set - # ======================== - + # Initialize Character Var char = '' - + if root: # Create With Root Node char = mc.character( objectList, @@ -83,11 +83,11 @@ def create( objectList, excludeScale=excludeScale, excludeDynamic=excludeDynamic, excludeVisibility=excludeVisibility ) - + # ================= # - Return Result - # ================= - + return char def setCurrent(charSet): @@ -99,10 +99,10 @@ def setCurrent(charSet): # Check Character Set if not isCharSet(charSet): raise Exception('Object "'+charSet+'" is not a valid character set!') - + # Set Current mm.eval('setCurrentCharacters({"'+charSet+'"})') - + # Return Result return charSet @@ -130,24 +130,24 @@ def bakeCharacterChannels(charSet,start=None,end=None,attrList=[]): # ========== # - Checks - # ========== - + if not isCharSet(charSet): raise Exception('Object "'+charSet+'" is not a valid character set!') - + # Start/End if start == None: start = mc.playbackOptions(min=True) if end == None: end = mc.playbackOptions(max=True) - + # ========================= # - Character Set Details - # ========================= - + # Get Character Set Channels charChannels = mc.sets(charSet,q=True) - + # Get Character Set Objects charObjList = mc.ls(charChannels,o=True) - + # Get Character Set Channel Names if not attrList: attrList = [] @@ -155,17 +155,17 @@ def bakeCharacterChannels(charSet,start=None,end=None,attrList=[]): attr = mc.attributeName(ch,s=True) if not attrList.count(attr): attrList.append(attr) - + # ================ # - Bake Results - # ================ - + mc.bakeResults(charObjList,t=(1,600),at=attrList,simulation=True) - + # ================= # - Return Result - # ================= - + return charObjList def removeTimelineClips(charSet): diff --git a/utils/characterize.py b/utils/characterize.py index 838dd4b..39f536d 100644 --- a/utils/characterize.py +++ b/utils/characterize.py @@ -9,14 +9,14 @@ def init(): ''' # Get Maya App Location MAYA_LOCATION = os.environ['MAYA_LOCATION'] - + # Source Mel Files mm.eval('source "'+MAYA_LOCATION+'/scripts/others/hikGlobalUtils.mel"') mm.eval('source "'+MAYA_LOCATION+'/scripts/others/hikCharacterControlsUI.mel"') mm.eval('source "'+MAYA_LOCATION+'/scripts/others/hikDefinitionOperations.mel"') mm.eval('source "'+MAYA_LOCATION+'/scripts/others/CharacterPipeline.mel"') mm.eval('source "'+MAYA_LOCATION+'/scripts/others/characterSelector.mel"') - + # Load Plugins if not mc.pluginInfo('mayaHIK',q=True,l=True): mc.loadPlugin('mayaHIK') @@ -24,7 +24,7 @@ def init(): mc.loadPlugin('mayaCharacterization') if not mc.pluginInfo('retargeterNodes',q=True,l=True): mc.loadPlugin('retargeterNodes') - + # HIK Character Controls Tool mm.eval('HIKCharacterControlsTool') @@ -33,10 +33,10 @@ def isCharacterDefinition(char): ''' # Check Node Exists if not mc.objExists(char): return False - + # Check Node Type if mc.objectType(char) != 'HIKCharacterNode': return False - + # Return Result return True @@ -46,10 +46,10 @@ def isCharacterDefinitionLocked(char): # Check Character Definition if not isCharacterDefinition(char): raise Exception('Invalid character definition node! Object "'+char+'" does not exist or is not a valid HIKCharacterNode!') - + # Check Lock lock = mc.getAttr(char+'.InputCharacterizationLock') - + # Return Result return lock @@ -59,14 +59,14 @@ def characterDefinitionLock(char,lockState=True,saveStance=True): # Check Character Definition if not isCharacterDefinition(char): raise Exception('Invalid character definition node! Object "'+char+'" does not exist or is not a valid HIKCharacterNode!') - + # Check Lock State isLocked = isCharacterDefinitionLocked(char) - + # Set Lock State if lockState != isLocked: mm.eval('hikToggleLockDefinition') #mm.eval('mayaHIKcharacterLock("'+char+'",'+str(int(lockState))+','+str(int(saveStance))+')') - + # Return State return int(lockState) @@ -76,22 +76,22 @@ def create(charNS,charName,lock=True): # ========== # - Checks - # ========== - + if charNS: charNS+=':' - + # =============================== # - Create Character Definition - # =============================== - + charDef = mm.eval('CreateHIKCharacterWithName "'+charName+'"') setCurrentCharacter(charDef) - + try: mm.eval('hikUpdateCharacterList()') mm.eval('hikSelectDefinitionTab()') except: pass - + # Apply Temmplate setCharacterObject(charDef,charNS+'Hips',1,0) setCharacterObject(charDef,charNS+'Head',15,0) @@ -162,14 +162,14 @@ def create(charNS,charName,lock=True): setCharacterObject(charDef,charNS+'Spine',8,0) setCharacterObject(charDef,charNS+'Spine1',23,0) setCharacterObject(charDef,charNS+'Spine2',24,0) - + # ======================================= # - Set Character Definition Properties - # ======================================= - + # Get Character Definition Properties Node propertyNode = getPropertiesNode(charDef) - + # Match Source mc.setAttr(propertyNode+'.ForceActorSpace',0) # OFF # Action Space Comp Mode @@ -184,19 +184,19 @@ def create(charNS,charName,lock=True): mc.setAttr(propertyNode+'.AnkleHeightCompensationMode',0) # OFF # Mass Center Comp Mode mc.setAttr(propertyNode+'.MassCenterCompensationMode',1) # ON - + # =================== # - Lock Definition - # =================== - + if lock: #characterDefinitionLock(charDef,lockState=True,saveStance=True) mm.eval('hikToggleLockDefinition') - + # ================= # - Return Result - # ================= - + return charDef def setCharacterObject(charDef,charBone,boneId,deleteBone=False): @@ -224,10 +224,10 @@ def getCharacterNodes(char): # Check Node if not isCharacterDefinition(char): raise Exception('Invalid character definition node! Object "'+char+'" does not exist or is not a valid HIKCharacterNode!') - + # Get Character Nodes charNodes = mm.eval('hikGetSkeletonNodes "'+char+'"') - + # Return Result return charNodes @@ -236,20 +236,20 @@ def setCharacterSource(char,source): ''' # HIK Character Controls Tool mm.eval('HIKCharacterControlsTool') - + # Get Current Character currChar = getCurrentCharacter() - + # Set Current Character setCurrentCharacter(char) - + # Set Character Source mm.eval('hikSetCurrentSource("'+source+'")') mm.eval('hikUpdateSourceList()') mm.eval('hikUpdateCurrentSourceFromUI()') mm.eval('hikUpdateContextualUI()') mm.eval('hikControlRigSelectionChangedCallback') - + # Restore Current Character if char != currChar: setCurrentCharacter(currChar) @@ -259,24 +259,24 @@ def getPropertiesNode(char): # Check Node if not isCharacterDefinition(char): raise Exception('Invalid character definition node! Object "'+char+'" does not exist or is not a valid HIKCharacterNode!') - + propertyNode = '' try: propertyNode = mm.eval('getProperty2StateFromCharacter("'+char+'")') except: - + # Get propertyState Connections conn = mc.listConnections(char+'.propertyState',s=True,d=False) if not conn: raise Exception('Unable to determine HIKProperty2State node from character definition node "'+char+'"!') - + # Check Number of Results if len(conn) > 1: print('Multiple HIKProperty2State nodes found for character definition "'+char+'"! Returning first item only...') - + # Assign Property Node propertyNode = conn[0] - + # Return Result return propertyNode @@ -286,16 +286,16 @@ def getSolverNode(char): # Check Node if not isCharacterDefinition(char): raise Exception('Invalid character definition node! Object "'+char+'" does not exist or is not a valid HIKCharacterNode!') - + # Get OutputPropertySetState Connections conn = mc.ls(mc.listConnections(char+'.OutputPropertySetState',d=True,s=False) or [],type='HIKSolverNode') if not conn: raise Exception('Unable to determine HIKSolverNode node from character definition node "'+char+'"!') - + # Check Number of Results if len(conn) > 1: print('Multiple HIKSolverNode nodes found for character definition "'+char+'"! Returning first item only...') - + # Return Result return conn[0] @@ -305,16 +305,16 @@ def getRetargetNode(char): # Check Node if not isCharacterDefinition(char): raise Exception('Invalid character definition node! Object "'+char+'" does not exist or is not a valid HIKCharacterNode!') - + # Get OutputPropertySetState Connections conn = mc.ls(mc.listConnections(char+'.OutputPropertySetState',d=True,s=False) or [],type='HIKRetargeterNode') if not conn: raise Exception('Unable to determine HIKRetargeterNode node from character definition node "'+char+'"!') - + # Check Number of Results if len(conn) > 1: print('Multiple HIKRetargeterNode nodes found for character definition "'+char+'"! Returning first item only...') - + # Return Result return conn[0] @@ -323,7 +323,7 @@ def bakeAnim(char): ''' # Get Character Bones bones = getCharacterNodes(char) - + # Bake Animation mc.bakeResults( bones, simulation=True, @@ -336,7 +336,7 @@ def bakeAnim(char): bakeOnOverrideLayer=False, minimizeRotation=False, at=['tx','ty','tz','rx','ry','rz'] ) - + # Return Result return bones diff --git a/utils/choice.py b/utils/choice.py index e6ee026..4e44864 100644 --- a/utils/choice.py +++ b/utils/choice.py @@ -21,14 +21,14 @@ def create(inputType='string',selectInput=None,inputVal=None,inputSrc=None,dst=N # ========== # - Checks - # ========== - + # Selector Input if selectInput: if not mc.objExists(selectInput): raise Exception('Selector input source "'+selectInput+'" does not exist!') if not glTools.utils.attribute.isAttr(selectInput): raise Exception('Selector input source "'+selectInput+'" is not a valid attribute!') - + # Input if inputSrc: for inSrc in inputSrc: @@ -36,29 +36,29 @@ def create(inputType='string',selectInput=None,inputVal=None,inputSrc=None,dst=N raise Exception('Input source "'+inSrc+'" does not exist!') if not glTools.utils.attribute.isAttr(inSrc): raise Exception('Input source "'+inSrc+'" is not a valid attribute!') - + # Destination if dst: if not mc.objExists(selectInput): raise Exception('Destination plug "'+dst+'" does not exist!') if not glTools.utils.attribute.isAttr(dst): raise Exception('Destination plug "'+dst+'" is not a valid attribute!') - + # Prefix if not prefix: prefix = '' if dst: prefix = dst.split('.')[0] - + # ====================== # - Create Choice Node - # ====================== - + choiceNode = mc.createNode('choice',n=prefix+('_'*int(bool(prefix)))+'choice') - + # ======================= # - Connect Choice Node - # ======================= - + # Selector Input if selectInput: try: @@ -67,7 +67,7 @@ def create(inputType='string',selectInput=None,inputVal=None,inputSrc=None,dst=N raise Exception('Error connecting selector input "'+selectInput+'" >> "'+choiceNode+'.selector"! Exception msg: '+str(e)) else: print ('Connected "'+selectInput+'" >> "'+choiceNode+'.selector"') - + # Input inputLen = 0 if inputVal: @@ -76,9 +76,9 @@ def create(inputType='string',selectInput=None,inputVal=None,inputSrc=None,dst=N if inputSrc: if len(inputSrc) > inputLen: inputLen = len(inputSrc) - + if inputLen: - + # Create Attribute (based on input type) if inputType == 'string': mc.addAttr(choiceNode,ln='inputValue',dt=inputType,m=True) @@ -86,7 +86,7 @@ def create(inputType='string',selectInput=None,inputVal=None,inputSrc=None,dst=N mc.addAttr(choiceNode,ln='inputValue',at=inputType,m=True) else: raise Exception('Invalid input type "'+inputType+'"!') - + # Set Input Values if inputVal: for i in range(len(inputVal)): @@ -99,27 +99,27 @@ def create(inputType='string',selectInput=None,inputVal=None,inputSrc=None,dst=N except Exception, e: raise Exception('Error setting input value "'+choiceNode+'.inputValue['+str(i)+']"! Exception msg: '+str(e)) else: raise Exception('Invalid input type "'+inputType+'"!') - + # Connect Input Source if inputSrc: for i in range(len(inputSrc)): if not inputSrc[i] == None: try: mc.connectAttr(inputSrc[i],choiceNode+'.inputValue['+str(i)+']',f=True) except Exception, e: raise Exception('Error connecting input source "'+inputSrc[i]+'" >> "'+choiceNode+'.inputValue['+str(i)+']"! Exception msg: '+str(e)) - + # Connect Input for i in range(inputLen): try: mc.connectAttr(choiceNode+'.inputValue['+str(i)+']',choiceNode+'.input['+str(i)+']',f=True) except Exception, e: raise Exception('Error connecting input value "'+choiceNode+'.inputValue['+str(i)+']" >> "'+choiceNode+'.input['+str(i)+']"! Exception msg: '+str(e)) - + # Connect Destination if dst: try: mc.connectAttr(choiceNode+'.output',dst,f=True) except Exception, e: raise Exception('Error connecting to choice destination "'+dst+'"! Exception msg: '+str(e)) else: print('Connected "'+choiceNode+'.output" >> "'+dst+'"') - + # ================= # - Return Result - # ================= - + return choiceNode diff --git a/utils/cleanup.py b/utils/cleanup.py index 790c87d..b4c912c 100644 --- a/utils/cleanup.py +++ b/utils/cleanup.py @@ -23,9 +23,9 @@ def toggleCons(state): ''' # Get List of Con Joints conList = mc.ls('*Con*_jnt',type='joint') - + for conJnt in conList: - + # Toggle State if state: glTools.utils.base.displayOverride(conJnt,overrideEnable=1,overrideLOD=0) @@ -33,16 +33,16 @@ def toggleCons(state): else: glTools.utils.base.displayOverride(conJnt,overrideEnable=1,overrideLOD=1) mc.setAttr(conJnt+'.drawStyle',2) # None - + # Set Joint Radius if mc.getAttr(conJnt+'.radius',se=True): mc.setAttr(conJnt+'.radius',0.0) mc.setAttr(conJnt+'.radius',cb=False) - + # Hide Rotate Order if mc.getAttr(conJnt+'.ro',se=True): mc.setAttr(conJnt+'.ro',cb=False) - + # Return Result return conList @@ -54,9 +54,9 @@ def toggleEnds(state): ''' # Get list of End joints endList = mc.ls('*End_jnt',type='joint') - + for endJnt in endList: - + # Toggle state if state: glTools.utils.base.displayOverride(endJnt,overrideEnable=1,overrideLOD=0) @@ -64,16 +64,16 @@ def toggleEnds(state): else: glTools.utils.base.displayOverride(endJnt,overrideEnable=1,overrideLOD=1) mc.setAttr(endJnt+'.drawStyle',2) # None - + # Set Joint Radius if mc.getAttr(endJnt+'.radius',se=True): mc.setAttr(endJnt+'.radius',0.0) mc.setAttr(endJnt+'.radius',cb=False) - + # Hide Rotate Order if mc.getAttr(endJnt+'.ro',se=True): mc.setAttr(endJnt+'.ro',cb=False) - + # Return Result return endList @@ -86,44 +86,44 @@ def disableDrawingOverrides(grp): # ========== # - Checks - # ========== - + if not mc.objExists(grp): raise Exception('Transform "'+grp+'" does not exists!') if not glTools.utils.transform.isTransform(grp): raise Exception('Object "'+grp+'" is not a valid transform!') - + # Get Descendent Node List nodeList = mc.ls(mc.listRelatives(grp,ad=True, pa=True) or [],dag=True) or [] if not nodeList: return [] - + # ============================= # - Disable Drawing Overrides - # ============================= - + overrideName = 'overrideEnabled' for node in nodeList: - + # Check Override Attribute overrideAttr = node+'.'+overrideName if not mc.attributeQuery(overrideName,n=node,ex=True): print('Override attribute "'+overrideAttr+'" does not exist! Skipping...') continue - + # Check Override Attribute Connections overrideConn = mc.listConnections(overrideAttr,s=True,d=False) or [] if overrideConn: print('Found incoming connection for override attribute "'+overrideAttr+'"! ('+overrideConn[0]+')') print('Disconnecting attribute and disabling drawing overrides...') mc.disconnectAttr(overrideConn[0],overrideAttr) - + # Disable Drawing Overrides try: mc.setAttr(overrideAttr,0) except: pass - + # ================= # - Return Result - # ================= - + return nodeList # ========== @@ -145,10 +145,10 @@ def uniqueNameCheck(objList=[],transformsOnly=False): nodeList = mc.ls(objList,transforms=True) else: nodeList = mc.ls(objList,dag=True) - + # Determine non unique names nonUniqueList = [i for i in nodeList if i.count('|')] - + # Return result return nonUniqueList @@ -161,7 +161,7 @@ def validNameCheck(objList=[]): # Check geo list if not objList: objList = mc.ls() if not objList: return [] - + # Remove Default Nodes defNodes = ['dof1','time1','lambert1','postProcessList1','sequenceManager1','lightLinker1','renderGlobalsList1','dynController1','lightList1','particleCloud1','shaderGlow1'] objList = [obj for obj in objList if not defNodes.count(obj)] @@ -169,33 +169,33 @@ def validNameCheck(objList=[]): objList = [obj for obj in objList if not mc.nodeType(obj) == 'objectTypeFilter'] objList = [obj for obj in objList if not mc.nodeType(obj) == 'objectNameFilter'] objList = [obj for obj in objList if not mc.nodeType(obj) == 'objectScriptFilter'] - + # Check valid names result = [] for obj in objList: - + # Check prefix #if not obj.startswith('cn_') and not obj.startswith('lf_') and not obj.startswith('rt_'): # result.append(obj) - + # Check "pasted" if obj.count('pasted'): result.append(obj) - + # Check "poly" if obj.count('poly'): result.append(obj) - + # Check double underscore "__" if obj.count('__'): result.append(obj) - + # Check names ending with a digit (0-9) digitSearch = re.search('(\d+)$', obj) if digitSearch and glTools.utils.transform.isTransform(obj): if digitSearch.group(0): result.append(obj) - + # Remove Duplicate Entries result = list(set(result)) - + # Return result return result @@ -220,55 +220,55 @@ def shapeNameCheck( objList = [], # ========== # - Checks - # ========== - + if not objList: objList = mc.ls(type=typeList) - + # ==================== # - Build Shape List - # ==================== - + shapeList = [] for obj in objList: - + # Get Shapes from Transform if glTools.utils.transform.isTransform(obj): - + # Check Multiple Shapes objShapes = mc.listRelatives(obj,s=True,pa=True) if not objShapes: continue if (len(objShapes) > 1) and skipMultipleShapes: continue - + # Get Shapes tShapeList = mc.listRelatives(obj,s=True,ni=skipIntermediates,pa=True) for shape in tShapeList: shapeList.append(obj) - + elif glTools.utils.shape.isShape(obj): shapeList.append(obj) - + else: print('Unable to determine shape from object "'+obj+'"! Skipping...') - + # ===================== # - Check Shape Names - # ===================== - + invalidShapeNameList = [] for shape in shapeList: - + # Check Type if not typeList.count(mc.objectType(shape)): continue - + # Check Intermediate Object if skipIntermediates and mc.getAttr(shape+'.intermediateObject'): continue - + # Get transform parent name parent = mc.listRelatives(shape,p=True,pa=True)[0] - + # Get Short Names shapeSN = mc.ls(shape,sn=True)[0] parentSN = mc.ls(parent,sn=True)[0] - + # Check Shape Name if strict and (shape != parent+'Shape'): invalidShapeNameList.append(shape) @@ -276,11 +276,11 @@ def shapeNameCheck( objList = [], invalidShapeNameList.append(shape) elif not shapeSN.count('Shape'): invalidShapeNameList.append(shape) - + # ================= # - Return Result - # ================= - + return invalidShapeNameList def intermediateShapesCheck(objList=[]): @@ -292,24 +292,24 @@ def intermediateShapesCheck(objList=[]): # Check nodeList if not objList: objList = mc.ls(transforms=True) else: objList = mc.ls(objList,transforms=True) - + # For each node result = [] for obj in objList: - + # Get All Shapes shapes = mc.listRelatives(obj,s=True,pa=True) if not shapes: shapes = [] for shape in shapes: - + # Check Intermediate Shapes if mc.objExists(shape+'.intermediateObject'): if mc.getAttr(shape+'.intermediateObject'): result.append(shape) - + # Return Result return result - + def multipleShapeCheck(objList=[]): ''' Return a list of transforms with multiple shape nodes @@ -319,25 +319,25 @@ def multipleShapeCheck(objList=[]): # Get scene transforms if not objList: objList = mc.ls(transforms=True) else: objList = mc.ls(objList,dag=True) - + # Iterate over scene transforms result = [] for transform in objList: - + # Check Transform if not glTools.utils.transform.isTransform(transform): transform = mc.listRelatives(transform,p=True)[0] - + # Get transform shape list shapeList = mc.listRelatives(transform,s=True) - + # Check shape list if not shapeList: continue shapeList = mc.ls(shapeList,type=['mesh','nurbsSurface','nurbsCurve']) - + # Check number of shapes if len(shapeList) > 1: result.append(transform) - + # Return result return result @@ -352,29 +352,29 @@ def constructionHistoryCheck(geoList=[]): geoList = mc.ls(geometry=True) else: geoList = mc.listRelatives(geoList,s=True,pa=True) - + # For each node result = [] for geo in geoList: - + # Check Construction History hist = mc.listHistory(geo) - + # Remove Self if hist.count(geo): hist.remove(geo) - + # Ignore Node Types ignore = mc.ls(hist,type=['groupId','shadingEngine','transform']) hist = list(set(hist)-set(ignore)) - + # Check History if hist: obj = mc.listRelatives(geo,p=True,pa=True) result.extend(obj) - + # Remove Duplicate Names if result: result = list(set(result)) - + # Return Result return result @@ -388,21 +388,21 @@ def userAttrCheck(objList=[],includeShapes=False): ''' # Initialize Return List result = [] - + # Check objList if not objList: objList = mc.ls() - + # For each node for obj in objList: - + userAttrs = mc.listAttr(obj,ud=True) if not userAttrs: userAttrs = [] for attr in userAttrs: result.append(obj+'.'+attr) - + # Check Shapes if includeShapes: - + shapes = mc.listRelatives(obj,s=True) if not shapes: shapes = [] for shape in shapes: @@ -410,7 +410,7 @@ def userAttrCheck(objList=[],includeShapes=False): if not userAttrs: userAttrs = [] for attr in userAttrs: result.append(shape+'.'+attr) - + # Return Result return result @@ -423,13 +423,13 @@ def emptyGroupCheck(objList=[]): # Check objList if not objList: objList = mc.ls(transforms=True) else: objList = mc.ls(objList,transforms=True) - + # Find Empty Groups result = [] for grp in objList: if not mc.listRelatives(grp,ad=True): result.append(grp) - + # Return Result return result @@ -441,22 +441,22 @@ def emptySetCheck(setList=[]): ''' # Check setList if not setList: setList = mc.ls(sets=True) - + # Check empty sets result = [] for setName in setList: - + # Check Set if not mc.ls(setName,sets=True): continue - + # Skip Default Sets if setName.startswith('default'): continue if setName.startswith('initial'): continue - + # Check Set if not mc.sets(setName,q=True): result.append(setName) - + # Return result return result @@ -469,21 +469,21 @@ def emptyLayerCheck(layerList=[]): # Check Layer List if not layerList: layerList = mc.ls(type=['displayLayer','renderLayer','animLayer']) else: layerList = mc.ls(layerList,type=['displayLayer','renderLayer','animLayer']) - + # Check Empty Layers result = [] for layer in layerList: - + # Check Layer if not mc.ls(layer,type=['displayLayer','renderLayer','animLayer']): continue - + # Skip Default Layers if layer.startswith('default'): continue - + # Check Membership if not glTools.utils.layer.memberList(layer): result.append(layer) - + # Return Result return result @@ -497,13 +497,13 @@ def animCurveCheck(curveTypeList=['animCurveTL','animCurveTA','animCurveTT','ani ''' # Initialize Return List animCurves = [] - + # List AnimCurve Nodes for curveType in curveTypeList: curveList = mc.ls(type=curveType) if curveList: animCurves.extend(curveList) - + # Return Result return animCurves @@ -525,13 +525,13 @@ def noGeometryShaderCheck(geoList=[]): else: geoList += mc.ls(mc.listRelatives(geoList,ad=True,pa=True) or [],type=['mesh','nurbsSurface'],ni=True) or [] geoList = mc.ls(geoList,type=['mesh','nurbsSurface'],ni=True) - + # Check Shader Assignment noShaderList = [] for geo in geoList: SG = glTools.utils.shader.getSG(geo) if not SG: noShaderList.append(geo) - + # Return Result return noShaderList @@ -541,15 +541,15 @@ def unusedReferenceCheck(): ''' # Initialize Return List result = [] - + # Get list of existing references refList = glTools.utils.reference.listReferences() - + # Check Unused Reference for ref in refList: try: refFile = glTools.utils.reference.getReferenceFile(ref) except: result.append(ref) - + # Return Result return result @@ -572,17 +572,17 @@ def checkTransforms(objList=[],tol=0.0000000001): # Check Object List if not objList: objList = mc.ls(transforms=True) if not objList: return [] - + # Check Transforms transformList = [] for obj in objList: - + # Skip Default Transforms if obj == 'persp': continue if obj == 'front': continue if obj == 'side': continue if obj == 'top': continue - + # Translate if abs(mc.getAttr(obj+'.tx')) > tol: transformList.append(obj) @@ -593,7 +593,7 @@ def checkTransforms(objList=[],tol=0.0000000001): if abs(mc.getAttr(obj+'.tz')) > tol: transformList.append(obj) continue - + # Rotate if abs(mc.getAttr(obj+'.rx')) > tol: transformList.append(obj) @@ -604,7 +604,7 @@ def checkTransforms(objList=[],tol=0.0000000001): if abs(mc.getAttr(obj+'.rz')) > tol: transformList.append(obj) continue - + # Scale if abs(mc.getAttr(obj+'.sx') - 1.0) > tol: transformList.append(obj) @@ -615,7 +615,7 @@ def checkTransforms(objList=[],tol=0.0000000001): if abs(mc.getAttr(obj+'.sz') - 1.0) > tol: transformList.append(obj) continue - + # Return Result return transformList @@ -628,13 +628,13 @@ def displayOverridesCheck(objList=[]): # Check Object List if not objList: objList = mc.ls(dag=True) else: objList = mc.ls(objList,dag=True) - + # Check Display Overrides displayOverrideList = [] for obj in objList: if mc.getAttr(obj+'.overrideEnabled'): displayOverrideList.append(obj) - + # Return Result return displayOverrideList @@ -654,15 +654,15 @@ def shapeNameFix(shape): ''' # Get Shape Transform Parent parent = mc.listRelatives(shape,p=True)[0] - + # Check Shape Name shapeName = parent+'Shape' if mc.objExists(shapeName): raise Exception('Shape "'+shapeName+'" already exists! Unable to rename shape "'+shape+'"!') - + # Rename Shape newShape = mc.rename(shape,shapeName) - + # Return Result return newShape @@ -695,21 +695,21 @@ def deleteUserAttrs(nodeList=[],includeShapes=False): Delete user defined attributes from the specified list of nodes @param nodeList: List of nodes to delete user defined attrs from. If empty, assume all nodes. @type nodeList: list - @param includeShapes: Delete user attributes + @param includeShapes: Delete user attributes @type includeShapes: bool ''' # Check nodeList if not nodeList: nodeList = mc.ls() - + # For each node for node in nodeList: - + # Delete user attributes glTools.utils.attribute.deleteUserAttrs(node) - + # Include Shapes if includeShapes: - + # Delete shape user attributes shapes = mc.listRelatives(node,s=True) for shape in shapes: @@ -754,7 +754,7 @@ def deleteUnknownNodes(): ''' # Get list of unknown nodes unknownNodes = unknownNodeCheck() or [] - + # Delete unknown nodes for node in unknownNodes: try: @@ -762,7 +762,7 @@ def deleteUnknownNodes(): mc.delete(node) except: print('Problem deleting unknown node "'+node+'"!') - + # Return Result return unknownNodes @@ -796,18 +796,18 @@ def deleteEmptySets(setList=[]): ''' # Check setList if not setList: setList = mc.ls(sets=True) - + # Check empty sets emptySetList = [] for set in setList: if not mc.sets(set,q=True): emptySetList.append(set) - + # Delete empty sets for emptySet in emptySetList: try: mc.delete(emptySet) except: pass - + # Return result return emptySetList @@ -822,15 +822,15 @@ def deleteAllSets(excludeList=[]): if excludeList: excludeSetList = mc.ls(excludeList,sets=True) setList = list(set(setList)-set(excludeSetList)) - + # Delete unused sets for deleteSet in setList: try: mc.delete(deleteSet) except: pass - + # Return result return setList - + def deleteUnusedShadingNodes(): ''' Delete all unused shading nodes in the scene @@ -846,10 +846,10 @@ def deleteDisplayLayers(): # Get display layer list displayLayers = mc.ls(type='displayLayer') displayLayers.remove('defaultLayer') - + # Delete display layers if displayLayers: mc.delete(displayLayers) - + # Return result return displayLayers @@ -860,10 +860,10 @@ def deleteRenderLayers(): # Get render layer list renderLayers = mc.ls(type='renderLayer') renderLayers.remove('defaultRenderLayer') - + # Delete render layers if renderLayers: mc.delete(renderLayers) - + # Return result return renderLayers @@ -876,10 +876,10 @@ def assignInitialShadingGroup(geoList=[]): # Check geoList if not geoList: geoList = mc.ls(geometry=True) if not geoList: return [] - + # Assign Initial Shading Group mc.sets(geoList,fe='initialShadingGroup') - + # Return result return geoList @@ -892,25 +892,25 @@ def zeroTransforms(objList=[]): # Check Object List if not objList: objList = mc.ls(transforms=True) if not objList: return [] - + # Check Transforms for obj in objList: - + # Translate if mc.getAttr(obj+'.tx',se=True): mc.setAttr(obj+'.tx',0) if mc.getAttr(obj+'.ty',se=True): mc.setAttr(obj+'.ty',0) if mc.getAttr(obj+'.tz',se=True): mc.setAttr(obj+'.tz',0) - + # Rotate if mc.getAttr(obj+'.rx',se=True): mc.setAttr(obj+'.rx',0) if mc.getAttr(obj+'.ry',se=True): mc.setAttr(obj+'.ry',0) if mc.getAttr(obj+'.rz',se=True): mc.setAttr(obj+'.rz',0) - + # Scale if mc.getAttr(obj+'.sx',se=True): mc.setAttr(obj+'.sx',0) if mc.getAttr(obj+'.sy',se=True): mc.setAttr(obj+'.sy',0) if mc.getAttr(obj+'.sz',se=True): mc.setAttr(obj+'.sz',0) - + # Return Result return objList @@ -923,21 +923,21 @@ def copyInputShapeAttrs(geoList=[]): # Check Geometry List if not geoList: geoList = mc.listRelatives(mc.ls(geometry=True) or [],p=True,pa=True) or [] if not geoList: return [] - + # Copy Input Shape Attrs for geo in geoList: - + # Get Output Shape geoShape = mc.listRelatives(geo,s=True,ni=True) or [] if not geoShape: print('No shape found for geometry transform "'+geo+'"!') continue - + # Get Input Shape geoInputShape = geoShape[0] try: geoInputShape = glTools.utils.shape.findInputShape(geoShape[0]) except: pass - + # Copy User Attributes if geoInputShape != geoShape[0]: userAttr = mc.listAttr(geoInputShape,ud=True,s=True) or [] @@ -957,7 +957,7 @@ def removeTurtle(): print('Removing Turtle nodes...') mc.lockNode(turtleNode,l=False) mc.delete(turtleNode) - + # Unload Plugin if mc.pluginInfo('Turtle',q=True,loaded=True): print('Unloading Turtle plugin...') diff --git a/utils/clip.py b/utils/clip.py index 56a6730..7317a3b 100644 --- a/utils/clip.py +++ b/utils/clip.py @@ -35,14 +35,14 @@ def createClip(charSet,startTime=None,endTime=None,name=''): # ========== # - Checks - # ========== - + # Check Character Set if not glTools.utils.characterSet.isCharSet(charSet): raise Exception('Object "'+charSet+'" is not a valid character set!') - + # Check Name if not name: name = 'clip' - + # Check Start/End Time if (startTime == None) or (endTime == None): charList = mc.sets(charSet,q=True) @@ -52,20 +52,20 @@ def createClip(charSet,startTime=None,endTime=None,name=''): startTime = charKeys[0] if endTime == None: endTime = charKeys[-1] - + # =============== # - Create Clip - # =============== - + clip = [''] try: clip = mc.clip(charSet, startTime=startTime, endTime=endTime, name=name ) except: print('Error creating clip "'+name+'"!') else: print('Clip "'+name+'" successfully created!') - + # ================= # - Return Result - # ================= - + return str(clip[0]) def exportClip(clip,clipPath,force=False): @@ -81,15 +81,15 @@ def exportClip(clip,clipPath,force=False): # ========== # - Checks - # ========== - + # Check Clip if not isClip(clip): raise Exception('Object "'+clip+'" is not a valid animation clip!') - + # Check Directory Path dirpath = os.path.dirname(clipPath) if not os.path.isdir(dirpath): os.makedirs(dirpath) - + # Check File Path if os.path.isfile(clipPath): if not force: @@ -97,31 +97,31 @@ def exportClip(clip,clipPath,force=False): else: try: os.remove(clipPath) except: pass - - + + # Check Extension ext = os.path.splitext(clipPath)[1].lower()[1:] if not (ext == 'ma') and not (ext == 'mb'): raise Exception('Invalid file extension "'+ext+'"!') - + # ======================= # - Source Required MEL - # ======================= - + scriptsPath = mm.eval('getenv MAYA_LOCATION')+'/scripts/others' mm.eval('source "'+scriptsPath+'/doExportClipArgList.mel"') - + # =============== # - Export Clip - # =============== - + mc.select(clip) result = mm.eval('clipEditorExportClip("'+clipPath+'", "'+ext+'")') - + # ================= # - Return Result - # ================= - + return result def importClip(clipPath,toChar='',toTrax=False): @@ -137,55 +137,55 @@ def importClip(clipPath,toChar='',toTrax=False): # Check File Path if not os.path.isfile(clipPath): raise Exception('No file exists at path "'+clipPath+'"!') - + # Check Extension ext = os.path.splitext(clipPath)[1].lower()[1:] if not (ext == 'ma') and not (ext == 'mb'): raise Exception('Invalid file extension "'+ext+'"!') - + # Check To Character if toChar: - + if not glTools.utils.characterSet.isCharSet(toChar): raise Exception('Object "'+toChar+'" is not a valid character set!') - + # Set Current Character glTools.utils.characterSet.setCurrent(toChar) - + else: - + # Get Current Character Set currChar = glTools.utils.characterSet.getCurrent() if currChar: toChar = currChar - + # ======================= # - Source Required MEL - # ======================= - + scriptsPath = mm.eval('getenv MAYA_LOCATION')+'/scripts/others' mm.eval('source "'+scriptsPath+'/doImportClipArgList.mel"') - + # =============== # - Import Clip - # =============== - + # Set Global MEL variables if toChar: mm.eval('global int $gImportClipToCharacter = 1;') mm.eval('global string $gImportToCharacter = "'+toChar+'";') if toTrax: mm.eval('global int $gScheduleClipOnCharacter = 1;') - + # Import Clip result = mm.eval('clipEditorImportClip("'+clipPath+'", "'+ext+'")') - + # Print Result if result: print ('Imported Clip: '+clipPath) - + # ================= # - Return Result - # ================= - + return result def importClips(charSet='',clips=[],toTrax=False): @@ -203,28 +203,28 @@ def importClips(charSet='',clips=[],toTrax=False): charSet = glTools.utils.characterSet.getCurrent() if charSet: glTools.utils.characterSet.setCurrent(charSet) - + # Get Asset from Character Set charSetNS = glTools.utils.namespace.getNS(charSet,topOnly=True) charCtx = glTools.utils.reference.contextFromNsReferencePath(charSetNS) char = charCtx['asset'] - + # Get Starting Directory assetPath = '' - + # Get Clips if not clips: clips = mc.fileDialog2(dir=assetPath,fileFilter='Maya Files (*.ma *.mb)',dialogStyle=2,fileMode=4,okCaption='Import',caption='Load Clip') - + # Import Clips for clipPath in clips: - + # Check Clip if not os.path.isfile(clipPath): print('Clip "'+clipPath+'" is not a valid file! Skipping...') continue - - # Import + + # Import importClip(clipPath,toChar=charSet,toTrax=toTrax) def importCharClips(charSet='',clips=[],toTrax=False): @@ -241,20 +241,20 @@ def importCharClips(charSet='',clips=[],toTrax=False): charSetNS = glTools.utils.namespace.getNS(charSet,topOnly=True) charCtx = glTools.utils.reference.contextFromNsReferencePath(charSetNS) char = charCtx['asset'] - + # Import Clips for clip in clips: - + # Determine Clip File Path clipFile = clipPath+clip+'.mb' - + # Check Clip File Path if not os.path.isfile(clipFile): clipFile = clipPath+clip+'.ma' if not os.path.isfile(clipFile): print('Clip file "'+clipFile+'" does not exist! Unable to import clip...') continue - + # Import Clip glTools.utils.clip.importClip(clipFile,toChar=charSet,toTrax=toTrax) @@ -270,15 +270,15 @@ def importClipsForAllChars(clips=[],toTrax=False): ''' # Get Clips if not clips: - + # Get Starting Directory assetPath = '/' - + # Select Clips clipList = mc.fileDialog2(dir=assetPath,fileFilter='Maya Files (*.ma *.mb)',dialogStyle=2,fileMode=4,okCaption='Import',caption='Load Clip') clips = [os.path.splitext(os.path.basename(clip))[0] for clip in clipList] - + # Import Clips for charSet in mc.ls(type='character'): - + importCharClips(charSet=charSet,clips=clips,toTrax=toTrax) diff --git a/utils/cluster.py b/utils/cluster.py index 41be745..7980875 100644 --- a/utils/cluster.py +++ b/utils/cluster.py @@ -29,24 +29,24 @@ def create( geo, prefix_geo = geo if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') - + # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(prefix_geo) - + # Create Cluster cluster = mc.cluster(geo,n=prefix+'_cluster') clusterHandle = cluster[1] clusterDeformer = cluster[0] - + # Group clusterGrp = None if group: clusterGrp = mc.duplicate(clusterHandle,po=True,n=prefix+'_clusterGrp')[0] mc.parent(clusterHandle,clusterGrp) - + # Bind Pre Matrix if bindPreMatrix: - + if bindPreMatrix == 'parent': # BindPreMatrix - ParentInverseMatrix mc.connectAttr(clusterHandle+'.parentInverseMatrix[0]',clusterDeformer+'.bindPreMatrix',f=True) @@ -57,6 +57,6 @@ def create( geo, if not glTools.utils.transform.isTransform(bindPreMatrix): raise Exception('Bind pre matrix transform "'+bindPreMatrix+'" is not a valid transform!') mc.connectAttr(bindPreMatrix+'.worldInverseMatrix[0]',clusterDeformer+'.bindPreMatrix',f=True) - + # Return Result return [clusterDeformer,clusterHandle,clusterGrp] diff --git a/utils/colorize.py b/utils/colorize.py index d3b2f53..978d789 100644 --- a/utils/colorize.py +++ b/utils/colorize.py @@ -11,7 +11,7 @@ def colorize(obj,color=None): # Check object if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!!') - + # Create color lookup dictionary colorDict = { 'grey':0, 'black':1, @@ -41,10 +41,10 @@ def colorize(obj,color=None): 'dull yellow':25, 'dull green':26, 'dull aqua':27 } - + # Enable Overrides mc.setAttr(obj+'.overrideEnabled',1) - + # Set Color if type(color) == str: if colorDict.has_key(color): mc.setAttr(obj+'.overrideColor',colorDict[color]) @@ -63,32 +63,32 @@ def setColour(obj): # ========== # - Checks - # ========== - + if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # ==================== # - Colorize By Name - # ==================== - + if obj.startswith('cn_') or obj.startswith('C_'): - + # Center if mc.objectType(obj) == 'joint': colorize(obj,'dull yellow') else: colorize(obj,'yellow') - + elif obj.startswith('lf_') or obj.startswith('L_'): - + # LEFT if mc.objectType(obj) == 'joint': colorize(obj,'pale green') else: colorize(obj,'green') - + elif obj.startswith('rt_') or obj.startswith('R_'): - + # LEFT if mc.objectType(obj) == 'joint': colorize(obj,'maroon') @@ -104,17 +104,17 @@ def colourHierarchy(root): # ========== # - Checks - # ========== - + if not mc.objExists(root): raise Exception('Object "'+root+'" does not exist!') - + if not mc.ls(root,dag=True): raise Exception('Object "'+root+'" is not a valid DAG node!') - + # ==================== # - Colorize By Name - # ==================== - + hier = mc.ls(mc.listRelatives(root,ad=True),dag=True) if not hier: hier = [] hier.append(root) @@ -128,28 +128,28 @@ def colorizeUI( colorIndex, layerOverride ): ''' ''' - + # ================= # - Create Window - # ================= - + window = 'colorizeUI' if mc.window(window,q=True,ex=1): mc.deleteUI(window) window = mc.window(window,t='Colorize',s=True) - + mc.columnLayout() mc.columnLayout(cw=550,adjustableColumn=True) mc.text(fn='boldLabelFont',align='center',label='Select all objects that you wish to adjust the override color of and then click OK or Apply.') mc.setParent('..') - + mc.separator(w=550,h=25) - + mc.columnLayout(cw=550,adjustableColumn=True) - mc.colorIndexSliderGrp('buildEdgeCurves_colorCISG',label="Select Color",min=1,max=32,value=colorIndex) + mc.colorIndexSliderGrp('buildEdgeCurves_colorCISG',label="Select Color",min=1,max=32,value=colorIndex) mc.setParent('..') - + mc.separator(w=550,h=25) - + mc.columnLayout(cw=550,adjustableColumn=True) mc.radioButtonGrp( 'colorize_applyToRBG', numberOfRadioButtons = 3, @@ -158,55 +158,55 @@ def colorizeUI( colorIndex, sl = applyTo, ann = 'Select whether to apply your colorize choices to the selected shape node(s), the transformation node, or both.') mc.setParent('..') - - mc.separator(w=550,h=25) - + + mc.separator(w=550,h=25) + """ rowColumnLayout -nc 2 -cw 1 362 -cw 2 188 ; - checkBoxGrp -ncb 2 + checkBoxGrp -ncb 2 -label "Advanced Overrides:" -labelArray2 "Visible" "Template" -v1 $visibility -v2 $template -ann "This will toggle the template or visibility state of the Shape(s) or Transformation nodes." advancedOptField; - checkBox -label "Override Display Layers" - -v $layerOverride + checkBox -label "Override Display Layers" + -v $layerOverride -cc "colorizeWinUpdate" layerOverrideField; setParent..; - - text -vis `checkBox -q -v layerOverrideField` - -label "WARNING: If your objects are in display layers, they will be removed by selecting this checkbox!" -align "center"; - - - separator -w 550 -h 25; - + + text -vis `checkBox -q -v layerOverrideField` + -label "WARNING: If your objects are in display layers, they will be removed by selecting this checkbox!" -align "center"; + + + separator -w 550 -h 25; + rowColumnLayout -nc 1 -cw 1 550 ; radioButtonGrp -numberOfRadioButtons 2 - -label "Set Override State:" - -labelArray2 "Enable Override" "Disable Override" - -sl $setState + -label "Set Override State:" + -labelArray2 "Enable Override" "Disable Override" + -sl $setState -ann "This will enable or disable the overrides that you are changing in this window." setStateField; setParent..; - - separator -w 550 -h 25; - + + separator -w 550 -h 25; + rowColumnLayout -nc 6 -cw 1 80 -cw 2 140 -cw 3 8 -cw 4 140 -cw 5 8 -cw 6 140; - text -label ""; + text -label ""; button -align "center" -label "OK" -c ("colorizeProc; deleteUI colorizeWin"); - text -label ""; - button -align "center" -label "Apply" -c ("colorizeProc"); - text -label ""; + text -label ""; + button -align "center" -label "Apply" -c ("colorizeProc"); + text -label ""; button -align "center" -label "Close" -c ("deleteUI colorizeWin"); """ - + mc.setParent('..') - + # =============== # - Show Window - # =============== - - mc.showWindow(window) + + mc.showWindow(window) diff --git a/utils/component.py b/utils/component.py index 1960743..fde5025 100644 --- a/utils/component.py +++ b/utils/component.py @@ -38,15 +38,15 @@ def isIntermediateShapeComponent(component): ''' # Check Component if not isComponent(component): return False - + # Check Object componentObj = mc.ls(component,o=True)[0] - + # Check Intermediate Object if mc.attributeQuery('intermediateObject',n=componentObj,ex=True): if mc.getAttr(componentObj+'.intermediateObject'): return True - + # Return Result return False @@ -59,17 +59,17 @@ def getComponentCount(geometry): # Check geometry if not mc.objExists(geometry): raise Exception('Object '+geometry+' does not exist!') - + # Check shape geomObj = glTools.utils.base.getMObject(geometry) if geomObj.hasFn(OpenMaya.MFn.kTransform): geomShape = mc.listRelatives(geometry,s=True,ni=True,pa=True)[0] - + # Get geometry path geomPath = glTools.utils.base.getMDagPath(geometry) # Initialize MItGeometry geomIt = OpenMaya.MItGeometry(geomPath) - + # Return result return geomIt.count() @@ -82,24 +82,24 @@ def getCenter(componentList=[]): # Check componentList if not componentList: componentList = mc.ls(sl=True) componentList = mc.ls(componentList,fl=True) - + # Initialize position pos = [0.0,0.0,0.0] - + # Append component position for component in componentList: pnt = mc.pointPosition(component) pos[0] += pnt[0] pos[1] += pnt[1] pos[2] += pnt[2] - + # Average position if componentList: componentLen = len(componentList) pos[0] /= componentLen pos[1] /= componentLen pos[2] /= componentLen - + # Return result return (pos[0],pos[1],pos[2]) @@ -143,19 +143,19 @@ def getComponentIndexList(componentList=[]): ''' # Initialize return dictionary componentIndexList = {} - + # Check string input if type(componentList) == str or type(componentList) == unicode: componentList = [componentList] - + # Get selection if componentList is empty if not componentList: componentList = mc.ls(sl=True,fl=True) or [] if not componentList: return [] - + # Get MSelectionList selList = OpenMaya.MSelectionList() for i in componentList: selList.add(str(i)) - + # Iterate through selection list selPath = OpenMaya.MDagPath() componentObj = OpenMaya.MObject() @@ -168,7 +168,7 @@ def getComponentIndexList(componentList=[]): componentSelList.clear() # Get current object name objName = selPath.partialPathName() - + # Transform if selPath.apiType() == OpenMaya.MFn.kTransform: numShapesUtil = OpenMaya.MScriptUtil() @@ -177,7 +177,7 @@ def getComponentIndexList(componentList=[]): selPath.numberOfShapesDirectlyBelow(numShapesPtr) numShapes = OpenMaya.MScriptUtil(numShapesPtr).asUint() selPath.extendToShapeDirectlyBelow(numShapes-1) - + # Mesh if selPath.apiType() == OpenMaya.MFn.kMesh: meshFn = OpenMaya.MFnMesh(selPath.node()) @@ -197,21 +197,21 @@ def getComponentIndexList(componentList=[]): tDiv = mc.getAttr(objName+'.tDivisions') uDiv = mc.getAttr(objName+'.uDivisions') componentSelList.add(objName+'.pt[0:'+str(sDiv - 1)+'][0:'+str(tDiv - 1)+'][0:'+str(uDiv - 1)+']') - + # Get object component MObject componentSelList.getDagPath(0,selPath,componentObj) - + # ======================= # - Check Geometry Type - # ======================= - + # MESH / NURBS CURVE if (selPath.apiType() == OpenMaya.MFn.kMesh) or (selPath.apiType() == OpenMaya.MFn.kNurbsCurve): indexList = OpenMaya.MIntArray() componentFn = OpenMaya.MFnSingleIndexedComponent(componentObj) componentFn.getElements(indexList) componentIndexList[selPath.partialPathName()] = list(indexList) - + # NURBS SURFACE if selPath.apiType() == OpenMaya.MFn.kNurbsSurface: indexListU = OpenMaya.MIntArray() @@ -219,7 +219,7 @@ def getComponentIndexList(componentList=[]): componentFn = OpenMaya.MFnDoubleIndexedComponent(componentObj) componentFn.getElements(indexListU,indexListV) componentIndexList[selPath.partialPathName()] = zip(list(indexListU),list(indexListV)) - + # LATTICE if selPath.apiType() == OpenMaya.MFn.kLattice: indexListS = OpenMaya.MIntArray() @@ -228,7 +228,7 @@ def getComponentIndexList(componentList=[]): componentFn = OpenMaya.MFnTripleIndexedComponent(componentObj) componentFn.getElements(indexListS,indexListT,indexListU) componentIndexList[selPath.partialPathName()] = zip(list(indexListS),list(indexListT),list(indexListU)) - + # Return Result return componentIndexList @@ -242,28 +242,28 @@ def getSingleIndexComponentList(componentList=[]): # Check Component List if not componentList: componentList = mc.ls(sl=True) if not componentList: return singleIndexList - + # Initialize Result singleIndexList = {} - + # Get Component Selection componentSel = getComponentIndexList(componentList) - + # Iterate Through Shape Keys shapeList = componentSel.keys() for shape in shapeList: - + # Get Shape Component Indices indexList = componentSel[shape] - + # Check Transform if mc.objectType(shape) == 'transform': shape = mc.listRelatives(shape,ni=True,pa=True)[0] - + # Check Mesh or Curve if (mc.objectType(shape) == 'mesh') or (mc.objectType(shape) == 'nurbsCurve'): singleIndexList[shape] = indexList - + # Check Surface elif mc.objectType(shape) == 'nurbsSurface': # Get nurbsSurface function set @@ -277,13 +277,13 @@ def getSingleIndexComponentList(componentList=[]): # Check for periodic surface if surfFn.formInV() == surfFn.kPeriodic: numV -= surfFn.degreeV() singleIndexList[shape] = [(i[0]*numV)+i[1] for i in indexList] - + # Check Lattice elif (mc.objectType(shape) == 'lattice'): sDiv = mc.getAttr(shape+'.sDivisions') tDiv = mc.getAttr(shape+'.tDivisions') singleIndexList[shape] = [i[0]+(i[1]*sDiv)+(i[2]*sDiv*tDiv) for i in indexList] - + # Return Result return singleIndexList @@ -297,15 +297,15 @@ def getSingleIndex(obj,index): @type index: list ''' # Get Shape - if mc.objectType(obj) == 'transform': + if mc.objectType(obj) == 'transform': obj = glTools.utils.selection.getShapes(obj,True,False)[0] - + # Mesh if mc.objectType(obj) == 'mesh': return index - + # Nurbs Curve if mc.objectType(obj) == 'nurbsCurve': return index - + # Nurbs Surface if mc.objectType(obj) == 'nurbsSurface': # Get nurbsSurface function set @@ -321,16 +321,16 @@ def getSingleIndex(obj,index): numV -= surfFn.degreeV() # Get Single Index return (index[0] * numV) + index[1] - + # Lattice elif mc.objectType(obj) == 'lattice': sDiv = mc.getAttr(obj+'.sDivisions') tDiv = mc.getAttr(obj+'.tDivisions') return (index[0] + (index[1] * sDiv) + (index[2] * sdiv * tDiv) ) - + # Return Result return None - + def getSingleIndexFromComponent(component): ''' Convert a 2 or 3 value index to a single value index. @@ -341,12 +341,12 @@ def getSingleIndexFromComponent(component): # Check component if not mc.objExists(component): raise Exception('Component "'+component+'" does not exist!') - + # Get selection elements comp = glTools.utils.selection.getSelectionElement(component) shape = comp[0].partialPathName() shapeType = mc.objectType(shape) - + # Check Mesh if shapeType == 'mesh': indexList = OpenMaya.MIntArray() @@ -354,7 +354,7 @@ def getSingleIndexFromComponent(component): componentFn.getElements(indexList) # Return Index return indexList[0] - + # Nurbs Curve if shapeType == 'nurbsCurve': indexList = OpenMaya.MIntArray() @@ -362,7 +362,7 @@ def getSingleIndexFromComponent(component): componentFn.getElements(indexList) # Return Index return indexList[0] - + # Nurbs Surface if shapeType == 'nurbsSurface': indexListU = OpenMaya.MIntArray() @@ -376,7 +376,7 @@ def getSingleIndexFromComponent(component): numV -= surfFn.degreeV() # Return Index return (indexListU[0] * numV) + indexListV[0] - + # Lattice if shapeType == 'lattice': indexListS = OpenMaya.MIntArray() @@ -402,17 +402,17 @@ def getMultiIndex(obj,index): # Get shape node if mc.objectType(obj) == 'transform': obj = glTools.utils.selection.getShapes(obj,True,False)[0] - + # Mesh if mc.objectType(obj) == 'mesh': print('Component specified is a mesh vertex! No multi index information for single element indices!!') return [index] - + # Nurbs Curve if mc.objectType(obj) == 'nurbsCurve': print('Component specified is a curve CV! No multi index information for single element indices!!') return [index] - + # Nurbs Surface if mc.objectType(obj) == 'nurbsSurface': # Spans / Degree / Form @@ -424,7 +424,7 @@ def getMultiIndex(obj,index): uIndex = int(index/(spansV+degreeV)) vIndex = index%(spansV+degreeV) return [uIndex,vIndex] - + # Lattice elif mc.objectType(obj) == 'lattice': sDiv = mc.getAttr(obj+'.sDivisions') @@ -446,19 +446,19 @@ def getComponentStrList(geometry,componentIndexList=[]): # Check object if not mc.objExists(geometry): raise Exception('Object '+geometry+' does not exist!') - + # Check transform mObj = glTools.utils.base.getMObject(geometry) if mObj.hasFn(OpenMaya.MFn.kTransform): geometry = glTools.utils.selection.getShapes(geometry,True,False) if geometry: geometry = geometry[0] else: raise Exception('Object '+geometry+' is not a valid geometry object!') - + # Check type mObj = glTools.utils.base.getMObject(geometry) if not mObj.hasFn(OpenMaya.MFn.kShape): raise Exception('Object "'+geometry+'" is not a valid geometry object!') - + # Get component multiIndex list componentStrList = [] componentList = [] @@ -469,7 +469,7 @@ def getComponentStrList(geometry,componentIndexList=[]): index = getMultiIndex(geometry,i) if len(index) == 1: componentList.append( index[0] ) else: componentList.append( index ) - + objType = mc.objectType(geometry) for i in componentList: # Mesh @@ -484,7 +484,7 @@ def getComponentStrList(geometry,componentIndexList=[]): # Lattice if objType == 'lattice': componentStrList.append(geometry+'.pt['+str(i[0])+']['+str(i[1])+']['+str(i[2])+']') - + # Return Component String List return componentStrList @@ -504,7 +504,7 @@ def rotate(componentList=[],rotate=(0.0,0.0,0.0),pivot='center',userPivot=(0,0,0 ''' # Check componentList if not componentList: componentList = mc.ls(componentList,fl=True) - + # Determine rotation pivot piv = (0,0,0) if pivot == 'center': @@ -516,7 +516,7 @@ def rotate(componentList=[],rotate=(0.0,0.0,0.0),pivot='center',userPivot=(0,0,0 piv = userPivot else: raise Exception('Invalid pivot option - "'+pivot+'"! Specify "object", "center" or "user"!!') - + # Rotate Components mc.rotate(rotate[0],rotate[1],rotate[2],componentList,p=piv,ws=worldSpace,os=not worldSpace) @@ -536,7 +536,7 @@ def scale(componentList=[],scale=(1.0,1.0,1.0),pivot='center',userPivot=(0,0,0), ''' # Check componentList if not componentList: componentList = mc.ls(componentList,fl=True) - + # Determine rotation pivot piv = (0,0,0) if pivot == 'center': @@ -549,7 +549,7 @@ def scale(componentList=[],scale=(1.0,1.0,1.0),pivot='center',userPivot=(0,0,0), piv = userPivot else: raise Exception('Invalid pivot option - "'+pivot+'"! Specify "object", "center" or "user"!!') - + # Scale Components if worldSpace: for component in componentList: @@ -571,15 +571,15 @@ def expandVertexSelection(vtxSel,useFace=False): # ========== # - Checks - # ========== - + # Check Vertex Selection vtxSel = mc.filterExpand(vtxSel,sm=31) if not vtxSel: raise Exception('Invalid vertex selection!') - + # ==================== # - Expand Selection - # ==================== - + conSel = [] if useFace: # Convert To Faces @@ -589,11 +589,11 @@ def expandVertexSelection(vtxSel,useFace=False): conSel = mc.polyListComponentConversion(vtxSel,fv=True,te=True,internal=False) # Convert To Vertex newSel = mc.polyListComponentConversion(conSel,ff=True,fe=True,tv=True,internal=False) - + # ================= # - Return Result - # ================= - + return newSel def shrinkVertexSelection(vtxSel): @@ -605,24 +605,24 @@ def shrinkVertexSelection(vtxSel): # ========== # - Checks - # ========== - + # Check Vertex Selection vtxSel = mc.filterExpand(vtxSel,sm=31) if not vtxSel: raise Exception('Invalid vertex selection!') - + # ==================== # - Shrink Selection - # ==================== - + # Convert To Faces conSel = mc.polyListComponentConversion(vtxSel,fv=True,tf=True,internal=True) # Convert To Vertex newSel = mc.polyListComponentConversion(conSel,ff=True,fe=True,tv=True,internal=True) - + # ================= # - Return Result - # ================= - + return newSel def removeIntermediateShapeComponents(componentList): @@ -633,10 +633,10 @@ def removeIntermediateShapeComponents(componentList): ''' # Check Component List if not componentList: return [] - + # Remove Intermediate Shape Components outComponentList = [i for i in componentList if not isIntermediateShapeComponent(i)] - + # Return Result return outComponentList @@ -649,11 +649,11 @@ def getNonIntermediateShapeComponent(component): # Check Component if not isComponent(component): raise Exception('Object "'+component+'" is not a valid shape component!') - + # Check Intermediate Shape Component if not isIntermediateShapeComponent(component): return component - + # Get Non-Intermediate Equivalent componentObj = mc.ls(component,o=True)[0] componentShape = componentObj @@ -662,7 +662,7 @@ def getNonIntermediateShapeComponent(component): if not componentOut: raise Exception('Unable to determine non-intermediate equivalent component!') nonIntComponent = component.replace(componentShape,componentOut[0]) - + # Return Result return nonIntComponent @@ -674,7 +674,7 @@ def replaceIntermediateShapeComponents(componentList): ''' # Check Component List if not componentList: return [] - + # Replace Intermediate Shape Components outComponentList = [] for i in componentList: @@ -685,6 +685,6 @@ def replaceIntermediateShapeComponents(componentList): else: if not i in outComponentList: outComponentList.append(i) - + # Return Result return outComponentList diff --git a/utils/connection.py b/utils/connection.py index a9cab44..940205b 100644 --- a/utils/connection.py +++ b/utils/connection.py @@ -12,11 +12,11 @@ def connectionListToAttr(toNode,toAttr): # Verify if not mc.objExists(toNode+'.'+toAttr): raise Exception('Attribute ' + toNode+'.'+toAttr + ' does not exist!') - + # Get MPlug to toAttr toNodeObj = glTools.utils.base.getMObject(toNode) toAttrPlug = OpenMaya.MFnDependencyNode(toNodeObj).findPlug(toAttr) - + # Get MPlugArray of connected plugs connectionList = {} connectedPlugArray = OpenMaya.MPlugArray() @@ -40,10 +40,10 @@ def connectionListToAttr(toNode,toAttr): attr += elem if (len(elem) > 1) and (elem != plugElem[-1]): attr += '.' connectionList[node] = (attr,-(i+1)) - + # Return Result return connectionList - + def connectionListFromAttr(fromNode,fromAttr): ''' Return a dictionary containing outgoing connection information for a specific attribute @@ -53,11 +53,11 @@ def connectionListFromAttr(fromNode,fromAttr): # Verify if not mc.objExists(fromNode+'.'+fromAttr): raise Exception('Attribute ' + fromNode+'.'+fromAttr + ' does not exist!') - + # Get MPlug to fromAttr fromNodeObj = glTools.utils.base.getMObject(fromNode) fromAttrPlug = OpenMaya.MFnDependencyNode(fromNodeObj).findPlug(fromAttr) - + # Get MPlugArray of connected plugs connectionList = {} connectedPlugArray = OpenMaya.MPlugArray() @@ -81,14 +81,14 @@ def connectionListFromAttr(fromNode,fromAttr): attr += elem if (len(elem) > 1) and (elem != plugElem[-1]): attr += '.' connectionList[node] = (attr,-(i+1)) - + # Return Result return connectionList def combineSingleAttrConnections(targetAttr,inputAttr1='',inputAttr2='',inputAttr1Value=None,inputAttr2Value=None,combineMode='add',enableAttributeOverride=False,blendAttr=''): ''' Connect the combined result of 2 input attributes/values to a target attribute. - + @param targetAttr: Target attribute to receive the combined values result @type targetAttr: str @param inputAttr1: First attribute to be used to obtain the combined result @@ -108,7 +108,7 @@ def combineSingleAttrConnections(targetAttr,inputAttr1='',inputAttr2='',inputAtt ''' # Check existing connections existingConn = mc.listConnections(targetAttr,s=True,d=False,p=True) - + # Check target attributes if not mc.objExists(targetAttr): raise Exception('Target attribute '+targetAttr+' does not exist!') # Check inputs @@ -117,11 +117,11 @@ def combineSingleAttrConnections(targetAttr,inputAttr1='',inputAttr2='',inputAtt # Check input attributes if inputAttr1 and not mc.objExists(inputAttr1): raise Exception('Input attribute 1 '+inputAttr1+' does not exist!') if inputAttr2 and not mc.objExists(inputAttr2): raise Exception('Input attribute 2 '+inputAttr2+' does not exist!') - + # Get target node name if not targetAttr.count('.'): raise Exception(targetAttr+' is not a valid attribute!') targetNode = targetAttr.split('.')[0] - + # Combine inputs combineNode = '' combineAttr1 = 'input1' @@ -137,7 +137,7 @@ def combineSingleAttrConnections(targetAttr,inputAttr1='',inputAttr2='',inputAtt combineNode = mc.createNode('blendTwoAttr',n=combineNode) combineAttr1 = 'input[0]' combineAttr2 = 'input[1]' - + # Set Input 1 if inputAttr1: mc.connectAttr(inputAttr1,combineNode+'.'+combineAttr1,f=True) @@ -152,10 +152,10 @@ def combineSingleAttrConnections(targetAttr,inputAttr1='',inputAttr2='',inputAtt mc.setAttr(inputAttr2,inputAttr2Value) else: mc.setAttr(combineNode+'.'+combineAttr2,inputAttr2Value) - + # Connect to target attribute mc.connectAttr(combineNode+'.output',targetAttr,f=True) - + # Connect blend attribute if combineMode == 'blend' and blendAttr: # Check blend attribute @@ -167,7 +167,7 @@ def combineSingleAttrConnections(targetAttr,inputAttr1='',inputAttr2='',inputAtt mc.addAttr(blendAttrName[0],ln=blendAttrName[1],at='float',min=0,max=1,dv=0) mc.setAttr(blendAttr,k=True) mc.connectAttr(blendAttr,blendNode+'.attributesBlender',f=True) - + # Return result return combineNode @@ -190,11 +190,11 @@ def replace(original,new,inputs=True,outputs=True): # Check new if not mc.objExists(new): raise Exception('Object "'+new+'" does not exist!!') newAttr = bool(new.count('.')) - + # Check argument types if origAttr != newAttr: raise Exception('Specify 2 nodes or node attributes! Cannot mix nodes and attributes!!') asAttr = origAttr - + # INPUTS if inputs: if asAttr: @@ -213,7 +213,7 @@ def replace(original,new,inputs=True,outputs=True): try: mc.connectAttr(inputList[(i*2)+1],newDest,f=True) except: raise Exception('FAILED: '+inputList[(i*2)+1]+' -> '+newDest+'!') else: print ('Connected: '+inputList[(i*2)+1]+' -> '+newDest) - + # OUTPUTS if outputs: if asAttr: @@ -239,48 +239,48 @@ def swap(node1,node2): # ======================== # - Get Node Connections - # ======================== - + node1conn_src = mc.listConnections(node1,s=True,d=False,p=True,c=True,sh=True) or [] node1conn_dst = mc.listConnections(node1,s=False,d=True,p=True,c=True,sh=True) or [] node2conn_src = mc.listConnections(node2,s=True,d=False,p=True,c=True,sh=True) or [] node2conn_dst = mc.listConnections(node2,s=False,d=True,p=True,c=True,sh=True) or [] - + # ==================== # - Disconnect Attrs - # ==================== - + # Disconnect Node 1 Source for i in range(0,len(node1conn_src),2): try: mc.disconnectAttr(node1conn_src[i+1],node1conn_src[i]) except: print ('FAILED: '+node1conn_src[i+1]+' X '+node1conn_src[i]+'!') else: print ('Disconnected: '+node1conn_src[i+1]+' X '+node1conn_src[i]+'!') - + # Disconnect Node 1 Destination for i in range(0,len(node1conn_dst),2): try: mc.disconnectAttr(node1conn_dst[i],node1conn_dst[i+1]) except: print ('FAILED: '+node1conn_dst[i]+' X '+node1conn_dst[i+1]+'!') else: print ('Disconnected: '+node1conn_dst[i]+' X '+node1conn_dst[i+1]+'!') - + # - - + # Disconnect Node 2 Source for i in range(0,len(node2conn_src),2): try: mc.disconnectAttr(node2conn_src[i+1],node2conn_src[i]) except: print ('FAILED: '+node2conn_src[i+1]+' X '+node2conn_src[i]+'!') else: print ('Disconnected: '+node2conn_src[i+1]+' X '+node2conn_src[i]+'!') - + # Disconnect Node 2 Destination for i in range(0,len(node2conn_dst),2): try: mc.disconnectAttr(node2conn_dst[i],node2conn_dst[i+1]) except: print ('FAILED: '+node2conn_dst[i]+' X '+node2conn_dst[i+1]+'!') else: print ('Disconnected: '+node2conn_dst[i]+' X '+node2conn_dst[i+1]+'!') - + # ================= # - Connect Attrs - # ================= - + # - Connect Node 1 --- - + # Connect Node 1 Source for i in range(0,len(node1conn_src),2): dst = node1conn_src[i].replace(node1,node2) @@ -288,7 +288,7 @@ def swap(node1,node2): try: mc.connectAttr(src,dst,f=True) except: print ('FAILED: '+src+' -> '+dst+'!') else: print ('Connected: '+src+' -> '+dst+'...') - + # Connect Node 1 Destination for i in range(0,len(node1conn_dst),2): src = node1conn_dst[i].replace(node1,node2) @@ -296,9 +296,9 @@ def swap(node1,node2): try: mc.connectAttr(src,dst,f=True) except: print ('FAILED: '+src+' -> '+dst+'!') else: print ('Connected: '+src+' -> '+dst+'...') - + # - Connect Node 2 --- - + # Connect Node 2 Source for i in range(0,len(node2conn_src),2): dst = node2conn_src[i].replace(node2,node1) @@ -306,7 +306,7 @@ def swap(node1,node2): try: mc.connectAttr(src,dst,f=True) except: print ('FAILED: '+src+' -> '+dst+'!') else: print ('Connected: '+src+' -> '+dst+'...') - + # Connect Node 2 Destination for i in range(0,len(node2conn_dst),2): src = node2conn_dst[i].replace(node2,node1) @@ -314,9 +314,9 @@ def swap(node1,node2): try: mc.connectAttr(src,dst,f=True) except: print ('FAILED: '+src+' -> '+dst+'!') else: print ('Connected: '+src+' -> '+dst+'...') - + # ================= # - Return Result - # ================= - - return \ No newline at end of file + + return diff --git a/utils/constraint.py b/utils/constraint.py index 8d945ab..65cccfb 100644 --- a/utils/constraint.py +++ b/utils/constraint.py @@ -20,17 +20,17 @@ def isBaked(constraint): # Check Constraint if not isConstraint(constraint): raise Exception('Constraint "'+constraint+'" does not exist!!') - + # Get Constraint Slave cSlave = slave(constraint) - + # Get Slave Channels cSlaveAttrs = mc.listConnections(constraint,s=False,d=True,p=True) or [] slaveAttrs = [i.split('.')[-1] for i in attrList if i.startswith(slave+'.')] or [] - + # Check Slave Channels if slaveAttrs: return False - + # Return Result return False @@ -43,7 +43,7 @@ def targetList(constraint): # Check Constraint if not isConstraint(constraint): raise Exception('Constraint "'+constraint+'" does not exist!!') - + # Get Target List targetList = [] constraintType = mc.objectType(constraint) @@ -56,10 +56,10 @@ def targetList(constraint): elif constraintType == 'poleVectorConstraint': targetList = mc.poleVectorConstraint(constraint,q=True,tl=True) elif constraintType == 'scaleConstraint': targetList = mc.scaleConstraint(constraint,q=True,tl=True) elif constraintType == 'tangentConstraint': targetList = mc.tangentConstraint(constraint,q=True,tl=True) - + # Check Target List if not targetList: targetList = [] - + # Return Result return targetList @@ -87,7 +87,7 @@ def targetAliasList(constraint): # Check Constraint if not isConstraint(constraint): raise Exception('Constraint "'+constraint+'" does not exist!!') - + # Get Target List targetList = [] constraintType = mc.objectType(constraint) @@ -100,10 +100,10 @@ def targetAliasList(constraint): elif constraintType == 'poleVectorConstraint': targetList = mc.poleVectorConstraint(constraint,q=True,weightAliasList=True) elif constraintType == 'scaleConstraint': targetList = mc.scaleConstraint(constraint,q=True,weightAliasList=True) elif constraintType == 'tangentConstraint': targetList = mc.tangentConstraint(constraint,q=True,weightAliasList=True) - + # Check Target List if not targetList: targetList = [] - + # Return Result return targetList @@ -118,21 +118,21 @@ def targetAlias(constraint,target): # Check Constraint if not isConstraint(constraint): raise Exception('Object "'+constraint+'" is not a valid constraint node!') - - # Get Target List + + # Get Target List conTargetList = targetList(constraint) if not conTargetList.count(target): raise Exception('Constraint "'+constraint+'" has no target "'+target+'"!') - + # Get Target Alias List conTargetAliasList = targetAliasList(constraint) - + # Get Target Index targetIndex = conTargetList.index(target) - + # Get Target Alias targetAlias = conTargetAliasList[targetIndex] - + # Return Result return targetAlias @@ -145,13 +145,13 @@ def slaveList(constraint): # Check constraint if not mc.objExists(constraint): raise Exception('Constraint '+constraint+' does not exist!!') constraintType = mc.objectType(constraint) - + # Get slave list #targetList = [] #[targetList.append(i) for i in mc.listConnections(constraint,s=False,d=True) if not targetList.count(i)] #if targetList.count(constraint): targetList.remove(constraint) targetList = mc.listConnections(constraint+'.constraintParentInverseMatrix',s=True,d=False) or [] - + # Return result return targetList @@ -185,48 +185,48 @@ def blendConstraint(targetList,slave,blendNode='',blendAttr='bias',maintainOffse ''' # Check prefix if not prefix: prefix = slave - + # Check targets if len(targetList) != 2: raise Exception('Target list must contain 2 target transform!') for target in targetList: if not mc.objExists(target): raise Exception('Target transform "'+target+'" does not exist!') - + # Check slave if not mc.objExists(slave): raise Exception('Slave transform "'+slave+'" does not exist!') - + # Check blendNode if not blendNode: blendNode = slave - + # Create constraint constraint = mc.parentConstraint(targetList,slave,mo=maintainOffset,n=prefix+'_parentConstraint')[0] constraintAlias = mc.parentConstraint(constraint,q=True,wal=True) - + # Create blend mc.addAttr(blendNode,ln=blendAttr,min=0,max=1,dv=0.5,k=True) blendSub = mc.createNode('plusMinusAverage',n=prefix+'_plusMinusAverage') mc.setAttr(blendSub+'.operation',2) # Subtract mc.setAttr(blendSub+'.input1D[0]',1.0) mc.connectAttr(blendNode+'.'+blendAttr,blendSub+'.input1D[1]',f=True) - + # Connect Blend mc.connectAttr(blendSub+'.output1D',constraint+'.'+constraintAlias[0],f=True) mc.connectAttr(blendNode+'.'+blendAttr,constraint+'.'+constraintAlias[1],f=True) - + # Return result return blendNode+'.'+blendAttr def rounding(transformList,control,attr='round',prefix=''): ''' Create rounding constraint. - + Given 5 transforms [1,2,3,4,5]: Transform 2 will be constrainted between 1 and 3. Transform 4 will be constrainted between 3 and 5. - + The attribute control.attr controls the weights of the constraint. - + @param transformList: Specify 5 transforms used for constraint @type transformList: list @param control: Control that contains attribute for controlling constraint weight @@ -240,24 +240,24 @@ def rounding(transformList,control,attr='round',prefix=''): if len(transformList) != 5: raise Exception('Supply exactly 5 valid transforms to the transformList list argument!') # Check control if not mc.objExists(control): raise Exception('Object "'+control+'" does not exist!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(control) - + # Ensure attr exists and in keyable if not mc.objExists(control+'.'+attr): mc.addAttr(control,ln=attr,at='double',min=0.0,max=1.0,dv=0.5,k=True) - + # Create point constraints pointConstraint1 = prefix+'_round_01_pointConstraint' pointConstraint1 = mc.pointConstraint([transformList[2],transformList[0]],transformList[1],w=1,mo=False,n=pointConstraint1)[0] pointConstraint2 = prefix+'_round_02_pointConstraint' pointConstraint2 = mc.pointConstraint([transformList[2],transformList[4]],transformList[3],w=1,mo=False,n=pointConstraint2)[0] - + # Get target alias lists targetAliasList1 = targetAliasList(pointConstraint1) targetAliasList2 = targetAliasList(pointConstraint2) - + # Setup constraint weight control mc.connectAttr(control+'.'+attr,pointConstraint1+'.'+targetAliasList1[1],force=True) mc.connectAttr(control+'.'+attr,pointConstraint2+'.'+targetAliasList2[1],force=True) @@ -266,7 +266,7 @@ def rounding(transformList,control,attr='round',prefix=''): mc.connectAttr(control+'.'+attr, reverseNode+'.inputX',force=True) mc.connectAttr(reverseNode+'.outputX',pointConstraint1+'.'+targetAliasList1[0],force=True) mc.connectAttr(reverseNode+'.outputX',pointConstraint2+'.'+targetAliasList2[0],force=True) - + # Return point constraints return [pointConstraint1,pointConstraint2] diff --git a/utils/container.py b/utils/container.py index 4d3de5a..386541e 100644 --- a/utils/container.py +++ b/utils/container.py @@ -28,32 +28,32 @@ def create(name,nodes=None,dagContainer=True): # ========== # - Checks - # ========== - + # Asset Node if mc.objExists(name): raise Exception('Object "'+name+'" already exist! Unable to create container...') - + # Nodes if nodes: for node in nodes: if not mc.objExists(node): raise Exception('Object "'+node+'" does not exist! Unable to add to container...') - + # ========================== # - Create Asset Container - # ========================== - + # Create Node if not dagContainer: containerNode = mc.container(n=name) else: containerNode = mc.container(n=name,typ='dagContainer') - + # Add Nodes if nodes: mc.container(containerNode,e=True,addNode=nodes,f=True) - + # ================= # - Return Result - # ================= - + return containerNode def nodeList(containerNode): @@ -65,12 +65,12 @@ def nodeList(containerNode): # Check Asset Node if not isContainer(containerNode): raise Exception('Object "'+containerNode+'" is not a valid container node!') - + # Get Asset Container Nodes nodeList = mc.container(containerNode,q=True,nodeList=True) if not nodeList: nodeList = [] else: nodeList = [str(i) for i in nodeList] - + # Return Result return nodeList @@ -100,33 +100,33 @@ def publishAttr(attr,assetAttrName=None,bind=True): # ========== # - Checks - # ========== - + # Attribute if not mc.objExists(attr): raise Exception('Attribute "'+attr+'" does not exist! Unable to publish attribute to asset...') - + # Asset Attribute Name if not assetAttrName: assetAttrName = attr.replace('.','_') - + # ====================== # - Get Node and Asset - # ====================== - + node = mc.ls(attr,o=True) containerNode = assetFromNode(node) - + # ===================== # - Publish Attribute - # ===================== - + # Publish Attribute (Unbound) mc.container(containerNode,e=True,publishName=assetAttrName) - + # Bid to Attribute if bind: mc.container(containerNode,e=True,bindAttr=[attr,assetAttrName]) - + # ================= # - Return Result - # ================= - + return containerNode+'.'+assetAttrName diff --git a/utils/copyMeshToCurve.py b/utils/copyMeshToCurve.py index 0f348f1..46ef429 100644 --- a/utils/copyMeshToCurve.py +++ b/utils/copyMeshToCurve.py @@ -14,24 +14,24 @@ def create(baseCrv,curveList,inMeshList,prefix): ''' # Create copyMeshToCurve node copyMeshToCurve = mc.createNode('copyMeshToCurve',n=prefix+'_copyMeshToCurve') - + # Connect base curve mc.connectAttr(baseCrv+'.worldSpace[0]',copyMeshToCurve+'.baseCurve',f=True) - + # Connect input curves connectInputCurves(copyMeshToCurve,curveList) - + # Connect input mesh connectInputMesh(copyMeshToCurve,inMeshList) - + # Create output mesh outMeshShape = mc.createNode('mesh',n=prefix+'_outMeshShape') outMesh = mc.listRelatives(outMeshShape,p=True)[0] mc.rename(outMesh,prefix+'_outMesh') - + # Connect out mesh mc.connectAttr(copyMeshToCurve+'.outputMesh',outMeshShape+'.inMesh',f=True) - + # Return Reult return copyMeshToCurve @@ -46,7 +46,7 @@ def connectInputCurves(copyMeshToCurve,curveList): # Connect Input Curves for i in range(len(curveList)): mc.connectAttr(curveList[i]+'.worldSpace[0]',copyMeshToCurve+'.inputCurve['+str(i)+']',f=True) - + def connectInputMesh(copyMeshToCurve,inMeshList): ''' Connect a list of input meshes to the specified copyMeshToCurve node. diff --git a/utils/curve.py b/utils/curve.py index 91b7822..b1c796a 100644 --- a/utils/curve.py +++ b/utils/curve.py @@ -12,10 +12,10 @@ def isCurve(curve): ''' Check if the specified object is a nurbs curve or transform parent of a curve - + @param curve: Object to query @type curve: str - + @return: Boolean value indicating if the input object is a valid nurbs curve @returnType: bool ''' @@ -24,41 +24,41 @@ def isCurve(curve): # Check shape if mc.objectType(curve) == 'transform': curve = mc.listRelatives(curve,s=True,ni=True,pa=True)[0] if mc.objectType(curve) != 'nurbsCurve': return False - + # Return result return True def getCurveFn(curve): ''' Create an MFnNurbsCurve class object from the specified nurbs curve - + @param curve: Curve to create function class for @type curve: str - + @return: An MFnNurnrsCurve function class initialized with the input curve @returnType: MFnNurnrsCurve ''' # Checks if not isCurve(curve): raise Exception('Object '+curve+' is not a valid curve!') - + # Get shape if mc.objectType(curve) == 'transform': curve = mc.listRelatives(curve,s=True,ni=True)[0] - + # Get MFnNurbsCurve curveSel = OpenMaya.MSelectionList() OpenMaya.MGlobal.getSelectionListByName(curve,curveSel) curvePath = OpenMaya.MDagPath() curveSel.getDagPath(0,curvePath) curveFn = OpenMaya.MFnNurbsCurve(curvePath) - + # Return result return curveFn - + def createFromPointList(pointList,degree=3,prefix=''): ''' Build a nurbs curve from a list of arbitrary positions - + @param pointList: List of CV positions @type pointList: list @param degree: Degree of the curve to create @@ -68,22 +68,22 @@ def createFromPointList(pointList,degree=3,prefix=''): ''' # Build CV list cvList = [glTools.utils.base.getPosition(i) for i in pointList] - + # Build curve crv = mc.curve(p=cvList,k=range(len(cvList)),d=1) crv = mc.rename(crv,prefix+'_crv') - + # Rebuild curve if degree > 1: crv = mc.rebuildCurve(crv,d=degree,kcp=True,kr=0,ch=False,rpo=True)[0] - + # Return resulting curve return crv def createFromEditPointList(pointList,degree=3,form=1,prefix='curve'): ''' Build a nurbs curve from a list of edit point positions - + @param pointList: List of edit point positions @type pointList: list @param degree: Degree of the curve to create @@ -92,7 +92,7 @@ def createFromEditPointList(pointList,degree=3,form=1,prefix='curve'): @type form: int @param prefix: Name prefix for newly created nodes @type prefix: str - + @return: The curve created based on input argument values @returnType: str ''' @@ -110,7 +110,7 @@ def createFromEditPointList(pointList,degree=3,form=1,prefix='curve'): def createFromLocators(locatorList,degree=3,attach=False,prefix='curve'): ''' Create a curve from a list of locators. Optionally attach curve CVs to locator positions - + @param locatorList: List of CV positions @type locatorList: list @param degree: Degree of the curve to create @@ -119,7 +119,7 @@ def createFromLocators(locatorList,degree=3,attach=False,prefix='curve'): @type attach: bool @param prefix: Name prefix for newly created nodes @type prefix: str - + @return: The curve created based on input argument values @returnType: str ''' @@ -127,17 +127,17 @@ def createFromLocators(locatorList,degree=3,attach=False,prefix='curve'): locPosList = [] for i in range(len(locatorList)): locPosList.append(mc.getAttr(locatorList[i]+'.worldPosition')[0]) - + # Build curve curve = createFromPointList(locPosList,degree,prefix) - + # Rename Curve curveShape = mc.listRelatives(curve,s=True,pa=True)[0] curveShape = mc.rename(curveShape,curve+'Shape') - + # Attach curve if attach: curveToLocators(curve,locatorList) - + # Return Result return curve @@ -161,11 +161,11 @@ def locatorCurve(curve,controlPoints=[],locatorScale=0.05,local=False,freeze=Tru # ========== # - Checks - # ========== - + # Check Curve if not isCurve(curve): raise Exception('Object '+curve+ ' is not a valid curve!') - + # Check Curve Shape curveShape=None if mc.objectType(curve) == 'transform': @@ -173,74 +173,74 @@ def locatorCurve(curve,controlPoints=[],locatorScale=0.05,local=False,freeze=Tru else: curveShape = curve curve = mc.listRelatives(curve,p=1)[0] - + # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # Check CVs controlPointList = [] if controlPoints: controlPointList = glTools.utils.component.getComponentIndexList(controlPoints)[curveShape] else: controlPointList = range(glTools.utils.component.getComponentCount(curve)) - + # =================== # - Create Locators - # =================== - + # Initialize Return List locatorList = [] - + # Set Locator Scale locatorScale *= mc.arclen(curve) - + # Iterate Over CVs for i in controlPointList: - + # Generate String Index ind = glTools.utils.stringUtils.stringIndex(i,1) - + # Get CV Position pos = mc.pointPosition(curve+'.cv['+str(i)+']') - + # Create Locator locator = mc.spaceLocator(n=prefix+'_cv'+ind+'_'+suffix)[0] - + # Position Locator mc.xform(locator,ws=True,t=pos) mc.setAttr(locator+".localScale",locatorScale,locatorScale,locatorScale) - + # Add CV ID Attribute mc.addAttr(locator,ln='cvID',at='long',dv=i) - + # Connect to CV if local: mc.connectAttr(locator+'.translate',curve+'.controlPoints['+str(i)+']') else: if freeze: mc.makeIdentity(locator,apply=True,t=1,r=1,s=1,n=0) mc.connectAttr(locator+'.worldPosition[0]',curve+'.controlPoints['+str(i)+']') - + # Append to Return List locatorList.append(locator) - + # ================= # - Return Result - # ================= - + return locatorList def locatorEpCurve(curve,locatorScale=0.05,prefix=''): ''' Creates locators for each edit point for the specified curve. Edit points are constrained to the locator world positions. - + @param curve: Curve to operate on @type curve: str @param locatorScale: Control the relative scale of the locators to the length of curve @type locatorScale: float @param prefix: Name prefix for newly created nodes @type prefix: str - + @return: A list containing the names of the locators driving the curve @returnType: list ''' @@ -253,18 +253,18 @@ def locatorEpCurve(curve,locatorScale=0.05,prefix=''): else: curveShape = curve curve = mc.listRelatives(curve,p=1)[0] - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # Get curve information spans = mc.getAttr(curve+'.spans') openCrv = not mc.getAttr(curve+'.form') numPt = spans + openCrv - + # Set locator scale locatorScale *= mc.arclen(curve) - + # Initialize return list locatorList=[] # Iterate over edit points @@ -288,7 +288,7 @@ def locatorEpCurve(curve,locatorScale=0.05,prefix=''): # Create point on curve deformer curveCon = mc.pointCurveConstraint(curveShape+'.u['+str(coord)+']',ch=1,rpo=1,w=1) locatorList.append(curveCon[0]) - + for i in range(len(locatorList)): # Scale and Center Locator Pivots localOffset = mc.getAttr(locatorList[i]+'.localPosition')[0] @@ -299,14 +299,14 @@ def locatorEpCurve(curve,locatorScale=0.05,prefix=''): ind = str(i+1) if i<9: ind = '0' + ind locatorList[i] = mc.rename(locatorList[i],prefix+'ep'+ind+'_locator') - + # Return locator list return locatorList def curveToLocators(curve,locatorList,controlPoints=[]): ''' Connect a list of existing locator positions to the control points of a specified curve - + @param curve: Curve to connect to locators @type curve: str @param locatorList: List of locators to connect to the curve control points @@ -320,7 +320,7 @@ def curveToLocators(curve,locatorList,controlPoints=[]): for i in range(len(locatorList)): if not mc.objExists(locatorList[i]): raise Exception('Object "'+locatorList[i]+'" does not exist!!') - + # Get Component List if controlPoints: if type(controlPoints[0]) == 'str': @@ -329,45 +329,45 @@ def curveToLocators(curve,locatorList,controlPoints=[]): else: componentIndexList = glTools.utils.component.getComponentIndexList(curve) controlPoints = componentIndexList[componentIndexList.keys()[0]] - + # Check Target Count if len(locatorList) != len(controlPoints): raise Exception('LocatorList length is not equal to the control point count!!') - + # Connect Control Points to Locators for i in range(len(controlPoints)): mc.connectAttr(locatorList[i]+'.worldPosition',curve+'.controlPoints['+str(controlPoints[i])+']',f=True) - + def closestPoint(curve,pos=(0,0,0)): ''' Return closest point on curve to target - + @param curve: Curve to query closest point from @type curve: str @param pos: Position to query curve from @type pos: tuple or list or str - + @return: The curve parameter value closest to the input point @returnType: float ''' # Check curve if not isCurve(curve): raise Exception('Object '+curve+ ' is not a valid nurbs curve!!') - + # Get Position pos = glTools.utils.base.getPosition(pos) - + # Get edit point world position pos = OpenMaya.MPoint(pos[0],pos[1],pos[2],1.0) - + # Get curve function set crvFn = getCurveFn(curve) - + # Get uCoord pointer object uCoord = OpenMaya.MScriptUtil() uCoord.createFromDouble(0.0) uCoordPtr = uCoord.asDoublePtr() - + # Get closest u coordinate to position crvFn.closestPoint(pos,uCoordPtr,0.0001,OpenMaya.MSpace.kWorld) return OpenMaya.MScriptUtil(uCoordPtr).asDouble() @@ -383,26 +383,26 @@ def getParamFromLength(curve,length): # Check curve if not isCurve(curve): raise Exception('Object "'+curve+'" is not a valid nurbs curve!') - + # Check length max_len = arclen(curve) if length > max_len: print('Input length is greater than actual curve length. Returning maximum U value!') return mc.getAttr(curve+'.maxValue') - + # Get curve function set curveFn = getCurveFn(curve) - + # Get parameter from length param = curveFn.findParamFromLength(length) - + # Return result return param def projectToSurface(curve,targetSurface,keepOriginal=False,prefix=''): ''' Project the edit points of the specified nurbs curve to aa nurbs or polygon object - + @param curve: Curve to project @type curve: str @param targetSurface: Surface to project onto @@ -411,7 +411,7 @@ def projectToSurface(curve,targetSurface,keepOriginal=False,prefix=''): @type keepOriginal: bool @param prefix: Name prefix for all created nodes @type prefix: str - + @return: The curve parameter value closest to the input point @returnType: float ''' @@ -420,19 +420,19 @@ def projectToSurface(curve,targetSurface,keepOriginal=False,prefix=''): raise Exception('Curve "'+curve+'" does not exist!!') if not isCurve(curve): raise Exception('Object "'+curve+'" is not a valid nurbs curve!!') - + # Check target surface if not mc.objExists(targetSurface): raise Exception('Target surface "'+targetSurface+'" does not exist!!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # Duplicate original curve if keepOriginal: curve = mc.duplicate(curve,rc=True,rr=True)[0] mc.delete(mc.listRelatives(curve,c=True,type=['transform'],pa=True)) - + # Create curve group grp = mc.createNode('transform',n=prefix+'_group') curve = mc.parent(curve,grp)[0] @@ -446,7 +446,7 @@ def projectToSurface(curve,targetSurface,keepOriginal=False,prefix=''): geomConstraintList.append(geomConstraint[0]) # Center group pivot mc.xform(grp,cp=True) - + # Return result return[curve,grp,curveLocList,geomConstraintList] @@ -476,10 +476,10 @@ def snapToCurve(curve,obj,uValue=0.0,useClosestPoint=False,snapPivot=False): # Verify surface parameter if uValue < minu or uValue > maxu: raise Exception('U paramater '+str(uValue)+' is not within the parameter range for '+curve+'!!') - + # Get curve point position pnt = mc.pointPosition(curve+'.u['+str(uValue)+']') - + # Snap to Curve piv = mc.xform(obj,q=True,ws=True,rp=True) if snapPivot: mc.xform(obj,piv=pnt,ws=True) @@ -519,18 +519,18 @@ def orientToCurve(curve,obj,uValue=0.0,useClosestPoint=False,upVector=(0,1,0),ta # Verify surface parameter if uValue < minu or uValue > maxu: raise Exception('U paramater '+str(uValue)+' is not within the parameter range for '+curve+'!!') - + # Check object if not mc.objExists(obj): raise Exception('Object '+obj+' does not exist!!') rotateOrder = mc.getAttr(obj+'.ro') - + # Get tangent at curve point tan = mc.pointOnCurve(curve,pr=uValue,nt=True) - + # Build rotation matrix mat = glTools.utils.matrix.buildRotation(tan,upVector,tangentAxis,upAxis) rot = glTools.utils.matrix.getRotation(mat,rotateOrder) - + # Orient object to curve mc.rotate(rot[0],rot[1],rot[2],obj,a=True,ws=True) @@ -552,7 +552,7 @@ def sampleParam(curve,samples,useDistance=False,minPercent=0.0,maxPercent=1.0,sp ''' # Check curve if not isCurve(curve): raise Exception('Object '+curve+' is not a valid curve!!') - + # Check percent if minPercent<0.0 or minPercent>1.0: raise Exception('Min percent argument is not within the valid range (0->1)!!') if maxPercent<0.0 or maxPercent>1.0: raise Exception('Max percent argument is not within the valid range (0->1)!!') @@ -561,7 +561,7 @@ def sampleParam(curve,samples,useDistance=False,minPercent=0.0,maxPercent=1.0,sp spacing = spacing, rangeStart = minPercent, rangeEnd = maxPercent ) - + # Build parameter list paramList = [] if useDistance: @@ -660,7 +660,7 @@ def edgeLoopCrv(meshEdgeList,rebuild=False,rebuildSpans=0,form=2,keepHistory=Tru curve = mc.rebuildCurve(curve,ch=keepHistory,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=rebuildSpans,d=3,tol=0.01)[0] # Rename curve curve = mc.rename(curve,prefix+'_curve') - + # Return result return curve @@ -681,16 +681,16 @@ def tubeFromCurve(curve,spans=6,radius=1,upVector=(0,1,0),prefix=''): # Check curve if not isCurve(curve): raise Exception('Object "'+curve+'" is not a valid nurbs curve!!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # Get curve info crvMin = mc.getAttr(curve+'.minValue') crvMax = mc.getAttr(curve+'.maxValue') crvSpan = mc.getAttr(curve+'.spans') crvInc = (crvMax - crvMin) / (crvSpan + 1) - + # Increment over curve edit points crvList = [] crvGrpList = [] @@ -703,13 +703,13 @@ def tubeFromCurve(curve,spans=6,radius=1,upVector=(0,1,0),prefix=''): orientToCurve(curve,crvGrp,(crvInc*i),False,upVector,'z','y') crvList.append(crvCirc[0]) crvGrpList.append(crvGrp) - + # Loft surface between curves surface = mc.loft(crvList,ch=1,u=1,c=0,ar=1,d=3,ss=1,rn=0,po=0,rsn=True,n=prefix+'_surface')[0] - + # Return result return[surface,crvList,crvGrpList] - + def buildCmd(curve,round=True): ''' Generate and return the python command to rebuild the specified curve in world space @@ -721,17 +721,17 @@ def buildCmd(curve,round=True): # Check curve if not isCurve(curve): raise Exception('Object "'+curve+'" is not a valid nurbs curve!!') - + # Initialize command cmd = 'mc.curve(' - + # Get curve function set curveFn = getCurveFn(curve) - + # Get curve degree degree = curveFn.degree() cmd += 'd='+str(degree)+',' - + # Get points points = OpenMaya.MPointArray() curveFn.getCVs(points,OpenMaya.MSpace.kWorld) @@ -741,7 +741,7 @@ def buildCmd(curve,round=True): if round: cmd += '('+('%.3f' % points[i][0])+','+('%.3f' % points[i][1])+','+('%.3f' % points[i][2])+')' else: cmd += '('+str(points[i][0])+','+str(points[i][1])+','+str(points[i][2])+')' cmd += '],' - + # Get knots knots = OpenMaya.MDoubleArray() curveFn.getKnots(knots) @@ -750,10 +750,10 @@ def buildCmd(curve,round=True): if i: cmd += ',' cmd += str(knots[i]) cmd += '],' - + # Finalize command cmd += 'n="'+str(curve)+'")' - + # Return result return cmd @@ -774,37 +774,37 @@ def mirrorCurve(srcCrv,dstCrv,axis='x',space='world'): raise Exception('Object "'+srcCrv+'" is not a valid nurbs curve!!') if not isCurve(dstCrv): raise Exception('Object "'+dstCrv+'" is not a valid nurbs curve!!') - + # Get curve funtion sets srcCrvFn = getCurveFn(srcCrv) dstCrvFn = getCurveFn(dstCrv) - + # Check curve CV counts if srcCrvFn.numCVs() != dstCrvFn.numCVs(): raise Exception('Source and destination curves are not compatible! Different CV counts.') - + # Get space if space=='world': mSpace = OpenMaya.MSpace.kWorld elif space=='object': mSpace = OpenMaya.MSpace.kObject else: raise Exception('Invalid Space "'+space+'"!') - + # Get source point array ptArray = OpenMaya.MPointArray() srcCrvFn.getCVs(ptArray,mSpace) - + # Determine mirror axis axis = axis.lower() axisDict = {'x':0,'y':1,'z':2} if not axisDict.keys().count(axis): raise Exception('Invalid axis "'+axis+'"!') axisInd = axisDict[axis] - + # Mirror Points for i in range(ptArray.length()): pt = [ptArray[i].x,ptArray[i].y,ptArray[i].z] pt[axisInd] *= -1 ptArray.set(OpenMaya.MPoint(pt[0],pt[1],pt[2],1.0),i) - + # Set mirror points dstCrvFn.setCVs(ptArray,mSpace) dstCrvFn.updateCurve() @@ -824,15 +824,15 @@ def uniformRebuild(curve,spans=6,replaceOriginal=False,prefix=None): # ========== # - Checks - # ========== - + # Check Plugin if not mc.pluginInfo('glCurveUtils',q=True,l=True): try: mc.loadPlugin('glCurveUtils') except: raise MissingPluginError('Unable to load glCurveUtils!') - + # Check Curve if not isCurve(curve): raise Exception('Object "'+curve+'" is not a valid nurbs curve!') - + # Check Curve Shape curveShape='' if mc.objectType(curve) == 'transform': @@ -840,25 +840,25 @@ def uniformRebuild(curve,spans=6,replaceOriginal=False,prefix=None): else: curveShape = curve curve = mc.listRelatives(curve,p=1)[0] - + # Check Prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # ============================== # - Create UniformRebuild Node - # ============================== - + uniformRebuildNode = mc.createNode('uniformRebuild',n=prefix+'_uniformRebuild') mc.setAttr(uniformRebuildNode+'.spans',spans) - + # Duplicate Curve rebuildCurve = mc.duplicate(curve,rr=True,rc=True,n=prefix+'_rebuild_curve')[0] rebuildCurveShape = mc.listRelatives(rebuildCurve,ni=True,s=True)[0] - + # Connect to UniformRebuild mc.connectAttr(curveShape+'.local',uniformRebuildNode+'.inputCurve',f=True) mc.connectAttr(uniformRebuildNode+'.outputCurve',rebuildCurveShape+'.create') - + # Replace original if replaceOriginal: rebuildCurveShape = mc.parent(rebuildCurveShape,curve,s=True,r=True)[0] @@ -867,11 +867,11 @@ def uniformRebuild(curve,spans=6,replaceOriginal=False,prefix=None): mc.rename(rebuildCurveShape,curveShape) mc.delete(rebuildCurve) rebuildCurve = curve - + # ================= # - Return Result - # ================= - + return [rebuildCurve,uniformRebuildNode] def moveSeam(crv,numSpansToMove): @@ -883,14 +883,14 @@ def moveSeam(crv,numSpansToMove): form = mc.getAttr(crv+'.form') spans = mc.getAttr(crv+'.spans') degree = mc.getAttr(crv+'.degree') - + # Get Number of CVs ncvs = spans # Initialize Lists cv = [0,0,0] cvs = [0 for i in range(ncvs*3)] - + # move CVs and store in array for u in range(ncvs): cv = mc.xform(crv+'.cv['+str(u)+']',q=True,ws=True,t=True) @@ -903,7 +903,7 @@ def moveSeam(crv,numSpansToMove): for u in range(ncvs): for dim in range(3): cv[dim] = cvs[3*u + dim] - + mc.xform(crv+'.cv['+str(u)+']',ws=True,t=cv) def avgCurves(crv1,crv2,wt1=1.0,wt2=1.0,prefix=None): @@ -923,15 +923,15 @@ def avgCurves(crv1,crv2,wt1=1.0,wt2=1.0,prefix=None): # Check Curves if not isCurve(crv1): raise Exception('Object "'+crv1+'" is not a valid curve!') if not isCurve(crv2): raise Exception('Object "'+crv2+'" is not a valid curve!') - + # Check Prefix if not prefix: prefix = curveList[0] - + # Create AvgCurve avgCrvShape = mc.createNode('nurbsCurve') avgCrv = mc.listRelatives(avgCrvShape,p=True)[0] avgCrv = mc.rename(avgCrv,prefix+'_crv') - + # Create AvgCurves Node avgCrvNode = mc.createNode('avgCurves',n=prefix+'_avgCurves') mc.connectAttr(crv1+'.worldSpace[0]',avgCrvNode+'.inputCurve1',f=True) @@ -939,7 +939,7 @@ def avgCurves(crv1,crv2,wt1=1.0,wt2=1.0,prefix=None): mc.setAttr(avgCrvNode+'.weight1',wt1) mc.setAttr(avgCrvNode+'.weight2',wt2) mc.connectAttr(avgCrvNode+'.outputCurve',avgCrvShape+'.create',f=True) - + # Return Result return avgCrv @@ -968,20 +968,20 @@ def rebuildCurveWithHistory( crv, ''' # Check Curve if not isCurve(crv): raise Exception('Object "'+crv+'" is not a valid curve!') - + # Get Shape crvShape = mc.ls(mc.listRelatives(crv,s=True,ni=True) or [],type='nurbsCurve') or [] if not crvShape: raise Exception('Unable to determine curve shape for "'+crv+'"!') crvShape = crvShape[0] - + # Check Inputs if spans == 0: spans = 0 if degree == None: degree = mc.getAttr(crvShape+'.degree') - + # Get Input Shape try: glTools.utils.shape.findInputShape(crvShape) except: glTools.utils.shape.createIntermediate(crvShape) - + # Rebuild Curve rebuildCrv = mc.rebuildCurve( crvShape, ch = True, @@ -994,10 +994,10 @@ def rebuildCurveWithHistory( crv, keepTangents = False, spans = spans, degree = degree ) - + # Rename Node rebuildCrv = mc.rename(rebuildCrv,crv.replace('_crv','')+'_rebuildCurve') - + # Return Result return rebuildCrv[1] @@ -1014,17 +1014,17 @@ def split(crv,param,deleteHistory=True): # Check Curve if not mc.objExists(crv): raise Exception('Curve "'+crv+'" does not exist!') - + # Split Curve detach = mc.detachCurve(crv,p=param,ch=True,replaceOriginal=True) detachCrv = mc.ls(detach,transforms=True) detachCrv.insert(0, detachCrv.pop(-1)) for i in range(len(detachCrv)): detachCrv[i] = mc.rename(detachCrv[i],crv+'_split'+str(i+1)) - + # Delete History if deleteHistory: mc.delete(detachCrv,ch=True) - + # Return Result return detachCrv @@ -1050,7 +1050,7 @@ def matchCurve(srcCrv,dstCrv): numCVs = crvFn.numCVs() CVs = OpenMaya.MPointArray() crvFn.getCVs(CVs,OpenMaya.MSpace.kWorld) - + # Build Points List pts = [] for i in range(CVs.length()): @@ -1058,7 +1058,7 @@ def matchCurve(srcCrv,dstCrv): pts.append(str(CVs[i].y)) pts.append(str(CVs[i].z)) pts.append(str(CVs[i].w)) - + # Build Curve Command cmd = 'setAttr '+dstCrv+'.create -type nurbsCurve' cmd += str(degree)+' ' @@ -1069,7 +1069,7 @@ def matchCurve(srcCrv,dstCrv): cmd += str(numKnots)+' ' cmd += ''.join(knots)+' ' cmd += str(numCVs)+' ' - + # Execute Command mm.eval(cmd) diff --git a/utils/curveConstraint.py b/utils/curveConstraint.py index c9a6dc1..c7d7e83 100644 --- a/utils/curveConstraint.py +++ b/utils/curveConstraint.py @@ -26,14 +26,14 @@ def curveConstraint(transform,curve,parameter,useClosestPoint=True,normalizePara ''' # Build axis dictionary axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(transform) - + # Parameter pos = mc.xform(transform,q=True,ws=True,rp=True) if useClosestPoint: parameter = glTools.utils.curve.closestPoint(curve,pos) - + # PointOnCurveInfo poc = prefix+'_pointOnCurveInfo' poc = mc.createNode('pointOnCurveInfo',n=poc) @@ -44,14 +44,14 @@ def curveConstraint(transform,curve,parameter,useClosestPoint=True,normalizePara maxParam = mc.getAttr(curve+'.maxValue') parameter = (parameter-minParam)/(maxParam-minParam) mc.setAttr(poc+'.parameter',parameter) - + # Point Constraint pntCon = prefix+'_pointConstraint' pntCon = mc.createNode('pointConstraint',n=pntCon) mc.connectAttr(poc+'.position',pntCon+'.target[0].targetTranslate',f=True) mc.connectAttr(transform+'.parentInverseMatrix[0]',pntCon+'.constraintParentInverseMatrix',f=True) mc.connectAttr(pntCon+'.constraintTranslate',transform+'.translate',f=True) - + # Aim Constraint aimCon = prefix+'_aimConstraint' aimCon = mc.createNode('aimConstraint',n=aimCon) @@ -70,20 +70,20 @@ def curveConstraint(transform,curve,parameter,useClosestPoint=True,normalizePara # Connect mc.connectAttr(transform+'.parentInverseMatrix[0]',aimCon+'.constraintParentInverseMatrix',f=True) mc.connectAttr(aimCon+'.constraintRotate',transform+'.rotate',f=True) - + # Parent constraints mc.parent(pntCon,transform) mc.parent(aimCon,transform) - + # Add parameter attribute if not mc.objExists(transform+'.param'): if normalizeParameter: mc.addAttr(transform,ln='param',at='float',dv=parameter,min=0.0,max=1.0,k=True) else: mc.addAttr(transform,ln='param',at='float',dv=parameter,min=minParam,max=maxParam,k=True) mc.connectAttr(transform+'.param',poc+'.parameter',f=True) - + # Return result return(poc,pntCon,aimCon) - + def curveAimConstraint(transform,curve,parameter,useClosestPoint=True,aimAxis='y',tangentAxis='x',prefix=''): ''' @param transform: Transform to aim at point on curve @@ -103,34 +103,34 @@ def curveAimConstraint(transform,curve,parameter,useClosestPoint=True,aimAxis='y ''' # Build axis dictionary axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(transform) - + # Transform worldSpace position pmm = prefix+'_pointMatrixMult' pmm = mc.createNode('pointMatrixMult',n=pmm) mc.connectAttr(transform+'.translate',pmm+'.inPoint',f=True) mc.connectAttr(transform+'.parentMatrix[0]',pmm+'.inMatrix',f=True) mc.setAttr(pmm+'.vectorMultiply',1) - + # Parameter pos = mc.xform(transform,q=True,ws=True,rp=True) if useClosestPoint: paramater = glTools.utils.curve.closestPoint(curve,pos) - + # PointOnCurveInfo poc = prefix+'_pointOnCurveInfo' poc = mc.createNode('pointOnCurveInfo',n=poc) mc.connectAttr(curve+'.worldSpace[0]',poc+'.inputCurve',f=True) mc.setAttr(poc+'.parameter',paramater) - + # Offset pma = prefix+'_plusMinusAverage' pma = mc.createNode('plusMinusAverage',n=pma) mc.connectAttr(poc+'.position',pma+'.input3D[0]',f=True) mc.connectAttr(pmm+'.output',pma+'.input3D[1]',f=True) mc.setAttr(pma+'.operation',2) # Subtract - + # Aim Constraint aimCon = prefix+'_aimConstraint' aimCon = mc.createNode('aimConstraint',n=aimCon) @@ -146,7 +146,7 @@ def curveAimConstraint(transform,curve,parameter,useClosestPoint=True,aimAxis='y mc.setAttr(aimCon+'.aimVector',aimVec[0],aimVec[1],aimVec[2]) mc.setAttr(aimCon+'.upVector',tanVec[0],tanVec[1],tanVec[2]) mc.parent(aimCon,transform) - + # Add parameter attribute minU = mc.getAttr(curve+'.minValue') maxU = mc.getAttr(curve+'.maxValue') @@ -173,17 +173,17 @@ def multiCurveAimConstraint(transform,curve1,curve2,toggleAttr,aimAxis='y',tange ''' # Build axis dictionary axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(transform) - + # Transform worldSpace position pmm = prefix+'_pointMatrixMult' pmm = mc.createNode('pointMatrixMult',n=pmm) mc.connectAttr(transform+'.translate',pmm+'.inPoint',f=True) mc.connectAttr(transform+'.parentMatrix[0]',pmm+'.inMatrix',f=True) mc.setAttr(pmm+'.vectorMultiply',1) - + # PointOnCurveInfo poc1 = prefix+'_pc01_pointOnCurveInfo' poc1 = mc.createNode('pointOnCurveInfo',n=poc1) @@ -191,41 +191,41 @@ def multiCurveAimConstraint(transform,curve1,curve2,toggleAttr,aimAxis='y',tange poc2 = prefix+'_pc02_pointOnCurveInfo' poc2 = mc.createNode('pointOnCurveInfo',n=poc2) mc.connectAttr(curve2+'.worldSpace[0]',poc2+'.inputCurve',f=True) - + pos = mc.xform(transform,q=True,ws=True,rp=True) param = glTools.utils.curve.closestPoint(curve1,pos) mc.setAttr(poc1+'.parameter',param) pos = mc.pointOnCurve(curve1,pr=param,p=True) param = glTools.utils.curve.closestPoint(curve2,pos) mc.setAttr(poc2+'.parameter',param) - + # Offset pma1 = prefix+'_pc01_plusMinusAverage' pma1 = mc.createNode('plusMinusAverage',n=pma1) mc.connectAttr(poc1+'.position',pma1+'.input3D[0]',f=True) mc.connectAttr(pmm+'.output',pma1+'.input3D[1]',f=True) mc.setAttr(pma1+'.operation',2) # Subtract - + pma2 = prefix+'_pc02_plusMinusAverage' pma2 = mc.createNode('plusMinusAverage',n=pma2) mc.connectAttr(poc2+'.position',pma2+'.input3D[0]',f=True) mc.connectAttr(pmm+'.output',pma2+'.input3D[1]',f=True) mc.setAttr(pma2+'.operation',2) # Subtract - + # Blend Offset pos_bcn = prefix+'_ps01_blendColors' pos_bcn = mc.createNode('blendColors',n=pos_bcn) mc.connectAttr(pma1+'.output3D',pos_bcn+'.color1',f=True) mc.connectAttr(pma2+'.output3D',pos_bcn+'.color2',f=True) mc.connectAttr(toggleAttr,pos_bcn+'.blender',f=True) - + # Blend Tangent tan_bcn = prefix+'_rt01_blendColors' tan_bcn = mc.createNode('blendColors',n=tan_bcn) mc.connectAttr(poc1+'.tangent',tan_bcn+'.color1',f=True) mc.connectAttr(poc2+'.tangent',tan_bcn+'.color2',f=True) mc.connectAttr(toggleAttr,tan_bcn+'.blender',f=True) - + # Aim Constraint aimCon = prefix+'_aimConstraint' aimCon = mc.createNode('aimConstraint',n=aimCon) @@ -241,7 +241,7 @@ def multiCurveAimConstraint(transform,curve1,curve2,toggleAttr,aimAxis='y',tange mc.setAttr(aimCon+'.aimVector',aimVec[0],aimVec[1],aimVec[2]) mc.setAttr(aimCon+'.upVector',tanVec[0],tanVec[1],tanVec[2]) mc.parent(aimCon,transform) - + # Add parameter attribute minU = mc.getAttr(curve1+'.minValue') maxU = mc.getAttr(curve1+'.maxValue') @@ -249,13 +249,13 @@ def multiCurveAimConstraint(transform,curve1,curve2,toggleAttr,aimAxis='y',tange mc.addAttr(transform,ln='param1',at='float',min=minU,max=maxU,k=True) mc.setAttr(transform+'.param1',mc.getAttr(poc1+'.parameter')) mc.connectAttr(transform+'.param1',poc1+'.parameter',f=True) - + minU = mc.getAttr(curve2+'.minValue') maxU = mc.getAttr(curve2+'.maxValue') if not mc.objExists(transform+'.param2'): mc.addAttr(transform,ln='param2',at='float',min=minU,max=maxU,k=True) mc.setAttr(transform+'.param2',mc.getAttr(poc2+'.parameter')) mc.connectAttr(transform+'.param2',poc2+'.parameter',f=True) - + # Return result return (aimCon,poc1,poc2) diff --git a/utils/defaultAttrState.py b/utils/defaultAttrState.py index 08f97c1..713d175 100644 --- a/utils/defaultAttrState.py +++ b/utils/defaultAttrState.py @@ -10,29 +10,29 @@ def addDefaultAttrState(objList): ''' # Check objList if not objList: return - + # Define defaultAttrState attribute name defAttr = 'defaultAttrState' - + # For each object in list attrList = [] for obj in objList: - + # Check Object if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check Attr if not mc.attributeQuery(defAttr,n=obj,ex=True): - + # Add attribute mc.addAttr(obj,ln=defAttr,dv=-1,m=True) attrList.append(obj+'.'+defAttr) - + else: - + print ('Object "'+obj+'" already has a "'+defAttr+'" attribute! Skipping...') - + # Return Result return attrList @@ -52,35 +52,35 @@ def setDefaultAttrState(objList,attrList,valueList=[]): if len(attrList) != len(valueList): print ('Attribute and value list mis-match! Recording existing attribute values.') valueList = [] - + # Define defaultAttrState attribute name defAttr = 'defaultAttrState' aliasSuffix = 'defaultState' - + # For each object in list for obj in objList: - + # Check Object if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') if not mc.attributeQuery(defAttr,n=obj,ex=True): addDefaultAttrState([obj]) - + # For each attribute in list for i in range(len(attrList)): - + # Get current attribute attr = attrList[i] attrAlias = attr+'_'+aliasSuffix - + # Check attribute if not mc.attributeQuery(attr,n=obj,ex=True): raise Exception('Object "'+obj+'" has no attribute "'+attr+'"!') - + # Get attribute value if valueList: value = valueList[i] else: value = mc.getAttr(obj+'.'+attr) - + # Add default attribute state if not mc.attributeQuery(attrAlias,n=obj,ex=True): try: index = mc.getAttr(obj+'.'+defAttr,s=True) @@ -88,7 +88,7 @@ def setDefaultAttrState(objList,attrList,valueList=[]): mc.setAttr(obj+'.'+defAttr+'['+str(index)+']',0) try: mc.aliasAttr(attrAlias,obj+'.'+defAttr+'['+str(index)+']') except: print('Error setting attribute alias ("'+attrAlias+'") for node attr "'+obj+'.'+defAttr+'['+str(index)+']"') - + # Set default attribute state try: mc.setAttr(obj+'.'+attrAlias,value) except: print('Unable to set default attr state ("'+attrAlias+'") for object "'+obj+'" to value ('+str(value)+')!') @@ -104,19 +104,19 @@ def setToDefaultState(objList=[],attrList=[]): # Define defaultAttrState attribute name defAttr = 'defaultAttrState' aliasSuffix = 'defaultState' - + # Check object list if not objList: objList = mc.ls('*.'+defAttr,o=True) if not objList: return - + # For each object in list for obj in objList: - + if not mc.attributeQuery(defAttr,n=obj,ex=True): raise Exception('Object "'+obj+'" has no attribute "'+defAttr+'"!') - + # Get attribute list attrAliasList = [] if not attrList: @@ -124,34 +124,34 @@ def setToDefaultState(objList=[],attrList=[]): attrList = [attrAlias.replace('_'+aliasSuffix,'') for attrAlias in attrAliasList] if not attrList: raise Exception('No valid attribute list supplied!') - + # For each attribute for attr in attrList: - + # Check attribute if not mc.attributeQuery(attr,n=obj,ex=True): raise Exception('Object "'+obj+'" has no attribute "'+attr+'"!') - + # Get associated attribute alias attrAlias = attr+'_'+aliasSuffix if not mc.attributeQuery(attrAlias,n=obj,ex=True): raise Exception('Object "'+obj+'" has no aliased attribute "'+attrAlias+'"!') - - # Get default attribute state value + + # Get default attribute state value attrVal = mc.getAttr(obj+'.'+attrAlias) - + # Check attribute locked state isLocked = mc.getAttr(obj+'.'+attr,l=True) if isLocked: try: mc.setAttr(obj+'.'+attr,l=False) except: raise Exception('Unable to unlock attribute "'+obj+'.'+attr+'"!') - + # Check attribute connected state isConnected = bool(mc.listConnections(obj+'.'+attr,s=True,d=False)) - + # Set to recorded default attribute state if not isConnected: mc.setAttr(obj+'.'+attr,attrVal) - + # Restore Lock state if isLocked: mc.setAttr(obj+'.'+attr,l=True) @@ -166,21 +166,21 @@ def setAttrValue(attr,value): # Check attribute if not mc.objExists(attr): raise Exception('Attribute "'+attr+'" does not exist!') - + # Check attribute locked state isLocked = mc.getAttr(attr,l=True) if isLocked: try: mc.setAttr(attr,l=False) except: raise Exception('Unable to unlock attribute "'+attr+'"!') - + # Check attribute connected state isConnected = bool(mc.listConnections(attr,s=True,d=False)) - + # Set to recorded default attribute state if not isConnected: try: mc.setAttr(attr,value) except: raise Exception('Unable to set attribute "'+attr+'" using value ('+str(value)+')!') - + # Restore Lock state if isLocked: mc.setAttr(attr,l=True) @@ -196,14 +196,14 @@ def recordVisibility(objList=[]): if not objList: print('No valid object list supplied for visibility state! Skipping...') return - + # For each object in list recordObjList = [] for obj in objList: - + # Skip Referenced Nodes if glTools.utils.reference.isReferenced(obj): continue - + # Get visibility value vis = mc.getAttr(obj+'.visibility') if not vis: @@ -211,7 +211,7 @@ def recordVisibility(objList=[]): setDefaultAttrState([obj],['visibility'],[vis]) # Append Record Object List recordObjList.append(obj) - + # Return Result print('Visibility attribute state recorded for - '+str(recordObjList)) @@ -220,37 +220,37 @@ def setVisibilityState(objList=[],visibilityState=1): Set the visibility state values for a specified list of objects. @param objList: List of objects to record visibility default attribute state values for. If empty, use all objects with stored visibility state values. @type objList: list - @param visibilityState: Visibilty state value to apply to object list. + @param visibilityState: Visibilty state value to apply to object list. @type visibilityState: int or bool ''' # Define attribute names attr = 'visibility' defAttr = 'defaultAttrState' aliasSuffix = 'defaultState' - + # Check Object List if not objList: objList = mc.ls('*.'+attr+'_'+aliasSuffix,o=True,r=True) if not objList: print('No valid object list supplied for visibility state! Skipping...') return - + # For each object in list for obj in objList: - + # Check defaultAttrState atribute if not mc.attributeQuery(defAttr,n=obj,ex=True): raise Exception('Object "'+obj+'" has no "'+defAttr+'" attribute!') - + # Get visibility attribute alias attrAlias = attr+'_'+aliasSuffix if not mc.attributeQuery(attrAlias,n=obj,ex=True): raise Exception('Object "'+obj+'" has no aliased attribute "'+attrAlias+'"!') - + # Get visibility value if visibilityState: value = mc.getAttr(obj+'.'+attrAlias) else: value = 1 - + # Set visibilty state value setAttrValue(obj+'.'+attr,value) @@ -266,7 +266,7 @@ def recordDisplayOverrides(objList=[]): if not objList: print('No valid object list supplied for display overrides state! Skipping...') return - + # Define display override attribute list attrList = [ 'overrideEnabled', 'overrideDisplayType', @@ -274,31 +274,31 @@ def recordDisplayOverrides(objList=[]): 'overrideShading', 'overrideVisibility', 'overrideColor' ] - + # For each object in list recordObjList = [] for obj in objList: - + # Skip Referenced Nodes if glTools.utils.reference.isReferenced(obj): continue - + # Check Override Enabled if mc.getAttr(obj+'.overrideEnabled'): - + # Get Display Override Value List valList = [] for attr in attrList: - + # Get Display Override Value val = mc.getAttr(obj+'.'+attr) valList.append(val) - + # Record Display Override State Values setDefaultAttrState([obj],attrList,valList) - + # Append Record Object List recordObjList.append(obj) - + # Return Result print('Display override attribute states recorded for - '+str(recordObjList)) @@ -307,35 +307,35 @@ def setDisplayOverridesState(objList=[],displayOverrideState=0): Set the display override state values for a specified list of objects. @param objList: List of objects to record display override default attribute state values for. If empty, use all objects with stored visibility state values. @type objList: list - @param displayOverrideState: Display override state value to apply to object list. + @param displayOverrideState: Display override state value to apply to object list. @type displayOverrideState: int or bool ''' # Define attribute names defAttr = 'defaultAttrState' aliasSuffix = 'defaultState' overrideAttr = 'overrideEnabled' - + overrideAttrList = [ 'overrideEnabled', 'overrideDisplayType', 'overrideLevelOfDetail', 'overrideShading', 'overrideVisibility', 'overrideColor' ] - + # Check Object List if not objList: objList = mc.ls('*.'+overrideAttr+'_'+aliasSuffix,o=True,r=True) if not objList: print('No valid object list supplied for display overrides state! Skipping...') return - + # For each object in list for obj in objList: - + # Check defaultAttrState atribute if not mc.attributeQuery(defAttr,n=obj,ex=True): raise Exception('Object "'+obj+'" has no "'+defAttr+'" attribute!') - + # Override Enabled attr = 'overrideEnabled' attrAlias = attr+'_'+aliasSuffix @@ -343,7 +343,7 @@ def setDisplayOverridesState(objList=[],displayOverrideState=0): raise Exception('Object "'+obj+'" has no aliased attribute "'+attrAlias+'"!') attrValue = mc.getAttr(obj+'.'+attrAlias) setAttrValue(obj+'.'+attr,attrValue) - + # Override Display Type attr = 'overrideDisplayType' attrAlias = attr+'_'+aliasSuffix @@ -354,7 +354,7 @@ def setDisplayOverridesState(objList=[],displayOverrideState=0): else: attrValue = 0 setAttrValue(obj+'.'+attr,attrValue) - + # Override Display Type attr = 'overrideLevelOfDetail' attrAlias = attr+'_'+aliasSuffix @@ -365,7 +365,7 @@ def setDisplayOverridesState(objList=[],displayOverrideState=0): else: attrValue = 0 setAttrValue(obj+'.'+attr,attrValue) - + # Override Shading attr = 'overrideShading' attrAlias = attr+'_'+aliasSuffix @@ -376,7 +376,7 @@ def setDisplayOverridesState(objList=[],displayOverrideState=0): else: attrValue = 1 setAttrValue(obj+'.'+attr,attrValue) - + # Override Visibility attr = 'overrideVisibility' attrAlias = attr+'_'+aliasSuffix @@ -387,7 +387,7 @@ def setDisplayOverridesState(objList=[],displayOverrideState=0): else: attrValue = 1 setAttrValue(obj+'.'+attr,attrValue) - + # Override Colour attr = 'overrideColor' attrAlias = attr+'_'+aliasSuffix @@ -395,5 +395,5 @@ def setDisplayOverridesState(objList=[],displayOverrideState=0): raise Exception('Object "'+obj+'" has no aliased attribute "'+attrAlias+'"!') attrValue = mc.getAttr(obj+'.'+attrAlias) setAttrValue(obj+'.'+attr,attrValue) - + diff --git a/utils/deformer.py b/utils/deformer.py index f90cbc3..03ac7e0 100644 --- a/utils/deformer.py +++ b/utils/deformer.py @@ -18,11 +18,11 @@ def isDeformer(deformer): ''' # Check Deformer Exists if not mc.objExists(deformer): return False - + # Check Deformer Type nodeType = mc.nodeType(deformer,i=1) if not nodeType.count('geometryFilter'): return False - + # Return result return True @@ -39,43 +39,43 @@ def getDeformerList(nodeType='geometryFilter',affectedGeometry=[],regexFilter='' ''' # Get Deformer List deformerNodes = mc.ls(type=nodeType) - + # =============================== # - Filter by Affected Geometry - # =============================== - + if affectedGeometry: if type(affectedGeometry) == str: affectedGeometry = [affectedGeometry] historyNodes = mc.listHistory(affectedGeometry,groupLevels=True,pruneDagObjects=True) deformerNodes = mc.ls(historyNodes,type=nodeType) - + # ========================= # - Remove Unwanted Nodes - # ========================= - + # Remove Duplicates deformerNodes = glTools.utils.arrayUtils.removeDuplicates(deformerNodes) - + # Remove Tweak Nodes tweakNodes = mc.ls(deformerNodes,type='tweak') if tweakNodes: deformerNodes = [x for x in deformerNodes if not x in tweakNodes] - + # Remove TransferAttributes Nodes transferAttrNodes = mc.ls(deformerNodes,type='transferAttributes') if transferAttrNodes: deformerNodes = [x for x in deformerNodes if not x in transferAttrNodes] - + # ================== # - Filter Results - # ================== - + if regexFilter: reFilter = re.compile(regexFilter) - deformerNodes = filter(reFilter.search, deformerNodes) - - # ================= + deformerNodes = filter(reFilter.search, deformerNodes) + + # ================= # - Return Result - # ================= - + return deformerNodes def getDeformerFn(deformer): @@ -87,14 +87,14 @@ def getDeformerFn(deformer): # Checks if not mc.objExists(deformer): raise Exception('Deformer '+deformer+' does not exist!') - + # Get MFnWeightGeometryFilter deformerObj = glTools.utils.base.getMObject(deformer) try: deformerFn = OpenMayaAnim.MFnWeightGeometryFilter(deformerObj) except: # is there a good exception type for this? raise Exception('Could not get a geometry filter for deformer "'+deformer+'"!') - + # Return result return deformerFn @@ -109,14 +109,14 @@ def getDeformerSet(deformer): raise Exception('Deformer '+deformer+' does not exist!') if not isDeformer(deformer): raise Exception('Object '+deformer+' is not a valid deformer!') - + # Get Deformer Set deformerObj = glTools.utils.base.getMObject(deformer) deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) deformerSetObj = deformerFn.deformerSet() if deformerSetObj.isNull(): raise Exception('Unable to determine deformer set for "'+deformer+'"!') - + # Return Result return OpenMaya.MFnDependencyNode(deformerSetObj).name() @@ -129,14 +129,14 @@ def getDeformerSetFn(deformer): # Checks if not mc.objExists(deformer): raise Exception('Deformer '+deformer+' does not exist!') - + # Get deformer set deformerSet = getDeformerSet(deformer) - + # Get MFnWeightGeometryFilter deformerSetObj = glTools.utils.base.getMObject(deformerSet) deformerSetFn = OpenMaya.MFnSet(deformerSetObj) - + # Return result return deformerSetFn @@ -154,29 +154,29 @@ def getDeformerSetMembers(deformer,geometry=''): ''' # Get MFnSet deformerSetFn = getDeformerSetFn(deformer) - + # Get deformer set members deformerSetSel = OpenMaya.MSelectionList() deformerSetFn.getMembers(deformerSetSel,1) deformerSetPath = OpenMaya.MDagPath() deformerSetComp = OpenMaya.MObject() - + # Get geometry index if geometry: # Initialize setSelIndex boolean setSelIndexFound = False - + # Check geometry geo = geometry if mc.objectType(geometry) == 'transform': try: geometry = mc.listRelatives(geometry,s=True,ni=True,pa=True)[0] except: raise Exception('Object "'+geo+'" is not a valid geometry!') geomPath = glTools.utils.base.getMDagPath(geometry) - + # Check geometry affected by deformer if not (geometry in getAffectedGeometry(deformer,returnShapes=True).keys()): raise Exception('Geometry "'+geometry+'" is not a affected by deformer "'+deformer+'"!') - + # Cycle through selection set members for i in range(deformerSetSel.length()): # Get deformer set members @@ -184,14 +184,14 @@ def getDeformerSetMembers(deformer,geometry=''): if geomPath == deformerSetPath: setSelIndexFound = True break - + # Check setSelIndex found if not setSelIndexFound: raise Exception('No valid geometryIndex found for "'+geometry+'" in deformer set for "'+deformer+'"!') else: # Get deformer set members deformerSetSel.getDagPath(0,deformerSetPath,deformerSetComp) - + # Return result return [deformerSetPath,deformerSetComp] @@ -210,25 +210,25 @@ def getDeformerSetMembers(deformer,geometry=''): ''' # Get deformer function sets deformerSetFn = getDeformerSetFn(deformer) - + # Get deformer set members deformerSetSel = OpenMaya.MSelectionList() deformerSetFn.getMembers(deformerSetSel,True) deformerSetPath = OpenMaya.MDagPath() deformerSetComp = OpenMaya.MObject() - + # Get geometry index if geometry: geomIndex = getGeomIndex(geometry,deformer) else: geomIndex = 0 - + # Get number of selection components deformerSetLen = deformerSetSel.length() if geomIndex >= deformerSetLen: raise Exception('Geometry index out of range! (Deformer: "'+deformer+'", Geometry: "'+geometry+'", GeoIndex: '+str(geomIndex)+', MaxIndex: '+str(deformerSetLen)+')') - + # Get deformer set members deformerSetSel.getDagPath(geomIndex,deformerSetPath,deformerSetComp) - + # Return result return [deformerSetPath,deformerSetComp] #""" @@ -245,16 +245,16 @@ def getDeformerSetMemberStrList(deformer,geometry=''): ''' # Get deformer function sets deformerSetFn = getDeformerSetFn(deformer) - + # Get deformer set members deformerSetSel = OpenMaya.MSelectionList() deformerSetFn.getMembers(deformerSetSel,True) - + # Convert to list of strings setMemberStr = [] deformerSetSel.getSelectionStrings(setMemberStr) setMemberStr = mc.ls(setMemberStr,fl=True) - + # Return Result return setMemberStr @@ -273,22 +273,22 @@ def getDeformerSetMemberIndices(deformer,geometry=''): except: raise Exception('Object "'+geo+'" is not a valid geometry!') # Get geometry type geometryType = mc.objectType(geometry) - + # Get deformer set members deformerSetMem = getDeformerSetMembers(deformer,geometry) - + # ========================== # - Get Set Member Indices - # ========================== memberIdList = [] - + # Single Index if geometryType == 'mesh' or geometryType == 'nurbsCurve' or geometryType == 'particle': memberIndices = OpenMaya.MIntArray() singleIndexCompFn = OpenMaya.MFnSingleIndexedComponent(deformerSetMem[1]) singleIndexCompFn.getElements(memberIndices) memberIdList = list(memberIndices) - + # Double Index if geometryType == 'nurbsSurface': memberIndicesU = OpenMaya.MIntArray() @@ -297,7 +297,7 @@ def getDeformerSetMemberIndices(deformer,geometry=''): doubleIndexCompFn.getElements(memberIndicesU,memberIndicesV) for i in range(memberIndicesU.length()): memberIdList.append([memberIndicesU[i],memberIndicesV[i]]) - + # Triple Index if geometryType == 'lattice': memberIndicesS = OpenMaya.MIntArray() @@ -307,7 +307,7 @@ def getDeformerSetMemberIndices(deformer,geometry=''): tripleIndexCompFn.getElements(memberIndicesS,memberIndicesT,memberIndicesU) for i in range(memberIndicesS.length()): memberIdList.append([memberIndicesS[i],memberIndicesT[i],memberIndicesU[i]]) - + # Return result return memberIdList @@ -326,32 +326,32 @@ def getAffectedGeometry(deformer,returnShapes=False,fullPathNames=False): # Verify Input if not isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # Initialize Return Array (dict) affectedObjects = {} - + # Get MFnGeometryFilter deformerObj = glTools.utils.base.getMObject(deformer) geoFilterFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) - + # Get Output Geometry outputObjectArray = OpenMaya.MObjectArray() geoFilterFn.getOutputGeometry(outputObjectArray) - + # Iterate Over Affected Geometry for i in range(outputObjectArray.length()): - + # Get Output Connection at Index outputIndex = geoFilterFn.indexForOutputShape(outputObjectArray[i]) outputNode = OpenMaya.MFnDagNode(outputObjectArray[i]) - + # Check Return Shapes if not returnShapes: outputNode = OpenMaya.MFnDagNode(outputNode.parent(0)) - + # Check Full Path if fullPathNames: affectedObjects[outputNode.fullPathName()] = outputIndex else: affectedObjects[outputNode.partialPathName()] = outputIndex - + # Return Result return affectedObjects @@ -366,20 +366,20 @@ def getGeomIndex(geometry,deformer): # Verify input if not isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # Check geometry geo = geometry if mc.objectType(geometry) == 'transform': try: geometry = mc.listRelatives(geometry,s=True,ni=True,pa=True)[0] except: raise Exception('Object "'+geo+'" is not a valid geometry!') geomObj = glTools.utils.base.getMObject(geometry) - + # Get geometry index deformerObj = glTools.utils.base.getMObject(deformer) deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) try: geomIndex = deformerFn.indexForOutputShape(geomObj) except: raise Exception('Object "'+geometry+'" is not affected by deformer "'+deformer+'"!') - + # Retrun result return geomIndex @@ -393,16 +393,16 @@ def findInputShape(shape): # Checks if not mc.objExists(shape): raise Exception('Shape node "'+shape+'" does not exist!') - + # Get inMesh connection inMeshConn = mc.listConnections(shape+'.inMesh',source=True,destination=False,shapes=True) if not inMeshConn: return shape - + # Check direct mesh (outMesh -> inMesh) connection if str(mc.objectType(inMeshConn[0])) == 'mesh': return inMeshConn[0] - + # Find connected deformer deformerObj = glTools.utils.base.getMObject(inMeshConn[0]) if not deformerObj.hasFn(OpenMaya.MFn.kGeometryFilt): @@ -413,15 +413,15 @@ def findInputShape(shape): #raise Exception('Shape node "'+shape+'" is not affected by any valid deformers!') else: deformerObj = glTools.utils.base.getMObject(deformerHist[0]) - + # Get deformer function set deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) - + # Get input shape for deformer shapeObj = glTools.utils.base.getMObject(shape) geomIndex = deformerFn.indexForOutputShape(shapeObj) inputShapeObj = deformerFn.inputShapeAtIndex(geomIndex) - + # Return result return OpenMaya.MFnDependencyNode(inputShapeObj).name() @@ -436,14 +436,14 @@ def renameDeformerSet(deformer,deformerSetName=''): # Verify input if not isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # Check deformer set name if not deformerSetName: deformerSetName = deformer+'Set' - + # Rename deformer set deformerSet = mc.listConnections(deformer+'.message',type='objectSet')[0] if deformerSet != deformerSetName: deformerSetName = mc.rename(deformerSet,deformerSetName) - + # Retrun result return deformerSetName @@ -458,24 +458,24 @@ def getWeights(deformer,geometry=None): # Check Deformer if not isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # Check Geometry if not geometry: geometry = getAffectedGeometry(deformer).keys()[0] - + # Get Geometry Shape geoShape = geometry if geometry and mc.objectType(geoShape) == 'transform': geoShape = mc.listRelatives(geometry,s=True,ni=True)[0] - + # Get deformer function set and members deformerFn = getDeformerFn(deformer) deformerSetMem = getDeformerSetMembers(deformer,geoShape) - + # Get weights weightList = OpenMaya.MFloatArray() deformerFn.getWeights(deformerSetMem[0],deformerSetMem[1],weightList) - + # Return result return list(weightList) """ @@ -491,7 +491,7 @@ def getWeights(deformer,geometry='',components=[]): geoShape = geometry if geometry and mc.objectType(geoShape) == 'transform': geoShape = mc.listRelatives(geometry,s=True,ni=True)[0] - + # Get deformer function set and members deformerFn = getDeformerFn(deformer) deformerSetMem = [] @@ -499,11 +499,11 @@ def getWeights(deformer,geometry='',components=[]): deformerSetMem = glTools.utils.selection.getSelectionElement(components) else: deformerSetMem = getDeformerSetMembers(deformer,geoShape) - + # Get weights weightList = OpenMaya.MFloatArray() deformerFn.getWeights(deformerSetMem[0],deformerSetMem[1],weightList) - + # Return result return list(weightList) """ @@ -520,25 +520,25 @@ def setWeights(deformer,weights,geometry=None): # Check Deformer if not isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # Check Geometry if not geometry: geometry = getAffectedGeometry(deformer).keys()[0] - + # Get Geometry Shape geoShape = geometry geoObj = glTools.utils.base.getMObject(geometry) if geometry and geoObj.hasFn(OpenMaya.MFn.kTransform): geoShape = mc.listRelatives(geometry,s=True,ni=True)[0] - + # Get deformer function set and members deformerFn = getDeformerFn(deformer) deformerSetMem = getDeformerSetMembers(deformer,geoShape) - + # Build weight array weightList = OpenMaya.MFloatArray() [weightList.append(i) for i in weights] - + # Set weights deformerFn.setWeight(deformerSetMem[0],deformerSetMem[1],weightList) @@ -557,12 +557,12 @@ def bindPreMatrix(deformer,bindPreMatrix='',parent=True): raise Exception('Object "'+deformer+'" is not a valid deformer!') if not mc.objExists(deformer+'.bindPreMatrix'): raise Exception('Deformer "'+deformer+'" does not accept bindPreMatrix connections!') - + # Get deformer handle deformerHandle = mc.listConnections(deformer+'.matrix',s=True,d=False) if deformerHandle: deformerHandle = deformerHandle[0] else: raise Exception('Unable to find deformer handle!') - + # Check bindPreMatrix if bindPreMatrix: if not mc.objExists(bindPreMatrix): @@ -571,17 +571,17 @@ def bindPreMatrix(deformer,bindPreMatrix='',parent=True): # Build bindPreMatrix transform prefix = deformerHandle.replace(deformerHandle.split('_')[-1],'') bindPreMatrix = mc.createNode('transform',n=prefix+'bindPreMatrix') - + # Match transform and pivot mc.xform(bindPreMatrix,ws=True,matrix=mc.xform(deformerHandle,q=True,ws=True,matrix=True)) mc.xform(bindPreMatrix,ws=True,piv=mc.xform(deformerHandle,q=True,ws=True,rp=True)) - + # Connect inverse matrix to localize cluster mc.connectAttr(bindPreMatrix+'.worldInverseMatrix[0]',deformer+'.bindPreMatrix',f=True) - + # Parent if parent: mc.parent(deformerHandle,bindPreMatrix) - + # Return result return bindPreMatrix @@ -598,7 +598,7 @@ def pruneWeights(deformer,geoList=[],threshold=0.001): # Check deformer if not mc.objExists(deformer): raise Exception('Deformer "'+deformer+'" does not exist!') - + # Check geometry if type(geoList) == str: geoList = [geoList] if not geoList: geoList = mc.deformer(deformer,q=True,g=True) @@ -606,19 +606,19 @@ def pruneWeights(deformer,geoList=[],threshold=0.001): for geo in geoList: if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') - + # For each geometry for geo in geoList: - + # Get deformer member indices memberIndexList = getDeformerSetMemberIndices(deformer,geo) - + # Get weight list weightList = getWeights(deformer,geo) - + # Prune weights pWeightList = [wt if wt > threshold else 0.0 for wt in weightList] - + # Apply pruned weight list setWeights(deformer,pWeightList,geo) @@ -635,7 +635,7 @@ def pruneMembershipByWeights(deformer,geoList=[],threshold=0.001): # Check deformer if not mc.objExists(deformer): raise Exception('Deformer "'+deformer+'" does not exist!') - + # Check geometry if type(geoList) == str: geoList = [geoList] if not geoList: geoList = mc.deformer(deformer,q=True,g=True) @@ -643,23 +643,23 @@ def pruneMembershipByWeights(deformer,geoList=[],threshold=0.001): for geo in geoList: if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') - + # Get deformer set deformerSet = getDeformerSet(deformer) - + # For each geometry allPruneList = [] for geo in geoList: - + # Get Component Type geoType = glTools.utils.geometry.componentType(geo) - + # Get Deformer Member Indices memberIndexList = getDeformerSetMemberIndices(deformer,geo) - + # Get Weights weightList = getWeights(deformer,geo) - + # Get Prune List pruneList = [memberIndexList[i] for i in range(len(memberIndexList)) if weightList[i] <= threshold] for i in range(len(pruneList)): @@ -670,10 +670,10 @@ def pruneMembershipByWeights(deformer,geoList=[],threshold=0.001): pruneList[i] = '['+']['.join(pruneList[i])+']' pruneList[i] = geo+'.'+geoType+str(pruneList[i]) allPruneList.extend(pruneList) - + # Prune deformer set membership if pruneList: mc.sets(pruneList,rm=deformerSet) - + # Return prune list return allPruneList @@ -681,18 +681,18 @@ def clean(deformer,threshold=0.001): ''' Clean specified deformer. Prune weights under the given tolerance and prune membership. - @param deformer: The deformer to clean. + @param deformer: The deformer to clean. @type deformer: str @param threshold: Weight value tolerance for prune operations. @type threshold: float ''' # Print Message print('Cleaning deformer: '+deformer+'!') - + # Check Deformer if not isDeformer(deformer): raise Exception('Object "'+deformer+'" is not a valid deformer!') - + # Prune Weights glTools.utils.deformer.pruneWeights(deformer,threshold=threshold) # Prune Membership @@ -709,21 +709,21 @@ def checkMultipleOutputs(deformer,printResult=True): # Check deformer if not isDeformer(deformer): raise Exception('Deformer "'+deformer+'" is not a valid deformer!') - + # Get outputGeometry plug outGeomPlug = glTools.utils.attribute.getAttrMPlug(deformer+'.outputGeometry') if not outGeomPlug.isArray(): raise Exception('Attribute "'+deformer+'.outputGeometry" is not an array attribute!') - + # Get existing indices indexList = OpenMaya.MIntArray() numIndex = outGeomPlug.getExistingArrayAttributeIndices(indexList) - + # Check output plugs returnDict = {} for i in range(numIndex): plugConn = mc.listConnections(deformer+'.outputGeometry['+str(indexList[i])+']',s=False,d=True,p=True) - + # Check multiple outputs if len(plugConn) > 1: # Append to return value @@ -732,7 +732,7 @@ def checkMultipleOutputs(deformer,printResult=True): if printResult: print('Deformer output "'+deformer+'.outputGeometry['+str(indexList[i])+']" has '+str(len(plugConn))+' outgoing connections:') for conn in plugConn: print('\t- '+conn) - + # Return result return returnDict - + diff --git a/utils/deformerCache.py b/utils/deformerCache.py index ae45fb8..995b940 100644 --- a/utils/deformerCache.py +++ b/utils/deformerCache.py @@ -12,25 +12,25 @@ def create(input,refTargetList=[],prefix=''): ''' # Check plugin loadPlugin() - + # Check prefix if not prefix: prefix = mc.ls(input,o=True)[0] - + # Create deformerCache node deformerCache = mc.createNode('deformerCache',n=prefix+'_deformerCache') - + # Connect Input mc.connectAttr(input,deformerCache+'.inGeom',f=True) - + # Find input destinations destPlugs = mc.listConnections(input,s=False,d=True,p=True) for destPlug in destPlugs: mc.connectAttr(deformerCache+'.outGeom',destPlug,f=True) - + # Connect reference targets for refTarget in refTargetList: mc.connectAttr(deformerCache+'.refOutGeom',refTarget,f=True) - + # Return result return deformerCache diff --git a/utils/dynWeights.py b/utils/dynWeights.py index dbe0768..cd3d13a 100644 --- a/utils/dynWeights.py +++ b/utils/dynWeights.py @@ -16,18 +16,18 @@ def addPaintAttr(mesh,attr='vertexMap',attrType='doubleArray'): # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Mesh "'+mesh+'" does not exist!!') - + # Check attr if mc.objExists(mesh+'.'+attr): raise Exception('Attribute "'+mesh+'.'+attr+'" already exists!!') - + # Get shape meshShape = mc.listRelatives(mesh,s=True,ni=True,pa=True) if not meshShape: raise Exception('Unable to determine shape for mesh "'+mesh+'"!!') - + # Add attribute mc.addAttr(meshShape[0],ln=attr,dt=attrType) - + # Make paintable mc.makePaintable('mesh',attr,attrType=attrType) @@ -42,21 +42,21 @@ def setPaintAttr(paintAttr,attrValue): # Check paint attr if not mc.objExists(paintAttr): raise Exception('Attribute "'+paintAttr+'" does not exist!!') - + # Check multi paintNode = '.'.join(paintAttr.split('.')[:-1]) paintAttr = paintAttr.split('.')[-1] paintMulti = mc.attributeQuery(paintAttr,node=paintNode,multi=True) - + # Set paint attribute value if paintMulti: - + # Set multi attribute values for i in range(len(attrValue)): mc.setAttr(paintNode+'.'+paintAttr+'['+str(i)+']',attrValue[i]) - + else: - + # Set array attribute values mc.setAttr(paintNode+'.'+paintAttr,attrValue,type='doubleArray') @@ -75,17 +75,17 @@ def copyPaintAttr(mesh,attr,sourceAttr,attrType='doubleArray'): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Mesh "'+mesh+'" does not exist!!') - + # Check Mesh Attribute if not mc.objExists(mesh+'.'+attr): addPaintAttr(mesh,attr,attrType) - + # Copy Attribute Values vtxCount = mc.polyEvaluate(mesh,v=True) attrVal = [] for i in range(vtxCount): val = mc.getAttr(sourceAttr+'['+str(i)+']') attrVal.append(val) - + # Set Attribute Value mc.setAttr(mesh+'.'+attr,attrVal,type=attrType) @@ -102,32 +102,32 @@ def connectVertexColour(mesh,colourData,prefix=''): # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Mesh "'+mesh+'" does not exist!!') - + # Check colourData if not mc.objExists(colourData): raise Exception('Colour data attribute "'+colourData+'" does not exist!!') - + # Get mesh shape shape = glTools.utils.shape.getShapes(mesh,True,False)[0] - + # Check inMesh connection inMeshConn = mc.listConnections(shape+'.inMesh',p=True) if not inMeshConn: inputConn = glTools.utils.shape.createIntermediate(shape)+'.outMesh' else: inputConn = inMeshConn[0] - + # Check prefix if not prefix: prefix = mesh - + # Create vertexColourArray node vtxColourNode = mc.createNode('vertexColourArray',n=prefix+'_vertexColourArray') - + # Connect nodes mc.connectAttr(inputConn,vtxColourNode+'.inMesh',f=True) mc.connectAttr(colourData,vtxColourNode+'.inputArray',f=True) mc.connectAttr(vtxColourNode+'.outMesh',shape+'.inMesh',f=True) - + # Return result return vtxColourNode @@ -143,14 +143,14 @@ def arrayToMulti(arrayAttr,prefix=''): # Check array attribute if not mc.objExists(arrayAttr): raise Exception('Array attribute "'+arrayAttr+'" does not exist!!') - + # Check prefix if not prefix: prefix = mc.ls(arrayAttr,o=True)[0] - + # Create node arrayToMultiNode = mc.createNode('arrayToMulti',n=prefix+'_arrayToMulti') mc.connectAttr(arrayAttr,arrayToMultiNode+'.inputArray',f=True) - + # Return result return arrayToMultiNode @@ -164,19 +164,19 @@ def combineArray(arrayList,method,prefix): for array in arrayList: if not mc.objExists(array): raise Exception('Array attribute "'+array+'" does not exist!') - + # Check Method methodDict = {'sum':0,'subtract':1,'multiply':2,'divide':3,'average':4,'min':5,'max':6} if not methodDict.has_key(method): raise Exception('Invalid method - "'+method+'"!') methodVal = methodDict[method] - + # Create combineArray node and connect combineArrayNode = mc.createNode('combineArray',n=prefix+'_combineArray') mc.setAttr(combineArrayNode+'.method',methodVal) for i in range(len(arrayList)): mc.connectAttr(arrayList[i],combineArrayNode+'.inputArray['+str(i)+']',f=True) - + # Return Result return combineArrayNode+'.outputArray' @@ -200,36 +200,36 @@ def meshDetailArray(mesh,refMesh,targetMesh='',detailType='stretch',useInMeshCon # Check refMesh if not glTools.utils.mesh.isMesh(refMesh): raise Exception('Reference mesh "'+refMesh+'" is not a valid mesh!!') - + # Check inMesh connections inMesh = mesh+'.outMesh' inMeshConn = mc.listConnections(mesh+'.inMesh',s=True,d=False,p=True) if inMeshConn and useInMeshConnection: inMesh = inMeshConn[0] - + # Check prefix if not prefix: prefix = mesh - + # Create node meshDetailArrayNode = mc.createNode('meshDetailArray',n=prefix+'_meshDetailArray') # Set Detail Attribute if detailType: - + # Define detail type mapping dtDict = { 'stretch':1,'compress':2,'stretch_abs':3,'stretch_raw':4,'stretch_norm':5, 'concave':6,'convex':7,'curve_abs':8,'curve_raw':9,'curve_norm':10 } - + # Check detail type if not dtDict.has_key(detailType): raise Exception('Invalid detail type ("'+detailType+'")!') - + # Set detail type mc.setAttr(meshDetailArrayNode+'.detailMethod',dtDict[detailType]) - + # Connect node attributes mc.connectAttr(inMesh,meshDetailArrayNode+'.inMesh',f=True) mc.connectAttr(refMesh+'.outMesh',meshDetailArrayNode+'.refMesh',f=True) if targetMesh: mc.connectAttr(targetMesh+'.outMesh',meshDetailArrayNode+'.targetMesh',f=True) - + # Return result return meshDetailArrayNode @@ -246,21 +246,21 @@ def noiseArray(mesh,useInMeshConnection=True,prefix=''): # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Mesh "'+mesh+'" is not a valid mesh!!') - + # Check inMesh connections inMesh = mesh+'.outMesh' inMeshConn = mc.listConnections(mesh+'.inMesh',p=True) if inMeshConn and useInMeshConnection: inMesh = inMeshConn[0] - + # Check prefix if not prefix: prefix = mesh - + # Create node noiseArrayNode = mc.createNode('noiseArray',n=prefix+'_noiseArray') # Connect node attributes mc.connectAttr(inMesh,noiseArrayNode+'.inMesh',f=True) mc.connectAttr(mesh+'.worldMatrix[0]',noiseArrayNode+'.inMatrix',f=True) - + # Return result return noiseArrayNode @@ -279,19 +279,19 @@ def proximityArray(mesh,proximityGeo,useInMeshConnection=True,prefix=''): # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Mesh "'+mesh+'" is not a valid mesh!!') - + # Check proximityGeo if not mc.objExists(proximityGeo): raise Exception('Proximity geometry "'+proximityGeo+'" does not exist!!') - + # Check inMesh connections inMesh = mesh+'.outMesh' inMeshConn = mc.listConnections(mesh+'.inMesh',p=True) if inMeshConn and useInMeshConnection: inMesh = inMeshConn[0] - + # Check prefix if not prefix: prefix = mesh - + # Create node proximityArrayNode = mc.createNode('proximityArray',n=prefix+'_proximityArray') # Connect node attributes @@ -299,10 +299,10 @@ def proximityArray(mesh,proximityGeo,useInMeshConnection=True,prefix=''): mc.connectAttr(mesh+'.worldMatrix[0]',proximityArrayNode+'.inMatrix',f=True) mc.connectAttr(proximityGeo+'.outMesh',proximityArrayNode+'.proximityGeometry',f=True) mc.connectAttr(proximityGeo+'.worldMatrix[0]',proximityArrayNode+'.proximityMatrix',f=True) - + # Return result return proximityArrayNode - + def velocityArray(mesh,useInMeshConnection=True,prefix=''): ''' Create a velocityArray node connected to the specified mesh. @@ -316,21 +316,21 @@ def velocityArray(mesh,useInMeshConnection=True,prefix=''): # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Mesh "'+mesh+'" is not a valid mesh!!') - + # Check inMesh connections inMesh = mesh+'.outMesh' inMeshConn = mc.listConnections(mesh+'.inMesh',p=True) if inMeshConn and useInMeshConnection: inMesh = inMeshConn[0] - + # Check prefix if not prefix: prefix = mesh - + # Create node velocityArrayNode = mc.createNode('velocityArray',n=prefix+'_velocityArray') # Connect node attributes mc.connectAttr(inMeshConn,velocityArrayNode+'.inMesh',f=True) mc.connectAttr('time1.outTime',velocityArrayNode+'.inTime',f=True) - + # Return result return velocityArrayNode @@ -352,19 +352,19 @@ def volumeArray(mesh,volume,center='',useInMeshConnection=True,prefix=''): # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Mesh "'+mesh+'" is not a valid mesh!!') - + # Check volume if not glTools.utils.mesh.isMesh(volume): raise Exception('Volume mesh "'+volume+'" is not a valid mesh!!') - + # Check inMesh connections inMesh = mesh+'.outMesh' inMeshConn = mc.listConnections(mesh+'.inMesh',p=True) if inMeshConn and useInMeshConnection: inMesh = inMeshConn[0] - + # Check prefix if not prefix: prefix = mesh - + # Create node volumeArrayNode = mc.createNode('volumeArray',n=prefix+'_volumeArray') # Connect node attributes @@ -373,7 +373,7 @@ def volumeArray(mesh,volume,center='',useInMeshConnection=True,prefix=''): mc.connectAttr(volume+'.outMesh',volumeArrayNode+'.volumeMesh',f=True) mc.connectAttr(volume+'.worldMatrix[0]',volumeArrayNode+'.volumeMatrix',f=True) if center: mc.connectAttr(center+'.worldPosition[0]',volumeArrayNode+'.volumeCenter',f=True) - + # Return result return volumeArrayNode diff --git a/utils/edgeFlowMirror.py b/utils/edgeFlowMirror.py index 25c9845..b1f3bcc 100644 --- a/utils/edgeFlowMirror.py +++ b/utils/edgeFlowMirror.py @@ -27,7 +27,7 @@ def addSymEdgeAttr(edge): if len(edge) > 1: print('Multiple mesh edges found! Using first edge only ("'+edge[0]+'").') edge = edge[0] - + # Get Edge Mesh mesh = mc.ls(edge,o=True) or [] if not mesh: @@ -35,16 +35,16 @@ def addSymEdgeAttr(edge): if len(mesh) > 1: print('Multiple mesh objects found from edge!') mesh = mesh[0] - + # Get Edge ID edgeID = glTools.utils.component.index(edge) - + # Add Attribute symAttr = 'symmetryEdgeId' if not mc.objExists(mesh+'.'+symAttr): mc.addAttr(mesh,ln=symAttr,at='long',min=0,dv=edgeID) mc.setAttr(mesh+'.'+symAttr,edgeID) - + # Return Result return mesh+'.'+symAttr @@ -55,30 +55,30 @@ def autoMirror(): ''' # Load plugin loadPlugin() - + # Get middle edge selection edgeSel = mc.ls(sl=1,fl=1)[0] meshSel = mc.ls(edgeSel,o=True)[0] mc.select(meshSel) - + # Duplicate mesh meshDup = mc.duplicate(meshSel,rr=True,n=meshSel+'_symmetry')[0] - + # Get base vertex array pts = glTools.utils.base.getMPointArray(meshSel) - + # Get Symmetry map map = mm.eval('edgeFlowMirror -task "getMapArray" -middleEdge '+edgeSel) - + # Flip mesh for i in range(len(map)): mc.move(-pts[i][0],pts[i][1],pts[i][2],meshDup+'.vtx['+str(map[i])+']',a=True,ws=True) - + # BlendShape original bs = mc.blendShape(meshDup,meshSel)[0] bsAlias = mc.listAttr(bs+'.w',m=True)[0] mc.setAttr(bs+'.'+bsAlias,0.5) - + # Delete history mc.delete(meshDup) mc.delete(meshSel,ch=True) @@ -96,24 +96,24 @@ def mirrorGeo(middleEdge,axis='x',posToNeg=True): ''' # Load plugin loadPlugin() - + # Get middle edge selection mesh = mc.ls(middleEdge,o=True)[0] mc.select(mesh) - + # Get base vertex array pts = glTools.utils.base.getMPointArray(mesh) - + # Get Symmetry map map = mm.eval('edgeFlowMirror -task "getMapArray" -middleEdge '+middleEdge) side = mm.eval('edgeFlowMirror -task "getSideArray" -middleEdge '+middleEdge) - + # Mirror mesh for i in range(len(map)): - + # Skip center verts if not side[i]: continue - + if axis == 'x': if posToNeg: if side[i] == 1: # < 0 @@ -139,81 +139,81 @@ def mirrorSkinWeights(middleEdge,leftToRight=True,search='lf_',replace='rt_',ref ''' # Load plugin loadPlugin() - + # ================= # - Get Mesh Data - # ================= - + # Get Middle Edge Mesh mesh = mc.ls(middleEdge,o=True)[0] - + if not refMesh: middleEdge.replace(mesh,refMesh) #refMesh = mesh - + # Get Edge Flow Data vmap = mm.eval('edgeFlowMirror -task "getMapArray" -middleEdge '+middleEdge) side = mm.eval('edgeFlowMirror -task "getSideArray" -middleEdge '+middleEdge) - + # ======================== # - Get SkinCluster Data - # ======================== - + # Get SkinCluster skinCluster = glTools.utils.skinCluster.findRelatedSkinCluster(mesh) - + # Get SkinCluster Inluence/Weight Lists wt = glTools.utils.skinCluster.getInfluenceWeightsAll(skinCluster) infList = mc.skinCluster(skinCluster,q=True,inf=True) - + # ======================= # - Build Influence Map - # ======================= - + infIndex = {} infMirror = {} for inf in infList: - + # Influence Index Map infIndex[inf] = glTools.utils.skinCluster.getInfluencePhysicalIndex(skinCluster,inf) - + # Influence Mirror Map mInf = inf if inf.startswith(search): mInf = inf.replace(search,replace) if inf.startswith(replace): mInf = inf.replace(replace,search) infMirror[inf] = mInf - + # ============================== # - Mirror SkinCluster Weights - # ============================== - + # Determine SideToSide ID leftToRightId = [2,1][int(leftToRight)] - + for v in range(len(vmap)): - + if side[v] == leftToRightId: - + # Get Mirror Vertex ID m = vmap[v] - + for inf in infMirror.keys(): - + # Get Influence and Mirror ID mInf = infMirror[inf] infInd = infIndex[inf] mInfInd = infIndex[mInf] - + # Assign Mirror Weight Value wt[mInfInd][m] = wt[infInd][v] - + # Apply Mirrored Weights glTools.utils.skinCluster.setInfluenceWeightsAll(skinCluster,wt,normalize=True,componentList=[]) - + # ================= # - Return Result - # ================= - + return wt def mirrorDeformerWeightValues(middleEdge,deformer): @@ -227,27 +227,27 @@ def mirrorDeformerWeightValues(middleEdge,deformer): ''' # Load plugin loadPlugin() - + # Get Mesh Data mesh = mc.ls(middleEdge,o=True)[0] vmap = mm.eval('edgeFlowMirror -task "getMapArray" -middleEdge '+middleEdge) - + # Get Deformer Weights wt = glTools.utils.deformer.getWeights(deformer,geometry=mesh) - + # Mirror Deformer Weights if len(vmap) > len(wt): - + # Membership Weight Mirror - (Generates weight list based on mirrored membership) mem = glTools.utils.deformer.getDeformerSetMemberIndices(deformer,mesh) mirror_mem = sorted([vmap[i] for i in mem]) wt = [wt[mem.index(vmap[i])] for i in mirror_mem] - + else: - + # Basic Weight Mirror wt = [wt[i] for i in vmap] - + # Return Result return wt @@ -266,18 +266,18 @@ def mirrorDeformerWeights(middleEdge,srcDeformer,dstDeformer=None,dstMesh=None): ''' # Load Plugin loadPlugin() - + # Get Mesh Data mesh = mc.ls(middleEdge,o=True)[0] - + # Check Destination Deformer/Mesh if not dstDeformer: dstDeformer = srcDeformer if not dstMesh: dstMesh = mesh - + # Mirror Deformer Weights dstWt = mirrorDeformerWeightValues(middleEdge,srcDeformer) glTools.utils.deformer.setWeights(dstDeformer,dstWt,geometry=mesh) - + # Return Result return dstWt @@ -288,7 +288,7 @@ def mirrorSelection(): ''' # Load plugin loadPlugin() - + # Seperate selection selection = mc.ls(sl=1,fl=1) @@ -300,33 +300,33 @@ def mirrorSelection(): if not len(vtxList): raise Exception('You must select a vertex to mirror!') - + if not len(edgeList): raise Exception('You must select a middle edge!') - + mirrorList = mirrorComponentList(vtxList,edgeList[0]) - + mc.select(mirrorList) - + return mirrorList - + def mirrorComponentList(componentList,middleEdge): ''' ''' # Load Plugin loadPlugin() - + # Check Component List if not componentList: raise Exception('Invalid component list!') - + # Get Mirror Component List mesh = mc.ls(componentList[0],o=True)[0] vmap = mm.eval('edgeFlowMirror -task "getMapArray" -middleEdge '+middleEdge) indList = glTools.utils.component.getComponentIndexList(componentList)[mesh] - + # Build Component List mirrorList = [mesh+'.vtx['+str(vmap[i])+']' for i in indList] - + # Return Result return mirrorList @@ -335,27 +335,27 @@ def mirrorDeformer(middleEdge,deformer,search='lf',replace='rt'): ''' # Load plugin loadPlugin() - + # Get Mesh Data mesh = mc.ls(middleEdge,o=True)[0] vmap = mm.eval('edgeFlowMirror -task "getMapArray" -middleEdge '+middleEdge) - + # Mirror Membership mem = glTools.utils.deformer.getDeformerSetMemberIndices(deformer,mesh) if len(vmap) > len(mem): mem = sorted([vmap[i] for i in mem]) mem = [mesh+'.vtx['+str(i)+']' for i in mem] - + # Create Mirror Deformer deformerType = mc.objectType(deformer) deformerName = deformer if deformerName.startswith(search): deformerName = deformerName.replace(search,replace) elif deformerName.startswith(replace): deformerName = deformerName.replace(replace,search) else: deformerName = deformerName+'_mirror' - + mDeformer = mc.deformer(mem,type=deformerType,name=deformerName)[0] - + # Mirror Deofmer Weights mirrorDeformerWeights(middleEdge,deformer,dstDeformer=mDeformer) - + # Return Result return mDeformer diff --git a/utils/eyeball.py b/utils/eyeball.py index 91db18c..7c352ec 100644 --- a/utils/eyeball.py +++ b/utils/eyeball.py @@ -4,10 +4,10 @@ class UserInputError(Exception): pass def create(piv=[0,0,0],axis=[0,0,-1],rad=1,dilate_ctrl='',prefix='eyeball'): - + #------------------------ # Generate Profile Curve - + # sphere eye_sphere = mc.sphere(p=piv,ax=axis,r=rad,n=prefix+'_history') # curve from sphere @@ -15,10 +15,10 @@ def create(piv=[0,0,0],axis=[0,0,-1],rad=1,dilate_ctrl='',prefix='eyeball'): eye_crv[0] = mc.rename(eye_crv[0],prefix+'_pfl01_crv') # rebuild curve 0-1 mc.rebuildCurve(eye_crv[0],rpo=1,end=1,kcp=1,kr=0,d=3,tol=0.01) - + #------------------------ # Extract Curve Segments - + # detach curve eye_crv_detach = mc.detachCurve(eye_crv[0]+'.u[0.125]',eye_crv[0]+'.u[0.25]',rpo=0,ch=1) eye_crv_detach[0] = mc.rename(eye_crv_detach[0],prefix+'_pl01_crv') @@ -32,10 +32,10 @@ def create(piv=[0,0,0],axis=[0,0,-1],rad=1,dilate_ctrl='',prefix='eyeball'): pupil_rebuild[1] = mc.rename(pupil_rebuild[1],prefix+'_pl01_rbc') iris_rebuild[1] = mc.rename(iris_rebuild[1],prefix+'_ir01_rbc') sclera_rebuild[1] = mc.rename(sclera_rebuild[1],prefix+'_sc01_rbc') - + #------------------------ # Generate Eye Surfaces - + # revolve pupil_revolve = mc.revolve(eye_crv_detach[0],po=0,rn=0,ut=0,tol=0.01,degree=3,s=8,ulp=1,ax=[0,0,1]) iris_revolve = mc.revolve(eye_crv_detach[1],po=0,rn=0,ut=0,tol=0.01,degree=3,s=8,ulp=1,ax=[0,0,1]) @@ -51,16 +51,16 @@ def create(piv=[0,0,0],axis=[0,0,-1],rad=1,dilate_ctrl='',prefix='eyeball'): mc.connectAttr(eye_sphere[0]+'.t',pupil_revolve[1]+'.pivot',f=1) mc.connectAttr(eye_sphere[0]+'.t',iris_revolve[1]+'.pivot',f=1) mc.connectAttr(eye_sphere[0]+'.t',sclera_revolve[1]+'.pivot',f=1) - + #------------------------ # Connect Dilate Control - + if len(dilate_ctrl): - + # Verify Control if not mc.objExists(dilate_ctrl): raise UserInputError('Object ' + dilate_ctrl + ' does not exist!') - + # Check Attributes Exist if not mc.objExists(dilate_ctrl+'.iris'): mc.addAttr(dilate_ctrl,ln='iris',min=0,max=4,dv=1) @@ -68,7 +68,7 @@ def create(piv=[0,0,0],axis=[0,0,-1],rad=1,dilate_ctrl='',prefix='eyeball'): if not mc.objExists(dilate_ctrl+'.pupil'): mc.addAttr(dilate_ctrl,ln='pupil',min=0,max=1,dv=0.5) mc.setAttr(dilate_ctrl+'.pupil',k=1) - + # Connect Attributes iris_md = mc.createNode('multDoubleLinear',n=prefix+'_irs01_mdl') pupil_md = mc.createNode('multDoubleLinear',n=prefix+'_ppl01_mdl') @@ -80,11 +80,11 @@ def create(piv=[0,0,0],axis=[0,0,-1],rad=1,dilate_ctrl='',prefix='eyeball'): mc.connectAttr(pupil_md+'.output',eye_crv_detach[3]+'.parameter[0]') def setup_aim(lf_pivot,rt_pivot,head_ccc,aim_dist,prefix): - + aim_axis=[0.0,0.0,1.0] up_axis=[0.0,1.0,0.0] worldUp_axis = up_axis - + # LEFT eye_pos = mc.xform(lf_pivot,q=1,ws=1,rp=1) # create eye aim transform @@ -92,7 +92,7 @@ def setup_aim(lf_pivot,rt_pivot,head_ccc,aim_dist,prefix): mc.xform(eye_aim,ws=1,t=(eye_pos[0],eye_pos[1],(eye_pos[2] + aim_dist))) # create aim constraint aim_con = mc.aimConstraint(eye_aim,lf_pivot,aim=aim_axis,u=up_axis,wu=worldUp_axis,wuo=head_ccc,wut='objectrotation') - + # RIGHT eye_pos = mc.xform(rt_pivot,q=1,ws=1,rp=1) # create eye aim transform @@ -100,4 +100,4 @@ def setup_aim(lf_pivot,rt_pivot,head_ccc,aim_dist,prefix): mc.xform(eye_aim,ws=1,t=(eye_pos[0],eye_pos[1],(eye_pos[2] + aim_dist))) # create aim constraint aim_con = mc.aimConstraint(eye_aim,rt_pivot,aim=aim_axis,u=up_axis,wu=worldUp_axis,wuo=head_ccc,wut='objectrotation') - + diff --git a/utils/follicle.py b/utils/follicle.py index 39eef40..4d85c25 100644 --- a/utils/follicle.py +++ b/utils/follicle.py @@ -12,16 +12,16 @@ def isFollicle(follicle): ''' # Check Object Exists if not mc.objExists(follicle): return False - + # Check Shape if 'transform' in mc.nodeType(follicle,i=True): follicleShape = mc.ls(mc.listRelatives(follicle,s=True,ni=True,pa=True) or [],type='follicle') if not follicleShape: return False follicle = follicleShape[0] - + # Check Follicle if mc.objectType(follicle) != 'follicle': return False - + # Return Result return True @@ -45,9 +45,9 @@ def create( targetGeo, # ========== # - Checks - # ========== - + if not prefix: prefix = targetGeo - + # Check Target Geo Type validType = False targetIsMesh = False @@ -59,48 +59,48 @@ def create( targetGeo, validType = True targetIsSurface = True if not validType: raise Exception('Invalid target geometry type! ('+targetGeo+')') - + # UV Set if uvSet and targetIsMesh: if not uvSet in mc.polyUVSet(targetGeo,q=True,auv=True): raise Exception('Target geometry has no UV set "'+uvSet+'"!') - + # =================== # - Create Follicle - # =================== - + follicleShape = mc.createNode('follicle') follicle = mc.listRelatives(follicleShape,p=True)[0] follicle = mc.rename(follicle,prefix+'_follicle') - + # Connect Translate/Rotate if translate: mc.connectAttr(follicle+'.outTranslate',follicle+'.translate',f=True) if rotate: mc.connectAttr(follicle+'.outRotate',follicle+'.rotate',f=True) - + # Set Parameter mc.setAttr(follicle+'.parameterU',parameter[0]) mc.setAttr(follicle+'.parameterV',parameter[1]) - + # UV Set if uvSet: mc.setAttr(follicle+'.mapSetName',uvSet,type='string') - + # ============================== # - Connect to Target Geometry - # ============================== - + # Connect Geometry if targetIsMesh: mc.connectAttr(targetGeo+'.outMesh',follicle+'.inputMesh',f=True) if targetIsSurface: mc.connectAttr(targetGeo+'.localSpace[0]',follicle+'.inputSurface',f=True) - + # Connect WorldSpace mc.connectAttr(targetGeo+'.worldMatrix[0]',follicle+'.inputWorldMatrix',f=True) - + # ================= # - Return Result - # ================= - + return follicle def buildAtPoint( pt, @@ -129,9 +129,9 @@ def buildAtPoint( pt, # ========== # - Checks - # ========== - + if not prefix: prefix = geo - + # Check Target Geo Type validType = False targetIsMesh = False @@ -143,41 +143,41 @@ def buildAtPoint( pt, validType = True targetIsSurface = True if not validType: raise Exception('Invalid target geometry type! ('+geo+')') - + # UV Set if uvSet and targetIsMesh: if not uvSet in mc.polyUVSet(geo,q=True,auv=True): raise Exception('Target geometry has no UV set "'+uvSet+'"!') - + # ===================================== # - Get Point Position and Closest UV - # ===================================== - + # Get Point Position pos = glTools.utils.base.getPosition(pt) - + # Get Closest UV parameter = [0,0] if targetIsMesh: parameter = list(glTools.utils.mesh.closestUV(geo,point=pos)) if targetIsSurface: parameter = list(glTools.utils.surface.closestPoint(geo,pos)) - + # Override UV if overrideU != None: parameter[0] = overrideU if overrideV != None: parameter[1] = overrideV - + # ================== # - Build Follicle - # ================== - + follicle = create( geo, parameter = parameter, uvSet = uvSet, translate = translate, rotate = rotate, prefix = prefix ) - + # ================= # - Return Result - # ================= - + return follicle diff --git a/utils/geometry.py b/utils/geometry.py index b8ea4e2..66051c8 100644 --- a/utils/geometry.py +++ b/utils/geometry.py @@ -10,16 +10,16 @@ def isGeometry(geometry): ''' # Check Object Exists if not mc.objExists(geometry): return False - + # Check Shape if 'transform' in mc.nodeType(geometry,i=True): geoShape = mc.ls(mc.listRelatives(mesh,s=True,ni=True,pa=True) or [],geometry=True) if not geoShape: return False geometry = geoShape[0] - + # Check Geometry if 'geometryShape' in mc.nodeType(geometry,i=True): return True - + # Return Result return False @@ -32,17 +32,17 @@ def geometryType(geometry): # Check Geometry if not mc.objExists(geometry): raise Exception('Geometry object "'+geometry+'" does not exist!!') - + # Get Shapes shapeList = glTools.utils.shape.getShapes(geometry,intermediates=False) if not shapeList: shapeList = glTools.utils.shape.getShapes(geometry,intermediates=True) if not shapeList: raise Exception('Geometry object "'+geometry+'" has no shape children!!') - + # Get Geometry Type geometryType = mc.objectType(shapeList[0]) - + # Return Result return geometryType @@ -55,20 +55,20 @@ def componentType(geometry): # Check geometry if not mc.objExists(geometry): raise Exception('Geometry object "'+geometry+'" does not exist!!') - + # Get geometry type geoType = geometryType(geometry) - + # Define return values compType = {'mesh':'vtx','nurbsSurface':'cv','nurbsCurve':'cv','lattice':'pt','particle':'pt'} - + # Return result return compType[geoType] def replace(sourceGeometry,destinationGeometry): ''' Replace the geometry of one object with another - @param sourceGeometry: The object that will provide the replacement geometry + @param sourceGeometry: The object that will provide the replacement geometry @type sourceGeometry: str @param destinationGeometry: The object whose geometry will be replaced @type destinationGeometry: str @@ -78,7 +78,7 @@ def replace(sourceGeometry,destinationGeometry): raise Exception('Destination geometry "'+destinationGeometry+'" does not exist!!') if not mc.objExists(sourceGeometry): raise Exception('Source geometry "'+sourceGeometry+'" does not exist!!') - + # Determine geometry types sourceShape = sourceGeometry sourceGeoType = geometryType(sourceGeometry) @@ -101,7 +101,7 @@ def replace(sourceGeometry,destinationGeometry): break else: raise Exception('Unknown geometry type "'+sourceGeoType+'" is not supported!!') - + destinationShape = destinationGeometry destinationGeoType = geometryType(destinationGeometry) if mc.objectType(destinationShape) == 'transform': @@ -123,11 +123,11 @@ def replace(sourceGeometry,destinationGeometry): break else: raise Exception('Unknown geometry type "'+destinationGeoType+'" is not supported!!') - + # Check geometry types if destinationGeoType != sourceGeoType: raise Exception('Destination and Source geometry types do not match!!') - + # Replace geometry #- # Mesh diff --git a/utils/geometryCache.py b/utils/geometryCache.py index 66a75a0..7857320 100644 --- a/utils/geometryCache.py +++ b/utils/geometryCache.py @@ -57,10 +57,10 @@ def isAlembicNode(cacheNode): ''' # Check object exists if not mc.objExists(cacheNode): return False - + # Check node type if mc.objectType(cacheNode) != 'AlembicNode': return False - + # Return result return True @@ -72,10 +72,10 @@ def isGpuCacheNode(gpuCacheNode): ''' # Check object exists if not mc.objExists(gpuCacheNode): return False - + # Check node type if mc.objectType(gpuCacheNode) != 'gpuCache': return False - + # Return result return True @@ -87,10 +87,10 @@ def isIkaGpuCacheNode(glGpuCacheNode): ''' # Check object exists if not mc.objExists(glGpuCacheNode): return False - + # Check node type if mc.objectType(glGpuCacheNode) != 'glGpuCache': return False - + # Return result return True @@ -103,7 +103,7 @@ def disconnectTime(cache): # Get existing connections timeConn = mc.listConnections(cache+'.time',s=True,d=False,p=True) if not timeConn: return - + # Disconnect time plug mc.disconnectAttr(timeConn[0],cache+'.time') @@ -118,7 +118,7 @@ def connectTime(cache,timeAttr='time1.outTime'): # Check time attribute if not mc.objExists(timeAttr): raise Exception('Time attribute "'+timeAttr+'" does not exist!') - + # Disconnect time plug mc.connectAttr(timeAttr,cache+'.time',f=True) @@ -132,10 +132,10 @@ def importMCCache(geo,cacheFile): ''' # Check geo if not mc.objExists(geo): raise Exception('Geometry "" does not exist!') - + # Check file if not os.path.isfile(cacheFile): raise Exception('Cache file "'+cacheFile+'" does not exist!') - + # Load cache mm.eval('doImportCacheFile "'+cacheFile+'" "" {"'+geo+'"} {}') @@ -153,18 +153,18 @@ def importMCCacheList(geoList,cachePath,cacheFileList=[]): if not os.path.isdir(cachePath): raise Exception('Cache path "'+cachePath+'" does not exist!') if not cachePath.endswith('/'): cachePath = cachePath+'/' - + # Check cacheFile list if cacheFileList and not (len(cacheFileList) == len(geoList)): raise Exception('Cache file and geometry list mis-match!') - + # For each geometry in list for i in range(len(geoList)): - + # Check geo if not mc.objExists(geoList[i]): raise Exception('Geometry "'+geoList[i]+'" does not exist!') - + # Determine cache file if cacheFileList: cacheFile = cacheFile = cachePath+cacheFileList[i]+'.mc' @@ -174,14 +174,14 @@ def importMCCacheList(geoList,cachePath,cacheFileList=[]): if not shapeList: raise Exception('No valid shape found for geometry!') geoShape = shapeList[0] cacheFile = cachePath+geoShape+'.mc' - + # Check file if not os.path.isfile(cacheFile): raise Exception('Cache file "'+cacheFile+'" does not exist!') - + # Import cache importMCCache(geoList[i],cacheFile) - + def exportMCCache(geo,cacheFile,startFrame=1,endFrame=100,useTimeline=True,filePerFrame=False,cachePerGeo=True,forceExport=False): ''' @param geo: List of geometry to cache @@ -194,11 +194,11 @@ def exportMCCache(geo,cacheFile,startFrame=1,endFrame=100,useTimeline=True,fileP @type endFrame: int @param useTimeline: Get start and end from from the timeline @type useTimeline: bool - @param filePerFrame: Write file per frame or single file + @param filePerFrame: Write file per frame or single file @type filePerFrame: bool - @param cachePerGeo: Write file per shape or single file + @param cachePerGeo: Write file per shape or single file @type cachePerGeo: bool - @param forceExport: Force export even if it overwrites existing files + @param forceExport: Force export even if it overwrites existing files @type forceExport: bool ''' # Constant value args @@ -207,27 +207,27 @@ def exportMCCache(geo,cacheFile,startFrame=1,endFrame=100,useTimeline=True,fileP usePrefix = 0 # Name as prefix cacheAction = 'export' # Cache action "add", "replace", "merge", "mergeDelete" or "export" simRate = 1 # Sim frame rate (steps per frame - ?) - + # Frame range if useTimeline: startFrame = mc.playbackOptions(q=True,ast=True) endFrame = mc.playbackOptions(q=True,aet=True) - + # Cache file distribution if filePerFrame: cacheDist = 'OneFilePerFrame' else: cacheDist = 'OneFile' - + # Determine destination directory and file fileName = cacheFile.split('/')[-1] cacheDir = cacheFile.replace(fileName,'') baseName = fileName.replace('.'+fileName.split('.')[-1],'') - + # Export cache mc.select(geo) mm.eval('doCreateGeometryCache '+str(version)+' {"0","'+str(startFrame)+'","'+str(endFrame)+'","'+cacheDist+'","'+str(refresh)+'","'+cacheDir+'","'+str(int(cachePerGeo))+'","'+baseName+'","'+str(usePrefix)+'","'+cacheAction+'","'+str(int(forceExport))+'","1","1","0","0","mcc" };') - + def importGpuCache(cachePath,cacheName='',namespace=''): ''' Import GPU Alembic cache from file @@ -239,19 +239,19 @@ def importGpuCache(cachePath,cacheName='',namespace=''): # ========= # - Check - # ========= - + # Load Import Plugin loadAbcImportPlugin() - + # Check Cache Path if not os.path.isfile(cachePath): raise Exception('Cache path "'+cachePath+'" is not a valid file!') - + # Check Cache Name if not cacheName: cacheBase = os.path.basename(cachePath) cacheName = os.path.splitext(cacheBase)[-1] - + # Check Namespace if namespace: if mc.namespace(ex=namespace): @@ -259,36 +259,36 @@ def importGpuCache(cachePath,cacheName='',namespace=''): while(mc.namespace(ex=namespace+str(NSind))): NSind += 1 namespace = namespace+str(NSind) - + # ============== # - Load Cache - # ============== - + # Create Cache Node cacheNode = mc.createNode('gpuCache',name=cacheName+'Cache') cacheParent = mc.listRelatives(cacheNode,p=True,pa=True) cacheParent = mc.rename(cacheParent,cacheName) - + # Set Cache Path mc.setAttr(cacheNode+'.cacheFileName',cachePath,type='string') - + # =================== # - Apply Namespace - # =================== - + if namespace: - + # Create Namespace (if necessary) if not mc.namespace(ex=namespace): mc.namespace(add=namespace) # Apply Namespace cacheParent = mc.rename(cacheParent,namespace+':'+cacheParent) # Update cacheNode cacheNode = mc.listRelatives(cacheParent,s=True,pa=True)[0] - + # ================= # - Return Result - # ================= - + return cacheParent def importAbcCache(cachePath='',cacheName='',namespace='',parent='',mode='import',debug=False): @@ -310,19 +310,19 @@ def importAbcCache(cachePath='',cacheName='',namespace='',parent='',mode='import # ========== # - Checks - # ========== - + # Load Import Plugin loadAbcImportPlugin() - + # Check Cache Path if not os.path.isfile(cachePath): raise Exception('Cache path "'+cachePath+'" is not a valid file!') - + # Check Cache Name if not cacheName: cacheBase = os.path.basename(cachePath) cacheName = os.path.splitext(cacheBase)[-1] - + # Check Namespace if namespace: if mc.namespace(ex=namespace): @@ -330,17 +330,17 @@ def importAbcCache(cachePath='',cacheName='',namespace='',parent='',mode='import while(mc.namespace(ex=namespace+str(NSind))): NSind += 1 namespace = namespace+str(NSind) - + # ============== # - Load Cache - # ============== - + cacheNode = mc.AbcImport(cachePath,mode=mode,debug=debug) cacheNode = mc.rename(cacheNode,cacheName+'Cache') - + # Get Cache Nodes cacheList = mc.listConnections(cacheNode,s=False,d=True) - + # Get Cache Roots rootList = [] for cacheItem in cacheList: @@ -349,27 +349,27 @@ def importAbcCache(cachePath='',cacheName='',namespace='',parent='',mode='import root = mc.listRelatives(root,p=True,pa=True)[0] if not rootList.count(root): rootList.append(root) - - + + # Add to Namespace if namespace: for root in rootList: glTools.utils.namespace.addHierarchyToNS(root,namespace) - + # Parent if parent: - + # Check Parent Transform if not mc.objExists(parent): parent = mc.group(em=True,n=parent) - + # Parent mc.parent(rootList,parent) - + # ================= # - Return Result - # ================= - + return cacheNode @@ -385,51 +385,51 @@ def loadAbcFromGpuCache(gpuCacheNode,debug=False): # ========= # - Check - # ========= - + # Load Import Plugin loadAbcImportPlugin() - + # Check GPU Cache Node if not isGpuCacheNode(gpuCacheNode): raise Exception('Object "'+gpuCacheNode+'" is not a valid GPU Cache Node!') - + # ===================== # - Get Cache Details - # ===================== - + cachePath = mc.getAttr(gpuCacheNode+'.cacheFileName') - + # Get Cache Node Transform and Parent cacheXform = mc.listRelatives(gpuCacheNode,p=True,pa=True)[0] cacheParent = mc.listRelatives(cacheXform,p=True,pa=True) if not cacheParent: cacheParent = '' - + # Get Cache Namespace cacheNS = glTools.utils.namespace.getNS(gpuCacheNode) - + # Get Cache Name cacheName = gpuCacheNode if gpuCacheNode.count('Cache'): cacheName = gpuCacheNode.replace('Cache','') - + # Delete GPU Cache mc.delete(cacheXform) - + # ====================== # - Load Alembic Cache - # ====================== - + cacheNode = importAbcCache(cachePath,cacheName=cacheName,namespace=cacheNS,parent=cacheParent,mode='import',debug=debug) #cacheXform = mc.listRelatives(cacheNode,p=True,pa=True)[0] - + # Parent Cache # if cacheParent: mc.parent(cacheXform,cacheParent) - + # ================= # - Return Result - # ================= - + return cacheNode def abcTimeOffset(offsetNode,offsetAttr='alembicTimeOffset',cacheList=[]): @@ -445,44 +445,44 @@ def abcTimeOffset(offsetNode,offsetAttr='alembicTimeOffset',cacheList=[]): # ========= # - Check - # ========= - + # Check Cache List if not cacheList: return '' - + # Check offsetNode if not mc.objExists(offsetNode): raise Exception('Offset node "'+offsetNode+'" does not exist!') - + # Check offsetAttr if not offsetAttr: offsetAttr = 'alembicTimeOffset' - + # ======================== # - Add Offset Attribute - # ======================== - + if not mc.objExists(offsetNode+'.'+offsetAttr): mc.addAttr(offsetNode,ln=offsetAttr,at='long',dv=0,k=True) - + # ======================= # - Connect Time Offset - # ======================= - + for cache in cacheList: - + # Get Current Time Connection timeConn = mc.listConnections(cache+'.time',s=True,d=False,p=True) if not timeConn: timeConn = ['time1.outTime'] - + # Offset Node addNode = mc.createNode('addDoubleLinear',n=cache+'_abcOffset_addDoubleLinear') - + # Connect to Offset Time mc.connectAttr(timeConn[0],addNode+'.input1',f=True) mc.connectAttr(offsetNode+'.'+offsetAttr,addNode+'.input2',f=True) mc.connectAttr(addNode+'.output',cache+'.time',f=True) - + # ================= # - Return Result - # ================= - + return offsetNode+'.'+offsetAttr diff --git a/utils/hair.py b/utils/hair.py index 9ba5f4e..935179f 100644 --- a/utils/hair.py +++ b/utils/hair.py @@ -12,16 +12,16 @@ def isHairSystem(hairSystem): ''' # Check object exists if not mc.objExists(hairSystem): return False - + # Check transform if mc.objectType(hairSystem) == 'transform': hairSystemShape = mc.listRelatives(hairSystem,s=True,pa=True) if not hairSystemShape: return False hairSystem = hairSystemShape[0] - + # Check hairSystem if mc.objectType(hairSystem) == 'hairSystem': return True - + # Return result return False @@ -30,16 +30,16 @@ def isFollicle(follicle): ''' # Check object exists if not mc.objExists(follicle): return False - + # Check transform if mc.objectType(follicle) == 'transform': follicleShape = mc.listRelatives(follicle,s=True,pa=True) if not follicleShape: return False follicle = follicleShape[0] - + # Check hairSystem if mc.objectType(follicle) == 'follicle': return True - + # Return result return False @@ -48,19 +48,19 @@ def getConnectedHairSystem(hair): ''' # Check object exists if not mc.objExists(hair): raise Exception('Object "'+hair+'" does not exist!') - + # Find connected follicle if not isFollicle(): follicle = getConnectedFollicle(hair) else: follicle = hair - + # Check follicle if isFollicle(follicle): hairSystem = mc.listConnections(hair+'.outHair',s=True,d=False,type='hairSystem') if not hairSystem: raise Exception('Unable to determine hairSystem from follicle "'+hair+'"!') return hairSystem[0] - + # Unable to determine hair system raise Exception('Unable to determine hairSystem from object "'+hair+'"!') @@ -69,18 +69,18 @@ def getConnectedFollicle(hair): ''' # Check object exists if not mc.objExists(hair): raise Exception('Object "'+hair+'" does not exist!') - + # Initialize output list follicles = [] - + # Check hairSystem if isHairSystem(hair): follicles = mc.listConnections(hair,s=True,d=False,type='follicle') - + # Check curve if glTools.utils.curve.isCurve(hair): follicles = mc.listConnections(hair,s=True,d=True,type='follicle') - + # Return result return follicles @@ -92,13 +92,13 @@ def createHairSystem(name=''): ''' # Check name if not name: name = 'hairSystem#' - + # Create hair system hairSystemShape = mc.createNode('hairSystem') mc.connectAttr('time1.outTime',hairSystemShape+'.currentTime',f=True) hairSystem = mc.listRelatives(hairSystemShape,p=True,pa=True)[0] hairSystem = mc.rename(hairSystem,name) - + # Return result return hairSystem @@ -121,27 +121,27 @@ def createFollicle(surface,u,v,prefix=''): elif glTools.utils.mesh.isMesh(surface): surfaceType = 'mesh' else: raise Exception('Invalid surface "'+surface+'"!') - + # Create follicle follicleShape = mc.createNode('follicle') follicle = mc.listRelatives(follicleShape,p=True,pa=True)[0] follicle = mc.rename(follicle,prefix+'_follicle') - + # Connect to surface mc.connectAttr(surface+'.worldMatrix[0]',follicle+'.inputWorldMatrix',f=True) if surfaceType == 'nurbsSurface': mc.connectAttr(surface+'.local',follicle+'.inputSurface',f=True) elif surfaceType == 'mesh': mc.connectAttr(surface+'.outMesh',follicle+'.inputMesh',f=True) - + # Set parameter values mc.setAttr(follicle+'.parameterU',u) mc.setAttr(follicle+'.parameterV',v) - + # Connect Translate/Rotate mc.connectAttr(follicle+'.outTranslate',follicle+'.translate',f=True) mc.connectAttr(follicle+'.outRotate',follicle+'.rotate',f=True) - + # Return result return follicle @@ -160,16 +160,16 @@ def createFollicles(ptList,childList,follicleSurface,prefix): # ========== # - Checks - # ========== - + # Point List if not ptList: raise Exception('Invalid input point list!') - + # Child List if childList: if len(ptList) != len(childList): raise Exception('Input point and child lists have a different number of elements!') - + # Determine surface type srfType = '' if glTools.utils.mesh.isMesh(follicleSurface): @@ -178,17 +178,17 @@ def createFollicles(ptList,childList,follicleSurface,prefix): srfType = 'nurbsSurface' else: raise Exception('Invalid surface type!') - + # ==================== # - Create Follicles - # ==================== - + follicleList = [] for i in range(len(ptList)): - + # Get follicle position pt = glTools.utils.base.getPosition(ptList[i]) - + # Determine closest surface uv if srfType == 'mesh': u,v = glTools.utils.mesh.closestUV(follicleSurface,pt,uvSet='') @@ -196,62 +196,62 @@ def createFollicles(ptList,childList,follicleSurface,prefix): u,v = glTools.utils.surface.closestPoint(follicleSurface,pt) else: raise Exception('Invalid surface type!') - + # Create Follicle ind = glTools.utils.stringUtils.stringIndex(i+1,padding=2) follicle = createFollicle(follicleSurface,u,v,prefix+'_'+ind) follicleList.append(follicle) - + # Parent to follicle if childList: mc.parent(childList[i],follicle) - + # Return Result return follicleList def makeDynamic(curveList,hairSystem='',connectRestPosition=True,follicleDegree=0,autoParentFollicle=False,prefix=''): ''' Create dynamic curves from a list of input curves - @param curveList: List of curves to make dynamic + @param curveList: List of curves to make dynamic @type curveList: list - @param hairSystem: Hair system to attach the dynamic curve follicles to. + @param hairSystem: Hair system to attach the dynamic curve follicles to. @type hairSystem: str @param prefix: Name prefix for newly created nodes @type prefix: str ''' # Check prefix if prefix and not prefix.endswith('_'): prefix += '_' - + # Check hair system if not hairSystem: hairSystem = createHairSystem() else: if not isHairSystem(hairSystem): hairSystem = createHairSystem(hairSystem) - + # Check curves for curve in curveList: if not glTools.utils.curve.isCurve(curve): raise Exception('Object "'+curve+'" is not a valid nurbs curve!') - + # Initialize MEL variable mm.eval('int $ind[1] = {0};') - + # Create hierarchy hairGrp = mc.group(hairSystem,n=prefix+'grp') hSysGrp = mc.createNode('transform',n=prefix+'follicle_grp',p=hairGrp) hOutGrp = mc.createNode('transform',n=prefix+'dynCurve_grp',p=hairGrp) - + # Iterate over curves follicleList = [] dynCurveList = [] for curve in curveList: - + # Check curve if not mc.objectType(curve) == 'nurbsCurve': curveShape = mc.listRelatives(curve,s=True,ni=True,type='nurbsCurve') if not curveShape: raise Exception('Unable to determine curve shape from "'+curve+'"!') curveShape = curveShape[0] - + # Input Argument Values surface = '' u = 0.0 @@ -259,30 +259,30 @@ def makeDynamic(curveList,hairSystem='',connectRestPosition=True,follicleDegree= numCVs = 0 length = 0.0 dynamic = 1 - + # Create dynamic curve follicle = mm.eval('createHairCurveNode("'+hairSystem+'","'+surface+'",'+str(u)+','+str(v)+','+str(numCVs)+',true,true,false,false,"'+curveShape+'",'+str(length)+', $ind,"'+hSysGrp+'","'+hOutGrp+'",'+str(dynamic)+')') follicle = mc.rename(follicle,prefix+curve+'_follicle') - + # Connect Rest Position if connectRestPosition: mc.connectAttr(curve+'.worldSpace[0]',follicle+'.restPosition',f=True) mc.setAttr(follicle+'.restPose',3) - + # Follicle Degree if follicleDegree: mc.setAttr(follicle+'.degree',follicleDegree) - + # Parent Follicle if autoParentFollicle: follicle = mc.parent(follicle,hSysGrp)[0] - + # Rename dynamic curve dynCurve = mc.listConnections(follicle+'.outCurve',s=False,d=True)[0] dynCurve = mc.rename(dynCurve,prefix+curve+'_dynCurve') - + # Append output list follicleList.append(follicle) dynCurveList.append(dynCurve) - + # Return result return [hairGrp,follicleList,dynCurveList,hairSystem] diff --git a/utils/hik.py b/utils/hik.py index 02d51c3..a5f92a6 100644 --- a/utils/hik.py +++ b/utils/hik.py @@ -14,13 +14,13 @@ def isCharacterDefinition(char,verbose=False): if verbose: print('Object "'+char+'" does not exist!') return False - + # Check Object Type if mc.objectType(char) != 'HIKCharacterNode': if verbose: print('Object "'+char+'" is not a valid "HIKCharacterNode"!') return False - + # Return Result return True @@ -41,12 +41,12 @@ def createCharacterDefinition(characterName=''): if characterName and isCharacterDefinition(characterName,False): raise Exception('Character definition "'+characterName+'" already exists!') if not characterName: characterName = 'Character1' - + # Create New Definition charStr = mm.eval('newCharacterWithName("'+characterName+'")') # Extract Definition Name from Return String - WTF!! char = charStr.split("'")[1] - + # Return Result return char @@ -68,11 +68,11 @@ def setCurrentCharacter(char): # Check Character Definition if not isCharacterDefinition(char,verbose=True): raise Exception('"'+char+'" is not a valid "HIKCharacterNode"!') - + # Set Current Character mc.optionMenuGrp('hikCharacterList',e=True,v=char) mm.eval('hikUpdateCurrentCharacterFromUI();') - + # Return Result current_char = getCurrentCharacter() return current_char @@ -83,7 +83,7 @@ def setCharacterLock(char,lock=True): # Check Character Definition if not isCharacterDefinition(char,verbose=True): raise Exception('"'+char+'" is not a valid "HIKCharacterNode"!') - + # Set Character Current activeChar = getCurrentCharacter() setCurrentCharacter(char) @@ -94,11 +94,11 @@ def setCharacterSource(char,source): # Check Character Definition if not isCharacterDefinition(char,verbose=True): raise Exception('"'+char+'" is not a valid "HIKCharacterNode"!') - + # Set Character Source mm.eval('hikSetCurrentSource("'+source+'");') mm.eval('hikUpdateSourceList();') mm.eval('hikUpdateSkeletonUI();') - + # Return Result return source diff --git a/utils/ik.py b/utils/ik.py index a672037..f55ecce 100644 --- a/utils/ik.py +++ b/utils/ik.py @@ -13,20 +13,20 @@ def getAffectedJoints(ikHandle): # Check ikHandle if not mc.objExists(ikHandle): raise Exception('IK handle '+ikHandle+' does not exist!') if mc.objectType(ikHandle) != 'ikHandle': raise Exception('Object '+ikHandle+' is not a valid ikHandle!') - + # Get startJoint startJoint = mc.listConnections(ikHandle+'.startJoint',s=True,d=False)[0] # Get endEffector endEffector = mc.listConnections(ikHandle+'.endEffector',s=True,d=False)[0] endJoint = mc.listConnections(endEffector+'.translateX',s=True,d=False)[0] - + # Get list of joints affected by ikHandle ikJoints = [endJoint] while ikJoints[-1] != startJoint: ikJoints.append(mc.listRelatives(ikJoints[-1],p=True)[0]) # Reverse joint list ikJoints.reverse() - + # Return ik joints list return ikJoints @@ -44,7 +44,7 @@ def poleVectorPosition(ikHandle,poleVectorType='free',distanceFactor=1.0): if mc.objectType(ikHandle) != 'ikHandle': raise Exception('Object "'+ikHandle+'" is not a valid IK Handle!!') if mc.listConnections(ikHandle+'.ikSolver',s=True,d=False)[0] != 'ikRPsolver': raise Exception('IK Handle "'+ikHandle+'" does not use a pole vector!!') - + # Get IK chain details ikJoints = getAffectedJoints(ikHandle) poleVector = mc.getAttr(ikHandle+'.poleVector')[0] @@ -54,11 +54,11 @@ def poleVectorPosition(ikHandle,poleVectorType='free',distanceFactor=1.0): if ikParent: ikMatrix = glTools.utils.matrix.buildMatrix(transform=ikParent[0]) poleVector = glTools.utils.matrix.vectorMatrixMultiply(poleVector,ikMatrix,transformAsPoint=False,invertMatrix=False) - + # Get start/end joint positions startPos = mc.xform(ikJoints[0],q=True,ws=True,rp=True) endPos = mc.xform(ikJoints[-1],q=True,ws=True,rp=True) - + # Calculate poleVector position # == # FREE @@ -81,7 +81,7 @@ def poleVectorPosition(ikHandle,poleVectorType='free',distanceFactor=1.0): pvPos = (startPos[0]+(poleVector[0]*pvDist),startPos[1]+(poleVector[1]*pvDist),startPos[2]+(poleVector[2]*pvDist)) else: raise Exception('Invalid poleVector type supplied ("'+poleVectorType+'")!! Specify "free" or "fixed"!') - + # Return position return pvPos @@ -96,15 +96,15 @@ def getLocalSolver(solverType): solverTypeList = ['ikRPsolver','ikSCsolver','ikSplineSolver'] if not solverType in solverTypeList: raise Exception('Invalid IK solver type "'+solverType+'"!') - + # Get Solvers for solvers in mc.ls(exactType=solverType): if not glTools.utils.reference.isReferenced(solvers): return solver - + # No Solver Found, Create New solver = mc.createNode(solverType) mc.connectAttr(solver+'.message','ikSystem.ikSolver',na=True) - + # Return Result return solver diff --git a/utils/isolateSelected.py b/utils/isolateSelected.py index bf65ae9..097445f 100644 --- a/utils/isolateSelected.py +++ b/utils/isolateSelected.py @@ -6,11 +6,11 @@ def getPanel(): ''' # Get Panel with Focus panel = mc.getPanel(wf=True) - + # Check Model Panel if not mc.modelPanel(panel,q=True,ex=True): panel = mc.getPanel(type='modelPanel')[0] - + # Return Result return panel @@ -27,40 +27,40 @@ def isolate(state,sel=None,panel=None): # ========== # - Checks - # ========== - + # Check Selection if (sel != None) and (not sel): sel = mc.ls(sl=1) - + # Check Panel if not panel: try: panel = getPanel() except: print('Unable to determine model panel! Aborting...') return - + # ==================== # - Isolate Selected - # ==================== - + if state: - + # Clear Selection mc.select(cl=True) - + # Isolate Selected - Enable mc.isolateSelect(panel,state=True) - + # Update Selection if sel: mc.select(sel) - + # Load Selected mc.isolateSelect(panel,loadSelected=True) - + # Update Isolate Set mc.isolateSelect(panel,update=True) - + else: - + # Isolate Selected - Disable mc.isolateSelect(panel,state=False) @@ -72,7 +72,7 @@ def getPanelVis(panel=None): ''' # Check Panel if not panel: panel = getPanel() - + # Get Panel Vis panelVis = [] panelVis.append(mc.modelEditor(panel,q=True,nurbsCurves=True)) @@ -183,13 +183,13 @@ def disableAllPanelVis(): ''' # Get Visible Panels panels = mc.getPanel(type='modelPanel') or [] - + # Store/Disable Panel Vis States panelVis = {} for panel in panels: panelVis[panel] = getPanelVis(panel=panel) disablePanelVis(panel) - + # Return Result return panelVis @@ -201,11 +201,11 @@ def enableAllPanelVis(panelVis): ''' # Get Stored Panel List panels = panelVis.keys() or [] - + # Restore/Enable Panel Vis States for panel in panels: if mc.modelPanel(panel,q=True,ex=True): setPanelVis(panel,panelVis[panel]) - + # Return Result return panels diff --git a/utils/joint.py b/utils/joint.py index 0cb38fb..33bc2ff 100644 --- a/utils/joint.py +++ b/utils/joint.py @@ -19,10 +19,10 @@ def isJoint(joint): ''' # Check object exists if not mc.objExists(joint): return False - + # Check joint if not mc.ls(type='joint').count(joint): return False - + # Return result return True @@ -35,7 +35,7 @@ def isEndJoint(joint): # Check Joint if not isJoint(joint): raise Exception('Object "'+joint+'" is not a valid joint!') - + # Check Child Joints jointDescendants = mc.ls(mc.listRelatives(joint,ad=True) or [],type='joint') if not jointDescendants: return True @@ -52,26 +52,26 @@ def getEndJoint(startJoint,includeTransforms=False): # Check Start Joint if not mc.objExists(startJoint): raise Exception('Start Joint "'+startJoint+'" does not exist!') - + # Find End Joint endJoint = None nextJoint = startJoint while(nextJoint): - + # Get Child Joints childList = mc.listRelatives(nextJoint,c=True) or [] childJoints = mc.ls(childList,type='joint') or [] if includeTransforms: childJoints = list(set(childJoints + mc.ls(childList,transforms=True) or [])) - + # Check End Joint if childJoints: nextJoint = childJoints[0] else: endJoint = nextJoint nextJoint = None - - # Return Result + + # Return Result return endJoint def getJointList(startJoint,endJoint): @@ -89,25 +89,25 @@ def getJointList(startJoint,endJoint): raise Exception('End Joint "'+endJoint+'" does not exist!') # Check Single Joint if startJoint == endJoint: return [startJoint] - + # Check hierarchy decendantList = mc.ls(mc.listRelatives(startJoint,ad=True),type='joint') if not decendantList.count(endJoint): raise Exception('End joint "'+endJoint+'" is not a decendant of start joint "'+startJoint+'"!') - + # Build joint list jntList = [endJoint] while(jntList[-1] != startJoint): pJnt = mc.listRelatives(jntList[-1],p=True,pa=True) - if not pJnt: raise Exception('Found root joint while searching for start joint "'+startJoint+'"!') + if not pJnt: raise Exception('Found root joint while searching for start joint "'+startJoint+'"!') jntList.append(pJnt[0]) - + # Reverse list jntList.reverse() - + # Return result return jntList - + def length(joint): ''' Get length of specified joint @@ -116,11 +116,11 @@ def length(joint): ''' # Check Joint if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') - + # Get Child Joints cJoints = mc.ls(mc.listRelatives(joint,c=True,pa=True) or [],type='joint') if not cJoints: return 0.0 - + # Get Length maxLength = 0.0 for cJoint in cJoints: @@ -129,7 +129,7 @@ def length(joint): offset = glTools.utils.mathUtils.offsetVector(pt1,pt2) length = glTools.utils.mathUtils.mag(offset) if length > maxLength: maxLength = length - + # Return Result return maxLength @@ -144,11 +144,11 @@ def group(joint,indexStr='A'): # ========== # - Checks - # ========== - + # Check Joint if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') - + # Check Index String if not indexStr: result = mc.promptDialog( title='Index String', @@ -158,35 +158,35 @@ def group(joint,indexStr='A'): defaultButton='Create', cancelButton='Cancel', dismissString='Cancel' ) - + if result == 'Create': indexStr = mc.promptDialog(q=True,text=True) else: print 'User canceled joint group creation...' return - + # Get Name Prefix prefix = glTools.utils.stringUtils.stripSuffix(joint) - + # ====================== # - Create Joint Group - # ====================== - + grp = mc.duplicate(joint,po=True,n=prefix+'Con'+indexStr+'_jnt')[0] mc.parent(joint,grp) - + # Set Joint Radius if mc.getAttr(grp+'.radius',se=True): try: mc.setAttr(grp+'.radius',0) except: pass - + # Connect Inverse Scale inverseScaleCon = mc.listConnections(joint+'.inverseScale',s=True,d=False) if not inverseScaleCon: inverseScaleCon = [] if not inverseScaleCon.count(grp): try: mc.connectAttr(grp+'.scale',joint+'.inverseScale',f=True) except: pass - + # Delete User Attrs udAttrList = mc.listAttr(grp,ud=True) if udAttrList: @@ -194,15 +194,15 @@ def group(joint,indexStr='A'): if mc.objExists(grp+'.'+attr): mc.setAttr(grp+'.'+attr,l=False) mc.deleteAttr(grp+'.'+attr) - + # Set Display Overrides glTools.utils.base.displayOverride(joint,overrideEnable=1,overrideLOD=0) glTools.utils.base.displayOverride(grp,overrideEnable=1,overrideDisplay=2,overrideLOD=1) - + # ================= # - Return Result - # ================= - + return grp def setDrawStyle(joints,drawStyle='bone'): @@ -216,25 +216,25 @@ def setDrawStyle(joints,drawStyle='bone'): # Check Joints if not joints: raise Exception('No joints specified!') - + # Check Draw Style drawStyle = drawStyle.lower() if not drawStyle in ['bone','box','none']: raise Exception('Invalid drawt style ("'+drawStyle+'")! Accepted values are "bone", "box" and "none"...') - + # For Each Joint for jnt in joints: - + # Check Joint if not isJoint(jnt): continue - + # Bone if drawStyle == 'bone': mc.setAttr(jnt+'.drawStyle',0) # Box if drawStyle == 'box': mc.setAttr(jnt+'.drawStyle',1) # None if drawStyle == 'none': mc.setAttr(jnt+'.drawStyle',2) - + # Return Result return joints @@ -252,15 +252,15 @@ def duplicateJoint(joint,name=None): if not name: name = joint+'_dup' if mc.objExists(str(name)): raise Exception('Joint "'+name+'" already exist!') - + # Duplicate Joint dupJoint = mc.duplicate(joint,po=True)[0] if name: dupJoint = mc.rename(dupJoint,name) - + # Unlock Transforms for at in ['tx','ty','tz','rx','ry','rz','sx','sy','sz','v','radius']: mc.setAttr(dupJoint+'.'+at,l=False,cb=True) - + # Return Result return dupJoint @@ -285,47 +285,47 @@ def duplicateChain( startJoint, # ========== # - Checks - # ========== - + # Check Joints if not mc.objExists(startJoint): raise Exception('Start Joint "'+startJoint+'" does not exist!') if endJoint and not mc.objExists(str(endJoint)): raise Exception('End Joint "'+endJoint+'" does not exist!') - + # Check Parent if parent: if not mc.objExists(parent): raise Exception('Specified parent transform "'+parent+'" does not exist!') if not glTools.utils.transform.isTransform(parent): raise Exception('Parent object "'+parent+'" is not a valid transform!') - + # ========================= # - Duplicate Joint Chain - # ========================= - + # Get Full Joint List if not endJoint: endJoint = getEndJoint(startJoint) joints = glTools.utils.joint.getJointList(startJoint,endJoint) - + # Get List of Skip Joints skipJoints = mc.ls(skipJnt) if skipJnt else [] - + dupChain = [] for i in range(len(joints)): - + # Skip Joints if joints[i] in skipJoints: continue - + # Rename Joint name = None if prefix: ind = glTools.utils.stringUtils.alphaIndex(i,upper=True) if (i == (len(joints)-1)): ind = 'End' name = prefix+ind+'_jnt' - + # Duplicate Joint jnt = duplicateJoint(joints[i],name) - + # Parent Joint if not i: if not parent: @@ -342,14 +342,14 @@ def duplicateChain( startJoint, mc.connectAttr(dupChain[-1]+'.scale',jnt+'.inverseScale',f=True) except Exception, e: raise Exception('Error duplicating joint chain! Exception Msg: '+str(e)) - + # Append to list dupChain.append(jnt) - + # ================= # - Return Result - # ================= - + return dupChain def createFromPointList(ptList,orient=False,side='cn',part='chain',suffix='jnt'): @@ -368,14 +368,14 @@ def createFromPointList(ptList,orient=False,side='cn',part='chain',suffix='jnt') ''' # Clear selection mc.select(cl=True) - + # Create joint chain jntList = [] for i in range(len(ptList)): jnt = mc.joint(p=ptList[i],n=side+'_'+part+str(i+1)+'_'+suffix) if i and orient: mc.joint(jntList[-1],e=True,zso=True,oj='xyz',sao='yup') jntList.append(jnt) - + # Return result return jntList @@ -394,53 +394,53 @@ def orient(joint,aimAxis='x',upAxis='y',upVec=(0,1,0)): # Check joint if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') - + # Get joint child list childList = mc.listRelatives(joint,c=1) childJointList = mc.listRelatives(joint,c=1,type='joint',pa=True) - + # Unparent children if childList: childList = mc.parent(childList,w=True) - + # Orient joint if not childJointList: - + # End joint - Zero out joint orient mc.setAttr(joint+'.jo',0,0,0) - + else: - + # Get parent joint matrix pMat = OpenMaya.MMatrix() pJoint = mc.listRelatives(joint,p=True,pa=True) if pJoint: pMat = glTools.utils.matrix.getMatrix(pJoint[0]) - + # Calculate aim vector p1 = glTools.utils.base.getPosition(joint) p2 = glTools.utils.base.getPosition(childJointList[0]) aimVec = glTools.utils.mathUtils.offsetVector(p1,p2) - + # Build target matrix tMat = glTools.utils.matrix.buildRotation(aimVec,upVec,aimAxis,upAxis) - + # Calculate orient matrix oriMat = tMat * pMat.inverse() - + # Extract joint orient values rotOrder = mc.getAttr(joint+'.ro') oriRot = glTools.utils.matrix.getRotation(oriMat,rotOrder) - + # Reset joint rotation and orientation mc.setAttr(joint+'.r',0,0,0) mc.setAttr(joint+'.jo',oriRot[0],oriRot[1],oriRot[2]) - + # Reparent children if childList: mc.parent(childList,joint) def orient_old(joints,aimAxis=(1,0,0),upAxis=(0,1,0),upVec=(0,1,0)): ''' Orient joints based on user defined vectors - + @param joints: List of joints to orient @type joints: list @param aimAxis: Axis to be aligned down the length of the joint @@ -452,7 +452,7 @@ def orient_old(joints,aimAxis=(1,0,0),upAxis=(0,1,0),upVec=(0,1,0)): ''' if not joints: joints = [] for joint in joints: - + # Get child list childList = mc.listRelatives(joint,c=1) childJointList = mc.listRelatives(joint,c=1,type='joint',pa=True) @@ -461,27 +461,27 @@ def orient_old(joints,aimAxis=(1,0,0),upAxis=(0,1,0),upVec=(0,1,0)): continue # Unparent children childList = mc.parent(childList,w=True) - + # Reset joint rotation and orientation mc.setAttr(joint+'.r',0,0,0) mc.setAttr(joint+'.jo',0,0,0) mc.makeIdentity(joint,apply=True,t=1,r=1,s=1,n=0,jointOrient=True) - + # Move transform to joint parent = mc.listRelatives(joint,p=True,pa=True) trans = mc.group(em=True,n=joint+'_ORIENT') if parent: mc.parent(trans,parent[0]) mc.delete(mc.pointConstraint(joint,trans)) - + # Match rotation order mc.setAttr(trans+'.ro',mc.getAttr(joint+'.ro')) - + # Derive orientation mc.aimConstraint(childJointList[0],trans,aimVector=aimAxis,upVector=upAxis,worldUpType='vector',worldUpVector=upVec) rot = mc.getAttr(trans+'.r')[0] mc.setAttr(joint+'.jo',rot[0],rot[1],rot[2]) mc.delete(trans) - + # Reparent children mc.parent(childList,joint) @@ -501,30 +501,30 @@ def orientTo(joint,target): raise Exception('Target transform "'+target+'" does not exist!') if not glTools.utils.transform.isTransform(target): raise Exception('Target "'+target+'" is not a valid transform!') - + # Unparent children childList = mc.listRelatives(joint,c=1,type=['joint','transform']) if childList: childList = mc.parent(childList,w=True) - + # Get parent joint matrix pMat = OpenMaya.MMatrix() pJoint = mc.listRelatives(joint,p=True,pa=True) if pJoint: pMat = glTools.utils.matrix.getMatrix(pJoint[0]) - + # Get target matrix tMat = glTools.utils.matrix.getMatrix(target) - + # Calculate orient matrix oriMat = tMat * pMat.inverse() - + # Extract joint orient values rotOrder = mc.getAttr(joint+'.ro') oriRot = glTools.utils.matrix.getRotation(oriMat,rotOrder) - + # Reset joint rotation and orientation mc.setAttr(joint+'.r',0,0,0) mc.setAttr(joint+'.jo',oriRot[0],oriRot[1],oriRot[2]) - + # Reparent children if childList: mc.parent(childList,joint) @@ -543,29 +543,29 @@ def flipOrient(joint,target='',axis='x'): # Check joint if not isJoint(joint): raise Exception('Joint "'+joint+'" is not a valid joint') - + # Check target if not target: target = joint if not isJoint(target): raise Exception('Target "'+target+'" is not a valid joint!') - + # Get Joint Matrix jMat = glTools.utils.matrix.getMatrix(joint) - + # Build flip matrix flipMat = None if axis == 'x': flipMat = glTools.utils.matrix.buildMatrix(xAxis=(-1,0,0)) if axis == 'y': flipMat = glTools.utils.matrix.buildMatrix(yAxis=(0,-1,0)) if axis == 'z': flipMat = glTools.utils.matrix.buildMatrix(zAxis=(0,0,-1)) - + # Get Matrix Rotation tMat = OpenMaya.MTransformationMatrix(jMat * flipMat.inverse()) flipRot = tMat.eulerRotation() - + # Set Target Joint Orientation radToDeg = 180.0 / math.pi mc.setAttr(target+'.jo',flipRot.x*radToDeg,flipRot.y*radToDeg,flipRot.z*radToDeg) - + # Return Result return (flipRot.x*radToDeg,flipRot.y*radToDeg,flipRot.z*radToDeg) @@ -580,22 +580,22 @@ def mirrorOrient(joint,rollAxis): # Check Joint if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') - + # Check Roll Axis if not ['x','y','z'].count(rollAxis): raise Exception('Invalid roll axis "'+rollAxis+'"!') - + # UnParent Children childList = mc.listRelatives(joint,c=True) if childList: mc.parent(childList,w=True) - + # ReOrient Joint rt = [0,0,0] axisDict = {'x':0,'y':1,'z':2} rt[axisDict[rollAxis]] = 180 mc.setAttr(joint+'.r',*rt) mc.makeIdentity(joint,apply=True,t=True,r=True,s=True) - + # Reparent children if childList: mc.parent(childList,joint) @@ -608,7 +608,7 @@ def zeroOrient(joint): # Check joint if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!') - + # Zero Joint Orient mc.setAttr(joint+'.jointOrient',0,0,0) @@ -623,26 +623,26 @@ def connectInverseScale(joint,invScaleObj=None,force=False): # Check Joint if not isJoint(joint): raise Exception('Object '+joint+' is not a valid joint!') - + # Check Inverse Scale Object if not invScaleObj: - + # Get Joint Parent parent = mc.listRelatives(joint,p=True) or [] if parent and force: parent = mc.ls(parent, type='joint') or [] if not parent: print('No source object specified and no parent joint found for joint "'+joint+'"! Skipping...') return None - + # Set Inverse Scale Object invScaleObj = parent[0] - + # Connect inverseScale invScaleCon = mc.listConnections(joint+'.inverseScale',s=True,d=False) or [] if not invScaleObj in invScaleCon: try: mc.connectAttr(invScaleObj+'.scale',joint+'.inverseScale',f=True) except Exception, e: print('Error connecting "'+invScaleObj+'.scale" to "'+joint+'.inverseScale"! Exception msg: '+str(e)) - + # Return Result return invScaleObj+'.scale' @@ -673,23 +673,23 @@ def curveIntersectJoints( curve, # Check curve if not mc.objExists(curve): raise Exception('Curve object '+curve+' does not exist!') - + # Check intersect curve list for i in range(len(intersectCurveList)): if not mc.objExists(intersectCurveList[i]): raise Exception('Object '+intersectCurveList[i]+' is not a valid curve!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(curve) - + # Get curve Range minU = mc.getAttr(curve+'.minValue') maxU = mc.getAttr(curve+'.maxValue') - + # Initialize return list mc.select(cl=True) jointList = [] - + # Create Base Joint if jointAtBase: # Get curve point position @@ -699,7 +699,7 @@ def curveIntersectJoints( curve, jnt = prefix+nameUtil.delineator+nameUtil.subPart['joint']+ind+nameUtil.delineator+nameUtil.node['joint'] jnt = mc.joint(p=pos,n=jnt) jointList.append(jnt) - + # Create joints at curve intersections for n in range(len(intersectCurveList)): # Get string index @@ -709,7 +709,7 @@ def curveIntersectJoints( curve, uList = mc.curveIntersect(curve,intersectCurveList[n],ud=useDirection,d=intersectDirection) if not uList: continue uList = uList.split(' ') - + # Create joints for u in range(len(uList)/2): # Get curve point position @@ -718,7 +718,7 @@ def curveIntersectJoints( curve, jnt = prefix+nameUtil.delineator+nameUtil.subPart['joint']+ind+nameUtil.delineator+nameUtil.node['joint'] jnt = mc.joint(p=pos,n=jnt) jointList.append(jnt) - + # Create Tip Joint if jointAtTip: # Get string index @@ -730,7 +730,7 @@ def curveIntersectJoints( curve, jnt = prefix+nameUtil.delineator+nameUtil.subPart['joint']+ind+nameUtil.delineator+nameUtil.node['joint'] jnt = mc.joint(p=pos,n=jnt) jointList.append(jnt) - + # Return result return jointList diff --git a/utils/kdTree.py b/utils/kdTree.py index ec84abd..89f0f14 100644 --- a/utils/kdTree.py +++ b/utils/kdTree.py @@ -16,7 +16,7 @@ class _Node(list): Simple wrapper around tree nodes - mainly to make the code a little more readable (although members are generally accessed via indices because its faster) ''' - + @property def point( self ): return self[0] @@ -41,7 +41,7 @@ def __init__( self, data=() ): ''' ''' self.performPopulate( data ) - + def performPopulate( self, data ): ''' ''' @@ -67,16 +67,16 @@ def populateTree( points, depth ): return node self.root = populateTree( data, 0 ) - + def getClosest( self, queryPoint, returnDistances=False ): ''' Returns the closest point in the tree to the given point NOTE: see the docs for getWithin for info on the returnDistances arg ''' dimension = self.DIMENSION - + distBest = ((self.root[0][0]-queryPoint[0]) ** 2) + ((self.root[0][1]-queryPoint[1]) ** 2) + ((self.root[0][2]-queryPoint[2]) ** 2) - + #distBest = (self.root[0] - queryPoint).get_magnitude() ** 2 bestList = [ (distBest, self.root[0]) ] @@ -154,7 +154,7 @@ def search( node, depth ): ''' nodePoint = node[0] axis = depth % dimension - + if queryPoint[axis] < nodePoint[axis]: nearNode = node[1] farNode = node[2] @@ -180,17 +180,17 @@ def search( node, depth ): if farNode is not None: if (nodePoint[ axis ] - queryPoint[ axis ])**2 < sqThreshold: search( farNode, depth+1 ) - + search( self.root, 0 ) - + # The best is guaranteed to be at the head of the list # But consequent points might be out of order - so order them now matches.sort() - + # Return Result if returnDistances: return matches return [ m[1] for m in matches ] - + def getDistanceRatioWeightedVector( self, queryPoint, ratio=2, returnDistances=False ): ''' Finds the closest point to the queryPoint in the tree and returns all points within a distance @@ -204,21 +204,21 @@ def getDistanceRatioWeightedVector( self, queryPoint, ratio=2, returnDistances=F ''' # Check Ratio assert ratio > 1 - + # Get Closest closestDist, closest = self.getClosest( queryPoint, returnDistances=True ) - + # Check Coincident if closestDist == 0: if returnDistances: return [ (0, closest) ] else: return [ closest ] - + # Get Dist / Max Dist closestDist = sqrt( closestDist ) maxDist = closestDist * ratio - + # Return Result return self.getWithin( queryPoint, maxDist, returnDistances=returnDistances ) diff --git a/utils/kdTreeMesh.py b/utils/kdTreeMesh.py index 13ea7ee..dae536c 100644 --- a/utils/kdTreeMesh.py +++ b/utils/kdTreeMesh.py @@ -21,14 +21,14 @@ class _Node(list): Simple wrapper around tree nodes - mainly to make the code a little more readable (although members are generally accessed via indices because its faster) ''' - + @property def point( self ): return self[0] @property def left( self ): return self[1] @property def right( self ): return self[2] - + def is_leaf( self ): return self[1] is None and self[2] is None @@ -43,23 +43,23 @@ def __init__( self, mesh ): ''' ''' self.performPopulate( mesh ) - + def performPopulate( self, mesh ): ''' ''' dimension = self.DIMENSION - + # Build Mesh Pt List meshFn = glTools.utils.mesh.getMeshFn(mesh) meshPtUtil = OpenMaya.MScriptUtil() meshPts = meshFn.getRawPoints() - + meshPtList = [] for i in range(meshFn.numVertices()): pt = [ meshPtUtil.getFloatArrayItem(meshPts,i*3+0), meshPtUtil.getFloatArrayItem(meshPts,i*3+1), meshPtUtil.getFloatArrayItem(meshPts,i*3+2) ] - + meshPtList.append(Pt(pt,i)) def populateTree( points, depth ): @@ -82,14 +82,14 @@ def populateTree( points, depth ): return node self.root = populateTree( meshPtList, 0 ) - + def getClosest( self, queryPoint, returnDistances=False ): ''' Returns the closest point in the tree to the given point NOTE: see the docs for getWithin for info on the returnDistances arg ''' dimension = self.DIMENSION - + distBest = ((self.root[0].pnt[0]-queryPoint[0]) ** 2) + ((self.root[0].pnt[1]-queryPoint[1]) ** 2) + ((self.root[0].pnt[2]-queryPoint[2]) ** 2) bestList = [ (distBest, self.root[0]) ] @@ -142,7 +142,7 @@ def search( node, depth ): return bestList[0] return bestList[0][1] - + def getWithin( self, queryPoint, threshold=1e-6, returnDistances=False ): ''' Returns all points that fall within the radius of the queryPoint within the tree. @@ -168,7 +168,7 @@ def search( node, depth ): ''' nodePoint = node[0].pnt axis = depth % dimension - + if queryPoint[axis] < nodePoint[axis]: nearNode = node[1] farNode = node[2] @@ -194,17 +194,17 @@ def search( node, depth ): if farNode is not None: if (nodePoint[ axis ] - queryPoint[ axis ])**2 < sqThreshold: search( farNode, depth+1 ) - + search( self.root, 0 ) - + # The best is guaranteed to be at the head of the list # But consequent points might be out of order - so order them now matches.sort() - + # Return Result if returnDistances: return matches return [ m[1] for m in matches ] - + def getDistanceRatioWeightedVector( self, queryPoint, ratio=2, returnDistances=False ): ''' Finds the closest point to the queryPoint in the tree and returns all points within a distance @@ -218,21 +218,21 @@ def getDistanceRatioWeightedVector( self, queryPoint, ratio=2, returnDistances=F ''' # Check Ratio assert ratio > 1 - + # Get Closest closestDist, closest = self.getClosest( queryPoint, returnDistances=True ) - + # Check Coincident if closestDist == 0: if returnDistances: return [ (0, closest) ] else: return [ closest ] - + # Get Dist / Max Dist closestDist = sqrt( closestDist ) maxDist = closestDist * ratio - + # Return Result return self.getWithin( queryPoint, maxDist, returnDistances=returnDistances ) diff --git a/utils/layer.py b/utils/layer.py index ffe273a..2d34a93 100644 --- a/utils/layer.py +++ b/utils/layer.py @@ -51,7 +51,7 @@ def memberList(layer,objectList=True): # Check Layer if not isLayer(layer): raise Excpetion('Object "'+layer+'" is not a valid layer type!') - + # Get Member List members = [] if isDisplayLayer(layer): @@ -60,13 +60,13 @@ def memberList(layer,objectList=True): members = mc.listConnections(layer+'.renderInfo',s=False,d=True,sh=True) if isAnimLayer(layer): members = mc.listConnections(layer+'.dagSetMembers',s=True,d=False,sh=True) - + # Get List of Objects from Member List if objectList: members = mc.ls(members,o=True) - + # Format Result if not members: members = [] members = list(set(members)) - + # Return Result return members diff --git a/utils/lidRails.py b/utils/lidRails.py index e1c6863..04a191e 100644 --- a/utils/lidRails.py +++ b/utils/lidRails.py @@ -21,32 +21,32 @@ def lidSurface_create(curveList,spans=4,attributeObject='',collisionObject='',si @param prefix: Name prefix for all created nodes @type prefix: str ''' - + # NameUtil nameUtil = gLib.common.namingConvention.NamingConvention() # Check prefix if not prefix: prefix = nameUtil.stripSuffix(crvList[0],'_') # Check side if not side: side = prefix.split('_')[0] - + # Check curveList for crv in curveList: if not mc.objExists(crv): raise UserInputError('Curve "'+crv+'" does not exist!') if not gLib.rig.utilities.curve.isCurve(crv): raise UserInputError('Object "'+crv+'" is not a valid nurbs curve!') - + # Create lidSurface node lidSurface = nameUtil.appendName(prefix,nameUtil.node['lidSurface']) lidSurface = mc.createNode('lidSurface',n=lidSurface) - + # Set spans mc.setAttr(lidSurface+'.spans',spans) - + # Connect curevList for i in range(len(curveList)): mc.connectAttr(curveList[i]+'.worldSpace',lidSurface+'.inputCurve['+str(i)+']',f=True) - + # Check Attribute Object if mc.objExists(attributeObject): # Check attributes @@ -60,24 +60,24 @@ def lidSurface_create(curveList,spans=4,attributeObject='',collisionObject='',si mc.connectAttr(attributeObject+'.'+side+'TopLid',lidSurface+'.top',f=True) mc.connectAttr(attributeObject+'.'+side+'LowLid',lidSurface+'.bottom',f=True) mc.connectAttr(attributeObject+'.'+side+'LidMeet',lidSurface+'.split',f=True) - + # Check Collision Object if mc.objExists(collisionObject): if not gLib.rig.utilities.surface.isSurface(collisionObject): raise UserInputError('Collision object "'+crv+'" is not a valid nurbs surface!') #mc.connectAttr(collisionObject+'.worldMatrix[0]',lidSurface+'.collisionMatrix',f=True) mc.connectAttr(collisionObject+'.worldSpace',lidSurface+'.collisionGeometry',f=True) - + # Create lid surfaces topLid_srf = nameUtil.appendName(prefix+'_tp01',nameUtil.node['surface']) topLid_srf = mc.nurbsPlane(ch=0,n=topLid_srf)[0] lowLid_srf = nameUtil.appendName(prefix+'_lw01',nameUtil.node['surface']) lowLid_srf = mc.nurbsPlane(ch=0,n=lowLid_srf)[0] - + # Attach lid surfaces mc.connectAttr(lidSurface+'.topLidSurface',topLid_srf+'.create',f=True) mc.connectAttr(lidSurface+'.lowLidSurface',lowLid_srf+'.create',f=True) - + # Return result return (topLid_srf,lowLid_srf) @@ -94,12 +94,12 @@ def setup_threeCtrl(lf_lidrails,rt_lidrails): lf_dn = ['lf_lid01_dn01_ccc','lf_lid01_dn02_ccc','lf_lid01_dn03_ccc'] rt_up = ['rt_lid01_tp01_ccc','rt_lid01_tp02_ccc','rt_lid01_tp03_ccc'] rt_dn = ['rt_lid01_dn01_ccc','rt_lid01_dn02_ccc','rt_lid01_dn03_ccc'] - + # Connect lidRails ramps to lid profile controls - + #======== # lf_up - + # inner mc.connectAttr(lf_up[0]+'.tx',lf_lidrails+'.offsettop[0].offsettop_Position',f=True) mc.connectAttr(lf_up[0]+'.ty',lf_lidrails+'.offsettop[0].offsettop_FloatValue',f=True) @@ -115,10 +115,10 @@ def setup_threeCtrl(lf_lidrails,rt_lidrails): mc.setAttr(lf_lid01_uo01_adn+'.input2',1.0) mc.connectAttr(lf_lid01_uo01_adn+'.output',lf_lidrails+'.offsettop[2].offsettop_Position',f=True) mc.connectAttr(lf_up[2]+'.ty',lf_lidrails+'.offsettop[2].offsettop_FloatValue',f=True) - + #======== # lf_dn - + # Reverse node lf_dn_rvn = mc.createNode('reverse',n='lf_lid01_dn01_rv') # inner @@ -139,7 +139,7 @@ def setup_threeCtrl(lf_lidrails,rt_lidrails): mc.connectAttr(lf_lid01_do01_adn+'.output',lf_lidrails+'.offsetbottom[2].offsetbottom_Position',f=True) mc.connectAttr(lf_dn[2]+'.ty',lf_dn_rvn+'.inputZ',f=True) mc.connectAttr(lf_dn_rvn+'.outputZ',lf_lidrails+'.offsetbottom[2].offsetbottom_FloatValue',f=True) - + #======== # rt_up @@ -164,10 +164,10 @@ def setup_threeCtrl(lf_lidrails,rt_lidrails): mc.setAttr(rt_lid01_uo_mdn+'.input2',-1.0) mc.connectAttr(rt_lid01_uo_mdn+'.output',rt_lidrails+'.offsettop[0].offsettop_Position',f=True) mc.connectAttr(rt_up[2]+'.ty',rt_lidrails+'.offsettop[0].offsettop_FloatValue',f=True) - + #======== # rt_dn - + # Reverse node rt_dn_rvn = mc.createNode('reverse',n='rt_lid01_dn01_rv') # inner @@ -207,11 +207,11 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): lf_dn = ['lf_lid01_dn01_ccc','lf_lid01_dn02_ccc','lf_lid01_dn03_ccc','lf_lid01_dn04_ccc'] rt_up = ['rt_lid01_tp01_ccc','rt_lid01_tp02_ccc','rt_lid01_tp03_ccc','rt_lid01_tp04_ccc'] rt_dn = ['rt_lid01_dn01_ccc','rt_lid01_dn02_ccc','rt_lid01_dn03_ccc','rt_lid01_dn04_ccc'] - + # Connect lidRails ramps to lid profile controls - + # lf_up ========= - + # inner mc.connectAttr(lf_up[0]+'.tx',lf_lidrails+'.offsettop[0].offsettop_Position',f=True) mc.connectAttr(lf_up[0]+'.ty',lf_lidrails+'.offsettop[0].offsettop_FloatValue',f=True) @@ -233,9 +233,9 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): mc.setAttr(lf_lid01_uo01_adn+'.input2',1.0) mc.connectAttr(lf_lid01_uo01_adn+'.output',lf_lidrails+'.offsettop[3].offsettop_Position',f=True) mc.connectAttr(lf_up[3]+'.ty',lf_lidrails+'.offsettop[3].offsettop_FloatValue',f=True) - + # lf_dn ========= - + lf_dn_rvn = mc.createNode('reverse',n='lf_lid01_dn01_rv') lf_dn02_rvn = mc.createNode('reverse',n='lf_lid01_dn02_rv') # inner @@ -263,9 +263,9 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): mc.connectAttr(lf_lid01_do01_adn+'.output',lf_lidrails+'.offsetbottom[3].offsetbottom_Position',f=True) mc.connectAttr(lf_dn[3]+'.ty',lf_dn02_rvn+'.inputY') mc.connectAttr(lf_dn02_rvn+'.outputY',lf_lidrails+'.offsetbottom[3].offsetbottom_FloatValue',f=True) - + # rt_up ========= - + # inner rt_lid01_ui01_asn = mc.createNode('plusMinusAverage',n='rt_lid01_ui01_asn') mc.setAttr(rt_lid01_ui01_asn+'.input1D[0]',1.0) @@ -281,7 +281,7 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): mc.setAttr(rt_lid01_um01_adn+'.input2',0.333) mc.connectAttr(rt_lid01_um01_adn+'.output',rt_lidrails+'.offsettop[2].offsettop_Position',f=True) mc.connectAttr(rt_up[2]+'.ty',rt_lidrails+'.offsettop[2].offsettop_FloatValue',f=True) - + # mid - outer rt_lid01_um02_mdn = mc.createNode('multDoubleLinear',n='rt_lid01_um02_mdn') rt_lid01_um02_adn = mc.createNode('addDoubleLinear',n='rt_lid01_um02_adn') @@ -291,16 +291,16 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): mc.setAttr(rt_lid01_um02_adn+'.input2',0.666) mc.connectAttr(rt_lid01_um02_adn+'.output',rt_lidrails+'.offsettop[1].offsettop_Position',f=True) mc.connectAttr(rt_up[1]+'.ty',rt_lidrails+'.offsettop[1].offsettop_FloatValue',f=True) - + # outer rt_lid01_uo_mdn = mc.createNode('multDoubleLinear',n='rt_lid01_uo_mdn') mc.connectAttr(rt_up[3]+'.tx',rt_lid01_uo_mdn+'.input1',f=True) mc.setAttr(rt_lid01_uo_mdn+'.input2',-1.0) mc.connectAttr(rt_lid01_uo_mdn+'.output',rt_lidrails+'.offsettop[0].offsettop_Position',f=True) mc.connectAttr(rt_up[3]+'.ty',rt_lidrails+'.offsettop[0].offsettop_FloatValue',f=True) - + # rt_dn ========= - + rt_dn_rvn = mc.createNode('reverse',n='rt_lid01_dn01_rv') rt_dn02_rvn = mc.createNode('reverse',n='rt_lid01_dn02_rv') # inner diff --git a/utils/lidSurface.py b/utils/lidSurface.py index 2a231fc..818489e 100644 --- a/utils/lidSurface.py +++ b/utils/lidSurface.py @@ -37,32 +37,32 @@ def lidSurface_create(curveList,spans=4,attributeObject='',collisionObject='',si topAttr = 'topLid' lowAttr = 'lowLid' splitAttr = 'lidCentre' - + # NameUtil nameUtil = glTools.tools.namingConvention.NamingConvention() # Check prefix if not prefix: prefix = nameUtil.stripSuffix(crvList[0],'_') # Check side if not side: side = prefix.split('_')[0] - + # Check curveList for crv in curveList: if not mc.objExists(crv): raise UserInputError('Curve "'+crv+'" does not exist!') if not glTools.utils.curve.isCurve(crv): raise UserInputError('Object "'+crv+'" is not a valid nurbs curve!') - + # Create lidSurface node lidSurface = prefix+'_lidSurface' lidSurface = mc.createNode('lidSurface',n=lidSurface) - + # Set spans mc.setAttr(lidSurface+'.spans',spans) - + # Connect curevList for i in range(len(curveList)): mc.connectAttr(curveList[i]+'.worldSpace',lidSurface+'.inputCurve['+str(i)+']',f=True) - + # Check Attribute Object if mc.objExists(attributeObject): # Check attributes @@ -76,23 +76,23 @@ def lidSurface_create(curveList,spans=4,attributeObject='',collisionObject='',si mc.connectAttr(attributeObject+'.'+topAttr,lidSurface+'.top',f=True) mc.connectAttr(attributeObject+'.'+lowAttr,lidSurface+'.bottom',f=True) mc.connectAttr(attributeObject+'.'+splitAttr,lidSurface+'.split',f=True) - + # Check Collision Object if mc.objExists(collisionObject): if not glTools.utils.surface.isSurface(collisionObject): raise UserInputError('Collision object "'+crv+'" is not a valid nurbs surface!') mc.connectAttr(collisionObject+'.worldSpace',lidSurface+'.collisionGeometry',f=True) - + # Create lid surfaces topLid_srf = prefix+'_tp01_surface' topLid_srf = mc.nurbsPlane(ch=0,n=topLid_srf)[0] lowLid_srf = prefix+'_lw01_surface' lowLid_srf = mc.nurbsPlane(ch=0,n=lowLid_srf)[0] - + # Attach lid surfaces mc.connectAttr(lidSurface+'.topLidSurface',topLid_srf+'.create',f=True) mc.connectAttr(lidSurface+'.lowLidSurface',lowLid_srf+'.create',f=True) - + # Return result return (topLid_srf,lowLid_srf) @@ -109,12 +109,12 @@ def setup_threeCtrl(lf_lidrails,rt_lidrails): lf_dn = ['lf_lid01_dn01_ccc','lf_lid01_dn02_ccc','lf_lid01_dn03_ccc'] rt_up = ['rt_lid01_tp01_ccc','rt_lid01_tp02_ccc','rt_lid01_tp03_ccc'] rt_dn = ['rt_lid01_dn01_ccc','rt_lid01_dn02_ccc','rt_lid01_dn03_ccc'] - + # Connect lidRails ramps to lid profile controls - + #======== # lf_up - + # inner mc.connectAttr(lf_up[0]+'.tx',lf_lidrails+'.offsettop[0].offsettop_Position',f=True) mc.connectAttr(lf_up[0]+'.ty',lf_lidrails+'.offsettop[0].offsettop_FloatValue',f=True) @@ -130,10 +130,10 @@ def setup_threeCtrl(lf_lidrails,rt_lidrails): mc.setAttr(lf_lid01_uo01_adn+'.input2',1.0) mc.connectAttr(lf_lid01_uo01_adn+'.output',lf_lidrails+'.offsettop[2].offsettop_Position',f=True) mc.connectAttr(lf_up[2]+'.ty',lf_lidrails+'.offsettop[2].offsettop_FloatValue',f=True) - + #======== # lf_dn - + # Reverse node lf_dn_rvn = mc.createNode('reverse',n='lf_lid01_dn01_reverse') # inner @@ -154,7 +154,7 @@ def setup_threeCtrl(lf_lidrails,rt_lidrails): mc.connectAttr(lf_lid01_do01_adn+'.output',lf_lidrails+'.offsetbottom[2].offsetbottom_Position',f=True) mc.connectAttr(lf_dn[2]+'.ty',lf_dn_rvn+'.inputZ',f=True) mc.connectAttr(lf_dn_rvn+'.outputZ',lf_lidrails+'.offsetbottom[2].offsetbottom_FloatValue',f=True) - + #======== # rt_up @@ -180,10 +180,10 @@ def setup_threeCtrl(lf_lidrails,rt_lidrails): mc.setAttr(rt_lid01_uo_mdn+'.input2',-1.0) mc.connectAttr(rt_lid01_uo_mdn+'.output',rt_lidrails+'.offsettop[0].offsettop_Position',f=True) mc.connectAttr(rt_up[2]+'.ty',rt_lidrails+'.offsettop[0].offsettop_FloatValue',f=True) - + #======== # rt_dn - + # Reverse node rt_dn_rvn = mc.createNode('reverse',n='rt_lid01_dn01_reverse') # inner @@ -223,11 +223,11 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): lf_dn = ['L_lowerLid1_ctrl','L_lowerLid2_ctrl','L_lowerLid3_ctrl','L_lowerLid4_ctrl'] rt_up = ['R_upperLid1_ctrl','R_upperLid2_ctrl','R_upperLid3_ctrl','R_upperLid4_ctrl'] rt_dn = ['R_lowerLid1_ctrl','R_lowerLid2_ctrl','R_lowerLid3_ctrl','R_lowerLid4_ctrl'] - + # Connect lidRails ramps to lid profile controls - + # lf_up ========= - + # inner mc.connectAttr(lf_up[0]+'.tx',lf_lidrails+'.offsettop[0].offsettop_Position',f=True) mc.connectAttr(lf_up[0]+'.ty',lf_lidrails+'.offsettop[0].offsettop_FloatValue',f=True) @@ -249,9 +249,9 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): mc.setAttr(lf_lid01_uo01_adn+'.input2',1.0) mc.connectAttr(lf_lid01_uo01_adn+'.output',lf_lidrails+'.offsettop[3].offsettop_Position',f=True) mc.connectAttr(lf_up[3]+'.ty',lf_lidrails+'.offsettop[3].offsettop_FloatValue',f=True) - + # lf_dn ========= - + lf_dn_rvn = mc.createNode('reverse',n='lf_lid01_dn01_reverse') lf_dn02_rvn = mc.createNode('reverse',n='lf_lid01_dn02_reverse') # inner @@ -279,9 +279,9 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): mc.connectAttr(lf_lid01_do01_adn+'.output',lf_lidrails+'.offsetbottom[3].offsetbottom_Position',f=True) mc.connectAttr(lf_dn[3]+'.ty',lf_dn02_rvn+'.inputY') mc.connectAttr(lf_dn02_rvn+'.outputY',lf_lidrails+'.offsetbottom[3].offsetbottom_FloatValue',f=True) - + # rt_up ========= - + # inner rt_lid01_ui01_asn = mc.createNode('plusMinusAverage',n='rt_lid01_ui01_plusMinusAverage') mc.setAttr(rt_lid01_ui01_asn+'.input1D[0]',1.0) @@ -297,7 +297,7 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): mc.setAttr(rt_lid01_um01_adn+'.input2',0.333) mc.connectAttr(rt_lid01_um01_adn+'.output',rt_lidrails+'.offsettop[2].offsettop_Position',f=True) mc.connectAttr(rt_up[2]+'.ty',rt_lidrails+'.offsettop[2].offsettop_FloatValue',f=True) - + # mid - outer rt_lid01_um02_mdn = mc.createNode('multDoubleLinear',n='rt_lid01_um02_multDoubleLinear') rt_lid01_um02_adn = mc.createNode('addDoubleLinear',n='rt_lid01_um02_addDoubleLinear') @@ -307,16 +307,16 @@ def setup_fourCtrl(lf_lidrails,rt_lidrails): mc.setAttr(rt_lid01_um02_adn+'.input2',0.666) mc.connectAttr(rt_lid01_um02_adn+'.output',rt_lidrails+'.offsettop[1].offsettop_Position',f=True) mc.connectAttr(rt_up[1]+'.ty',rt_lidrails+'.offsettop[1].offsettop_FloatValue',f=True) - + # outer rt_lid01_uo_mdn = mc.createNode('multDoubleLinear',n='rt_lid01_uo_multDoubleLinear') mc.connectAttr(rt_up[3]+'.tx',rt_lid01_uo_mdn+'.input1',f=True) mc.setAttr(rt_lid01_uo_mdn+'.input2',-1.0) mc.connectAttr(rt_lid01_uo_mdn+'.output',rt_lidrails+'.offsettop[0].offsettop_Position',f=True) mc.connectAttr(rt_up[3]+'.ty',rt_lidrails+'.offsettop[0].offsettop_FloatValue',f=True) - + # rt_dn ========= - + rt_dn_rvn = mc.createNode('reverse',n='rt_lid01_dn01_reverse') rt_dn02_rvn = mc.createNode('reverse',n='rt_lid01_dn02_reverse') # inner diff --git a/utils/log.py b/utils/log.py index 8545c61..0d85649 100644 --- a/utils/log.py +++ b/utils/log.py @@ -8,11 +8,11 @@ def openLog(logDir,logName,mode='a'): ''' # Check directory if not os.path.isdir(logDir): os.makedirs(logDir) - + # Open file for writing logFile = logDir+'/'+logName f = open(logFile,mode) - + # Add log header file = mc.file(q=True,sn=True) dt = datetime.datetime.now() @@ -20,23 +20,23 @@ def openLog(logDir,logName,mode='a'): f.write('file: '+file+'\n') f.write('time: '+str(dt)+'\n') f.write('=========\n\n') - + # Return log file handle return f - + def printLog(logDir,logName,mode='a',logLines=[]): ''' ''' # Check directory if not os.path.isdir(logDir): os.makedirs(logDir) - + # Open file for writing logFile = logDir+'/'+logName f = open(logFile,mode) - + # Print progress print('Printing to log file "'+logFile+'"!') - + # Add log header file = mc.file(q=True,sn=True) dt = datetime.datetime.now() @@ -44,13 +44,13 @@ def printLog(logDir,logName,mode='a',logLines=[]): f.write('file: '+file+'\n') f.write('time: '+str(dt)+'\n') f.write('=========\n\n') - + # Add lines to log for line in logLines: f.write(line+'\n') - + # Close file handle f.close() - + # Return log file handle return logFile @@ -60,11 +60,11 @@ def clearLog(logDir,logName): # Check directory if not os.path.isdir(logDir): raise Exception('Log directory "'+logDir+'" does not exist!') - + # Clear log file logFile = logDir+'/'+logName f = open(logFile,'w') f.write('') - + # Close file handle f.close() diff --git a/utils/massive.py b/utils/massive.py index 3972cb4..51b7322 100644 --- a/utils/massive.py +++ b/utils/massive.py @@ -32,42 +32,42 @@ def loadMatrixCache(cacheFile,agent='',targetNS=''): ''' # Initialize Frame No. frame = 0 - + # Check NS if targetNS: targetNS+=':' - + # Open File f = open(cacheFile,'r') lines = f.readlines() - + # Load Cache for line in lines: - + # Get Frame if line.startswith('# frame'): frame = line.split(' ')[-1] print frame continue - + # Get Matrix seg = line.split(' ')[0] mat = ast.literal_eval(line.replace(seg+' ','')) matrix = buildMatrix(mat) - + # Check Agent if agent and seg == 'Agent': seg = agent - + # =================== # - Get Translation - # =================== - + pos = OpenMaya.MTransformationMatrix(matrix).getTranslation(OpenMaya.MSpace.kTransform) t = [pos[0],pos[1],pos[2]] - + # ================ # - Get Rotation - # ================ - + # Factor in Joint Orientation if mc.objectType(seg) == 'joint': segObj = glTools.utils.base.getMObject(seg) @@ -75,27 +75,27 @@ def loadMatrixCache(cacheFile,agent='',targetNS=''): segOri = OpenMaya.MQuaternion() segFn.getOrientation(segOri) matrix *= segOri.asMatrix().inverse() - + # Get Rotation rot = OpenMaya.MTransformationMatrix(matrix).eulerRotation() rad = mm.eval('rad_to_deg(1)') r = [rot.x*rad,rot.y*rad,rot.z*rad] - + # ================= # - Set Keyframes - # ================= - + mc.setKeyframe(targetNS+seg,at='tx',v=t[0],t=float(frame)) mc.setKeyframe(targetNS+seg,at='ty',v=t[1],t=float(frame)) mc.setKeyframe(targetNS+seg,at='tz',v=t[2],t=float(frame)) mc.setKeyframe(targetNS+seg,at='rx',v=r[0],t=float(frame)) mc.setKeyframe(targetNS+seg,at='ry',v=r[1],t=float(frame)) mc.setKeyframe(targetNS+seg,at='rz',v=r[2],t=float(frame)) - + # ============== # - Close File - # ============== - + f.close() def loadAgentData(dataFile): @@ -103,35 +103,35 @@ def loadAgentData(dataFile): ''' # Get Radian Conversion Factor rad = mm.eval('rad_to_deg(1)') - + # Open File f = open(dataFile,'r') lines = f.readlines() - + # Build Matrices agent_matrix = OpenMaya.MTransformationMatrix(buildMatrix(ast.literal_eval(lines[0]))) segment_matrix = OpenMaya.MTransformationMatrix(buildMatrix(ast.literal_eval(lines[1]))) - + # AGENT a = mc.spaceLocator(n='agent')[0] b = mc.spaceLocator(n='Hips')[0] mc.parent(b,a) - + # Agent Position pos = agent_matrix.getTranslation(OpenMaya.MSpace.kTransform) t = [pos[0],pos[1],pos[2]] mc.setAttr(a+'.t',*t) - + # Agent Rotation rot = agent_matrix.eulerRotation() r = [rot.x*rad,rot.y*rad,rot.z*rad] mc.setAttr(a+'.r',*r) - + # Hip Position pos = segment_matrix.getTranslation(OpenMaya.MSpace.kTransform) t = [pos[0],pos[1],pos[2]] mc.setAttr(b+'.t',*t) - + # Return Result return [a,b] @@ -140,26 +140,26 @@ def printAgentData(dataFile): ''' # Get Radian Conversion Factor rad = mm.eval('rad_to_deg(1)') - + # Open File f = open(dataFile,'r') lines = f.readlines() - + # Build Matrices agent_matrix = OpenMaya.MTransformationMatrix(buildMatrix(ast.literal_eval(lines[0]))) segment_matrix = OpenMaya.MTransformationMatrix(buildMatrix(ast.literal_eval(lines[1]))) - + # AGENT - + # Position pos = agent_matrix.getTranslation(OpenMaya.MSpace.kTransform) t = [pos[0],pos[1],pos[2]] print('Agent Translate: '+str(t)) - + rot = agent_matrix.eulerRotation() r = [rot.x*rad,rot.y*rad,rot.z*rad] print('Agent Rotate: '+str(r)) - + scaleUtil = OpenMaya.MScriptUtil() scaleUtil.createFromDouble(0,0,0) scalePtr = scaleUtil.asDoublePtr() @@ -168,18 +168,18 @@ def printAgentData(dataFile): OpenMaya.MScriptUtil().getDoubleArrayItem(scalePtr,1), OpenMaya.MScriptUtil().getDoubleArrayItem(scalePtr,2) ] print('Agent Scale: '+str(s)) - + # SEGMENT - + # Position pos = segment_matrix.getTranslation(OpenMaya.MSpace.kTransform) t = [pos[0],pos[1],pos[2]] print('Segment Translate: '+str(t)) - + rot = segment_matrix.eulerRotation() r = [rot.x*rad,rot.y*rad,rot.z*rad] print('Segment Rotate: '+str(r)) - + scaleUtil = OpenMaya.MScriptUtil() scaleUtil.createFromDouble(0,0,0) scalePtr = scaleUtil.asDoublePtr() @@ -188,5 +188,5 @@ def printAgentData(dataFile): OpenMaya.MScriptUtil().getDoubleArrayItem(scalePtr,1), OpenMaya.MScriptUtil().getDoubleArrayItem(scalePtr,2) ] print('Segment Scale: '+str(s)) - - + + diff --git a/utils/mathUtils.py b/utils/mathUtils.py index 1fcdf5a..ddb7e5c 100644 --- a/utils/mathUtils.py +++ b/utils/mathUtils.py @@ -106,15 +106,15 @@ def closestPointOnLine(pt,lineA,lineB,clampSegment=False): # Get Vector Offsets ptOffset = offsetVector(lineA,pt) lineOffset = offsetVector(lineA,lineB) - + # Vector Comparison dot = dotProduct(ptOffset,lineOffset) - + # Clamp Segment if clampSegment: if dot < 0.0: return lineA if dot > 1.0: return lineB - + # Project Vector return [lineA[0]+(lineOffset[0]*dot),lineA[1]+(lineOffset[1]*dot),lineA[2]+(lineOffset[2]*dot)] @@ -157,7 +157,7 @@ def distributeValue(samples,spacing=1.0,rangeStart=0.0,rangeEnd=1.0): vList = [rangeStart] vDist = abs(rangeEnd - rangeStart) unit = 1.0 - + # Find the Unit Distance factor = 1.0 for i in range(samples-2): @@ -165,17 +165,17 @@ def distributeValue(samples,spacing=1.0,rangeStart=0.0,rangeEnd=1.0): factor *= spacing unit = vDist/unit totalUnit = unit - + # Build Sample List for i in range(samples-2): multFactor = totalUnit/vDist vList.append(rangeStart-((rangeStart - rangeEnd) * multFactor)) unit *= spacing totalUnit += unit - + # Append Final Sample vList.append(rangeEnd) - + # Return Result return vList @@ -194,15 +194,15 @@ def inverseDistanceWeight1D(valueArray,sampleValue,valueDomain=(0,1),cycleValue= # Initialize method varialbles distArray = [] totalInvDist = 0.0 - + # Initialize weightArray wtArray = [] - + # Calculate inverse distance weight for v in range(len(valueArray)): # Calculate distance dist = abs(sampleValue - valueArray[v]) - + # Check cycle value if cycleValue: valueDomainLen = valueDomain[1]-valueDomain[0] @@ -210,17 +210,17 @@ def inverseDistanceWeight1D(valueArray,sampleValue,valueDomain=(0,1),cycleValue= rCycDist = abs(sampleValue - (valueArray[v] - valueDomainLen)) if fCycDist < dist: dist = fCycDist if rCycDist < dist: dist = rCycDist - + # Check zero distance if dist < 0.00001: dist = 0.00001 - + # Append distance distArray.append(dist) totalInvDist += 1.0/dist - + # Normalize value weights wtArray = [(1.0/d)/totalInvDist for d in distArray] - + # Return result return wtArray @@ -235,24 +235,24 @@ def inverseDistanceWeight3D(pointArray,samplePoint): # Initialize Method Variables distArray = [] totalInvDist = 0.0 - + # Initialize weightArray wtArray = [] - + # Calculate inverse distance weight for i in range(len(pointArray)): # Calculate Distance dist = distanceBetween(samplePoint, pointArray[i]) - + # Check Zero Distance if dist < 0.00001: dist = 0.00001 - + # Append distance distArray.append(dist) totalInvDist += 1.0/dist - + # Normalize Value Weights wtArray = [(1.0/d)/totalInvDist for d in distArray] - + # Return Result return wtArray diff --git a/utils/matrix.py b/utils/matrix.py index 27e732c..b45a701 100644 --- a/utils/matrix.py +++ b/utils/matrix.py @@ -18,19 +18,19 @@ def getMatrix(transform,local=False,time=None): # Check transform if not mc.objExists(transform): raise Exception('Object "'+transform+'" does not exist!!') - + # Define Matrix attribute matAttr = 'worldMatrix[0]' if local: matAttr = 'matrix' - + # Get time mat = OpenMaya.MMatrix() if time != None: mat = mc.getAttr(transform+'.'+matAttr,t=frame) else: mat = mc.getAttr(transform+'.'+matAttr) - + # Build Matrix matrix = buildMatrix(translate=(mat[12],mat[13],mat[14]),xAxis=(mat[0],mat[1],mat[2]),yAxis=(mat[4],mat[5],mat[6]),zAxis=(mat[8],mat[9],mat[10])) - + # Return result return matrix @@ -78,16 +78,16 @@ def vectorMatrixMultiply(vector,matrix,transformAsPoint=False,invertMatrix=False # Create MPoint/MVector object for transformation if transformAsPoint: vector = OpenMaya.MPoint(vector[0],vector[1],vector[2],1.0) else: vector = OpenMaya.MVector(vector[0],vector[1],vector[2]) - + # Check input is of type MMatrix if type(matrix) != OpenMaya.MMatrix: raise Exception('Matrix input variable is not of expected type! Expecting MMatrix, received '+str(type(matrix))+'!!') - + # Transform vector if matrix != OpenMaya.MMatrix.identity: if invertMatrix: matrix = matrix.inverse() vector *= matrix - + # Return new vector return [vector.x,vector.y,vector.z] @@ -112,7 +112,7 @@ def getRotation(matrix,rotationOrder='xyz'): ''' # Calculate radian constant radian = 180.0/math.pi - + # Check rotation order if type(rotationOrder) == str: rotationOrder = rotationOrder.lower() @@ -122,16 +122,16 @@ def getRotation(matrix,rotationOrder='xyz'): rotationOrder = rotateOrder[rotationOrder] else: rotationOrder = int(rotationOrder) - + # Get transformation matrix transformMatrix = OpenMaya.MTransformationMatrix(matrix) - + # Get Euler rotation from matrix eulerRot = transformMatrix.eulerRotation() - + # Reorder rotation eulerRot.reorderIt(rotationOrder) - + # Return XYZ rotation values return (eulerRot.x*radian,eulerRot.y*radian,eulerRot.z*radian) @@ -156,25 +156,25 @@ def buildRotation(aimVector,upVector=(0,1,0),aimAxis='x',upAxis='y'): if upAxis[0] == '-': upAxis = upAxis[1] negUp = True - + # Check valid axis axisList = ['x','y','z'] if not axisList.count(aimAxis): raise Exception('Aim axis is not valid!') if not axisList.count(upAxis): raise Exception('Up axis is not valid!') if aimAxis == upAxis: raise Exception('Aim and Up axis must be unique!') - + # Determine cross axis axisList.remove(aimAxis) axisList.remove(upAxis) crossAxis = axisList[0] - + # Normaize aimVector aimVector = mathUtils.normalizeVector(aimVector) if negAim: aimVector = (-aimVector[0],-aimVector[1],-aimVector[2]) # Normaize upVector upVector = mathUtils.normalizeVector(upVector) if negUp: upVector = (-upVector[0],-upVector[1],-upVector[2]) - + # Get cross product vector crossVector = (0,0,0) if (aimAxis == 'x' and upAxis == 'z') or (aimAxis == 'z' and upAxis == 'y'): @@ -186,12 +186,12 @@ def buildRotation(aimVector,upVector=(0,1,0),aimAxis='x',upAxis='y'): upVector = mathUtils.crossProduct(aimVector,crossVector) else: upVector = mathUtils.crossProduct(crossVector,aimVector) - + # Build axis dictionary axisDict={aimAxis: aimVector,upAxis: upVector,crossAxis: crossVector} # Build rotation matrix mat = buildMatrix(xAxis=axisDict['x'],yAxis=axisDict['y'],zAxis=axisDict['z']) - + # Return rotation matrix return mat @@ -212,32 +212,32 @@ def inverseTransform(source,destination,translate=True,rotate=True,scale=True): # ========== # - Checks - # ========== - + if not mc.objExists(source): raise Exception('Transform "'+source+'" does not exist!!') if not mc.objExists(destination): raise Exception('Transform "'+destination+'" does not exist!!') - + # Load decomposeMatrix plugin if not mc.pluginInfo('decomposeMatrix',q=True,l=True): try: mc.loadPlugin('decomposeMatrix') except: raise MissingPluginError('Unable to load "decomposeMatrix" plugin!!') - + # ================================= # - Apply Inverse Transformations - # ================================= - + # Create and name decomposeMatrix node dcm = mc.createNode('decomposeMatrix',n=source+'_decomposeMatrix') - + # Make connections mc.connectAttr(source+'.inverseMatrix',dcm+'.inputMatrix',f=True) if translate: mc.connectAttr(dcm+'.outputTranslate',destination+'.translate',f=True) if rotate: mc.connectAttr(dcm+'.outputRotate',destination+'.rotate',f=True) if scale: mc.connectAttr(dcm+'.outputScale',destination+'.scale',f=True) - + # ================= # - Return Result - # ================= - + return dcm def fromList(valueList): @@ -249,7 +249,7 @@ def fromList(valueList): # Check Value List if len(valueList) != 16: raise Exception('Invalid value list! Expecting 16 element, found '+str(len(valueList))) - + # Create transformation matrix from input vaules matrix = OpenMaya.MMatrix() OpenMaya.MScriptUtil.createMatrixFromList(valueList,matrix) @@ -269,7 +269,7 @@ def fromList(valueList): #OpenMaya.MScriptUtil.setDoubleArray(matrix[3], 1, valueList[13]) #OpenMaya.MScriptUtil.setDoubleArray(matrix[3], 2, valueList[14]) #OpenMaya.MScriptUtil.setDoubleArray(matrix[3], 3, valueList[15]) - + # Return Result return matrix diff --git a/utils/mesh.py b/utils/mesh.py index 30e106d..b22c022 100644 --- a/utils/mesh.py +++ b/utils/mesh.py @@ -19,16 +19,16 @@ def isMesh(mesh): ''' # Check Object Exists if not mc.objExists(mesh): return False - + # Check Shape if 'transform' in mc.nodeType(mesh,i=True): meshShape = mc.ls(mc.listRelatives(mesh,s=True,ni=True,pa=True) or [],type='mesh') if not meshShape: return False mesh = meshShape[0] - + # Check Mesh if mc.objectType(mesh) != 'mesh': return False - + # Return Result return True @@ -41,21 +41,21 @@ def isOpen(mesh): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # Get User Selection sel = mc.ls(sl=1) - + # Select Mesh mc.select(mesh) mc.polySelectConstraint(mode=3,type=1,where=1) boundarySel = mc.ls(sl=1,fl=1) - + # Restore User Selection if sel: mc.select(sel) - + # Return Result return bool(boundarySel) - + def getMeshFn(mesh): ''' Create an MFnMesh class object from the specified polygon mesh @@ -64,15 +64,15 @@ def getMeshFn(mesh): ''' # Checks if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get shape if mc.objectType(mesh) == 'transform': mesh = mc.listRelatives(mesh,s=True,ni=True,pa=True)[0] - + # Get MFnMesh meshPath = glTools.utils.base.getMDagPath(mesh) meshFn = OpenMaya.MFnMesh(meshPath) - + # Return result return meshFn @@ -84,21 +84,21 @@ def getMeshVertexIter(mesh,vtxId=None): ''' # Checks if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get shape if mc.objectType(mesh) == 'transform': mesh = mc.listRelatives(mesh,s=True,ni=True,pa=True)[0] - + # Get MFnMesh meshPath = glTools.utils.base.getMDagPath(mesh) meshVertIt = OpenMaya.MItMeshVertex(meshPath) - + # Initialize faceId if vtxId != None: meshVertUtil = OpenMaya.MScriptUtil(0) meshVertPtr = meshVertUtil.asIntPtr() meshVertIt.setIndex(vtxId,meshVertPtr) - + # Return result return meshVertIt @@ -112,21 +112,21 @@ def getMeshFaceIter(mesh,faceId=None): ''' # Checks if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get shape if mc.objectType(mesh) == 'transform': mesh = mc.listRelatives(mesh,s=True,ni=True,pa=True)[0] - + # Get MFnMesh meshPath = glTools.utils.base.getMDagPath(mesh) meshFaceIt = OpenMaya.MItMeshPolygon(meshPath) - + # Initialize faceId if faceId != None: meshFaceUtil = OpenMaya.MScriptUtil(0) meshFacePtr = meshFaceUtil.asIntPtr() meshFaceIt.setIndex(faceId,meshFacePtr) - + # Return result return meshFaceIt @@ -141,21 +141,21 @@ def getMeshEdgeIter(mesh,edgeId=None): # Checks if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get shape if mc.objectType(mesh) == 'transform': mesh = mc.listRelatives(mesh,s=True,ni=True,pa=True)[0] - + # Get MFnMesh meshPath = glTools.utils.base.getMDagPath(mesh) meshEdgeIt = OpenMaya.MItMeshEdge(meshPath) - + # Initialize faceId if edgeId != None: meshEdgeUtil = OpenMaya.MScriptUtil(0) meshEdgePtr = meshEdgeUtil.asIntPtr() meshEdgeIt.setIndex(edgeId,meshEdgePtr) - + # Return result return meshEdgeIt @@ -168,12 +168,12 @@ def getRawPoints(mesh): # Checks if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get Mesh Points meshFn = getMeshFn(mesh) meshPts = meshFn.getRawPoints() meshVtx = meshFn.numVertices() - + # Convert Mesh Points (MPointArray) #meshPtUtil = OpenMaya.MScriptUtil() #meshPtArray = OpenMaya.MPointArray(meshVtx,OpenMaya.MPoint.origin) @@ -181,7 +181,7 @@ def getRawPoints(mesh): # meshPtArray[i] = OpenMaya.MPoint( meshPtUtil.getFloatArrayItem(meshPts,(i*3)+0), # meshPtUtil.getFloatArrayItem(meshPts,(i*3)+1), # meshPtUtil.getFloatArrayItem(meshPts,(i*3)+2) ) - + # Return Result return meshPts @@ -194,12 +194,12 @@ def getPoints(mesh): # Checks if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get Mesh Points meshFn = getMeshFn(mesh) meshPts = meshFn.getRawPoints() meshVtx = meshFn.numVertices() - + # Convert Mesh Points (MPointArray) meshPtArray = [] meshPtUtil = OpenMaya.MScriptUtil() @@ -207,7 +207,7 @@ def getPoints(mesh): meshPtArray.append( [ meshPtUtil.getFloatArrayItem(meshPts,(i*3)+0), meshPtUtil.getFloatArrayItem(meshPts,(i*3)+1), meshPtUtil.getFloatArrayItem(meshPts,(i*3)+2) ] ) - + # Return Result return meshPtArray @@ -224,20 +224,20 @@ def getNormal(mesh,vtxId,worldSpace=False): # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MFnMesh meshFn = getMeshFn(mesh) - + # Determine sample space if worldSpace: sampleSpace = OpenMaya.MSpace.kWorld else: sampleSpace = OpenMaya.MSpace.kObject - + # Get Normals normal = OpenMaya.MVector() meshFn.getVertexNormal(vtxId,normal,sampleSpace) - + # Return result return normal @@ -252,20 +252,20 @@ def getNormals(mesh,worldSpace=False): # Check Mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MFnMesh meshFn = getMeshFn(mesh) - + # Determine sample space if worldSpace: sampleSpace = OpenMaya.MSpace.kWorld else: sampleSpace = OpenMaya.MSpace.kObject - + # Get Normals normalArray = OpenMaya.MFloatVectorArray() meshFn.getVertexNormals(False,normalArray,sampleSpace) - + # Return result return normalArray @@ -283,17 +283,17 @@ def getUVs(mesh,UVset=None): # Check UV Set if UVset and not UVset in mc.polyUVSet(mesh,allUVSets=True): raise Exception('Mesh "'+mesh+'" has not UV set "'+UVset+'"!') - + # Get MeshFn meshFn = getMeshFn(mesh) - + # Get UVs uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() meshFn.getUVs(uArray,vArray,UVset) u = list(uArray) v = list(vArray) - + # Return Result return u, v @@ -306,14 +306,14 @@ def resetVertices(mesh): # Check Mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Reset Vertices vtx = mc.polyEvaluate(mesh,v=True) for i in range(vtx): mc.setAttr(mesh+'.pnts['+str(i)+'].pntx',0) mc.setAttr(mesh+'.pnts['+str(i)+'].pnty',0) mc.setAttr(mesh+'.pnts['+str(i)+'].pntz',0) - + # Return Result return mesh @@ -327,11 +327,11 @@ def freezeVertices(mesh): # Check Mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Freeze Vertices mc.polyMoveVertex(mesh) mc.delete(mesh,ch=True) - + # Return Result return mesh @@ -347,32 +347,32 @@ def reassignUVs(mesh,precision=4): # Check Mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MeshFn meshFn = getMeshFn(mesh) - + # Get UV Ids uvCount = OpenMaya.MIntArray() uvIds = OpenMaya.MIntArray() meshFn.getAssignedUVs(uvCount,uvIds) - + # Get UVs uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() meshFn.getUVs(uArray,vArray) u = list(uArray) v = list(vArray) - + # Set UVs uArrayNew = OpenMaya.MFloatArray() vArrayNew = OpenMaya.MFloatArray() for i in u: uArrayNew.append(round(i,precision)) for i in v: vArrayNew.append(round(i,precision)) meshFn.setUVs(uArrayNew,vArrayNew) - + # Reassign UVs meshFn.assignUVs(uvCount,uvIds) - + def getEdgeVertexIndices(mesh,edgeId): ''' Return the vertex indices connected to the specified mesh edge. @@ -384,22 +384,22 @@ def getEdgeVertexIndices(mesh,edgeId): # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MItMeshEdge edgeIter = getMeshEdgeIter(mesh) - + # Create edgeId MScriptUtil edgeIdUtil = OpenMaya.MScriptUtil() edgeIdUtil.createFromInt(0) edgeIdPtr = edgeIdUtil.asIntPtr() - + # Set current edge index edgeIter.setIndex(edgeId,edgeIdPtr) - + # Get edge vertex indices vtx0 = edgeIter.index(0) vtx1 = edgeIter.index(1) - + # Return result return [vtx0,vtx1] @@ -414,20 +414,20 @@ def getFaceVertexIndices(mesh,faceId): # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MItMeshPolygon faceIter = getMeshFaceIter(mesh) - + # Create faceId MScriptUtil faceIdUtil = OpenMaya.MScriptUtil() faceIdUtil.createFromInt(0) faceIdPtr = faceIdUtil.asIntPtr() - + # Get face vertex indices faceVtxArray = OpenMaya.MIntArray() faceIter.setIndex(faceId,faceIdPtr) faceIter.getVertices(faceVtxArray) - + # Return result return list(faceVtxArray) @@ -442,20 +442,20 @@ def getFaceEdgeIndices(mesh,faceId): # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MItMeshPolygon faceIter = getMeshFaceIter(mesh) - + # Create faceId MScriptUtil faceIdUtil = OpenMaya.MScriptUtil() faceIdUtil.createFromInt(0) faceIdPtr = faceIdUtil.asIntPtr() - + # Get face vertex indices faceEdgeArray = OpenMaya.MIntArray() faceIter.setIndex(faceId,faceIdPtr) faceIter.getEdges(faceEdgeArray) - + # Return result return list(faceEdgeArray) @@ -470,7 +470,7 @@ def numUvShells(mesh,uvSet=''): # Check Mesh if not isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check UV Set uvSets = mc.polyUVSet(mesh,q=True,allUVSets=True) if not uvSets: @@ -478,22 +478,22 @@ def numUvShells(mesh,uvSet=''): if not uvSet: uvSet = uvSets[0] if not uvSets.count(uvSet): raise Exception('Mesh object "'+mesh+'" has no UVset "'+uvSet+'"!') - + # Initialize Function Sets uvShellArray = OpenMaya.MIntArray() meshFn = getMeshFn(mesh) - + # Build Pointer shells = OpenMaya.MScriptUtil() shells.createFromInt(0) shellsPtr = shells.asUintPtr() - + # Get UV Shell IDs meshFn.getUvShellsIds(uvShellArray, shellsPtr, uvSet) - + # Return Result return shells.getUint(shellsPtr) - + def getVertexUV(mesh,vtxId,uvSet=None,average=False): ''' Return the UV value of the specified mesh vertex @@ -509,18 +509,18 @@ def getVertexUV(mesh,vtxId,uvSet=None,average=False): # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Check uvSet if not uvSet: uvSet = mc.polyUVSet(mesh,q=True,cuv=True) - + # Get Mesh Vertex Function Set vtxIdUtil = OpenMaya.MScriptUtil() vtxIdUtil.createFromInt(0) vtxIdPtr = vtxIdUtil.asIntPtr() vtxIt = glTools.utils.mesh.getMeshVertexIter(mesh) vtxIt.setIndex(vtxId,vtxIdPtr) - + # Get UV value uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() @@ -531,7 +531,7 @@ def getVertexUV(mesh,vtxId,uvSet=None,average=False): vArray = list(vArray) u = uArray[0] v = vArray[0] - + # Average shared vertex UVs if average: u=0.0 @@ -540,10 +540,10 @@ def getVertexUV(mesh,vtxId,uvSet=None,average=False): for i in range(uvCount): u += uArray[i]/uvCount v += vArray[i]/uvCount - + # Return Result return [u,v] - + def closestPoint(mesh,point=(0,0,0)): ''' Get the closest point on the specified mesh to a given point @@ -555,17 +555,17 @@ def closestPoint(mesh,point=(0,0,0)): ''' # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MPoint pos = glTools.utils.base.getMPoint(point) cpos = OpenMaya.MPoint() - + # Get MFnMesh meshFn = getMeshFn(mesh) - + # Get closestPoint meshFn.getClosestPoint(pos,cpos,OpenMaya.MSpace.kWorld) - + # Return result return (cpos.x,cpos.y,cpos.z) @@ -580,17 +580,17 @@ def closestNormal(mesh,point=(0,0,0)): ''' # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MPoint pos = glTools.utils.base.getMPoint(point) norm = OpenMaya.MVector() - + # Get MFnMesh meshFn = getMeshFn(mesh) - + # Get closestPoint meshFn.getClosestNormal(pos,norm,OpenMaya.MSpace.kWorld) - + # Return result return (norm.x,norm.y,norm.z) @@ -604,22 +604,22 @@ def closestFace(mesh,point=(0,0,0)): ''' # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MPoint pos = glTools.utils.base.getMPoint(point) cpos = OpenMaya.MPoint() - + # Create faceId MScriptUtil faceId = OpenMaya.MScriptUtil() faceId.createFromInt(0) faceIdPtr = faceId.asIntPtr() - + # Get MFnMesh meshFn = getMeshFn(mesh) - + # Get closestPoint meshFn.getClosestPoint(pos,cpos,OpenMaya.MSpace.kWorld,faceIdPtr) - + # Return result return OpenMaya.MScriptUtil(faceIdPtr).asInt() @@ -634,24 +634,24 @@ def closestVertex(mesh,point=(0,0,0)): # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MPoint pos = glTools.utils.base.getMPoint(point) - + # Get closest face faceId = closestFace(mesh,point) - + # Create prevIndex MScriptUtil indexUtil = OpenMaya.MScriptUtil() indexUtil.createFromInt(0) indexUtilPtr = indexUtil.asIntPtr() - + # Get face vertices faceVtxArray = OpenMaya.MIntArray() faceIter = getMeshFaceIter(mesh) faceIter.setIndex(faceId,indexUtilPtr) faceIter.getVertices(faceVtxArray) - + # Get closest vertex vtxId = -1 minDist = 99999 @@ -661,7 +661,7 @@ def closestVertex(mesh,point=(0,0,0)): if dist < minDist: vtxId = i minDist = dist - + # Return result return vtxId @@ -676,21 +676,21 @@ def closestEdge(mesh,point=(0,0,0)): # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get closest face faceId = closestFace(mesh,point) - + # Create prevIndex MScriptUtil indexUtil = OpenMaya.MScriptUtil() indexUtil.createFromInt(0) indexUtilPtr = indexUtil.asIntPtr() - + # Get face vertices faceEdgeArray = OpenMaya.MIntArray() faceIter = getMeshFaceIter(mesh) faceIter.setIndex(faceId,indexUtilPtr) faceIter.getEdges(faceEdgeArray) - + # Get Closest Edge edgeId = -1 minDist = 99999 @@ -700,7 +700,7 @@ def closestEdge(mesh,point=(0,0,0)): if dist < minDist: edgeId = i minDist = dist - + # Return result return edgeId @@ -715,25 +715,25 @@ def closestPointWeightedAverage(mesh,point=(0,0,0)): # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MPoint pos = glTools.utils.base.getMPoint(point) - + # Get closest face faceId = closestFace(mesh,point) - + # Create prevIndex MScriptUtil indexUtil = OpenMaya.MScriptUtil() indexUtil.createFromInt(0) indexUtilPtr = indexUtil.asIntPtr() - + # Get face vertices faceVtxArray = OpenMaya.MIntArray() faceIter = getMeshFaceIter(mesh) faceIter.setIndex(faceId,indexUtilPtr) faceIter.getVertices(faceVtxArray) faceVtxArray = list(faceVtxArray) - + # Calculate weighted average wt = {} distArray = [] @@ -744,10 +744,10 @@ def closestPointWeightedAverage(mesh,point=(0,0,0)): if dist < 0.00001: dist = 0.00001 distArray.append(dist) totalInvDist += 1.0/dist - + for v in range(len(faceVtxArray)): wt[faceVtxArray[v]] = (1.0/distArray[v])/totalInvDist - + # Return result return wt @@ -761,17 +761,17 @@ def closestNormal(mesh,point=(0,0,0)): ''' # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - - # Get closest face + + # Get closest face cFace = closestFace(mesh,point) - + # Get MItMeshPolygon meshSel = OpenMaya.MSelectionList() OpenMaya.MGlobal.getSelectionListByName(mesh,meshSel) meshPath = OpenMaya.MDagPath() meshSel.getDagPath(0,meshPath) faceIter = OpenMaya.MItMeshPolygon(meshPath) - + # Get face normal faceNorm = OpenMaya.MVector() # Setup int pointer for setIndex() @@ -781,7 +781,7 @@ def closestNormal(mesh,point=(0,0,0)): faceIter.setIndex(cFace,indexUtilPtr) # Get normal faceIter.getNormal(faceNorm,OpenMaya.MSpace.kWorld) - + # Return result return (faceNorm.x,faceNorm.y,faceNorm.z) @@ -795,7 +795,7 @@ def closestUV(mesh,point=(0,0,0),uvSet=''): ''' # Check mesh if not isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check uvSet if not uvSet: currentUvSet = mc.polyUVSet(mesh,q=True,cuv=True) @@ -803,17 +803,17 @@ def closestUV(mesh,point=(0,0,0),uvSet=''): uvSet = currentUvSet[0] if not mc.polyUVSet(mesh,q=True,auv=True).count(uvSet): raise Exception('Invalid UV set "'+uvSet+'" specified!"') - + # Get mesh function set meshFn = getMeshFn(mesh) - + # Get closest UV pnt = glTools.utils.base.getMPoint(point) uv = OpenMaya.MScriptUtil() uv.createFromList([0.0,0.0],2) uvPtr = uv.asFloat2Ptr() meshFn.getUVAtPoint(pnt,uvPtr,OpenMaya.MSpace.kWorld,uvSet) - + # Return result return (uv.getFloat2ArrayItem(uvPtr,0,0),uv.getFloat2ArrayItem(uvPtr,0,1)) @@ -829,47 +829,47 @@ def getPointFromUV(mesh,uv=(-1,-1),uvSet=None,tolerance=0.01): @param tolerance: tolerance ge @type uv: tuple ''' - + # Check mesh if not isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + if not uvSet: currentUvSet = mc.polyUVSet(mesh,q=True,cuv=True) if not currentUvSet: raise Exception('Mesh "'+mesh+'" has no valid uvSet!') uvSet = currentUvSet[0] if not mc.polyUVSet(mesh,q=True,auv=True).count(uvSet): raise Exception('Invalid UV set "'+uvSet+'" specified!"') - + # Get mesh function set meshFn = getMeshFn(mesh) faceCount = mc.polyEvaluate(mesh, face=True) - + # convert uv to ptr - util = OpenMaya.MScriptUtil() - util.createFromList ((uv[0], uv[1]),2) + util = OpenMaya.MScriptUtil() + util.createFromList ((uv[0], uv[1]),2) uvPtr = util.asFloat2Ptr() - + positionMPoint = OpenMaya.MPoint() - + # check each face for uv #worldPos = {'face#': [x,y,z]} worldPos = {} for faceIndex in range(faceCount): - - try: + + try: meshFn.getPointAtUV( faceIndex , positionMPoint, uvPtr, OpenMaya.MSpace.kWorld, uvSet, tolerance ) - + worldPos[faceIndex] = (positionMPoint.x, positionMPoint.y, positionMPoint.z) except: pass - + return worldPos - + def faceCenter(mesh,faceId): ''' Return the center position of the specified mesh face @@ -881,7 +881,7 @@ def faceCenter(mesh,faceId): # Get Face Center faceIter = getMeshFaceIter(mesh,faceId) pt = faceIter.center(OpenMaya.MSpace.kObject) - + # Return Result return [pt[0],pt[1],pt[2]] @@ -896,7 +896,7 @@ def edgeCenter(mesh,edgeId): # Get Face Center edgeIter = getMeshEdgeIter(mesh,edgeId) pt = edgeIter.center(OpenMaya.MSpace.kObject) - + # Return Result return [pt[0],pt[1],pt[2]] @@ -960,13 +960,13 @@ def snapToMesh(mesh,transform,snapPivot=False): ''' # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a valid mesh!') - + # Get transform position pos = mc.xform(transform,q=True,ws=True,rp=True) - + # Get mesh point position meshPt = closestPoint(mesh,pos) - + # Snap to Mesh if snapPivot: mc.xform(obj,piv=meshPt,ws=True) else: mc.move(meshPt[0]-pos[0],meshPt[1]-pos[1],meshPt[2]-pos[2],transform,r=True,ws=True) @@ -995,18 +995,18 @@ def orientToMesh(mesh,transform,upVector=(0,1,0),upVectorObject='',normalAxis='x mPos = closestPoint(mesh,pos) # Get closest normal norm = closestNormal(mesh,pos) - + # Check upVector object if upVectorObject: if not mc.objExists(upVectorObject): raise Exception('UpVector object "'+upVectorObject+'" does not exist!!') upVectorMat = glTools.utils.matrix.buildMatrix(transform=upVectorObject) upVector = glTools.utils.matrix.vectorMatrixMultiply(upVector,upVectorMat,transformAsPoint=False,invertMatrix=False) - + # Build rotation matrix rotateOrder = mc.getAttr(transform+'.ro') mat = glTools.utils.matrix.buildRotation(norm,upVector,normalAxis,upAxis) rot = glTools.utils.matrix.getRotation(mat,rotateOrder) - + # Orient object to mesh mc.rotate(rot[0],rot[1],rot[2],transform,a=True,ws=True) @@ -1025,22 +1025,22 @@ def snapToVertex(mesh,transform,vtxId=-1,snapPivot=False): # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a valid mesh!') - + # Get transform position pos = glTools.utils.base.getPosition(transform) - + # Get mesh vertex to snap to if vtxId < 0: vtxId = closestVertex(mesh,pos) - + # Get vertex position vtxPt = mc.pointPosition(mesh+'.vtx['+str(vtxId)+']') - + # Snap to Vertex if snapPivot: mc.xform(obj,piv=vtxPt,ws=True) else: mc.move(vtxPt[0]-pos[0],vtxPt[1]-pos[1],vtxPt[2]-pos[2],transform,r=True,ws=True) - + # Retrun result return vtxPt @@ -1056,17 +1056,17 @@ def snapPtsToMesh_old(mesh,pointList,amount=1.0): ''' # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a valid mesh!') - + # Check points pointList = mc.ls(pointList,fl=True) if not pointList: pointList = mc.ls(sl=True,fl=True) - + # Transform types transform = ['transform','joint','ikHandle','effector'] - + # Snap points for pt in pointList: - + # Check Transform if transform.count(mc.objectType(pt)): snapToMesh(mesh,pt,snapPivot=False) @@ -1088,14 +1088,14 @@ def snapPtsToMesh(mesh,pointList,amount=1.0): ''' # Check mesh if not isMesh(mesh): raise Exception('Object '+mesh+' is not a valid mesh!') - + # Check points pointList = mc.ls(pointList,fl=True) if not pointList: pointList = mc.ls(sl=True,fl=True) - + # Get MFnMesh meshFn = getMeshFn(mesh) - + # Snap points pos = OpenMaya.MPoint() for pt in pointList: @@ -1121,17 +1121,17 @@ def closestVertexAttr(obj,mesh,attr='vtx'): raise Exception('Mesh "'+mesh+'" does not exist!!') if not isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # Get Closest Vertex pos = mc.xform(obj,q=True,ws=True,rp=True) vtx = closestVertex(mesh,pos) - + # Add Vertex Attribute if not mc.objExists(obj+'.'+attr): mc.addAttr(obj,ln=attr,at='long',dv=0,k=False) mc.setAttr(obj+'.'+attr,cb=True) mc.setAttr(obj+'.'+attr,vtx) - + # Return Result return (obj+'.'+attr) @@ -1153,11 +1153,11 @@ def intersect(mesh,source,direction,testBothDirections=False,maxDist=9999): sourcePt = OpenMaya.MFloatPoint(source[0],source[1],source[2]) # Get direction vector directionVec = OpenMaya.MFloatVector(direction[0],direction[1],direction[2]) - + # Calculate intersection hitPt = OpenMaya.MFloatPoint() meshFn.closestIntersection(sourcePt,directionVec,None,None,False,OpenMaya.MSpace.kWorld,maxDist,testBothDirections,None,hitPt,None,None,None,None,None,0.0001) - + # Return intersection hit point return [hitPt[0],hitPt[1],hitPt[2]] @@ -1183,11 +1183,11 @@ def allIntersections(mesh,source,direction,testBothDirections=False,maxDist=9999 sourcePt = OpenMaya.MFloatPoint(source[0],source[1],source[2]) # Get direction vector directionVec = OpenMaya.MFloatVector(direction[0],direction[1],direction[2]) - + # Calculate intersection hitPtArray = OpenMaya.MFloatPointArray() meshFn.allIntersections(sourcePt,directionVec,None,None,False,OpenMaya.MSpace.kWorld,maxDist,testBothDirections,None,True,hitPtArray,None,None,None,None,None,0.0001) - + # Sort intersectionList = [] if sort: @@ -1203,15 +1203,15 @@ def allIntersections(mesh,source,direction,testBothDirections=False,maxDist=9999 if dist < minDist: minDist = dist ind = i - # Append Sorted Intersection List + # Append Sorted Intersection List intersectionList.append((hitPtArray[ind][0],hitPtArray[ind][1],hitPtArray[ind][2])) # Remove Sorted Intersection hitPtArray.remove(ind) - + else: # Pass Unsorted Intersection List intersectionList = [(hitPtArray[i][0],hitPtArray[i][1],hitPtArray[i][2])] - + # Return intersection hit point return intersectionList @@ -1271,16 +1271,16 @@ def intersectDist(mesh,source,direction,testBothDirections=False,maxDist=9999): sourcePt = OpenMaya.MFloatPoint(source[0],source[1],source[2]) # Get direction vector directionVec = OpenMaya.MFloatVector(direction[0],direction[1],direction[2]) - + # Create hit distance utils hitDistUtil = OpenMaya.MScriptUtil() hitDistUtil.createFromDouble(-1.0) hitDistPtr = hitDistUtil.asFloatPtr() - + # Calculate intersection hitPt = OpenMaya.MFloatPoint() meshFn.closestIntersection(sourcePt,directionVec,None,None,False,OpenMaya.MSpace.kWorld,maxDist,testBothDirections,None,hitPt,hitDistPtr,None,None,None,None,0.0001) - + # Return intersection hit point return OpenMaya.MScriptUtil(hitDistPtr).asFloat() @@ -1302,16 +1302,16 @@ def intersectFace(mesh,source,direction,testBothDirections=False,maxDist=9999): sourcePt = OpenMaya.MFloatPoint(source[0],source[1],source[2]) # Get direction vector directionVec = OpenMaya.MFloatVector(direction[0],direction[1],direction[2]) - + # Create hit face utils hitFaceUtil = OpenMaya.MScriptUtil() hitFaceUtil.createFromInt(0) hitFacePtr = hitDistUtil.asIntPtr() - + # Calculate intersection hitPt = OpenMaya.MFloatPoint() meshFn.closestIntersection(sourcePt,directionVec,None,None,False,OpenMaya.MSpace.kWorld,maxDist,testBothDirections,None,None,None,hitFacePtr,None,None,None,0.0001) - + # Return intersection hit point return OpenMaya.MScriptUtil(hitFacePtr).asInt() @@ -1333,11 +1333,11 @@ def intersectAllFaces(mesh,source,direction,testBothDirections=False,maxDist=999 sourcePt = OpenMaya.MFloatPoint(source[0],source[1],source[2]) # Get direction vector directionVec = OpenMaya.MFloatVector(direction[0],direction[1],direction[2]) - + # Calculate intersection hitFaceArray = OpenMaya.MIntArray() meshFn.allIntersections(sourcePt,directionVec,None,None,False,OpenMaya.MSpace.kWorld,maxDist,testBothDirections,None,True,None,None,hitFaceArray,None,None,None,0.0001) - + # Return intersection hit point return list(hitFaceArray) @@ -1355,16 +1355,16 @@ def faceArea(mesh,faceId): # Check faceId if faceId > mc.polyEvaluate(mesh,f=True): raise Exception('Face ID ('+str(faceId)+') out of range for for mesh "'+mesh+'"!') - + # Get Mesh Face Fn faceIt = getMeshFaceIter(mesh,faceId) - + # Get Area areaUtil = OpenMaya.MScriptUtil() areaUtil.createFromDouble(0.0) areaPtr = areaUtil.asDoublePtr() faceIt.getArea(areaPtr) - + # Return Result return OpenMaya.MScriptUtil(areaPtr).asDouble() @@ -1381,49 +1381,49 @@ def locatorMesh(mesh,locatorScale=0.1,prefix=''): # ========== # - Checks - # ========== - + # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # Check Prefix if not prefix: prefix = mesh - + # ======================= # - Build Mesh Locators - # ======================= - + # Get Vertices componentList = glTools.utils.component.getComponentStrList(mesh) - + # Iterate over component list locatorList = [] for i in range(len(componentList)): - + # Get componet position pos = mc.pointPosition(componentList[i]) - + # Build Vertex Locator loc = mc.spaceLocator(n=prefix+'_vtx'+str(i)+'_loc')[0] mc.move(pos[0],pos[1],pos[2],loc,a=True,ws=True) mc.setAttr(loc+'.localScale',locatorScale,locatorScale,locatorScale) locatorList.append(loc) - + # Freeze Vertices mc.move(0,0,0,componentList[i],a=True,ws=True) - + # Freeze Mesh deformer = mc.deformer(mesh,type='cluster') mc.delete(mesh,constructionHistory=True) - + # Connect Locators for i in range(len(locatorList)): mc.connectAttr(locatorList[i]+'.worldPosition[0]',mesh+'.controlPoints['+str(i)+']',f=True) - + # ================= # - Return Result - # ================= - + return locatorList def buildMeshFromPoints(pts,ptsInU=None,ptsInV=None,closedInU=False,attach=False,prefix=None): @@ -1445,10 +1445,10 @@ def buildMeshFromPoints(pts,ptsInU=None,ptsInV=None,closedInU=False,attach=False # ========== # - Checks - # ========== - + # Check Prefix if not prefix: prefix = 'point' - + # Check Point Count if not ptsInU: ptsInU = math.sqrt(len(pts)) @@ -1458,11 +1458,11 @@ def buildMeshFromPoints(pts,ptsInU=None,ptsInV=None,closedInU=False,attach=False if ptsInV % 1: raise Exception('Invalid point count! Points in V not specified!') if len(pts) != (ptsInU*ptsInV): raise Exception('Invalid point count! Does not match ptsInU*ptsInV!') - + # ============== # - Build Mesh - # ============== - + # Create Mesh mesh = None if closedInU: @@ -1470,43 +1470,43 @@ def buildMeshFromPoints(pts,ptsInU=None,ptsInV=None,closedInU=False,attach=False mc.delete(mesh+'.f['+str(ptsInU*(ptsInV-1))+':'+str(ptsInU*(ptsInV-1)+1)+']') else: mesh = mc.polyPlane(ch=False,sx=(ptsInU-1),sy=(ptsInV-1))[0] - + # Rename Mesh mesh = mc.rename(mesh,prefix+'_mesh') - + # Get Mesh Vertices componentList = glTools.utils.component.getComponentStrList(mesh) - + # ========================== # - Position Mesh Vertices - # ========================== - + if attach: - + # Freeze Mesh Vertices mc.move(0,0,0,componentList,a=True,ws=True) freezeVertices(mesh) - + # Attach Vertices to Points for i in range(len(componentList)): mc.connectAttr(pts[i]+'.worldPosition[0]',mesh+'.controlPoints['+str(i)+']',f=True) - + else: - + # Position Vertices to Points for i in range(len(componentList)): pt = glTools.utils.base.getPosition(pts[i]) mc.move(pt[0],pt[1],pt[2],componentList[i],a=True,ws=True) - + # Freeze Mesh Vertices freezeVertices(mesh) - + # ================= # - Return Result - # ================= - + return mesh - + def borderEdgeList(mesh): ''' Return a list of mesh border edges. @@ -1515,22 +1515,22 @@ def borderEdgeList(mesh): ''' # Initialize edge list sel = [] - + # Initialize mesh edge iterator meshIt = getMeshEdgeIter(mesh) - + # Iterate over edges meshIt.reset() while(1): - + # Check border edge if meshIt.onBoundary(): sel.append(mesh+'.e['+str(meshIt.index())+']') - + # Iterate meshIt.next() if meshIt.isDone(): break - + # Return result return sel @@ -1544,32 +1544,32 @@ def getCornerVertexIds(mesh): # Checks if not isMesh(mesh): raise Exception('Object '+mesh+' is not a polygon mesh!') - + # Get MItMeshvertex meshIt = getMeshVertexIter(mesh) - + # Iterate over vertices meshIt.reset() cornerVetexList = [] while not meshIt.isDone(): - + # Get vertex Id vId = meshIt.index() - + # Get connected edges connEdgeList = OpenMaya.MIntArray() meshIt.getConnectedEdges(connEdgeList) connEdge = list(connEdgeList) - + # Check number of connected edges if len(connEdge) == 2: cornerVetexList.append(vId) - + # Iterate to next vertex meshIt.next() - + # Return result return cornerVetexList - + def vertexConnectivityList(mesh,faceConnectivity=False,showProgress=False): ''' Return a vertex connectivity list for the specified mesh @@ -1583,42 +1583,42 @@ def vertexConnectivityList(mesh,faceConnectivity=False,showProgress=False): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # ========================= # - Iterate Over Vertices - # ========================= - + # Begin Progress Bar gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') if showProgress: vtxCount = mc.polyEvaluate(mesh,v=True) mc.progressBar( gMainProgressBar,e=True,bp=True,ii=True,status=('Building Vertex Connectivity Array...'),maxValue=vtxCount ) - + # Initialize Connectivity List vtxConnectList = [] vtxCount = glTools.utils.component.getComponentCount(mesh) - + # Iterate over vertices for i in range(vtxCount): - + # Get Connected Vertex IDs connSel = glTools.utils.component.expandVertexSelection(mesh+'.vtx['+str(i)+']',useFace=faceConnectivity) connIDs = glTools.utils.component.singleIndexList(connSel) connIDs.remove(i) - + # Append Return Value vtxConnectList.append(connIDs) - + # Update Progress Bar if showProgress: if mc.progressBar(gMainProgressBar,q=True,isCancelled=True): mc.progressBar(gMainProgressBar,e=True,endProgress=True) raise UserInterupted('Operation cancelled by user!') mc.progressBar(gMainProgressBar,e=True,step=1) - + # End Current Progress Bar if showProgress: mc.progressBar(gMainProgressBar,e=True,endProgress=True) - + # Return Result return vtxConnectList @@ -1637,39 +1637,39 @@ def vertexConnectivityDict(mesh,vtxIDs,faceConnectivity=False,showProgress=False # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # ========================= # - Iterate Over Vertices - # ========================= - + # Begin Progress Bar gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') if showProgress: mc.progressBar( gMainProgressBar,e=True,bp=True,ii=True,status=('Building Vertex Connectivity Array...'),maxValue=len(vtxIDs) ) - + # Initialize Connectivity List vtxConnectDict = {} - + for vtxID in vtxIDs: - + # Get Connected Vertex IDs connSel = glTools.utils.component.expandVertexSelection(mesh+'.vtx['+str(vtxID)+']',useFace=faceConnectivity) connIDs = glTools.utils.component.singleIndexList(connSel) connIDs.remove(vtxID) - + # Append Return Value vtxConnectDict[vtxID] = connIDs - + # Update Progress Bar if showProgress: if mc.progressBar(gMainProgressBar,q=True,isCancelled=True): mc.progressBar(gMainProgressBar,e=True,endProgress=True) raise UserInterupted('Operation cancelled by user!') mc.progressBar(gMainProgressBar,e=True,step=1) - + # End Current Progress Bar if showProgress: mc.progressBar(gMainProgressBar,e=True,endProgress=True) - + # Return Result return vtxConnectDict @@ -1684,33 +1684,33 @@ def faceVertexList(mesh,showProgress=False): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # ====================== # - Iterate Over Faces - # ====================== - + # Initialize Face Iterator faceIter = getMeshFaceIter(mesh) - + # Begin Progress Bar gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') if showProgress: mc.progressBar( gMainProgressBar,e=True,bp=True,ii=True,status=('Building Face Vertex Array...'),maxValue=faceIter.count() ) - + # Initialize Connectivity List faceVertexList = [] faceVertexArray = OpenMaya.MIntArray() - + # Face Iterator faceIter.reset() for i in range(faceIter.count()): - + # Get Face Vertices faceIter.getVertices(faceVertexArray) - + # Append to Face Vertex List faceVertexList.append(list(faceVertexArray)) - + # Increment Iterator try: faceIter.next() @@ -1720,21 +1720,21 @@ def faceVertexList(mesh,showProgress=False): #if not faceIter.next(): # print('end of iter') # break - + # Update Progress Bar if showProgress: if mc.progressBar(gMainProgressBar,q=True,isCancelled=True): mc.progressBar(gMainProgressBar,e=True,endProgress=True) raise UserInterupted('Operation cancelled by user!') mc.progressBar(gMainProgressBar,e=True,step=1) - + # End Current Progress Bar if showProgress: mc.progressBar(gMainProgressBar,e=True,endProgress=True) - + # ================= # - Return Result - # ================= - + return faceVertexList def faceVertexDict(mesh,faceIDs,showProgress=False): @@ -1748,49 +1748,49 @@ def faceVertexDict(mesh,faceIDs,showProgress=False): # Check Mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!!') - + # ====================== # - Iterate Over Faces - # ====================== - + # Initialize Face Iterator faceIter = getMeshFaceIter(mesh) - + # Begin Progress Bar gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') if showProgress: mc.progressBar( gMainProgressBar,e=True,bp=True,ii=True,status=('Building Face Vertex Array...'),maxValue=len(faceIDs) ) - + # Initialize Connectivity List faceVertexDict = {} faceVertexArray = OpenMaya.MIntArray() - + # Face Iterator for i in faceIDs: - + # Go to Face Index faceIter.setIndex(i) - + # Get Face Vertices faceIter.getVertices(faceVertexArray) - + # Append to Face Vertex List faceVertexDict[i].append(list(faceVertexArray)) - + # Update Progress Bar if showProgress: if mc.progressBar(gMainProgressBar,q=True,isCancelled=True): mc.progressBar(gMainProgressBar,e=True,endProgress=True) raise UserInterupted('Operation cancelled by user!') mc.progressBar(gMainProgressBar,e=True,step=1) - + # End Current Progress Bar if showProgress: mc.progressBar(gMainProgressBar,e=True,endProgress=True) - + # ================= # - Return Result - # ================= - + return faceVertexDict def uncombine(polyUnite): @@ -1801,36 +1801,36 @@ def uncombine(polyUnite): ''' # Check polyUnite if not mc.objExists(polyUnite): raise Exception('PolyUnite "'+polyUnite+'" does not exist!!') - + # Get input meshes meshInputs = mc.listConnections(polyUnite+'.inputPoly',s=True,d=False,sh=True) print meshInputs - + # Delete output mesh and polyUnite meshOutput = mc.ls(mc.listHistory(polyUnite,f=True),type='mesh') meshOutputParent = mc.listRelatives(meshOutput[0],p=True)[0] mc.delete(polyUnite) mc.delete(meshOutput) mc.delete(meshOutputParent) - + # Restore input meshes meshRestore = [] for mesh in meshInputs: - + # Set input shape as non-intermediate mc.setAttr(mesh+'.intermediateObject',0) - + # Determine parent transforms transform = mc.listRelatives(mesh,p=True)[0] newParent = mc.listRelatives(transform,p=True)[0] - + # Reparent input shape and delete intermediate transform mc.parent(mesh,newParent,s=True,r=True) mc.delete(transform) - + # Append result meshRestore.append(newParent) - + # Return result return meshRestore @@ -1890,24 +1890,24 @@ def polyCleanup( meshList = [], for mesh in meshList: if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') - + if not meshList: allMeshes = 1 else: allMeshes = 0 mc.select(meshList) - + # Check fix if fix: selectOnly = 0 else: selectOnly = 2 - + # Check NonManifold if nonManifold: if fix: doNonManifold = 1 else: doNonManifold = 2 else: doNonManifold = -1 - + # Build Poly Cleanup Command polyCleanupCmd = 'polyCleanupArgList 3 {' polyCleanupCmd += '"'+str(allMeshes)+'",' # [0] - All selectable meshes @@ -1928,20 +1928,20 @@ def polyCleanup( meshList = [], polyCleanupCmd += '"'+str(doNonManifold)+'",' # [15] - Check non-manifold geometry polyCleanupCmd += '"'+str(int(laminaFace))+'"' # [16] - Check lamina faces polyCleanupCmd += '};' - + # Perform Poly Cleanup mm.eval(polyCleanupCmd) if printCmd: print polyCleanupCmd - + # Generate return value result = mc.ls(sl=1) - + # Restore selection state if meshList: mc.select(meshList) else: mc.select(cl=True) hiliteList = mc.ls(hilite=True) if hiliteList: mc.hilite(hiliteList,tgl=False) - + # Return Result return result diff --git a/utils/meshRelax.py b/utils/meshRelax.py index 4a6ba49..004e551 100644 --- a/utils/meshRelax.py +++ b/utils/meshRelax.py @@ -19,34 +19,34 @@ def neighbour(vertexList,referenceObject,meshRelax): meshRelaxNode = OpenMaya.MFnDependencyNode(meshRelaxObj) neighbourDataPlug = meshRelaxNode.findPlug('neighbourData') neighbourDataArrayPlug = neighbourDataPlug.elementByLogicalIndex(0) - + # Check reference object isCurve = True if not glTools.utils.curve.isCurve(referenceObject): isCurve = False elif not glTools.utils.curve.isSurface(referenceObject): raise UserInputError('Reference object must be a valid nurbs curve or surface!!') - + # Create neighbourData object neighbourData = OpenMaya.MVectorArray() - + # Get mesh and vertex list mesh = glTools.utils.component.getComponentIndexList(vertexList).keys()[0] - + # Get vertexIterator for mesh sel = OpenMaya.MSelectionList() OpenMaya.MGlobal.getSelectionListByName(mesh,sel) meshObj = OpenMaya.MObject() sel.getDependNode(0,meshObj) meshIt = OpenMaya.MItMeshVertex(meshObj) - + # Get neighbour data for i in range(len(vertexList)): - + # Get current point pnt = mc.pointPosition(vertexList[i]) pntId = glTools.utils.component.getComponentIndexList([vertexList[i]])[mesh][0] - + # Get closest U tangent if isCurve: u = glTools.utils.curve.closestPoint(referenceObject,pnt) @@ -55,21 +55,21 @@ def neighbour(vertexList,referenceObject,meshRelax): uv = glTools.utils.surface.closestPoint(referenceObject,pnt) tan = mc.pointOnSurface(referenceObject,u=uv[0],v=uv[1],ntu=True) tangent = OpenMaya.MVector(tan[0],tan[1],tan[2]) - + # Get neighbouring points n1 = mc.pickWalk(vertexList[i],d='up')[0] n1Id = glTools.utils.component.getComponentIndexList([n1])[mesh][0] n1Pt = mc.pointPosition(n1) n1Dist = glTools.utils.mathUtils.distanceBetween(pnt,n1Pt) - + n2 = mc.pickWalk(vertexList[i],d='down')[0] n2Id = glTools.utils.component.getComponentIndexList([n2])[mesh][0] n2Pt = mc.pointPosition(n2) n2Dist = glTools.utils.mathUtils.distanceBetween(pnt,n2Pt) - + # Build neighbour data vector tDist = n1Dist + n2Dist neighbourData.append(OpenMaya.MVector(float(pntId),n1Id+(n1Dist/tDist),n2Id+(n2Dist/tDist))) - + # Set value neighbourDataArrayPlug.setMObject(OpenMaya.MFnVectorArrayData().create(neighbourData)) diff --git a/utils/meshSwitch.py b/utils/meshSwitch.py index da97e55..3448fb1 100644 --- a/utils/meshSwitch.py +++ b/utils/meshSwitch.py @@ -12,21 +12,21 @@ def create(sourceList,targetList): # For Each Target meshSwitchList = [] for target in targetList: - + # Determine Prefix pre = target.replace(target.split('_')[-1],'') - + # Create meshSwitch Node meshSwitch = mc.createNode('meshSwitch',n=pre+'meshSwitch') meshSwitchList.append(meshSwitch) - + # Connect Source Meshes for i in range(len(sourceList)): mc.connectAttr(sourceList[i]+'.outMesh',meshSwitch+'.inMesh['+str(i)+']',f=True) - + # Connect To Target mc.connectAttr(meshSwitch+'.outMesh',target+'.inMesh',f=True) - + # Return Result return meshSwitchList @@ -41,13 +41,13 @@ def connect(switchList,sourceList): # Check switchList if type(switchList) == str or type(switchList) == unicode: switchList = [str(switchList)] - + # For each switch for meshSwitch in switchList: - + # For item in source list for i in range(len(sourceList)): - + # Connect source item to meshSwitch input try: mc.connectAttr(sourceList[i]+'.outMesh',meshSwitch+'.inMesh['+str(i)+']',f=True) except: pass @@ -61,19 +61,19 @@ def clearInput(switchList): # Check switchList if type(switchList) == str or type(switchList) == unicode: switchList = [str(switchList)] - + # For each switch for meshSwitch in switchList: - + # Get list of incoming mesh connections connectionList = mc.listConnections(meshSwitch+'.inMesh',s=True,d=False,p=True,c=True) if not connectionList: continue - + # Iterate over connections for i in range(len(connectionList)): - + # Skip odd numbered iteration if i%2: continue - + # Disconnect attribute mc.disconnectAttr(connectionList[i+1],connectionList[i]) diff --git a/utils/muscle.py b/utils/muscle.py index 7e1a2ae..55ac569 100644 --- a/utils/muscle.py +++ b/utils/muscle.py @@ -7,7 +7,7 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,startPt=[0.0,0.0,6.0],endPt=[0.0,0.0,-6.0],prefix='muscle'): ''' Build muscle primitive based on the input argument values between the start and end points - + @param attachments: Number of attachments points @type attachments: int @param sections: Number of profile curves @@ -24,19 +24,19 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s @type endPt: list @param prefix: Name prefix for muscle primitive @type prefix: str - + @return: Muscle mesh @returnType: str ''' # Checks - + # Get start, end and distance values startPoint = glTools.utils.base.getMPoint(startPt) endPoint = glTools.utils.base.getMPoint(endPt) startEndOffset = endPoint - startPoint startEndDist = startEndOffset.length() startEndInc = startEndDist / (attachments - 1) - + # Calculate attachment point positions attachPoints = [] for i in range(attachments): @@ -50,36 +50,36 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s attachPts = [[pt.x,pt.y,pt.z] for pt in attachPoints] # Resize attachments value to accomodate for tangent points attachments = len(attachPts) - + # ------------------------ # - Build base hierarchy - # ------------------------ - + # Create groups muscleGrp = mc.createNode('transform',n=prefix+'_group') muscleAttachGrp = mc.createNode('transform',n=prefix+'_attachment_group') muscleProfileGrp = mc.createNode('transform',n=prefix+'_profile_group') - + # Build hierarchy mc.parent(muscleAttachGrp,muscleGrp) mc.parent(muscleProfileGrp,muscleGrp) - - + + # ---------------------- # - Build Muscle Curve - # ---------------------- - + # Build muscle base curve muscleCurve = mc.rename(mc.curve(d=1,p=attachPts,k=range(len(attachPts))),prefix+'_curve') mc.rebuildCurve(muscleCurve,ch=0,rpo=1,rt=0,end=1,kr=0,kcp=1,kep=1,kt=1,s=0,d=1) muscleCurveShape = mc.listRelatives(muscleCurve,s=True)[0] mc.parent(muscleCurve,muscleAttachGrp) - + # Add muscle attributes mc.addAttr(muscleCurve,ln='muscle',at='message') mc.addAttr(muscleCurve,ln='muscleObjectType',dt='string') mc.setAttr(muscleCurve+'.muscleObjectType','spline',type='string',l=True) - + # Connect curve to attachment locators attachLocators = glTools.utils.curve.locatorCurve(muscleCurve,locatorScale=0.1,freeze=False,prefix=prefix) # Rename attachment locators and add muscle attibutes @@ -88,7 +88,7 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s mc.addAttr(attachLocators[i],ln='muscle',at='message') mc.addAttr(attachLocators[i],ln='muscleObjectType',dt='string') mc.setAttr(attachLocators[i]+'.muscleObjectType','attachment',type='string',l=True) - + # Rename attachment locators if not i: attachLocators[i] = mc.rename(attachLocators[i],prefix+'_attachStart_locator') @@ -104,43 +104,43 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s attachLocators[i] = mc.rename(attachLocators[i],prefix+'_attachEnd_locator') else: attachLocators[i] = mc.rename(attachLocators[i],prefix+'_attachMid'+str(i-1)+'_locator') - + # Group attachment locators attachLocGroup = [] [attachLocGroup.append(glTools.utils.base.group(loc)) for loc in attachLocators] mc.parent(attachLocGroup,muscleAttachGrp) - + # Create spline rebuild curve splineCurve = mc.rebuildCurve(muscleCurve,ch=1,rpo=0,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=5,d=3) splineRebuild = mc.rename(splineCurve[1],prefix+'_spline_rebuildCurve') splineCurveShape = mc.rename(mc.listRelatives(splineCurve[0],s=True)[0],prefix+'_spline_curveShape') mc.parent(splineCurveShape,muscleCurve,s=True,r=True) mc.delete(splineCurve[0]) - + # Create tangent rebuild curve tangentCurve = mc.rebuildCurve(muscleCurve,ch=1,rpo=0,rt=0,end=1,kr=0,kcp=0,kep=1,kt=1,s=2,d=3) tangentRebuild = mc.rename(tangentCurve[1],prefix+'_tangent_rebuildCurve') tangentCurveShape = mc.rename(mc.listRelatives(tangentCurve[0],s=True)[0],prefix+'_tangent_curveShape') mc.parent(tangentCurveShape,muscleCurve,s=True,r=True) mc.delete(tangentCurve[0]) - + # Create curve visibility attributes mc.addAttr(muscleCurve,ln='attachment',at='enum',en='Off:On:') mc.setAttr(muscleCurve+'.attachment',k=False,cb=True) mc.connectAttr(muscleCurve+'.attachment',muscleCurveShape+'.v') - + mc.addAttr(muscleCurve,ln='spline',at='enum',en='Off:On:') mc.setAttr(muscleCurve+'.spline',k=False,cb=True) mc.connectAttr(muscleCurve+'.spline',splineCurveShape+'.v') - + mc.addAttr(muscleCurve,ln='tangent',at='enum',en='Off:On:') mc.setAttr(muscleCurve+'.tangent',k=False,cb=True) mc.connectAttr(muscleCurve+'.tangent',tangentCurveShape+'.v') - + mc.setAttr(muscleCurve+'.attachment',0) mc.setAttr(muscleCurve+'.spline',1) mc.setAttr(muscleCurve+'.tangent',1) - + # Setup start tangent toggle mc.addAttr(attachLocators[0],ln='tangentControl',at='enum',en='Off:On:') mc.setAttr(attachLocators[0]+'.tangentControl',k=False,cb=True) @@ -159,67 +159,67 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s mc.connectAttr(attachLocators[-3]+'.worldPosition[0]',endTangentBlend+'.color2',f=True) mc.connectAttr(attachLocators[-1]+'.tangentControl',endTangentBlend+'.blender',f=True) mc.connectAttr(endTangentBlend+'.output',muscleCurve+'.controlPoints['+str(attachments-2)+']',f=True) - - + + # ------------------------------- # - Build Muscle Profile Curves - # ------------------------------- - + # Initialize profile list profileList = [] profileGrpList = [] profileFollowList = [] - + # Iterate through profiles profileInc = 1.0/(sections-1) for i in range(sections): - + # Create profile curve profile = mc.circle(ch=0,c=(0,0,0),nr=(0,0,1),sw=360,r=1,d=3,ut=0,tol=0.01,s=sectionsSpans,n=prefix+'_profile'+str(i+1)+'_curve')[0] profileList.append(profile) - + # Add muscle profile attribute mc.addAttr(profile,ln='muscle',at='message') mc.addAttr(profile,ln='muscleObjectType',dt='string') mc.setAttr(profile+'.muscleObjectType','profile',type='string',l=True) - + # Group profile curve profileGrp = glTools.utils.base.group(profile) profileGrpList.append(profileGrp) - + # Skip start/end profiles if (not i) or (i ==(sections-1)): continue - + # Add curve parameter attribute mc.addAttr(profile,ln='uValue',min=0.0,max=1.0,dv=profileInc*i) mc.setAttr(profile+'.uValue',k=False,cb=True) - + # Create profile pointOnCurveInfo node profileCurveInfo = mc.createNode('pointOnCurveInfo',n=prefix+'_profile'+str(i+1)+'_pointOnCurveInfo') - + # Attach profile group to point on muscle spline curve mc.connectAttr(splineCurveShape+'.worldSpace[0]',profileCurveInfo+'.inputCurve',f=True) mc.connectAttr(profile+'.uValue',profileCurveInfo+'.parameter',f=True) mc.connectAttr(profileCurveInfo+'.position',profileGrp+'.translate',f=True) - + # Create profile follow group profileFollowGrp = mc.createNode('transform',n=prefix+'_profileFollow'+str(i+1)+'_group') profileFollowList.append(profileFollowGrp) mc.connectAttr(profileCurveInfo+'.position',profileFollowGrp+'.translate',f=True) - + mc.parent(profileGrpList,muscleProfileGrp) mc.parent(profileFollowList,muscleProfileGrp) - - + + # ------------------------------------ # - Create profile orientation setup - # ------------------------------------ - + oddProfile = sections % 2 intProfile = int(sections * 0.5) midProfile = intProfile + oddProfile intIncrement = 1.0/intProfile - + # Create mid profile orientConstraint if oddProfile: midPointObject = profileFollowList[midProfile-2] @@ -227,29 +227,29 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s midPointObject = mc.createNode('transform',n=prefix+'_midPointFollow_group') mc.parent(midPointObject,muscleProfileGrp) midOrientCon = mc.orientConstraint([attachLocators[0],attachLocators[-1]],midPointObject,n=prefix+'_midPoint_orientConstraint') - + # Create intermediate profile orientConstraints for i in range(intProfile): - + # Skip start/end profiles if not i: continue - + # Create orientConstraints startMidOriCon = mc.orientConstraint([attachLocators[0],midPointObject],profileFollowList[i-1])[0] endMidOriCon = mc.orientConstraint([attachLocators[-1],midPointObject],profileFollowList[-(i)])[0] startMidOriWt = mc.orientConstraint(startMidOriCon,q=True,weightAliasList=True) endMidOriWt = mc.orientConstraint(endMidOriCon,q=True,weightAliasList=True) - + # Set constraint weights mc.setAttr(startMidOriCon+'.'+startMidOriWt[0],1.0-(intIncrement*i)) mc.setAttr(startMidOriCon+'.'+startMidOriWt[1],(intIncrement*i)) mc.setAttr(endMidOriCon+'.'+endMidOriWt[0],1.0-(intIncrement*i)) mc.setAttr(endMidOriCon+'.'+endMidOriWt[1],(intIncrement*i)) - + # Add constraint weight attribute to profile mc.addAttr(profileList[i],ln='twist',min=0,max=1,dv=1.0-(intIncrement*i),k=True) mc.addAttr(profileList[-(i+1)],ln='twist',min=0,max=1,dv=1.0-(intIncrement*i),k=True) - + # Connect twist attribite to constraint weights startMidOriRev = mc.createNode('reverse',n=profileList[i].replace('_curve','_reverse')) endMidOriRev = mc.createNode('reverse',n=profileList[-(i+1)].replace('_curve','_reverse')) @@ -259,7 +259,7 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s mc.connectAttr(profileList[-(i+1)]+'.twist',endMidOriRev+'.inputX',f=True) mc.connectAttr(profileList[-(i+1)]+'.twist',endMidOriCon+'.'+endMidOriWt[0],f=True) mc.connectAttr(endMidOriRev+'.outputX',endMidOriCon+'.'+endMidOriWt[1],f=True) - + # Create Profile tangent constraints tangentConList = [] for i in range(len(profileGrpList)): @@ -275,22 +275,22 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s # Create constraint tangentCon = mc.tangentConstraint(tangentCurveShape,profileGrpList[i],aim=[0,0,-1],u=[0,1,0],wu=[0,1,0],wut='objectrotation',wuo=worldUpObject) tangentConList.append(tangentCon) - + # ----------------------------- # - Set profile radius values - # ----------------------------- - + # Set default profile radius values radiusList = glTools.utils.mathUtils.distributeValue(midProfile,rangeStart=minRadius,rangeEnd=maxRadius) radiusList = [glTools.utils.mathUtils.smoothStep(i,minRadius,maxRadius,0.5) for i in radiusList] for i in range(midProfile): mc.setAttr(profileList[i]+'.scale',radiusList[i],radiusList[i],radiusList[i]) mc.setAttr(profileList[-(i+1)]+'.scale',radiusList[i],radiusList[i],radiusList[i]) - + # ---------------------------- # - Generate Muscle Geometry - # ---------------------------- - + # Loft mesh between profile curves loft = mc.loft(profileList,u=0,c=0,d=3,ch=1,po=1) muscleMesh = mc.rename(loft[0],prefix) @@ -298,7 +298,7 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s muscleTess = mc.listConnections(muscleLoft+'.outputSurface',s=False,d=True,type='nurbsTessellate')[0] muscleTess = mc.rename(muscleTess,prefix+'_nurbsTessellate') mc.parent(muscleMesh,muscleGrp) - + # Set nurbsTessellate settings mc.setAttr(muscleTess+'.format',2) mc.setAttr(muscleTess+'.polygonType',1) @@ -306,33 +306,33 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s mc.setAttr(muscleTess+'.vType',1) mc.setAttr(muscleTess+'.uNumber',20) mc.setAttr(muscleTess+'.vNumber',10) - + # Add muscle mesh attributes mc.addAttr(muscleMesh,ln='precision',at='long',min=1,dv=5) mc.setAttr(muscleMesh+'.precision',k=False,cb=True) mc.addAttr(muscleMesh,ln='tangentPrecision',at='long',min=1,dv=2) mc.setAttr(muscleMesh+'.tangentPrecision',k=False,cb=True) - + mc.addAttr(muscleMesh,ln='uDivisions',at='long',min=4,dv=20) mc.setAttr(muscleMesh+'.uDivisions',k=False,cb=True) mc.addAttr(muscleMesh,ln='vDivisions',at='long',min=3,dv=10) mc.setAttr(muscleMesh+'.vDivisions',k=False,cb=True) - + mc.addAttr(muscleMesh,ln='restLength',at='float',min=0,dv=startEndDist) mc.setAttr(muscleMesh+'.restLength',k=False,cb=True) mc.addAttr(muscleMesh,ln='currentLength',at='float',min=0,dv=startEndDist) mc.setAttr(muscleMesh+'.currentLength',k=True) mc.addAttr(muscleMesh,ln='lengthScale',at='float',min=0,dv=1) mc.setAttr(muscleMesh+'.lengthScale',k=True) - + mc.addAttr(muscleMesh,ln='muscleMessage',at='message') mc.addAttr(muscleMesh,ln='muscleSpline',at='message') mc.addAttr(muscleMesh,ln='attachment',at='message',m=True) mc.addAttr(muscleMesh,ln='profile',at='message',m=True) - + mc.addAttr(muscleMesh,ln='muscleObjectType',dt='string') mc.setAttr(muscleMesh+'.muscleObjectType','geo',type='string',l=True) - + # Connect muscle mesh attributes mc.connectAttr(muscleCurve+'.message',muscleMesh+'.muscleSpline',f=True) for i in range(len(attachLocators)): @@ -341,7 +341,7 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s for i in range(len(profileList)): mc.connectAttr(profileList[i]+'.message',muscleMesh+'.profile['+str(i)+']',f=True) mc.connectAttr(muscleMesh+'.message',profileList[i]+'.muscle',f=True) - + # Connect muscle mesh attributes to curve rebuild settings mc.connectAttr(muscleMesh+'.precision',splineRebuild+'.spans',f=True) musclePreCondition = mc.createNode('condition',n=prefix+'_precision_condition') @@ -351,11 +351,11 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s mc.connectAttr(muscleMesh+'.precision',musclePreCondition+'.colorIfTrueR',f=True) mc.connectAttr(muscleMesh+'.tangentPrecision',musclePreCondition+'.colorIfFalseR',f=True) mc.connectAttr(musclePreCondition+'.outColorR',tangentRebuild+'.spans',f=True) - + # Connect musle mesh attributes to nurbsTessellate settings mc.connectAttr(muscleMesh+'.uDivisions',muscleTess+'.uNumber',f=True) mc.connectAttr(muscleMesh+'.vDivisions',muscleTess+'.vNumber',f=True) - + # Setup length calculation muscleLenCurveInfo = mc.createNode('curveInfo',n=prefix+'_length_curveInfo') mc.connectAttr(splineCurveShape+'.worldSpace[0]',muscleLenCurveInfo+'.inputCurve',f=True) @@ -367,26 +367,26 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s mc.connectAttr(muscleLenCurveInfo+'.arcLength',muscleLenDiv+'.input1X',f=True) mc.connectAttr(muscleMesh+'.restLength',muscleLenDiv+'.input2X',f=True) mc.connectAttr(muscleLenDiv+'.outputX',muscleMesh+'.lengthScale',f=True) - + # ----------- # - Cleanup - # ----------- - + # Parent start/end tangent locators mc.parent(attachLocGroup[1],attachLocators[0]) mc.parent(attachLocGroup[-2],attachLocators[-1]) - + # Parent start/end profiles mc.parent(profileGrpList[0],attachLocators[0]) mc.setAttr(profileGrpList[0]+'.t',0.0,0.0,0.0) mc.setAttr(profileGrpList[0]+'.r',0.0,0.0,0.0) mc.setAttr(profileGrpList[0]+'.s',1.0,1.0,1.0) - + mc.parent(profileGrpList[-1],attachLocators[-1]) mc.setAttr(profileGrpList[-1]+'.t',0.0,0.0,0.0) mc.setAttr(profileGrpList[-1]+'.r',0.0,0.0,0.0) mc.setAttr(profileGrpList[-1]+'.s',1.0,1.0,1.0) - + # Setup start/end profile scale compensation attachStartScaleCompNode = mc.createNode('multiplyDivide',n=prefix+'_attachStart_multiplyDivide') mc.setAttr(attachStartScaleCompNode+'.input1',1,1,1) @@ -398,13 +398,13 @@ def build(attachments=4,sections=9,sectionsSpans=8,minRadius=0.0,maxRadius=1.0,s mc.setAttr(attachEndScaleCompNode+'.operation',2) mc.connectAttr(attachLocators[-1]+'.scale',attachEndScaleCompNode+'.input2',f=True) mc.connectAttr(attachEndScaleCompNode+'.output',profileGrpList[-1]+'.scale',f=True) - + # Lock transforms mc.setAttr(muscleGrp+'.inheritsTransform',0) mc.setAttr(muscleGrp+'.t',l=True,cb=True) mc.setAttr(muscleGrp+'.r',l=True,cb=True) mc.setAttr(muscleGrp+'.s',l=True,cb=True) - + # Return result return muscleMesh @@ -418,12 +418,12 @@ def isMuscle(muscle): if not mc.objExists(muscle): print('Object "'+muscle+'" does not exis!') return False - + # Check muscle message attribute if not mc.objExists(muscle+'.muscleMessage'): print('Object "'+muscle+'" is not a valid muscle!') return False - + # Return result return True @@ -436,14 +436,14 @@ def getMuscleObjectType(muscleObject): # Check muscleObject exists if not mc.objExists(muscleObject): raise Exception('Muscle object "'+muscleObject+'" does not exist!') - + # Check muscleObjectType attribute if not mc.objExists(muscleObject+'.muscleObjectType'): raise Exception('Object "'+muscleObject+'" is not connected to a valid muscle!') - + # Get muscle object type muscleObjType = mc.getAttr(muscleObject+'.muscleObjectType') - + # Return result return muscleObjType @@ -455,7 +455,7 @@ def getMuscle(muscleObject): ''' # Get muscle object type muscleObjType = getMuscleObjectType(muscleObject) - + # Get muscle muscle = '' if muscleObjType == 'geo': @@ -473,7 +473,7 @@ def getMuscle(muscleObject): muscle = muscleConn[0] else: raise Exception('Invalid muscleObjectType value: "'+muscleObjType+'"!') - + # Return result return muscle @@ -485,12 +485,12 @@ def getAttachments(muscleObject): ''' # Get muscle muscle = getMuscle(muscleObject) - + # Get attachments attachments = mc.listConnections(muscle+'.attachment',s=True,d=False) if not attachments: raise Exception('No valid muscle attachments associated with muscleObject "'+muscleObject+'"!') - + # Return result return attachments @@ -502,12 +502,12 @@ def getProfiles(muscleObject): ''' # Get muscle muscle = getMuscle(muscleObject) - + # Get profile curves profiles = mc.listConnections(muscle+'.profile',s=True,d=False) if not profiles: raise Exception('No valid muscle profiles associated with muscleObject "'+muscleObject+'"!') - + # Return result return profiles @@ -519,12 +519,12 @@ def getSpline(muscleObject): ''' # Get muscle muscle = getMuscle(muscleObject) - + # Get profile curves spline = mc.listConnections(muscle+'.muscleSpline',s=True,d=False) if not spline: raise Exception('No valid muscle spline associated with muscleObject "'+muscleObject+'"!') - + # Return result return spline[0] diff --git a/utils/nDynamics.py b/utils/nDynamics.py index 3b98216..49bd4c5 100644 --- a/utils/nDynamics.py +++ b/utils/nDynamics.py @@ -24,7 +24,7 @@ def isNDynamicsNode(nNode): if not mc.objExists(nNode): return False # Check shape if mc.objectType(nNode) == 'transform': nNode = mc.listRelatives(nNode,s=True,ni=True,pa=True)[0] - + # Check nucleus if mc.objectType(nNode) == 'nucleus': return True # Check nCloth @@ -37,7 +37,7 @@ def isNDynamicsNode(nNode): if mc.objectType(nNode) == 'nComponent': return True # Check dynamicConstraint if mc.objectType(nNode) == 'dynamicConstraint': return True - + # Return result return False @@ -54,10 +54,10 @@ def isNType(nNode,nType): # Check shape if mc.objectType(nNode) == 'transform': nNode = mc.listRelatives(nNode,s=True,ni=True,pa=True)[0] if mc.objectType(nNode) != nType: return False - + # Return result return True - + def isNucleus(nucleus): ''' Check if the specified object is a nucleus node @@ -121,10 +121,10 @@ def getConnectedNucleus(obj): nNode = nNode[0] else: nNode = obj - + # Check nucleus connections nucleusConn = mc.listConnections(nNode,type='nucleus') - + # Return result if nucleusConn: return nucleusConn[0] else: return '' @@ -139,7 +139,7 @@ def getConnectedNNode(obj,nType=''): # Check object exists if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check nNode nNode = obj if mc.objectType(obj) == 'transform': @@ -148,27 +148,27 @@ def getConnectedNNode(obj,nType=''): if isNDynamicsNode(nNode): if not nType or nType == mc.objectType(nNode): return [nNode] - + # Check nCloth if not nType or nType == 'nCloth': nNodeConn = mc.listConnections(nNode,type='nCloth',shapes=True) if nNodeConn: return list(set(nNodeConn)) - + # Check nRigid if not nType or nType == 'nRigid': nNodeConn = mc.listConnections(nNode,type='nRigid',shapes=True) if nNodeConn: return list(set(nNodeConn)) - + # Check nParticle if not nType or nType == 'nParticle': nNodeConn = mc.listConnections(nNode,type='nParticle',shapes=True) if nNodeConn: return list(set(nNodeConn)) - + # Check nComponent if not nType or nType == 'nComponent': nNodeConn = mc.listConnections(nNode,type='nComponent',shapes=True) if nNodeConn: return list(set(nNodeConn)) - + # No nNode found, return empty result return [] @@ -212,15 +212,15 @@ def getConnectedMesh(nNode,returnShape=False): # Check nNode node if not isNDynamicsNode(nNode): nNode = getConnectedNNode(nNode) - + # Check outgoing connections meshConn = mc.listConnections(nNode,s=False,d=True,sh=returnShape,type='mesh') if meshConn: return meshConn[0] - + # Check incoming connections meshConn = mc.listConnections(nNode,s=True,d=False,sh=returnShape,type='mesh') if meshConn: return meshConn[0] - + # No mesh connections found, return empty result return '' @@ -246,7 +246,7 @@ def setActiveNucleus(nucleus): # Check nucleus if not isNucleus(nucleus): raise Exception('Object "'+nucleus+'" is not a valid nucleus node!') - + # Set active nucleus mm.eval('source getActiveNucleusNode') mm.eval('setActiveNucleusNode("'+nucleus+'")') @@ -265,14 +265,14 @@ def createNucleus(name='',setActive=True): ''' # Check nucleus name if not name: name = 'nucleus#' - + # Create nucleus node nucleus = mc.createNode('nucleus',n=name) mc.connectAttr('time1.outTime',nucleus+'.currentTime') - + # Set active nucleus if setActive: setActiveNucleus(nucleus) - + # Return result return nucleus @@ -291,38 +291,38 @@ def createNCloth(mesh,nucleus='',worldSpace=False,prefix=''): # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check prefix if not prefix: if '_' in mesh: prefix = glTools.utils.stringUtils.stripSuffix(mesh) else: prefix = mesh if ':' in prefix: prefix = prefix.split(':')[-1] - + # Check nucleus if nucleus: if not isNucleus(nucleus): print('Object "'+nucleus+'" is not a valid nucleus. Using current active nucleus!') getActiveNucleus(nucleus) - + # Set active nucleus setActiveNucleus(nucleus) - + # Create nCloth from mesh mc.select(mesh) nClothShape = mm.eval('createNCloth '+str(int(worldSpace))) nCloth = mc.listRelatives(nClothShape,p=True)[0] - + # Rename nCloth nCloth = mc.rename(nCloth,prefix+'_nCloth') nClothShape = mc.listRelatives(nCloth,s=True)[0] - + # Get outMesh outMesh = mc.listConnections(nClothShape+'.outputMesh',s=False,d=True,sh=True)[0] outMesh = mc.rename(outMesh,mesh+'ClothShape') - + # return result return nCloth - + def createNRigid(mesh,nucleus='',prefix=''): ''' @@ -337,30 +337,30 @@ def createNRigid(mesh,nucleus='',prefix=''): # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') - + # Check prefix if not prefix: if '_' in mesh: prefix = glTools.utils.stringUtils.stripSuffix(mesh) else: prefix = mesh if ':' in prefix: prefix = prefix.split(':')[-1] - + # Check nucleus if nucleus: if not isNucleus(nucleus): print('Object "'+nucleus+'" is not a valid nucleus. Using current active nucleus!') getActiveNucleus(nucleus) - + # Set active nucleus setActiveNucleus(nucleus) - + # Create nRigid from mesh mc.select(mesh) nRigidShape = mm.eval('makeCollideNCloth') nRigid = mc.listRelatives(nRigidShape,p=True,pa=True)[0] - + # Rename nCloth nRigid = mc.rename(nRigid,prefix+'_nRigid') - + # Return result return nRigid @@ -377,16 +377,16 @@ def createNParticle(ptList=[],nucleus='',prefix=''): # Check prefix if prefix: nParticle = prefix+'_nParticle' else: nParticle = 'nParticle#' - + # Check nucleus if nucleus: if not isNucleus(nucleus): print('Object "'+nucleus+'" is not a valid nucleus. Using current active nucleus!') getActiveNucleus(nucleus) - + # Set active nucleus setActiveNucleus(nucleus) - + # Create nParticles nParticle = mc.nParticle(p=ptList,n=nParticle) @@ -402,7 +402,7 @@ def softBody(geometry,nucleus='',prefix=''): ''' # Check prefix if not prefix: prefix = geometry - + # Check geometry geometryType = mc.objectType(geometry) if geometryType == 'transform': @@ -413,25 +413,25 @@ def softBody(geometry,nucleus='',prefix=''): else: geometryTransform = mc.listRelatives(geometry,p=True)[0] geometryShape = geometry - + # Check geometry type geometryType = mc.objectType(geometryShape) if geometryType == 'mesh': geometryAttribute = 'inMesh' elif geometryType == 'nurbsCurve': geometryAttribute = 'create' elif geometryType == 'nurbsSurface': geometryAttribute = 'create' else: raise Exception('Invalid geometry type ('+geometryType+')!') - + # Get geometry points mPtList = glTools.utils.base.getMPointArray(geometry) ptList = [(i[0],i[1],i[2]) for i in mPtList] - + # Create nParticles nParticle = mc.nParticle(p=ptList,n=prefix+'_nParticle') - + # Connect to geometry mc.connectAttr(geometryTransform+'.worldMatrix[0]',nParticle+'.targetGeometryWorldMatrix',f=True) mc.connectAttr(nParticle+'.targetGeometry',geometryShape+'.'+geometryAttribute,f=True) - + # Return result return nParticle @@ -450,7 +450,7 @@ def connectToNucleus(object,nucleus): # Check nucleus if not isNucleus(nucleus): preNucleusList = mc.ls(type='nucleus') - + # Check nDynamics node if isNDynamicsNode(object): nNode = object @@ -458,21 +458,21 @@ def connectToNucleus(object,nucleus): nNode = getConnectedNNode(nNode) if not nNode: raise Exception('Object "'+object+'" is not a valid nDynamics node, or connected to a valid nDynamics node!') nNode = nNode[0] - + # Check nRigid if isNRigid(nNode): connectNRigidToNucleus(nNode,nucleus,True) - + # Assign nNode to nucleus solver mc.select(nNode) mm.eval('assignNSolver '+nucleus) - + # Rename new nucleus node if not mc.objExists(nucleus): postNucleusList = mc.ls(type='nucleus') newNucleus = list(set(postNucleusList) - set(preNucleusList)) if not newNucleus: raise Exception('Unable to determine new nucleus node attached to "'+object+'"!') nucleus = mc.rename(newNucleus[0],nucleus) - + # Return result mc.select(nucleus) return nucleus @@ -493,19 +493,19 @@ def connectNRigidToNucleus(nRigid,nucleus,createNucleus=True): nRigid = getConnectedNRigid(nRigid) if not nRigid: raise Exception('Object "'+nRigid+'" is not a valid nRigid node!') nRigid = nRigid[0] - + # Check nucleus if not isNucleus(nucleus): if createNucleus: nucleus = createNucleus(nucleus) else: raise Exception('Object "'+nucleus+'" is not a valid nucleus node!') - + # Get next available index nIndex = glTools.utils.attribute.nextAvailableMultiIndex(nucleus+'.inputPassive',0) - + # Connect to nucleus mc.connectAttr(nRigid+'.currentState',nucleus+'.inputPassive['+str(nIndex)+']') mc.connectAttr(nRigid+'.startState',nucleus+'.inputPassiveStart['+str(nIndex)+']') - + # Return result return nIndex @@ -519,20 +519,20 @@ def deleteUnusedNucleusNodes(): ''' # Get existsing nucleus nodes nucleusList = mc.ls(type=nucleus) - + # Initialize return list nucleusDel = [] - + # Iterate over nodes for nucleus in nucleusList: - + # Check outgoing connections nConn = mc.listConnections(nucleus,s=False,d=True) if not nConn: nucleusDel.append(nucleus) - + # Delete unused nucleus nodes mc.delete(nucleusDel) - + # Return result return nucleusDel @@ -546,11 +546,11 @@ def deleteNCloth(nCloth): connNCloth = getConnectedNCloth(nCloth) if not connNCloth: raise Exception('Object "'+nCloth+'" is not a valid nCloth object!') nCloth = connNCloth[0] - - # Get connected mesh + + # Get connected mesh nClothMesh = getConnectedMesh(nCloth) mc.select(nClothMesh) - + # Remove nCloth mm.eval('nClothRemove') @@ -570,10 +570,10 @@ def getVertexWeights(nCloth,attr): connNCloth = getConnectedNCloth(nCloth) if not connNCloth: raise Exception('Object "'+nCloth+'" is not a valid nCloth object!') nCloth = connNCloth[0] - + # Get vertex weights wt = mc.getAttr(nCloth+'.'+attr+'PerVertex') - + # Return Result return wt @@ -591,7 +591,7 @@ def setVertexWeights(nCloth,attr,wt): connNCloth = getConnectedNCloth(nCloth) if not connNCloth: raise Exception('Object "'+nCloth+'" is not a valid nCloth object!') nCloth = connNCloth[0] - + # Set vertex weights mc.setAttr(nCloth+'.'+attr+'PerVertex',list(wt),type='doubleArray') @@ -601,11 +601,11 @@ def saveWeightList(nCloth,attr,filePath=None,force=False): # Build Weight List wt = getVertexWeights(nCloth,attr) wtList = WeightList(wt) - + # Save Weight List if filePath: filePath = wtList.saveAs(filePath,force) else: filePath = wtList.saveAs() - + # Return Result return filePath @@ -615,10 +615,10 @@ def loadWeightList(nCloth,attr,filePath=None,apply=True): # Load Weight List wt = WeightList() wt = wt.load(filePath) - + # Apply Weight List if apply: setVertexWeights(nCloth,attr,wt) - + # Return Result return wt @@ -639,21 +639,21 @@ def loadWeightMap(nCloth,attr,filePath,loadAsVertexMap=False): connNCloth = getConnectedNCloth(nCloth) if not connNCloth: raise Exception('Object "'+nCloth+'" is not a valid nCloth object!') nCloth = connNCloth[0] - + # Check file path if not os.path.isfile(filePath): raise Exception('Weight map file path "'+filePath+'" does not exist!') - + # Create file node fileName = os.path.basename(filePath) fileName = fileName.replace('.'+fileName.split('.')[-1],'') fileNode = mc.shadingNode('file',asTexture=True,n=fileName) mc.setAttr(fileNode+'.fileTextureName',filePath,type='string') - + # Connect to nCloth mc.connectAttr(fileNode+'.outAlpha',nCloth+'.'+attr+'Map',f=True) mc.setAttr(nCloth+'.'+attr+'MapType',2) # Texture Map - + # Convert to vertex map if loadAsVertexMap: mc.nBase(nCloth,e=True,textureToVertex=attr+'Map') diff --git a/utils/nParticle.py b/utils/nParticle.py index 7e93ee6..1988a70 100644 --- a/utils/nParticle.py +++ b/utils/nParticle.py @@ -8,7 +8,7 @@ def softBody(geometry,prefix=''): ''' # Check prefix if not prefix: prefix = geometry - + # Check geometry geometryType = mc.objectType(geometry) if geometryType == 'transform': @@ -19,24 +19,24 @@ def softBody(geometry,prefix=''): else: geometryTransform = mc.listRelatives(geometry,p=True)[0] geometryShape = geometry - + # Check geometry type geometryType = mc.objectType(geometryShape) if geometryType == 'mesh': geometryAttribute = 'inMesh' elif geometryType == 'nurbsCurve': geometryAttribute = 'create' elif geometryType == 'nurbsSurface': geometryAttribute = 'create' else: raise Exception('Invalid geometry type ('+geometryType+')!') - + # Get geometry points mPtList = glTools.utils.base.getMPointArray(geometry) ptList = [(i[0],i[1],i[2]) for i in mPtList] - + # Create nParticles nParticle = mc.nParticle(p=ptList,n=prefix+'_nParticle') - + # Connect to geometry mc.connectAttr(geometryTransform+'.worldMatrix[0]',nParticle+'.targetGeometryWorldMatrix',f=True) mc.connectAttr(nParticle+'.targetGeometry',geometryShape+'.'+geometryAttribute,f=True) - + # Return result return nParticle diff --git a/utils/namespace.py b/utils/namespace.py index fdac029..b9d3b66 100644 --- a/utils/namespace.py +++ b/utils/namespace.py @@ -13,15 +13,15 @@ def getNS(obj,topOnly=True): # Check Object if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check namespace NS = '' if not obj.count(':'): return NS - + # Get Namespace if topOnly: NS = obj.split(':')[0] else: NS = obj.replace(':'+obj.split(':')[-1],'') - + # Return namespace return NS @@ -41,12 +41,12 @@ def getNSList(objList,topOnly=True): NS = getNS(obj,topOnly=topOnly) if not NS in NSlist: NSlist.append(NS) - + # Remove Duplicates (Done Above!) #returnNSlist = [] #[returnNSlist.append(NS) for NS in NSlist if not NS in returnNSlist] #NSlist = list(set(NSlist)) - Set does not return corrent order! - + # Return result return NSlist @@ -58,16 +58,16 @@ def getAllNS(excludeList=['UI','shared']): ''' # Get all scene namespaces nsList = mc.namespaceInfo(lon=True) - + # Remove exclude list items [nsList.remove(ns) for ns in excludeList if nsList.count(ns)] - + # Return result return nsList def resetNS(): ''' - Reset to global namespace (':') + Reset to global namespace (':') ''' # Reset scene namespace mc.namespace(set=':') @@ -83,10 +83,10 @@ def deleteNS(NS): raise Exception('Invalid namespace specified!') if not mc.namespace(ex=NS): raise Exception('Namespace "'+NS+'" does not exist!') - + # Print Message print('Deleting Namespace: '+NS) - + # Delete namespace mc.namespace(mv=[NS,':'],f=True) mc.namespace(rm=NS) @@ -102,16 +102,16 @@ def moveNS(srcNS,dstNS): # Check NS if not mc.namespace(exists=srcNS): raise Exception('Source namespace "'+srcNS+'" does not exist!') - + # Check Destination NS if not mc.namespace(exists=dstNS): - + # Create newNS dstNS = mc.namespace(add=dstNS,f=True) - + # Move namespace mc.namespace(mv=(srcNS,dstNS),f=True) - + # Return newNS return newNS @@ -130,11 +130,11 @@ def renameNS(NS,newNS,parentNS=None): raise Exception('Namespace "'+NS+'" does not exist!') if mc.namespace(exists=newNS): raise Exception('Namespace "'+newNS+'" already exist!') - + # Rename NS if not parentNS: mc.namespace(rename=[NS,newNS]) else: mc.namespace(rename=[NS,newNS],parent=parentNS) - + # Return newNS return newNS @@ -155,19 +155,19 @@ def getAllInNS(ns): # Check namespace if not mc.namespace(ex=ns): raise Exception('Namespace "'+ns+'" does not exist!') - + # Get Current Namespace currNS = mc.namespaceInfo(currentNamespace=True) - + # Set Namespace mc.namespace(set=ns) - + # List all objects in namespace nsNodeList = mc.namespaceInfo(lod=True,dagPath=True) - + # Reset Namespace mc.namespace(set=currNS) - + # Return result return nsNodeList @@ -184,25 +184,25 @@ def addHierarchyToNS(root,NS,replaceNS=True): # ========== # - Checks - # ========== - + # Check namespace if not mc.namespace(ex=NS): mc.namespace(add=NS) - + # Check Hierarchy Root if not mc.objExists(root): raise Exception('Hierarchy root object "'+root+'" does not exist!') - + # ====================== # - Get Hierarchy List - # ====================== - + hier = mc.ls(mc.listRelatives(root,ad=True,pa=True),transforms=True) hier.append(root) - + # ==================== # - Add to Namespace - # ==================== - + for i in range(len(hier)): item = hier[i] currNS = getNS(item,topOnly=False) @@ -211,9 +211,9 @@ def addHierarchyToNS(root,NS,replaceNS=True): else: mc.rename(item,NS+':'+item) hier[i] = item - + # ================= # - Return Result - # ================= - - return hier \ No newline at end of file + + return hier diff --git a/utils/namespacer.py b/utils/namespacer.py index 89a6782..a5c4e5e 100644 --- a/utils/namespacer.py +++ b/utils/namespacer.py @@ -6,24 +6,24 @@ import maya.mel as mm import maya.utils as mu -DEFAULT_NODES = [u'characterPartition', u'defaultHardwareRenderGlobals', u'defaultLayer', u'defaultLightList1', u'defaultLightSet', -u'defaultObjectSet', u'defaultRenderGlobals', u'defaultRenderLayer', u'defaultRenderLayerFilter', u'defaultRenderQuality', -u'defaultRenderUtilityList1', u'defaultResolution', u'defaultShaderList1', u'defaultTextureList1', u'dof1', u'dynController1', -u'globalCacheControl', u'hardwareRenderGlobals', u'hyperGraphInfo', u'hyperGraphLayout', u'ikSystem', u'initialMaterialInfo', -u'initialParticleSE', u'initialShadingGroup', u'lambert1', u'layerManager', u'layersFilter', u'lightLinker1', u'lightList1', -u'objectNameFilter4', u'objectScriptFilter10', u'objectTypeFilter69', u'objectTypeFilter70', u'objectTypeFilter71', -u'particleCloud1', u'postProcessList1', u'relationshipPanel1LeftAttrFilter', u'relationshipPanel1RightAttrFilter', +DEFAULT_NODES = [u'characterPartition', u'defaultHardwareRenderGlobals', u'defaultLayer', u'defaultLightList1', u'defaultLightSet', +u'defaultObjectSet', u'defaultRenderGlobals', u'defaultRenderLayer', u'defaultRenderLayerFilter', u'defaultRenderQuality', +u'defaultRenderUtilityList1', u'defaultResolution', u'defaultShaderList1', u'defaultTextureList1', u'dof1', u'dynController1', +u'globalCacheControl', u'hardwareRenderGlobals', u'hyperGraphInfo', u'hyperGraphLayout', u'ikSystem', u'initialMaterialInfo', +u'initialParticleSE', u'initialShadingGroup', u'lambert1', u'layerManager', u'layersFilter', u'lightLinker1', u'lightList1', +u'objectNameFilter4', u'objectScriptFilter10', u'objectTypeFilter69', u'objectTypeFilter70', u'objectTypeFilter71', +u'particleCloud1', u'postProcessList1', u'relationshipPanel1LeftAttrFilter', u'relationshipPanel1RightAttrFilter', u'renderGlobalsList1', u'renderLayerFilter', u'renderLayerManager', u'renderPartition', u'renderingSetsFilter', u'shaderGlow1', -u'strokeGlobals', u'test:brush1', u'time1', u'|front', u'|front|frontShape', u'|persp', u'|persp|perspShape', u'|side', -u'|side|sideShape', u'|top', u'|top|topShape', u'front', u'frontShape', u'persp', u'perspShape', u'side', +u'strokeGlobals', u'test:brush1', u'time1', u'|front', u'|front|frontShape', u'|persp', u'|persp|perspShape', u'|side', +u'|side|sideShape', u'|top', u'|top|topShape', u'front', u'frontShape', u'persp', u'perspShape', u'side', u'sideShape', u'top', u'topShape', u'polyMergeEdgeToolDefaults', u'polyMergeFaceToolDefaults'] HISTORY_STACK = [] - + class NamespacerError(Exception): pass - - + + class InvalidNamespaceError(Exception): pass @@ -77,11 +77,11 @@ def getAllNS(): grandchildspaces = mc.namespaceInfo(lon=True) if grandchildspaces: childspaces.extend(grandchildspaces) - + #remove default namespaces if namespaces.count('UI'): namespaces.remove('UI') if namespaces.count('shared'): namespaces.remove('shared') - + mc.namespace(set=(":" + curNS)) namespaces.sort() return namespaces @@ -91,17 +91,17 @@ def getRelatedNS(ns, mode='children'): ''' Find the namespaces that are part of a namespace provieded. You can use this function to find all the namespaces that are children of a given namespace, all the namespaces that are parents of a given namespace. - + @todo: add ability for siblings - + @note: this does not act like the old mel version of this function, this will not return the enire tree (cousins and all) for a namespace, you can return the children of a namespace (recursively), the parents (full namespaces for each parent), or both. - + @param ns: the namespace to find relatives for @type ns: str @param mode: the type of relatives to locate, options are "children", "parents", "both" @type mode: str - + @return: a list of namespaces @rtype: list(str) ''' @@ -110,20 +110,20 @@ def getRelatedNS(ns, mode='children'): vaildModes = ['children', 'parents', 'both'] if not mode in vaildModes: raise Exception('The mode specified "%s" is not a valid choice %s' % (mode, vaildModes)) - + # clean the namespace ns = cleanNS(ns) - + # make sure the namespace specified exists if not mc.namespace(exists=":%s" % ns): raise InvalidNamespaceError('The namespace "%s" does not exist, unable to locate relatives' % ns) - + # get the current namespace curNS = mc.namespaceInfo(cur=True) - + # create the return list relatives = [ns] - + if mode == 'parents' or mode == 'both': # break the namespace into its parts nsParts = ns.split(':') @@ -134,12 +134,12 @@ def getRelatedNS(ns, mode='children'): base.append(str(part)) # add the new item relatives.append(":".join(base)) - - + + if mode == 'children' or mode == 'both': # create a queue to find children recursively on queue = collections.deque([ns]) - + # cycle through the namespaces to recurse on while queue: cur = queue.popleft() @@ -152,58 +152,58 @@ def getRelatedNS(ns, mode='children'): children = mc.namespaceInfo(listOnlyNamespaces=True) if children: queue.extend(children) - + # set the namespace back curNS = cleanNS(curNS) mc.namespace(set=":%s" % curNS) - + return relatives - + def separateNS(name): logger.warning('DEPRECATED METHOD: namespacer.separateNS(): use splitNS() instead') return splitNS(name) - + def splitNS(name): ''' Take the namespace on the string and return a tuple with the namespace in the first field, and the short name in the second - + @param name: name to separate namespace from @type: str - + @return: (namespace, baseName) @rtype: tuple(str, str) ''' if not name: return None, None - + # remove full paths path = [x for x in name.split('|') if x] name = path[-1] - + stack = [x for x in name.split(":") if x] - + if stack == []: return ("", "") if len(stack) == 1: return ("", stack[0]) else: return (':'.join(stack[:-1]), stack[-1]) - + def getObjectsOfNS(namespace, filterOut=None, recursive=False): ''' ''' filterOut = filterOut if filterOut else [] - + # create a set for the objects objects = set() - + # handle recursive namespaces = [cleanNS(namespace)] if recursive: namespaces.extend(getRelatedNS(namespace)) - + # cycle through the objects for ns in namespaces: # get the objects in that namespace @@ -214,9 +214,9 @@ def getObjectsOfNS(namespace, filterOut=None, recursive=False): filterObjects.update(set(mc.ls(':%s:*' % ns, type=filterItem))) # remove the filterObjects from allObjects and push them into the objects set objects.update(allObjects.difference(filterObjects)) - + return objects - + def exists(namespace): namespace = cleanNS(namespace) @@ -227,29 +227,29 @@ def addNS(namespace): #logger.warning('DEPRECATED METHOD: namespacer.addNS(): use createNS() instead') return createNS(namespace) - + def createNS(namespace): ''' Add a namespace to the scene. This namespace can be nested and already exist. - + @param namespace: a namespace to create @type namespace: str ''' # clean the namespace provided namespace = cleanNS(namespace) - + # check that the namespace exists if mc.namespace(exists=':%s' % namespace): return namespace - + # see if there is a maya node with the same name as the namespace (as this will cause your namespace to increment) if mc.objExists(namespace): raise NamespacerError('Unable to add namespace "%s" to your scene since a node exists with the same name' % namespace) - + # get the current namespace curNS = mc.namespaceInfo(cur=True) mc.namespace(set=":") - + # split the namespace apart parts = namespace.split(":") # create each part @@ -260,27 +260,27 @@ def createNS(namespace): mc.namespace(add=part) # set the current namespace to the part created mc.namespace(set=part) - + # set it back mc.namespace(set=':%s' % curNS) - + # check that it was made if not mc.namespace(exists=":%s" % namespace): raise NamespacerError('The namespace "%s" was not created, current namespaces: %s' % (namespace, getAllNS())) - - return namespace - + + return namespace + def pushNS(namespace=':'): ''' - Stores the current namespace in HISTORY_STACK stack, and sets the current namespace to value of "namespace" arg. + Stores the current namespace in HISTORY_STACK stack, and sets the current namespace to value of "namespace" arg. Original namespace can be restored using popNS(). Note: this does not append to the actual namespace, but acts more like a history of full namespaces. ''' HISTORY_STACK.append(':'+mc.namespaceInfo(cur=True)) namespace = ':' + namespace if namespace[0] != ':' else namespace mc.namespace(set=namespace) - + def popNS(): ''' @@ -291,14 +291,14 @@ def popNS(): else: logger.warning('popNS() failed - the namespace history stack is empty. Current namespace has been set to ":"') mc.namespace(set=':') - - - + + + def setLiveNS(namespace): ''' Set the current namespace, this will cause all items created to be in this namespace. @note: this namespace does not need to exist, it will be created otherwise - + @param namespace: the namespace to create/set @type namespace: str ''' @@ -314,23 +314,23 @@ def setLiveNS(namespace): if not curNS == namespace: raise NamespacerError('The namespace "%s" was not set, current namespace is "%s"'\ % (namespace, curNS)) - + return True - + def removeUnusedNS(namespace=None): ''' Remove all namespaces that have no children ''' curNS = mc.namespaceInfo(cur=True) - + if namespace: namespaces = getRelatedNS(namespace) else: namespaces = getAllNS() - + namespaces.reverse() - + for ns in namespaces: try: mc.namespace(rm=ns) @@ -338,71 +338,71 @@ def removeUnusedNS(namespace=None): raise except: pass - + mc.namespace(set=':') if mc.namespace(exists=curNS): mc.namespace(set=curNS) - - + + def cleanNS(origNamespace): ''' Clean the namespace provided (removes additional colons) - + Example: ":jack::bar:fred:" ---> jack:bar:fred - + @param origNamespace: the dirty namespace to clean @type origNamespace: str - + @return: a correctly coloned namespace "foo:bar" @rtype: str - + ''' # handle namespace of None, False, "" origNamespace = origNamespace if origNamespace else "" - + cleaned = ":".join([x for x in origNamespace.split(":") if x]) if cleaned: return cleaned else: return ":" - + def renameNS(origNamespace, newNamespace): ''' Move the objects in one namespace to another namespace - + @note: this will handle renaming the world namespace but world ":" can never be deleted. This means that it will always return False when renaming world. It will however do its best to rename everything in the world namespace to the name specified - + @param origNamespace: the name of the namespace you want to rename @type origNamespace: str @param newNamespace: the new name for your namespace @type newNamespace: str - + @return: success @rtype: boolean ''' # clean the namespaces origNamespace = cleanNS(origNamespace) newNamespace = cleanNS(newNamespace) - + # check if origNamespace == newNamespace: logger.info('You are attempting to rename a namespace to the same name... nothing to move') return True - + if not mc.namespace(exists=":"+origNamespace): logger.error('The namespace provided "%s" for renaming does not exist, unable to continue') return False - + # get the current namespcae curNS = mc.namespaceInfo(cur=True) mc.namespace(set=":") - + # create the new namespace addNS(newNamespace) - + # if renaming the world namespace ":", we have to use append since it will not allow you to move world into a child ns if origNamespace == ':': setNS(mc.ls(), newNamespace, force=True) @@ -410,22 +410,22 @@ def renameNS(origNamespace, newNamespace): else: # move it mc.namespace(force=True, mv=[origNamespace, newNamespace]) - + # delete the origional deleteNS(origNamespace) - + # set the namespace back if exists(curNS): mc.namespace(set=curNS) - + stillExists = exists(origNamespace) - + if stillExists: logger.warning('The namespace "%s" was renamed to "%s" but it was not successfully deleted, some nodes may still be in origional namespace' % origNamespace, newNamespace) - + # return False if the namespace was not fully renamed return not stillExists - + def deleteAllNS(): ''' @@ -433,56 +433,56 @@ def deleteAllNS(): namespaces = getAllNS() for namespace in namespaces: deleteNS(namespace) - + return True - - + + def deleteNS(namespace): ''' Delete a namespace from the scene, move all objects into world namespace during delete - + @return: all the object in the namespace after moving it - may be renamed @rtype: list(str) ''' # clean the namespace provided namespace = cleanNS(namespace) - + # if world, stop if namespace == ":": return [] - + # get the current namespace curNS = mc.namespaceInfo(cur=True) setLiveNS(":") - + # see if the namespace provided exists if not mc.namespace(exists=namespace): logger.debug('the namespace "%s" is not in your scene, that means its deleted!' % namespace) return [] - + # get all the nodes currently in world namespace preSet = set(mc.ls(":*", dag=True, dep=True)) - + # move logger.debug('attempting to move namespace "%s"' % namespace) mc.namespace(mv=(namespace, ":"), force=True) - + # get all the node after the move (includes renames postSet = set(mc.ls(":*", dag=True, dep=True)) - + # get the ones that are new diffSet = postSet.difference(preSet) - + # remove the origional namespace mc.namespace(rm=namespace, force=True) - + # set the namespace back if mc.namespace(exists=curNS): setLiveNS(curNS) - + if exists(namespace): logger.warning('The namespace %s was not successfully deleted (likely due to references in namespace' % namespace) - + # return them return list(diffSet) @@ -492,38 +492,38 @@ def stripNS(nodes, force=True, autoExpandShapes=True): ''' if not nodes: return {} - + curNS = mc.namespaceInfo(cur=True) setLiveNS(":") - + mapping = {} - + # process the nodes nodes = _processNodes(nodes, autoExpandShapes) - + # cycle through the objects for node in nodes: - + # check if default if node in DEFAULT_NODES: continue - + # split the namespace ns, baseNode = splitNS(node) - + # if node isn't namespaced, key == value == node if not ns: mapping[node] = node continue - + # see if the non-namespaced node exists if mc.objExists(baseNode) and not force: continue - + newName = mc.rename(node, baseNode) mapping[node] = newName - - + + setLiveNS(curNS) return mapping @@ -535,24 +535,24 @@ def appendNS(nodes, namespace, force=True, autoExpandShapes=True): provided. It will detect whether or not a name conflict will result. If the force flag is set to true, it will rename the object and allow maya to number it to resolve the conflict. If false, it will not change the namespace. - + This will return the names of the nodes that were renamed with the new namespace. This will include any shape nodes for the nodes provided. - + @param objList: a list of objects to have their namespace altered @type objList: list(str) @param namespace: the namespace to apply to the objList @type namespace: str @param force: whether or not to force the namespace in the event it will result in a name conflict @type force: bool - + @return: dictionary of origional nodes to new names @rtype: dict ''' logger.warning('DEPRECATED: namespacer.appendNS: use setNS() instead') return setNS(nodes, namespace, force=force, autoExpandShapes=autoExpandShapes) - - + + def setNS(nodes, namespace, force=True, autoExpandShapes=True, prefix=False): ''' Set Namespace takes the namespace provided and sets it as the namespace @@ -560,7 +560,7 @@ def setNS(nodes, namespace, force=True, autoExpandShapes=True, prefix=False): provided. It will detect whether or not a name conflict will result. If the force flag is set to true, it will rename the object and allow maya to number it to resolve the conflict. If false, it will not change the namespace. - + @param objList: a list of objects to have their namespace altered @type objList: list(str) @param namespace: the namespace to apply to the objList @@ -569,54 +569,54 @@ def setNS(nodes, namespace, force=True, autoExpandShapes=True, prefix=False): @type force: bool @param prefix: whether to use the namespace provided to prefix existing namespaces as opposed to flat out replacing @type prefix: bool - + @return: dictionary of origional nodes to new names @rtype: dict ''' if not nodes: return {} - + namespace = addNS(namespace) curNS = mc.namespaceInfo(cur=True) setLiveNS(":") - + mapping = {} - + # process the nodes nodes = _processNodes(nodes, autoExpandShapes) # cycle through the objects for node in nodes: - + # check if default if node in DEFAULT_NODES: continue - + # split the namespace ns, baseNode = splitNS(node) - + if prefix: applyNamespace = namespace + ":" + ns applyNamespace = addNS(applyNamespace) else: applyNamespace = namespace - + # generate the new name newNode = applyNamespace + ":" + baseNode - + # see if the non-namespaced node exists if mc.objExists(newNode) and not force: logger.warning('namespacer.setNS(): skipping renaming "%s" to "%s" because a name conflict will result, use force flag to apply change' % (node, newNode)) continue - + try: newNode = mc.rename(node, newNode) except Exception, e: logger.warning('unable to change namespace on %s to %s: %s' % (node, namespace, e)) continue mapping[node] = newNode - - + + setLiveNS(curNS) return mapping @@ -626,34 +626,34 @@ def prefixNS(nodes, namespace, force=True, autoExpandShapes=True): Prefix a namespace on a list of nodes, while maintining their current namespace after the one being added. ''' raise NotImplementedError('Not yet created') - + def searchReplaceNS(nodes, search, replace, force=True, autoExpandShapes=True): ''' ''' curNS = mc.namespaceInfo(cur=True) setLiveNS(":") - + mapping = {} - + search = cleanNS(search) replace = cleanNS(replace) - + if search == ":": logger.error('You are attempting to searchReplaceNS without any search string.. use appendNS for this functionality') return {} - + # process the nodes nodes = _processNodes(nodes, autoExpandShapes) - + for node in nodes: # check if default if node in DEFAULT_NODES: continue - + # split the namespace ns, baseNode = splitNS(node) - + if ns.count(search): newNS = cleanNS(ns.replace(search, replace)) newNode = newNS + ":" + baseNode @@ -662,10 +662,10 @@ def searchReplaceNS(nodes, search, replace, force=True, autoExpandShapes=True): addNS(newNS) newNode = mc.rename(node, newNode) mapping[node] = newNode - + return mapping - - + + def _processNodes(nodes, autoExpandShapes=True): newNodes = set() # if expanding to shapes @@ -679,27 +679,27 @@ def _processNodes(nodes, autoExpandShapes=True): continue # add the node newNodes.add(node) - + # handle shapes if autoExpandShapes: shapes = mc.listRelatives(node, shapes=True, pa=True) if shapes: newNodes.update(set(shapes)) - + # sort the nodes so we rename them in the right order nodes = sorted(mc.ls(list(newNodes), long=True)) nodes.reverse() return nodes - + # This converts a namespace to a list (removes empty spots that a split might leave behind) (":set:asset:" >> ['set', 'asset']) def namespaceToList(namespace): ''' Take a namespace and convert it to a list of parts (like a split but ensures that it is clean, no empty elements) - + @param namespace: the namespace to turn into a list @type namespace: str - + @return: list of elements in the namespace (split on the :) @rtype: list(str) ''' @@ -712,7 +712,7 @@ def listToNamespace(namespaceList): removed. @param namespaceList: a list of strings to turn into a namespace @type namespaceList: list(str) - + @return: the namespace @rtype: str ''' @@ -722,10 +722,10 @@ def listToNamespace(namespaceList): def importToNamespace(filePath, namespace, group=False, removeExistingNamespaces=False): ''' Import a file into maya with the namespace provided - + @todo: could using the mc.file(rnn) flag which returns new nodes be used to optimize this? @note: nested namespaces are supported - + @param filepath: the filepath to imported into your scene @type filepath: str @param namespace: the namespace to imported into @@ -733,56 +733,56 @@ def importToNamespace(filePath, namespace, group=False, removeExistingNamespaces @param removeExistingNamespaces: remove namespaces that were in the file your are importing as opposed to just adding a namespace in front of all the nodes imported #type removeExistingNamespaces: bool - + @return: success @rtype: boolean ''' # clean the namespace namespace = cleanNS(namespace) - + # checks if not os.path.isfile(filePath): raise Exception('The filepath "%s" does not exist, unable to reference into the "%s" namespace'\ % (filePath, namespace)) - + # record the current objects in the namespace we are importing to origObjects = set(mc.ls()) # get the current namespace curNS = mc.namespaceInfo(cur=True) mc.namespace(set=":") - + # create a temp namespace tempNS = generateTmpNamespace('importToNamespaceTmp', create=False) - + # now impot into the namespace provided mc.file(filePath, i=True, namespace=tempNS, groupReference=group) - + # find all namespaces in the tempNS (if imported nodes were already in namespace it will be like tmpNS:foo:bar) if removeExistingNamespaces: namespaces = sorted(getRelatedNS(tempNS)) namespaces.reverse() else: namespaces = [tempNS] - + # now move the namespaces to the desired one for crap in namespaces: renameNS(crap, namespace) removeUnusedNS() - + # cleanup setLiveNS(curNS) - + # get all the new objects in the namespace diffObjects = set(mc.ls()).difference(origObjects) - + #logger.info('importToNamespace() took %s seconds' % mc.timerX(startTime=timer)) return diffObjects - - + + def generateTmpNamespace(base='tmpNS', create=False): ''' Create a temp namespace in your scene. - + @param base: the base of the namespace @type base: str @return: the new namespace name @@ -792,36 +792,36 @@ def generateTmpNamespace(base='tmpNS', create=False): while mc.namespace(exists=base): base+=str(cnt) cnt+=1 - + if create: base = addNS(base) - + return base - - + + def referenceToNamespace(filepath, namespace=None): ''' Reference a file into maya with the namespace provided - + @note: nested namespaces are supported @todo: add groupReference flag to reference to create a group automatically - + @param filepath: the filepath to reference into your scene @type filepath: str @param namespace: the namespace to reference into @type namespace: str - + @return: The reference node created from the reference @rtype: str ''' if not os.path.isfile(filepath): raise Exception('The filepath "%s" does not exist, unable to reference into the "%s" namespace'\ % (filepath, namespace)) - + # get the current namespace curNS = mc.namespaceInfo(cur=True) mc.namespace(set=":") - + # split the namespace, set current one, and reference the file namespace = namespaceToList(cleanNS(namespace)) if not namespace: @@ -831,17 +831,17 @@ def referenceToNamespace(filepath, namespace=None): referencedNodes = mc.file(filepath, r=True, namespace=namespace[-1], rnn=True) else: referencedNodes = mc.file(filepath, r=True, namespace=namespace[0], rnn=True) - + # cleanup setLiveNS(curNS) - + refNodes = mc.ls(referencedNodes, type='reference', long=True) if refNodes: - return refNodes[0] + return refNodes[0] else: raise NamespacerError('No reference node created from reference to %s' % filepath) - + def nukeNamespace(namespace): ''' Remove a namespace and all the nodes in it from your scene. This will delete all nodes possible as well as remove any referenced @@ -851,16 +851,16 @@ def nukeNamespace(namespace): namespace = cleanNS(namespace) if namespace == ':': raise NamespacerError('You can not nuke the world ":" namespace!') - + # get the nodes in the namespace nodes = getObjectsOfNS(namespace) if not nodes: deleteNS(namespace) return True - + # create a problem flag for the deleteing non referenced nodes problemFlag = False - + # see if the namespace is referenced - must check all nodes in that namespace (faster way anyone?) for node in nodes: # check if the node is referenced @@ -875,7 +875,7 @@ def nukeNamespace(namespace): except Exception, e: raise NamespacerError('%s Exception: %s' % (nukeMessage, e)) break - + # after unloading reference re-aquire all the nodes in the namespace nodes = getObjectsOfNS(namespace) # cycle through the nodes in the namespace to delete them @@ -886,17 +886,17 @@ def nukeNamespace(namespace): except: logger.debug('unloadNamespace was unable to delete the namespaced node "' + str(n) + '" during unload procedure..') problemFlag = True - + # delete the namespace deleteNS(namespace) - + # timer if problemFlag: logger.info('nukeNamespace encountered some issues while deleting nodes in the namespace "'+namespace+\ '". However, your scene should still be usable.') else: logger.info('nukeNamespace successfully unloaded the namespace "' + namespace + '" from your scene.') - + return True diff --git a/utils/nonUniqueCheck.py b/utils/nonUniqueCheck.py index d8b0a44..7010324 100644 --- a/utils/nonUniqueCheck.py +++ b/utils/nonUniqueCheck.py @@ -2,7 +2,7 @@ def check(): ''' - Non-Unique Checker looks for non unique node names. + Non-Unique Checker looks for non unique node names. It will separate shape, dag and dep nodes when reporting. ''' @@ -10,23 +10,23 @@ def check(): dagErrors=[] # hold all the nonunique DAG items shapeErrors=[] # hold all the nonunique Shape items depErrors=[] # hold all the nonunique DG items - + dag = mc.ls(dag=True) shapes = mc.ls(geometry=True) dep = mc.ls(dep=True) - + for item in shapes: while dag.count(item): dag.remove(item) - + for item in shapes: while dep.count(item): dep.remove(item) - + for item in dag: while dep.count(item): dep.remove(item) - + # Print header statement print 'Non-Unique Checker' @@ -37,24 +37,24 @@ def check(): for item in dag: if item.count('|'): dagErrors.append(item) print '\n'.join(sorted(dagErrors)) + '\n' - + print 'DEP NODES' print '------------' for item in dep: if item.count('|'): depErrors.append(item) print '\n'.join(sorted(depErrors)) + '\n' - + print 'SHAPE NODES' print '------------' for item in shapes: if item.count('|'): shapeErrors.append(item) print '\n'.join(sorted(shapeErrors)) + '\n' - + del dep del dag del shapes - + mc.select(cl=True) - + print '==========================================' print ('Non-Unique Check located ' + str(len(dagErrors) + len(depErrors) + len(shapeErrors)) + ' errors.') diff --git a/utils/osUtils.py b/utils/osUtils.py index edbb41b..81fedef 100644 --- a/utils/osUtils.py +++ b/utils/osUtils.py @@ -12,14 +12,14 @@ def getFileList(path,filesOnly=False): # Check path if not os.path.isdir(path): raise Exception('Invalid path! ("'+path+'")') - + # Get file list fileList = os.listdir(path) - + # Filter if filesOnly: fileList = [i for i in fileList if not os.path.isdir(path+'/'+i)] - + # Return Result return fileList @@ -29,11 +29,11 @@ def searchAndReplaceFilename(path,search,replace): # Check path if not os.path.isdir(path): raise Exception('Invalid path! ("'+path+'")') - + # Get dir list fileList = os.listdir(path) fileList.sort() - + for file in fileList: if file.count(search): newfile = file.replace(search,replace) diff --git a/utils/poseSpace.py b/utils/poseSpace.py index f5a583c..38cd5dd 100644 --- a/utils/poseSpace.py +++ b/utils/poseSpace.py @@ -17,62 +17,62 @@ def poseDrivenAttr(poseTransform,poseAxis='x',targetAttr,remapValue=False,prefix # ---------- # - Checks - # ---------- - + # Check pose transform if not mc.objExists(poseTransform): raise Exception('PoseTransform "'+poseTransform+'" does not exist!') - + # Check target attribute if not mc.objExists(targetAttr): raise Exception('Target attribute "'+targetAttr+'" does not exist!') - + # Check reference axis poseAxis = poseAxis.lower() if not poseAxis in ['x','y','z']: raise Exception('Invalid pose axis! Valid pose axis values are "x" "y" and "z"!!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(poseTransform) - + # ---------------------------------- # - Create poseReference transform - # ---------------------------------- - + poseReference = prefix+'_poseReference' poseReference = mc.duplicate(transform,parentOnly=True,n=poseReference) - + # Add poseTransform message attribute mc.addAttr(poseReference,ln='poseTransform',at='message') mc.connectAttr(poseTransform+'.message',poseReference+'.poseTransform',f=True) - + # ------------------------------------ # - Create vector comparison network - # ------------------------------------ - + poseVector = {'x':[1,0,0],'y':[0,1,0],'z':[0,0,1]}[poseAxis] - + # - Pose Transform Vector poseVecDotProduct = mc.createNode('vectorProduct',n=prefix+'_poseVector_vectorProduct') mc.setAttr(poseVecDotProduct+'.operation',3) # Vector Matric Product mc.setAttr(poseVecDotProduct+'.input',poseVector[0],poseVector[1],poseVector[2]) mc.setAttr(poseVecDotProduct+'.normalizeOutput',1) mc.connectAttr(poseTransform+'.worldMatrix[0]',poseVecDotProduct+'.matrix',f=True) - + # - Pose Reference Vector referenceVecDotProduct = mc.createNode('vectorProduct',n=prefix+'_referenceVector_vectorProduct') mc.setAttr(referenceVecDotProduct+'.operation',3) # Vector Matric Product mc.setAttr(referenceVecDotProduct+'.input',poseVector[0],poseVector[1],poseVector[2]) mc.setAttr(referenceVecDotProduct+'.normalizeOutput',1) mc.connectAttr(poseReference+'.worldMatrix[0]',referenceVecDotProduct+'.matrix',f=True) - + # - Pose Vector Comparison vectorCompareDotProduct = mc.createNode('vectorProduct',n=prefix+'_vectorCompare_vectorProduct') mc.setAttr(vectorCompareDotProduct+'.operation',1) # Dot Product mc.setAttr(vectorCompareDotProduct+'.normalizeOutput',1) mc.connectAttr(poseVecDotProduct+'.output',vectorCompareDotProduct+'.input1') mc.connectAttr(referenceVecDotProduct+'.output',vectorCompareDotProduct+'.input2') - + # ----------------------- # - Clamp output values - # ----------------------- @@ -80,7 +80,7 @@ def poseDrivenAttr(poseTransform,poseAxis='x',targetAttr,remapValue=False,prefix mc.connectAttr(vectorCompareDotProduct+'.outputX',poseClamp+'.inputR',f=True) mc.setAttr(poseClamp+'.minR',0.0) mc.setAttr(poseClamp+'.maxR',1.0) - + # ----------------------- # - Remap output Values - # ----------------------- @@ -91,9 +91,9 @@ def poseDrivenAttr(poseTransform,poseAxis='x',targetAttr,remapValue=False,prefix mc.connectAttr(remapValNode+'.outValue',targetAttr,f=True) else: mc.connectAttr(poseClamp+'.outputR',targetAttr,f=True) - + # ----------------- # - Return Result - # ----------------- - + return poseReference diff --git a/utils/primvar.py b/utils/primvar.py index 410bdd8..cabe20d 100644 --- a/utils/primvar.py +++ b/utils/primvar.py @@ -18,7 +18,7 @@ def addRmanPrimVar(mesh,attrName,attrType='float',paintable=False): ''' # Prefix attr attr = '' - + # Data type if attrType == 'float': dataType = 'doubleArray' @@ -34,23 +34,23 @@ def addRmanPrimVar(mesh,attrName,attrType='float',paintable=False): attr = 'rmanC'+attrName else: raise Exception('Invalid attribute type! Accepted values are: "float", "vector", "color" and "string".') - + # Check mesh if not glTools.utils.mesh.isMesh(mesh): raise Exception('Mesh "'+mesh+'" does not exist!!') - + # Check attr if mc.objExists(mesh+'.'+attr): raise Exception('Attribute "'+mesh+'.'+attr+'" already exists!!') - + # Get shape meshShape = mc.listRelatives(mesh,s=True,ni=True,pa=True) if not meshShape: raise Exception('Unable to determine shape for mesh "'+mesh+'"!!') - + # Add attribute mc.addAttr(meshShape[0],ln=attr,dt=dataType) - + # Make paintable if paintable: mc.makePaintable('mesh',attr,attrType=dataType) @@ -75,57 +75,57 @@ def addAbcPrimVar(geo,attrName,attrType=None,dataType='long',keyable=False,paint # ========== # - Checks - # ========== - + # Check Geometry if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!!') if geoIsMesh and not glTools.utils.mesh.isMesh(geo): raise Exception('Geometry "'+geo+'" is not a valid mesh!!') - + # Check Attribute attr = 'ABC_'+attrName if mc.objExists(geo+'.'+attr): # mc.deleteAttr(geo+'.'+attr) raise Exception('Attribute "'+geo+'.'+attr+'" already exists!!') - + # Check Attribute Type typeList = ['var','vtx','uni','fvr'] if attrType and not typeList.count(attrType): raise Exception('Invalid attribute type! Accepted values are: "var", "vtx", "uni" and "fvr" (or for per object attribute).') - + # ================= # - Add Attribute - # ================= - + # Data type if not attrType: - + # Check Data Type if not dataType: dataType = 'long' - + # Add primVar attribute mc.addAttr(geo,ln=attr,at=dataType,k=keyable) - + else: - + # Set Attribute Data Type dataType = 'doubleArray' - + # Add primVar attribute mc.addAttr(geo,ln=attr,dt=dataType) - + # Set Geometey Scope Value attrTypeAttr = 'ABC_'+attrName+'_AbcGeomScope' mc.addAttr(geo,ln=attrTypeAttr,dt='string') mc.setAttr(geo+'.'+attrTypeAttr,attrType,type='string',l=True) - + # Make paintable if paintable: mc.makePaintable('mesh',attr,attrType=dataType) - + # ================= # - Return Result - # ================= - + return geo+'.'+attr def addAbcPrimVarStr(geo,attrName,stringVal='',lock=False): @@ -143,34 +143,34 @@ def addAbcPrimVarStr(geo,attrName,stringVal='',lock=False): # ========== # - Checks - # ========== - + # Check Geometry if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!!') - + # Check Attribute attr = 'ABC_'+attrName if mc.objExists(geo+'.'+attr): # mc.deleteAttr(geo+'.'+attr) raise Exception('Attribute "'+geo+'.'+attr+'" already exists!!') - + # ================= # - Add Attribute - # ================= - + # Add primVar attribute mc.addAttr(geo,ln=attr,dt='string') - + # Set String Value if stringVal: mc.setAttr(geo+'.'+attr,stringVal,type='string') - + # Lock Attr if lock: mc.setAttr(geo+'.'+attr,l=True) - + # ================= # - Return Result - # ================= - + return geo+'.'+attr def addStepSeedAttr(geo,attrNode='',prefix=''): @@ -186,59 +186,59 @@ def addStepSeedAttr(geo,attrNode='',prefix=''): # ========== # - Checks - # ========== - + # Check Plugin if not mc.pluginInfo('meshRandomSeed.py',q=True,l=True): try: mc.loadPlugin('meshRandomSeed.py') except: raise MissingPluginError('Unable to load "meshRandomSeed" plugin!!') - + # Check Prefix if not prefix: prefix = geo - + # Check Geometry if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!!') if not glTools.utils.mesh.isMesh(geo): raise Exception('Geometry "'+geo+'" is not a valid mesh!!') - + # Check Attribute Node if not attrNode: attrNode = geo - + # Check Attribute attrType = None attrName = 'stepSeed' attr = 'ABC_'+attrName if mc.objExists(attrNode+'.'+attr): raise Exception('Attribute "'+attrNode+'.'+attr+'" already exists!!') - + # ================= # - Add Attribute - # ================= - + attr = addAbcPrimVar(attrNode,attrName,attrType,keyable=True) - + # =================== # - Connect To Mesh - # =================== - + # Get Geometry Shape geoShape = mc.listRelatives(geo,s=True,ni=True,pa=True) if not geoShape: raise Exception('Unable to determine geometry shape from transform "'+geo+'"!') - + # Connect to meshRandomSeed Node meshRandomSeed = mc.createNode('meshRandomSeed',n=prefix+'_meshRandomSeed') mc.connectAttr(geoShape[0]+'.outMesh',meshRandomSeed+'.inputMesh',f=True) - + # ========================= # - Connect StepSeed Attr - # ========================= - + mc.connectAttr(meshRandomSeed+'.outputSeed',attr,f=True) - + # ================= # - Return Result - # ================= - + return attr diff --git a/utils/progressBar.py b/utils/progressBar.py index 65cea8b..fa08614 100644 --- a/utils/progressBar.py +++ b/utils/progressBar.py @@ -48,4 +48,4 @@ def end(): gMainProgressBar = mm.eval('$tmp = $gMainProgressBar') # End Progress - mc.progressBar(gMainProgressBar,e=True,endProgress=True) \ No newline at end of file + mc.progressBar(gMainProgressBar,e=True,endProgress=True) diff --git a/utils/reference.py b/utils/reference.py index 0fd8dfe..dfb0971 100644 --- a/utils/reference.py +++ b/utils/reference.py @@ -18,7 +18,7 @@ def listReferences(parentNS=None): if not ref.startswith(parentNS): continue refNodes.append(ref) - + # Return Result return refNodes @@ -30,7 +30,7 @@ def isReference(refNode): ''' # Check reference node if refNode not in listReferences(): return False - + # Return Result return True @@ -44,7 +44,7 @@ def isProxyManager(proxyManager): if not proxyManager: return False if not mc.objExists(proxyManager): return False if mc.objectType(proxyManager) != 'proxyManager': return False - + # Return Result return True @@ -57,7 +57,7 @@ def isReferenced(node): # Check referenced node if mc.referenceQuery(node,isNodeReferenced=True): return True else: return False - + def isLoaded(refNode): ''' Query if the reference associated with the given reference node is currently loaded @@ -67,10 +67,10 @@ def isLoaded(refNode): # Check reference node if not isReference(refNode): raise Exception('Object "'+refNode+'" is not a valid reference node!') - + # Check load state for given reference isLoaded = not mc.file(referenceNode=refNode,q=True,deferReference=True) - + # Return Result return isLoaded @@ -83,10 +83,10 @@ def getReferenceNode(node): # Check Referenced Node if not isReferenced(node): raise Exception('Object "'+node+'" is not a referenced node!') - + # Get Reference Node refNode = mc.referenceQuery(node,referenceNode=True) - + # Return Result return refNode @@ -99,10 +99,10 @@ def getReferenceFile(node,withoutCopyNumber=True): # Check Reference/Referenced Node if not isReference(node) and not isReferenced(node): raise Exception('Object "'+node+'" is not a valid reference node or a node from a referenced file!') - + # Get Reference details refFile = mc.referenceQuery(node,filename=True,wcn=withoutCopyNumber) - + # Return Result return refFile @@ -116,18 +116,18 @@ def getReferenceProxyManager(refNode): if not mc.attributeQuery('proxyMsg',n=refNode,ex=True): print('Reference "'+refNode+'" has no "proxyMsg" attribute! Unable to determine proxy manager...') return None - - # Get Connected Proxy Manager + + # Get Connected Proxy Manager proxyManager = mc.ls(mc.listConnections(refNode+'.proxyMsg',s=True,d=False) or [],type='proxyManager') or [] if not proxyManager: print('Reference "'+refNode+'" has no valid "proxyMsg" connections! Unable to determine proxy manager...') return None - + # Check Result if len(proxyManager) > 1: print('Multiple proxy manager nodes attached to reference "'+refNode+'"! Retunring first node only...') print(str(proxyManager)) - + # Return Result return proxyManager[0] @@ -140,10 +140,10 @@ def getReferencesFromProxyManager(proxyManager): # Check Proxy Manager if not isProxyManager(proxyManager): raise Exception('Object "'+str(proxyManager)+'" is not a valid proxyManager node!') - + # Get Connected Reference Nodes refList = mc.listConnections(proxyManager+'.proxyList',s=False,d=True) or [] - + # Return Result return refList @@ -156,21 +156,21 @@ def getNamespace(refNode): # Check Referenced Node if not isReference(refNode): raise Exception('Object "'+refNode+'" is not a referenced node!') - + # Get Namespace from File - OLD #refFile = getReferenceFile(refNode,withoutCopyNumber=False) #ns = mc.file(refFile,q=True,ns=True) - + # Get Namespace from Reference - NEW ns = mc.referenceQuery(refNode,namespace=True) if ns.startswith(':'): ns = ns[1:] - + # Return Result return ns def getReferenceFromNamespace(ns,parentNS=None): ''' - Get the reference node associated with the specified namespace + Get the reference node associated with the specified namespace @param ns: Namespace to query reference node from @type ns: str @param parentNS: Parent namespace to query reference nodes from @@ -180,26 +180,26 @@ def getReferenceFromNamespace(ns,parentNS=None): if ns.endswith(':'): ns = ns[:-1] if not mc.namespace(ex=ns): raise Exception('Namespace "'+ns+'" does not exist!') - + # Check Parent Namespace if parentNS: parentNS+=':' else: parentNS='' - + # Check Each Reference for refNode in listReferences(parentNS): - + # Get Reference Namespace try: refNS = mc.referenceQuery(refNode,namespace=True) except: #print('Unable to get namespace from reference "'+refNode+'"!') continue - + # Strip Leading ":" if refNS.startswith(':'): refNS = refNS[1:] - + # Check Namespace Match if refNS == parentNS+ns: - + # Check Proxy Manager Connections if mc.attributeQuery('proxyMsg',n=refNode,ex=True): proxyManager = mc.ls(mc.listConnections(refNode+'.proxyMsg',s=True,d=False) or [],type='proxyManager') or [] @@ -209,10 +209,10 @@ def getReferenceFromNamespace(ns,parentNS=None): activeProxyInfo = mc.connectionInfo(activeProxyPlug,destinationFromSource=True) if not activeProxyInfo: raise Exception('Error getting active reference from proxy manager "'+proxyManager[0]+'"!') return mc.ls(activeProxyInfo[0],o=True)[0] - + # Return Reference return refNode - + # No Reference Found from Namespace - Print Msg print('Unable to determine reference from namespace: '+ns) return '' @@ -226,19 +226,19 @@ def allReferencesFromNamespace(ns): ''' # Get Loaded Reference from Namespace refMain = getReferenceFromNamespace(ns) - + # Get Proxy Manager from Reference proxyManager = getReferenceProxyManager(refMain) - + # Get Reference Nodes from Proxy Manager refList = getReferencesFromProxyManager(proxyManager) - + # Return Reference return refList def getReferenceFromNamespaceOLD(ns): ''' - Get the reference node associated with the specified namespace + Get the reference node associated with the specified namespace #@param ns: Namespace to query reference node from #@type ns: str ''' @@ -246,27 +246,27 @@ def getReferenceFromNamespaceOLD(ns): if ns.endswith(':'): ns = ns[:-1] if not mc.namespace(ex=ns): raise Exception('Namespace "'+ns+'" does not exist!') - + # Get all Nodes in Namespace nodes = mc.ls(ns+':*') - + # For each node in list refNode = '' for node in nodes: - + # Check referenced node if not isReferenced(node): print('('+ns+') NS node not referenced - '+node) continue - + # Get reference node - escape refNode = getReferenceNode(node) break - + # Check refNode if not refNode: print('Unable to determine reference from namespace: '+ns) - + # Return result return refNode @@ -279,11 +279,11 @@ def getReferencedNodes(refNode): # Check reference node if not isReference(refNode): raise Exception('Object "'+refNode+'" is not a valid reference node!') - + # Get list of associated nodes nodes = mc.referenceQuery(refNode,nodes=True,dagPath=True) if not nodes: return [] - + # Return Result return nodes @@ -298,31 +298,31 @@ def importReference(refNode,verbose=True): # Check reference node if not isReference(refNode): raise Exception('Object "'+refNode+'" is not a valid reference node!') - + # Get referenced file path refFile = '' try: - + # Get reference file path refFile = mc.referenceQuery(refNode,filename=True) - + except: - + # Check reference node if mc.objExists(refNode): - + # Print message if verbose: print('No file associated with reference! Deleting node "'+refNode+'"') - + # Delete refNode mc.lockNode(refNode,l=False) mc.delete(refNode) - + else: - + # Import reference mc.file(refFile,importReference=True) - + # Print message if verbose: print('Imported reference "'+refNode+'" from - "'+refFile) @@ -337,24 +337,24 @@ def replaceReference(refNode,refPath,verbose=True): # Check reference node if not isReference(refNode): raise Exception('Object "'+refNode+'" is not a valid reference node!') - + # Check reference file if getReferenceFile(refNode,withoutCopyNumber=True) == refPath: print ('Reference "'+refNode+'" already referencing "'+refPath+'"!') return - + # Get file type refType = '' if refPath.endswith('.ma'): refType = 'mayaAscii' elif refPath.endswith('.mb'): refType = 'mayaBinary' else: raise Exception('Invalid file type! ("'+refPath+'")') - + # Replace reference mc.file(refPath,loadReference=refNode,typ=refType,options='v=0') - + # Print message if verbose: print('Replaced reference "'+refNode+'" using file - "'+refPath+'"') - + # Return result return refPath @@ -367,14 +367,14 @@ def removeReference(refNode,verbose=True): # Check reference node if not isReference(refNode): raise Exception('Object "'+refNode+'" is not a valid reference node!') - + # Remove Reference refFile = getReferenceFile(refNode) try: mc.file(referenceNode=refNode,removeReference=True) except Exception, e: print('Error removing reference "'+refNode+'"! Exception Msg: '+str(e)) return - + # Print message if verbose: print('Removed reference "'+refNode+'"! ('+refFile+')') @@ -387,10 +387,10 @@ def unloadReference(refNode,verbose=True): # Check reference node if not isReference(refNode): raise Exception('Object "'+refNode+'" is not a valid reference node!') - + # Unload Reference mc.file(referenceNode=refNode,unloadReference=True) - + # Print message if verbose: print('Unloadeded reference "'+refNode+'"! ('+getReferenceFile(refNode)+')') @@ -403,10 +403,10 @@ def reloadReference(refNode,verbose=True): # Check reference node if not isReference(refNode): raise Exception('Object "'+refNode+'" is not a valid reference node!') - + # Unload Reference mc.file(referenceNode=refNode,loadReference=True) - + # Print message if verbose: print('Reloadeded reference "'+refNode+'"! ('+getReferenceFile(refNode)+')') @@ -420,17 +420,17 @@ def renameReferenceNamespace(refNS,newNS): ''' # Check Namespace if mc.namespace(ex=newNS): raise Exception('Namespace "'+newNS+'" already exists! Unable to rename reference namespace...') - + # Get Reference Node from Namespace refNode = getReferenceFromNamespace(refNS) if not refNode: raise Exception('Namespace "'+refNS+'" is not a reference namespace!') - + # Get Reference File Path refPath = getReferenceFile(refNode) - + # Rename Reference Namespace mc.file(refPath,e=True,namespace=newNS) - + # Return Result return newNS @@ -443,37 +443,37 @@ def recordSourcePath(targetNode): # ========== # - Checks - # ========== - + # Check Referenced Node if not isReferenced(targetNode): raise Exception('Object "'+targetNode+'" is not a referenced node!') - + # ====================== # - Get Reference Data - # ====================== - + # Get Reference Node refNode = getReferenceNode(targetNode) - + # Get Reference Source Path refPath = getReferenceFile(refNode,withoutCopyNumber=True) realPath = os.path.realpath(refPath) - + # ====================== # - Record Source Path - # ====================== - + # Add String Attr mc.addAttr(targetNode,ln='sourceReferencePath',dt='string') # Set String Attr Value mc.setAttr(targetNode+'.sourceReferencePath',realPath,type='string') # Lock Attribute #mc.setAttr(targetNode+'.sourceReferencePath',l=True) - + # ================= # - Return Result - # ================= - + return realPath def removeUnloadedReferences(): @@ -482,16 +482,16 @@ def removeUnloadedReferences(): ''' # Get list of scene reference nodes refNodes = listReferences() - + # For each reference node for refNode in refNodes: - + # If NOT loaded if not isLoaded(refNode): - + # Print message print 'Removing unloaded reference "'+str(refNode)+'"...' - + # Remove Reference mc.file(referenceNode=refNode,removeReference=True) @@ -534,13 +534,13 @@ def getEditNodes( refNode, # ================================ # - Build ReferenceQuery Command - # ================================ - + refQueryCmd = 'referenceQuery ' refQueryCmd += ' -showNamespace '+str(showNamespace).lower() refQueryCmd += ' -showDagPath '+str(showDagPath).lower() refQueryCmd += ' -successfulEdits '+str(successfulEdits).lower() refQueryCmd += ' -failedEdits '+str(failedEdits).lower() - + nodeList = [] if parent and setAttr and addAttr and deleteAttr and connectAttr and disconnectAttr: nodeList.extend(mm.eval(refQueryCmd+' -editNodes '+refNode) or []) @@ -551,19 +551,19 @@ def getEditNodes( refNode, if deleteAttr: nodeList.extend(mm.eval(refQueryCmd+' -editCommand deleteAttr -editNodes '+refNode) or []) if connectAttr: nodeList.extend(mm.eval(refQueryCmd+' -editCommand connectAttr -editNodes '+refNode) or []) if disconnectAttr: nodeList.extend(mm.eval(refQueryCmd+' -editCommand disconnectAttr -editNodes '+refNode) or []) - + # Remove Duplicates and Sort if nodeList: nodeList = list(set(nodeList)) nodeList.sort() - + # Clean Node Names if not showDagPath: nodeList = [i.split('|')[-1] for i in nodeList] - + # ================= # - Return Result - # ================= - + return nodeList def getEditAttrs( refNode, @@ -608,10 +608,10 @@ def getEditAttrs( refNode, # ============== # - Check Node - # ============== - + refNS = getNamespace(refNode)+':' editNode = node - + # Check Short Name #if not mc.objExists(node): node = node.split('|')[-1] # Check Append NS @@ -619,17 +619,17 @@ def getEditAttrs( refNode, node = refNS+node # Unable to Determine Node #if not mc.objExists(node): raise Exception('Reference edit node "'+editNode+'" not found!') - + # ================================ # - Build ReferenceQuery Command - # ================================ - + refQueryCmd = 'referenceQuery ' refQueryCmd += ' -showNamespace '+str(showNamespace).lower() refQueryCmd += ' -showDagPath '+str(showDagPath).lower() refQueryCmd += ' -successfulEdits '+str(successfulEdits).lower() refQueryCmd += ' -failedEdits '+str(failedEdits).lower() - + attrList = [] if parent and setAttr and addAttr and deleteAttr and connectAttr and disconnectAttr: attrList.extend(mm.eval(refQueryCmd+' -editAttrs '+node) or []) @@ -640,16 +640,16 @@ def getEditAttrs( refNode, if deleteAttr: attrList.extend(mm.eval(refQueryCmd+' -editCommand deleteAttr -editAttrs '+node) or []) if connectAttr: attrList.extend(mm.eval(refQueryCmd+' -editCommand connectAttr -editAttrs '+node) or []) if disconnectAttr: attrList.extend(mm.eval(refQueryCmd+' -editCommand disconnectAttr -editAttrs '+node) or []) - + # Remove Duplicates and Sort if attrList: attrList = list(set(attrList)) attrList.sort() - + # ================= # - Return Result - # ================= - + return attrList def getEditCommands( refNode, @@ -694,13 +694,13 @@ def getEditCommands( refNode, # ============== # - Check Node - # ============== - + refNS = getNamespace(refNode)+':' editNode = node - + if not node: node = refNode else: node = refNS+node - + # Check Short Name #if not mc.objExists(node): node = node.split('|')[-1] # Check Append NS @@ -708,17 +708,17 @@ def getEditCommands( refNode, #node = refNS+node # Unable to Determine Node #if not mc.objExists(node): raise Exception('Reference edit node "'+editNode+'" not found!') - + # ================================ # - Build ReferenceQuery Command - # ================================ - + refQueryCmd = 'referenceQuery ' refQueryCmd += ' -showNamespace '+str(showNamespace).lower() refQueryCmd += ' -showDagPath '+str(showDagPath).lower() refQueryCmd += ' -successfulEdits '+str(successfulEdits).lower() refQueryCmd += ' -failedEdits '+str(failedEdits).lower() - + cmdList = [] if parent and setAttr and addAttr and deleteAttr and connectAttr and disconnectAttr: cmdList.extend(mm.eval(refQueryCmd+' -editStrings '+node) or []) @@ -729,12 +729,12 @@ def getEditCommands( refNode, if deleteAttr: cmdList.extend(mm.eval(refQueryCmd+' -editCommand deleteAttr -editStrings '+node) or []) if connectAttr: cmdList.extend(mm.eval(refQueryCmd+' -editCommand connectAttr -editStrings '+node) or []) if disconnectAttr: cmdList.extend(mm.eval(refQueryCmd+' -editCommand disconnectAttr -editStrings '+node) or []) - + # Remove Duplicates and Sort if cmdList: cmdList = list(set(cmdList)) #cmdList.sort() - + # Return Result return cmdList @@ -774,29 +774,29 @@ def removeReferenceEdits( refNode, # ========== # - Checks - # ========== - + # Check Reference Node if not isReference(refNode): raise Exception('Object "'+refNode+'" is not a valid reference node!') refNS = getNamespace(refNode)+':' - + # Check Reference is Loaded refLoaded = isLoaded(refNode) if refLoaded: mc.file(unloadReference=refNode) - + # Check Node if not node: node = refNode - + # ========================== # - Remove Reference Edits - # ========================== - + refQueryCmd = 'referenceEdit' refQueryCmd += ' -successfulEdits '+str(successfulEdits).lower() refQueryCmd += ' -failedEdits '+str(failedEdits).lower() - + # Print Progress print('Removing Reference Edits: "'+node+'"...') - + # Remove Edits if parent and setAttr and addAttr and deleteAttr and connectAttr and disconnectAttr: # Remove All Edits @@ -810,10 +810,10 @@ def removeReferenceEdits( refNode, if deleteAttr: mm.eval(refQueryCmd+'-editCommand deleteAttr -removeEdits '+node) if connectAttr: mm.eval(refQueryCmd+'-editCommand connectAttr -removeEdits '+node) if disconnectAttr: mm.eval(refQueryCmd+'-editCommand disconnectAttr -removeEdits '+node) - + # Reload Reference if refLoaded: mc.file(loadReference=refNode) - + # Return Result #print('Removing Reference Edits Complete!') return @@ -823,14 +823,14 @@ def removeParentEdits(node=''): ''' # Get Reference details refNode = getReferenceNode(node) - + # Unload Reference refLoaded = isLoaded(refNode) if refLoaded: mc.file(unloadReference=refNode) - + # Remove Edits - referenceEdit command not working correctly using python WTF?? mm.eval('referenceEdit -removeEdits -failedEdits true -successfulEdits true -editCommand parent '+refNode) - + # Reload Reference if refLoaded: mc.file(loadReference=refNode) @@ -839,14 +839,14 @@ def removeSetAttrEdits(node='',refFile=''): ''' # Get Reference details refNode = getReferenceNode(node) - + # Unload Reference refLoaded = isLoaded(refNode) if refLoaded: mc.file(unloadReference=refNode) - + # Remove Edits - referenceEdit command not working correctly using python WTF?? mm.eval('referenceEdit -removeEdits -failedEdits true -successfulEdits true -editCommand setAttr "'+refFile+'"') - + # Reload Reference if refLoaded: mc.file(loadReference=refNode) @@ -855,16 +855,16 @@ def removeConnectAttrEdits(nodeList=''): ''' # Get Reference details refNode = getReferenceNode(nodeList[0]) - + # Unload Reference refLoaded = isLoaded(refNode) if refLoaded: mc.file(unloadReference=refNode) - + # Remove Edits - referenceEdit command not working correctly using python WTF?? for node in nodeList: mm.eval('referenceEdit -failedEdits true -successfulEdits true -editCommand connectAttr -removeEdits '+node) mm.eval('referenceEdit -failedEdits true -successfulEdits true -editCommand disconnectAttr -removeEdits '+node) - + # Reload Reference if refLoaded: mc.file(loadReference=refNode) diff --git a/utils/remap.py b/utils/remap.py index 400794c..aeee4f3 100644 --- a/utils/remap.py +++ b/utils/remap.py @@ -9,9 +9,9 @@ class Remap(object): Object wrapper for remapValue node in Maya. ''' # CONSTANTS - + _REMAPSUFFIX = 'remap' - + def __init__( self, remapName, inputValue = None, @@ -41,16 +41,16 @@ def __init__( self, else: # Create New Node self.create(remapName) - + # Set Input if(inputValue != None): self.setInput(inputValue) - + # Set Range self.setRange(inputMin,inputMax,outputMin,outputMax) - + # Initialize Index self.setIndex(0) - + def create( self,name ): ''' Create new remapValue node with the specified name @@ -59,20 +59,20 @@ def create( self,name ): ''' self._name = mc.createNode('remapValue', name='%s_%s' % (name, self._REMAPSUFFIX)) return self._name - + #================== # get #================== def getName(self): return self._name - + def getIndex(self): return self._index - + #================== # set #================== - + def setAttribute(self,attr,value): ''' Set remapValue node value or source plug. @@ -83,18 +83,18 @@ def setAttribute(self,attr,value): ''' # Check None if(value == None): return - + # Check Numeric Input if isinstance(value,(types.IntType,types.FloatType)): - + # Set Numeric Attribute Value try: mc.setAttr(attr,value) except: raise Exception('Error setting remapValue attribute "'+attr+'" value!') return - + # Check String Input elif isinstance(value,types.StringTypes): - + # Connect External Plug if glTools.utils.attribute.isAttr(value): if not mc.isConnected(value,attr): @@ -106,10 +106,10 @@ def setAttribute(self,attr,value): return else: raise Exception('Source plug value is not a valid attribute! ("'+value+'")') - + # Invlaid Type raise Exception('Invalid value type specified for remapValue attribute "'+attr+'"! ('+str(type(value))+')!') - + def setInput(self, inputValue): ''' Set remapValue node inputValue. @@ -118,7 +118,7 @@ def setInput(self, inputValue): ''' attr = self._name+'.inputValue' self.setAttribute(attr,inputValue) - + def setInputMin(self,inputMin): ''' Set remapValue node inputMin attribute value @@ -127,7 +127,7 @@ def setInputMin(self,inputMin): ''' attr = self._name+'.inputMin' self.setAttribute(attr,inputMin) - + def setInputMax(self,inputMax): ''' Set remapValue node inputMax attribute value @@ -136,7 +136,7 @@ def setInputMax(self,inputMax): ''' attr = self._name+'.inputMax' self.setAttribute(attr,inputMax) - + def setOutputMin(self,outputMin): ''' Set remapValue node outputMin attribute value @@ -154,7 +154,7 @@ def setOutputMax(self,outputMax): ''' attr = self._name+'.outputMax' self.setAttribute(attr,outputMax) - + def setInputRange( self, inputMin = None, inputMax = None ): @@ -167,7 +167,7 @@ def setInputRange( self, ''' if(inputMin != None): self.setInputMin(inputMin) if(inputMax != None): self.setInputMax(inputMax) - + def setOutputRange( self, outputMin = None, outputMax = None ): @@ -180,7 +180,7 @@ def setOutputRange( self, ''' if(outputMin != None): self.setOutputMin(outputMin) if(outputMax != None): self.setOutputMax(outputMax) - + def setRange( self, inputMin = None, inputMax = None, @@ -195,7 +195,7 @@ def setRange( self, ''' self.setInputRange(inputMin,inputMax) self.setOutputRange(outputMin,outputMax) - + def setPoint( self, index, position = None, @@ -220,7 +220,7 @@ def setPoint( self, self.setValue(value) # Set Interpolation self.setInterpolation(interpolation) - + def setIndex(self,index): ''' Set remapValue point index. @@ -229,7 +229,7 @@ def setIndex(self,index): ''' self._index = index self._indexedName = '%s.value[%s]' % (self._name, index) - + def setPosition(self,position): ''' Set remapValue point position value. @@ -238,7 +238,7 @@ def setPosition(self,position): ''' attr = self._indexedName+'.value_Position' self.setAttribute(attr,position) - + def setValue(self,value): ''' Set remapValue point float value. @@ -247,7 +247,7 @@ def setValue(self,value): ''' attr = self._indexedName+'.value_FloatValue' self.setAttribute(attr,value) - + def setInterpolation(self,interpolation): ''' Set remapValue point interpolation value. @@ -256,13 +256,13 @@ def setInterpolation(self,interpolation): ''' attr = self._indexedName+'.value_Interp' self.setAttribute(attr,interpolation) - + def connectInput(self, objectAttrName): ''' ''' if not mc.isConnected(objectAttrName, '%s.inputValue' % self._name): mc.connectAttr(objectAttrName, '%s.inputValue' % self._name, force=True) - + def connectOutput(self,dstAttr): ''' Connect remapValue node output to destination plug. @@ -272,7 +272,7 @@ def connectOutput(self,dstAttr): # Checks if not glTools.utils.attribute.isAttr(dstAttr): raise Exception('Destination attribute "'+dstAttr+'" is not a valid attribute! Unable to establish output connection...') - + # Connect Output outAttr = self._name+'.outValue' if not mc.isConnected(outAttr,dstAttr): @@ -280,5 +280,5 @@ def connectOutput(self,dstAttr): except: raise Exception('Error connecting remapValue output ("'+outAttr+'" >> "'+dstAttr+'")!') else: print('RemapValue node output "'+outAttr+'" already connected to destination plug "'+dstAttr+'"! Skipping...') - + diff --git a/utils/resolution.py b/utils/resolution.py index 14d83ba..d913aee 100644 --- a/utils/resolution.py +++ b/utils/resolution.py @@ -19,7 +19,7 @@ def addResolutionAttr(obj,resList=['low','medium','high'],resAttr='resolution',k raise UserInputError('Object '+obj+' does not exist. Cannot add attribute!') if mc.objExists(obj+'.'+resAttr): raise UserInputError('Attribute "'+obj+'.'+resAttr+'" already exists. Cannot add the attribute again.') - + # Build enum string enumStr = '' for res in resList: enumStr += (res+':') diff --git a/utils/rmanAttr.py b/utils/rmanAttr.py index 18ac860..a7daa66 100644 --- a/utils/rmanAttr.py +++ b/utils/rmanAttr.py @@ -18,26 +18,26 @@ def jointDrivenRmanAttr(geo,joint,axis='z',min=0,max=180,prefix=''): ''' # Check prefix if not prefix: prefix = joint - + # Check joint if not mc.objExists(joint): raise Exception('Joint "'+joint+'" does not exist!!') - + # Check axis axis = axis.lower() if not ['x','y','z'].count(axis): raise Exception('Invalid rotation axis specified! Acceptable values are "x", "y" or "z"!') - + # Check mesh if not mc.objExists(geo): raise Exception('Object "'+geo+'" does not exist!!') - + # Add renderman variable attr meshShape = mc.listRelatives(mesh,s=True,ni=True,pa=True)[0] mc.addAttr(meshShape,ln='rmanF'+prefix,min=0,max=1,dv=0,k=True) - + # Add joint min/max value attrs mc.addAttr(joint,ln='outputMin',dv=min,k=True) mc.addAttr(joint,ln='outputMax',dv=max,k=True) - + # Remap to 0-1 range remapNode = mc.createNode('remapValue',n=prefix+'_remapValue') mc.connectAttr(joint+'.r'+axis,remapNode+'.inputValue',f=True) @@ -45,9 +45,9 @@ def jointDrivenRmanAttr(geo,joint,axis='z',min=0,max=180,prefix=''): mc.connectAttr(joint+'.outputMax',remapNode+'.inputMax',f=True) mc.setAttr(remapNode+'.outputMin',0.0) mc.setAttr(remapNode+'.outputMax',1.0) - + # Connect to shape attr mc.connectAttr(remapNode+'.outValue',meshShape+'.rmanF'+prefix,f=True) - + # Return result return meshShape+'.rmanF'+prefix diff --git a/utils/selection.py b/utils/selection.py index 1a9e57e..f1316a5 100644 --- a/utils/selection.py +++ b/utils/selection.py @@ -6,292 +6,292 @@ import glTools.utils.namespace def numSelectionElements(selection): - ''' - Return the number of selection elements are specified by the input selection list - @param selection: Selection list to return the element count for. - @type selection: list or str - ''' - # Initialize function wrappers - selectionList = OpenMaya.MSelectionList() - - # Build selection list - if type(selection) == str or type(selection) == unicode: selection = [str(selection)] - [selectionList.add(i) for i in selection] - - # Return Result - return selectionList.length() + ''' + Return the number of selection elements are specified by the input selection list + @param selection: Selection list to return the element count for. + @type selection: list or str + ''' + # Initialize function wrappers + selectionList = OpenMaya.MSelectionList() + + # Build selection list + if type(selection) == str or type(selection) == unicode: selection = [str(selection)] + [selectionList.add(i) for i in selection] + + # Return Result + return selectionList.length() def getSelectionElement(selection,element=0): - ''' - Return the selection components (MDagPath object, MObject component) - for the specified element of the input selection list - @param selection: Selection to return the element components for. - @type selection: list or str - @param element: Element of the selection to return selection components for. - @type element: int - ''' - # Initialize function wrappers - selectionList = OpenMaya.MSelectionList() - selectionPath = OpenMaya.MDagPath() - selectionObj = OpenMaya.MObject() - - # Build selection list - if type(selection) == str or type(selection) == unicode: selection = [str(selection)] - [selectionList.add(i) for i in selection] - - # Check length - if element >= selectionList.length(): - raise Exception('Element value ('+str(element)+') out of range!') - - # Get selection elements - selectionList.getDagPath(element,selectionPath,selectionObj) - - # Return result - return[selectionPath,selectionObj] + ''' + Return the selection components (MDagPath object, MObject component) + for the specified element of the input selection list + @param selection: Selection to return the element components for. + @type selection: list or str + @param element: Element of the selection to return selection components for. + @type element: int + ''' + # Initialize function wrappers + selectionList = OpenMaya.MSelectionList() + selectionPath = OpenMaya.MDagPath() + selectionObj = OpenMaya.MObject() + + # Build selection list + if type(selection) == str or type(selection) == unicode: selection = [str(selection)] + [selectionList.add(i) for i in selection] + + # Check length + if element >= selectionList.length(): + raise Exception('Element value ('+str(element)+') out of range!') + + # Get selection elements + selectionList.getDagPath(element,selectionPath,selectionObj) + + # Return result + return[selectionPath,selectionObj] def getShapes(transform,returnNonIntermediate=True,returnIntermediate=True): - ''' - Return a list of shapes under a specified transform - @param transform: Transform to query - @type transform: str - @param returnNonIntermediate: Return non intermediate shapes. - @type returnNonIntermediate: bool - @param returnIntermediate: Return intermediate shapes. - @type returnIntermediate: bool - ''' - # Initialize arrays - shapeList = [] - - # Check for shape input - transformObj = base.getMObject(transform) - if not transformObj.hasFn(OpenMaya.MFn.kTransform): - transform = mc.listRelatives(transform,p=True,pa=True)[0] - - # Get shape lists - allShapeList = mc.listRelatives(transform,s=True,pa=True) - if not allShapeList: return [] - for shape in allShapeList: - intermediate = bool(mc.getAttr(shape+'.intermediateObject')) - if intermediate and returnIntermediate: shapeList.append(shape) - if not intermediate and returnNonIntermediate: shapeList.append(shape) - - # Return result - return shapeList + ''' + Return a list of shapes under a specified transform + @param transform: Transform to query + @type transform: str + @param returnNonIntermediate: Return non intermediate shapes. + @type returnNonIntermediate: bool + @param returnIntermediate: Return intermediate shapes. + @type returnIntermediate: bool + ''' + # Initialize arrays + shapeList = [] + + # Check for shape input + transformObj = base.getMObject(transform) + if not transformObj.hasFn(OpenMaya.MFn.kTransform): + transform = mc.listRelatives(transform,p=True,pa=True)[0] + + # Get shape lists + allShapeList = mc.listRelatives(transform,s=True,pa=True) + if not allShapeList: return [] + for shape in allShapeList: + intermediate = bool(mc.getAttr(shape+'.intermediateObject')) + if intermediate and returnIntermediate: shapeList.append(shape) + if not intermediate and returnNonIntermediate: shapeList.append(shape) + + # Return result + return shapeList def componentSelectionInOrder(): - ''' - Returns a list of the selected components in the order they were selected. - ''' - # Get selection - selection = [] - selectionAll = mc.ls(sl=1) - lastCommand = mc.undoInfo(q=True,un=True) - counter = 0 - - # Traverse undo list - while lastCommand.count('select'): - lastCommand = mc.undoInfo(q=True,un=True) - if lastCommand.count('select'): - selectElem = lastCommand.split(' ') - selection.append(selectElem[2]) - mc.undo() - - # Sort selection - selection.reverse() - realSelection = [] - [realSelection.append(i) for i in selection if not realSelection.count(i)] - - # Return result - return realSelection + ''' + Returns a list of the selected components in the order they were selected. + ''' + # Get selection + selection = [] + selectionAll = mc.ls(sl=1) + lastCommand = mc.undoInfo(q=True,un=True) + counter = 0 + + # Traverse undo list + while lastCommand.count('select'): + lastCommand = mc.undoInfo(q=True,un=True) + if lastCommand.count('select'): + selectElem = lastCommand.split(' ') + selection.append(selectElem[2]) + mc.undo() + + # Sort selection + selection.reverse() + realSelection = [] + [realSelection.append(i) for i in selection if not realSelection.count(i)] + + # Return result + return realSelection def enableObjectVertexSelection(item): - ''' - Enable vertex selection for specified object - @param item: Object to switch selection mode for - @type item: str - ''' - # Hilite item - mc.hilite(item) - # Get item type - itemType = mc.objectType(mc.listRelatives(item,s=1,ni=1)[0]) - # Set selection mode - if itemType == 'mesh': - mc.selectType(ocm=1,vertex=1) - if itemType == 'nurbsSurface' or itemType == 'nurbsCurve': - mc.selectType(ocm=1,controlVertex=1) + ''' + Enable vertex selection for specified object + @param item: Object to switch selection mode for + @type item: str + ''' + # Hilite item + mc.hilite(item) + # Get item type + itemType = mc.objectType(mc.listRelatives(item,s=1,ni=1)[0]) + # Set selection mode + if itemType == 'mesh': + mc.selectType(ocm=1,vertex=1) + if itemType == 'nurbsSurface' or itemType == 'nurbsCurve': + mc.selectType(ocm=1,controlVertex=1) def disableObjectVertexSelection(item): - ''' - Disable vertex selection for specified object - @param item: Object to switch selection mode for - @type item: str - ''' - # Hilite item - mc.hilite(item,u=1) + ''' + Disable vertex selection for specified object + @param item: Object to switch selection mode for + @type item: str + ''' + # Hilite item + mc.hilite(item,u=1) def selectFromViewport(): - ''' - Select all objects visible in the current active viewport - ''' - # Get active viewport - viewPort = OpenMayaUI.M3dView.active3dView() - - # Select from screen - OpenMaya.MGlobal.selectFromScreen(0,0,viewPort.portWidth(),viewPort.portHeight(),OpenMaya.MGlobal.kReplaceList,OpenMaya.MGlobal.kWireframeSelectMethod) + ''' + Select all objects visible in the current active viewport + ''' + # Get active viewport + viewPort = OpenMayaUI.M3dView.active3dView() + + # Select from screen + OpenMaya.MGlobal.selectFromScreen(0,0,viewPort.portWidth(),viewPort.portHeight(),OpenMaya.MGlobal.kReplaceList,OpenMaya.MGlobal.kWireframeSelectMethod) def selectByAttr(attr=''): - ''' - Select nodes with the specified attribute - @param attr: Attribute to use a for the selection filter - @type attr: str - ''' - # Check Attribute - if not attr: - - result = mc.promptDialog( title='Select By Attribute', - message='Attribute:', - button=['Select','Cancel'], - defaultButton='Select', - cancelButton='Cancel', - dismissString='Cancel' ) - - if result == 'Select': - attr = mc.promptDialog(q=True,text=True) - - # Check Attribute - if not attr: return - - # Select By Attribute - sel = mc.ls('*.'+attr,o=True) - - # Return Result - return sel + ''' + Select nodes with the specified attribute + @param attr: Attribute to use a for the selection filter + @type attr: str + ''' + # Check Attribute + if not attr: + + result = mc.promptDialog( title='Select By Attribute', + message='Attribute:', + button=['Select','Cancel'], + defaultButton='Select', + cancelButton='Cancel', + dismissString='Cancel' ) + + if result == 'Select': + attr = mc.promptDialog(q=True,text=True) + + # Check Attribute + if not attr: return + + # Select By Attribute + sel = mc.ls('*.'+attr,o=True) + + # Return Result + return sel def componentListByObject(componentList=[]): - ''' - Return a list of component lists. - Each components list is grouped by parent object. - @param componentList: Flat component list that will be grouped by object - @type componentList: list - ''' - # Check Component List - If empty, get user selection - if not componentList: componentList = mc.ls(sl=1,fl=1) - if not componentList: return [] - - # Initialize function wrappers - selList = OpenMaya.MSelectionList() - objPath = OpenMaya.MDagPath() - compObj = OpenMaya.MObject() - - # Build Selection List - if type(componentList) == str or type(componentList) == unicode: componentList = [str(componentList)] - [selList.add(i) for i in componentList] - - # For Each Object - objCompList = [] - for i in range(selList.length()): - - # Get Object Selection - selList.getDagPath(i,objPath,compObj) - compList = OpenMaya.MSelectionList() - compList.clear() - compList.add(objPath,compObj) - - # Get Component Selection List - compStrList = [] - compList.getSelectionStrings(compStrList) - - # Append to Output List - objCompList.append(compStrList) - - # Return Result - return objCompList + ''' + Return a list of component lists. + Each components list is grouped by parent object. + @param componentList: Flat component list that will be grouped by object + @type componentList: list + ''' + # Check Component List - If empty, get user selection + if not componentList: componentList = mc.ls(sl=1,fl=1) + if not componentList: return [] + + # Initialize function wrappers + selList = OpenMaya.MSelectionList() + objPath = OpenMaya.MDagPath() + compObj = OpenMaya.MObject() + + # Build Selection List + if type(componentList) == str or type(componentList) == unicode: componentList = [str(componentList)] + [selList.add(i) for i in componentList] + + # For Each Object + objCompList = [] + for i in range(selList.length()): + + # Get Object Selection + selList.getDagPath(i,objPath,compObj) + compList = OpenMaya.MSelectionList() + compList.clear() + compList.add(objPath,compObj) + + # Get Component Selection List + compStrList = [] + compList.getSelectionStrings(compStrList) + + # Append to Output List + objCompList.append(compStrList) + + # Return Result + return objCompList def componentDictByObject(componentList=[]): - ''' - Return a dictionary of component lists, using the components object as a key. - @param componentList: Flat component list that will be grouped by object - @type componentList: list - ''' - # Check Component List - If empty, get user selection - if not componentList: componentList = mc.ls(sl=1,fl=1) - if not componentList: return [] - - # Initialize function wrappers - selList = OpenMaya.MSelectionList() - objPath = OpenMaya.MDagPath() - compObj = OpenMaya.MObject() - - # Build Selection List - if type(componentList) == str or type(componentList) == unicode: componentList = [str(componentList)] - [selList.add(i) for i in componentList] - - # For Each Object - objCompDict = {} - for i in range(selList.length()): - - # Get Object Selection - selList.getDagPath(i,objPath,compObj) - compList = OpenMaya.MSelectionList() - compList.clear() - compList.add(objPath,compObj) - - # Get Component Selection List - compStrList = [] - compList.getSelectionStrings(compStrList) - - # Append to Output List - objCompDict[objPath.name()] = compStrList - - # Return Result - return objCompList + ''' + Return a dictionary of component lists, using the components object as a key. + @param componentList: Flat component list that will be grouped by object + @type componentList: list + ''' + # Check Component List - If empty, get user selection + if not componentList: componentList = mc.ls(sl=1,fl=1) + if not componentList: return [] + + # Initialize function wrappers + selList = OpenMaya.MSelectionList() + objPath = OpenMaya.MDagPath() + compObj = OpenMaya.MObject() + + # Build Selection List + if type(componentList) == str or type(componentList) == unicode: componentList = [str(componentList)] + [selList.add(i) for i in componentList] + + # For Each Object + objCompDict = {} + for i in range(selList.length()): + + # Get Object Selection + selList.getDagPath(i,objPath,compObj) + compList = OpenMaya.MSelectionList() + compList.clear() + compList.add(objPath,compObj) + + # Get Component Selection List + compStrList = [] + compList.getSelectionStrings(compStrList) + + # Append to Output List + objCompDict[objPath.name()] = compStrList + + # Return Result + return objCompList def mirrorSelection(sel=[],mirrorPrefix=[('lf','rt')],addToSel=False): - ''' - Mirror selection - @param sel: User defined selection to mirror. If empty, use current active selection. - @type sel: list - @param mirrorPrefix: List of side prefix pairs. - @type mirrorPrefix: list - @param addToSel: Add to or replace current selection. - @type addToSel: bool - ''' - # Check Selection - if not sel: sel = mc.ls(sl=True) - - # Get Mirror Selection - mSel = [] - for obj in sel: - - # Get Namespace and Short Name - NS = glTools.utils.namespace.getNS(obj) - if NS: NS += ':' - objSN = glTools.utils.namespace.stripNS(obj) - - # Get Side Prefix - side = objSN.split('_')[0] - - # Get Mirror - mObj = objSN - for mPrefix in mirrorPrefix: - if side == mPrefix[0]: - mObj = objSN.replace(mPrefix[0],mPrefix[1]) - break - if side == mPrefix[1]: - mObj = objSN.replace(mPrefix[1],mPrefix[0]) - break - - # Check Mirror Object - if not mc.objExists(NS+mObj): - print ('Mirror object "'+NS+mObj+'" does not exist!') - continue - - # Add to Mirror Selection - mSel.append(NS+mObj) - - # Set Selection - if addToSel: mSel = sel + mSel - mc.select(mSel) - - # Return Result - return mSel + ''' + Mirror selection + @param sel: User defined selection to mirror. If empty, use current active selection. + @type sel: list + @param mirrorPrefix: List of side prefix pairs. + @type mirrorPrefix: list + @param addToSel: Add to or replace current selection. + @type addToSel: bool + ''' + # Check Selection + if not sel: sel = mc.ls(sl=True) + + # Get Mirror Selection + mSel = [] + for obj in sel: + + # Get Namespace and Short Name + NS = glTools.utils.namespace.getNS(obj) + if NS: NS += ':' + objSN = glTools.utils.namespace.stripNS(obj) + + # Get Side Prefix + side = objSN.split('_')[0] + + # Get Mirror + mObj = objSN + for mPrefix in mirrorPrefix: + if side == mPrefix[0]: + mObj = objSN.replace(mPrefix[0],mPrefix[1]) + break + if side == mPrefix[1]: + mObj = objSN.replace(mPrefix[1],mPrefix[0]) + break + + # Check Mirror Object + if not mc.objExists(NS+mObj): + print ('Mirror object "'+NS+mObj+'" does not exist!') + continue + + # Add to Mirror Selection + mSel.append(NS+mObj) + + # Set Selection + if addToSel: mSel = sel + mSel + mc.select(mSel) + + # Return Result + return mSel diff --git a/utils/shader.py b/utils/shader.py index f81930e..3a85679 100644 --- a/utils/shader.py +++ b/utils/shader.py @@ -14,7 +14,7 @@ def getSG(geo): ''' # Get Face Sets sets = mc.listSets(extendToShape=True,type=1,object=geo) or [] - + # Return Result return list(set(sets)) @@ -26,7 +26,7 @@ def getMaterial(geo): ''' # Get Material mat = mc.listConnections([SG+'.surfaceShader' for SG in getSG(geo)],s=True,d=False) or [] - + # Return Result return list(set(mat)) @@ -39,17 +39,17 @@ def getRenderNodes(): renderTypes.extend(mc.listNodeTypes('utility')) renderTypes.extend(mc.listNodeTypes('imageplane')) renderTypes.extend(mc.listNodeTypes('shader')) - + # Get Nodes by Type renderNodes = mc.ls(long=True,type=renderTypes) if not renderNodes: renderNodes = [] mrRenderNodes = mc.lsThroughFilter('DefaultMrNodesFilter') if not mrRenderNodes: mrRenderNodes = [] renderNodes.extend(mrRenderNodes) - + # Remove Duplicates renderNodes = list(set(renderNodes)) - + # Return Result return renderNodes @@ -61,22 +61,22 @@ def shadingGroupUnused(shadingGroup): ''' # Check Object Exists if not mc.objExists(shadingGroup): return False - + # Check Renderable if not mc.sets(shadingGroup,q=True,renderable=True): return False - + # Ignore Default Types if shadingGroup == 'initialShadingGroup': return False if shadingGroup == 'initialParticleSE': return False - + # Connection to DAG objects objs = mc.sets(shadingGroup,q=True) # Connection to render layers layers = mc.listConnections(shadingGroup,type='renderLayer') - + # Check Membership / Layer attachment if not objs and not layers: return True - + # Check to make sure at least one shader is connected to the group attrs = [ '.surfaceShader', '.volumeShader', @@ -90,13 +90,13 @@ def shadingGroupUnused(shadingGroup): '.miEnvironmentShader', '.miLightMapShader', '.miContourShader'] - + # Check Shader Connections for attr in attrs: if mc.objExists(shadingGroup+attr): if mc.listConnections(shadingGroup+attr): return False - + # Return Result return False @@ -108,47 +108,47 @@ def listUnusedShadingNodes(verbose=False): ''' # List Unused Shading Nodes unused = [] - + # ============== # - Check Sets - # ============== - + # Check Unused Sets for curr_set in mc.ls(sets=True): - + # Skip Default Sets if curr_set.count('default'): continue - + # Check Set is Used if shadingGroupUnused(curr_set): if verbose: print('Unused shading group: '+curr_set) unused.append(curr_set) - + # =================== # - Check Materials - # =================== # Delete all unconnected materials. materials = mc.ls(long=True,mat=True) - + for currShader in materials: - + # Skip Default Materials if currShader.count('default'): continue - + # Skip Defaults if currShader == 'lambert1': continue if currShader == 'particleCloud1': continue - + shouldDelete = False # conn is an array of plug/connection pairs conn = mc.listConnections(currShader,shapes=True,connections=True,source=False) - + # Check Shader Connections for j in range(0,len(conn),2): - + # Check connection to unused shading engine se = mc.listConnections(conn[j],type='shadingEngine') if not se: @@ -157,12 +157,12 @@ def listUnusedShadingNodes(verbose=False): if unused.count(se[0]): shouldDelete = True break - + # Check Message Connection if conn[j] != (currShader+'.message'): shouldDelete = False break - + # Third Party Prevent Deletions thirdPartyPreventDeletions = mc.callbacks(currShader,conn[j+1],conn[j],executeCallbacks=True,hook="preventMaterialDeletionFromCleanUpSceneCommand") if not thirdPartyPreventDeletions: thirdPartyPreventDeletions = [] @@ -171,7 +171,7 @@ def listUnusedShadingNodes(verbose=False): if(deletionPrevented): thirdPartyPreventsDeletion = True break - + # Check if Used if se: shouldDelete = False @@ -181,42 +181,42 @@ def listUnusedShadingNodes(verbose=False): break else: shouldDelete = True - + if shouldDelete: if verbose: print('Unused shader: '+currShader) unused.append(currShader) - + # ======================= # - Check Shading Utils - # ======================= - + # Get All Render Nodes allRenderNodes = getRenderNodes() - + for node in allRenderNodes: - + # Skip Default Nodes if node.count('default'): continue - + # Skip Defaults if node == 'lambert1': continue if node == 'particleCloud1': continue - + # Deleting one node can delete other connected nodes. if not mc.objExists(node): continue - + # Check heightField if mc.nodeType(node) == 'heightField': conn = mc.listConnections(node,connections=True,source=True,shapes=True) if conn: continue - + # It's a texture, postprocess or utility node. Now determine if the readable connections are done. shouldDelete = True - + # Decide whether or not the node is unused conn = mc.listConnections(node,c=True,s=False,shapes=True) or [] for j in range(0,len(conn),2): - + # Check Messgae Connection if conn[j].count('.message'): connType = mc.nodeType(conn[j+1]) @@ -228,13 +228,13 @@ def listUnusedShadingNodes(verbose=False): 'pointLight', 'areaLight', 'transform' ] - + if connList.count(connType): shouldDelete = False - + if mc.objectType(conn[j+1],isa='camera') == connType: shouldDelete = False - + # Check Classification if shouldDelete and mm.eval('isClassified "'+conn[j+1]+'" "shader/surface"'): shouldDelete = False @@ -242,31 +242,31 @@ def listUnusedShadingNodes(verbose=False): shouldDelete = False if shouldDelete and mm.eval('isClassified "'+conn[j+1]+'" "shader/displacement"'): shouldDelete = False - + # Give plugins a chance to label the node as 'shouldnt be deleted' thirdPartyPreventDeletions = mc.callbacks(node,conn[j+1],conn[j],executeCallbacks=True,hook='preventMaterialDeletionFromCleanUpSceneCommand') if not thirdPartyPreventDeletions: thirdPartyPreventDeletions = [] #thirdPartyPreventDeletions = mc.callbacks( -executeCallbacks -hook "preventMaterialDeletionFromCleanUpSceneCommand" $node $conn[$j+1] $conn[$j]`; - + for deletionPrevented in thirdPartyPreventDeletions: if deletionPrevented: shouldDelete = False break - + if not shouldDelete: break - + else: shouldDelete = False break - + if shouldDelete: if verbose: print('Unused render node: '+node) unused.append(node) - + # ================= # - Return Result - # ================= - + return unused def applyReferencedShader(geo): @@ -279,17 +279,17 @@ def applyReferencedShader(geo): # ========== # - Checks - # ========== - + # Check Geometry if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!!') - + # Get Shapes shapes = glTools.utils.shape.getShapes(geo,nonIntermediates=True,intermediates=False) ishapes = glTools.utils.shape.getShapes(geo,nonIntermediates=False,intermediates=True) if not shapes: raise Exception('Unable to determine shape node from geometry "'+geo+'"!') if not ishapes: raise Exception('Unable to determine intermediate shape node from geometry "'+geo+'"!') - + # Get Referenced Shape refShape = '' for i in ishapes: @@ -299,26 +299,26 @@ def applyReferencedShader(geo): if not refShape: print('No referenced shape found! Using first intermediate shape ("'+ishapes[0]+'").') refShape = ishapes[0] - + # ==================== # - Reconnect Shader - # ==================== - + # Get Reference Shader Assignment shader = mc.listConnections(refShape+'.instObjGroups',d=True) if not shader: raise Exception('Unable to determine shader assignment from intermediate shape node "'+refShape+'"!') - + # Break Placeholder Connections breakReferencePlaceholderConnections(shapes[0]) - + # Assigned Shader mc.sets(shapes[0],fe=shader[0]) - + # ================= # - Return Result - # ================= - + return shader[0] def breakReferencePlaceholderConnections(shape): @@ -329,14 +329,14 @@ def breakReferencePlaceholderConnections(shape): ''' # Get Shape Connections placeHolderConn = mc.listConnections(shape,s=True,d=True,p=True,c=True) or [] - + # For Each Connection Pair for i in range(0,len(placeHolderConn),2): - + # Check Reference Connection placeHolderNode = mc.ls(placeHolderConn[i+1],o=True)[0] if glTools.utils.reference.isReference(placeHolderNode): - + # Disconnect PlaceHolder if mc.isConnected(placeHolderConn[i],placeHolderConn[i+1]): try: mc.disconnectAttr(placeHolderConn[i],placeHolderConn[i+1]) @@ -357,16 +357,16 @@ def reconnectShader(geo): # Check Geometry if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') - + # Get Shapes geoShapes = mc.listRelatives(geo,s=True,ni=True,pa=True) geoAllShapes = mc.listRelatives(geo,s=True,pa=True) if not geoAllShapes: raise Exception('No shapes found under geometry "'+geo+'"! Unable to determine shader connections...') - + # Break Reference Placeholder Connections for shape in geoAllShapes: breakReferencePlaceholderConnections(shape) - + # Get Shader Connections if geoShapes: geoShapeConn = mc.listConnections(geoShapes) or [] @@ -374,13 +374,13 @@ def reconnectShader(geo): if geoShaderConn: mc.sets(geo,fe=geoShaderConn[0]) return geoShaderConn[0] - + # NonIntermediate Shape Shader Connections Failed - Use All Shapes geoShapeConn = mc.listConnections(geoAllShapes) or [] geoShaderConn = mc.ls(geoShapeConn,type='shadingEngine') if not geoShaderConn: raise Exception('No shader connections found for geometry "'+geo+'"!') - + # Reconnect Shader mc.sets(geo,fe=geoShaderConn[0]) return geoShaderConn[0] @@ -390,34 +390,34 @@ def fixReferenceShaders(refList=None,defaultShader='initialShadingGroup'): ''' # Check Reference List if not refList: refList = glTools.utils.reference.listReferences() - + # Check Each Reference for ref in refList: - + # Initialize Reference Shape List shpList = [] - + # Check Disconnected Shaders c = mc.listConnections(ref+'.placeHolderList',s=True,d=False,p=True,c=True,sh=True) - + # Check Each Reference Connection for i in range(0,len(c),2): - + # Define Connection Source and Destination dst = c[i] src = c[i+1] - + # Check instObjGroups Connections if 'instObjGroups' in src: - + # Disconnect placeHolderList Connection mc.disconnectAttr(src,dst) - + # Get Source Shape shp = mc.ls(src,o=True)[0] if not shp in shpList: shpList.append(shp) - + # Reconnect to Shader if shpList: mc.sets(shpList,e=True,fe=defaultShader) @@ -434,32 +434,32 @@ def basicTextureShader(texturePath,useFrameExtension=True,prefix=''): # ========== # - Checks - # ========== - + # Check Texture Path if not os.path.isfile(texturePath): raise Exception('Invalid texture path "'+texturePath+'"!!') - + # Prefix if not prefix: basename = os.path.basename(texturePath) prefix = basename.split('.')[0] - + # ===================================== # - Create Material and Shading Group - # ===================================== - + # Create material mat = mc.shadingNode('lambert',asShader=True,n=prefix+'_mat') sg = mc.sets(renderable=True,noSurfaceShader=True,empty=True,name=prefix+'_SG') mc.connectAttr(mat+'.outColor',sg+'.surfaceShader',f=True) - + # Create File Texture fileNode = mc.shadingNode('file',asTexture=True,n=prefix+'_file') - + # Assign File Path mc.setAttr(fileNode+'.fileTextureName',texturePath,type='string') - - # Create File Placement + + # Create File Placement placeNode = mc.shadingNode('place2dTexture',asUtility=True,n=prefix+'_place2dTexture') mc.connectAttr(placeNode+'.coverage',fileNode+'.coverage',f=True) mc.connectAttr(placeNode+'.translateFrame',fileNode+'.translateFrame',f=True) @@ -480,15 +480,15 @@ def basicTextureShader(texturePath,useFrameExtension=True,prefix=''): mc.connectAttr(placeNode+'.outUvFilterSize',fileNode+'.uvFilterSize',f=True) mc.connectAttr(placeNode+'.outUV',fileNode+'.uv',f=True) mc.setAttr(placeNode+'.rotateUV',90) - + # Connect To Shader mc.connectAttr(fileNode+'.outColor',mat+'.color',f=True) - + # Use Frame Extension if useFrameExtension: mc.setAttr(fileNode+'.useFrameExtension',1) - + # ================= # - Return Result - # ================= - + return [sg,mat,fileNode,placeNode] diff --git a/utils/shape.py b/utils/shape.py index c7cafb9..500d117 100644 --- a/utils/shape.py +++ b/utils/shape.py @@ -13,11 +13,11 @@ def isShape(obj): ''' # Check object exists if not mc.objExists(obj): return False - + # Check Shape mObject = glTools.utils.base.getMObject(obj) if not mObject.hasFn(OpenMaya.MFn.kShape): return False - + # Return Result return True @@ -40,18 +40,18 @@ def listIntermediates(geo): raise Exception('Object "'+geo+'" does not exist!!') if isShape(geo): geo = mc.listRelatives(geo,p=True,pa=True)[0] - + # Get Non Intermediate Shapes shapes = mc.listRelatives(geo,s=True,ni=True,pa=True) - + # Get All Shapes allShapes = mc.listRelatives(geo,s=True,pa=True) - + # Get Intermediate Shapes if not allShapes: return [] if not shapes: return allShapes intShapes = list(set(allShapes) - set(shapes)) - + # Return Result return intShapes @@ -70,7 +70,7 @@ def getShapes(geo,nonIntermediates=True,intermediates=True): raise Exception('Object "'+geo+'" does not exist!!') if isShape(geo): geo = mc.listRelatives(geo,p=True,pa=True)[0] - + # Get Shapes shapes = [] if nonIntermediates: @@ -78,10 +78,10 @@ def getShapes(geo,nonIntermediates=True,intermediates=True): if nonIntShapes: shapes.extend(nonIntShapes) if intermediates: shapes.extend(listIntermediates(geo)) - + # Return Result return shapes - + def rename(geo): ''' Rename shape nodes based on the parent transform name @@ -90,19 +90,19 @@ def rename(geo): ''' # Get Shapes shapes = getShapes(geo) - + # Check Shapes if not shapes: return [] - + # Rename Shapes for i in range(len(shapes)): - + # Get Shape Type shapeType = mc.objectType(shapes[i]) - + # Temporarily rename shapes, so hash index (#) is accurate shapes[i] = mc.rename(shapes[i],geo+'ShapeTMP') - + # Rename Shape if shapeType == 'nurbsCurve': shapes[i] = mc.rename(shapes[i],geo+'CrvShape#') @@ -112,7 +112,7 @@ def rename(geo): shapes[i] = mc.rename(shapes[i],geo+'MeshShape#') else: shapes[i] = mc.rename(shapes[i],geo+'Shape#') - + # Return Result return shapes @@ -125,7 +125,7 @@ def shapeInputAttr(shape): # Check Shape if not isShape(shape): raise Exception('Object "'+shape+'" is not a valid shape node!') - + # Determine Shape Input Plug shapeInputAttr = '' shapeInputType = mc.objectType(shape) @@ -136,7 +136,7 @@ def shapeInputAttr(shape): shapeInputAttr = shapeInputDict[shapeInputType] else: raise Exception('Unsupported shape type! ('+shapeInputType+')') - + # Return Result return shapeInputAttr @@ -151,19 +151,19 @@ def shapeOutputAttr(shape,worldSpace=False): # Check Shape if not isShape(shape): raise Exception('Object "'+shape+'" is not a valid shape node!') - + # Determine Shape Input Plug shapeOutputAttr = '' shapeOutputType = mc.objectType(shape) shapeOutputDict = { 'mesh':['outMesh','worldMesh'], 'nurbsCurve':['local','worldSpace'], 'nurbsSurface':['local','worldSpace'] } - + if shapeOutputDict.has_key(shapeOutputType): shapeOutputAttr = shapeOutputDict[shapeOutputType][int(worldSpace)] else: raise Exception('Unsupported shape type! ('+shapeOutputType+')') - + # Return Result return shapeOutputAttr @@ -176,15 +176,15 @@ def shapeInputSrc(shape): # Check Shape if not isShape(shape): raise Exception('Object "'+shape+'" is not a valid shape node!') - + # Determine Shape Input Plug shapeInAttr = shapeInputAttr(shape) - + # Determine Shape Input Source Plug shapeInputPlug = '' shapeInputSrc = mc.listConnections(shape+'.'+shapeInAttr,s=True,d=False,p=True) if shapeInputSrc: shapeInputPlug = shapeInputSrc[0] - + # Return Result return shapeInputPlug @@ -196,7 +196,7 @@ def findInputShape(shape,recursive=False,printExceptions=False): ''' # Initialize Default Value inputShape = None - + # Try inputShape methods if not inputShape: try: inputShape = glTools.utils.shape.findInputShape1(shape) @@ -208,16 +208,16 @@ def findInputShape(shape,recursive=False,printExceptions=False): except Exception, e: if printExceptions: print('Caught Exception: '+str(e)) - + # Check Result if not inputShape: raise Exception('Unable to determine input shape for "'+shape+'"!') - + # Recursive Check if recursive: while(inputShape!=findInputShape(inputShape)): inputShape = findInputShape(inputShape) - + # Return Result return inputShape @@ -230,23 +230,23 @@ def findInputShape1(shape): ''' # Get MObject for shape shapeObj = glTools.utils.base.getMObject(shape) - + # Get inMesh connection inConn = mc.listConnections(shape,s=True,d=False) if not inConn: return shape - + # Find connected deformer deformerHist = mc.ls(mc.listHistory(shape),type='geometryFilter') if not deformerHist: raise Exception('Shape node "'+shape+'" is not affected by any valid deformers! Unable to determine input shape') deformerObj = glTools.utils.base.getMObject(deformerHist[0]) - + # Get deformer function set deformerFn = OpenMayaAnim.MFnGeometryFilter(deformerObj) - + # Get input shape for deformer geomIndex = deformerFn.indexForOutputShape(shapeObj) inputShapeObj = deformerFn.inputShapeAtIndex(geomIndex) - + # Return result return OpenMaya.MFnDagNode(inputShapeObj).partialPathName() @@ -258,25 +258,25 @@ def findInputShape2(shape): ''' # Initialize Transform transform = mc.listRelatives(shape,p=True,pa=True) or [] - + # Check shape if glTools.utils.base.isType(shape,'transform'): transform = [shape] shapes = mc.listRelatives(shape,s=True,ni=True,pa=True) if not shapes: raise Exception('Unable to determine shape node from transform "'+shape+'"!') shape = shapes[0] - + # Get All Shapes allShapes = mc.listRelatives(transform[0],s=True,pa=True) - + # Get shape type shapeType = mc.objectType(shape) - + # Get shape history shapeHist = mc.ls(mc.listHistory(shape),type=shapeType) if shapeHist.count(shape): shapeHist.remove(shape) if not shapeHist: raise Exception('Unable to determine history nodes for shape "'+shape+'"!') - + # Check shape history if len(shapeHist) == 1: inputShape = shapeHist[0] @@ -284,7 +284,7 @@ def findInputShape2(shape): shapeInput = list(set(shapeHist).intersection(set(allShapes))) if shapeInput: inputShape = shapeInput[0] else: inputShape = shapeHist[0] - + # Return result return inputShape @@ -303,7 +303,7 @@ def parent(shape,parent,deleteShapeTransform=False,force=False): raise Exception('Object "'+shape+'" does not exist!!') if not mc.objExists(parent): raise Exception('Object "'+parent+'" does not exist!!') - + # Get shapes shapes = [] if mc.ls(shape,type='transform'): @@ -312,25 +312,25 @@ def parent(shape,parent,deleteShapeTransform=False,force=False): else: transform = mc.listRelatives(shape,p=True,pa=True)[0] shapes = [shape] - + # Match parent transform mc.parent(transform,parent) mc.makeIdentity(transform,apply=True,t=True,r=True,s=True) mc.parent(transform,w=True) - + # Parent shapes for i in range(len(shapes)): - + # Parent Shape to Target Transform shapeList = mc.parent(shapes[i],parent,s=True,r=True) shapes[i] = shapeList[0] - + # Get Shape Type shapeType = mc.objectType(shapes[i]) - + # Temporarily rename shapes, so hash index (#) is accurate shapes[i] = mc.rename(shapes[i],parent+'ShapeTMP') - + # Rename Shapes if shapeType == 'nurbsCurve': shapes[i] = mc.rename(shapes[i],parent+'CrvShape#') @@ -340,10 +340,10 @@ def parent(shape,parent,deleteShapeTransform=False,force=False): shapes[i] = mc.rename(shapes[i],parent+'MeshShape#') else: shapes[i] = mc.rename(shapes[i],parent+'Shape#') - + # Delete Old Shape Transform if deleteShapeTransform: - + # Check remaining descendants if mc.listRelatives(transform,ad=True): if not force: @@ -351,7 +351,7 @@ def parent(shape,parent,deleteShapeTransform=False,force=False): deleteShapeTransform = False else: print('Transform "'+transform+'" has remaining descendants, deleting anyway! (force=True)') - + # Check outgoing connections if mc.listConnections(transform,s=False,d=True): if not force: @@ -359,10 +359,10 @@ def parent(shape,parent,deleteShapeTransform=False,force=False): deleteShapeTransform = False else: print('Transform "'+transform+'" has outgoing conections, deleting anyway! (force=True)') - + # Delete Transform if deleteShapeTransform: mc.delete(transform) - + # Return Result return shapes @@ -375,7 +375,7 @@ def unparent(shape): # Checks if not mc.objExists(shape): raise Exception('Object "'+shape+'" does not exist!!') - + # Get shapes if mc.ls(shape,type='transform'): transform = shape @@ -383,17 +383,17 @@ def unparent(shape): else: transform = mc.listRelatives(shape,p=True,pa=True)[0] shapes = [shape] - + # Create shape holder shapeHolder = transform+'Shapes' if not mc.objExists(shapeHolder): shapeHolder = mc.createNode('transform',n=shapeHolder) targetXform = mc.xform(transform,q=True,ws=True,m=True) mc.xform(shapeHolder,ws=True,m=targetXform) - + # Unparent shapes for shape in shapes: mc.parent(shape,shapeHolder,s=True,r=True) - + # Return Result return shapeHolder @@ -417,25 +417,25 @@ def copyToTransform(shape,transform,relative=True,move=False,overrideColour=None # Check transform if not mc.objExists(transform): raise Exception('Transform "'+transform+'" does not exist!') - + # Duplicate shape if not move: shapeParent = mc.listRelatives(shape,p=True,pa=True)[0] tmpXform = mc.duplicate(shapeParent,rr=True)[0] shape = mc.listRelatives(tmpXform,s=True,pa=True)[0] - + # Parent shape mc.parent(shape,transform,s=True,r=relative,a=not(relative)) shape = mc.rename(shape,transform+'Shape#') - + # Delete temp transform if not move: mc.delete(tmpXform) - + # Colour Override if overrideColour: mc.setAttr(shape+'.overrideEnabled',1) mc.setAttr(shape+'.overrideColor',overrideColour) - + # Return result return shape @@ -448,11 +448,11 @@ def createIntermediate(shape): # ========== # - Checks - # ========== - + # Check Shape if not mc.objExists(shape): raise Exception('Object "'+shape+'" does not exist!!') - + # Check Geometry Type geoType = mc.objectType(shape) if geoType == 'transform': @@ -460,33 +460,33 @@ def createIntermediate(shape): if not shapes: raise Exception('Object "'+shape+'" has no valid shapes!!') shape = shapes[0] geoType = mc.objectType(shape) - + # Check In/Out Attributes geoDict = {'mesh':('outMesh','inMesh'),'nurbsSurface':('local','create'),'nurbsCurve':('local','create')} if not geoDict.has_key(geoType): raise Exception('Invalid shape type ('+geoType+') for "'+shape+'"!!') - + # ============================= # - Create Intermediate Shape - # ============================= - + # Get Shape Node from Transform transform = str(mc.listRelatives(shape,p=True)[0]) - + # Rename Current Shape as Intermediate shapeOrig = mc.rename(shape,shape+'Orig') - + # Create New Shape shape = mc.createNode(geoType,n=shape,p=transform) mc.connectAttr(shapeOrig+'.'+geoDict[geoType][0],shape+'.'+geoDict[geoType][1],f=True) mc.setAttr(shapeOrig+'.intermediateObject',1) mc.reorder(shape,f=True) - + # Connect Shader shader = mc.listConnections(shapeOrig,type='shadingEngine') if shader: mc.sets(shapeOrig,rm=shader[0]) mc.sets(shape,fe=shader[0]) - + # Update Outgoing Connections outConn = mc.listConnections(shapeOrig,s=False,d=True,p=True,c=True) for i in range(0,len(outConn),2): @@ -502,10 +502,10 @@ def createIntermediate(shape): continue # Update Connection mc.connectAttr(src,dst,f=True) - + # ================= # - Return Result - # ================= - + return shapeOrig - + diff --git a/utils/skinCluster.py b/utils/skinCluster.py index d1adebc..2e572fc 100644 --- a/utils/skinCluster.py +++ b/utils/skinCluster.py @@ -27,7 +27,7 @@ def isSkinCluster(skinCluster): if mc.objectType(skinCluster) != 'skinCluster': print('Object "'+skinCluster+'" is not a vaild skinCluster node!') return False - + # Retrun result return True @@ -44,14 +44,14 @@ def findRelatedSkinCluster(geometry): if mc.objectType(geometry) == 'transform': try: geometry = mc.listRelatives(geometry,s=True,ni=True,pa=True)[0] except: raise Exception('Object '+geometry+' has no deformable geometry!') - + # Determine skinCluster skin = mm.eval('findRelatedSkinCluster "'+geometry+'"') - if not skin: + if not skin: skin = mc.ls(mc.listHistory(geometry),type='skinCluster') if skin: skin = skin[0] if not skin: skin = '' - + # Return result return skin @@ -64,16 +64,16 @@ def getSkinClusterFn(skinCluster): # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "' + skinCluster + '" specified!') - + # Get skinCluster node skinClusterSel = OpenMaya.MSelectionList() skinClusterObj = OpenMaya.MObject() OpenMaya.MGlobal.getSelectionListByName(skinCluster,skinClusterSel) skinClusterSel.getDependNode(0,skinClusterObj) - + # Initialize skinCluster function class skinClusterFn = OpenMayaAnim.MFnSkinCluster(skinClusterObj) - + # Return function class return skinClusterFn @@ -88,17 +88,17 @@ def getInfluenceIndex(skinCluster,influence): # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "'+skinCluster+'" specified!') - + # Check influence if not mc.objExists(influence): raise Exception('Influence object "'+influence+'" does not exist!') - + # Get skinCluster node skinClusterFn = getSkinClusterFn(skinCluster) - + # Get influence object influencePath = glTools.utils.base.getMDagPath(influence) - + # Get influence index return skinClusterFn.indexForInfluenceObject(influencePath) @@ -113,13 +113,13 @@ def getInfluenceAtIndex(skinCluster,influenceIndex): # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "'+skinCluster+'" specified!') - + # Get Influence at Index infConn = mc.listConnections(skinCluster+'.matrix['+str(influenceIndex)+']',s=True,d=False) - + # Check Connection if not infConn: raise Exception('No influence at specified index!') - + # Return Result return infConn[0] @@ -134,24 +134,24 @@ def getInfluencePhysicalIndex(skinCluster,influence): # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "'+skinCluster+'" specified!') - + # Check influence if not mc.objExists(influence): raise Exception('Influence object "'+influence+'" does not exist!') - + # Get skinCluster node skinClusterFn = getSkinClusterFn(skinCluster) - + # Get influence path list infPathArray = OpenMaya.MDagPathArray() skinClusterFn.influenceObjects(infPathArray) infNameArray = [infPathArray[i].partialPathName() for i in range(infPathArray.length())] - + # Check influence if not influence in infNameArray: raise Exception('Unable to determine influence index for "'+influence+'"!') infIndex = infNameArray.index(influence) - + # Retrun result return infIndex @@ -168,29 +168,29 @@ def getInfluenceWeights(skinCluster,influence,componentList=[]): # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "' + skinCluster + '" specified!') - + # Check influence if not mc.objExists(influence): raise Exception('Influence object "'+influence+'" does not exists!') - + # Get geometry affectedGeo = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys()[0] - + # Check component list if not componentList: componentList = glTools.utils.component.getComponentStrList(affectedGeo) componentSel = glTools.utils.selection.getSelectionElement(componentList,0) - + # Get skinCluster Fn skinFn = getSkinClusterFn(skinCluster) - + # Get Influence Index influenceIndex = getInfluencePhysicalIndex(skinCluster,influence) - + # Get weight values weightList = OpenMaya.MDoubleArray() skinFn.getWeights(componentSel[0],componentSel[1],influenceIndex,weightList) - + # Return weight array return list(weightList) @@ -208,7 +208,7 @@ def getInfluenceWeightsAll(skinCluster,componentList=[]): # Get Geometry affectedGeo = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys()[0] - + # Check component list if not componentList: componentList = glTools.utils.component.getComponentStrList(affectedGeo) componentSel = glTools.utils.selection.getSelectionElement(componentList,0) @@ -222,11 +222,11 @@ def getInfluenceWeightsAll(skinCluster,componentList=[]): infCountPtr = infCountUtil.asUintPtr() skinFn.getWeights(componentSel[0],componentSel[1],weightList,infCountPtr) infCount = OpenMaya.MScriptUtil(infCountPtr).asUint() - + # Break List Per Influence wtList = list(weightList) infWtList = [wtList[i::infCount] for i in xrange(infCount)] - + # Return Result return infWtList @@ -243,22 +243,22 @@ def getInfluenceWeightsSlow(skinCluster,influence,componentList=[]): # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "' + skinCluster + '" specified!') - + # Check influence if not mc.objExists(influence): raise Exception('Influence object "'+influence+'" does not exists!') - + # Get geometry affectedGeo = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys()[0] - + # Check component list if not componentList: componentList = glTools.utils.component.getComponentStrList(affectedGeo) componentIndexList = glTools.utils.component.getComponentIndexList(componentList) componentIndexList = componentIndexList[componentIndexList.keys()[0]] - + # Get weight values weightList = [mc.skinPercent(skinCluster,affectedGeo+'.vtx['+str(i)+']',transform=influence,q=True) for i in componentIndexList] - + # Return weight array return weightList @@ -279,36 +279,36 @@ def setInfluenceWeights(skinCluster,influence,weightList,normalize=True,componen # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "' + skinCluster + '" specified!') - + # Check influence if not mc.objExists(influence): raise Exception('Influence object "'+influence+'" does not exists!') - + # Get geometry affectedGeo = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys()[0] - + # Get skinCluster Fn skinFn = getSkinClusterFn(skinCluster) - + # Get Influence Index influenceIndex = getInfluencePhysicalIndex(skinCluster,influence) - + # Check component list if not componentList: componentList = glTools.utils.component.getComponentStrList(affectedGeo) componentSel = glTools.utils.selection.getSelectionElement(componentList,0) - + # Encode argument arrays infIndexArray = OpenMaya.MIntArray() infIndexArray.append(influenceIndex) - + wtArray = OpenMaya.MDoubleArray() oldWtArray = OpenMaya.MDoubleArray() [wtArray.append(i) for i in weightList] - + # Set skinCluster weight values skinFn.setWeights(componentSel[0],componentSel[1],infIndexArray,wtArray,normalize,oldWtArray) - + # Return result return list(oldWtArray) @@ -329,25 +329,25 @@ def setInfluenceWeightsSlow(skinCluster,influence,weightList,normalize=True,comp # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "' + skinCluster + '" specified!') - + # Check influence if not mc.objExists(influence): raise Exception('Influence object "'+influence+'" does not exists!') if not mc.skinCluster(skinCluster,q=True,inf=True).count(influence): raise Exception('Influence "'+influence+'" not connected to skinCluster "'+skinCluster+'"!') - + # Get geometry affectedGeo = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys()[0] - + # Check component list if not componentList: componentList = glTools.utils.component.getComponentStrList(affectedGeo) componentIndexList = glTools.utils.component.getComponentIndexList(componentList) componentIndexList = componentIndexList[componentIndexList.keys()[0]] - + # Check component and weight list lengths if len(componentIndexList) != len(weightList): raise Exception('List length mis-match!') - + # Set weight values for i in range(len(componentIndexList)): comp = glTools.utils.component.getComponentStrList(affectedGeo,[componentIndexList[i]])[0] @@ -359,43 +359,43 @@ def setInfluenceWeightsAll(skinCluster,weightList,normalize=True,componentList=[ # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "' + skinCluster + '" specified!') - + # Get SkinCluster Influence List influenceList = mc.skinCluster(skinCluster,q=True,inf=True) infIndexArray = OpenMaya.MIntArray() [infIndexArray.append(getInfluencePhysicalIndex(skinCluster,inf)) for inf in influenceList] infDict = {} for inf in influenceList: infDict[inf] = getInfluencePhysicalIndex(skinCluster,inf) - + # Get SkinCluster Geometry skinGeo = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys()[0] if not mc.objExists(skinGeo): raise Exception('SkinCluster geometry "'+skinGeo+'" does not exist!') - + # Check Component List if not componentList: componentList = glTools.utils.component.getComponentStrList(skinGeo) componentSel = glTools.utils.selection.getSelectionElement(componentList,0) - + # Get Component Index List indexList = OpenMaya.MIntArray() componentFn = OpenMaya.MFnSingleIndexedComponent(componentSel[1]) componentFn.getElements(indexList) componentIndexList = list(indexList) - + # Check SkinCluster Weights List if len(weightList) != len(influenceList): raise Exception('Influence and weight list miss-match!') - + # Build Master Weight Array wtArray = OpenMaya.MDoubleArray() oldWtArray = OpenMaya.MDoubleArray() for c in componentIndexList: for inf in influenceList: wtArray.append(weightList[infDict[inf]][c]) - + # Get skinCluster function set skinFn = glTools.utils.skinCluster.getSkinClusterFn(skinCluster) - + # Set skinCluster weights skinFn.setWeights(componentSel[0],componentSel[1],infIndexArray,wtArray,False,oldWtArray) @@ -412,18 +412,18 @@ def lockInfluenceWeights(influence,lock=True,lockAttr=False): # Check SkinCluster if not mc.objExists(influence): raise Exception('Influence "'+influence+'" does not exist!') - + # Check Lock Influence Weights Attr if not mc.attributeQuery('liw',n=influence,ex=True): raise Exception('Influence ("'+influence+'") does not contain attribute "lockInfluenceWeights" ("liw")!') - + # Set Lock Influence Weights Attr try: mc.setAttr(influence+'.liw',l=False) mc.setAttr(influence+'.liw',lock) if lockAttr: mc.setAttr(influence+'.liw',l=True) except: pass - + # Return Result return lock @@ -440,16 +440,16 @@ def lockSkinClusterWeights(skinCluster,lock=True,lockAttr=False): # Check SkinCluster if not isSkinCluster(skinCluster): raise Exception('Object "'+skinCluster+'" is not a valid skinCluster node!') - + # Get Influence List influenceList = mc.skinCluster(skinCluster,q=True,inf=True) or [] - + # For Each Influence for influence in influenceList: - + # Set Lock Influence Weights Attr lockInfluenceWeights(influence,lock=lock,lockAttr=lockAttr) - + # Return Result return influenceList @@ -466,17 +466,17 @@ def lockSkinClusterWeightsFromGeo(geo,lock=True,lockAttr=False): # Check SkinCluster if not mc.objExists(geo): raise Exception('Geometry "'+geo+'" does not exist!') - + # Get skinCluster skinCluster = findRelatedSkinCluster(geo) if not skinCluster: return [] - + # Lock Weights influenceList = lockSkinClusterWeights(skinCluster,lock=lock,lockAttr=lockAttr) - + # Return Result return influenceList - + def getAffectedPoints(skinCluster,influence): ''' Get a list of points affected by a specific influence of a named skinCluster. @@ -488,22 +488,22 @@ def getAffectedPoints(skinCluster,influence): # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Object "'+skinCluster+'" is not a valid skinCluster!!') - + # Get skinCluster function set skinClusterFn = getSkinClusterFn(skinCluster) - + # Get influence DAG path influencePath = glTools.utils.base.getMDagPath(influence) - + # Get affected points pointSel = OpenMaya.MSelectionList() weightList = OpenMaya.MDoubleArray() skinClusterFn.getPointsAffectedByInfluence(influencePath,pointSel,weightList) - + # Return result pointList = [] pointSel.getSelectionStrings(pointList) - return pointList + return pointList def rename(geometry,suffix='skinCluster'): ''' @@ -514,20 +514,20 @@ def rename(geometry,suffix='skinCluster'): # Check geometry if not mc.objExists(geometry): raise Exception('Geometry "'+geometry+'" does not exist!') - + # Get name prefix prefix = geometry.split(':')[-1] # glTools.utils.stringUtils.stripSuffix(geometry) - + # Get connected skinCluster try: skinCluster = findRelatedSkinCluster(geometry) except: print ('Object "'+geometry+'" is not connected to a valid skinCluster!!') skinCluster = '' - + # Check skinCluster if not skinCluster: return '' - + # Rename skinCluster skinCluster = mc.rename(skinCluster,prefix+'_'+suffix) return skinCluster @@ -540,26 +540,26 @@ def reset(geometry): ''' # Delete bind pose nodes deleteBindPose() - + # Determine skinCluster skinCluster = findRelatedSkinCluster(geometry) - + # Detach skinCluster mc.skinCluster(geometry,e=True,ubk=True) - + # Get influence list influenceList = mc.skinCluster(skinCluster,q=True,inf=True) - + # Get MaxInfluence settings maxInfluences = mc.getAttr(skinCluster+'.maxInfluences') useMaxInfluences = mc.getAttr(skinCluster+'.maintainMaxInfluences') - + # Rebuild skinCluster skinCluster = mc.skinCluster(geometry,influenceList,dr=4,mi=maxInfluences,omi=useMaxInfluences,tsb=True) - + # Delete bind pose nodes deleteBindPose() - + # Return skinCluster return skinCluster @@ -572,36 +572,36 @@ def clearWeights(geometry): # ========== # - Checks - # ========== - + # Check Geometry if not mc.objExists(geometry): raise Exception('Geometry object "'+geometry+'" does not exist!') - + # Get SkinCluster skinCluster = findRelatedSkinCluster(geometry) if not mc.objExists(skinCluster): raise Exception('Geometry object "'+geometry+'" is not attached to a valid skinCluster!') - + # ================= # - Clear Weights - # ================= - + # Get geometry component list componentList = glTools.utils.component.getComponentStrList(geometry) componentSel = glTools.utils.selection.getSelectionElement(componentList,0) - + # Build influence index array infList = mc.skinCluster(skinCluster,q=True,inf=True) infIndexArray = OpenMaya.MIntArray() for inf in infList: infIndex = getInfluencePhysicalIndex(skinCluster,inf) infIndexArray.append(infIndex) - + # Build master weight array wtArray = OpenMaya.MDoubleArray() oldWtArray = OpenMaya.MDoubleArray() [wtArray.append(0.0) for i in range(len(componentList)*len(infList))] - + # Set skinCluster weights skinFn = glTools.utils.skinCluster.getSkinClusterFn(skinCluster) skinFn.setWeights(componentSel[0],componentSel[1],infIndexArray,wtArray,False,oldWtArray) @@ -626,37 +626,37 @@ def mirrorSkinWIP( srcGeo, # ========== # - Checks - # ========== - + # Check Source Geometry and SkinCluster if not mc.objExists(srcGeo): raise Exception('Source geometry "'+srcGeo+'" does not exist!') srcSkin = findRelatedSkinCluster(srcGeo) if not srcSkin: raise Exception('No skinCluster found for source geometry "'+srcGeo+'"!') - + # Check Destination Geometry and SkinCluster if not mc.objExists(dstGeo): raise Exception('Destination geometry "'+dstGeo+'" does not exist!') dstSkin = findRelatedSkinCluster(dstGeo) if not dstSkin: dstSkin = dstGeo.split(':')[-1]+'_skinCluster' - + # Get Source Influence List srcInfluenceList = mc.skinCluster(srcSkin,q=True,inf=True) - + # Check Joint List if not jointList: jointList = mc.ls(type='joint') - + # ==================================== # - Build Destination Influence List - # ==================================== - + # Get Destination Influence List dstInfluenceList = [] if mc.objExists(dstSkin): dstInfluenceList = mc.skinCluster(dstSkin,q=True,inf=True) - - - + + + def mirrorSkin(skinCluster,search='lf_',replace='rt_',destGeo=''): ''' @@ -673,31 +673,31 @@ def mirrorSkin(skinCluster,search='lf_',replace='rt_',destGeo=''): # Check skinCluster if not isSkinCluster(skinCluster): raise Exception('Object "'+skinCluster+'" is not a valid skinCluster!') - + # Check Source Geometry sourceGeo = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys()[0] - + # Get Destination Geometry if not destGeo: destGeo = sourceGeo.replace(search,replace) if not mc.objExists(destGeo): raise Exception('Destination geometry "'+destGeo+'" does not exist!') - + # Get influence list influenceList = mc.skinCluster(skinCluster,q=True,inf=True) - + # Check destination skinCluster mSkinCluster = skinCluster.replace(search,replace) destSkinCluster = findRelatedSkinCluster(destGeo) if destSkinCluster and destSkinCluster != mSkinCluster: mc.rename(destSkinCluster,mSkinCluster) - + # Check influenceList mInfluenceList = [inf.replace(search,replace) for inf in influenceList] for mInf in mInfluenceList: if not mc.objExists(mInf): raise Exception('Mirror influence "'+mInf+'" does not exist!!') - + # Check mirror skinCluster if not mc.objExists(mSkinCluster): # Create skinCluster @@ -708,54 +708,54 @@ def mirrorSkin(skinCluster,search='lf_',replace='rt_',destGeo=''): for mInf in mInfluenceList: if not destInfluenceList.count(mInf): mc.skinCluster(mSkinCluster,e=True,ai=mInf) - + # Get Mirror Weights mirroWeightList = {} for inf in influenceList: mirroWeightList[inf] = getInfluenceWeights(skinCluster,inf) - + # Clear mirrorSkin weights clearWeights(destGeo) - + # Apply mirror weights for i in range(len(influenceList)): setInfluenceWeights(mSkinCluster,mInfluenceList[i],mirroWeightList[influenceList[i]]) - + def createMirrorInfluenceList(influenceList, searchJointList=None, flipAxis = [-1,1,1]): - + # Check Joint List if not searchJointList: searchJointList = mc.ls(type='joint') - + mInfluenceList = [i for i in influenceList] for i in range(len(influenceList)): - + # Get Joint Mirror Position inf = influenceList[i] pos = mc.xform(inf,q=True,ws=True,rp=True) mirrorPos = [pos[x]*flipAxis[x] for x in range(len(pos))] - + closestJoint = inf smallestDist = 1000 for jnt in searchJointList: - + # Check Mirror Joint testPos = mc.xform(jnt,q=True,ws=True,rp=True) dist = glTools.utils.mathUtils.distanceBetween(point1=mirrorPos,point2=testPos) - + # Test Distance if dist < smallestDist: closestJoint = jnt smallestDist = dist - + # Append Mirror Influence List mInfluenceList[i] = closestJoint - + # Check influenceList for mInf in mInfluenceList: if not mc.objExists(mInf): print ('Warning :: Mirror influence "'+mInf+'" does not exist!!') mInfluenceList.remove(mInf) - + return mInfluenceList def mirrorSkinToNewGeom( srcSkin, @@ -777,63 +777,63 @@ def mirrorSkinToNewGeom( srcSkin, # ========== # - Checks - # ========== - + # Check skinCluster if not isSkinCluster(srcSkin): raise Exception('Object "'+srcSkin+'" is not a valid skinCluster!') - + # Get Destination Geometry if not mc.objExists(dstGeo): raise Exception('Destination geometry "'+dstGeo+'" does not exist!') - + # Get Destination SkinCluster dstSkin = findRelatedSkinCluster(dstGeo) if not dstSkin: dstSkin = dstGeo+'_skinCluster' - + # Get Influence List influenceList = mc.skinCluster(srcSkin,q=True,inf=True) - + # Check Joint List if not jointList: jointList = mc.ls(type='joint') - + # ============================= # - Get Mirror Influence List - # ============================= - + mInfluenceList = [i for i in influenceList] for i in range(len(influenceList)): - + # Get Joint Mirror Position inf = influenceList[i] pos = mc.xform(inf,q=True,ws=True,rp=True) mirrorPos = [pos[x]*flipAxis[x] for x in range(len(pos))] - + closestJoint = inf smallestDist = 1000 for jnt in jointList: - + # Check Mirror Joint testPos = mc.xform(jnt,q=True,ws=True,rp=True) dist = glTools.utils.mathUtils.distanceBetween(point1=mirrorPos,point2=testPos) - + # Test Distance if dist < smallestDist: closestJoint = jnt smallestDist = dist - + # Append Mirror Influence List mInfluenceList[i] = closestJoint - + # Check influenceList for mInf in mInfluenceList: if not mc.objExists(mInf): print ('Warning :: Mirror influence "'+mInf+'" does not exist!!') mInfluenceList.remove(mInf) - + # ============================ # - Build Mirror SkinCluster - # ============================ - + if not mc.objExists(dstSkin): # Create SkinCluster dstSkin = mc.skinCluster(mInfluenceList,dstGeo,tsb=True,n=dstSkin)[0] @@ -844,20 +844,20 @@ def mirrorSkinToNewGeom( srcSkin, if not mInf in dstInfluenceList: try: mc.skinCluster(dstSkin,e=True,ai=mInf) except: print "Warning :: Could not add %s to %s" % (mInf, dstSkin) - + # Clear Weights mc.setAttr(dstSkin+'.normalizeWeights',0) clearWeights(dstGeo) - - + + # Mirror Weights for i in range(len(influenceList)): print(influenceList[i]+' : '+mInfluenceList[i]) wt = getInfluenceWeights(srcSkin,influenceList[i]) setInfluenceWeights(dstSkin,mInfluenceList[i],wt) - + mc.setAttr(dstSkin+'.normalizeWeights',1) - + def bindPreMatrix(skinCluster,influence,influenceBase=None,parent=True): ''' Set a skinCluster influences deformation relative to a specified transform. @@ -873,34 +873,34 @@ def bindPreMatrix(skinCluster,influence,influenceBase=None,parent=True): # ========== # - Checks - # ========== - + # Check SkinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "'+skinCluster+'" specified!') - + # Check Influence if not mc.objExists(influence): raise Exception('Influence "'+influence+'" does not exist!') - + # Check InfluenceBase if influenceBase: if not mc.objExists(influenceBase): raise Exception('Influence base "'+influenceBase+'" does not exist!') if not influenceBase: influenceBase = influence - + # ========================= # - Connect BindPreMatrix - # ========================= - + # Get Influence Index infIndex = getInfluenceIndex(skinCluster,influence) - + # Check influence == influenceBase if influence == influenceBase: print('BindPreMatrix >> '+influence) mc.connectAttr(influence+'.parentInverseMatrix[0]',skinCluster+'.bindPreMatrix['+str(infIndex)+']',f=True) return influence - + # Create BindPreMatrix Transform bpm = None if influenceBase: @@ -912,21 +912,21 @@ def bindPreMatrix(skinCluster,influence,influenceBase=None,parent=True): mc.delete(mc.scaleConstraint(influence,bpm)) # Parent bindPreMatrix transform to relativeTo object if parent: mc.parent(influence,bpm) - + # Connect bindPreMatrix message to skinCluster influence if not mc.objExists(influence+'.influenceBase'): mc.addAttr(influence,ln='influenceBase',at='message') try: mc.connectAttr(bpm+'.message',influence+'.influenceBase',f=True) except: pass - + # Connect bindPreMatrix to skinCluster try: mc.connectAttr(bpm+'.worldInverseMatrix[0]',skinCluster+'.bindPreMatrix['+str(infIndex)+']',f=1) except: pass - + # ================= # - Return Result - # ================= - + return bpm def setGeomMatrix(geo): @@ -934,11 +934,11 @@ def setGeomMatrix(geo): ''' # Determine skinCluster skinCluster = findRelatedSkinCluster(geo) - + # Get Geometry Matrix mat = mc.getAttr(geo+'.worldMatrix[0]') mc.setAttr(skinCluster+'.geomMatrix',mat,type='matrix') - + # Return Result return skinCluster @@ -953,19 +953,19 @@ def makeRelative(skinCluster,relativeTo): # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "' + skinCluster + '" specified!') - + # Verify relativeTo object if not mc.objExists(relativeTo): raise Exception('Object "'+relativeTo+'" does not exist!') else: if mc.objectType(relativeTo) != 'transform': raise Exception('Object "'+relativeTo+'" is not a valid transform!') - + # Build bindPreMatrix network influenceList = mc.skinCluster(skinCluster,q=1,inf=1) infBaseList = [] for inf in influenceList: - + # Determine influenceIndex infInd = -1 plugConnection = mc.listConnections(inf+'.worldMatrix[0]',s=0,d=1,p=1,type="skinCluster") @@ -978,7 +978,7 @@ def makeRelative(skinCluster,relativeTo): break if infInd < 0: raise Exception('Influence index could not be determined!') - + # Create bindPreMatrix transform bpm = '' try: @@ -1007,12 +1007,12 @@ def makeRelative(skinCluster,relativeTo): if bpm != bpmConn[0]: mc.connectAttr(bpm+'.worldInverseMatrix[0]',skinCluster+'.bindPreMatrix['+str(infInd)+']',f=1) else: mc.connectAttr(bpm+'.worldInverseMatrix[0]',skinCluster+'.bindPreMatrix['+str(infInd)+']',f=1) - + # Determine skin object obj = glTools.utils.deformer.getAffectedGeometry(skinCluster).keys()[0] # Connect skinned geometry parent matrix to skinCluster.geomMatrix mc.connectAttr(obj+'.parentMatrix[0]',skinCluster+'.geomMatrix',f=1) - + # Return InfluenceBase List return infBaseList @@ -1029,19 +1029,19 @@ def skinAs(src,dst,smooth=False): # Check inputs if not mc.objExists(src): raise Exception('Source object "'+src+'" does not exist!') if not mc.objExists(dst): raise Exception('Destination object "'+dst+'" does not exist!') - + # Get source skinCluster srcSkin = findRelatedSkinCluster(src) - + # Check destination skinCluster dstSkin = findRelatedSkinCluster(dst) - + # Build destination skinCluster if not dstSkin: dstPrefix = dst.split(':')[-1] srcInfList = mc.skinCluster(srcSkin,q=True,inf=True) dstSkin = mc.skinCluster(srcInfList,dst,toSelectedBones=True,rui=False,n=dstPrefix+'_skinCluster')[0] - + # Copy skin weights mc.copySkinWeights( sourceSkin=str(srcSkin), destinationSkin=str(dstSkin), @@ -1049,7 +1049,7 @@ def skinAs(src,dst,smooth=False): influenceAssociation='name', noMirror=True, smooth=smooth ) - + # Return result return dstSkin @@ -1064,39 +1064,39 @@ def skinObjectList(objList,jntList): # ========== # - Checks - # ========== - + # Check Geometry for obj in objList: if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') - + # Check Joints for jnt in jntList: if not mc.objExists(jnt): raise Exception('Joint "'+jnt+'" does not exist!') - + # ======================= # - Create SkinClusters - # ======================= - + # Initialize SkinCluster List skinClusterList = [] - + for obj in objList: - + # Get Short Name objName = mc.ls(obj,sn=True)[0].split(':')[-1] - + # Create SkinCluster skinCluster = mc.skinCluster(jntList,obj,toSelectedBones=True,rui=False,n=objName+'_skinCluster')[0] - + # Append to Return List skinClusterList.append(skinCluster) - + # ================= # - Return Result - # ================= - + return skinClusterList def skinObjectListFromUI(): @@ -1105,14 +1105,14 @@ def skinObjectListFromUI(): ''' # Get User Selection sel = mc.ls(sl=1,o=True) - + # Sort Geometry from Joints jntList = [jnt for jnt in sel if glTools.utils.joint.isJoint(jnt)] objList = [jnt for jnt in sel if not glTools.utils.joint.isJoint(jnt)] - + # Create SkinClusters skinClusterList = skinObjectList(objList,jntList) - + # Return Result return skinClusterList @@ -1126,7 +1126,7 @@ def clean(skinCluster,tolerance=0.005): ''' # Print Message print('Cleaning skinCluster: '+skinCluster) - + # Get Affected Geometry geoShape = mc.skinCluster(skinCluster,q=True,g=True) if not geoShape: @@ -1136,16 +1136,16 @@ def clean(skinCluster,tolerance=0.005): raise Exception('Unable to determine geometry from deformed shape "'+geoShape[0]+'"!') # Select Geometry mc.select(geo[0]) - + # Unlock Influence Weights lockSkinClusterWeights(skinCluster,lock=False,lockAttr=False) - + # Prune weights mm.eval('doPruneSkinClusterWeightsArgList 1 { "'+str(tolerance)+'" }') - + # Remove unused influences mm.eval('removeUnusedInfluences') - + # Lock Influence Weights lockSkinClusterWeights(skinCluster,lock=True,lockAttr=True) @@ -1163,26 +1163,26 @@ def removeMultipleInfluenceBases(base,duplicates): baseShape = mc.listRelatives(base,s=True,ni=True)[0] if not baseShape: raise Exception('Unable to determine base influence shape for "'+base+'"!') - + # For Each Duplicate Base for dup in duplicates: - + # Get Duplicate Base Shape dupShape = mc.listRelatives(dup,s=True,ni=True) if not dupShape: print('Unable to determine base influence shape for "'+base+'"! Skipping...') continue - + # Get SkinCluster Connection dupConn = mc.listConnections(dup+'.outMesh',s=0,d=1,p=True,type='skinCluster') if not dupConn: print('Base influence "'+dup+'" deleted! No outgoing skinCluster connections...') mc.delete(dup) continue - + # Get SkinCluster dupConnSkin = mc.ls(dupConn[0],o=True)[0] - + # Override Connection try: mc.connectAttr(baseShape+'.outMesh',dupConn[0],f=True) @@ -1190,10 +1190,10 @@ def removeMultipleInfluenceBases(base,duplicates): except: print('Unable to override base influence connection to skinCluster"'+dupConnSkin+'" ('+dup+' >>> '+base+' )! Skipping...') continue - + # Delete Duplicate Base Influence mc.delete(dup) - + # Return Result return @@ -1203,34 +1203,34 @@ def replaceGeomInfluenceBase(skinCluster,influence,influenceBase,deleteOldBase=F # ========== # - Checks - # ========== - + # Verify skinCluster if not isSkinCluster(skinCluster): raise Exception('Invalid skinCluster "' + skinCluster + '" specified!') - + # Influence infList = mc.skinCluster(skinCluster,q=True,inf=True) if not infList.count(influence): raise Exception('Object "'+influence+'" is not a valid influence of skinCluster "'+skinCluster+'"!') - + # ========================== # - Replace Influence Base - # ========================== - + # Get influence index infIndex = getInfluenceIndex(skinCluster,influence) - + # Get Existing Influence Base oldBase = mc.listConnections(skinCluster+'.basePoints['+str(infIndex)+']',s=True,d=False) - + # Connect to SkinCluster mc.connectAttr(influenceBase+'.outMesh',skinCluster+'.basePoints['+str(infIndex)+']',f=True) - + # Delete Old Influence Base if deleteOldBase: mc.delete(oldBase) - + # ================= # - Return Result - # ================= - + return infIndex diff --git a/utils/stringUtils.py b/utils/stringUtils.py index 0c24edf..d3c835d 100644 --- a/utils/stringUtils.py +++ b/utils/stringUtils.py @@ -17,7 +17,7 @@ def stripSuffix(name,delineator='_'): result = name.replace(delineator+suffix,'') # Return Result return result - + def stringIndex(index,padding=2): ''' Return the string equivalent for the specified iteger index. @@ -32,7 +32,7 @@ def stringIndex(index,padding=2): for i in range(padding-len(strInd)): strInd = '0'+strInd # Return Result return strInd - + def alphaIndex(index,upper=True): ''' Return the alpha string equivalent for the specified iteger index. @@ -43,16 +43,16 @@ def alphaIndex(index,upper=True): ''' # Define Alpha List alpha = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'] - + # Build Alpha Index alphaInd = alpha[index % 26] depth = index / 26.0 while int(math.floor(depth)): alphaInd = alpha[int(depth % 26)-1] + alphaInd depth = depth / 26.0 - + # Check Case if upper: alphaInd = alphaInd.upper() - + # Return result return alphaInd diff --git a/utils/surface.py b/utils/surface.py index b63f097..ae065f1 100644 --- a/utils/surface.py +++ b/utils/surface.py @@ -22,7 +22,7 @@ def isSurface(surface): # Check shape if mc.objectType(surface) == 'transform': surface = mc.listRelatives(surface,s=True,ni=True,pa=True)[0] if mc.objectType(surface) != 'nurbsSurface': return False - + # Return result return True @@ -36,7 +36,7 @@ def getSurfaceFn(surface): if not isSurface(surface): raise Exception('Object '+surface+' is not a valid surface!') if mc.objectType(surface) == 'transform': surface = mc.listRelatives(surface,s=True,ni=True,pa=True)[0] - + # Get MFnNurbsSurface selection = OpenMaya.MSelectionList() OpenMaya.MGlobal.getSelectionListByName(surface,selection) @@ -44,7 +44,7 @@ def getSurfaceFn(surface): selection.getDagPath(0,surfacePath) surfaceFn = OpenMaya.MFnNurbsSurface() surfaceFn.setObject(surfacePath) - + # Return result return surfaceFn @@ -79,14 +79,14 @@ def closestPoint(surface,pos=(0,0,0)): ''' # Check surface if not isSurface(surface): raise Exception('Object '+surface+' is not a valid surface!') - + # Get point world position pos = glTools.utils.base.getPosition(pos) pt = OpenMaya.MPoint(pos[0],pos[1],pos[2],1.0) - + # Get surface function set surfFn = getSurfaceFn(surface) - + # Get uCoord and vCoord pointer objects uCoord = OpenMaya.MScriptUtil() uCoord.createFromDouble(0.0) @@ -94,7 +94,7 @@ def closestPoint(surface,pos=(0,0,0)): vCoord = OpenMaya.MScriptUtil() vCoord.createFromDouble(0.0) vCoordPtr = vCoord.asDoublePtr() - + # get closest uCoord to edit point position surfFn.closestPoint(pt,uCoordPtr,vCoordPtr,True,0.0001,OpenMaya.MSpace.kWorld) return (OpenMaya.MScriptUtil(uCoordPtr).asDouble(),OpenMaya.MScriptUtil(vCoordPtr).asDouble()) @@ -104,14 +104,14 @@ def distToSurface(surface,pos=(0,0,0)): ''' # Get point world position pos = glTools.utils.base.getPosition(pos) - + # Get closest point to surface uv = closestPoint(surface,pos) pt = mc.pointOnSurface(surface,u=uv[0],v=uv[1],p=True) - + # Get distance to surface point dist = glTools.utils.mathUtils.distanceBetween(pos,pt) - + # Return Result return dist @@ -124,13 +124,13 @@ def snapPtsToSurface(surface,pointList): ''' # Check surface if not isSurface(surface): raise Exception('Object '+surface+' is not a valid surface!') - + # Check points pointList = mc.ls(pointList,fl=True) - + # Transform types transform = ['transform','joint','ikHandle','effector'] - + # Snap points for pt in pointList: # Check Transform @@ -142,7 +142,7 @@ def snapPtsToSurface(surface,pointList): (uParam,vParam) = closestPoint(surface,pos) sPt = mc.pointOnSurface(surface,u=uParam,v=vParam,position=True) mc.move(sPt[0],sPt[1],sPt[2],pt,ws=True,a=True) - + def locatorSurface(surface,controlPoints=[],locatorScale=0.075,prefix=''): ''' Drive the control point positions of a surface with a set of control locators @@ -160,19 +160,19 @@ def locatorSurface(surface,controlPoints=[],locatorScale=0.075,prefix=''): raise Exception('Object '+surface+' is not a valid surface!') if mc.objectType(surface) == 'transform': surface = mc.listRelatives(surface,s=True,ni=True,pa=True)[0] - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(surface) - + # Calculate locator scale locatorScale *= math.sqrt(glTools.utils.surface.surfaceArea(surface)) - + # Get Control Points if not controlPoints: controlPoints = glTools.utils.component.getComponentIndexList(surface)[surface] else: controlPoints = glTools.utils.component.getComponentIndexList(controlPoints)[surface] - + # Create locators and connect to control points locatorList = [] for cv in controlPoints: @@ -184,14 +184,14 @@ def locatorSurface(surface,controlPoints=[],locatorScale=0.075,prefix=''): loc = mc.spaceLocator(n=loc)[0] locatorList.append(loc) mc.setAttr(loc+'.localScale',locatorScale,locatorScale,locatorScale) - + # Get control point world position pos = mc.pointPosition(surface+'.cv['+str(cv[0])+']['+str(cv[1])+']') mc.setAttr(loc+'.t',pos[0],pos[1],pos[2]) mc.makeIdentity(loc,apply=True,t=1,r=1,s=1,n=0) # Connect locator position to control point mc.connectAttr(loc+'.worldPosition[0]',surface+'.controlPoints['+str(ind)+']') - + return locatorList def surfaceArea(surface,worldSpace=True): @@ -209,14 +209,14 @@ def surfaceArea(surface,worldSpace=True): if mc.objectType(surfaceShape) != 'nurbsSurface': raise Exception('Object '+surface+' is not a valid nurbs surface!') surface = surfaceShape - + # Get MFnNurbsSurface surfaceFn = getSurfaceFn(surface) # Get surface area area = 0.0 if worldSpace: area = surfaceFn.area(OpenMaya.MSpace.kWorld) else: area = surfaceFn.area(OpenMaya.MSpace.kObject) - + # Return result return area @@ -238,13 +238,13 @@ def snapToSurface(surface,obj,uValue=0.0,vValue=0.0,useClosestPoint=False,snapPi ''' # Check surface if not isSurface(surface): raise Exception('Object '+surface+' is not a valid surface!!') - + # Check uValue/vValue minu = mc.getAttr(surface+'.minValueU') maxu = mc.getAttr(surface+'.maxValueU') minv = mc.getAttr(surface+'.minValueV') maxv = mc.getAttr(surface+'.maxValueV') - + # Closest Point if useClosestPoint: pos = mc.xform(obj,q=True,ws=True,rp=True) @@ -252,10 +252,10 @@ def snapToSurface(surface,obj,uValue=0.0,vValue=0.0,useClosestPoint=False,snapPi # Verify surface parameter if uValue < minu or uValue > maxu: raise Exception('U paramater '+str(uValue)+' is not within the U parameter range for '+surface+'!!') if vValue < minv or vValue > maxv: raise Exception('V paramater '+str(vValue)+' is not within the V parameter range for '+surface+'!!') - + # Get surface point position pnt = mc.pointPosition(surface+'.uv['+str(uValue)+']['+str(vValue)+']') - + # Snap to Curve piv = mc.xform(obj,q=True,ws=True,rp=True) if snapPivot: mc.xform(obj,piv=pnt,ws=True) @@ -306,15 +306,15 @@ def orientToSurface( surface, # Verify surface parameter if uValue < minu or uValue > maxu: raise Exception('U paramater '+str(uValue)+' is not within the U parameter range for '+surface+'!!') if vValue < minv or vValue > maxv: raise Exception('V paramater '+str(uValue)+' is not within the V parameter range for '+surface+'!!') - + # Check object if not mc.objExists(obj): raise Exception('Object '+obj+' does not exist!!') rotateOrder = mc.getAttr(obj+'.ro') - + # Get tangents at surface point tanU = mc.pointOnSurface(surface,u=uValue,v=vValue,ntu=True) tanV = mc.pointOnSurface(surface,u=uValue,v=vValue,ntv=True) - + # Build rotation matrix aimVector = tanU if alignTo == 'v': aimVector = tanV @@ -324,10 +324,10 @@ def orientToSurface( surface, if alignTo == 'v': aimAxis = tangentVAxis upAxis = tangentVAxis if alignTo == 'v': upAxis = tangentUAxis - + mat = glTools.utils.matrix.buildRotation(aimVector,upVector,aimAxis,upAxis) rot = glTools.utils.matrix.getRotation(mat,rotateOrder) - + # Orient object to surface mc.rotate(rot[0],rot[1],rot[2],obj,a=True,ws=True) @@ -346,19 +346,19 @@ def rebuild(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False,rebu # ========== # - Checks - # ========== - + # Check surface if not isSurface(surface): raise Exception('Object "'+surface+'" is not a valid surface!') - + # Check spans if not spansU: spansU = mc.getAttr(surface+'.spansU') if not spansV: spansV = mc.getAttr(surface+'.spansV') - + # ============= # - Rebuild U - # ============= - + # Get V range if rebuildUfirst: dir = 'u' @@ -373,17 +373,17 @@ def rebuild(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False,rebu min = mc.getAttr(surface+'.minValueU') max = mc.getAttr(surface+'.maxValueU') val = min + (max - min) * 0.5 - + # Caluculate surface length iso_crv = mc.duplicateCurve(surface+'.'+opp+'['+str(val)+']',ch=0,rn=0,local=0)[0] iso_len = mc.arclen(iso_crv) iso_inc = iso_len / spans - + # Get spaced isoparm list curveFn = glTools.utils.curve.getCurveFn(iso_crv) iso_list = [surface+'.'+dir+'['+str(curveFn.findParamFromLength(iso_inc*i))+']' for i in range(spans+1)] mc.delete(iso_crv) - + # Check full rebuild if fullRebuildV: # Extract isoparm curves @@ -398,11 +398,11 @@ def rebuild(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False,rebu else: # Loft intermediate surface int_surface = mc.loft(iso_list,ch=0,u=1,c=0,ar=1,d=3,ss=1,rn=0,po=0,rsn=True)[0] - + # ============= # - Rebuild V - # ============= - + # Get V range (intermediate surface) if rebuildUfirst: dir = 'u' @@ -417,17 +417,17 @@ def rebuild(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False,rebu min = mc.getAttr(int_surface+'.minValueV') max = mc.getAttr(int_surface+'.maxValueV') val = min + (max - min) * 0.5 - + # Caluculate surface length (intermediate surface) iso_crv = mc.duplicateCurve(int_surface+'.'+opp+'['+str(val)+']',ch=0,rn=0,local=0)[0] iso_len = mc.arclen(iso_crv) iso_inc = iso_len / spans - + # Get spaced isoparm list curveFn = glTools.utils.curve.getCurveFn(iso_crv) iso_list = [int_surface+'.'+dir+'['+str(curveFn.findParamFromLength(iso_inc*i))+']' for i in range(spans+1)] mc.delete(iso_crv) - + # Check full rebuild if fullRebuildU: # Extract isoparm curves @@ -442,31 +442,31 @@ def rebuild(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False,rebu else: # Loft final surface rebuild_surface = mc.loft(iso_list,ch=0,u=1,c=0,ar=1,d=3,ss=1,rn=0,po=0,rsn=True)[0] - + # Rename rebuilt surface rebuild_surface = mc.rename(rebuild_surface,surface+'_rebuild') rebuild_surfaceShape = mc.listRelatives(surface,s=True,ni=True,pa=True)[0] mc.delete(int_surface) - + # Re-parameterize 0-1 mc.rebuildSurface(rebuild_surface,ch=False,rpo=True,dir=2,rt=0,end=1,kr=0,kcp=1,kc=1,tol=0,fr=0) - + # Initialize return value outputShape = rebuild_surfaceShape - + # ==================== # - Replace Original - # ==================== - + if replaceOrig: - + """ # Get original shape shapes = glTools.utils.shape.getShapes(surface,nonIntermediates=True,intermediates=False) if not shapes: # Find Intermediate Shapes shapes = glTools.utils.shape.listIntermediates(surface) - + # Check shapes if not shapes: raise Exception('Unable to determine shape for surface "'+surface+'"!') @@ -475,7 +475,7 @@ def rebuild(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False,rebu # Find Intermediate Shapes shapes = glTools.utils.shape.findInputShape(shapes[0]) """ - + # Check history shapes = mc.listRelatives(surface,s=True,ni=True,pa=True) if not shapes: raise Exception('Unable to determine shape for surface "'+surface+'"!') @@ -483,15 +483,15 @@ def rebuild(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False,rebu shapeHist = mc.listHistory(shape) if shapeHist.count(shape): shapeHist.remove(shape) if shapeHist: print('Surface "" contains construction history, creating new shape!') - + # Override shape info and delete intermediate mc.connectAttr(rebuild_surfaceShape+'.local',shape+'.create',f=True) outputShape = shape - + # ================= # - Return Result - # ================= - + return outputShape def rebuild_old(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False,replaceOrig=False): @@ -509,19 +509,19 @@ def rebuild_old(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False, # Check surface if not isSurface(surface): raise Exception('Object "'+surface+'" is not a valid surface!') - + # Check spans if not spansU: spansU = mc.getAttr(surface+'.spansU') if not spansV: spansV = mc.getAttr(surface+'.spansV') - + # ------------- # - Rebuild V - - + # Get V range minu = mc.getAttr(surface+'.minValueU') maxu = mc.getAttr(surface+'.maxValueU') u = minu + (maxu - minu) * 0.5 - + # Extract isoparm curve iso_crv = mc.duplicateCurve(surface+'.u['+str(u)+']',ch=0,rn=0,local=0)[0] iso_len = mc.arclen(iso_crv) @@ -529,7 +529,7 @@ def rebuild_old(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False, curveFn = glTools.utils.curve.getCurveFn(iso_crv) iso_list = [surface+'.v['+str(curveFn.findParamFromLength(iso_inc*i))+']' for i in range(spansV+1)] mc.delete(iso_crv) - + # Check full rebuild if fullRebuildU: # Extract isoparm curves @@ -544,15 +544,15 @@ def rebuild_old(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False, else: # Loft intermediate surface int_surface = mc.loft(iso_list,ch=0,u=1,c=0,ar=1,d=3,ss=1,rn=0,po=0,rsn=True)[0] - + # ------------- # - Rebuild U - - + # Get V range (intermediate surface) minv = mc.getAttr(int_surface+'.minValueV') maxv = mc.getAttr(int_surface+'.maxValueV') v = minv + (maxv - minv) * 0.5 - + # Extract isoparm curve (intermediate surface) iso_crv = mc.duplicateCurve(int_surface+'.v['+str(v)+']',ch=0,rn=0,local=0)[0] iso_len = mc.arclen(iso_crv) @@ -560,7 +560,7 @@ def rebuild_old(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False, curveFn = glTools.utils.curve.getCurveFn(iso_crv) iso_list = [int_surface+'.u['+str(curveFn.findParamFromLength(iso_inc*i))+']' for i in range(spansU+1)] mc.delete(iso_crv) - + # Check full rebuild if fullRebuildV: # Extract isoparm curves @@ -575,26 +575,26 @@ def rebuild_old(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False, else: # Loft final surface rebuild_surface = mc.loft(iso_list,ch=0,u=1,c=0,ar=1,d=3,ss=1,rn=0,po=0,rsn=True)[0] - + rebuild_surface = mc.rename(rebuild_surface,surface+'_rebuild') rebuild_surfaceShape = mc.listRelatives(surface,s=True,ni=True,pa=True)[0] mc.delete(int_surface) - + # Initialize return value outputShape = rebuild_surfaceShape - + # -------------------- # - Replace Original - - + if replaceOrig: - + """ # Get original shape shapes = glTools.utils.shape.getShapes(surface,nonIntermediates=True,intermediates=False) if not shapes: # Find Intermediate Shapes shapes = glTools.utils.shape.listIntermediates(surface) - + # Check shapes if not shapes: raise Exception('Unable to determine shape for surface "'+surface+'"!') @@ -603,7 +603,7 @@ def rebuild_old(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False, # Find Intermediate Shapes shapes = glTools.utils.shape.findInputShape(shapes[0]) """ - + # Check history shapes = mc.listRelatives(surface,s=True,ni=True,pa=True) if not shapes: raise Exception('Unable to determine shape for surface "'+surface+'"!') @@ -611,11 +611,11 @@ def rebuild_old(surface,spansU=0,spansV=0,fullRebuildU=False,fullRebuildV=False, shapeHist = mc.listHistory(shape) if shapeHist.count(shape): shapeHist.remove(shape) if shapeHist: print('Surface "" contains construction history, creating new shape!') - + # Override shape info and delete intermediate mc.connectAttr(rebuild_surfaceShape+'.local',shape+'.create',f=True) outputShape = shape - + # Return result return outputShape @@ -635,14 +635,14 @@ def intersect(surface,source,direction): source = glTools.utils.base.getMPoint(source) # Get direction vector direction = OpenMaya.MVector(direction[0],direction[1],direction[2]) - + # Calculate intersection hitPt = OpenMaya.MPoint() hit = surfaceFn.intersect(source,direction,None,None,hitPt,0.0001,OpenMaya.MSpace.kWorld,False,None,None) if not hit: print 'No intersection found!' hitPt = OpenMaya.MPoint.origin - + # Return intersection hit point return [hitPt[0],hitPt[1],hitPt[2]] @@ -665,27 +665,27 @@ def projectToSurface(surface,targetSurface,direction='u',keepOriginal=False,pref raise Exception('Surface "'+surface+'" does not exist!!') if not isSurface(surface): raise Exception('Object "'+surface+'" is not a valid nurbs surface!!') - + # Check target surface if not mc.objExists(targetSurface): raise Exception('Target surface "'+targetSurface+'" does not exist!!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(surface) - + # Check direction direction = direction.upper() if (direction != 'U') and (direction != 'V'): raise Exception('Invalid surface direction specified! Must specify either "u" or "v"!!') - + # Get surface information spans = mc.getAttr(surface+'.spans'+direction) minVal = mc.getAttr(surface+'.minValue'+direction) maxVal = mc.getAttr(surface+'.maxValue'+direction) - + # Create main surface group mainGrp = mc.createNode('transform',n=prefix+'_grp') - + # Extract curves curveList = [] curveGrpList = [] @@ -717,23 +717,23 @@ def projectToSurface(surface,targetSurface,direction='u',keepOriginal=False,pref geomConstraintList.append(geomConstraint[0]) # Center group pivot mc.xform(curveGrp,cp=True) - + # Delete original surface surfaceName = prefix+'_surface' if not keepOriginal: surfaceName = surface mc.delete(surface) - + # Loft new surface surfaceLoft = mc.loft(curveList,ch=1,u=1,c=0,ar=1,d=3,ss=1,rn=0,po=0,rsn=True) surface = mc.rename(surfaceLoft[0],surface) surface = mc.parent(surface,mainGrp)[0] mc.reorder(surface,f=True) loft = mc.rename(surfaceLoft[1],prefix+'_loft') - + # Return result return[surface,loft,curveList,curveGrpList,curveLocList,geomConstraintList] - + def rebuildFromExistingIsoparms(surface,direction='u',degree=3,close=False,keepHistory=False): ''' Build a new nurbs surface from an existing surfaces isoparms @@ -753,12 +753,12 @@ def rebuildFromExistingIsoparms(surface,direction='u',degree=3,close=False,keepH raise Exception('Surface "'+surface+'" does not exist!!') if not isSurface(surface): raise Exception('Object "'+surface+'" is not a valid nurbs surface!!') - + # Check direction direction = direction.lower() if not direction == 'u' and not direction == 'v': raise Exception('Invalid surface direction! Accepted values are "u" and "v"!') - + # Get surface details surfFn = getSurfaceFn(surface) spans = mc.getAttr(surface+'.spans'+direction.upper()) @@ -767,18 +767,18 @@ def rebuildFromExistingIsoparms(surface,direction='u',degree=3,close=False,keepH knots = OpenMaya.MDoubleArray() if direction == 'u': surfFn.getKnotsInU(knots) if direction == 'v': surfFn.getKnotsInV(knots) - + # Build iso list for surface rebuild if degree > 1: knots = knots[(degree-1):-(degree-1)] isoList = [surface+'.'+direction+'['+str(i)+']' for i in knots] if not close and form: #isoList.append(isoList[0]) isoList[-1] = isoList[-1] - 0.0001 - + # Loft new rebuild surface rebuild = mc.loft(isoList,ch=keepHistory,u=True,c=close,ar=False,d=degree,ss=1,rn=False,po=False,rsn=(direction=='v')) rebuild = mc.rename(rebuild[0],surface+'_rebuild') - + # Return result return rebuild @@ -799,13 +799,13 @@ def rebuildFromIsoparms(surface,spansU=0,spansV=0,degree=3,keepHistory=False): raise Exception('Surface "'+surface+'" does not exist!!') if not isSurface(surface): raise Exception('Object "'+surface+'" is not a valid nurbs surface!!') - + # Initialize function pointers uMinPtr = OpenMaya.MScriptUtil().asDoublePtr() uMaxPtr = OpenMaya.MScriptUtil().asDoublePtr() vMinPtr = OpenMaya.MScriptUtil().asDoublePtr() vMaxPtr = OpenMaya.MScriptUtil().asDoublePtr() - + # Get surface details surfFn = getSurfaceFn(surface) surfFn.getKnotDomain(uMinPtr,uMaxPtr,vMinPtr,vMaxPtr) @@ -815,15 +815,15 @@ def rebuildFromIsoparms(surface,spansU=0,spansV=0,degree=3,keepHistory=False): vMax = OpenMaya.MScriptUtil(vMaxPtr).asDouble() uDif = uMax - uMin vDif = vMax - vMin - + # Get surface form closeU = bool(mc.getAttr(surface+'.formU')) closeV = bool(mc.getAttr(surface+'.formV')) - + # Check spans if not spansU: spansU = surfFn.numKnotsInU() if not spansV: spansV = surfFn.numKnotsInV() - + # Get new knot values uList = [] vList = [] @@ -831,15 +831,15 @@ def rebuildFromIsoparms(surface,spansU=0,spansV=0,degree=3,keepHistory=False): vInc = vDif/(spansV-int(not closeV)) for u in range(spansU): uList.append(uMin+(uInc*u)) for v in range(spansV): vList.append(vMin+(vInc*v)) - + # Rebuild in U uLoft = mc.loft([surface+'.u['+str(i)+']' for i in uList],close=closeU,degree=degree) uSurface = uLoft[0] - + # Rebuld in V vLoft = mc.loft([uSurface+'.v['+str(i)+']' for i in vList],close=closeV,degree=degree) rebuildSurface = vLoft[0] - + # Return result return rebuildSurface diff --git a/utils/surfacePoints.py b/utils/surfacePoints.py index 9744f50..a69142d 100644 --- a/utils/surfacePoints.py +++ b/utils/surfacePoints.py @@ -28,13 +28,13 @@ def add(surface,targetList,surfacePointsNode='',alignTo='u',rotate=True,tangentU # Check surface if not glTools.utils.surface.isSurface(surface): raise Exception('Object "" is not a valid nurbs surface!!') - + # Check prefix if not prefix: prefix = glTools.utils.stringUtils.stripSuffix(surface) - + # Check targetList if not targetList: raise Exception('Invalid target list!!') - + # Check surfacePoints node if not surfacePointsNode: surfacePointsNode = prefix+'surfacePoints' @@ -53,17 +53,17 @@ def add(surface,targetList,surfacePointsNode='',alignTo='u',rotate=True,tangentU axisDict = {'x':0,'y':1,'z':2,'-x':3,'-y':4,'-z':5} mc.setAttr(surfacePointsNode+'.tangentUAxis',axisDict[tangentUAxis]) mc.setAttr(surfacePointsNode+'.tangentVAxis',axisDict[tangentVAxis]) - + # Find next available input index nextIndex = getNextAvailableIndex(surfacePointsNode) - + # Create surface constraints transformList = [] for i in range(len(targetList)): - + # Get current input index ind = glTools.utils.stringUtils.stringIndex(i+1,2) - + # Initialize UV parameter variable uv = (0.0,0.0) pos = (0.0,0.0,0.0) @@ -81,13 +81,13 @@ def add(surface,targetList,surfacePointsNode='',alignTo='u',rotate=True,tangentU pos = mc.pointOnSurface(surface,u=uv[0],v=uv[1],p=True) paramU = uv[0] paramV = uv[1] - + # Get surface point information pnt = mc.pointOnSurface(surface,u=paramU,v=paramV,p=True) normal = mc.pointOnSurface(surface,u=paramU,v=paramV,nn=True) tangentU = mc.pointOnSurface(surface,u=paramU,v=paramV,ntu=True) tangentV = mc.pointOnSurface(surface,u=paramU,v=paramV,ntv=True) - + # Clamp param to safe values minU = mc.getAttr(surface+'.minValueU') maxU = mc.getAttr(surface+'.maxValueU') @@ -97,26 +97,26 @@ def add(surface,targetList,surfacePointsNode='',alignTo='u',rotate=True,tangentU elif paramU > (maxU-0.001): paramU = maxU if paramV < (minV+0.001): paramV = minV elif paramV > (maxV-0.001): paramV = maxV - + # Create constraint transform transform = prefix+'_surfacePoint'+ind+'_transform' transform = mc.createNode('transform',n=transform) transformList.append(transform) - + # Add param attributes mc.addAttr(transform,ln='param',at='compound',numberOfChildren=2) mc.addAttr(transform,ln='paramU',at='double',min=minU,max=maxU,dv=paramU,k=True,p='param') mc.addAttr(transform,ln='paramV',at='double',min=minV,max=maxV,dv=paramV,k=True,p='param') - + # Connect to surfacePoints node #mc.setAttr(surfacePointsNode+'.offset['+ind+']',offsetU,offsetV,offsetN) mc.connectAttr(transform+'.param',surfacePointsNode+'.param['+ind+']',f=True) mc.connectAttr(transform+'.parentMatrix',surfacePointsNode+'.targetMatrix['+ind+']',f=True) - + # Connect to transform mc.connectAttr(surfacePointsNode+'.outTranslate['+ind+']',transform+'.translate',f=True) if rotate: mc.connectAttr(surfacePointsNode+'.outRotate['+ind+']',transform+'.rotate',f=True) - + # Return result return (surfacePointsNode,transformList) @@ -130,17 +130,17 @@ def getNextAvailableIndex(surfacePointsNode): OpenMaya.MGlobal.getSelectionListByName(surfacePointsNode,sel) obj = OpenMaya.MObject() sel.getDependNode(0,obj) - + # Get param plug paramPlug = OpenMaya.MFnDependencyNode(obj).findPlug('param') - + # Get valid index list indexList = OpenMaya.MIntArray() paramPlug.getExistingArrayAttributeIndices(indexList) - + # Determine next available index nextIndex = 0 if indexList.length(): nextIndex = indexList[-1] + 1 - + # Return next available index return nextIndex diff --git a/utils/tag.py b/utils/tag.py index 99083b2..0eccfad 100644 --- a/utils/tag.py +++ b/utils/tag.py @@ -3,59 +3,59 @@ import glTools.tools.namingConvention class Tag( object ): - + def __init__(self): ''' ''' self.nameTagAttr = 'nameTag' - + def addNameTag(self,control,tag): ''' Set the name tag value for the specified control ''' - + # Check control if not mc.objExists(control): raise Exception('Object '+control+' does not exist!') - + # Add Tag attribute if mc.objExists(control+'.'+self.nameTagAttr): mc.addAttr(control,ln=self.nameTagAttr,dt='string') mc.setAttr(control+'.'+self.nameTagAttr,tag,type='string') - + def getNameTag(self,control): ''' Return the name tag value of the specified control ''' - + # Check control if not mc.objExists(control): raise Exception('Object '+control+' does not exist!') # Check tag attribute if not mc.objExists(control+'.'+self.nameTagAttr): raise Exception('Object '+control+' does not have a "'+self.nameTagAttr+'" attribute!') # Return tag string value return mc.getAttr(control+'.'+self.nameTagAttr) - + def guessNameTag(self,control,side=True,part=True,optSide=True,subPart=True,node=False): - ''' + ''' Return a best guess name tag based on a controls current name. Uses name element comparison to our naming convention module. ''' tag = '' - + # Get naming convention dictionaries nameConvention = glTools.tools.namingConvention.NamingConvention() sideDict = dict((value, key) for key, value in nameConvention.side.iteritems()) partDict = dict((value, key) for key, value in nameConvention.part.iteritems()) subPartDict = dict((value, key) for key, value in nameConvention.subPart.iteritems()) nodeDict = dict((value, key) for key, value in nameConvention.node.iteritems()) - + # Get name elements controlElem = control.split(nameConvention.delineator) controlElemCnt = len(controlElem) controlElemInd = 0 - + # Check number of elements if controlElemCnt < 3: print 'Warning: Name pattern does not match naming convention' - + # Get side if side and sideDict.has_key(controlElem[controlElemInd]): if controlElem[controlElemInd] != nameConvention.side['center']: @@ -78,5 +78,5 @@ def guessNameTag(self,control,side=True,part=True,optSide=True,subPart=True,node # Get type if node and nodeDict.has_key(controlElem[controlElemInd]): tag += nodeDict[controlElem[controlElemInd]].capitalize() - + return tag diff --git a/utils/tangentBlend.py b/utils/tangentBlend.py index 9518e58..d84b154 100644 --- a/utils/tangentBlend.py +++ b/utils/tangentBlend.py @@ -36,26 +36,26 @@ def findTangentBlendDeformer(geo): # Get Geometry History tangentBlend = '' history = mc.listHistory(geo) - + # Check for tangentBlendDeformer for i in range(len(history)): if(mc.objectType(history[i],isAType='tangentBlendDeformer')): # Capture result tangentBlend = history[i] - + # Return result return tangentBlend - + def findAffectedGeometry(tangentBlend): ''' ''' # Check deformer if not isTangentBlend(tangentBlend): raise Exception('Object "'+tangentBlend+'" is not a valid tangentBlend deformer node!') - + # Get affected geometry geometry = glTools.utils.deformer.getAffectedGeometry(tangentBlend).keys()[0] - + # Return result return geometry @@ -73,16 +73,16 @@ def duplicateGeo(obj,name): ''' # Duplicate Geometry dup = mc.duplicate(obj,name=name)[0] - + # Removed unused shapes dupShapes = mc.listRelatives(dup,s=True,ni=True) dupShapesAll = mc.listRelatives(dup,s=True) deleteShapes = list(set(dupShapesAll) - set(dupShapes)) mc.delete(deleteShapes) - + # Unlock transforms unlockTransform(dup) - + # Return result return dup @@ -91,31 +91,31 @@ def create(geo,name=''): ''' # Load Plugin if not mc.pluginInfo('tangentBlendDeformer',q=True,l=True): mc.loadPlugin('tangentBlendDeformer') - + # Create Deformer if not name: name = geo+'_tangentBlendDeformer' tangentBlend = mc.deformer(geo,type='tangentBlendDeformer',n=name)[0] - + # Return Result - return tangentBlend + return tangentBlend def connectPose(baseXForm,offsetXForm,deformer): ''' ''' - # Get next available deformer index + # Get next available deformer index index = glTools.utils.attribute.nextAvailableMultiIndex(deformer+'.pose',useConnectedOnly=False) - + # Get pose geometry shapes baseShape = mc.listRelatives(baseXForm,s=True,ni=True,pa=True) - offsetShape = mc.listRelatives(offsetXForm,s=True,ni=True,pa=True) - + offsetShape = mc.listRelatives(offsetXForm,s=True,ni=True,pa=True) + # Connect pose base attrName = geomAttrName(baseShape[0]) mc.connectAttr(baseShape[0]+attrName,deformer+'.pose['+str(index)+'].poseBaseMesh',f=True) # Connect pose offset attrName = geomAttrName(offsetShape[0]) mc.connectAttr(offsetShape[0]+attrName,deformer+'.pose['+str(index)+'].poseOffsetMesh',f=True) - + # Return result return index @@ -125,21 +125,21 @@ def addPose(tangentBlend,baseGeo='',offsetGeo='',poseName=''): # Define suffix tags tangentBlend_baseTag = '_poseBase' tangentBlend_offsetTag = '_poseOffset' - + # Get connected geometry geo = findAffectedGeometry(tangentBlend) - + # Check pose geometry if not baseGeo: baseGeo = duplicateGeo(geo,geo+tangentBlend_baseTag) if not offsetGeo: baseGeo = duplicateGeo(geo,geo+tangentBlend_offsetTag) - + # Connect to deformer poseIndex = connectPose(baseGeo,offsetGeo,tangentBlend) - + # Alias pose name and set keyable if poseName: mc.aliasAttr(poseName,tangentBlend+'.pose['+str(poseIndex)+'].poseWeight') mc.setAttr(tangentBlend+'.pose['+str(poseIndex)+'].poseWeight',cb=True) mc.setAttr(tangentBlend+'.pose['+str(poseIndex)+'].poseWeight',k=True) - + return [baseGeo,offsetGeo] diff --git a/utils/toggleOverride.py b/utils/toggleOverride.py index d2881b3..f62ce57 100644 --- a/utils/toggleOverride.py +++ b/utils/toggleOverride.py @@ -1,17 +1,17 @@ import maya.cmds as mc def ui(): - + ''' Toggles override display state of selected element surfaces Open existing asset scene, select a control on your asset(example - supermover) Launch toggleOverride_GUI from the rigTools menu, select the options you want and execute. - + @keyword: rig, cfin, utilities, gui, interface, window - + @appVersion: 8.5, 2008 ''' - + if mc.window('toggleUIwin', q=1, ex=1): mc.deleteUI('toggleUIwin') @@ -25,9 +25,9 @@ def ui(): toggleUI = mc.window('toggleUIwin', title='toggleOverride_GUI - v.5', iconName='toggleOverride_GUI', w=uiWidth, h=uiHeight, resizeToFitChildren=False) mc.frameLayout(marginHeight=30, labelVisible=0, borderStyle='out') - + genForm = mc.formLayout(numberOfDivisions=100) - + genColumn =mc.columnLayout(adjustableColumn=True, rowSpacing=5) mc.rowLayout(nc=4, cat=[(1, 'right', 5), (2, 'both', 5), (3, 'right', 5), (4, 'both', 5)], cw=[(1,100),(2,110),(3,100),(4,100)]) @@ -49,21 +49,21 @@ def ui(): radioPolyEnableOverrides = mc.checkBox('polyEnable', v=True, label='overrides', h=30) # back up to Column Layout - mc.setParent('..') + mc.setParent('..') mc.rowLayout(nc=2, cat=[(1, 'right', 128)],cw=[(1,305),(2,305)]) radioPolyEnableShadingOverrides = mc.checkBox('polyEnableShading', v=True, label='shading', h=30) # back up to Column Layout - mc.setParent('..') + mc.setParent('..') mc.rowLayout(nc=2, cat=[(1, 'right', 116), (2, 'right', 290)], cw=[(1,305),(2,305)]) ok = mc.button(w=85, h=30, backgroundColor=(0, 1, 0), al='center', command='glTools.utils.toggleOverride.toggleOverride_WRP()', label='OK') cancel = mc.button(w=85, h=30, backgroundColor=(1, 0, 0), al='center', command='mc.deleteUI("'+toggleUI+'")', label='Cancel') - + # tell Maya to draw the window mc.showWindow('toggleUIwin') @@ -71,34 +71,34 @@ def toggleOverride_WRP(): ''' Wrapper to execute toggleOverride with inputs from toggleOverride_GUI - + @keyword: rig, cfin, utilities, gui, interface, window - + @appVersion: 8.5, 2008 - + ''' - + sel=mc.ls(sl=True) - + mEnableOverrides = mc.checkBox('polyEnable', q=True, v=True) mDisplayMode = mc.optionMenu('polyToggleTypeDropdown', q=True, select=True) mEnableShading = mc.checkBox('polyEnableShading', q=True, v=True) - + if not len(sel): raise Exception('error You must select a control in order to toggle display override on!') - + toggleOverride(sel[0], 'model', mEnableOverrides, (mDisplayMode - 1), mEnableShading) - + def toggleOverride(assetNode, geoGroup, enableOverrides, displayMode, enableShading): - + ''' executable for toggleOverride. The executable needs to be given a node from the asset in your scene to perform the operation on - available modes are as follows: - Normal(0) - geometry is selectable - Template(1) - geometry is in template mode - Reference(2) - geometry is in reference mode - + available modes are as follows: + Normal(0) - geometry is selectable + Template(1) - geometry is in template mode + Reference(2) - geometry is in reference mode + @param assetNode: Node on the asset on which to toggleOverrides @type assetNode: str @param geoGroup: Node which contains all meshes for asset @@ -109,28 +109,28 @@ def toggleOverride(assetNode, geoGroup, enableOverrides, displayMode, enableShad @type displayNode: int @param enableShading: 1 or 0 to enable the shading. Default is on. @type: displayNode: int - + @keyword: rig, cfin, utilities, gui, interface, window - + @example: toggleOverride jack:cn_hed01_ccc model 1 2 1; - + @appVersion: 8.5, 2008 ''' - + ##find all the geo in that group if not mc.objExists(assetNode): raise Exception('') if assetNode.count(':'): geoGroup = assetNode.split(':')[0] + ':' + geoGroup - + if not mc.objExists(geoGroup): raise Exception('') geo = mc.listRelatives(geoGroup, ad=1, ni=1, typ=['mesh','nurbsSurface']) - + ##cycle through that geo and set its state based on the mode, overrides, and shading for shape in geo: mc.setAttr(shape + ".overrideEnabled",enableOverrides) if(enableOverrides): mc.setAttr(shape + ".overrideShading",enableShading) mc.setAttr(shape + ".overrideDisplayType",displayMode) - + ##finished print 'Done toggling overrides' diff --git a/utils/transform.py b/utils/transform.py index e8a77da..2d5650f 100644 --- a/utils/transform.py +++ b/utils/transform.py @@ -13,11 +13,11 @@ def isTransform(obj): ''' # Check object exists if not mc.objExists(obj): return False - + # Check transform mObject = glTools.utils.base.getMObject(obj) if not mObject.hasFn(OpenMaya.MFn.kTransform): return False - + # Return result return True @@ -44,22 +44,22 @@ def axisVector(transform,axis,normalize=False): # Define axis dictionary axis = axis.lower() axisDict = {'x':(1,0,0),'y':(0,1,0),'z':(0,0,1),'-x':(-1,0,0),'-y':(0,-1,0),'-z':(0,0,-1)} - + # Checks if not mc.objExists(transform): raise Exception('Transform "'+transform+'" does not exist!') if not axisDict.has_key(axis): raise Exception('Invalid axis "'+axis+'"!') - + # Get transform matrix tMatrix = getMatrix(transform) - + # Get worldSpace axis vector axisVector = glTools.utils.matrix.vectorMatrixMultiply(axisDict[axis],tMatrix) - + # Normalize if normalize: axisVector = glTools.utils.mathUtils.normalizeVector(axisVector) - + # Return Result return axisVector @@ -76,10 +76,10 @@ def match(transform,target): raise Exception('Transform "'+transform+'" does not exist!') if not mc.objExists(target): raise Exception('Target transform "'+target+'" does not exist!') - + # Get target matrix targetMat = mc.xform(target,q=True,ws=True,matrix=True) - + # Set source matrix mc.xform(transform,ws=True,matrix=targetMat) @@ -100,15 +100,15 @@ def matchUsing(transform,reference,target): raise Exception('Reference transform "'+target+'" does not exist!') if not mc.objExists(target): raise Exception('Target transform "'+target+'" does not exist!') - + # Get Transform, Target and Reference Matrices trMat = getMatrix(transform) rfMat = getMatrix(reference) tgMat = getMatrix(target) - + # Calculate Transform Target resultMat = trMat * rfMat.inverse() * tgMat - + # Set Transform Matrix setFromMatrix(transform,resultMat) @@ -123,12 +123,12 @@ def setFromMatrix(transform,matrix): # Checks if not mc.objExists(transform): raise Exception('Transform "'+transform+'" does not exist!') - + # Get Matrix as List matrixList = glTools.utils.matrix.asList(matrix) - + # Set source matrix mc.xform(transform,ws=True,matrix=matrixList) - + # Return Result return matrixList diff --git a/utils/visConnect.py b/utils/visConnect.py index d76ec27..369c976 100644 --- a/utils/visConnect.py +++ b/utils/visConnect.py @@ -10,31 +10,31 @@ def visConnect(): connects the visibilty attr of two or more objects ''' sel = mc.ls(sl = True) - + if sel < 2: raise UserInputError('You must select at least two objects in order to connect visibilities') - + ccc = sel[0] obj[] = stringArrayRemove({ccc}, sel); - + rig_visConnect(ccc, obj); ################################################################################################################# def rig_visConnect(control, geo[]): - + ''' used to create a vis channel on an object (first selected object) and attach it to the visibility of all other selected objects ''' - + if not mc.objExists(control): raise UserInputError('The control specified to rig_visConnect does not exist!') - + if not mc.attributeExists('vis', control): mc.addAttr(control, k=True, ln='vis', at='enum', en='off:on:') mc.setAttr(control + '.vis') 1 - + for i in len(geo): if not mc.objExists(geo[i]): continue diff --git a/utils/weightList.py b/utils/weightList.py index dd8c0cf..3e9941e 100644 --- a/utils/weightList.py +++ b/utils/weightList.py @@ -6,48 +6,48 @@ import os.path class WeightList(list): - + ''' to do : remap(0,1), normalize(), smooth() ''' - + FILE_FILTER = "All Files (*.*)" - + #============================= # Checks #============================= def _initialChecks(self, other): - + self._extraElements=[] self._scalar=False - + self._checkType(other) self._checkLength(other) - + def _checkType(self, other): if isinstance(other,types.FloatType) or isinstance(other,types.IntType): self._scalar=True - + def _checkLength(self, other): if self._scalar : return - + if len(self) < len(other): self._extraElements = other[len(self):] elif len(self) > len(other): self._extraElements = self[len(other):] - + #============================= # Utilities #============================= - + def _addExtraElements(self, other): other.extend(self._extraElements) return WeightList(other) - + #============================= # Modifiers #============================= - + def clamp(self, clampMin=0, clampMax=1): self = [max( clampMin, min(i, clampMax)) for i in self ] return self @@ -57,15 +57,15 @@ def normalize(self, normalizeMin=0, normalizeMax=1): old_range = max(self) - old_min self = WeightList([(n - old_min) / old_range * normalizeMax + normalizeMin for n in self]) return self - + def invert(self): self = WeightList([1.0-i for i in self]) return self - + #============================= # Operators #============================= - + def __add__(self,other): self._initialChecks(other) if self._scalar: @@ -86,7 +86,7 @@ def __mul__(self,other): return WeightList([i*other for i in self]) else: return self._addExtraElements([i[0]*i[1] for i in zip(self,other)]) - + # needs a 0 check def __div__(self,other): self._initialChecks(other) @@ -94,37 +94,37 @@ def __div__(self,other): return WeightList([i/other for i in self]) else: return self._addExtraElements([i[0]/i[1] for i in zip(self,other)]) - - + + def __iadd__(self,other): return WeightList(self.__add__(other)) - + def __isub__(self,other): return WeightList(self.__sub__(other)) - + def __imul__(self,other): return WeightList(self.__mul__(other)) - + def __idiv__(self,other): return WeightList(self.__div__(other)) - + def __radd__(self,other): return self.__add__(other) - + def __rsub__(self,other): return self.__sub__(other) - + def __rmul__(self,other): return self.__mul__(other) - + def __rdiv__(self,other): return self.__div__(other) - - + + # =============== # - SAVE / LOAD - # =============== - + def save(self,filePath,force=False): ''' Save data object to file. @@ -136,40 +136,40 @@ def save(self,filePath,force=False): # Check Directory Path dirpath = os.path.dirname(filePath) if not os.path.isdir(dirpath): os.makedirs(dirpath) - + # Check File Path if os.path.isfile(filePath) and not force: raise Exception('File "'+filePath+'" already exists! Use "force=True" to overwrite the existing file.') - + # Save File fileOut = open(filePath,'wb') cPickle.dump(self,fileOut) fileOut.close() - + # Print Message print('Saved '+self.__class__.__name__+': "'+filePath+'"') - + # Return Result return filePath - + def saveAs(self): ''' Save data object to file. - Opens a file dialog, to allow the user to specify a file path. + Opens a file dialog, to allow the user to specify a file path. ''' # Specify File Path filePath = mc.fileDialog2(fileFilter=self.FILE_FILTER,dialogStyle=2,fileMode=0,caption='Save As') - + # Check Path if not filePath: return filePath = filePath[0] - + # Save Data File filePath = self.save(filePath,force=True) - + # Return Result return filePath - + def load(self,filePath=''): ''' Load data object from file. @@ -184,14 +184,14 @@ def load(self,filePath=''): else: if not os.path.isfile(filePath): raise Exception('File "'+filePath+'" does not exist!') - + # Open File fileIn = open(filePath,'rb') self = cPickle.load(fileIn) - + # Print Message print('Loaded '+self.__class__.__name__+': "'+filePath+'"') - + # Return Result - return self - + return self + diff --git a/utils/wire.py b/utils/wire.py index b2fbf94..c909da2 100644 --- a/utils/wire.py +++ b/utils/wire.py @@ -31,31 +31,31 @@ def create(geo,wireCrv,baseCrv=None,dropoffDist=1.0,prefix=''): # ========== # - Checks - # ========== - + if baseCrv and not mc.objExists(baseCrv): raise Exception('Base curve "'+baseCrv+'" does not exist!') - + # =================== # - Create Deformer - # =================== - + # Create Wire wire = mc.wire(geo,w=wireCrv,n=prefix+'_wire') wireNode = wire[0] - + # Set Dropoff Distance mc.setAttr(wireNode+'.dropoffDistance[0]',dropoffDist) - + # Connect Custome Base Curve if baseCrv: oldBase = mc.listConnections(wireNode+'.baseWire[0]',s=True,d=False) mc.connectAttr(baseCrv+'.worldSpace[0]',wireNode+'.baseWire[0]',f=True) if oldBase: mc.delete(oldBase) - + # ================= # - Return Result - # ================= - + return wire def createMulti(geo,wireList,dropoffDist=1.0,prefix=''): @@ -73,19 +73,19 @@ def createMulti(geo,wireList,dropoffDist=1.0,prefix=''): # =================== # - Create Deformer - # =================== - + # Create Wire wire = mc.wire(geo,w=wireList,n=prefix+'_wire') wireNode = wire[0] - + # Set Dropoff Distance for i in range(len(wireList)): mc.setAttr(wireNode+'.dropoffDistance['+str(i)+']',dropoffDist) - + # ================= # - Return Result - # ================= - + return wire def getWireCurve(wire): @@ -97,10 +97,10 @@ def getWireCurve(wire): # Check Wire if not isWire(wire): raise Exception('Object "'+wire+'" is not a valid wire deformer!') - + # Get Wrap Driver wireCrv = mc.listConnections(wire+'.deformedWire',s=True,d=False) or [] - + # Return Result return wireCrv @@ -113,9 +113,9 @@ def getWireBase(wire): # Check Wire if not isWire(wire): raise Exception('Object "'+wire+'" is not a valid wire deformer!') - + # Get Wrap Base baseCrv = mc.listConnections(wire+'.baseWire',s=True,d=False) or [] - + # Return Result return baseCrv diff --git a/utils/wrap.py b/utils/wrap.py index ec83272..5c98cad 100644 --- a/utils/wrap.py +++ b/utils/wrap.py @@ -30,23 +30,23 @@ def create(geo,wrapGeo,worldSpace=True,prefix=''): # Build/Store Selection sel = mc.ls(sl=1) mc.select(geo,wrapGeo) - + # Create Wrap Deformer mm.eval('CreateWrap') wrap = mc.ls(mc.listHistory(geo),type='wrap')[0] wrap = mc.rename(wrap,prefix+'_wrap') - + # World/Local Space Deformation if not worldSpace: geomMatrixInput = mc.listConnections(wrap+'.geomMatrix',s=True,d=False,p=True) if geomMatrixInput: mc.disconnectAttr(geomMatrixInput[0],wrap+'.geomMatrix') - + # Clean Base cleanWrapBase(wrap) - + # Restore Selection if sel: mc.select(sel) - + # Return Result return wrap @@ -61,17 +61,17 @@ def addInfluence(geo,wrapInf): # Build/Store Selection sel = mc.ls(sl=1) mc.select(geo,wrapInf) - + # Add Wrap Influence mm.eval('AddWrapInfluence') wrap = mc.ls(mc.listHistory(geo),type='wrap')[0] - + # Clean Base cleanWrapBase(wrap) - + # Restore Selection if sel: mc.select(sel) - + # Return Result return wrap @@ -84,11 +84,11 @@ def getWrapDriver(wrap): # Check Wrap if not isWrap(wrap): raise Exception('Object "'+wrap+'" is not a valid wrap deformer!') - + # Get Wrap Driver driver = mc.listConnections(wrap+'.driverPoints',s=True,d=False) if not driver: driver = [] - + # Return Result return driver @@ -101,11 +101,11 @@ def getWrapBase(wrap): # Check Wrap if not isWrap(wrap): raise Exception('Object "'+wrap+'" is not a valid wrap deformer!') - + # Get Wrap Base base = mc.listConnections(wrap+'.basePoints',s=True,d=False) if not base: base = [] - + # Return Result return base @@ -115,18 +115,18 @@ def getDriverIndex(wrap,driver): # Check Wrap if not isWrap(wrap): raise Exception('Object "'+wrap+'" is not a valid wrap deformer!') - + # Check Driver if not driver in getWrapDriver(wrap): raise Exception('Object "'+driver+'" is not a valid driver for wrap deformer "'+wrap+'"!') - + # Get Driver Connections driverConn = glTools.utils.connection.connectionListToAttr(wrap,'driverPoints') for driverShape in driverConn: driverShapeParent = mc.listRelatives(driverShape,p=True)[0] if driverShapeParent == driver: return driverConn[driverShape][1] - + # Return NULL Result return None @@ -136,18 +136,18 @@ def getBaseIndex(wrap,base): # Check Wrap if not isWrap(wrap): raise Exception('Object "'+wrap+'" is not a valid wrap deformer!') - + # Check Driver if not base in getWrapBase(wrap): raise Exception('Object "'+base+'" is not a valid base for wrap deformer "'+wrap+'"!') - + # Get Base Connections baseConn = glTools.utils.connection.connectionListToAttr(wrap,'basePoints') for baseShape in baseConn: baseShapeParent = mc.listRelatives(baseShape,p=True)[0] if baseShapeParent == base: return baseConn[baseShape][1] - + # Return NULL Result return None @@ -159,14 +159,14 @@ def cleanWrapBase(wrap): ''' # Get Wrap Base Geometry base = getWrapBase(wrap) - + # Remove Unused Shapes baseShapes = mc.listRelatives(base,s=True,pa=True) wrapShapes = mc.listConnections(wrap+'.basePoints',s=True,d=False,sh=True) for shape in baseShapes: if not shape in wrapShapes: mc.delete(shape) - + # Remove Unused Attributes for baseObj in base: glTools.utils.attribute.deleteUserAttrs(baseObj) for shape in wrapShapes: glTools.utils.attribute.deleteUserAttrs(shape)