MetaFusion/Reference/SuperRiggingEditor/scripts/SGCloneBlandShape.mel
2025-02-03 22:58:41 +08:00

449 lines
16 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//******************************************************************************
//
// 版权所有: 玉溪时光科技有限公司
// 联系邮箱: 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;
}