Complex and Dynamic Attributes

In addition to the simple, static attributes described in Attributes and plugs, your custom node classes can use complex attributes made up of multiple data values. These may be arrays that contain multiple instances of the same data type, or they may be compounds that are made up of multiple different data types. In addition, you can use dynamic attributes to add and remove attributes from nodes on the fly.

Array attributes

By default, attributes have only one associated plug. These are called simple attributes. An attribute can also be defined as containing an arbitrarily long list of plugs. Attributes of this type are called array attributes and the plugs in the array are called elements. Each element plug can contain its own value and can have its own connection, and the array can be sparse. The data type of each element is defined to be the type specified by the attribute. Each element in the array is identified by its sparse index into the array.

Maya’s Hypergraph and Connection Editor display the index of an element plug in square brackets ([]) after the attribute name.

The array of plugs is accessed through another plug called the array plug. This plug is returned when asking an attribute for its associated plug. Any attribute can be defined as an array attribute. The specification is made using the MFnAttribute::setArray() method and must be called after calling the create() method for the attribute.

NOTE:
  • It is not recommended to connect an array plug to another array plug.

An important distinction must be made between plugs which are defined as array plugs and simple plugs which are defined to contain array data. Both constructs can contain multiple values and are referred to as "arrays."

In the case of a simple array, the data type is defined as an array, such as pointArray or intArray (refer to the reference page for the MFnData class for a description of the allowable array types). The array is treated as a single data item by the plug. When asking for the plug’s value, the whole array is returned. If the plug is connected to another plug in the scene, the whole array is passed or retrieved along the connection.

For an array attribute, the data type of the attribute is the data type of a single value, such as an int or a double. The array comes from the list of element plugs, each containing a single data value. Each element is independently connectable. The data items are retrieved by accessing each plug in the array and retrieving the single values stored at the plugs. So there is an advantage and disadvantage to each method. In the single attribute case the data are treated as a single unit and can be moved more efficiently through the dependency graph network, but there is less flexibility in accessing the individual data items. In the array attribute case there is great flexibility as each data item can be accessed and connected, but there is more overhead for the node and the dependency graph network.

Following these rules, one can define an attribute whose data type itself is an array. Such an attribute would contain an array plug whose element plugs each contained a whole array. Each array could be independently accessed. As noted above, connections between array plugs are not recommended.

Compound attributes

An attribute can also be defined as a collection of other attributes. Such an attribute is called a compound attribute and the members of its collection are called children. Compound attributes are not defined as containing a particular data type—they are defined as the set of attributes which make up the collection.

Compound attributes are created using the MFnCompoundAttribute class. This class contains methods for specifying the child attributes which will be contained in the compound attribute. Refer to the reference page of MFnCompoundAttribute for more information.

Child attributes

Each child attribute is treated as any other attribute. Child attributes have names and data types and can be defined as array attributes or compound attributes. A plug is associated with the compound attribute itself and is referred to as the parent plug to the members of the compound attribute. Each child attribute also follows the same rules of connectability. A child is independently connectable, and if a child attribute is defined as an array attribute, its element plugs are also independently connectable. The parent plug of a compound attribute can be connected to another node’s compound parent plug as long as the child attributes of each plug are defined identically. In this case, the data for all of the child plugs is sent along the connection. If a compound attribute is specified as an array attribute, then each element plug of the array will contain children plugs for each of the members of the compound attribute. The element plug will be the parent plug.

NOTE:
  • If a compound attribute is specified as an array then the parent will be an array plug. It is not recommended to connect an array plug to another array plug.

Dynamic Attributes

Dynamic attributes are used to attach blind data to a node. Every node initially has a set of attributes defined. You may, however, want to add new attributes to either a single node or to all nodes of a given type. These attributes are called dynamic attributes.

A dynamic attribute is treated much like any other attribute. The main difference is that someone is responsible for allocating and deallocating it since it will not be statically created.

The following is a code fragment taken from the blindShortDataCmd example. It creates a simple dynamic attribute to contain a short which it then attaches to a selected dependency graph node. The blindComplexDataCmd example demonstrates adding user-defined data as a dynamic attribute.

MFnNumericAttribute fnAttr;
const MString fullName( "blindData" );
const MString briefName( "bd" );
double attrDefault = 99;
MObject newAttr = fnAttr.create( fullName, briefName, MFnNumericData::kShort,
 attrDefault, &stat );

This creates a new numeric attribute called "blindData" with a short name of "bd" which has a default value of 99. When using dynamic attributes as blind data the name of the attribute must be unique so that you and someone else do not create attributes which conflict with each other.

stat = fnDN.addAttribute(newAttr,MFnDependencyNode::kLocalDynamicAttr);
if ( MS::kSuccess != stat ) {
    cerr << "Error adding dynamic attribute" << endl;
}

These few lines add the attribute to the selected dependency graph node (fnDN is an instance of MFnDependencyNode that was initialized elsewhere). Note the use of MFnDependencyNode::kLocalDynamicAttr which indicates that this new attribute is a dynamic attribute.