In reply to:
// Jesse Carlson
// seven6ty@hotmail.com
//
// jcFlipBlends script tested with Maya 6.0 (PC).
// Copyright © 3-01-2005
//
// Thanks for help and contributions along the way: John Homer (from CGTalk, for help
// with setting the wrap deformer options), David Keegan (for initially explaining the
// concept behind this script to me a while ago, Jooja (from www.highend3d.com, for
// suggesting use of "DeleteHistory" on objects).
// Procedure flipName is used to virtually change the name of an influence object,
// from "left" to "right". A number of left/right labelling methods are taken
// into consideration.
proc string flipName(string $OBJ)
{
string $replacement = $OBJ;
if (gmatch $OBJ "L\_*"
)
$replacement = substitute "L\_" $OBJ "R\_"
;
else if (gmatch $OBJ "l\_*"
)
$replacement = substitute "l\_" $OBJ "r\_"
;
else if (gmatch $OBJ "left*"
)
$replacement = substitute "left" $OBJ "right"
;
else if (gmatch $OBJ "Left*"
)
$replacement = substitute "Left" $OBJ "Right"
;
else if (gmatch $OBJ "lt*"
)
$replacement = substitute "lt" $OBJ "lt"
;
else if (gmatch $OBJ "Lt*"
)
$replacement = substitute "Lt" $OBJ "Rt"
;
else if (gmatch $OBJ "\_L\_*"
)
$replacement = substitute "\_L\_" $OBJ "\_R\_"
;
else if (gmatch $OBJ "R\_*"
)
$replacement = substitute "R\_" $OBJ "L\_"
;
else if (gmatch $OBJ "l\_*"
)
$replacement = substitute "l\_" $OBJ "r\_"
;
else if (gmatch $OBJ "right*"
)
$replacement = substitute "right" $OBJ "left"
;
else if (gmatch $OBJ "Right*"
)
$replacement = substitute "Right" $OBJ "Left"
;
else if (gmatch $OBJ "rt*"
)
$replacement = substitute "rt" $OBJ "lt"
;
else if (gmatch $OBJ "Rt*"
)
$replacement = substitute "Rt" $OBJ "Lt"
;
else if (gmatch $OBJ "\_R\_*"
)
$replacement = substitute "\_R\_" $OBJ "\_L\_"
;
return($replacement);
}
// Procedure jcFlipBlends is the main procedure call used for this script. First,
// the user must select the base shape, then select whatever number of blendshape
// targets. Simply run the script, like this "jcFlipBlends("X", 1, "Head_BLNDs");".
// Where "X", is the axis to flip the symmetrical shapes over. "1", or "true", will
// tell the procedure to automatically add all mirrored blend targets to a new blendshape,
// name with the string that is called next by the procedure, in this case "Head_BLNDs".
// Otherwise, if false or 0, it will simply create all the new blends and leave them
// selected.
// Also, this procedure will automatically add the newly created flipped blendShape to the
// same layer that the original targe object is on. Lastly, this script organizes all of
// newly created blendshapes alphabetically, and groups left and right shapes together.
// Ex: The order of the blendshapes in your blendshape window when created, would be
// something like: "L_BrowUp, R_BrowUp, L_LipRoll, R_LipRoll, L_Smile, R_Smile,
// L_Smirk, R_Smirk". Or, if you choose not to create a blendshape automatically with
// these new shapes at the end, the new shapes are selected in this same order, in case
// you want to make the blend right away yourself.
// It took me about 2 to 3 minutes to duplicate 13 blendShapes on a 10,000 vert/face
// character, with a 3.01 gig P4 chip and a gig of ram. Also, your character must be
// completely symmetrical (the same on both sides for this procedure to work correctly.
// ENJOY!
global proc jcFlipBlends(string $axis, int $addBlend, string $blendName)
{
// Selection section:
// __________________
// select base mesh and blend mesh.
string $selected[] = ls -sl
;
if (!size $selected
)
error ("Nothing has been selected.");
int $selSize = size $selected
;
string $baseMesh = $selected[0];
string $blendShapes[];
for ($i=1; $i<($selSize); $i++)
{
$blendShapes[size $blendShapes
] = $selected[($i)];
}
int $blendSize = size $blendShapes
;
// Define some Vars:
// _________________
// Names:
string $blendName_temp = "temp_BLNDs";
string $wrapMesh = ($baseMesh + "_wrap");
string $wrapBlendName = ($blendName_temp + "_wrap");
string $baseDup = ($baseMesh + "_dup");
int $whatever;
// Arrays:
string $flippedBlends[], $flippedBlends_final[];
// Define $flippedBlends[]:
for ($whatever=0; $whatever<$blendSize; $whatever++)
{
$flippedBlends[$whatever] = (`flipName($blendShapes[$whatever])` + "_wrap");
}
// Duplication section:
// ___________________
// Duplicate and flip the base mesh. This will be used as a wrap deformer on the
// original geometry soon:
duplicate -n $wrapMesh $baseMesh;
setAttr -l off ($wrapMesh + ".scaleX");
setAttr -l off ($wrapMesh + ".scaleY");
setAttr -l off ($wrapMesh + ".scaleZ");
switch($axis)
{
case "X":
scale -r -1 1 1 $wrapMesh;
break;
case "Y":
scale -r 1 -1 1 $wrapMesh;
break;
case "Z":
scale -r 1 1 -1 $wrapMesh;
break;
}
// Create all the negatively scaled blendShape dups and move them to the origin:
for ($whatever=0; $whatever<$blendSize; $whatever++)
{
duplicate -n $flippedBlends[$whatever] $blendShapes[$whatever];
switch($axis)
{
case "X":
scale -r -1 1 1 $flippedBlends[$whatever];
break;
case "Y":
scale -r 1 -1 1 $flippedBlends[$whatever];
break;
case "Z":
scale -r 1 1 -1 $flippedBlends[$whatever];
break;
}
move -ws 0 0 0 $flippedBlends[$whatever];
}
// Duplicate and move into position, the original mesh to be used as the new blendShape:
duplicate -n $baseDup $baseMesh;
// BlendShape creation section:
// ____________________________
// Delete history:
select -r $wrapMesh $flippedBlends $blendShapes $baseDup;
DeleteHistory;
select -r $flippedBlends $wrapMesh;
blendShape -foc -n $wrapBlendName;
// Wrap Deformer Section:
// ______________________
// Create warp deformer, $wrapMesh, for the object $baseDup:
select -r $baseDup $wrapMesh;
string $wrapName[] = doWrapArgList "2" { "1", "0", "0.05"}
;
string $wrapBase = ($wrapMesh + "Base");
// Duplicate wrap deformer blend shape objects:
// ____________________________________________
// Create the final blendShapes using the wrap deformer's various blendshapes:
for ($whatever=0; $whatever<$blendSize; $whatever++)
{
// Set blend to 1.
setAttr ($wrapBlendName + "." + $flippedBlends[$whatever]) 1.0;
// Duplicate and move new blend into it's new position:
$flippedBlends_final[$whatever] = flipName($blendShapes[$whatever])
;
duplicate -n $flippedBlends_final[$whatever] $baseDup;
setAttr -l off ($flippedBlends_final[$whatever] + ".translateX");
setAttr -l off ($flippedBlends_final[$whatever] + ".translateY");
setAttr -l off ($flippedBlends_final[$whatever] + ".translateZ");
// Find position to move $flippedBlend_final to:
vector $loc = xform -q -a -t $blendShapes[$whatever]
;
vector $newLoc;
switch($axis)
{
case "X":
float $x = -($loc.x);
$newLoc = <>;
break;
case "Y":
float $y = -($loc.y);
$newLoc = <>;
break;
case "Z":
float $z = -($loc.z);
$newLoc = <>;
break;
}
// Move the finished flipped blendshape onto the opposite side of the axis as the original:
move -r -ws ($newLoc.x) ($newLoc.y) ($newLoc.z) $flippedBlends_final[$whatever];
// Set blend to 0.
setAttr ($wrapBlendName + "." + $flippedBlends[$whatever]) 0.0;
// Add the new blends to the same layer that the original blend shape resides on:
string $blendsLayer = objectLayer $blendShapes[$whatever]
;
select -r $flippedBlends_final[$whatever];
layerEditorAddObjects $blendsLayer;
}
// Parent all new blends under the previous blendshapes' group:
select -r $blendShapes[0];
string $parent[] = pickWalk -d up
;
if (size $parent
)
parent $flippedBlends_final $parent[0];
// Cleanup:
// ________
// Delete remaining temp shapes:
delete $wrapName $wrapBlendName $flippedBlends $wrapMesh $baseDup $wrapBase;
// Organize selection order of all shapes, to make a cleaner blendshape organization when created:
select -r $flippedBlends_final $blendShapes;
string $newSel[] = sort (ls -sl
);
int $newSelSize = size $newSel
;
select -cl;
for ($whatever=0; $whatever<($newSelSize/2); $whatever++)
{
select -tgl $newSel[$whatever];
select -tgl $newSel[($whatever + ($newSelSize/2))];
}
// Create the new blendshapes, if $addBlends = true:
if ($addBlend == true)
{
select -tgl $baseMesh;
blendShape -foc -n $blendName;
}
}