// =========================================================================== // 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: // AEtransformSkinCluster // // Description: // Creates attribute editor controls for transforms of // skinCluster influence objects // // Input Value: // nodeName // // Output Value: // None // proc string[] connectedSkinClusters(string $transform) // // Description: // Returns a list of the skinCluster nodes that are // using this transform as an influence object // { string $list[]; string $connections[] = `listConnections ($transform+".worldMatrix")`; for ($conn in $connections) { if (`nodeType $conn` == "skinCluster") $list[size($list)] = $conn; } return $list; } proc int plugMultiIndex(string $plug) // // Method: int plugMultiIndex(string $plug) // // Description: // Given a plug that contains a multiIndex, return the index // // If no multiIndex is found, returns -1. // If plug is a multi multi, returns the first multiIndex only. // { string $buffer[], $buffer2[]; tokenize($plug,"[",$buffer); if (size($buffer) != 2) { return(-1); } tokenize($buffer[1],"]",$buffer2); return $buffer2[0]; } proc int[] connectedIndexList(string $transform) // // Description: // Returns the indices of the connections of the transform // to the skinClusters // { int $list[]; string $connections[] = `listConnections -p true ($transform+".worldMatrix")`; string $buffer[]; int $count = 0; for($conn in $connections) { tokenize($conn, ".", $buffer); if (size($buffer) == 0) continue; if (`nodeType $buffer[0]` == "skinCluster") $list[$count++] = plugMultiIndex($conn); } return $list; } proc string influenceType(string $skinCluster, string $transform) // // Description: // Returns the type of object this influence is // The valid types are "poly" and "nurbs". An empty string // is returned if the object has no attached geometry // { string $connections[] = `listConnections -p true ($transform+".worldMatrix")`; string $buffer[]; for($conn in $connections) { tokenize($conn, ".",$buffer); if (size($buffer) == 0) return ""; if ($buffer[0] == $skinCluster) { int $multiIndex = plugMultiIndex($conn); if ($multiIndex != -1) { string $shapeList[] = `listConnections -p true ($skinCluster+".driverPoints["+$multiIndex+"]")`; if (size($shapeList) != 0) { tokenize($shapeList[0],".",$buffer); string $shape = $buffer[0]; string $type = `nodeType $shape`; if ($type == "nurbsSurface" || $type == "nurbsCurve") return "nurbs"; if ($type == "mesh") return "poly"; } } } } return ""; } proc float scCurrentAttrValue(string $attr, string $skinClusters[], int $indices[]) // // Description: // Returns the value of the given attribute on all the // skinClusters in the list at the respective multi index // { if (size($skinClusters) == 0) return -1.0; float $val = `getAttr ($skinClusters[0]+"."+$attr+"["+$indices[0]+"]")`; int $count = 0; for($cluster in $skinClusters) { float $newVal = `getAttr ($skinClusters[$count]+"."+$attr+"["+$indices[$count]+"]")`; if ($newVal != $val) { $val = -99.0; break; } $count++; } return $val; } proc deleteUpdateButton(string $name) // // Deletes the update weights button and its layout // { if (`rowLayout -exists $name`) deleteUI $name; } global proc scInfluenceReplace(string $nodeNameArr) { // Find the name of the influence transform // string $buffer[]; tokenize($nodeNameArr,".",$buffer); string $nodeName = $buffer[0]; // Find the skinClusters connected to the transform // string $skinClusters[] = connectedSkinClusters($nodeName); string $parent = `setParent -q`; tokenize($parent,"|",$buffer); $fullName = $parent+"|skinClusterLayout"; string $controlLayoutName = $fullName+"|scColumn"; $lockFullName = $parent+"|skinLockLayout"; string $inflType = ""; if (size($skinClusters) != 0) { // When there is something to show, we need to make sure controls' parent columnlayout // is visible. if (`columnLayout -exists $parent`) columnLayout -e -visible true $parent; // Find the type of the influence object // $inflType = influenceType($skinClusters[0], $nodeName); } else { // If no skinCluster is attached then delete the smooth // skin layout // if (`frameLayout -exists $fullName`) deleteUI -layout $fullName; // When there is nothing to show, we should hide control's parent column layout // as well. This column layout is created when call editorTemplate -callCustom and // will display some unwanted gap if it's empty. // This is not aesthetically pleasing. So let's hide this column layout when there // is nothing to show. if (`columnLayout -exists $parent`) columnLayout -e -visible false $parent; return; } string $smoothnessSlider = $controlLayoutName+"|scSmoothness"; string $samplesSlider = $controlLayoutName+"|scNurbsSamples"; if (`frameLayout -exists $fullName`) { // If this is one of autoupdating AE windows (not a tear-off copy) // then clean up the controls we don't need // if (($buffer[0] == "AEWindow" || $buffer[0] == "MayaWindow")) { if ($inflType == "poly") { // Delete the samples slider if it exists // if (`floatSliderGrp -exists $samplesSlider`) deleteUI $samplesSlider; } if ($inflType == "nurbs") { // Delete the smoothnsess slider if it exists // if (`floatSliderGrp -exists $smoothnessSlider`) deleteUI $smoothnessSlider; } } } else { // If the smooth skin layout doesn't exist then we need to // make one // frameLayout -label (uiRes("m_AEtransformSkinCluster.kSmoothSkinParameters")) -collapse true skinClusterLayout; setUITemplate -pst attributeEditorTemplate; columnLayout scColumn; // Create the lock influence check box // if (! `checkBoxGrp -exists scLockWeights`) { checkBoxGrp -label "" -label1 (uiRes("m_AEtransformSkinCluster.kLockInfluence")) -onc ("artSkinLockInfPassedIn " + $nodeName + " 1") -ofc ("artSkinLockInfPassedIn " + $nodeName + " 0") scLockWeights; } connectControl -index 2 scLockWeights ($nodeName+".liw"); } setParent $controlLayoutName; string $buttonLayoutLong = $controlLayoutName+"|weightsButtonLayout"; // Create the smoothness slider // if (($inflType == "poly") && (!`floatSliderGrp -exists $smoothnessSlider`)) { deleteUpdateButton($buttonLayoutLong); floatSliderGrp -label (uiRes("m_AEtransformSkinCluster.kSmoothness")) -min 0 -max 50 -field true -value 0.0 -pre 1 scSmoothness; } // Create the samples slider // if (($inflType == "nurbs") && (!`floatSliderGrp -exists $samplesSlider`)) { deleteUpdateButton($buttonLayoutLong); floatSliderGrp -label (uiRes("m_AEtransformSkinCluster.kNURBSSamples")) -min 1 -max 50 -field true -value 10.0 -pre 0 scNurbsSamples; } setUITemplate -ppt; // Update the values // int $indInfls[] = connectedIndexList($nodeName); // Set the value of the lock weights check box // if (! `checkBoxGrp -exists scLockWeights`) { checkBoxGrp -label (uiRes("m_AEtransformSkinCluster.kHoldWeights2")) -label1 "" scLockWeights; } connectControl -index 2 scLockWeights ($nodeName+".liw"); if ($inflType == "poly") { float $smoothness = scCurrentAttrValue("smoothness", $skinClusters, $indInfls); if ($smoothness == -99.0) floatSliderGrp -e -enable false scSmoothness; else floatSliderGrp -e -value $smoothness scSmoothness; } if ($inflType == "nurbs") { float $samples = scCurrentAttrValue("nurbsSamples", $skinClusters, $indInfls); if ($samples == -99.0) floatSliderGrp -e -enable false scNurbsSamples; else floatSliderGrp -e -value $samples scNurbsSamples; } setParent $parent; } global proc scInfluenceNew(string $nodeName) { scInfluenceReplace($nodeName); } global proc AEtransformSkinCluster( string $nodeName ) { editorTemplate -callCustom "scInfluenceNew" "scInfluenceReplace" $nodeName; editorTemplate -suppress "lockInfluenceWeights"; }