// =========================================================================== // Copyright 2018 Autodesk, Inc. All rights reserved. // // Use of this software is subject to the terms of the Autodesk license // agreement provided at the time of installation or download, or which // otherwise accompanies this software in either electronic or hard copy form. // =========================================================================== global proc performUpdatePoseShape(string $tpl, string $poseName, string $blendShape) { poseInterpolatorGoToPose($tpl, $poseName); // Since regularization and interpolation can make the pose weights not 1 at the pose, // set them to 0 regularization and linear interpolation so the shape can be calculated from // the proper state of the mesh. string $regularizationAttr = $tpl + ".regularization"; string $interpolationAttr = $tpl + ".interpolation"; float $regularization = `getAttr $regularizationAttr`; int $interpolation = `getAttr $interpolationAttr`; if( $regularization != 0.0 || $interpolation != 0 ) { setAttr $regularizationAttr 0.0; setAttr $interpolationAttr 0; } // Get target index from poseName int $targetIndex = -1; int $index = poseInterpolatorPoseIndex($tpl, $poseName); if ($index < 0) return; string $sPlug = $tpl + ".output[" + $index + "]"; string $connectedTargets[] = `listConnections -plugs on -source off -type "blendShape" $sPlug`; for ($target in $connectedTargets) { string $buffer[]; tokenize($target, ".", $buffer); string $node = $buffer[0]; if( $node == $blendShape ) { string $attr = $buffer[1]; string $parentAttr = $node + ".weight"; int $indices[] = `getAttr -multiIndices $parentAttr`; for ($i in $indices) { string $childAttr = $node + ".weight[" + $i + "]"; string $alias = `aliasAttr -q $childAttr`; if ($attr == $alias) $targetIndex = $i; } } } // Filter out valid meshes from selection string $sel[] = `ls -dag -g -sl`; string $selectedMeshes[]; for ($i = 0; $i < size($sel); ++ $i) { if (blendShapeCanAddAsTarget($sel[$i])) $selectedMeshes = stringArrayCatenate($selectedMeshes, {$sel[$i]}); } if(size($selectedMeshes) == 0) { error((uiRes("m_performUpdatePoseShape.kNoMeshSelected"))); return; } //Get base meshes string $baseMeshes[]=`blendShape -q -g $blendShape`; int $baseIndices[]=`blendShape -q -gi $blendShape`; if( size($baseMeshes) == 0 ) return; //Match selected meshes to base meshes string $matchedMeshes[]; int $matchedIndices[]; if( size($baseMeshes) == 1 ) { //case 1: only one base mesh, get the first mesh in selection list and use it to update the pose shape $matchedIndices[size($matchedIndices)] = 0; $matchedMeshes[size($matchedMeshes)] = $selectedMeshes[0]; } else { //case 2: multiple base meshes exist, try to match using names for($i = 0; $i < size($selectedMeshes); $i++) { string $shortName = shortNameOf($selectedMeshes[$i]); for($j = 0; $j < size($baseMeshes); $j++) { string $shortBaseName = shortNameOf($baseMeshes[$j]); if (startsWith($shortName, $shortBaseName)) { $matchedIndices[size($matchedIndices)] = $j; $matchedMeshes[size($matchedMeshes)] = $selectedMeshes[$i]; break; } } } } //Disconnect the poseInterpolator and blendshape, and set the weight to 0.0, so it gets calculated correctly string $weightAttr = $blendShape + ".weight[" + $targetIndex + "]"; disconnectAttr $sPlug $weightAttr; setAttr $weightAttr 0.0; string $toUpdateMeshes[]; //Invert mesh for pre-deformation case string $invertedMeshes[]; int $invertShapeLoaded = `pluginInfo -q -loaded invertShape`; string $attrOrderString = $blendShape + ".deformationOrder"; int $invert = 0; if(`getAttr $attrOrderString` == 0 && $invertShapeLoaded) $invert = 1; if($invert) { // pre-deformation case, we need to invert selected meshes first for ($i = 0; $i < size($matchedMeshes); $i++) { string $invertedMesh = invertShape($baseMeshes[$matchedIndices[$i]], $matchedMeshes[$i]); $invertedMeshes[size($invertedMeshes)] = $invertedMesh; $toUpdateMeshes[size($toUpdateMeshes)] = $invertedMesh; } } else { for ($i = 0; $i < size($matchedMeshes); $i++) { $toUpdateMeshes[size($toUpdateMeshes)] = $matchedMeshes[$i]; } } //Connect meshes to target for ($i = 0; $i < size($toUpdateMeshes); $i++) { int $baseIndex = $baseIndices[$matchedIndices[$i]]; string $srcAttr = $toUpdateMeshes[$i] + ".outMesh"; string $destAttr = $blendShape + ".inputTarget[" + $baseIndex + "].inputTargetGroup[" + $targetIndex + "].inputTargetItem[6000].inputGeomTarget"; catch(`connectAttr -f $srcAttr $destAttr`); catch(`disconnectAttr $srcAttr $destAttr`); } //Reconnect the blendShape to pose interpolator connectAttr $sPlug $weightAttr; //Delete the inverted meshes if($invert) { for($invertedMesh in $invertedMeshes) delete $invertedMesh; } // Restore the two values back to what they were. if( $regularization != 0.0 || $interpolation != 0 ) { setAttr $regularizationAttr $regularization; setAttr $interpolationAttr $interpolation; } }