MEL - Writing simple tools

From TOI-Pedia

Working with object lists

Most tools should operate on specific objects. Many MEL commands are applied to the selected elements if no object is specified. But it's likely that you want a little more control over what is applied to what. Or that an object wouldn't be selected at all when the tools is used. Therefore you need to know some basics on object listings in Maya.

The command that will be used is: ls This command lists objects.

  • When you specify the -selection flag, it lists objects that are selected
  • When you use the -type flag, it lists all objects of a specific type


The ls command will always return a string array.


It's recommended to use the -long flag with the ls command to ensure you get the complete (unique) object names.

Listing selections

If you want to list all selected objects, you can use the -selection flag.

string $selection[] = `ls -selection -long`;
print $selection[0]; //the first selected object
 
/* loop through all objects */
string $object;
for ( $object in $selection ) {
  delete $object; // a quite destructive example, deleting the object
}

Listing objects of a specific type

If you want to list all lights in your scene, for example, you can use the -type flag.

string $lights[] = `ls -type "light" -long`;
print $lights[0]; //the first light
 
/* loop through all objects */
string $light;
float $intensity;
for ( $light in $lights ) {
  // get the current intensity
  $intensity = `getAttr ($light + ".intensity")`;
  // increase the intensity by 0.1
  setAttr ($light + ".intensity") ($intensity + 0.1);
}

Another example to list all file nodes (file textures) in your scene:

/* List all file textures */
 string $filenodes[] = `ls -type "file"`;
 string $filenode,$filename;
 for ( $filenode in $filenodes ) {
  $filename = `getAttr ($filenode + ".fileTextureName")`;
  print ($filename + "\n"); // print the filename (+ newline)
  AEfileTextureReloadCmd ($filenode + ".fileTextureName"); // reload the file texture
}


If you want to select specific object types, use the -exactType flag

string $pointLights[] = `ls -exactType "pointLight" -long`;

You can use the objectType command to find out what the object type is. Note that you need to specify the name of the shape, instead of the transform node of the object (which determines position, rotation and scale).

Transforms and shapes

You may run into the 'problem' that most Maya objects consist of two nodes: a transform and a shape node. When you select, move, rotate or scale an object, you're working with the transform node. If you want to adjust specific properties, for instance the intensity of a light, you need to change attributes of the shape node of that object.

The shape node is a descendant (child) from the transform node:

Maya transform and shape.jpg

You can also see the names of both nodes in the Attribute Editor:

Maya AE transform and shape.jpg

If you want to get the shape node of a transform node, e.g. when a user selects the light (transform node!) and you want to change the intensity, you could achieve that using the following code:

string $selection[] = `ls -selected -long`;
 
// get child shape(s) of the first selected object:
string $shapes[] = `listRelatives -children -shapes $selection[0]`;
 
// $shape[0] is the value of the first child shape.
// In most cases there would be only one child shape.

As this is a commonly needed set of commands, you could write a custom command (procedure) to do this more easily.

/* procedure definition of our getObjectShape command */
 
global proc string getObjectShapeNode ( string $object ) {
  string $shapes[] = `listRelatives -children -shapes $object`;
  return $shapes[0];
}


The implementation of this function would look something like this:

string $selection[] = `ls -selected -long`;
string $shape = getObjectShapeNode ( $selection[0] );
setAttr ($shape + ".intensity") 1.2; //sets the intensity of the selected light to 1.2

Make sure you incorporate the procedure definition in any script you want to use the function in.

Working with attributes

Things get interesting when you can (dynamically) change attributes of objects. There are two commands that allow you to do this:

  • getAttr reads a attribute and returns it's current value
  • setAttr writes a specified value to the specified attribute

Attributes are written as: objectname.attributename. E.g.:

pCube1.tx (translation X of a cube) pointLightShape1.intensity (intensity of a pointlight)


If you need to find out the name of an attribute, you can just change the value and take a look in the command history of the script editor. you'll probably find the corresponding setAttr command there.

In many scripts you have the name of the object (transform or shape node) stored in a variable and the name of the attribute you want to change. For both the getAttr and setAttr commands you need to combine these into the objectname.attributename notation. This is done by 'adding' two string together (this will concatenate them):

$object = "pointLightShape1";
$lightIntensity = ($object + ".intensity");
print $lightIntensity;

Connections (construction history)

So far we've seen parent/child relations between nodes. There is one other very important relation: connections between nodes. This may sound very new to you, but in fact you've probably already worked with it quite regularly. The construction history Maya has, is a direct result of connections between nodes (the building blocks). If you're interested, you can take a look at the connections using the Hypergraph (Window > Hypergraph; use Help > Help on Hypergraph for further information).

To explain this using a hands-on example, we're going to take a look at the polyExtrudeFace building block. This operates on the shape node of an object. So we need to find the connections of the shape node of the object. First we create a simple polygon cube (pCube1) and extrude on of it's faces. Then you can execute this command:

// find the connections into the pCubeShape1 node
listConnections -source 1 -destination 0 pCubeShape1;

This will list all connections going into (source 1, destination 0) our polygon shape. This can be one connection, but it may well be a large number of connections. So the result will always be a string array.

But how can we find out whether we're dealing with a connection for extrudeFace? We will look at the node that is connected and query its type. As we can expect multiple connections, we're using a loop:

// find all connections into the pCubeShape1 node
string $conn;
string $connections[] = `listConnections -source 1 -destination 0 pCubeShape1`;
//loop through the array
for ( $conn in $connections ) {
  // we use objectType() to find out the type of node we're dealing with  
  if ( objectType($conn) == "polyExtrudeFace" ) {
    print $conn; //just print the connection in this case
  }
}

Now we know the name of the extrudeFace building block(s), we can use that to modify the extrusion using the setAttr command.



Overview of Maya topics

Maya main index

Personal tools
Actions
Navigation
Tools