This topic summarizes the basic concepts of Maya's Dependency Graph.
The Dependency Graph is a network of nodes, represented by instances of MObject
. The connection points of a node are known as plugs, and are represented by instances of MPlug
. A directed edge connects one node's output plug to another node's input plug. As we explain in greater detail below, data blocks (MDataBlock
) sequentially visit the connected nodes in the graph, providing input to each node's compute()
function, and storing the resulting output.
To illustrate the behavior of nodes in the Dependency Graph, consider a simple mesh deformation node. Such a node would take set of vertices as inputs, and transform them via its compute()
function into a new set of output vertices. This new set of vertices can be subsequently modified by another node in the dependency graph, and so on.
The Directed Acyclic Graph (DAG), also known as the scene graph, is a subset of the Dependency Graph. Transform and Shape nodes in the DAG can be connected to other nodes in the Dependency Graph to affect or animate their behavior.
The purpose of MPlug
is to flag values which need to be recomputed during Maya's ongoing Dependency Graph evaluation process. If an MPlug
is marked as dirty, its associated value needs to be recomputed. This dirty flag propagates to the relevant MPlug
s in the graph. When a node containing a dirty MPlug
has its compute()
function invoked, the dirty MPlug
is marked as clean to avoid unnecessary recomputations.
In the diagram below, the compute()
function of the mynode1
instance is being called to recompute the value associated with the "mynode1.outputAttribute
" output MPlug
. The compute()
function takes the following two parameters:
MPlug
s. This parameter informs us of which MPlug
we are "cleaning" with our computation.MDataBlock
contains the input values needed to compute the output. The resulting output must be stored in the corresponding output MDataHandle
, contained within the MDataBlock
. Later in this topic, we explain how Maya knows which inputs to provide to compute a specific output.As a brief example of data propagation and computation, suppose the user changes a polygon's number of subdivisions via Maya's user interface. This will first cause the immediately connected input MPlugs
of the related shape node to be marked as "dirty". After this dirty flag has propagated throughout the dependency graph, Maya will sequentially call compute()
on the concerned nodes to "clean" the dirtied MPlug
s.
A custom node is defined by creating a Maya Dependency Graph plug-in. Such a plug-in contains a class which inherits from MPxNode
or one of its subclasses. This new class will override the MPxNode.compute()
function to define the custom node's behavior. Once a Dependency Graph plug-in is loaded into Maya, the Script Editor can be used to create an instance of the node.
In the previous diagram, the initializePlugin()
function makes a call to mplugin.registerNode()
, passing the parameter "mynode
" to declare the custom node type's name. An instance of this node can therefore be created using the following Python script:
import maya.cmds as cmds
cmds.createNode( "mynode" )
The result is an instance of a node whose input and output MPlug
s are initialized according to the attributes declared in the plug-in (nodeInitializer()
). More concretely, the attributes declared in the plug-in will dictate how the MPlug
s will be created in terms of their type, default value, visibility in the UI, readability (usable as input), writeability (usable as output), and whether or not the run-time value should be stored to a file when the scene is saved.
Observe that in the nodeInitializer()
function of our plug-in definition, we declare an affects relationship between:
inputAttribute1
and outputAttribute
,inputAttribute2
and outputAttribute
.The affects relationship, declared using MPxNode.attributeAffects()
, tells Maya which inputs are required to compute a given output. As such, for any given instance of our node, if the MPlug
associated to its inputAttribute1
is marked dirty, the dirty flag will also propagate to the MPlug
associated to its outputAttribute
. This dirty flag propagation will therefore cause the node's compute()
function to be called to clean the dirty outputAttribute
MPlug
.