//////////////////////////////////////// // SetExps.mel: generate most sizing expressions //////////////////////////////////////// source deformExps; // deformer expressions source centerFeet; source defpose; global float $g_minMult; $g_minMult = .5; // min for attribute values global float $g_maxMult; $g_maxMult = 2; // min for attribute values // list of names of "joints" which correspond to bones // the appended "=WLD" correlates Width/Length/Depth with global "XYZ" axes global string $g_joints[]; $g_joints = { "humanoidRoot=WLD", "sacroiliac=WLD", "l_hip=WLD", "r_hip=WLD", "l_knee=WLD", "r_knee=WLD", "l_ankle=WDL", "r_ankle=WDL", "l_midtarsal=WDL", "r_midtarsal=WDL", "vl5=WLD", "skullbase=WLD", "l_shoulder=LWD", "r_shoulder=LWD", "l_elbow=LWD", "r_elbow=LWD", "l_wrist=LDW", "r_wrist=LDW" }; // part hierarchy global string $g_parts[]; $g_parts = { "l_arm:l_shoulder,l_elbow", "r_arm:r_shoulder,r_elbow", "l_leg:l_hip,l_knee", "r_leg:r_hip,r_knee", "feet:l_ankle,l_midtarsal,r_ankle,r_midtarsal", "calves:l_knee,r_knee", "thighs:l_hip,r_hip", "hands:l_wrist,r_wrist", "forearms:l_elbow,r_elbow", "upperarms:l_shoulder,r_shoulder", "trunk:humanoidRoot,sacroiliac,vl5", "legs:l_leg,r_leg", "arms:l_arm,r_arm", "limbs:arms,legs" }; // high level attributes // format -> HL_attr_name : : // limits is optional, defaults to .5@1@2 if not given // sub_attributes -> "," sep list of .; // if no dim or indiv limits given, periods optional // attr_limits is optional also // sub_att_name -> HL_attr, part, or joint name // dimension -> optional dimension such as W, D, T, or L // if not given, scale W, D, and L // limits -> Format: @@ global string $g_HLattributes[]; $g_HLattributes = { "weight:trunk.T,legs.T,arms.T", "height:trunk.L,legs.L,arms.L:.5@1@1.5", "muscle:upperarms.T,thighs.T,calves.T;.66@1@1.33,vl5.D,sacroiliac.T;.66@1@1,humanoidRoot.T;.66@1@1,vl5.W,forearms.T;.66@1@1.33:.66@1@1.5", "age:skullbase;.5@1@1,legs,chestSize;-1@0@0,feet,trunk;.4@1@1,arms,hands:.33@1@1", "gender:pelvicTilt;.4@0@-.2,muscle,vl5.W,hairSides;.25@0@-.25,hairBack;.25@0@-.5,chestSize;.25@0@-.5,height,humanoidRoot.W;.7@1@1,sacroiliac.T;1.35@1@1,feet,hands:.91@1@1.1" }; //////////////////////////////////////// proc show(string $str, string $val) { print($str + "=" + $val + "\n"); } //////////////////////////////////////// // deletes all expression nodes global proc deleteExps() { string $exps[] = `ls "*_exp"`; string $exp; for ($exp in $exps) { delete $exp; } } //////////////////////////////////////// proc string getAxisFromDimension(string $dimension, string $segName) { global string $g_joints[]; string $item; string $tokens[]; for ($item in $g_joints) { tokenize($item, "=", $tokens); string $sn = $tokens[0]; if(strcmp($segName, $sn)==0) { string $orient = $tokens[1]; if(strcmp($dimension, substring($orient,1,1))==0) { return "X"; } if(strcmp($dimension, substring($orient,2,2))==0) { return "Y"; } if(strcmp($dimension, substring($orient,3,3))==0) { return "Z"; } } } return ""; } //////////////////////////////////////// // adds a part size attribute to Humanoid node proc createPartSizeAttribute(string $attributeName, string $dimension) { global float $g_minMult; global float $g_maxMult; string $exp = "addAttr -ln " + $attributeName + "Size" + $dimension + " -at double -min 0 -dv 0.5 -max 1 humanoid_1;"; //print($exp+"\n"); eval($exp); $exp = "setAttr -e -keyable true humanoid_1." +$attributeName + "Size" + $dimension + ";"; //print($exp+"\n"); eval($exp); } //////////////////////////////////////// // given inVal in [inLo..inDef..inHi] with inDef mapping to outDef, // map the inVal into [outLo..outDef..outHi] // return value between lo and hi, centered at one global proc float attrFunc(float $inVal, float $inLo, float $inDef, float $inHi, float $outLo, float $outDef, float $outHi) { float $outVal; if($inVal < $inDef) { float $inR = $inDef - $inLo; float $outR = $outDef - $outLo; float $inT = ($inR!=0) ? ($inVal - $inLo) / $inR : 0; $outVal = $inT * $outR + $outLo; } else { float $inR = $inHi - $inDef; float $outR = $outHi - $outDef; float $inT = ($inR!=0) ? ($inVal - $inDef) / $inR : 0; $outVal = $inT * $outR + $outDef; } return $outVal; } //////////////////////////////////////// // appends an attribute multiplier to the size attribute of a joint's exp proc appendToSizeExpression(string $jntName, string $attributeName, string $dimension) { //print("appendToSizeExpression("+$jntName+", "+$attributeName+", "+ //$dimension+");\n"); string $axis = getAxisFromDimension($dimension, $jntName); string $expNode = $jntName+"_S"+$axis+"_exp"; string $subat = $expNode + ".expression"; //print("$subat="+$subat+"\n"); string $exp = getAttr($subat); int $esize = size($exp); $exp = substring($exp,1,($esize-1)); //show("exp1=",$exp); global float $g_minMult; global float $g_maxMult; $exp += " * attrFunc(humanoid_1." + $attributeName + $dimension + ", 0, 0.5, 1, "+$g_minMult+", 1, "+$g_maxMult+")"; //show("exp2=",$exp); if((strcmp($dimension, "W")==0) || (strcmp($dimension, "D")==0)) { $exp += " * attrFunc(humanoid_1." + $attributeName + "T" + ", 0, 0.5, 1, "+$g_minMult+", 1, "+$g_maxMult+")"; } $exp += " * attrFunc(humanoid_1." + $attributeName + ", 0, 0.5, 1, "+$g_minMult+", 1, "+$g_maxMult+")"; $exp += ";"; //show("exp3=",$exp); select -r $expNode; string $cmd = "expression -e -s \"" + $exp + "\";"; //print($cmd+"\n"); eval($cmd); } //////////////////////////////////////// // determines whether given partName is a base joint by searching LHSides // of parts list proc int partIsaJoint(string $partName) { global string $g_parts[]; string $tokens[]; string $partLine; for($partLine in $g_parts) { tokenize($partLine, ":", $tokens); string $nextPart = $tokens[0]; if(strcmp($nextPart, $partName)==0) { return 0; } } return 1; } //////////////////////////////////////// // appends Size multipliers for each part defined in g_parts to // the appropriate joints' sizing expressions proc adjustPartSizeExpressions(string $partName, string $attributeName) { //print("adjustPartSizeExpressions for "+$partName+"\n"); global string $g_parts[]; string $tokens[]; string $partLine; for($partLine in $g_parts) { tokenize($partLine, ":", $tokens); if(strcmp($partName, $tokens[0])==0) { string $subParts = $tokens[1]; tokenize($subParts, ",", $tokens); string $subPartName; for($subPartName in $tokens) { if(partIsaJoint($subPartName)) { //print($subPartName+" is a joint\n"); appendToSizeExpression($subPartName, $attributeName+"Size", "W"); appendToSizeExpression($subPartName, $attributeName+"Size", "L"); appendToSizeExpression($subPartName, $attributeName+"Size", "D"); } else { //print($subPartName+" is not a joint\n"); adjustPartSizeExpressions($subPartName, $attributeName); } } break; } } } //////////////////////////////////////// // create all higher level parts and controlling expressions proc makePartAttributesAndExps() { global string $g_parts[]; string $partLine; string $exp; string $tokens[]; string $partLine; for($partLine in $g_parts) { tokenize($partLine, ":", $tokens); string $partName = $tokens[0]; string $str = "select -r humanoid_1"; eval($str); createPartSizeAttribute($partName, ""); createPartSizeAttribute($partName, "T"); createPartSizeAttribute($partName, "W"); createPartSizeAttribute($partName, "L"); createPartSizeAttribute($partName, "D"); adjustPartSizeExpressions($partName, $partName); } } //////////////////////////////////////// // adds a "Size" attribute for a given axis to a given joint // also creats an expression linking joints' scale to the size attribute proc createOneSizeAttributeAndExp(string $jntName, string $dimension) { global float $g_minMult; global float $g_maxMult; string $exp = "addAttr -ln size" + $dimension + " -at double -min 0 -dv 0.5 -max 1 " + $jntName; //print($exp+"\n"); eval($exp); $exp = "setAttr -e -keyable true " + $jntName + ".size" + $dimension + ";"; //print($exp+"\n"); eval($exp); // create expressions for scaleXYZ with sizeWLD multipliers * default scale // also tack on sizeT multiplier if doing W or D dimension if((strcmp($dimension, "T")!=0) && (strcmp($dimension, "")!=0)) { string $axis = getAxisFromDimension($dimension, $jntName); //show("$axis",$axis); $jointBaseS = getAttr($jntName+".scale"+$axis); //show("$jointBaseS",$jointBaseS); // // new modified code based on this: // $exp += " * attrFunc(humanoid_1." + $attributeName + // ", 0, 0.5, 1, "+$g_minMult+", 1, "+$g_maxMult+")"; // $exp = "expression -n " + $jntName + "_S" + $axis + "_exp" + " -s \"" + $jntName + ".scale" + $axis + " = " + $jointBaseS + " * " + "attrFunc(" + $jntName + ".size" + $dimension + ", 0, 0.5, 1, "+$g_minMult+", 1, "+$g_maxMult+")"; if((strcmp($dimension, "W")==0) || (strcmp($dimension, "D")==0)) { $exp += " * attrFunc(" + $jntName + ".sizeT" + ", 0, 0.5, 1, "+$g_minMult+", 1, "+$g_maxMult+")"; } $exp += " * attrFunc(" + $jntName + ".size" + ", 0, 0.5, 1, "+$g_minMult+", 1, "+$g_maxMult+")"; $exp += ";\" -o " + $jntName + " -ae 1 -uc all;"; // ORIG CODE: // $exp = "expression -n " + $jntName + "_S" + $axis + "_exp" + // " -s \"" + $jntName + ".scale" + $axis + // " = " + $jointBaseS + // " * " + $jntName + ".size" + $dimension; // if((strcmp($dimension, "W")==0) || (strcmp($dimension, "D")==0)) { // $exp += " * " + $jntName + ".sizeT"; // } // $exp += " * " + $jntName + ".size"; // $exp += ";\" -o " + $jntName + " -ae 1 -uc all;"; //print($exp+"\n"); eval($exp); } } //////////////////////////////////////// // add SizeXYZ attributes to each joint bone // create expression in scale attribute proc makeJointSizeAttributesAndExps() { global string $g_joints[]; string $exp, $tokens[], $item; for ($item in $g_joints) { tokenize($item, "=", $tokens); string $jntName = $tokens[0]; $exp = "select -r " + $jntName; //print($exp+"\n"); eval($exp); createOneSizeAttributeAndExp($jntName, ""); createOneSizeAttributeAndExp($jntName, "T"); createOneSizeAttributeAndExp($jntName, "W"); createOneSizeAttributeAndExp($jntName, "D"); createOneSizeAttributeAndExp($jntName, "L"); } } //////////////////////////////////////// // search LHSs of joint list global proc int isaJoint(string $name) { global string $g_joints[]; string $item; string $tokens[]; for($item in $g_joints) { tokenize($item, "=", $tokens); if(strcmp($tokens[0], $name)==0) { return 1; } } return 0; } //////////////////////////////////////// // this will multiply the attribute given by multname // into the specified joint's correct axis expression proc appendHLMultToExpression(string $joint, string $multName, string $dim, float $lo, float $def, float $hi) { //print("Adding " + $multName + " to " + $joint + " with range " + $lo + ", " + $def + ", " + $hi + "\n"); string $axis = getAxisFromDimension($dim, $joint); string $expNode = $joint+"_S"+$axis+"_exp"; string $subat = $expNode + ".expression"; string $exp = getAttr($subat); int $esize = size($exp); $exp = substring($exp,1,($esize-1)); $exp += " * attrFunc(humanoid_1." + $multName + ", 0, 0.5, 1, "+$lo+", "+$def+", "+$hi+")"; // WAS: $exp += " * humanoid_1." + $multName; $exp += ";"; select -r $expNode; string $cmd = "expression -e -s \"" + $exp + "\";"; print($cmd+"\n"); eval($cmd); } //////////////////////////////////////// proc string findAttributeLineInRA(string $name, string $names[]) { string $tokens[]; string $nline; for($nline in $names) { tokenize($nline, ":", $tokens); if(strcmp($name, $tokens[0])==0) { return $nline; } } return ""; } //////////////////////////////////////// // add a high level attribute multiplier to relevant joint expressions // // $multname is the actual HL attribute we will be appending to expressions // // $attribute is the current attribute we're finding sub attributes of. // Initially it is probably a HL attribute, but in recursive calls, it will // be the sub attributes of a HL attr, or their sub-attrs. // // if $dim is given, it will be something like W, L, or T // if not given, then add attribute in all three dimensions (WLD) // // limits may be given, and they may be overwridden on a per subpart basis... // proc addHLtoExp(string $attribute, string $multName, string $dim, float $lo, float $def, float $hi) { //print("addHLtoExp("+$attribute+", "+$multName+", "+$dim+", "+$lo+", "+$def+", "+$hi+")\n"); // look for attribute in HLattr array global string $g_HLattributes[]; string $line = findAttributeLineInRA($attribute, $g_HLattributes); if(strcmp($line,"")==0) { // if didn't find, search part list //print("didn't find "+$attribute+" in HLattributes\n"); global string $g_parts[]; $line = findAttributeLineInRA($attribute, $g_parts); } if(strcmp($line,"")==0) { // if didn't find, search HL deformer list //print("didn't find "+$attribute+" in parts\n"); global string $g_deformAttrs[]; $line = findAttributeLineInRA($attribute, $g_deformAttrs); } float $doing_posture = 0; if(strcmp($line,"")==0) { // if didn't find, search HL posture list //print("didn't find "+$attribute+" in deformers\n"); global string $g_posture[]; $line = findAttributeLineInRA($attribute, $g_posture); if(strcmp($line,"")!=0) { $doing_posture = 1; } } if(strcmp($line,"")!=0) { // found a line for $attribute string $tokens[]; tokenize($line, ":", $tokens); // take apart the line string $name = $tokens[0]; string $subnamesStr = $tokens[1]; // already have limits cuz passed, so ignoring them in [2] string $subnames[]; tokenize($subnamesStr, ",", $subnames); string $item; for($item in $subnames) { // extract range info for this subattribute, if present tokenize($item, ";", $tokens); string $nameAndDim = $tokens[0]; string $range = $tokens[1]; //print("$nameAndDim="+$nameAndDim+", $range="+$range+"\n"); float $lo2=$lo; float $def2=$def; float $hi2=$hi; if(strcmp("", $range)!=0) { tokenize($range, "@", $tokens); $lo2 = $tokens[0]; $def2 = $tokens[1]; $hi2 = $tokens[2]; } //print("lo2/def2/hi2: "+$lo2+", "+$def2+", "+$hi2+"\n"); tokenize($nameAndDim, ".", $tokens); string $sn = $tokens[0]; string $subdim = $tokens[1]; if(strcmp($subdim, "")==0) { $subdim = $dim; } // hold on to it! //print("$sn="+$sn+" $subdim="+$subdim+"\n"); // if it's a joint, then append the HLAttribute to seg's expression if(isaJoint($sn) && ($doing_posture==0)) { //print("IT'S A JOINT!\n"); if(strcmp($subdim,"T")==0) { // thickness is width and depth appendHLMultToExpression($sn, $multName, "W", $lo2, $def2, $hi2); appendHLMultToExpression($sn, $multName, "D", $lo2, $def2, $hi2); } else if(strcmp($subdim,"")==0) { // size, do all dimensions appendHLMultToExpression($sn, $multName, "W", $lo2, $def2, $hi2); appendHLMultToExpression($sn, $multName, "D", $lo2, $def2, $hi2); appendHLMultToExpression($sn, $multName, "L", $lo2, $def2, $hi2); } else { appendHLMultToExpression($sn, $multName, $subdim, $lo2, $def2, $hi2); } } // if it's a base deformer, append the HLAttribute to ffd's expression else if(isaBaseDeformer($sn)) { //print("IT'S A DEFORMER!\n"); appendToDeformExp($multName, $sn, $lo2, $def2, $hi2); } // if it's a posture joint, append the HLAttribute to jnt's axis exp else if(isaPostureJnt($sn) && ($doing_posture==1)) { //print("IT'S A POSTURE!\n"); // hack together appropriate ranges for posture angles // limits1 contain posture limit %s (e.g. [-0.1..0.1]) // limits2 contain angle extremes for this particular joint float $lo3 = $def2 - (-$lo * ($def2 - $lo2)); float $def3 = $def2; float $hi3 = $def2 + ($hi * ($hi2 - $def2)); appendToPostureExp($multName, $sn, $lo3, $def3, $hi3); } // otherwise recurse... find subparts of $sn else { addHLtoExp($sn, $multName, $subdim, $lo2, $def2, $hi2); } } } else { print("didn't find "+$attribute+" in g_parts\n"); } } //////////////////////////////////////// // based on the line from the array, create/add the attribute to humanoid // call a function to append the attr to the approp joints proc createOneHLAttribute(string $attributeLine) { global string $g_parts[]; global string $g_HLattributes[]; string $tokens[]; tokenize($attributeLine, ":", $tokens); string $attributeName = $tokens[0]; string $subAttributes = $tokens[1]; string $def_limits = $tokens[2]; string $defLimit = 1; global float $g_minMult; global float $g_maxMult; float $loLimit = $g_minMult; float $hiLimit = $g_maxMult; if(strcmp($def_limits, "") != 0) { tokenize($def_limits, "@", $tokens); $loLimit = $tokens[0]; $defLimit = $tokens[1]; $hiLimit = $tokens[2]; } string $exp = "addAttr -ln " + $attributeName + " -at double -min 0 -dv 0.5 -max 1 humanoid_1;"; //print($exp+"\n"); eval($exp); $exp = "setAttr -e -keyable true humanoid_1." + $attributeName + ";"; //print($exp+"\n"); eval($exp); // doing this way instead of sending subAttributes because want // addHLtoExp to be recursive addHLtoExp($attributeName, $attributeName, "", $loLimit, $defLimit, $hiLimit); } //////////////////////////////////////// // create all high level attributes proc makeHighLevelAttributesAndExps() { global string $g_HLattributes[]; string $attributeLine; for($attributeLine in $g_HLattributes) { string $str = "select -r humanoid_1"; eval($str); createOneHLAttribute($attributeLine); } } //////////////////////////////////////// // find global translation of a joint global proc float getJointGlobalT(string $jnt, string $axis) { int $i = 0; if(strcmp($axis, "X")==0) { $i = 0; } if(strcmp($axis, "Y")==0) { $i = 1; } if(strcmp($axis, "Z")==0) { $i = 2; } float $T[] = `joint -q -position $jnt`; return $T[$i]; } //////////////////////////////////////// global proc setExps() { makeJointSizeAttributesAndExps(); makePartAttributesAndExps(); makeHighLevelAttributesAndExps(); } //////////////////////////////////////// setExps(); source centerFeet; print "done\n"; // bind skin to skeleton select -r polySurface9; select -tgl humanoidRoot; createSkinCluster "-mi 5 -dr 4"; select -r humanoid_1; //////////////////////////////////////// ////////////////////////////////////////