MEL How-To #75

Back · Previous · Next Maya

How can I list all active values/connections in a compound array attribute, such as the ‘.colorEntryList’ for a ramp texture, or the ‘.inputs’ for a layeredShader node?

Compound array attributes are a little tricky to manage. There can be any number of valid values/connections to the array (and possibly zero), but it's not immediately obvious how to determine the correlation between the number of values and their indices. The values/connections are not necessarily assigned/connected in a linear order.

The first thing you will try is something list this:

getAttr -size ramp1.colorEntryList;
// Result: 3 //

Unfortunately, this doesn't tell you everything you need to know. This count is indeed the number of valid elements in the array; however, it does not mean that the array starts at ‘.colorEntryList[0]’ and ends at ‘.colorEntryList[2]’. The first index might be ‘.colorEntryList[3]’, and the last index could be anything.

To illustrate this phenomenon, create a ramp (which has three entries by default) and add a couple "color entry keys" to it. Then delete the second-to-last key you added, leaving four entries.

Now try:

getAttr -size ramp1.colorEntryList;
// Result: 4 //

This is as expected. However, you'll notice that the Connection Editor lists the array as:

Color Entry List[0]
Color Entry List[1]
Color Entry List[2]
Color Entry List[4]   // Skips colorEntryList[3]

To add further annoyance, if you attempt to query ‘.colorEntryList[3]’ at this point:

getAttr ramp1.colorEntryList[3].color;

This will generate a new entry in the table -- one which will likely change the intended properties of the ramp.

The easiest way I've found to obtain all of the active elements to an array attribute is via:

listAttr -multi "node.arrayAttr";

This has the unfortunate side-effect of listing all of the children of the array. In the case of a layeredShader:

string $multiAttr[] = `listAttr -multi ( $layeredShader + ".inputs" )`;

// Result: inputs[3] inputs[3].color inputs[3].colorR inputs[3].colorG
           inputs[3].colorB inputs[3].transparency
           inputs[3].transparencyR inputs[3].transparencyG
           inputs[3].transparencyB inputs[3].glowColor
           inputs[3].glowColorR inputs[3].glowColorG
           inputs[3].glowColorB inputs[4] inputs[4].color
           inputs[4].colorR inputs[4].colorG inputs[4].colorB
           inputs[4].transparency inputs[4].transparencyR
           inputs[4].transparencyG inputs[4].transparencyB
           inputs[4].glowColor inputs[4].glowColorR inputs[4].glowColorG
           inputs[4].glowColorB //

Oi.

To weed out the chaff, I use the "gmatch" command to test for the specific attribute: ‘.color’ in this case.

With attribute in hand, use the "listConnections" command to trace the input attibute back to its source.

"ramp" Example

The following MEL demonstrates how to retrieve the active colors for a ramp node's ‘.colorEntryList’:

// Get all ramp textures nodes in this Scene.
string $ramps[] = `ls -type "ramp"`;

for ( $ramp in $ramps )
{
  print ( "Ramp: " + $ramp + "\n" );

  // Get a list of all active '.colorEntryList' array elements.
  string $multiAttr[] = `listAttr -multi ( $ramp + ".colorEntryList" )`;

  for ( $attr in $multiAttr )
  {
    // Only concered with those ending with ".color".
    if ( `gmatch $attr "*.color"` )
    {
      // Found an active Color connection.
      float $color[3] = `getAttr ( $ramp + "." + $attr )`;

      // Extract the index for the connection.
      string $tokens[];
      tokenize $attr "[]" $tokens;

      print ( "  Color Entry " + $tokens[1] + ": { " + $color[0] + ", " + $color[1] + ", " + $color[2] + " }\n" );
    }
  }
}

Example output:

Ramp: ramp1
  Color Entry 0: { 1, 0, 0 }
  Color Entry 2: { 0, 0, 1 }
  Color Entry 3: { 0.9056821465, 0.6435719728, 0.9089999795 }

"layeredShader" Example

The following traces the connections to each Material from a layeredShader:

// Get all layeredShader nodes in this Scene.
string $layeredShaders[] = `ls -type "layeredShader"`;

for ( $ls in $layeredShaders )
{
  print ( "Layered Shader: " + $ls + "\n" );

  // Get a list of all active '.inputs' array elements.
  string $multiAttr[] = `listAttr -multi ( $ls + ".inputs" )`;

  for ( $attr in $multiAttr )
  {
    // Only concered with those ending with ".color".
    if ( `gmatch $attr "*.color"` )
    {
      // Found an active Color connection.
      // The following retrieves the Material that feeds the
      // Color for this layer.
      string $connect[] = `listConnections ( $ls + "." + $attr )`;

      // Extract the index for the connection.
      string $tokens[];
      tokenize $attr "[]" $tokens;

      print ( "  Input " + $tokens[1] + " is connected to " + $connect[0] + ".\n" );
    }
  }
}

Example output:

Layered Shader: layeredShader1
  Input 1 is connected to Rufwood.
  Input 2 is connected to meatwrap.

Wednesday, October 10, 2001