Keep up-to-date with Free tutorials!!

 

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

 

- 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

3DTotal.com logo
 
Shop
Tutorials
Textures
Galleries
Forums
Submit
 
submit tutorial
1 | 2 | 3 | 4 | 5 | 6
mel ShapeEditor

By Martin Andersson
| Your Rating:
starstarstarstarstar
(0 Votes)
| 4588 Views
| 0 Comments
| Comments 0
Date Added: 9th December 2009
Software used:
Maya

Ok, now that we have the basic layout we can start fixing the parts one by one. I will start with the textScrollList. I want this control to list selected objects. Now, we have already talked about the command we have to use here "ls". But how are we going to get this command to throw values into the textScrollList. We create a proc for this, see code below (I had to put the code in a table to make it more readable. If you wish to copy the code, use the code with a white background below.):

global proc ma_multiAttrEdList ()
{
string $ma_selected[] = `ls -sl`;
if (!(`size($ma_selected)`))
{
warning "nothing selected. List will not display any objects";
}


else
{
textScrollList -e -ra ma_multiAttrEdTSL;
for ($ma_sel in $ma_selected)
{
string $ma_pickWalked[] = `pickWalk -d down $ma_sel`;
textScrollList -e -a $ma_pickWalked ma_multiAttrEdTSL;
}
}
}


Now this proc has a lot of actions, it includes an "if statement" and a "for in loop". So now we get to see how this really works. I'm also going to explain the commands.

  • global proc ma_multiAttrEdList () : This is just the name of the proc, I have no arguments here.
  • string $ma_selected stores the selected objects in an array.
  • if (!(size($ma_selected)`){...}: I check if the size of $ma_selected is NOT. If it's not, it has to be "0". Then inside the curly braces I have a print command telling the user that nothing is selected. We need a selection for this script to work properly.
  • else: This is what will happen if we have a selection.
  • textScrollList -e -ra ma_multiAttrEdTSL: First we want to empty the textScrollList in case there were already a selection present. If you have something listed there already and you appended another selection it would simply add to the bottom of the list. What we want is the list updating with the new selection and therefore we have to empty it first and then add the new selection.
  • for ($ma_sel in $ma_selection) {...} Here we tell Maya that we want to do something to each object in the selection. Of course I want to append each object to the list. Well, not really, I want the SHAPES to be listed because they are the ones being manipulated when we change the renderStats.
  • string $ma_pickWalked[]: There is a command called pickWalk. If you check the documentation it has certain directions and the one we are looking for is "down". listRelatives could probably also do the trick. Try it out if you want to.
  • Last thing is an edit of the textScrollList. We want to append the shapes which is stored in $ma_pickWalked and the layout being edited is ma_multiAttrEdTSL.

That's basically all the proc does. Now I'm going to do two things with this proc. First I'm going to put it in the command for the button and then I'll put it somewhere in the code between "window" and "showWindow". This way the list will be updated if the user has a selection when he/she opens the window. The changes are in bold letters:

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

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


setParent..;
setParent..;
frameLayout -l "options:" -fn "smallFixedWidthFont" -bs "etchedIn" -h 200;
columnLayout ma_optionsColumn;
ma_multiAttrEdList;
showWindow ma_multiAttrEdWin;


You can try it out. If you click the button after selecting some objects the list gets updated. Funny stuff huh? :)

Now the tricky part begins. I want to build the checkboxes and I also want to create a button that changes the renderStats... Well, you might think. That shouldn't be a problem. You can just add a lot of checkBoxes and create integers that check the values and then you can just let the button go through all that?

Well, I don't want to use a lot of lines for this and I also want it to be easy to remove or add checkBoxes. Therefore I create an array that holds all the info I need to create the checkBoxes and the command for the button. Then there's some mixin' and trixin' to nest all this together. I'll write down the code and go through it step by step.

//Array that defines the commands I want to use
global string $ma_meshArray[] = {"castsShadows" , "receiveShadows" , "motionBlur", "primaryVisibility" ,
"smoothShading" , "visibleInReflections" , "visibleInRefractions" , "doubleSided" , "opposite"};


I know which attributes the renderStats hold so I simply create an array that can store all of these. Now I can use these as labels as well as commands. ( Because I do it like this the labels will not have the EXACT same name as in the attributeEditor.) The way I found out which strings to write down was simple. I turn "echo all commands" on in the scriptEditor, select an object, open the attributeEditor and check/uncheck stats. Then I can read directly in the scriptEditor what Maya changes. Notice that I declared the array as a GLOBAL string. This is because I want to use it later inside another loop and if I want to use strings like that I have to make them global.

//A loop building all the "options" - UI
for ($i = 0; $i < `size($ma_meshArray)`; $i++)
{
checkBox -l $ma_meshArray[$i] -v 1 -p ma_optionsColumn ($ma_meshArray[$i] + "checkBox");
}


You should be able to read this now. This is very close to the example I used earlier, only the command here is different. The loop checks the size of the array ( which is 9 (count the strings in the array above) ) Let's say we go through the loop with the first string in the array as an example "castsShadow".

checkBox -l "castsShadow" -v 1 -p optionsColumn castsShadowcheckBox;

Notice that there is a flag here "-p" that parents this checkBox to the optionsColumn. This column was empty earlier. Now it's time to fill it. We'll fill it the way we filled a window with 50 buttons in the loop example.

If you look at the sketch again you see that I also want a button here. So right after the loop I add these lines: ( I decided to put a separator there too...)

separator -h 46 -w 115;
button -w 116 -l "Edit RenderStats";


Now we already have a UI where the button on the left can update our list and we also have a lot of check boxes here :) Pluss a separator and a button ( A button that doesn't do anything yet... )

Let's see if the checkBox loop works. This is how it looks so far:

760_tid_sketchToReal.jpg
I think it's looking very good. This is exactly what we wanted it to look like. I have also selected a few primitives to check what that looks like.

The remaining stuff to add here are two procs. The first one is a bit advanced, but the other one is rather easy.This is the first one:

global proc ma_renderStatCommand (int $ma_whichCommand)
{
global string $ma_meshArray[];
string $ma_listShapes[] = `textScrollList -q -si ma_multiAttrEdTSL`;
for ($ma_shapes in $ma_listShapes)
{
setAttr ($ma_shapes + "." + $ma_meshArray[$ma_whichCommand]) (`checkBox -q -v ($ma_meshArray[$ma_whichCommand] +
"checkBox")`);
}
}


Here we actually have a proc with an argument for the first time during the scripting of this script. Time to puton the "focus-hat" ladies and gentlemen...

  • ma_renderStatCommand (int $ma_whichCommand): Just the name of the proc and we also tell Maya that we wish to use an integer to do something inside the proc.
  • global string $ma_meshArray[]; But this is the variable we declared earlier in the script... Yes it is, but we have to tell Maya that we intend to use it her too. Since we are inside the proc, Maya pays no attention to what's on the outside. We just went inside a proc-house. Now we say "Maya! Remember that I declared a value outside the proc?... Well I intend to use it again so I'll just redeclare it in here OK?".
    We're allowed to use it again as long as we redeclare it. However you don't have to cast values to it. Maya will remember the values.
  • Then we query the selected objects in the textScrollList ( -q -si (selectItem) ) and we cast the list to the array $ma_listShapes.
  • We use a for in loop to go through all the selected objects and setting the new renderStats for them. Now, let's take a closer look at the command in that loop....
    --> setAttr ( command for "set attribute" )
    --> ($ma_shapes + "." + $ma_meshArray[$ma_whichCommand]) ( object + attribute ) Here we include the integer we wanted as an argument. This means that when I call this proc I have to write:ma_renderStatCommand 0 to set the value for castsShadows and so on.
  • (`checkBox -q -v ($ma_meshArray[$ma_whichCommand] + "checkBox")`): But since setAttr needs two arguments like this: "setAttr object.attribute value" we need to add this. This line is a bit tricky. We directly query the state of the checkBox and then this becomes the value we set (say we call the proc again with the argument 0: checkBox -q -v castsShadowcheckBox ) If it equals 1 the attribute will be turned on, if it equals 0 the attibute will be turned off.

But what are we going to use this proc for? We cant call it 9 times to go through it? ( the array have 9 values, but starts at 0 remember so the last one is 8 / see the next proc ) Are we going to assign that proc to the button? That won't make sense will it?

We build another proc, that's what we do. And inside that proc we'll loop through all the checkBoxes and set the attributes according to the queried values. Here it is:

//Check the checkBox-values and edit the renderStats:
global proc ma_cycleValues()
{
for ($i = 0; $i <= 8; $i++)
{
ma_renderStatCommand $i;
}
}


This proc does all the job for us. It inserts the integer we need as an argument for the previous proc and loops through it by setting 0, 1,2 and so on... It will loop through all the checkBoxes and set the attributes USING the other proc... Pretty clever huh? Now this is the proc we'd want to add to our button. Now you already know how to do that so I won't write down the code for that here. Of course you can download the code below here and you can also download my final version of this script on the resources- page. This is how my version looked when I was finished with it:

760_tid_finishedWithIcons.jpg

You should be able to make something similar if you browse the helpFiles a bit ;)

NOTE: The script we wrote together is downloadable here, but it's not cleaned. I suggest you download the one in the resource section and compare them. Because the script I have there is an official release and therefore the script is commented, icons included and also a readMe with install-notes are supplied.

There are several things you could do to improve the script, but I think this will do for now. Of course you can do some research and try rewriting it to do other tasks too :)

In this tutorial I have gone through the very essence of MEL scripting. I have only scratched the surface, but I feel the things I went through her is essential if you want to write short code that can do big things.

--> commands
--> variables
--> strings, ints, arrays, floats
--> if statements
--> loops
--> procedures.

And as I have said before: Even if it can seem a bit unclear you'll grow with experience and learn while doing. I'm just trying to push you in the right direction here. If you have any comments or questions you can reply in this cgTalk thread or use the contact form on my site to get in touch with me directly.

760_tid_forTutMEL.jpg
to download, rightClick and "save target as..."



 
1 | 2 | 3 | 4 | 5 | 6
Readers Comments (Newest on Top)
no comments!
No comments yet. Be the first to comment!
Add Your Comment