// =========================================================================== // 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. // =========================================================================== // // Procedure Name: // doBlendShapeAddInBetweenTarget // // Description: // Add a in-between target with/without selection // // Input Arguments: // bsNodeName - Blend shape name; // checkTopo - If check topology; // heroTargetIndex - Hero target index to add the in-between target; // inBetweenWeight - Maximum influence weight of the in-between target; // inBetweenType - The type of in-between target to create, relative/absolute to hero target; // 0 absolute, 1 relative; // $targetShapes - Target shapes to be added as in-between target // global proc doBlendShapeAddInBetweenTarget( string $bsNodeName, int $checkTopo, int $heroTargetIndex, float $inBetweenWeight, int $inBetweenType, string $targetShapes[] ) { if($inBetweenWeight == 1.000) { error( (uiRes("m_doBlendShapeAddInBetweenTarget.kInBetweenWtsNotOne"))); } int $inBetweenIndices[]; $tempAttr = $bsNodeName + ".inputTarget"; $baseIndices = getAttr("-mi", $tempAttr); for ($baseIndex in $baseIndices) { $tempAttr = $bsNodeName + ".inputTarget[" + $baseIndex + "].inputTargetGroup[" + $heroTargetIndex + "].inputTargetItem"; int $tempIBIndices[] = `getAttr -mi $tempAttr`; for ($ibi in $tempIBIndices) $inBetweenIndices[size($inBetweenIndices)] = $ibi; } int $inBetweenIndex = 5000 + $inBetweenWeight * 1000; if(intArrayFind($inBetweenIndex, 0, $inBetweenIndices) != -1) { error( (uiRes("m_doBlendShapeAddInBetweenTarget.kInBetweenWtsNotUnique"))); } string $cmd; //Get base meshes string $baseGeoms[]=`blendShape -q -g $bsNodeName`; // Get the target type of the hero target to add In-between. // 0 for object space; // 1 for tangent space; // 2 for transform space; string $heroTargetTypePlug = $bsNodeName + ".inputTarget[0].inputTargetGroup[" + $heroTargetIndex + "].pdm"; int $targetType = `getAttr $heroTargetTypePlug`; string $typePara = ""; if ($targetType == 1) //tangent space $typePara = " -tangentSpace"; if ($targetType == 2) //transform space { //Get the joint the hero target is using if the hero target is transform space type. string $tmxPlug = $bsNodeName + ".inputTarget[0].inputTargetGroup[" + $heroTargetIndex + "].tmx"; $cmd = "listConnections " + $tmxPlug; string $connections[] = evalEcho($cmd); string $transformName = $connections[0]; if(`objExists $transformName` == 0) { error( (uiRes("m_doBlendShapeAddInBetweenTarget.kInvalidTransformName")) ); return; } $typePara = " -transform " + $transformName; } string $checkTopoPara = "off"; if ($checkTopo == 1) { $checkTopoPara = "on"; } string $inbetweenTypeString = "absolute"; if($inBetweenType == 1) { $inbetweenTypeString = "relative"; } int $resetDeltaAfterAdded = 1; if (size($targetShapes) > 0) { // Physical target shapes are presented string $targetGeoms[]; for ($i = 0; $i < size($targetShapes); ++ $i) { if (blendShapeCanAddAsTarget($targetShapes[$i])) $targetGeoms = stringArrayCatenate($targetGeoms, {$targetShapes[$i]}); } if(size($targetGeoms) == 0) { return; // No valid target geom } string $diffGeoms[] = stringArrayRemove($baseGeoms, $targetGeoms); // Add in-between target for selected non-base meshes one by one int $targetGeomNum = size($diffGeoms); int $baseGeomNum = size($baseGeoms); if($targetGeomNum != 0) { // Non-base geoms are fed // If there is only one base geom, then we add all target geoms as its in-between target with the accumulated weights. if($baseGeomNum == 1) { string $longName = longNameOf($baseGeoms[0]); $cmd = "blendShape -e -ib -tc " + $checkTopoPara + " -ibt " + $inbetweenTypeString ; for ($ii = 0; $ii < size($diffGeoms); ++ $ii) { float $accumulatedInBetweenWeight = blendShapeWeightRoundoff($inBetweenWeight * ($ii+1), 3); $cmd += " -t " + $longName + " " + $heroTargetIndex + " " + $diffGeoms[$ii] + " " + $accumulatedInBetweenWeight + " "; } $cmd += $typePara + " " +$bsNodeName; evalEcho $cmd; if(blendShapeTargetIsVisible($bsNodeName, $heroTargetIndex)) { $cmd = "sculptTarget -e -target " + $heroTargetIndex + " -ibw " + $inBetweenWeight + " " + $bsNodeName; evalDeferred $cmd; } return; } // If there are multiple base geoms, then we add the target geoms one by one corresponding to the base geoms. if($baseGeomNum > 1) { for($jj = 0; $jj < $baseGeomNum; ++$jj) { string $longName = longNameOf($baseGeoms[$jj]); $cmd = "blendShape -e -ib -tc " + $checkTopoPara + " -ibt " + $inbetweenTypeString ; if($jj < $targetGeomNum) { $cmd += " -t " + $longName + " " + $heroTargetIndex + " " + $diffGeoms[$jj] + " " + $inBetweenWeight + " "; } $cmd += $typePara + " " +$bsNodeName; evalEcho $cmd; } if(blendShapeTargetIsVisible($bsNodeName, $heroTargetIndex)) { $cmd = "sculptTarget -e -target " + $heroTargetIndex + " -ibw " + $inBetweenWeight + " " + $bsNodeName; evalDeferred $cmd; } return; } } else {// Only selected base geoms $resetDeltaAfterAdded = 0; $baseGeoms = $targetGeoms; //Only copy selected base geom then add in-between target } } // Current process to add an in-between target is: // - Duplicate the shape at the in-between weight // - Add the shape as an in-between target // - Remove all target deltas on the newly added in-between target // (This is to eliminate all possible deformation effect from // other hero targets and other deformers.) // - Restore the in-between target to what the shape looks like when // the in-between target does not exist (This is to make sure user // can insert an empty in-between just like the shape at that weight // and then do minor adjustment, that's what in-between for). // // The reasons we need this tedious process are: // - It is safer because we do not touch current way to add target. // - Currently blendShape command does not support to add target // without physical shape. // A more ideal way is to support add target without physical shape // in blendShape command. //loop scope base meshes for ($i = 0; $i < size($baseGeoms); ++ $i) { string $longName = longNameOf($baseGeoms[$i]); string $copyMesh[] = `duplicate $longName`; $cmd = "blendShape -e -ib -tc " + $checkTopoPara + " -ibt " + $inbetweenTypeString + " -t " + $longName + " " + $heroTargetIndex + " " + $copyMesh[0] + " " + $inBetweenWeight + " " + $typePara + " " +$bsNodeName; evalEcho $cmd; delete $copyMesh[0]; if($resetDeltaAfterAdded) { $cmd = "blendShape -e -rtd " + $i + " " + $heroTargetIndex + " -ibi " + $inBetweenIndex + " " + $bsNodeName; evalEcho $cmd; $cmd = "sculptTarget -e -snapshot " + $i + " -target " + $heroTargetIndex + " -inbetweenWeight " + $inBetweenWeight + " " + $bsNodeName; evalEcho $cmd; } } if(blendShapeTargetIsVisible($bsNodeName, $heroTargetIndex)) { $cmd = "sculptTarget -e -target " + $heroTargetIndex + " -ibw " + $inBetweenWeight + " " + $bsNodeName; evalEcho $cmd; } }