Feedback

What's your question?

By: [ Editor ] Asked from United States of America

How can I write a mel script that writes particle expressions?

How can I write a mel script that writes particle expressions?

Add comment viewed 1,087 times Latest activity 7 months ago

NN comments
hugh_gid
-

Hi Martin,

I’ve just edited your question to make the title of the question a little more explanatory – in a lot of cases, that’s the only thing that people see, so it really should give an brief summary of what the question is…

Cheers!

or Cancel

2 answers

  • 3

julian [ Admin ]

Writing code that writes code is called meta-programming. You need to get good at building and evaluating strings.

For particle expressions, usually you want to append to an existing expression rather than overwrite it. So store whatever is there in a variable.

You also need to specify which of the three types of expression you want with the flags:

  • -c = creation
  • -rbd = runtimeBeforeDynamics.
  • -rad = runtimeAfterDynamics

You can query a particle expression even if its empty, so this will never fail.

// get particle object and existing expression code as a string
string $particle = "particleShape1";
string $expr =  `dynExpression -rbd -q -s $particle`; 

// just in case the last line didn't end in a semi colon, add one and a newline.
$expr += ";\n";

// add some new stuff
$expr += "velocity = <<0 , sin(time),0 >>;\n";
$expr += "rgbPP = <<1, ((sin(time) +1)  / 2.0) ,0>>;\n";

// set the new string to be the expression.
dynExpression -rbd  -s $expr  $particle;

For the above to work you should obviously have an rgbPP attribute. Don't expect it to look pretty when it runs ;)

That's a pain to do if you write particle expressions all the time. Better to write a general purpose expression appender function.. So you want to specify the type of expression (creation, rbd, or rad) as a variable, that way you only have to write the function once and you can keep it small. You can't pass that flag as a variable to the dynExpression command and execute normally (as far as I know). You need to build the whole dynExpression command as a string, then use "eval" to evaluate it. "eval" is a powerful meta-programming tool.

It works like this:

$result = eval(cmd) ; // where cmd is a string that can be executed.

Here's where it can get tricky though. When you write the new expression using eval, you need the expression string (what you want to be the final expression) to be part of the string that will be evaluated as a command. It can be a nightmare to make all those quote marks stay in tact. Fortunately there is another command that comes in useful for meta-programming: "encodeString()"; You give it a string and it wraps it up so you can pass it around without frying your brain - too much. Check out the examples in the docs.

So here's a complete function to append code to any particle expression.

global proc appendExpression(string $particle, string $code, string $typeFlag){

    string $expr = eval("dynExpression -" +$typeFlag + " -q -s " + $particle);  
    $expr += ( ";\n// *************************************\n");
    $expr += $code;
    $expr += ( ";\n// *************************************\n");
    eval("dynExpression -" +$typeFlag + " -s \"" +  encodeString($expr) +"\" "+ $particle);  
}

The 2 lines of "*" make it easy to see which bits you added.

Now when you want to write an expression, like the first one above, you can do this:

string $newExpression = "velocity = <<0 , sin(time),0 >>;\n";
$newExpression += "rgbPP = <<1, ((sin(time) +1)  / 2.0) ,0>>;\n";

appendExpression("particleShape1", $newExpression, "rbd");
// much cleaner ;)
NN comments
martin_61
-

Wow, thanks so much Julian. I really appreciate such a thorough answers.

or Cancel