Announcements

Between mid-October and November, the content on AREA will be relocated to the Autodesk Community M&E Hub and the Autodesk Community Gallery. Learn more HERE.

Conditionnal MEL script

Conditionnal MEL script

contact
Participant Participant
2,145 Views
11 Replies
Message 1 of 12

Conditionnal MEL script

contact
Participant
Participant

Hello, 

I am having issues with MEL Script being a rookie in that. 
I am trying to make some selected cubes (thousands) scale when ever they reach a certain Translate.

Here is the MEL I am working on :

string $selectedList[] = `ls -sl`;
string $currentObject;

for ($currentObject in $selectedList)
{
if ($currentObject + ".translateY" > 17) ;
{
$currentObject + ".scaleX"=0;
$currentObject + ".scaleX"=0;
$currentObject + ".scaleX"=0;
else {
$currentObject + ".scaleX"=1;
$currentObject + ".scaleX"=1;
$currentObject + ".scaleX"=1;
}
}

Maya report a lot of syntax error that I can't fix. Can someone help me ? 

// Error: if ($currentObject + ".translateY" > 17) ;
//
// Error: Line 6.48: Illegal operation ">" on data of type string. //
// Error: $currentObject + ".scaleX"=0;
//
// Error: Line 8.36: Syntax error //
// Error: $currentObject + ".scaleX"=0;
//
// Error: Line 9.36: Syntax error //
// Error: $currentObject + ".scaleX"=0;
//
// Error: Line 10.36: Syntax error //
// Error: else {
//
// Error: Line 12.20: Syntax error //
// Error: $currentObject + ".scaleX"=1;
//
// Error: Line 14.36: Syntax error //
// Error: $currentObject + ".scaleX"=1;
//
// Error: Line 15.36: Syntax error //

0 Likes
Accepted solutions (1)
2,146 Views
11 Replies
Replies (11)
Message 2 of 12

kevin.picott
Alumni
Alumni

I'll first clear up a basic misconception that should help a lot. MEL strings do not represent actual Maya objects, they only represent the names of Maya objects. So when you say something like this

$currentObject + ".translateY"

what you're referring to is "the string formed by concatenating the name of the object and the attribute "translateY".

In order to actually perform operations on Maya objects you have to use the commands available that do this sort of thing. In this particular case the "getAttr" command is what you want. It is responsible for retrieving the value of an attribute from a node.

float $ty = `getAttr ($currentObject + ".translateY")`;

Similarly for setting values you would use the "setAttr" command like this:

setAttr ($currentObject + ".scaleY") 0;


Kevin "Father of the DG" Picott

Senior Principal Engineer
Message 3 of 12

rajasekaransurjen
Collaborator
Collaborator

Hi,

Try this....

string $selectedList[] = `ls -sl`;
string $currentObject;
 
for ($currentObject in $selectedList)
{
    float $rsTransY = `getAttr ($currentObject + ".translateY")`;
    if ($rsTransY >= 17) 
    {
        setAttr ($currentObject + ".scaleX") 0;
        setAttr ($currentObject + ".scaleY") 0;
        setAttr ($currentObject + ".scaleZ") 0;
    }   
    else
    {
        setAttr ($currentObject + ".scaleX") 1;
        setAttr ($currentObject + ".scaleY") 1;
        setAttr ($currentObject + ".scaleZ") 1;
    }
}
Message 4 of 12

contact
Participant
Participant

Thank you both for your script. I understand the fact that we need a float variable to call it later. 
As I can see it's working for a certain precise moment. 

As I have an animation, I wanted to use a runtime expression that would scale the objets when they are higher than -17 in Translate Y.

I think it's really close.

0 Likes
Message 5 of 12

kevin.picott
Alumni
Alumni

To do something like that which actively modifies values rather than just doing them once on demand you have to run the script every evaluation. In this case your best bet is to use an expression node to define the scale values. The expression name doesn't require "getAttr" and "setAttr" commands though, you can reference values directly and it will create connections that handle those operations for you. For example an expression that will set scaleX to 0 when translateX is > 5.0 is:

expression -s "if( NODE.tx > 5.0) { NODE.sx = 0.0; } else { NODE.sx = 1.0; }"


Kevin "Father of the DG" Picott

Senior Principal Engineer
Message 6 of 12

contact
Participant
Participant

So for multiple objets may I use a string like $selection ? 
That's crazy how hard it is to do a combinaison of 2 easy thing... 

Or should I use ObjectName* to put the expression to all the ObjectName

0 Likes
Message 7 of 12

kevin.picott
Alumni
Alumni

Not in an expression, no. The expression is parsed to look for plug names like "NODE.tx" and then makes direct connections to them. If the names are in a variable like $selection it will have no way of knowing where to connect.

 

Mel is meant to be a very simplified language for artists. To get more power you would want to move to Python.



Kevin "Father of the DG" Picott

Senior Principal Engineer
0 Likes
Message 8 of 12

contact
Participant
Participant

So I tryed like this : 

string $selectedList[] = `ls -sl`;
string $currentObject;
 
for ($currentObject in $selectedList)
{
    float $rsTransY = `getAttr ($currentObject + ".translateY")`;
    float $rsScaleX = `getAttr ($currentObject + ".scaleX")`;
    float $rsScaleY = `getAttr ($currentObject + ".scaleX")`;
    float $rsScaleZ = `getAttr ($currentObject + ".scaleX")`;
expression -s 
    if ($rsTransY >= 17)
    {
       $rsScaleX = 0;
       $rsScaleY = 0;
       $rsScaleZ = 0;
    }   
    else
    {
        $rsScaleX = 1;
        $rsScaleY = 1;
        $rsScaleZ = 1;
    }
}



But it doesn't work

0 Likes
Message 9 of 12

contact
Participant
Participant
// Error:     if ($rsTransY >= 17)
 // 
// Error: Line 11.6: Syntax error // 
// Error:     else
 // 
// Error: Line 17.8: Syntax error // 
// Error:     }
 // 
// Error: Line 22.5: Syntax error // 
0 Likes
Message 10 of 12

kevin.picott
Alumni
Alumni
Accepted solution

As I said you cannot use a variable for an expression since it will not understand how to parse the string. Also your scale attributes are named incorrectly (lower case "s") and your expression command is formatted incorrectly (the string has to be a valid Mel string, which cannot span multiple lines unless you end the line with a backslash).

 

If you are trying to construct an expression from the selection list then you would have to do something like this:

string $selectedList[] = `ls -sl`;
string $currentObject;
string $expressionString = "";
for ($currentObject in $selectedList)
{
    $expressionString += ("if( " + $currentObject + ".translateX > 17 )\n");
    $expressionString += ("{\n");
    $expressionString += ("    " + $currentObject + ".scaleX = 0.0;\n" );
    $expressionString += ("    " + $currentObject + ".scaleY = 0.0;\n" );
    $expressionString += ("    " + $currentObject + ".scaleZ = 0.0;\n" );
    $expressionString += ("} else {\n");
    $expressionString += ("    " + $currentObject + ".scaleX = 1.0;\n" );
    $expressionString += ("    " + $currentObject + ".scaleY = 1.0;\n" );
    $expressionString += ("    " + $currentObject + ".scaleZ = 1.0;\n" );
    $expressionString += ("}\n");
}

expression -s $expressionString;


Kevin "Father of the DG" Picott

Senior Principal Engineer
Message 11 of 12

contact
Participant
Participant

Thank you so much Kevin,

The code you sent me work overtime and it sets to all the selected object an expression. 
With some tweeks to make it work on my project you made it work as intended. 

So Thank you ! 
Can I ask, with no hurry to explain me some code line then ?  So I can get better the next time and trying to understand is always good. 

string $expressionString = ""; 

Why you need to declare that variable with "" ? Is it for any value ? Like not an float / int etc ???

    $expressionString +

The "+" create the evaluation work for everyframe isn't it ?  

$expressionString += ("{\n");

I don't understand the ("{\n"); 

("    " + $currentObject + ".scaleX = 1.0;\n" );

Why not +$currentObject+.scaleX =1.0; only ? the "     " + is somehow disturbing.

expression -s $expressionString;

And this is creating the expression for all the object right ? 

As you can see I don't understand a lot in MEL, and I wonder how much time would I need to understand first (reading, understanding) and then create (write) MEL / Python ?

0 Likes
Message 12 of 12

kevin.picott
Alumni
Alumni
  1. expressionString is declared as a string, and since I'm constructing it as I go it needs to start as an empty string, which is what this line does. (You might also want to add error checking for the case of an empty selection list.)
  2. The "+" is shortform for "put these two strings together into a bigger string", so ("a" + "b") is the same as "ab". The parentheses are necessary when constructing a string, and I use the "+" since some of the string components are not constants.
  3. The "\n" is a special character meaning "new line". It just separates the expression into multiple lines to make it easier to read. See how it appears in the expression editor after you construct it to see what I mean.
  4. The "    " is again just to make it look nicer in the editor.
  5. And yes, that last line is the one that actually creates the expression, which will then live in the scene so that it updates whenever you move the objects.

The best ways to learn Mel programming are to look at the online documentation for the commands, especially the sample code, look at existing scripts, and search online for more detailed examples. Mel has been around for over 25 years so there are plenty of examples out there. (You can even look into the .mel files in the Maya installation directory if you're adventurous.)



Kevin "Father of the DG" Picott

Senior Principal Engineer