Tuesday, November 26, 2013

Seamless Ik/Fk Switch


The Process of how this Ik/Fk works is that there are six locators setup in the rig that the script will take the information of the locators and apply them to the controls.  

Setup

To set up the Seamless Switch, you must first create a normal Ik/Fk Switch.
The elbow joints in the main skeleton and the contorller joints have all the translation, rotation, and scale locked except for the Y rotate.  So the arm bends like a real arm.


Fk Locators:
 
The Fk locators are set up just like the Fk controls.  There are three locators: one in the hand, one in the elbow, and one in the shoulder.  The hand is parented to the elbow and the elbow is parented to the shoulder.  Then each of the locators are orient constrained to the Ik control joints.  This way the locators have the right orientation when switching from Ik to Fk.

Ik Locators:

The Ik locators are a little more tricky.  There are three locators.  The first one is located in the Fk Hand Controller Joint.  This locator is then Parent constrained to the Fk Hand Controller Joint.  That one will be for the Ik handle control. 
The other two are for the Elbow control.  The first one with be parented in the Fk Control Joints.  What you do is you put the locator on top of the shoulder joint.  You then parent the locator to the Fk Shoulder Control Joint.  If you zero out the rotation of the locator it will then be pointing down the joint chain.  slide the locator down the joint chain and place it on top of the Elbow joint.  Then move it back so that it sits where the Elbow Control will be located.  This locator will now move wherever the Fk Shoulder Control Joint moves and since we locked all the movements of the Elbow joints, the arm will always be level with the locator.  The last locator will not be parented to anything.  You will place this locator on top of the Locator that is parented to the shoulder joint.  You will then zero out the locator and then point constrain it to the Locator its on top of.  This way the second locator will have the translate information you need for the Elbow control when you switch from Fk to Ik.


Script Setup:

I set up the script as a global proc, then set that global proc in a seperate button so the animator can use the Ik/Fk switch normally then when they want to use the seamless setup it will work at any time.

Seamless Switch Global Proc:
This scrip is for just the left arm.  You will have to setup a second one for the right arm.
The scrip also checks if there are any keys on the Ik Hand Control or the Fk Shoulder Control.  If there are keys then it will key the switch so the animator doesnt have to.

global proc L_IkFkArmScripts ()

{
    int $L_IkFkSwitchCheck = `getAttr L_IkFkSwitchCTL.IkFkSwitch`;
    int $i;
    select -r  L_IkFkSwitchCTL.IkFkSwitch;
    $StepCurvsObj = `ls -sl`;
    select -cl  ;
    int $time = `currentTime -q`;
    int $time2 = ($time - 1);
    int $keys1 = `selectKey  L_ShoulderFkCTL` ;
    int $keys2 = `selectKey L_HandIkCTL`;
   


    if ($L_IkFkSwitchCheck == 1) {//Ik
        if ($keys1 > 0 || $keys2 > 0){
            setKeyframe -v 1 -t $time2 {"L_IkFkSwitchCTL"};
            setKeyframe -t $time2 {"L_ShoulderFkCTL"};
            setKeyframe -t $time2 {"L_ArmFkCTL"};
            setKeyframe -t $time2 {"L_HandFkCTL"};
        }
        float $IkHandRot[] = `xform -q -ro L_IkHandParent`;
        setAttr L_HandIkCTL.rotateX $IkHandRot[0];
        setAttr L_HandIkCTL.rotateY $IkHandRot[1];
        setAttr L_HandIkCTL.rotateZ $IkHandRot[2];
        float $IkHandTran[] = `xform -q -t L_IkHandParent`;
        setAttr L_HandIkCTL.translateX $IkHandTran[0];
        setAttr L_HandIkCTL.translateY $IkHandTran[1];
        setAttr L_HandIkCTL.translateZ $IkHandTran[2];
        float $IkElbowTran[] = `xform -q -t L_ElbowTran`;
        setAttr L_ElbowIkCTL.translateX $IkElbowTran[0];
        setAttr L_ElbowIkCTL.translateY $IkElbowTran[1];
        setAttr L_ElbowIkCTL.translateZ $IkElbowTran[2];
        //Switch Ik to Fk
        setAttr L_IkFkSwitchCTL.IkFkSwitch 0;
        if ($keys1 > 0 || $keys2 > 0){
            setKeyframe -v 0 -t $time {"L_IkFkSwitchCTL"};
            setKeyframe -t $time {"L_HandIkCTL"};
            setKeyframe -t $time {"L_ElbowIkCTL"};
        }
    }

    else if ($L_IkFkSwitchCheck == 0) {//Ik
            //Key the frame before
        if ($keys1 > 0 || $keys2 > 0){
            setKeyframe -v 0 -t $time2 {"L_IkFkSwitchCTL"};
            setKeyframe -t $time2 {"L_HandIkCTL"};
            setKeyframe -t $time2 {"L_ElbowIkCTL"};
        }
        // Shoulder
        float $FkShoulder[] = `xform -q -ro L_FkShoudlerRot`;
        setAttr L_ShoulderFkCTL.rotateX $FkShoulder[0];
        setAttr L_ShoulderFkCTL.rotateY $FkShoulder[1];
        setAttr L_ShoulderFkCTL.rotateZ $FkShoulder[2];
        //Arm
        float $FkElbow[] = `xform -q -ro L_FkArmRot`;
        setAttr L_ArmFkCTL.rotateY $FkElbow[1];
        //Hand
        float $FkHand[] = `xform -q -ro L_FkHandRot`;
        setAttr L_HandFkCTL.rotateX $FkHand[0];
        setAttr L_HandFkCTL.rotateY $FkHand[1];
        setAttr L_HandFkCTL.rotateZ $FkHand[2];
        //Switch Ik to Fk
        setAttr L_IkFkSwitchCTL.IkFkSwitch 1;
        if ($keys1 > 0 || $keys2 > 0){
            setKeyframe -v 1 -t $time {"L_IkFkSwitchCTL"};
            setKeyframe -t $time {"L_ShoulderFkCTL"};
            setKeyframe -t $time {"L_ArmFkCTL"};
            setKeyframe -t $time {"L_HandFkCTL"};
        }
    }

}



The Button has the script to create the Ik/Fk Switch window.

global proc L_IkFkSwitchButton ()

{
string $window = `window -title "IkFk Switch" -widthHeight 410 25`;
     rowLayout
          -numberOfColumns 2
          -columnWidth2 120 120
          -columnAlign2 "center" "center";

     button -l "L_IkFkSwitch" -c L_IkFkArmScripts -w 200;
     button -l "R_IkFkSwitch" -c R_IkFkArmScripts -w 200;
showWindow $window;
}


Each of the buttons calls the scripts above to seamlessly switch between Ik and Fk.

The rig still works normally without this script.  This system is there just in case the animator want to seamlessly switch in the middle of the animation.