from maya.api import OpenMayaAnim
from maya.api import OpenMaya
from maya import mel
import inspect
import timeit
import pymel.core as pm
## Get the current UI Unit
uiUnit = OpenMaya.MTime.uiUnit()
#####
## Util functions
#####
def get_dep_node(n):
return OpenMaya.MGlobal.getSelectionListByName(n).getDependNode(0)
################################
## Get attr methods
################################
def cmds_get_attr_cmds_set_time(obj, attr):
'''
The normal method of getting an attribute.
:param obj: object string name i.e. "pSphere1"
:param attr: the attribute to check i.e. "tx"
:return: a list of values per frame.
'''
fullName = "%s.%s" % (obj, attr)
values = []
for frameNr in xrange(20):
cmds.currentTime(frameNr)
value = cmds.getAttr(fullName)
values.append(value)
return values
def cmds_get_attr_no_eval(obj, attr):
'''
ERROR DOESNT EVAL THE ATTR SO NO DATA WILL CHANGE
The normal method of getting an attribute but without updating the time
Doesnt work correctly as the attribute does not update.
:param obj: object string name i.e. "pSphere1"
:param attr: the attribute to check i.e. "tx"
:return: a list of values per frame.
'''
fullName = "%s.%s" % (obj, attr)
values = []
for frameNr in xrange(20):
cmds.currentTime(frameNr, update=False)
value = cmds.getAttr(fullName)
values.append(value)
return values
def cmds_get_attr_arg_time(obj, attr):
'''
The normal method of getting an attribute but without updating the time
but using the time argument of the get attr.
Definitly the fastest method if you dont want to use open maya.
:param obj: object string name i.e. "pSphere1"
:param attr: the attribute to check i.e. "tx"
:return: a list of values per frame.
'''
fullName = "%s.%s" % (obj, attr)
values = []
for frameNr in xrange(20):
value = cmds.getAttr(fullName, time = frameNr)
values.append(value)
return values
def cmds_get_attr_om_set_time(obj, attr):
'''
Normal get attr but
using open maya to change the time.
:param obj: object string name i.e. "pSphere1"
:param attr: the attribute to check i.e. "tx"
:return: a list of values per frame.
'''
fullName = "%s.%s" % (obj, attr)
values = []
for frameNr in xrange(20):
OpenMayaAnim.MAnimControl.setCurrentTime(OpenMaya.MTime(frameNr, uiUnit))
value = cmds.getAttr(fullName)
values.append(value)
return values
def mel_get_attr(obj, attr):
'''
Using mel get attr.
using open maya to change the time.
:param obj: object string name i.e. "pSphere1"
:param attr: the attribute to check i.e. "tx"
:return: a list of values per frame.
'''
## Slight speed optimisation, this way we dont have to construct the string every time.
fullName = "getAttr -time %s "+obj+"."+attr
values = []
for frameNr in xrange(20):
#OpenMayaAnim.MAnimControl.setCurrentTime(OpenMaya.MTime(frameNr, uiUnit))
value = mel.eval(fullName%frameNr)
values.append(value)
return values
def pymel_get_attr_om_set_time(obj, attr):
'''
Using pymel get with openmaya set time.
pymel basically uses the openmaya api so should be faster.
:param obj: object string name i.e. "pSphere1"
:param attr: the attribute to check i.e. "tx"
:return: a list of values per frame.
'''
## Slight speed optimisation, this way we dont have to construct the string every time.
pmAttr = pm.PyNode("%s.%s" % (obj, attr))
values = []
for frameNr in xrange(20):
OpenMayaAnim.MAnimControl.setCurrentTime(OpenMaya.MTime(frameNr, uiUnit))
value = pmAttr.get()
values.append(value)
return values
def pymel_get_attr_arg_time(obj, attr):
'''
Using pymel get with passing time as argument
pymel basically uses the openmaya api so should be faster.
Definitly faster as setting time with maya api
:param obj: object string name i.e. "pSphere1"
:param attr: the attribute to check i.e. "tx"
:return: a list of values per frame.
'''
## Slight speed optimisation, this way we dont have to construct the string every time.
pmAttr = pm.PyNode("%s.%s" % (obj, attr))
values = []
for frameNr in xrange(20):
value = pmAttr.get(time=frameNr)
values.append(value)
return values
def cmds_eval_keyframe_om_set_time(obj, attr):
'''
WARNING DOESNT EVAL CORRECTLY WITH MULTIPLE ANIM LAYERS!!
Use the cmds.keyframe function to evaluate the keyframe.
Its really fast! but .... doesnt eval correctly with anim layers.
:param obj: object string name i.e. "pSphere1"
:param attr: the attribute to check i.e. "tx"
:return: a list of values per frame.
'''
fullName = "%s.%s" % (obj, attr)
values = []
for frameNr in xrange(20):
value = cmds.keyframe(fullName, query=True, eval=True, t=(frameNr,)) or 0
values.append(value)
return values
def om_plug_as_double_mdg_set_time(obj, attr):
'''
Getting the plug from openMaya.
Then create a time mdgContext and evaluate it.
This is the fastest with layer compatability... however i suspect there to be issues when doing complex simulations.
:param obj: object string name i.e. "pSphere1"
:param attr: the attribute to check i.e. "tx"
:return: a list of values per frame.
'''
values = []
obj = get_dep_node(obj)
objMfn = OpenMaya.MFnDependencyNode(obj)
## Get the plug of the node. (networkedplug = False, as it no longer profides a speed improvement)
plug = objMfn.findPlug(attr, False)
for frameNr in xrange(20):
## The creaction of the MDG context takes the longest!
mdg = OpenMaya.MDGContext(OpenMaya.MTime(frameNr, uiUnit))
value = plug.asDouble(mdg)
values.append(value )
return values
## Put all functions in a nice list
fList = [cmds_get_attr_cmds_set_time, cmds_get_attr_no_eval, cmds_get_attr_arg_time,
cmds_get_attr_om_set_time, mel_get_attr, pymel_get_attr_om_set_time,
pymel_get_attr_arg_time, cmds_eval_keyframe_om_set_time, om_plug_as_double_mdg_set_time]
## Prepare some constants
obj = "pSphere1"
attr = "tx"
## Start testing all results
resultList = []
print "Duration for each function 100 times: "
for f in fList:
## Using the timeit module to check how long the functions last
duration = timeit.timeit(f.__name__ + "('%s','%s')" % (obj, attr), setup="from __main__ import %s" % f.__name__, number=10)
## Run it once more to get the actual results
result = f(obj, attr)
## Store the results in a list
resultList.append(result)
## And report the total duration.
print "\t", f.__name__, duration
print "Accuracy comparison: "
for index, results in enumerate( resultList[1:]):
print "Function Name: ",fList[index+1].__name__
for rIndex, result in enumerate( results ):
print "\t", result - resultList[0][rIndex]