MEL - Writing scripts
Commands
You can enter MEL commands in the Script Editor. If you want to execute your command (or commands), you need to press Ctrl + enter (or the enter of your numpad). When you just press enter without crtl, the cursor will go to a new line.
A script really is just a list of commands which are executed one by one (from top to bottom) once you execute the script (Ctrl + enter). In a bit you'll see various ways to influence which commands in your script are executed (which should be skipped or repeated).
Command reference
The list of commands may seem endless at first and the number of options for each command is even longer. It's madness to know each and every one by heart and it's completely useless to try. The Maya help contains a complete Command Reference, which describes every command and the flags for that command. You can open the Command Reference directly through the Help menu: Help > MEL Command Reference.
polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 -sz 1 -ax 0 1 0 -tx 1 -ch 1;
creates a new cube. The last created object will automatically be selected.
move -r 0 4 -2.6;
moves the selected object. -r denotes a relative translation (see Command Reference). The object is in this case translated by: 4 units in the y and -2,6 in z. There is no translation in x. An absolute translation would move the pivot point of the object to the specified coordinates.
Syntax
Computers aren't too intelligent. They need very strict rules in order to understand the commands in your script. Therefore some rules should be applied when writing a script. Those rules are called syntax. You can compare it to the grammar of a language.
- everything is case sensitive. the command polycube won't work, polyCube will
- Each command is terminated by a ; at the end of the line (after the flags, if applicable). Only if you enter just a single command, you may omit the semicolon , but that is not recommended.
- Comments (which shouldn't be executed) are preceded by // and end at the end of the line.
- Large blocks of comments (multiple lines) are placed between /* [comment] */
Especially when your script is getting more complex or very long, it's of vital importance to use comments. It helps you (and others) to keep an overview and it makes it easier to understand your script if you use it at any later date. It helps you to understand the structure and find out how the script works.
Variables
If you enter all commands with all values (numbers, sizes, etc) manually, a script isn't really too useful. It's very likely that the 'normal' interface will prove to be faster or at least more convenient. Scripting gets powerful when you use variables.
You may know variables (x, y, t) from math; variables are labels that refer to a value that may not be known at a given time. They correspond to a value (at a time). A variable has three key properties:
- a variable has a name
- a variable has a value
- a variable has a type
Variable names start with a $ to denote a variable. Variable names may not contain spaces, points or any special character. They can't begin with a number either.
example: $height (variable with the name height)
A variable can be assigned a value:
$height = 6.2;
Once that command has been executed, the variable $height has a value of 6.2. The computer will keep this value for height in memory until you assign a new value (or you shutdown Maya).
This variable can now be used in any command, for example:
polyCube -h $height;
This will create a cube. As soon as the command is executed, Maya will read the value of $height from memory and use that in this command. If this example is executed directly after the previous example, the value will be 6.2.
Take a look at the example below and analyze what happens when each line is executed in order:
$height = 6.2; polyCube -h $height; $height = 4; polyCube -h $height;
All in all not too exciting yet, but we're getting there. This is the first step in writing more complex (and useful) scripts.
Types
There are a few types of variables. The type of a variable determines what kind of values can be stored. The most important types are:
- float - numbers with a decimal precision
- integer (int) - numbers without decimals
- string - text
- vector - vectors (we won't use them for now)
As soon as a variable is created and is set to a specific type, it can only store values of that type. If you try to assign a value of a different type, you may gat an error or warning or you can get strange results. Only assigning a integer number to a float variable will work without errors; if you assign a decimal number to a variable with type int, all decimals will be ignored.
You cannot change the type of a variable. You need to restart Maya to start with a clean slate.
Declaring variables
To prevent any confusion or errors from occurring related to the type of a variable, it is recommended to declare' a variable on first use. This will look something like this:
int $integer_number; float $name_of_my_var;
Declaring a variable should be done once for each variable in each script. To keep track of the variables you've used (declared) so far, it's recommended to place all of the at the top of your script. Use comments to describe the use of variables.
You can declare a variable and assign it a value in one go:
int $number = 4; float $length = 25.3; string $text = "a piece of text";
Using variables in calculations
You can do calculations with your variables where you apply them. The calculation will be done and the result is used in the command. For example:
float $gridsize = 0.3; polyCube -w (4*$gridsize); polyCube -w (6*$gridsize);
Notice the round brackets around the calculation (4 * $gridsize). The are compulsory to ensure that Maya will first determine the result of the calculation 'value of $gridsize times four' and then use the result of that calculation in the command (polyCube).
Arrays
An array is a special class of variables: it can store multiple values. The only restriction is that all values have the same type (int, float, string, etc). Each value is stored with an index reference:
index | value |
---|---|
0 | value1 |
1 | value2 |
2 | value3 |
3 | value4 |
To store or read a specific value to/from an array, the index number is used. The index is specified withing square brackets directly after the variable name:
$myArray[0] $myArray[1] ... $myArray[224]
Arrays are especially useful when you don't know the number of values you need to store in advance or when you have a large sequence of values to store. Creating separate variables for each of the values would be impractical (even impossible) in these cases.
Float array
//declaring a float array. Note the [] after the name of the variable to indicate an array float $coord[]; // assigning a value (index 0, 1 and 2) $coord[0] = 5.4; $coord[1] = 3.8; $coord[2] = 4.2; // reading the values, combined with (for example) the curve command curve -d 1 -p $coord[0] 0 0 -p $coord[1] 0 0 -p $coord[2] 0 0;
The contents of the array $coord now is:
index | value |
---|---|
0 | 5.4 |
1 | 3.8 |
2 | 4.2 |
String array
A list of object names:
string $lines[]; $lines[0] = "curve1"; $lines[1] = "curve3"; $lines[2] = "Mycurve";
A list of values can be assigned to an array directly. These values will be stored in successive index numbers, starting at 0.
string $newlines[] = {"curve1","curve3","Mycurve"};
The contents of the array $newlines is:
index | value |
---|---|
0 | curve1 |
1 | curve3 |
2 | Mycurve |
Printing variable values
Function: print
string $name = "test 1"; print($name); test 1 float $array[] = { 5.4, 3.8, 7.2 }; print($array); 5.4 3.8 7.2
Control structures
Before was mentioned that a script, a list of commands, was executed line by line (sequentially) from start to end. But other than the default of executing a script sequentially, you can influence the 'flow' of the execution of your script. You might want to execute a part of your script only in special cases (determined by some condition you set). It is also possible to repeat the execution of one or more lines several times, without putting the command in your script multiple times (copy paste).
This is achieved by the so called control structures. These structures determine the execution of your script. The next section covers the IF-structure and two repetitive structures: the WHILE-loop and the FOR-loop.
Comparisons (tests)
Most control structures use some form of comparison, called tests. Two values are compared and tested. The test will yield true or false. You can compare the value of a variable to a fixed value, but you can also test (the values of) two variables or some form of calculation. Some examples:
- $a == 4
- equal to; see ! below
- $a < 5
- less than
- $a > $b
- greater than
- 5 >= $b
- greater than or equal to
- $a <= $b
- less than or equal to
- $a != (2*$b)
- not equal to
! Notice: In comparisons, there is a fundamental difference between == and =
= denotes assigning a value to a variable and will always result in true.
== denotes the comparison of two values. It will only result in true when both values are equal.
IF
if ( $a < $b ) { polyCube -h $a; }
In this example the value of variable $a is compared to the value of variable $b. If (and only if) the value of $a is less than the value of $b (the result of the test is true), the command (or commands) between the curly brackets { ... } is executed.
This structure can be expanded to an If-else structure:
if ( $a < $b ) { polyCube -h $a; } else { polyCube -h 5; move -r 0 4 0; }
The if-part is equal to the example before, but here we've added a part: the keyword else and a second block enclosed by curly brackets. This second block is executed when the test is not true, false.
WHILE loop
float $distance = 0; while ( $distance < 50 ) { polyCube; move -r $distance 0 0; $distance = $distance + 7.2; }
In a While-loop, the command(s) between the curly brackets is executed repeatedly for as long as the test results true.
iteration
The While structure will do the test and only if it results true, the commands between curly brackets are executed. This is called an iteration. After a single iteration, the structure will repeat the events. It will test the expression and if it results true (again), it will execute the commands. If the expression results false it will terminate the entire structure. A loop has zero or more iterations, but in most cases one or more.
infinite loops
If none of the parameters of the expression (comparison) change, the loop will be repeated forever as the test will return true each and every time. If an infnite loop is executed, you need to terminate Maya through the task manager. Not saving any of the files that are open.
So you need to incorporate a command in a While-loop that influences the test that determines if a next iteration is to be executed.
FOR loop
for ( $i = 1; $i < 10; $i = $i + 1 ) { polyCube; move -r ($i * 3) 0 0; }
The For-loop is a variation to the While-loop. It is often used when 'something' needs to be repeated 'a (counted) number of times'. This type of loop uses a counter that keeps track of the number of iterations.
In the For-loop there are three components between the round brackets separated by semicolons: initialization, condition and iteration.
- Initialization
- $i = 1
- A variable $i that is used as a counter is set to its starting value
- Condition
- $i < 10
- The test that determines whether the loop is continued to be executed. In the example $i must be less than 10.
- Iteration
- $i = $i + 1
- In each iteration this command is executed after the command between curly brackets have been executed. In the example the value of $i is increased by 1.
You can do the exact same thing using a While-loop. It would look something like this:
int $i = 1; while ( $i < 10 ) { polyCube; move -r ($i * 3) 0 0; $i = $i + 1; }
Both options are correct, only the For-loop will be a more clear in most cases. Especially when the commands between curly brackets is very long.
Loop in loop
you can create a new loop within the curly brackets of a loop. An example of the application of a loop-in-a-loop is when you want to create a grid of objects:
for ( $i=0; $i < 10; $i++ ) { for ( $j=0; $j < 5; $j++ ) { polyCube; move ($i * 3) 0 ($j * 2); } }
Arrays and loops
We've seen that arrays are a special 'type' of variables that can hold multiple values. Thos values are indexed by sequential number. Working with arrays get useful and practical when they're combined with loops.
Storing values in an array using a loop
//declare variables int $i; string $name; string $lines[]; // loop for ( $i=0; $i<10; $i++ ) { // use the name of the curve; store string value in $name. $name = `curve -d 1 -p 0 0 0 -p 10 0 $i`; // store the name in the array $lines. $i is used as the index number. $lines[$i] = $name; }
Result:
print ($lines); curve1 curve2 curve3 curve4 curve5 curve6 curve7 curve8 curve9 curve10
Looping through all values in an array
A special variant of the for-loop, can be used to cycle through all values in any given array:
//declare variables string $lines[] = {"curve1","curve2","curve3"}; string $curvename; string $profile[] = `circle -c 0 0 0 -nr 1 0 0 -r 0.06 -name "Profiel"`; for ( $curvename in $lines ) { extrude -et 2 -po 0 -fpt 1 -ucp 1 -upn 1 -rsp 1 $profile[0] $curvename; }
Until now, we've seen three parts between the round brackets of a for loop (initialisation, condition, iteration). In this variant there's the keyword in. This for-loop can be interpreted as: loop through all elements (values) in the array given after the in keyword. Each value is stored in the variable given before the in keyword. This will result in one or more iterations of the loop, executing the code between the curly brackets.
It's recommended to make sure any variables used in this structure are properly declared.
Drawing curves
Function: curve
curve -degree 1 -p 0 0 0 -p 5 0 0;
The command is curve with several flags (options):
- -degree
- specifies the degree of the curve. 1 for straight lines, 3 for curved lines.
- -p
- Specifies a point of the curve. The flag is followed by three numbers (floats) separated by spaces. Those are the X, Y and Z coordinates of the point.
Obviously a curve consists of several points. A minimum of two points is required for a first degree curve. A Third degree curve needs at least four points. Each of these points is specified by repeating the -p flag.
Extruding surfaces
Function: extrude
extrude -et 2 -po 0 -fpt 1 -upn 1 -rsp 1 "Profile" "Path";
This example uses multiple flags. A complete overview of the available flags can be found in the Command Reference. A brief overview:
- -et, -extrudeType
- 2 for a Tube extrusion
- -po, -polygon
- 0 for NURBS
- -fpt, -fixedPath
- 1 (place at the path curve)
- -upn, -useProfileNormal
- 1 (true)
Using object names
When you create a curve using the curve command, it would be nice to know the name of the object that was created, so you can use that name in subsequent commands. For example when using that curve with the extrude function.
Although it's possible to specify a name for the object with the curve command (using the -name flag), you cannot be sure that it will be the exact, final name. A name must be unique, so when it is not, Maya will automatically add a number suffix:
curve -d 1 -name "myCurve" -p 1 0 0 -p 0 1 0; // Result: myCurve // curve -d 1 -name "myCurve" -p 2 0 0 -p 0 2 0; // Result: myCurve1 //
Result of a command
For almost every command, Maya returns a result (number, text, etc):
curve -degree 1 -p 0 0 0 -p 5 0 0; // Result: curve1 //
This result can be assigned to a variable as a value:
$result = `command ...`; // or $result2 = command();
Application using backticks:
$result = `curve -d 1 -p 0 0 0 -p 0 0 6`; // Result: curve1 //
Application using round brackets:
$result2 = sin(8/3); // Result: 0.909297 //
Using the name of an object
As we've seen, Maya returns the name of an object when it's created. We can store this result in a variable. An object name is a string:
string $name; $name = `curve -d 1 -p 0 0 0 -p 0 0 6`; extrude [options...] "Profile" $name;
The example above shows a curve being created using the curve function. The name of the resulting object is stored in the $name variable (type: string) so we can use it for future application. The name is, for instance, used in the extrude function to specify a curve that should be used (in this example as a path). Instead of passing the name 'hard coded', you can let Maya read the value of the $name variable. Note that the example still uses a 'hard coded' name for the extrusion profile, "profile". Of course this could be specified using a variable as well.
Curve functions
Position on a curve
You can define any point on a curve by using the parameter value. Parameters are the unique numeric values (like coordinates) of points on a curve or surface. Parameters let you refer to specific points along the length of a curve. The higher the parameter, the further is the point along the curve.
Note that there are two main parameter ranges:
- 0 - num spans
- the startpoint of the curve has parameter value 0, the endpoint a number equal to the number of spans (number of editpoints minus 1)
- 0 - 1
- the startpoint of the curve has parameter value 0, the endpoint 1
Example: the length of a curve between parameter 0 and 0.1 isn't necessarily the same as between 0.4 and 0.5!
Using the parameter value, you can obtain the X, Y and Z (world) positions of any point on a curve:
Function: pointOnCurve
pointOnCurve -position -pr 0.75 "curve1";
- -position
- world coordinate
- -pr
- parameter
The result of the function pointOnCurve is a float array:
// This script generates a vertical line (3 units tall) // on 6 points that are on curve1. float $pos[]; float $p = 0; while ( $p <= 1 ) { $pos = `pointOnCurve -position -pr $p "curve1"`; curve -d 1 -p $pos[0] $pos[1] $pos[2] -p $pos[0] 3 $pos[2]; $p = $p + 0.2; }
To generate a few lines between a point at parameter (U-value) $p on the first curve and point at parameter $p on a second curve, using parameter increments of 0.2 between 0 and 1:
float $pos1[]; //declare variable to save coordinates of the first curve float $pos2[]; //declare variable to save coordinates of the second curve float $p = 0; //declare variable for the parameter value while ( $p <= 1 ) { $pos1 = `pointOnCurve -position -pr $p "ondersteBuis"`; $pos2 = `pointOnCurve -position -pr $p "bovensteBuis"`; // draw a curve that start at the position of the requested point curve -d 1 -p $pos1[0] $pos1[1] $pos1[2] -p $pos2[0] $pos2[1] $pos2[2]; // increase $p with 0.2 $p = $p + 0.2; }
Curve length
It can be useful to measure the length of any curve in your script. This way you can determine the number of subdivisions you want to make, for example.
Function: arclen
float $length = arclen("curve1"); // Result: 58.589098 //
Procedures (functions)
We've used several commands so far. A command will perform certain operations, mostly determined by the flags (attributes) specified.
It's possible to create your own commands, called procedures. As this is more in-depth stuff, it's not covered in this page. See: MEL procedures.
Library with some procedures
- Download lib_bsc2.mel (downloads BSc2)
- Script Editor > Source Script > choose lib_bsc2.mel
- The procedures specified in this file are now loaded and ready to be used.
- On the page MEL BSc2 library is a short explanation of each procedure.