Hi!
What you want to do is possible in python using the csv library.
This code can certainly be optimized, but it does what you want:
import maya.cmds as mc
import csv
def exportToCSV(start = None, end= None,path = None, multiFile = False):
if path == None:
path = mc.file(q= True, sn = True)
path = path[:-3]
if start== None:
start = mc.playbackOptions(q= True, min= True)
if end== None:
end = mc.playbackOptions(q= True, max= True)
sel = mc.ls(sl= True, l= True)
dict = getAttributes(objs = sel)
if dict != {} and multiFile == False:
getValuesForExportSF(dict= dict, start = start, end= end, path = path)
elif dict != {} and multiFile == True:
getValuesForExportMF(dict= dict, start = start, end= end, path= path)
else:
mc.error("No animated attributes found")
def getValuesForExportSF(dict= None, start = None,end= None, path = None):
fieldNames= []
rows= []
for k in dict:
for v in dict[k]:
fieldNames.append("{0}.{1}".format(k,v))
for f in range(int(start),int(end)):
temp = []
for n in fieldNames:
temp.append(mc.getAttr(n, t= f))
rows.append(temp)
writeCSV(path = path,fieldNames = fieldNames,rows = rows)
def getValuesForExportMF(dict= None, start = None,end= None, path = None):
for k in dict:
fieldNames= []
rows= []
for v in dict[k]:
fieldNames.append(v)
for f in range(int(start),int(end)):
temp = []
for n in fieldNames:
temp.append(mc.getAttr("{0}.{1}".format(k,n), t= f))
rows.append(temp)
kS = k.split("|")
kS = kS[1:]
k= kS.pop(0)
k= "_"+k
for e in kS:
k= k +"_"+ e
pathN= path + k
writeCSV(path = pathN,fieldNames = fieldNames,rows = rows)
def getAttributes(objs = None):
attrDict = {}
relatvies = []
for o in objs:
rel = mc.listRelatives(o, ad = True, f= True) or []
rel.append(o)
relatvies = relatvies + rel
for r in relatvies:
tempList = []
attrList = mc.listAttr(r, s=True) or []
for attr in attrList:
try:
kf = mc.keyframe("{0}.{1}".format(r, attr), n= True, q= True)
if kf != None:
tempList.append(attr)
except:
pass
if tempList != []:
attrDict[r] = tempList
return attrDict
def writeCSV(path = None,fieldNames = None,rows = None):
path= path + ".csv"
with open(path,'w') as f:
writer = csv.writer(f)
writer.writerow(fieldNames)
writer.writerows(rows)
exportToCSV(start = None, end= None,path = None, multiFile = False)
Just select the top level node of your skeleton and run this script from a python tab, it will store the csv file in the same folder as your scene file.
Now a problem here, is that you have way too much data in one file. you have the nodes that have animation, for each node you have multiple attributes and all of them have a row of values for each frame in your set timerange from start to end. for a full skeleton, this is barely humanly readable. So I built in the possibility to have a file for each node.
import maya.cmds as mc
import csv
def exportToCSV(start = None, end= None,path = None, multiFile = False):
if path == None:
path = mc.file(q= True, sn = True)
path = path[:-3]
if start== None:
start = mc.playbackOptions(q= True, min= True)
if end== None:
end = mc.playbackOptions(q= True, max= True)
sel = mc.ls(sl= True, l= True)
dict = getAttributes(objs = sel)
if dict != {} and multiFile == False:
getValuesForExportSF(dict= dict, start = start, end= end, path = path)
elif dict != {} and multiFile == True:
getValuesForExportMF(dict= dict, start = start, end= end, path= path)
else:
mc.error("No animated attributes found")
def getValuesForExportSF(dict= None, start = None,end= None, path = None):
fieldNames= []
rows= []
for k in dict:
for v in dict[k]:
fieldNames.append("{0}.{1}".format(k,v))
for f in range(int(start),int(end)):
temp = []
for n in fieldNames:
temp.append(mc.getAttr(n, t= f))
rows.append(temp)
writeCSV(path = path,fieldNames = fieldNames,rows = rows)
def getValuesForExportMF(dict= None, start = None,end= None, path = None):
for k in dict:
fieldNames= []
rows= []
for v in dict[k]:
fieldNames.append(v)
for f in range(int(start),int(end)):
temp = []
for n in fieldNames:
temp.append(mc.getAttr("{0}.{1}".format(k,n), t= f))
rows.append(temp)
kS = k.split("|")
kS = kS[1:]
k= kS.pop(0)
k= "_"+k
for e in kS:
k= k +"_"+ e
pathN= path + k
writeCSV(path = pathN,fieldNames = fieldNames,rows = rows)
def getAttributes(objs = None):
attrDict = {}
relatvies = []
for o in objs:
rel = mc.listRelatives(o, ad = True, f= True) or []
rel.append(o)
relatvies = relatvies + rel
for r in relatvies:
tempList = []
attrList = mc.listAttr(r, s=True) or []
for attr in attrList:
try:
kf = mc.keyframe("{0}.{1}".format(r, attr), n= True, q= True)
if kf != None:
tempList.append(attr)
except:
pass
if tempList != []:
attrDict[r] = tempList
return attrDict
def writeCSV(path = None,fieldNames = None,rows = None):
path= path + ".csv"
with open(path,'w') as f:
writer = csv.writer(f)
writer.writerow(fieldNames)
writer.writerows(rows)
exportToCSV(start = None, end= None,path = None, multiFile = True)
You'll get a file per node which you can then set up as separate sheets in your excel file which is much more organsied.
I should mention that this code has one restriction, it ignores multi attributes with the formatting node.attr[0].subAttr.
This is because of compadibility issues between the results of listAttr() and the accepted spacial arguments for keyframes().
This could certainly be fixed with more time, but since these kinds of attributes are hardly ever keyed, I decided to ignore the for now.
I hope it helps!