Keep up-to-date with Free tutorials!!


Sign up to our twice-monthly newsletter today for the latest tutorials, interviews and product information.

Sign me up to receive third-party emails from 3dtotal's partners, too!

- Latest news
- Exclusive Shop Offers
- Preview early content
- Plus much more


Not Ready to take that step? OK, Why not just Subscribe to the RSS Feed

submit tutorial
1 | 2 | 3 | 4 | 5 | 6
mel ShapeEditor

| Your Rating:
rating star nonerating star nonerating star nonerating star nonerating star none
(Score 0 out of 5 after 0 Votes)
| Comments 0
Date Added: 9th December 2009
Software used:


There is a way in Maya to collect several commands in something called a procedure. There are local procs and global procs. If you want to use the proc outside the script you have to make it global. When we create a button and we want that button to call the procedure we have to make it global because the window is outside the script. (in Maya, but outside the code...) Let's define a proc.

global proc ma_createPrinitives(){

The syntax: "global proc" tells Maya that we want to define the procedure. "ma_createPrimitives" is the name of the proc that we have to use when we want to call it later. The brackets can include arguments (which we will go through next.) Now you can see that we have three commands between the curly braces and that's basically it for this proc. If you highlight the code above, copy it into Maya and run it you see that nothing happens. This is because we just store the info in Maya. If we want the chunk of code to be executed we have to call the proc by writing ma_createPrimitives. Nothing more, nothing less. If you use it in a longer code you have to terminate the line with ";" of course.

Now I'll go through an example with an argument:

global proc ma_print (string $name){
print ("Hi, my name is " + $name);

Here you can see that the argument is a string. You can have several arguments, you just have to separate them with a comma. We'll use two arguments in the next example. When we use an argument like this we tell Maya that we don't have a defined name right now so we depend on user interference. The user/ or scripter have to tell Maya which name to print. When we call the proc it looks like this:

ma_print Martin;

this will print "Hi, my name is Martin". If we write ma_print Robert it will print "Hi, my name is Robert". Now we'll include an int called $age.

global proc ma_print (string $name, int $age){
print ("Hi, my name is " + $name + ". I'm " + $age + " years young");

So if I write ma_print Martin 24 it will print "Hi, my name is Martin. I'm 24 years young". Just as a final example I'll create a proc that I'm actually going to use with a button. I'll start by creating the window:

window -t "test" ma_labelWin;
textField -tx "insert label here" -w 150 ma_labelText;
button -l "click me to change label" ma_labelButton;
showWindow ma_labelWin;

This will make a window that looks like this:

We can change the text here, but when we click the button nothing happens. We want the button to change the label on itself to whatever is in the textField. The proc would look like this:

global proc ma_changeLabel(){
string $ma_getLabel = `textField -q -tx ma_labelText`;
button -e -l $ma_getLabel ma_labelButton;

You can see that I get the input from the textField and cast it into the string $ma_getLabel by querying -tx. Then I put the button in edit mode to edit the label for the ma_labelButton. The label will get the new value $ma_getLabel. The final thing we have to do now is to "attach" the proc to the button. If you check the helpfiles you can see that the button has a "command-flag". What we do now is put the proc as a value to that flag. Also I included an if statement that checks if the window exists. You know the error you get whenyou try to open a window that already exists, this will prevent this.

if (`window -ex ma_labelWin` == 1){
deleteUI ma_labelWin;

window -t "test" ma_labelWin;
textField -tx "insert label here" -w 150 ma_labelText;
button -l "click me to change label" -c ma_changeLabel ma_labelButton;
showWindow ma_labelWin;

global proc ma_changeLabel(){
string $ma_getLabel = `textField -q -tx ma_labelText`;
button -e -l $ma_getLabel ma_labelButton;

Go through the code and see if you understand it. If not, break it down. Look at the sections:

  • You check if the window exits (`window -ex ma_labelWin`). This will return 0 or 1 depending if the window is open or not. You don't need to write == really. Think of it like this: "If icecream..." If icecream exists it has to return 1.
  • window [flags] [name]
  • a layout for the window
  • textField [flags] [name]
  • button [flags] (the most important flag "-c /-command") [name]
  • the showWindow command to show the window.
  • Defining proc.
  • query the text written.
  • use the queried text to edit the label for the button.

final 3_mulitpleAttrEditor

I think it's time to go through the script now. You probably have enough knowlege to attack scripts now. Remember that even if something here is not too clear right now you'll learn from experience. Remember how I told you I couldn't get my head around loops? I wasn't kidding when I said it took weeks. Even when someone explained them to me I just couldn't. Stupid, stupid, stupid... Then I started using them and I felt more comfortable with them right away. You will learn faster by doing. Everyone knows this! Do it!

Ok, what I want the script to do is this:

  • List the objects I want to edit. I want to be able to select just some of the objects from the list too. I also want to be able to change the selection without reopening the window.
  • I want a layout with check boxes for the renderStats.
  • I want a button that cycles through all the choices I made with the check boxes and applies the new render settings.

When I picture this script in my head it looks like this: ( quick paint over...)

I'm also writing down which commands I think I'll end up using. Programmers have their own way of scripting. Someone likes to do all the code first and make that work before they even think about the UI, others script the UI first and then worry about the core. I am a 3d artist and not a programmer so I tend to care more about how thing looks, maybe a bit too much really :) But anyways, with this script I'll go from top to bottom:

window: You should ask yourself: "Does the script really need a UI?" If you don't rely on user interaction there is no need for a UI. It could be a shelfButton instead. In this case we actually need an interface. I'll also make sure Maya deletes my window if it exists, just like we did earlier.

if(`window -ex ma_multiAttrEdWin`)deleteUI ma_multiAttrEdWin;

window -t "final3 Multiple renderStatsEditor" -wh 280 294 ma_multiAttrEdWin;
showWindow ma_multiAttrEdWin;

You might noticed that the deleteUI-command is on the same line as the if statement and I also left the curly braces out. When you only have ONE line to go between the curly braces you can skip them. For beginners I recommend you stick with the curly braces so you won't forget them later. Stick with this code for a while:

if(`window -ex ma_multiAttrEdWin`){
deleteUI ma_multiAttrEdWin;

I gave the window a title, defined the width and height using the -wh flag and I also gave the window an ID. But in Maya you will always need some sort of layout to hold anything at all. If you try to put a button in there between the window and showWindow command you'll get this error:
// Error: line 4: Controls must have a layout. No layout found in window : ma_multiAttrEdWin //

If you hit f1 you can read more about Maya's UI controls. Under Developer resources -> Mel commands you'll see them listed on the far right:

I'd say the most common layout is columnLayout. If we look at the sketch I drew we see that I need more than one column, I need two ( one for the textScrollList and one for the checkBoxes. I still have to use a columnLayout to hold it all together though so I create a columnLayout first and then the rowColumnLayout. In a rowColumnLayout you can define how many columns you want per row:

window -t "final3 Multiple renderStatsEditor" -wh 280 294 ma_multiAttrEdWin;
rowColumnLayout -nc 2 -cw 1 152 -cw 2 120;
showWindow ma_multiAttrEdWin;

What the flag -cw does is define the width for the columns. The width for column 1 should be 152 and the width for column 2 should be 120. These are numbers I have found best for this exact script. You need to try out many values here and there before you find something that fits. When you create a window like this you'll have to nest several layouts and controls. There are different ways of achieving the same looks so basicly do it the way you feel like doing it as long as it works. This is how I set up the layouts for my window:

window -t "final3 Multiple renderStatsEditor" -wh 285 295 ma_multiAttrEdWin;
rowColumnLayout -nc 2 -cw 1 154 -cw 2 122 -h 230;
frameLayout -l "objects:" -fn "smallFixedWidthFont" -bs "etchedIn" -h 232;
textScrollList -w 150 -h 190 -ams 1 ma_multiAttrEdTSL;
button -l "update selection" -w 148;

frameLayout -l "options:" -fn "smallFixedWidthFont" -bs "etchedIn" -h 200;
columnLayout ma_optionsColumn;

showWindow ma_multiAttrEdWin;

If you execute this code you get this:


You can see how the rowColumnLayout sets the different width for the two frame layouts, I have labels for both my frameLayouts and I also have the controls textScrollList (empty white list) and a button. The reason I haven't put in the controls for the options-side yet is because I plan to do this in a very different way. You can also see that I put in a new command called setParent..; What this command does it to guide us out of the current layout and one step upwards. See this paint over:

  • The green layout is the main columnLayout. This is the first layout we put ourselves in.
  • Then we create the rowColumnLayout. Now we are inside this one and this layout is also inside the green one
  • Then we create a frameLayout. This layout is inside the rowColumnLayout that is inside the green one.This frameLayout represents the first column in the rowColumnLayout.
  • The layouts are defined and we create a columnLayout to hold the controls. This layout is then inside the frameLayout. So far we have gone like this:
    So when we go back once (setParent..;) we go back to frameLayout. Then the second setParent will guide us back to the layout above this one again which is rowColumnLayout. Now we are ready to define the second column. So after the second setParent we simply write frameLayout because that's the layout we want for the optionsColumn. It would have been easier to see this if we named the layouts, but I only name the ones I know I'll be modifying later.

< previous page continued on next page >

1 | 2 | 3 | 4 | 5 | 6
Related Tutorials

Using Driven Keys to create a handController

by Martin Andersson
published on 2009-12-09

Keywords: drive, keys, hand, controller, maya,

rating star nonerating star nonerating star nonerating star nonerating star none (0)
Comments 0 Views 31459

Setting up animation controls in Maya

by Martin Andersson
published on 2009-12-09

Keywords: animation, controls, maya,

rating star fullrating star fullrating star fullrating star fullrating star full (1)
Comments 0 Views 26779

Modelling and Rigging a nut and bolt

by Martin Andersson
published on 2007-04-12

Keywords: nut, bolt, modeling, maya,

rating star fullrating star fullrating star fullrating star fullrating star full (1)
Comments 0 Views 94840

Introduction to rigging in Maya - The shoulder and the arms

by Jahirul Amin
published on 2014-03-03

Keywords: Maya, Rigging, Animation, Body, Neck, Shoulder, Arms

rating star fullrating star fullrating star fullrating star fullrating star full (23)
Comments 5 Views 75876
Readers Comments (Newest on Top)
no comments!
No comments yet. Be the first to comment!
Add Your Comment..