The Dependency Graph

This topic summarizes the basic concepts of Maya's Dependency Graph.

What is the 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.

NOTE: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.

Data Propagation and Node Computation

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 MPlugs 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:

  1. The "dirty" output MPlug - A node may have multiple dirty output MPlugs. This parameter informs us of which MPlug we are "cleaning" with our computation.
  2. An instance of MDataBlock - The provided instance of 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 MPlugs.

Defining a Custom Node

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 MPlugs 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 MPlugs 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:

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.