A második példaprogram egy tetszoleges úton mozgó objektum forgását automatikusan beállítja úgy, hogy a tárgy mindig a mozgás irányába nézzen. A program megjelenít egy kis ablakot, melyben beállíthatjuk tárgyunkra és a kívánt eredményre vonatkozó paramétereket.
// ez az eljárás hozza létre a beállítás ablakot
proc buildFaceForwardWindow(string $faceForwardWindow)
{
window -title "Face Forward" -iconName "Face Forward" -titleBar true
-minimizeButton true -maximizeButton false
-sizeable true $faceForwardWindow;
columnLayout -rs 5 -adjustableColumn true;
//létrehozunk három float-beírási mezot
floatFieldGrp -label "Aim vector" -numberOfFields 3 -value1 1 -value2 0 -value3 0 faceForwardAimVector;
floatFieldGrp -label "Up vector" -numberOfFields 3 -value1 0 -value2 1 -value3 0 faceForwardLocalUpVector;
floatFieldGrp -label "World up vector" -numberOfFields 3 -value1 0 -value2 1 -value3 0 faceForwardWorldUpVector;
// egy csekkboxot is létrehozunk, ahol be lehet állítani hogy kívánunk-e a forgáshoz sebesség mezot is létrehozni
checkBoxGrp -l "Add velocity attribute" -l1 "" -v1 true faceForwardAddVelocity;
separator -style out;
// létrehozzuk a gombot, amely a kiválsztott objektummal meghívja a makeAllFaceForward fügvényt
button -l "Face Forward" -c "makeAllFaceForward()";
button -l "Close" -c ("window -e -vis 0 " + $faceForwardWindow);
}
// itt történik az irányba állítás
proc makeFaceForward(string $object)
{
// itt kihámozzuk a kiválasztott objektumunk nevét
string $temp[];
tokenize($object, "|", $temp);
string $name = $temp[size($temp) - 1];
// lekérdezzük az objektumunk pozicióját
float $trans[] = `getAttr ($object + ".translate")`;
float $pivot[] = `getAttr ($object + ".transMinusRotatePivot")`;
float $pos[] = {$trans[0] - $pivot[0], $trans[0] - $pivot[0],
$trans[0] - $pivot[0]};
// létrehozunk egy rejtett locator-t
$temp = `spaceLocator -name ($name + "Direction")`;
string $locator = "|" + $temp[0];
hide $locator;
parent $locator $object;
$locator = $object + $locator;
setAttr ($locator + ".inheritsTransform") false;
// lekérdezzük az ablakban beállított értékeket
float $aim[] = `floatFieldGrp -q -value faceForwardAimVector`;
float $localUp[] = `floatFieldGrp -q -value faceForwardLocalUpVector`;
float $worldUp[] = `floatFieldGrp -q -value faceForwardWorldUpVector`;
// létrehzunk egy un. nézo kényszert
aimConstraint -weight 1
-aimVector (-$aim[0]) (-$aim[1]) (-$aim[2])
-upVector $localUp[0] $localUp[1] $localUp[2]
-worldUpVector $worldUp[0] $worldUp[1] $worldUp[2]
-name aimConstraint $locator $object;
addAttr -ln faceForward -at bool -dv true $object;
setAttr -keyable on ($object + ".faceForward");
addAttr -ln lastX -at double -dv $pos[0] $object;
addAttr -ln lastY -at double -dv $pos[1] $object;
addAttr -ln lastZ -at double -dv $pos[2] $object;
// ha a sebesség ki volt választva, akkor létrehozzuk a megfelelo sebesség atribútumokat
string $velocityExpression = "";
if (`checkBoxGrp -q -v1 faceForwardAddVelocity`)
{
// kiszámítjuk hogy egy frame alatt mennyi ido telik el
float $secondsPerFrame;
switch((string)`currentUnit -q -t`)
{
case "hour":
$secondsPerFrame = 3600;
break;
case "min":
$secondsPerFrame = 60;
break;
case "sec":
$secondsPerFrame = 1;
break;
case "millisec":
$secondsPerFrame = 1.0 / 1000;
break;
case "game":
$secondsPerFrame = 1.0 / 15;
break;
case "film":
$secondsPerFrame = 1.0 / 24;
break;
case "pal":
$secondsPerFrame = 1.0 / 25;
break;
case "ntsc":
$secondsPerFrame = 1.0 / 30;
break;
case "show":
$secondsPerFrame = 1.0 / 48;
break;
default:
$secondsPerFrame = 1.0 / 24;
break;
}
addAttr -ln velocityX -at double $object;
addAttr -ln velocityY -at double $object;
addAttr -ln velocityZ -at double $object;
setAttr -keyable on ($object + ".velocityX");
setAttr -keyable on ($object + ".velocityY");
setAttr -keyable on ($object + ".velocityZ");
// létrehozzuk a sebesség kifejezést
$velocityExpression =
"velocityX = ($positionX - lastX) / " + $secondsPerFrame + ";\n" +
"velocityY = ($positionY - lastY) / " + $secondsPerFrame + ";\n" +
"velocityZ = ($positionZ - lastZ) / " + $secondsPerFrame + ";\n" +
"\n";
}
// az elore-nézést is kifejezés (expression) segítségével állítjuk be
// a kifejezés is lényegében egy mel scriptet tartalmaz.
expression -s (
"float $positionX = translateX - transMinusRotatePivotX;\n" +
"float $positionY = translateY - transMinusRotatePivotY;\n" +
"float $positionZ = translateZ - transMinusRotatePivotZ;\n" +
"if (! faceForward)\n" +
"{\n" +
" lastX = $positionX;\n" +
" lastY = $positionY;\n" +
" lastZ = $positionZ;\n" +
"}\n" +
$locator + ".tx = lastX;\n" +
$locator + ".ty = lastY;\n" +
$locator + ".tz = lastZ;\n" +
"\n" + $velocityExpression +
"lastX = $positionX;\n" +
"lastY = $positionY;\n" +
"lastZ = $positionZ;\n"
) -o $object -name ($name + "FaceForwardExpr") -ae 0 -uc all;
}
global proc makeAllFaceForward()
{
waitCursor -state on;
string $objects[] = `ls -l -sl`;
string $object;
// az összes kiválasztott objektumra meghívjuk a irányba állító fv.-t
for ($object in $objects)
makeFaceForward($object);
// visszaállítjuk a kiválasztást
select -r $objects;
waitCursor -state off;
}
// ez a függvény hozza létre szükség esetén az ablakot ahol beálíthatjuk a paramétereket.
global proc faceForward()
{
waitCursor -state on;
string $faceForwardWindow = "faceForwardWindow";
if (!`window -exists $faceForwardWindow`)
buildFaceForwardWindow($faceForwardWindow);
showWindow $faceForwardWindow;
waitCursor -state off;
}