MEL How-To #37

Back · Previous · Next Maya

How do I represent a custom numeric attribute as a drop-down text menu in the Attribute Editor?

If you select any transform node in Maya, the Attribute Editor displays a drop-down option menu for its Rotate Order attribute. This How-To demonstrates how to create a similar menu for your own attributes.

The first task is to determine how Maya generates these menus for numeric attributes. I had a look through the AEtemplate scripts, expecting these would be defined as custom controls there. However, it seems that this behavior is defined internally and not via the MEL template:

global proc AEtransformMain ( string $nodeName )
{
  // ...
  editorTemplate -beginLayout "Transform Attributes" -collapse 0;

  // ...
    editorTemplate -addControl "rotateOrder";
}

Well, we can't modify Maya's internal behavior. But we can achieve the effect by using the AEtemplate system -- modifying/adding code in the template for the node type. I use a locator in this example, and create an attrEnumOptionMenuGrp for a .locatorOption attribute.

Note: There's one small hiccup when defining this type of behavior for a custom attribute that's not included in the node type's definition: The whole works will FAIL if the first locator instance this script sees does not have the specified attribute. And if it does, only a restart will convince Maya to again consider adding the tweaked AEtemplate items.

I've added a hack here to ensure that the locator attribute always exists; however, I admit this is by no means the best way or place to do this. And while there may be a better place to instigate the hack, the only permanent solution is to create a custom node class through the API and define your locator-derived node to include your custom attribute.

Here's what I came up with:

//  Procedure Name:
//  AElocatorTemplate (modified)
//
//  Description:
//  Creates the attribute editor controls for the locator node
//  and creates an attrEnumOptionMenuGrp for a '.locatorOption' attr

// This function adds the given attribute if it doesn't already exist.
proc assertAttribute( string $attrName )
{
  string $nodeName[];
  tokenize($attrName, ".", $nodeName);

  if ( !`attributeQuery -node $nodeName[0] -exists $nodeName[1]` )
    addAttr -at "short" -ln $nodeName[1] -dv 0 -min 0 $nodeName[0];
}

// This function is called when the Attribute Editor page is 
// first created for a locator node
global proc AElocatorOptionNew( string $attrName )
{
  string $nodeName[];
  tokenize($attrName, ".", $nodeName);

  // This hack ensures that the standard locator has the
  // extra attribute; else, this enhancement will not work!
  assertAttribute( $attrName );

  // Push the Attribute Editor UITemplate 
  setUITemplate -pst attributeEditorPresetsTemplate;

  // Add the optionMenu enumeration group.
  // This will be connected to the our specified attribute.
  attrEnumOptionMenuGrp
    -l "Option"
    -columnAlign 1 "right"
    -at $attrName
    -ei 0 "Default"
    -ei 1 "Option #1"
    -ei 2 "Option #2"
    -ei 3 "Option #3"
    -ei 4 "(etc)"
      locatorEnumOptionMenu;

  // Pop to restore the UITemplate 
  setUITemplate -ppt;
}

// This function is called for subsequent selections 
// of a locator node
global proc AElocatorOptionReplace( string $attrName )
{
  string $nodeName[];
  tokenize($attrName, ".", $nodeName);

  // Disable the drop-down menu if the attribute does not exist
  if ( `attributeQuery -node $nodeName[0] -exists "locatorOption"` )
    attrEnumOptionMenuGrp -e
       -enable true
       -attribute $attrName
          locatorEnumOptionMenu;
  else
    attrEnumOptionMenuGrp -e -enable false locatorEnumOptionMenu;

}

// The editor template for the locator
global proc AElocatorTemplate( string $nodeName )
{
  editorTemplate -beginScrollLayout;

    editorTemplate -beginLayout "Locator Attributes" -collapse 0;
      AElocatorCommon $nodeName;

      // Define custom control for locatorOption attribute
      editorTemplate -callCustom
        "AElocatorOptionNew"
        "AElocatorOptionReplace"
        "locatorOption";

      // Suppress the numerical attribute in Extra Attributes
      editorTemplate -suppress "locatorOption";

    editorTemplate -endLayout;

    AElocatorInclude $nodeName;

  editorTemplate -addExtraControls;
  editorTemplate -endScrollLayout;
}

(The bitch about developing AEtemplates is that they are cached and you have to restart Maya if you change anything substantial.)

The next obvious question is: How do I elicit this behavior in the Channel Box.

Unfortunately, I don't know how (or if) this is possible.