//****************************************************************************** // // 版权所有: 玉溪时光科技有限公司 // 联系邮箱: q.100@qq.com // 开发日期: 2023/08/08 // //****************************************************************************** global proc SGCloneBlandShape() { if (`window -ex wrapChangeBS`){ deleteUI wrapChangeBS; } window -w 300 -h 300 -t "BlendShapeBake" -menuBar on wrapChangeBS; columnLayout -adj 1 -columnAttach "both" 5 -rowSpacing 2 -columnWidth 150 ; separator -height 10 -style "in"; checkBox -label "Use Wrap Method" -v 1 -cc sparklyWrapConvertBlendCheckRetrun wrapMethod; if (`exists deltaMush`) { checkBox -label "DeltaMushTarget" -v 0 -cc sparklyWrapConvertBlendCheckRetrun deltaMushTarget; intSliderGrp -f on -min 0 -max 100 -w 50 -v 10 deltaIntensity; separator -height 10 -style "in"; } else { text -fn "boldLabelFont" -l "低版本DeltaMush不可用"; separator -height 10 -style "in"; } button -l "Cloning" -c "SGWrapConvertBlend"; button -l "Copy" -c "SGCopyBlend"; button -l "Mirror" -c "SGMirrorBlend"; separator -height 10 -style "in"; window -e -w 260 -h 85 wrapChangeBS; showWindow; } global proc sparklyWrapConvertBlendCheckRetrun() { } global proc string[] sparkey_getBlendShape(string $geo) { string $skins[] ; clear $skins ; if ($geo == "" || objExists($geo) != true) return $skins ; string $hist[] = `listHistory -pdo 1 -il 2 $geo` ; string $h ; for ($h in $hist) { if (nodeType($h) == "blendShape") { $skins[size($skins)] = $h ; } } return $skins ; } global proc string[] sparkey_getWrap(string $geo) { string $skins[] ; clear $skins ; if ($geo == "" || objExists($geo) != true) return $skins ; string $hist[] = `listHistory -pdo 1 -il 2 $geo` ; string $h ; for ($h in $hist) { if (nodeType($h) == "wrap") { $skins[size($skins)] = $h ; } } return $skins ; } global proc SGWrapConvertBlend() { string $sel[] = `ls -sl`; if (size($sel) == 2) { string $bs[] = `sparkey_getBlendShape($sel[1])`; if (size($bs) != 0) { /*-------------------------------------*/ string $bsNode[] = `listAttr -m ($bs[0] + ".w")`; int $bsNum = size($bsNode); if ($bsNum != 0) { if (`checkBox -q -v wrapMethod`) { select -r $sel[0] $sel[1]; CreateWrap; } string $rbMesh[]; clear $rbMesh; /*--------------- copy target ----------------------*/ if (`objExists "WrapConvertTemp"`) { delete "WrapConvertTemp"; } else { group -em -n "WrapConvertTemp"; } for ($num = 0; $num < $bsNum; $num++) { int $bsWeight = `getAttr ($bs[0] + "." + $bsNode[$num])`; int $conInfo=`connectionInfo -il ($bs[0] + "." + $bsNode[$num])`; if (($bsWeight != 1)&&($conInfo==0)) { setAttr ($bs[0] + "." + $bsNode[$num]) 1 ; string $copyMesh[] = `duplicate $sel[0]`; parent $copyMesh[0] "WrapConvertTemp"; rename $copyMesh[0] $bsNode[$num]; $rbMesh[size($rbMesh)] = (":WrapConvertTemp|:" + $bsNode[$num]); setAttr ($bs[0] + "." + $bsNode[$num]) 0 ; } } /*--------------- category ----------------------*/ if (`checkBox -q -v wrapMethod`) { string $wrapName[] = `sparkey_getWrap ($sel[0])`; string $del[] = `ls ($sel[1] + "Bas*")`; delete $wrapName $del; } blendShape -frontOfChain $rbMesh $sel[0]; delete "WrapConvertTemp"; print "blendshape完美复制!"; /*----------------delta mush ---------------------*/ if (`checkBox -q -v deltaMushTarget`) { int $deltaValue = `intSliderGrp -q -v deltaIntensity`; string $dlNames[] = `deltaMush -smoothingIterations $deltaValue -smoothingStep 1.0 -pinBorderVertices 1 -envelope 1 $sel[0]`; string $bs[] = `sparkey_getBlendShape($sel[0])`; string $bsNode[] = `listAttr -m ($bs[0] + ".w")`; int $bsNum = size($bsNode); string $rbMesh[]; clear $rbMesh; if (`objExists "WrapConvertTemp"`) { delete "WrapConvertTemp"; } else { group -em -n "WrapConvertTemp"; } for ($num = 0; $num < $bsNum; $num++) { int $bsWeight = `getAttr ($bs[0] + "." + $bsNode[$num])`; if ($bsWeight != 1) { setAttr ($bs[0] + "." + $bsNode[$num]) 0 ; currentTime -10; setAttr ($bs[0] + "." + $bsNode[$num]) 1 ; currentTime 0; string $copyMesh[] = `duplicate $sel[0]`; parent $copyMesh[0] "WrapConvertTemp"; rename $copyMesh[0] $bsNode[$num]; $rbMesh[size($rbMesh)] = (":WrapConvertTemp|:" + $bsNode[$num]); setAttr ($bs[0] + "." + $bsNode[$num]) 0 ; currentTime -10; currentTime 0; } } delete $dlNames $bs; blendShape -frontOfChain $rbMesh $sel[0]; delete "WrapConvertTemp"; print "DeltaMush完美优化完毕!"; } } else { warning "驱动物体blendshape列表为空"; } } else { warning "驱动物体不存在blendshape,请确保所选择的驱动物体拥有blendshape"; } } else { warning "请选择两个多边形物体"; } } global proc SGCopyBlend() { string $SelBsNameList[] = getShapeEditorTreeviewSelection(14); string $tmpA[] = stringToStringArray($SelBsNameList[0], "."); string $tmpB[] = stringToStringArray($SelBsNameList[1], "."); int $targetA = $tmpA[1]; int $targetB = $tmpB[1]; //refresh;//Maya2016 bug workaround string $MeshA[] = `sculptTarget -e -regenerate true -target $targetA $tmpA[0]`; string $MeshShapeA[] = `listRelatives -s $MeshA[0]`; disconnectAttr ($MeshShapeA[0]+".worldMesh[0]") ($tmpA[0]+".inputTarget[0].inputTargetGroup["+$targetA+"].inputTargetItem[6000].inputGeomTarget"); connectAttr -f ($MeshShapeA[0]+".worldMesh[0]") ($tmpA[0]+".inputTarget[0].inputTargetGroup["+$targetB+"].inputTargetItem[6000].inputGeomTarget"); delete $MeshA; //refresh;//Maya2016 bug workaround //blendShape -e -ft 0 $targetB -ss 1 -sa "x" $tmpB[0]; } global proc SGMirrorBlend() { int $originalSymmetry = `symmetricModelling -q -s`; string $symmetrySpace, $symmetryAxis; if ($originalSymmetry) { $symmetrySpace = `symmetricModelling -q -about`; if ($symmetrySpace == "topo") $symmetryAxis = blendShapeGetTopoSymmetryEdge(); else $symmetryAxis = `symmetricModelling -q -axis`; } string $SelBsNameList[] = getShapeEditorTreeviewSelection(14); string $tmpA[] = stringToStringArray($SelBsNameList[0], "."); string $tmpB[] = stringToStringArray($SelBsNameList[1], "."); int $targetA = $tmpA[1]; int $targetB = $tmpB[1]; //refresh;//Maya2016 bug workaround string $MeshA[] = `sculptTarget -e -regenerate true -target $targetA $tmpA[0]`; string $MeshShapeA[] = `listRelatives -s $MeshA[0]`; disconnectAttr ($MeshShapeA[0]+".worldMesh[0]") ($tmpA[0]+".inputTarget[0].inputTargetGroup["+$targetA+"].inputTargetItem[6000].inputGeomTarget"); connectAttr -f ($MeshShapeA[0]+".worldMesh[0]") ($tmpA[0]+".inputTarget[0].inputTargetGroup["+$targetB+"].inputTargetItem[6000].inputGeomTarget"); delete $MeshA; //refresh;//Maya2016 bug workaround blendShape -e -ft 0 $targetB -ss 1 -sa "x" $tmpB[0]; reflectionSetMode none; string $cmd; if (!$originalSymmetry || size($symmetryAxis) == 0) $cmd += "eval -ue 0 \"symmetricModelling -s 0\";"; else if ($symmetrySpace == "topo") $cmd += "eval -ue 0 \"symmetricModelling -e -about " + $symmetrySpace + " -s 1 " + $symmetryAxis + "\";"; else $cmd += "eval -ue 0 \"symmetricModelling -e -about " + $symmetrySpace + " -axis " + $symmetryAxis + " -s 1\";"; eval($cmd); } // =========================================================================== // Copyright 2016 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 string[] getShapeEditorTreeviewSelection(int $scope) // // Description: // Get selections from shape editor tree view // // Input Arguments: // int $scope - Scope of tree view selection: // // Simple Scopes: // 0: Selected blend shape deformer group indices. e.g. {"-1", "-2", "-3"} // 1: Selected blend shape deformers. e.g. {"blendShape1", "blendShape2", "blendShape3", "blendShape4"} // 2: Blend shape deformers in selected groups. e.g. {"blendShape1", "blendShape2"} // 3: Selected target group indices with blend shape name prefix. e.g. {"blendShape1.-1", "blendShape1.-2", "blendShape2.-1", "blendShape2.-2"} // 4: Selected target indices with blend shape name prefix. e.g. {"blendShape1.0", "blendShape1.1", "blendShape1.2"} // 5: Targets in selected groups with blend shape name prefix. e.g. {"blendShape2.0", "blendShape2.1"} // 6: Inbetween targets. e.g. {"blendShape2.0.5500", "blendShape2.1.5800"} // 7: Purely selected blend shape deformer (groups). e.g. {"-1", "2", "blendshape1", "blendshap2", "-3"} // 8: Purely selected target (groups). e.g. {"blendshape1.1", "blendshape1.-1", "blendshape2.2", "blendshape2.-2"} // 9: Purely selected target (groups) within one BSD. e.g. {"blendshape1.1", "blendshape1.-1"} // // Only one type of item is selected: // 10: Purely selected blend shape deformer group indices:, return {} for mixed selection // 11: Purely selected blend shape deformers:, return {} for mixed selection // 12: Blend shape deformers in purely selected of groups:, return {} for mixed selection // 13: Purely selected target group indices:, return {} for mixed selection // 14: Purely selected targets:, return {} for mixed selection // 15: Target in purely selected of groups, return {} for mixed selection // 16: Purely selected in-between targets. return {} for mixed selection // // Last Selected Item // 20: Last selection // // Only one type and its group type of item are selected: // 21: Purely selected blend shape deformers and the ones in group without duplicates, return {} for mixed selection. // 24: Purely selected target and the ones in group without duplicates, return {} for mixed selection. // // Flags: // 30: If selection contains reference item. return {"1"} if true; {"0"} if false; // 31: First selection item // // Return Value: // String array of given scope // { $TypeRoof = 6; //NOTE: Update roof when new tree item type added int $TypeArray[]; for ($i = 0; $i < $TypeRoof; ++ $i) $TypeArray[$i] = $i; // initialize type arrary if(!`optionVar -exists blendShapeEditorTreeViewSelection`) return{}; string $ov[] = `optionVar -q blendShapeEditorTreeViewSelection`; if($scope > -1 && $scope < $TypeRoof + 3) //Scope 0 ~ 8 return stringToStringArray($ov[$scope], "/"); if($scope == 9) //Scope 9 return filterSingleBSD(stringToStringArray($ov[8], "/")); else if($scope > 9 && $scope < $TypeRoof + 11) //Scope 10 ~ 16 { $selection = stringToStringArray($ov[$scope-10], "/"); if(size($selection) == 0) return {}; int $newTypeArray[] = intArrayRemove({$scope-10, 2, 5}, $TypeArray); // Skip checking scope related types if($scope == 12 || $scope == 15) $newTypeArray = intArrayRemove({$scope-12}, $newTypeArray); // Skip checking bsd/target group types for ($i in $newTypeArray) if(size(stringToStringArray($ov[$i], "/")) != 0) return {}; // If mixed selection return $selection; } else if($scope == 20) //Scope 20 return stringToStringArray($ov[9], "/"); else if ($scope == 21 || $scope == 24) //Scope 21, 24 { $selectionOutG = stringToStringArray($ov[$scope-20], "/"); $selectionInG = stringToStringArray($ov[$scope-19], "/"); $selection = stringArrayRemoveDuplicates(stringArrayCatenate($selectionOutG, $selectionInG)); if(size($selection) == 0) return {}; int $newTypeArray[] = intArrayRemove({$scope-20, $scope-19, $scope-21}, $TypeArray); // Skip checking scope related types for ($i in $newTypeArray) if(size(stringToStringArray($ov[$i], "/")) != 0) return {}; // If mixed selection return $selection; } else if ($scope == 30) //Scope 30 return stringToStringArray($ov[10], "/"); else if ($scope == 31) return stringToStringArray($ov[11], "/"); else // Invalid scope return {}; } global proc string[] filterSingleBSD(string $items[]) // // Description: // Return selected target(group) from single blend shape deformer. return empty for more multi-BSD // { string $result[]; string $oneBsd = ""; for($item in $items) { string $subStrings[] = stringToStringArray($item, "."); if($oneBsd == "") $oneBsd = $subStrings[0]; if($oneBsd != $subStrings[0]) { return {}; } $result = stringArrayCatenate($result, {$item}); } return $result; } global proc int isShapeEditorRefItemSelected() // // Description: // Return 1 if reference item selected in shape editor tree view // { $ResultL = getShapeEditorTreeviewSelection(30); if(size($ResultL) == 1) { if($ResultL[0] == "1") return 1; else return 0; } return 0; } global proc int blendShapeEditorSelectedAncestor(string $bsdName, int $tgtIndex, string $selectedTargets[]) // // Description: // Get the selected ancestor if there is, otherwise return 0. // In the blendShape target/directory hierarchy, there is always a highest directory // with index=0 and cannot be selected, if going up to this highest directory, stop and return 0. // Since this directory 0 cannot be selected, so return 0 means fail to find. // // This function dest not care whether the $tgtIndex is selected or not. // // Input: // $tgtIndex >= 0, target, // < 0, target directory. // // Return: // 0 if ancestors are not selected. // if there is a highest ancestor is selected, which must be a directory, // since target's parent and directory's parent are directory. // { int $highestParentDirectory = 0; int $parentDir = -1; if ($tgtIndex >= 0) { // this is a target, // go to parent directory. $tempAttr = $bsdName + ".parentDirectory[" + $tgtIndex + "]"; $parentDir = `getAttr $tempAttr`; if ($parentDir <= -1) return 0; // default value if ($parentDir == 0) return 0; // target item directly under blendShape node } else { // this is a target directory. // go to parent directory $tempAttr = $bsdName + ".targetDirectory[" + -$tgtIndex + "].parentIndex"; $parentDir = `getAttr $tempAttr`; } while ($parentDir > 0) { // check if this directory is selected or not string $dirNameEncoded = $bsdName + "." + -$parentDir; if ( stringArrayFind($dirNameEncoded, 0, $selectedTargets) != -1 ) $highestParentDirectory = $parentDir; // go to parent directory, parent of a directory is always a directory. $tempAttr = $bsdName + ".targetDirectory[" + $parentDir + "].parentIndex"; $parentDir = `getAttr $tempAttr`; } return $highestParentDirectory; }