// =========================================================================== // 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. // =========================================================================== // FILE: filterNucleusNodes.mel // INPUT: string[] (nodes) // string[] (filter node types) // int (max display type in Dynamics mode) // // RETURN: string[] (list of nodes, sorted & filtered according to the // preference) // proc string getParent( string $node, string $nodes[], int $lastIndex ) // // Description: // Given an array of nodes, it's last valid index, and a node, return this // node's parent, if it's present in the array, and "" otherwise. If the // parent is found at $lastIndex, replace it with "". If it's found at less // than $lastIndex, swap the found entry with the entry at $lastIndex, and // again, replace the one $lastIndex by "". // { string $parents[] = `listRelatives -parent $node`; if( size($parents) > 0 ){ string $parent = $parents[0]; int $xIndex = $lastIndex; while( $xIndex >= 0 ){ if( $nodes[$xIndex] == $parent ){ // Found transform if( $xIndex < $lastIndex ){ // Swap xIndex & last entry // $nodes[$xIndex] = $nodes[$lastIndex]; } $nodes[$lastIndex] = ""; // Mark node as processed return( $parent ); } $xIndex--; } } return( "" ); } proc int isTexture( string $node ) // // Description: // Given a node, return true if it's a texture that's hooked up to an // nCloth or nRigid node through an outAlpha attribute. // { string $plugs[] = `listAttr -st "outAlpha" $node`; if( size($plugs) != 1 ){ return false; } if( $plugs[0] != "outAlpha" ){ return false; } string $nodes[] = `listConnections -sh 1 ($node + ".outAlpha")`; int $numNodes = size($nodes); int $index = 0; while( $index < $numNodes ){ string $nType = `nodeType $nodes[$index]`; if( $nType == "nCloth" || $nType == "nRigid" ){ return true; } $index++; } return false; } global proc string[] filterNucleusNodes( string $prefNode, // Node flagged as preferred, if // any. string $nNodes[], // List of nodes string $alwaysTypes[], // Types always displayed int $optional ) // True iff we also want the // optional types displayed. // // Description: // Given a list of nodes, and a list of node types, sort the nodes // according to the node types. If a prefNode is specified, this one will be // repeated as the last one in the list. The optional node types are // controlled by various optionVar variables. // { // First, remove duplicates and null strings // string $nulls[] = {""}; string $validNodes[] = stringArrayRemove($nulls, $nNodes); string $uniqNodes[] = stringArrayRemoveDuplicates( $validNodes ); int $numNodes = size($uniqNodes); // First, sort the nodes into the various types that are always displayed. // int $processedDynamicConstraints = false; int $wantDynamicConstraint = true; int $nucleusShowTransformNodes = $optional; string $xNames[]; if( $nucleusShowTransformNodes ){ // Make a list of all the transforms; since the transforms were usually // added to the uniqArray in the same order as their child was, we'll // create the list backwards, search the list backwards, and be able to // efficiently remove the last entry from the end. // int $nodeIndex = $numNodes; int $xIndex; while( $nodeIndex > 0 ){ $nodeIndex--; string $node = $uniqNodes[$nodeIndex]; string $currType = `nodeType $node`; if( $currType == "transform" ){ $xNames[$xIndex] = $node; $uniqNodes[$nodeIndex] = ""; $xIndex++; } } } int $xLast = size($xNames)-1; string $retval[]; int $retIndex = 0; int $typeIndex = 0; int $numTypes = size($alwaysTypes); int $nodeIndex; while( $typeIndex < $numTypes ){ string $nType = $alwaysTypes[$typeIndex]; // If we're doing optional types, and dynamicConstraint is one of them, // but it's also in $alwaysTypes, force a skip, as long as it's not the // very first type. // if( $nType == "dynamicConstraint" ){ $processedDynamicConstraints = true; if( ($typeIndex > 0 ) && ( !$wantDynamicConstraint ) ){ $processedDynamicConstraints = false; $typeIndex++; continue; } } $nodeIndex = 0; while( $nodeIndex < $numNodes ){ string $node = $uniqNodes[$nodeIndex]; if( $node != "" ){ string $currType = `nodeType $node`; if( $currType == $nType ){ if( $xLast >= 0 ){ // If we want transforms, and this node's parent is in // the list of unique nodes, add it. // string $parent = getParent( $node, $xNames, $xLast ); if( $parent != "" ){ $xLast--; // One less transform remains $retval[$retIndex] = $parent; $retIndex++; } } $retval[$retIndex] = $node; $retIndex++; $uniqNodes[$nodeIndex] = ""; // Mark node as processed } } $nodeIndex++; } $typeIndex++; } if( $optional ){ // Next, sort the remaining nodes according to the types that are // optionally displayed, as controlled by the relevant optionVar // variable. // // Note: The type "other" should always be the last one, since we // assume a node is of type "other" if it's not of one of the // previous types. // string $optionalTypes[] = {"nComponent","dynamicConstraint","material","place2dTexture","other"}; string $optionVars[] = {"NComponent","DynamicConstraint","Material","Texture","Other"}; $numTypes = size($optionalTypes); int $showOther = true; if( !$showOther ){ $numTypes--; } $typeIndex = 0; string $shaderTypes[] = `listNodeTypes "shader"`; while( $typeIndex < $numTypes ){ string $optionName = ("nucleusShow"+$optionVars[$typeIndex]+"Nodes"); int $showType = true; if( !$showType && !$showOther ){ // We don't care about other types, or this type, so we don't need // to mark the nodes of this type. We can safely skip this one // entirely. $typeIndex++; continue; } string $nType = $optionalTypes[$typeIndex]; if( ($nType == "dynamicConstraint") && $processedDynamicConstraints ){ // We've already processed dynamic constraint, skip it here. // $typeIndex++; continue; } $nodeIndex = 0; while( $nodeIndex < $numNodes ){ string $node = $uniqNodes[$nodeIndex]; if( $node != "" ){ string $currType = `nodeType $node`; if( ($nType == "other") && ($currType != "transform") || ( $currType == $nType ) || (($nType == "material" ) && stringArrayContains($currType,$shaderTypes)) || (($nType=="place2dTexture") &&isTexture($node))){ if( $showType ){ if( $xLast >= 0 ){ // If we want transforms, and this node's parent // is in the list of unique nodes, add it. // string $parent = getParent( $node, $xNames, $xLast ); if( $parent != "" ){ $xLast--; // One less transform remains $retval[$retIndex] = $parent; $retIndex++; } } $retval[$retIndex] = $node; $retIndex++; } $uniqNodes[$nodeIndex] = ""; // Mark node as processed } } $nodeIndex++; } $typeIndex++; } } if( $prefNode != "" ){ $retval[$retIndex] = $prefNode; } return $retval; }