When Maya calls the compute() method for a dependency graph node, it passes along an MDataBlock object that stores the values of all input and output attributes. This page describes how your implementation of MPxNode::compute() can read and write attribute values in this data block.
It may seem at first that getting at the data being received or sent by a node is a little complex. However, this apparent complexity permits the use of a fast mechanism behind the scenes, which is crucial to the overall operation of the dependency graph.
Note that the data block, and all of the data it contains, are only valid during the execution of your node’s compute() method. Never maintain a pointer to the data block or any of its data for use after the compute() method exits.
A data handle is a reference into the data block that references a particular piece of the node's data, such as an attribute or plug. To read or write an attribute value in the data block, you must create an MDataHandle object, set it up to access the attribute you want it to handle, and use the functions in the MDataHandle interface to get or set the data value expressed as a particular data type.
The following code shows how to create and useMDataHandle objects to read and write the values of attributes within the data block:
MStatus myNode::compute( const MPlug& plug, MDataBlock& data ) { ... MStatus status = MS::kSuccess; // get a handle on an input attribute MDataHandle inputDataHandle = data.inputValue( myInAttributeName, &status ); if (status != MStatus::kSuccess) { /* handle the error */ } // retrieve its value as a float: float& inAttributeValue = inputDataHandle.asFloat(); ... // perform your node's computations, and come up with a result // get a handle on an output attribute MDataHandle outputDataHandle = data.outputValue( myOutAttributeName, &status ); if (status != MStatus::kSuccess) { /* handle the error */ } // assign our computed result to the output attribute outputDataHandle.set( result ); ... }
Or, as a slightly more abbreviated way to retrieve a value without error checking:
// retrieve the value of an input handle as a float: float& inAttributeValue = data.inputValue( myInAttributeName ).asFloat();
The type you use to get or set the data on an attribute or plug must match the type of the attribute. For example, if an attribute is declared as an integer attribute, you should not use the data handle to get or set it as a float, matrix, or even a short. You should only get or set it as an integer. If you need to do any type casting or re-interpreting of the data, do it after you retrieve the value.
Data creators are classes you use to create data to be put into a data block, most likely to an output plug of a node. Data creators are not required for simple data types such as integers and floating point values, but are necessary for heavier data such as mesh shapes and NURBS surfaces.
The classes allow Maya to more efficiently modify and transfer the data along dependency graph connections. The subclasses of MFnData are the data creator classes. For the data creator classes that create heavier data which also corresponds to shape nodes, such as mesh shapes and NURBS surfaces, the MFnDependencyNode subclasses pertaining to the data type are used to fill the data block item with data. For instance, the MFnMeshData class is used to create a new mesh data block item, but the MFnMesh class must be used to fill the item with vertices and polygons.
For example, the following snippets from the shellNode/shellNode.cpp sample illustrate how to fill an output attribute with a mesh:
MStatus shellNode::initialize() { MFnTypedAttribute typedFn; MStatus stat; // the output mesh attribute is initialized as an MFnTypedAttribute, with type MFnData::kMesh. outMesh = typedFn.create( "outMesh", "o", MFnData::kMesh ); typedFn.setStorable(false); typedFn.setWritable(false); stat = addAttribute( outMesh ); ... } ... MStatus shellNode::compute( const MPlug& plug, MDataBlock& data ) { ... // use the data creator to create a new data object of the right type: MFnMeshData dataCreator; MObject newOutputData = dataCreator.create(&returnStatus); ... // compute the vertices and polygons for the new output mesh // create a new mesh using the MFnMesh function set, and store the result // in the data object created above: MFnMesh meshFn; mesh= meshFn.create( n, // number of vertices np, // number of polygons vertices, // The points pcounts, // # of vertex for each poly pconnect, // Vertices index for each poly newOutputData, // Dependency graph data object &returnStatus ); // store the data object in the output attribute: outputHandle.set(newOutputData); ... }
Some operations may behave differently depending on the data block item. That is because these shape-related dependency node function set classes can be used to access data block items that have come from connections to other nodes in the graph as well as to access data block items that have been created locally within the node.