PDA

View Full Version : Passing arrays and getting names


H3ro
11-13-2007, 07:20 PM
Im working on a Mel script that creates an expression, but I am having a few problems with getting some of the variables I need into the expression

1. How do I pass an array from the MEL part to the expression part?

string $list[] = ls -sl;

expression -s("string $myList[] = "+ $list +") <-- Gives an error


2. How could I go about doing this; I have a lot of objects created by the MEL script that the expression has to know about. They all have a prefix set by the script, and a name.
To get the name of them in MEL, this works:
string $cirSel[] = `ls -tr ($preFix + ("controlCircle_*"))`;

But what would the expression version be, the example under is the best I can come up with, but it does not work
string $cirSel[] = `ls -tr (\""+$preFix+"controlCircle_\*")`;

Regards,
Ole Kristian

scottiedoo
11-13-2007, 07:58 PM
hi ole, hopefully I understood you

1:

string $list[] = `ls -sl`;

string $exp = "string $myList[] = {";
int $num = size($list);

for($i=0; $i < $num;$i++){
$exp += "\"" + $list[$i] + "\"";
if($i != ($num - 1)){
$exp += ",";
}
}

$exp += "};";

print $exp;

expression -s $exp;


This builds the string to put into the expression and then creates the expression with the names of the selected objects.

2: You could do the same thing as the above you would use MEL to get the names and then pass them through. So you don't have to use mel commands in the expression editor which will only slow down your scene calling the "ls" command constantly.

I am not sure what you plan to do with the names, so there may be a easier way to build your expression in MEL first and then making the expression rather than putting a ton of MEL into the expression again which will only slow down your scene depending on what you are trying to do.

-Scott

H3ro
11-13-2007, 08:50 PM
Thank you for your answare, but it will not work in my case I think.

Here is a simplified version of my MEL script:

get selection
create control objects
add attributes to control objects

for all the selected objects
create rigidBody node
create control expression


Its the control expression I am having trouble with. How can I pass the list of control objects to the expression? I have the name of all the control objects stored in a variable, but have no idea on how to pass that array to the expression.

This is invalid:

string list[] = loads of objects...

expression -s ("string controlList[] = "+list+"")


So basically question 1 and 2 is two different ways to solve my problem, but I couldn't get any of them to work.

Any ideas?

scottiedoo
11-13-2007, 09:29 PM
What is your control expression suppose to be?

Is it something along the lines of:
object1.translateX = controlObject1.someAttr


But of course you want to automate in making that line through the script and passing it into a single expression.

That would be easier as you would just have to build the expression in MEL such as:


string $list[] = `ls -sl`;
string $controlObjs[] = your control objects array

string $exp;

for($i=0;$i < size($list);$i++){
$exp += ($list[$i] + ".translateY = " + $controlObjs[$i] + ".someAttr \n");
}

expression -s $exp;


Of course you would have to adjust the string to be the expression you want and change the attributes to what you want to connect to. Your control list would have to be in the same order as your object selection as well.

Is this getting closer?

If you could write out a working example of just 1 object and what the expression looks like then I can get a clearer picture.

Chadrik
11-13-2007, 09:33 PM
what scottiedoo suggests is the typical way of dealing with this, compile the commands for each object into a long string that gets passed to the expression command.

if you actually want your data as an array, you just have to deal with mel's sometimes painful string formatting idioms. the expression needs to be passed a string that represents the code to be executed. so you want your list to end up looking something like this:

{"object1", "object2", "object3"}

but maya won't do that formatting for you, so you can use stringArrayToString:


string $list[] = `ls -sl`;
expression -s ("string $myList[] = {\""+ stringArrayToString( $list, "\", \"") +"\"};")

H3ro
11-14-2007, 12:59 AM
I feel so bad, but I cant get this to work. Spent the whole day working on this now.
Anyone feel like taking a look for me?


{
// -------------------------------------------------
// Create controls for the script
// -------------------------------------------------
string $preFix = "OK_"; // Add a uniqe prefix to avaoid name problems
int $nCircles = 3; // Controls how many circles to make
int $collisions = 0; // Bool variable for turning on and off collision
int $nCollisionLayers = 1; // Bool variable for adding each rBody to a new cLayer NOT working at this stage


// -------------------------------------------------
// Store objects that is needed for the script for later use
// -------------------------------------------------
string $geoSel[] = `ls -sl -fl`;


// -------------------------------------------------
// Create the interactive controls
// -------------------------------------------------
// Create n circles, each one unit apart in the y-axis, just to make
// it easier to tell them apart later on
for($i = 0; $i< $nCircles; $i++)
{
circle -c 0 $i 0 -nr 0 1 0 -sw 360 -r 1 -d 3 -ut 0 -tol 0.01 -s 8 -ch 1;
rename ($preFix + ("controlCircle_" + $i));

// Add a radius attribute to easy both animation and scripting
addAttr -ln "radius" -at double -dv 1 ($preFix + ("controlCircle_"+$i+""));
setAttr -e -keyable true (""+$preFix+"controlCircle_"+$i+".radius");

// Link the radius to the X and Z scale
expression -s (" \n \
"+$preFix+"controlCircle_"+$i+".scaleX = "+$preFix+"controlCircle_"+$i+".radius; \n \
"+$preFix+"controlCircle_"+$i+".scaleZ = "+$preFix+"controlCircle_"+$i+".radius; \n \
")
-o ($preFix + ("controlCircle_"+$i+""))
-ae 1
-uc all;
}

// Store all control circles in a variable
string $cirSel[] = `ls -tr ($preFix + ("controlCircle_*"))`;


// -------------------------------------------------
// Turn the geometry selected into rigidBodies, and create
// the script for controlling them
// -------------------------------------------------
for ($i = 0; $i< size($geoSel); $i++)
{
select $geoSel[$i];

// Create the rigidBody node
string $rbNode = `rigidBody -active
-m 1
-dp 0
-sf 0.2
-df 0.2
-b 0.6
-l $i
-tf 200
-iv 0 0 0
-iav 0 0 0
-cl $collisions
-c 0
-pc 0
-i 0 0 0
-imp 0 0 0
-si 0 0 0
-sio none` ;

// Create the control expression
expression -s (" \n \
// Create the variables we need to keep track of the script \n \
int $active; \n \
string $objName = " + $geoSel[$i] + "; \n \
string $cirSel[] = {\""+ stringArrayToString( $cirSel, "\", \"") +"\"}; \n \ <----- PROBLEM LINE
\n \
// If we are at the startFrame, initialize the needed variables \n \
if (frame == 1) \n \
{ \n \
$active = 0; \n \
"+$rbNode+".active = 0; \n \
} \n \
\n \
// Check if the object is inside the circle, if it is, turn the \n \
// RigidBody on. Since the calculation is so expensive, we first check \n \
// if the object already has been activated \n \
if ($active == 0) \n \
{ \n \
int $result = checkIntersection($objName,$cirSel); \n \
\n \
if ($result == 1) \n \
{ \n \
// The object is inside the circle \n \
"+$rbNode+".active = 1; \n \
$active = 1; \n \
} \n \
else \n \
{ \n \
"+$rbNode+".active = 0; \n \
} \n \
} \n \
")
-o geoSel[$i]
-ae 1
-uc all;
}
}

scottiedoo
11-14-2007, 04:10 PM
Let me know if this works, it works on my end but of course I don't have the procedure "checkIntersection" I would imagine that is yours.

I rewrote some parts to be quicker and cut some fat.


// -------------------------------------------------
// Create controls for the script
// -------------------------------------------------
string $preFix = "OK_"; // Add a uniqe prefix to avaoid name problems
int $nCircles = 3; // Controls how many circles to make
int $collisions = 0; // Bool variable for turning on and off collision
int $nCollisionLayers = 1; // Bool variable for adding each rBody to a new cLayer NOT working at this stage

// -------------------------------------------------
// Store objects that is needed for the script for later use
// -------------------------------------------------
string $geoSel[] = `ls -sl -fl`;
string $cirSel[];
// -------------------------------------------------
// Create the interactive controls
// -------------------------------------------------
// Create n circles, each one unit apart in the y-axis, just to make
// it easier to tell them apart later on
for($i = 0; $i< $nCircles; $i++)
{
string $circleName[] = `circle -c 0 $i 0 -nr 0 1 0 -sw 360 -r 1 -d 3 -ut 0 -tol 0.01 -s 8 -ch 1 -n ($preFix + "controlCircle_" + $i)`;

// Add a radius attribute to easy both animation and scripting
addAttr -ln "radius" -at double -dv 1 $circleName[0];
setAttr -e -keyable true ($circleName[0] + ".radius");

// Link the radius to the X and Z scale
connectAttr -f ($circleName[0] + ".radius") ($circleName[0] + ".scaleX");
connectAttr -f ($circleName[0] + ".radius") ($circleName[0] + ".scaleZ");

$cirSel[$i] = $circleName[0];
}

// -------------------------------------------------
// Turn the geometry selected into rigidBodies, and create
// the script for controlling them
// -------------------------------------------------
for ($i = 0; $i< size($geoSel); $i++)
{
select $geoSel[$i];

// Create the rigidBody node
string $rbNode = `rigidBody -active
-m 1
-dp 0
-sf 0.2
-df 0.2
-b 0.6
-l $i
-tf 200
-iv 0 0 0
-iav 0 0 0
-cl $collisions
-c 0
-pc 0
-i 0 0 0
-imp 0 0 0
-si 0 0 0
-sio none`;

// Create the control expression
string $exp = "string $cirSel[] = {\"" + stringArrayToString($cirSel,"\", \"") +"\"}; \n";
$exp += "if(frame == 1){ \n";
$exp += " " + $rbNode + ".active = 0; \n} \n";
$exp += "if(" + $rbNode + ".active == 0){ \n";
$exp += " int $result = checkIntersection(\"" + $geoSel[$i] + "\",$cirSel); \n";
$exp += " if($result == 1){ \n";
$exp += " " + $rbNode + ".active = 1; \n";
$exp += " } else { \n";
$exp += " " +$rbNode + ".active = 0; \n";
$exp += " } \n}";

expression -s $exp -o geoSel[$i] -ae 1 -uc all;
}

H3ro
11-16-2007, 07:35 PM
Thank you scottiedoo.

What is the advantage of doing the expression as you do it? Is it just personal preference, or does it give some advantages?

Thank you for pointing out the "connectAttr" instead of using expression to link them together.

An other question, normally I do this when I send a string to the expression:
" + $myString + "
But you do it this way:
"\" + $myString + "\"

I though that would mean that you send $myString as a string, instead of the content inside it.

So, you would have
string $a = "$myString"

I see that the script works, so that is not the case, so what do the extra quotes do?

Thanks again for helping me out like this, very very kind of you.

scottiedoo
11-17-2007, 03:20 AM
They way you do it is not necessarly wrong, but anything you can do to reduce the amount of variables and code is always good. So its to trim things that are not needed such as the "active" variable as you can see it does the same thing as the "active" attribute on the rigid body. Same thing goes with storing the name in a variable. Its not a HUGE time saver, but every little helps and keeps your code lean as possible. I am sure with some more though my expression could be reduced even more.

Any time you use expressions rather than other nodes, it takes Maya more time to read, translate it, then process it than to simply use a node or a connection. Some times there are no other ways to do something than to use expressions which is why they are great, but I try to keep away from them or use for part of the job when no other node can do it.

Ok, the string question.. I'll use this line as an example:
string $exp = "string $cirSel[] = {\"" + stringArrayToString($cirSel,"\", \"") +"\"}; \n";

we need to put this piece of MEL inside the expression editor so in the above the expression editor would read:

string $cirSel[] = {"bobby","sammy","eric","joe"}; which is a valid mel statement that the expression editor will read

Notice I broke out of the string and injected the array items as a string in the middle and then resumed the rest of the string cause we want whatever is in your MEL script to be in the expression editor.

Example:
string $myArray[] = {"bobby","sammy","eric","joe"};
string $stringArray = stringArrayToString($myArray,"\",\"");
string $expression = "string $newArray[] = {\"" + $stringArray + "\"}; \n";
print $expression;

RESULT:
string $newArray[] = {"bobby","sammy","eric","joe"};
without the \" it would print

string $newArray[] = {bobby","sammy","eric","joe}; <- invalid no qoutes at beginning and end!


does that help at all?

Scott

H3ro
11-17-2007, 03:14 PM
Thank you again, it makes much more sense now. Thank you for taking time to walk me through it like that :)

CGTalk Moderation
11-17-2007, 03:14 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.