Optional Variables in MEL
My biggest problem with MEL Script is that once I’ve written a function and released it I can’t add any new variables to it. This is an issue when you’re writing rig tools that are used across multiple studios and projects, and then an animator asks for a new addition to the rig.
So late last year I had this idea. What if every function I wrote had an extra input variable, a string that could contain any optional flag, which I can use to add extra options to a procedure without breaking existing uses of it? Inside the function I could specify all my default values, that get replaced if it finds a different value in the string.
I decided that I’m not likely to ever use tilde (~) so I’m using it to identify flags. (Maya’s own functions use the minus symbol, but it’s also used for negative numeric values, so I wanted something I’d never use)
// Create Cube Function has two input strings: name, and optional flags ;
createCube( “testCube” , “~visible 0 ~scale 2” ) ;
I figured I couldn’t be the only person to think of using a string to contain multiple optional flags. After a bit of googling I found a few people talking about the same idea, and I discovered ZooTools is doing the same thing, but instead of returning a single string, it returns a string array, which is a bit nicer than the single string because you don’t have to convert it into an array afterwards. So I added that this afternoon.
Example code:
global proc string[] FlagValue ( string $flag , string $string )
{
string $allFlags[] ;
// find all flags in string
int $tokens = `tokenize $string “~” $allFlags` ;
for( $i = 0 ; $i < $tokens ; $i++ )
{
// find all values for each flag
string $buffer[] = {};
int $num = `tokenize $allFlags[$i] ” ” $buffer` ;
// if found desired flag, spit it into an array
if( $buffer[0] == $flag )
{
string $values[] ;
for( $v = 1 ; $v < $num ; $v++ )
{
$values[ size( $values ) ] = $buffer[$v] ;
}
print $values ;
return $values ;
}
}
return {} ;
}
global proc createCube ( string $name , string $flags )
{
//////////////////////
// Variables
//////////////////////
// defaults
int $visible = 1 ;
float $scale[] = { 1 , 1 , 1 } ;
// Search $flags string for a match
string $temp[] ;
$temp = FlagValue( “visible” , $flags ) ; if ( size($temp) > 0 ) $visible = (int)$temp[0] ;
$temp = FlagValue( “scale” , $flags ) ;
if ( size($temp) > 0 ) $scale = { (float)$temp[0] , (float)$temp[1] , (float)$temp[2] } ;
////////////////////////
// Create poly Cube
////////////////////////
string $cube[] = `polyCube -name $name` ;
setAttr ( $cube[0] + “.visibility” ) $visible ;
scale -r $scale[0] $scale[1] $scale[2] $cube[0] ;
}
createCube( “testCube” , “~visible 0 ~scale 2 1 5” ) ;