Sunday, December 9, 2007

MEL

MEL Is Fundamental

Maya Embedded Language (MEL) is the ground from which you interact with Maya. When you open Maya, the program first runs several MEL scripts that actually build all the windows you see—that's right: Maya itself has no interface whatsoever. You can even run Maya from your operating system command prompt by typing Maya –prompt! Behind nearly everything you see in Maya is a MEL script.

What does this mean to the average Maya user? Simple: whatever the original programmers did, you also can do. You can write windows that have sliders, tabs, text fields, and buttons in them; you can create attributes in the Channel Box; you can even add menu items to the main menu bar. The fact that Maya is built on MEL is one of the program's most powerful features.

What Is a Scripting Language?

MEL is a scripting language, not a complete programming language (like Java or C++). A program written in a programming language is compiled and becomes an independent program (like the core program, Maya, which just runs off your computer's operating system). A scripting language, on the other hand, resides on top of another program (in this case, Maya) and is interpreted at every line rather than compiled. Because scripting languages are interpreted by the "mother" program, they are a bit slower than compiled programs—however, they require much less programming overhead than do compiled programs.

If you are a real "propeller head" and like to get into the guts of a program, you can create plug-ins for the program itself using the C or C++ programming languages. Maya has its own API (application programming interface)—appropriately enough named Maya API. MEL does just fine for 95 percent of the things most people want to do, however, and it isn't too difficult to learn.

The Script Editor

One of the best ways to get to know MEL is to use the Script Editor. MEL is a huge language (with more than 600 commands and about 75 functions), but the Script Editor will clue you in on how commands are used and allow you to "cut and paste" whole scripts together without the need to program a thing yourself. You don't even need to use the command line to enter the MEL commands. Operations you perform in the Maya interface are recorded as MEL commands in the Script Editor. With no knowledge of programming, you can actually copy-paste together a fairly complex script.

What Is an Attribute?

As you likely understand from reading earlier chapters, an attribute (MEL uses the term Attr to refer to attributes) is any item that lives on a Maya node. (A Maya node is anything you can see in the Hypergraph, or the tabs at the top of the Attribute Editor.) This sounds a bit obscure, but it's really fairly straightforward: anything in the Channel Box, such as rotateX, transformY, or scaleZ, is an attribute of an object (more specifically, an object's transform node).

When you build, alter, or animate an object, you're changing one or more attributes on one or more nodes in the object—and, of course, all of these changes are just MEL commands, so you can make Maya do the work for you. In this section, we'll take a quick look at how MEL works with attributes; in a later section, we'll get into more detail about how to build complex scripts using attributes.

You might have noticed when you adjusted certain attributes of myCube in the previous section that the Script Editor was filled with statements that started with setAttr. The setAttr statement tells MEL to set a certain attribute to a certain value. Likewise, the getAttr statement gets (reads) the value of an attribute on a certain object, so you can use that value in another MEL statement. The addAttr statement tells MEL to add a custom attribute to a certain item. Essentially, using the setAttr statement is the same as opening the Attribute Editor window and changing a value in one of its fields. (Try changing a value in the Attribute Editor, and you'll notice that the Script Editor history pane shows that a setAttr statement has been executed.)

The syntax (the rules of what goes where) for an Attr statement is as follows:

setAttr [flags] objectName value;

Flags, as you've seen, are any special requests for MEL to complete; the object name is the name of the item's attribute to set (such as myCube.translateX); and the value is the value to set the attribute to. The getAttr and addAttr commands have similar syntax. For example, we can move a cube called "box" to 10 on the X axis by typing the following in the Script Editor:

setAttr box.translateX 10;

Once you execute this command, your box moves from where it is to 10 on the X axis. (Of course, if you have no object called "box," you will get an error message.)

The way MEL (and Maya) references an attribute is similar to the way C++ and other object-oriented programs work. You reference the node, then a period, then the attribute: Object.Attribute. If you don't specify the node on which the attribute is located , you'll get an error message. For example, typing setAttr translateX 10; generates an error message, because Maya doesn't know what to translate.

Setting the translateX attribute is much like giving the move command: move 10 0 0. Unlike giving the move command, however, setting the attribute of translateX does not affect the other two attributes (the Y and Z translate attributes). Also, the setAttr statement is far more flexible than the move command, which can translate only an object.

As a quick example of how setAttr can work, let's make a box and manually set several of its attributes. Type the following in the Script Editor's input pane:

polyCube –n box;
setAttr polyCube1.sw 3;
setAttr polyCube1.w 5;
setAttr box.rotateY 45;
setAttr box.translateX –2.5;
setAttr box.translateY .25;

setAttr box.scaleY 0.5;

Can you figure out what each command does on your own? Try highlighting each line and pressing the numeric Enter key to execute it. Highlighting one line at a time is a useful way to figure out what's happening in a script—and to see where things go wrong!

To change the way your cube is constructed, you reference the shape node (polyCube1), not the transform node, which you have renamed box.

How to Get Help with MEL

Before we delve any further into the world of MEL, let's examine the powerful Maya help tools—and how easy they are to use.

First, you have Maya's internal Help function. Because there are so many MEL commands and functions (about 700), the Help function is a quick and useful feature. (You can even type help help to get a look at how the Help command works.)

Here's an example of the type of information available in Help. Open the Script Editor and type the name of the command you want help with into the input pane (or just type it in the command line below the main window). For example, to get help with the setAttr command, type:

help setAttr;

Execute the command (press Enter on the numeric keypad, or press Ctrl+Enter on the keyboard), and in the Script Editor's history pane, you'll see the following result lines:

// Result:
Synopsis: setAttr [flags] Name[...]
Flags:
-e -edit
-q -query
-av -alteredValue
-k -keyable on|off
-l -lock on|off
-s -size Index
-typ -type String
//

These result lines give you a quick look at the setAttr command: a synopsis of its syntax (or how to use it) and a list of flags that you can use with the command.

If you're an experienced programmer, this information might be all you need to use the command. If you're just starting out, however, you'll probably want more guidance. In that case, try typing the following in the input pane:

help –doc setAttr;

When you execute this command, Maya automatically opens your browser of choice (usually Netscape Communicator or Microsoft Internet Explorer) and finds the correct HTML page in your online documents (contained on your hard drive) that contains the command you want help with. In the case of the setAttr statement, the following is displayed (this is merely an excerpt—the actual page contains much more information):

Name
setAttr
Synopsis
SetAttr
[flags] object.attribute value [value..]
ReturnValue
None.
Description
Sets the value of a dependency node attribute. No value for the
attribute is needed when the -l/-k/-s flags are used. The -type flag
is only required when setting a non-numeric attribute.
The following chart outlines the syntax of setAttr for non-numeric
data types:
{TYPE} below means any number of values of type TYPE, separated by a space
[TYPE] means that the value of type TYPE is optional
A|B means that either of A or B may appear

Examples
sphere -n sphere;
// Set a simple numeric value
setAttr sphere.translateX 5;
// Lock an attribute to prevent further modification
setAttr -lock on sphere.translateX;
// Make an attribute unkeyable
setAttr -keyable off sphere.translateZ;
// Set an entire list of multi-attribute values in one command
setAttr -size 7 "sphereShape.weights[0:6]" 1 1 2 1 1 1 2
// Set an attribute with a compound numeric type
setAttr "sphere.rotate" -type "double3" 0 45 90;
// Set a multi-attribute with a compound numeric type
setAttr "sphereShape.controlPoints[0:2]" -type "double3"

0 0 0 1 1 1 2 2 2;

As you can see, a few examples can do a lot to clarify how a command is used.

You can also access an entire MEL manual online, for a more in-depth look at the structure of the scripting language itself. In Maya, choose Help ® Library to open the main reference page in your web browser. Choose the Using Maya/MEL link to display a menu of introductory material, frequently asked questions, and other resources for learning MEL. Between the internal Help files and the online help on your hard drive, you can access excellent reference material rapidly.

A Comment on Commenting

Comments are a way for you, as a programmer, to document your code. Comments can be useful when you revisit old code, when you're writing code that may be confusing, or when others are reading your code.

Comments are identified by two forward slashes (//). When the script executes, the interpreter ignores anything that follows the two slashes. Here are some examples of legal comments:

//Script written by: John Doe
polyCube –n myCube; //create a cube named myCube

As you can see, a comment can be on a line by itself or at the end of a line of code.

Always include comments at the top of a script about what the script does, which arguments (inputs) it needs (you'll learn about arguments later in the section on procedures), who wrote (and modified) it, and when it was last modified. It's also not a bad idea to put in a "use at your own risk" line to indicate that some unforeseen problem could arise while using the script and that the author is not responsible for any mishaps because of the script's usage (ah, the joys of a litigious society!).

You might think that these comments are of use only to others and not to yourself, and you'd rather not bother with them if you don't plan to distribute the script. But remember that two months after you create the script, you might need to modify it, and if you can't figure out what you did or why, you'll waste a great deal of time hunting through the script instead of getting right to your modifications.

Always comment your scripts well (even the simplest ones). It's a habit (and for once, a good one), so get into it! Commenting well doesn't necessarily mean commenting everything though. In this chapter, the scripts are a little over-commented for instructional purposes, but in most cases, if you have more comments than code, you have overdone it. Good code is self-documenting with comments included where you or someone else might need a little extra information about what is happening. Here is an example of poor, or overdone, commenting technique:

// z equals x plus y
$z = $x + $y;

Hands On: Building a Room Automatically

Let's put all this information to some use now. We're going to record several actions we perform to create a default room setup, copy those actions into a macro, and place that macro on a shelf. Once we've done that, we can automatically set up a room for any scene we want, at the click of a mouse.

  1. Open Maya or begin a new scene.

  2. Open the Script Editor and clear the history pane.

  3. Build a room with three walls, a floor, and a ceiling (polygon cubes or planes). Leave one side of the room open to see inside. Place a cube and a sphere inside the room. Create a point light and place it in the center of the room, and shine a spotlight into the room. Then create a camera to see inside the room.

  4. Once you're happy with the room, simply select everything in the history pane and MM drag the highlighted text up to the shelf of your choosing. If you're not happy with your room, you can use a sample room script, room.mel, on the accompanying CD-ROM. Simply load it into the input pane of the Script Editor by choosing File ® Open Script. Once the script is loaded, highlight it and then MM drag it up to a shelf. A new button appears .

  5. Let's see if it worked. Select everything in your scene and press Delete. (Or you can type select –all; delete; in the Script Editor to do the same thing.)

  6. Once your scene is empty, go up to the shelf and click your newly made button. After a couple of seconds, you should see your room magically appear in the scene, just as you had it set up.


Variables, Loops, and Branching

If you've done any programming at all, you've probably been waiting for this point: the main reasons to program are (1) to create flexibility and (2) to take care of repetitive tasks. Flexibility comes through variables and branching; repetition is made possible through looping.

Variables

It's actually much easier to see what a variable is than to talk about it. Type the following in the Script Editor:

string $myVariable;
$myVariable = "hi there";

print $myVariable;

When you execute these commands, you'll see that "hi there" is displayed in the last line of the history pane, indicating that when you told Maya to print $myVariable, it displayed "hi there." The first line of this script is called a declaration of the variable: string is the variable's type (a string is just text contained in quotes), and $myVariable is its name. The second line of the script assigns the string "hi there" to the variable $myVariable, and the third line tells the print command to output the contents of the variable $myVariable, which as you can see is "hi there".

Looping

Next, let's examine looping. Say you want to create five cubes in your scene using MEL commands. You can either type polyCube –n box five times or have MEL do it for you using the for loop. To build our five cubes, type the following:

int $i; for ($i = 1; $i<= 5; $i++){ polyCube –n box; }

VoilĂ , five cubes named box1 through box5. (However, you'll need to move them away from each other to see them as separate objects. We'll do that in a moment.)

MEL supports implicit variable declaration, so the int $i line is not strictly necessary. However, in most cases, it is preferable to declare all variables explicitly to avoid possible complications in the script.

Notice that there is no semicolon after the for statement: MEL expects one or more commands (contained within the { } brackets) after the for statement, so a semicolon is unnecessary. Additionally, the closing bracket (}) functions as a semicolon, so a semicolon is also unnecessary on the last line. The syntax for the for loop is as follows:

for (initial value; test value; increment)

Branching

The last basic program structure we'll look at is branching. Branching provides a way to ask a question and decide whether to take some further action given the answer. (The for statement actually contains a branch in its test value statement.) Let's use the same script as previously, only this time let's put a conditional statement inside it:

for ($i = 1; $i<= 5; $i++){
polyCube –n box;
if ($i<=3){
move –r 0 (2 * $i) 0;
}
else{
move –r (2 * $i) 0 0;
}
}

What happens when you execute these commands? The first three cubes are stacked up on the Y axis (when $i is less than or equal to 3), and the last two are stacked along the X axis (when $i is 4 and 5, and therefore greater than 3). In abstract, the syntax for the if statement is as follows:

if (test){
commands;
}
else if (test){
commands;
}
else{
commands;
}

The else if and else statements do not have to exist for the if statement to work. The else if statement, listed here, allows you to make as many tests as you like (your conditional statement can have as many else if statements as you wish), allowing you to test for multiple possibilities within one large conditional statement. The else statement must always be last in such examples, and it is the "default" answer if no other conditions are met. All the commands for an if, else if, or else statement must be enclosed in brackets ({ }). If we want, we can increase the complexity of our create-and-move-box code with an else if statement:



No comments: