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']
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)