Thursday, June 20, 2013

Tip Animate Poses At Fixed Frame Numbers

Happy Thursday!

Here I basically wanted to talk about one way that i've found really helpful to save poses while face rigging. It doesn't require making a complex user interface ... Basically it goes simply by figuring out what command needs to be run to move all the selected animator controls to where they are currently.

The code snippet below may look a little complicated but basically it goes off of something like this please note this isn't code here.

Say we selected some anim controls browUp and lipSmile, its got some keyable attributes on it lets say translateZ for both. So if we have a command that can tell us

setAttr browUp.translateZ 5 setAttr lipSmile.translateZ 3 were done we've got our pose.

Now we can call this whole string type thing as a pose and make a string attribute for it say
"happy". Say we made some other poses, "happy","pout","grumpy".

Then we can write a function that sets a keyframe for all animator controls at fixed frames.
Say happy should be on at frame 10 up to frame 15. Pout should be on from frame 25 to frame 30.
Here below i call this delay of 5 frames and between of 10 frames.

In the code the important thing is that its really using MEL's eval on a string that can make us get our pose.

Here is some of the code for animating pose. In an earlier post I talked a little about the eval.

Hope this is helpful.


//float $delay = 5;//CHANGE how much should pose be held in frames
//float $between = 10; //CHANGE number frames to reach pose, make it longer for slower pose transition
//float $startFrame = 10; //CHANGE what frame should we begin

global proc na_previewPose(string $poseObj, string $poseAttr[], float $delay, float $between, float $startFrame ){
    //float $delay = 5;//CHANGE how much should pose be held in frames
    //float $between = 10; //CHANGE number frames to reach pose, make it longer for slower pose transition
    //float $startFrame = 10; //CHANGE what frame should we begin

    string $anim[] = {};
    $anim =`ls -sl`;
    if(size($anim) == 0){error("Requires Animator Controls Selected\n");}

    float $frameA = $startFrame;
    float $frameB = $startFrame + $delay;
    for($i = 0; $i < size($poseAttr);  $i++){
        string $attr = $poseObj+"."+$poseAttr[$i];
        if( `objExists $attr`)
            //$tempA = $frameA;
            $tempB = $frameB;
            print("pose "+($i+1)+" at "+ $frameA + "," + $frameB +"\n");
            //key pose
            currentTime $frameA;
            select -r $anim;
            currentTime $frameB;
            select -r $anim;
            //update frames
            $frameA = $tempB + $between;
            $frameB = $frameA + $delay;
print("First source naAnimate posePrintCommand icon ... See na_evalSetAttr for any questions !!!\n");
print("Select all Animator controls then\n Type na_previewPose( pose object, pose array, 5 delay f, 10 between f ,10 start f) )\n");
//-------- eval on string type of command for saving face rig pose
//--this will run something like eval(`getAttr object.attr`) but it will not error out if an object is missing
//getAttr object.attr --- gives a string of form ex: "setAttr browLeft_anim.visibility 1; setAttr browLeft_anim.translateX 0.1362689445;"
global proc na_evalSetAttr(string $obj, string $attr){
 string $arg = `getAttr ($obj+"."+$attr)`;
 string $all[] = stringToStringArray($arg,";");
 python("import re");
 string $condition[]={};//for ignoring if locked

 for($cmd in $all){
 string $obj = "";

 $obj = python("'setAttr')+'(.*)'+re.escape(' '),'"+$cmd+"'.strip() ).group(1)");//ex: browLeft_anim.translateX
 //ignore if locked
 $condition = {};
     if(`objExists $obj`){$condition = `listAttr -u $obj`;}
 if(`objExists $obj` && (size($condition)==1) ){eval($cmd+";");}else{print($obj+" :NOT FOUND or LOCKED--Skipping!!!\n");}
print("Run:-- na_evalSetAttr(poses transform string, and its pose attribute string ) --ex:\n na_evalSetAttr(\"poses\",\"smile\")\n");

//------ code for getting the pose from selected animator control
//-------assumes all animator controls selected on scene 
global proc string na_getPose(){
    print("[na_getPose] Start Computing Pose….\n");
    string $cmd = "";
    string $sel[] = `ls -sl`;
    if(size($sel)==0){error("Requires Animator Controls Selected First !!!\n");}
    string $attr[] = {};
    for($obj in $sel){
        $attr = {};
        $attr = `listAttr -k -u $obj`;
        //visibility translateX translateZ
        //visibility translateX translateZ
        //visibility translateX translateY translateZ rotateX rotateY rotateZ scaleX scaleY scaleZ
        //rotateX rotateY rotateZ mouthUp
        //print( stringArrayToString($attr," ") );
        $cmd += ""+na_getSinglePose($obj, stringArrayToString($attr," ") );
    print("[na_getPose] Completed Computing Pose !!!\n");
    print $cmd;
    return $cmd;

//result ex: "setAttr jaw_anim.rotateX 0; setAttr jaw_anim.rotateY 0; setAttr jaw_anim.rotateZ -11.81234478"
//obj   --  the object ex: "jaw_anim" 
//attr  --  the attributes space separated ex: "rotateX rotateY rotateZ"

global proc string na_getSinglePose(string $obj, string $attr){
    //print("[na_getSinglePose] Computing current pose ….\n");
    //string $obj = "jaw_anim";
    //string $attr = "rotateX rotateY rotateZ";
    string $result = "";
    string $attrAr[] = stringToStringArray($attr," ");
    string $cmdAr[] = {};
    for($attr in $attrAr)
        $cmd = "";
        float $arg;
        $arg = getAttr ($obj + "." + $attr);
        $cmd = "setAttr "+($obj + "." + $attr) + " "+$arg;
        $cmdAr[size($cmdAr)] = $cmd;
    //print(stringArrayToString($cmdAr,"; "));
    $result = stringArrayToString($cmdAr,"; ");
    $result += ";";
    return $result;