The following section describes new API classes and methods to define custom evaluators. Custom evaluators allow control over how the Maya scene is computed.
If you want to create a custom evaluator, you need to define a plug-in that extends the MPxCustomEvaluator class. The following lists the key class methods that you should override.
Before new evaluators can be used, they must be registered:
MStatus registerEvaluator( // name of the evaluator const char * evaluatorName, // evaluator priority. Higher priority evaluators get 'first-dibs' unsigned int uniquePriority, // function pointer to method returning a new evaluator instance MCreatorFunction creatorFunction )
MStatus deregisterEvaluator( // name of the evaluator const char* evaluatorName )
using MFnPlugin methods. These functions should be used during plug-in initialization:
as illustrated above.
Once the plug-in has been loaded, you can use Python or MEL commands to enable:
import maya.cmds as cmds cmds.evaluator(enable=True, name='SimpleEvaluator') # Result: False #
cmds.evaluator(enable=False, name='SimpleEvaluator') # Result: True #
and query information about evaluators:
print cmds.evaluator(query=True) [u'dynamics', ... u'SimpleEvaluator']
To view the priorities of all loaded evaluators, use the priority flag on the evaluator command:
for evaluatorName in cmds.evaluator(): print "%-25s : %d" % ( evaluatorName, cmds.evaluator(name=evaluatorName, query=True, priority=True)) dynamics : 103000 ikSystem : 102000 timeEditorCurveEvaluator : 101000 disabling : 100000 GPUOverride : 5000 transformFlattening : 3000 reference : 1000 SimpleValuator : 40
This section provides more detail on different MPxCustomEvaluator API methods.
During EG partitioning, each evaluator can claim evaluation nodes, using the:.outputValue/.outputArrayValue) or whether the previously evaluated datablock values can be re-used (call .inputValue/.inputArrayValue). If multiple evaluators mark a specific node, priority is used to determine which evaluator is assigned a node at run-time. For example, if you have two evaluators, A and B, mark node C of interest, and if evaluator A has priority 100, and evaluator B has priority 10, then during graph evaluation, evaluator A is assigned the cluster with node C.
To determine if an evaluator can evaluate clusters in Parallel, use:
MCustomEvaluatorClusterNode::SchedulingType schedulingType( // a disjoint set of nodes on a custom evaluator layer const MCustomEvaluatorClusterNode * cluster )
|kParallel||any number of nodes of the same type can run in parallel|
|kSerial||all nodes of this type should be chained and executed sequentially|
|kGloballySerial||only one node of this type can be run at a time|
|kUntrusted||nothing else can execute with this node since it is not possible to predict what will happen|
During EG scheduling:
bool MPxCustomEvaluator::clusterInitialize( const MCustomEvaluatorClusterNode* cluster // evaluation cluster node )
can be used to do any required cluster preparation. The pointer to the cluster remains valid until graph invalidation, such as when the scene topology changes.
Before the cluster is deleted,
void MPxCustomEvaluator::clusterTerminate( const MCustomEvaluatorClusterNode* cluster // the cluster to terminate )
is called to allow needed cleanup, such as releasing evaluator-specific resources. It's up to the custom evaluator to decide if it wants to clear its internal representation.
There are 3 main methods used during execution.
Prior to graph execution, the EM calls:
void MPxCustomEvaluator::preEvaluate( const MEvaluationGraph* graph // the graph about to be evaluated )
during execution, the EM calls:
void MPxCustomEvaluator::clusterEvaluate( const MCustomEvaluatorClusterNode* cluster // the cluster to be evaluated )
You will only receive clusters that belong to this evaluator. This call always happens after clusterInitialize and never after clusterTerminate. Finally,
void MPxCustomEvaluator::postEvaluate( const MEvaluationGraph* graph // the graph that was evaluated )
is called just after a graph evaluation finishes.
This simple script checks which nodes are associated with a given evaluator:
def printClusters(evaluatorName): """ Print out any clusters of nodes captured by the specified evaluator. """ evaluators = cmds.evaluator( query=True ) if evaluatorName in evaluators: try: print cmds.evaluator( query=True, name=evaluatorName, clusters=True )[1:] except KeyError: print 'No clusters in the specified evaluator' else: print 'The specified evaluator is not active. Use the "evaluator" command to activate it'