3D animation,rigging,coding, math ,fun stuff welcome !

rf_bakeBlandShapeTargets.mel

// --------------------------------------------------------------------------
// rf_.mel - MEL Script
// --------------------------------------------------------------------------
//
// DESCRIPTION:
//     Takes a geometry with blendshape node applied and extracts all the
//     targets from the base mesh. Use this in case you get a file with no targets
//     included. Or if you work on facial blendshapes and get rid of targets and
//     want to add soem later you can extract them again and build more out
//     of those.
//
// REQUIRES:
//    Selection of the blendshape node . Either channel box or Hypergraph.
//    The function takes a simple arg of how far from the main geometry you
//  want the targets to sit. So if i am working real  life units i would :
//  rf_bakeBlendShapeTargets(40) - as 40cm in +X from the main mesh.
//
// USAGE:
//    source "rf_bakeBlendShapeTargets.mel" rf_bakeBlandShpaeTargets(arg - distance);
//
// AUTHORS:
//    Rick Fronek - TD at Perspective Studios
//                        http://specialfx3d.blogspot.com
//                           www.perspectivestudios.com
//
//    Copyright ©2006 Rick Fronek - All Rights Reserved.
//
// VERSIONS:
//    1.00 - March 25, 2008 - Initial Release.
//
// --------------------------------------------------------------------------


global proc rf_unlockTransAttrs()
{
  string $sel[] = `ls -sl`;
  string $lockedAttrs[] = `listAttr -locked $sel[0]`;
      for($b in $lockedAttrs)
        {
         setAttr -lock 0 ($sel[0] + "." + $b);
        }
}  // End of proc

//---------------------------------------------------------------------------------------------------

global proc string rf_getNameOfBaseGeo()
{
  string $headName = "";
  string $selection[] = `ls -sl`;
  if(size($selection) == 0) error("No BS node seleted, please select BS node.");
      // Get the shape of the selection and compare it with the selection
      if(`nodeType $selection[0]` != "blendShape") error("Please select the BS node.");
          // otherwise do this...
             $headName = $selection[1];
             return $headName;
}  // End of function

//---------------------------------------------------------------------------------------------------

// A function that takes a selected blend shape node and returns its name
// which is then passed to another function for futher work.
// You must select the BS node. Easy way to do it is to select the mesh
// the blendshape is applied to and click on it in the channel box
// That's important for this function to run properly.
global proc string[] rf_findBS()
{
  string $blendShape[];
  string $bsArray[];   // Needed to store the bs node and return a single node
  string $allObjects[] = `ls -type "blendShape"`;
  //error check
      if(size($allObjects) == 0) error("Please select mesh with BS applied.");
                for($n in $allObjects)
          {
            $bsArray[size($bsArray)] = $n;
            $blendShape = $bsArray;
           }

  // return the shapes
   return $blendShape;
}

//---------------------------------------------------------------------------------------------------

// This is the CORE function that goes through all the weights on the blendshape
// node returned from function named rf_findBS().
// The goal is to reset the BS node to 0 ,take the weight num 0 and turn it to 1
// then duplicate/bake the base mesh move it aside , reset the bs node and take
// another weight and do the same to it. Until all the weights are baked and you
// end up with extracting all the BS weights = targets.
global proc rf_bakeBlendShapeTargets(int $iDistance)
{
  string $blendShapeNode[] = `rf_findBS`;
  string $BSmeshNode = `rf_getNameOfBaseGeo`;
// Take a single blendShape node from the array that gets the blenshapes
  string $bsNode = $blendShapeNode[0];
  // To get the multi attributes use the listAttr -multi flag to get the names and index
  // string $wts[]=`listAttr -m controller_morph_Head.w`;
  // This is my way of getting the values only in a float array and iterate through them
  float $targets[] = `getAttr ($bsNode + ".weight")`;
      for($x=0;$x
      {
        setAttr($bsNode + ".weight" + "[" + $x + "]") 0;   // set the BS to 0 first to make sure its reseted
        setAttr($bsNode + ".weight" + "[" + $x + "]") 1;
        select -r $BSmeshNode;
        duplicate -rr;
        rf_unlockTransAttrs();
        move -x $iDistance;
        select -r $bsNode;
        setAttr($bsNode + ".weight" + "[" + $x + "]") 0;
       }

}