PDA

View Full Version : Struggling with mel into expression


foggyball
11-16-2010, 04:47 PM
Can anyone help me?

Firstly I'm really rubbish with mel, I've dabbled on and off over the years but never enough to get a good handle on it.
So with my excuses out of the way.....

I have a scene with a nurbsSphere1 a locator and a distanceBetween node connect to them both.
If I added the expression (shown at the end of the post) to the nurbsSphere1 scale X,Y and Z I get the exact result I'm after.

The problem is I need to apply this to 50 or more spheres. I can get the first part done with this:
//How many spheres do you want?
float $numberSphere = 60;

//How big a gap between the spheres
float $sphereGap = 1.3;

//How large a sphere do you want?
float $sphereRadius = .5;


$i=0;
while($i++ < $numberSphere)
{
sphere -r .5 -ax 0 1 0;
move ($i*$sphereGap) 0 0;
}

spaceLocator -p 0 2 0;

//Create distanceBetween node and connect to sphere1 and locator
shadingNode -asUtility distanceBetween;
connectAttr -f locator1.translate distanceBetween1.point1;
connectAttr -f nurbsSphere1.translate distanceBetween1.point2;

But I can't figure out how to get the expression to be put on each sphere via a for loop. Can anyone help me?

This is the expression for the spheres.

$dummy = distanceBetween1.distance;

// get locators position in X
float $locPos = `getAttr locator1.translateX`;

// Get the spheres world position
float $spherePos = `getAttr nurbsSphere1.translateX`;

// Check the distance in comparison to the sphere.
$distX = $locPos - $spherePos;


float $scaleUp = 0;
float $scaleDown = 0;
float $scaleUpRate = -2;
float $scaleDownRate = 10;


if ($distX < $scaleUp)
{
nurbsSphere1.scaleX = 1.0 + ((`smoothstep ($scaleUpRate) ($scaleUp) ($distX)`) * 1);
nurbsSphere1.scaleY = 1.0 + ((`smoothstep ($scaleUpRate) ($scaleUp) ($distX)`) * 1);
nurbsSphere1.scaleZ = 1.0 + ((`smoothstep ($scaleUpRate) ($scaleUp) ($distX)`) * 1);
}
else if ($distX > $scaleDown)
{
nurbsSphere1.scaleX = 1 + ((1.0 - `smoothstep ($scaleDown) ($scaleDownRate) ($distX)`) * 1);
nurbsSphere1.scaleY = 1 + ((1.0 - `smoothstep ($scaleDown) ($scaleDownRate) ($distX)`) * 1);
nurbsSphere1.scaleZ = 1 + ((1.0 - `smoothstep ($scaleDown) ($scaleDownRate) ($distX)`) * 1);
}

print (" scale Sphere 1 :"+nurbsSphere1.scaleX+" distX to sphere 1 :"+$distX+"\n");

What this should give me is a locator which when dragged along the x direction, scales the spheres up and down based on distance. This gives a similar look to the Dock in Mac OS X.
If anyone can shed some light on how I can 'glue' these two bits of code together, I'd be very grateful.

Dave

fezz
11-16-2010, 06:17 PM
Didn't have time to check over this too thoroughly, but this should be the syntax you're looking for:

{
int $numberSphere = 60;


//How big a gap between the spheres
float $sphereGap = 1.3;

//How large a sphere do you want?
float $sphereRadius = .5;

for ($i = 0; $i < $numberSphere; $i++){

string $sphere[] = `sphere -r $sphereRadius -ax 0 1 0`;
move ($i*$sphereGap) 0 0;
string $loc[] = `spaceLocator -p 0 2 0`;

string $dist = `shadingNode -asUtility distanceBetween`;
connectAttr -f ($loc[0]+".translate") ($dist+".point1");
connectAttr -f ($sphere[0]+".translate") ($dist+".point2");

expression -s ("float $locPos = `getAttr "+$loc[0]+".translateX`;\n"+
"float $spherePos = `getAttr "+$sphere[0]+".translateX`;\n"+
"$distX = $locPos - $spherePos;\n"+
"float $scaleUp = 0;\n"+
"float $scaleDown = 0;\n"+
"float $scaleUpRate = -2;\n"+
"float $scaleDownRate = 10;\n"+
"if ($distX < $scaleUp){\n"+
"\t"+$sphere[0]+".scaleX = 1.0 + ((`smoothstep ($scaleUpRate) ($scaleUp) ($distX)`) * 1);\n"+
"\t"+$sphere[0]+".scaleY = 1.0 + ((`smoothstep ($scaleUpRate) ($scaleUp) ($distX)`) * 1);\n"+
"\t"+$sphere[0]+".scaleZ = 1.0 + ((`smoothstep ($scaleUpRate) ($scaleUp) ($distX)`) * 1);\n"+
"}\n"+
"else if ($distX > $scaleDown){\n"+
"\t"+$sphere[0]+".scaleX = 1 + ((1.0 - `smoothstep ($scaleDown) ($scaleDownRate) ($distX)`) * 1);\n"+
"\t"+$sphere[0]+".scaleY = 1 + ((1.0 - `smoothstep ($scaleDown) ($scaleDownRate) ($distX)`) * 1);\n"+
"\t"+$sphere[0]+".scaleZ = 1 + ((1.0 - `smoothstep ($scaleDown) ($scaleDownRate) ($distX)`) * 1);\n"+
"}\n"+
"print \(\"// scale "+$sphere[0]+": "+(`getAttr ($sphere[0]+".scaleX")`)+", distX to "+$sphere[0]+": \"+$distX+\"\\n\"\);\n") -ae 1 -o $sphere[0] -uc all -n ($sphere[0] + "_distBtwn");
}
}


Basically it's running a loop to create the spheres and locator, then building an expression to attach to each sphere. The tricky part is escaping the expression (the print statement was a bitch). Don't forget to declare variables for the objects you are creating so that you can pass them into the expression.

foggyball
11-16-2010, 08:26 PM
I really appreciate you spending the time to look over this for me. I'm looking forward to checking it first thing in morning. I will let you know how I get on.

Dave

foggyball
11-17-2010, 09:14 AM
That works like a dream, thanks very much.

I did the tiniest of tweaks as I only needed one locator, which is connected to sphere1. There is a useful bug in Maya that gives viewport feedback when moving the locator. This only seems to work if at least one of the spheres in connected to the distanceBetween node and one locator. Then in each of the spheres expression I just have the line $xxxxxx = distanceBetween1.distance. Even though the var isn't used it's enough to get all the spheres to scale when moving the locator.

So my final script looked like this.


{
int $numberSphere = 60;


//How big a gap between the spheres
float $sphereGap = 1.3;

//How large a sphere do you want?
float $sphereRadius = .5;

string $loc[] = `spaceLocator -p 0 2 0`;
string $dist = `shadingNode -asUtility distanceBetween`;

for ($i = 0; $i < $numberSphere; $i++){

string $sphere[] = `sphere -r $sphereRadius -ax 0 1 0`;
move ($i*$sphereGap) 0 0;
//string $loc = `spaceLocator -p 0 2 0`;

//string $dist = `shadingNode -asUtility distanceBetween`;
//connectAttr -f ($loc[0]+".translate") ($dist+".point1");
//connectAttr -f ($sphere[0]+".translate") ($dist+".point2");

expression -s ("$xxxxxx = distanceBetween1.distance;\n"+
"float $locPos = `getAttr "+$loc[0]+".translateX`;\n"+
"float $spherePos = `getAttr "+$sphere[0]+".translateX`;\n"+
"$distX = $locPos - $spherePos;\n"+
"float $scaleUp = 0;\n"+
"float $scaleDown = 0;\n"+
"float $scaleUpRate = -2;\n"+
"float $scaleDownRate = 10;\n"+
"if ($distX < $scaleUp){\n"+
"\t"+$sphere[0]+".scaleX = 1.0 + ((`smoothstep ($scaleUpRate) ($scaleUp) ($distX)`) * 1);\n"+
"\t"+$sphere[0]+".scaleY = 1.0 + ((`smoothstep ($scaleUpRate) ($scaleUp) ($distX)`) * 1);\n"+
"\t"+$sphere[0]+".scaleZ = 1.0 + ((`smoothstep ($scaleUpRate) ($scaleUp) ($distX)`) * 1);\n"+
"}\n"+
"else if ($distX > $scaleDown){\n"+
"\t"+$sphere[0]+".scaleX = 1 + ((1.0 - `smoothstep ($scaleDown) ($scaleDownRate) ($distX)`) * 1);\n"+
"\t"+$sphere[0]+".scaleY = 1 + ((1.0 - `smoothstep ($scaleDown) ($scaleDownRate) ($distX)`) * 1);\n"+
"\t"+$sphere[0]+".scaleZ = 1 + ((1.0 - `smoothstep ($scaleDown) ($scaleDownRate) ($distX)`) * 1);\n"+
"}\n"+
"print \(\"// scale "+$sphere[0]+": "+(`getAttr ($sphere[0]+".scaleX")`)+", distX to "+$sphere[0]+": \"+$distX+\"\\n\"\);\n") -ae 1 -o $sphere[0] -uc all -n ($sphere[0] + "_distBtwn");
}
connectAttr -f ($loc[0]+".translate") ($dist+".point1");
}

I'll add a bit more more control over the input vars, but for now this gets me up and running.

Looks like I owe you a new \ key, as you probably wore yours out escaping the print line.
Thanks again.

Dave

CGTalk Moderation
11-17-2010, 09:14 AM
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.