// =========================================================================== // 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. // =========================================================================== global proc string[] performDeleteLod() // // Description: // This script deletes associated "lod" nodes and // connections from a transform and/or its group. // The user must select one or more transforms. // // If any selected transform has: // a) any connections to an "lod" node, or // b) a child of this transform is connected to an "lod" node, // // then what happens is: // a) all associated "lod" nodes are deleted, // b) associated visibility attributes are turned ON // { string $nodesToDelete[]; string $selAll[] = `ls -sl`; if( size($selAll) == 0 ) { error( (uiRes("m_performDeleteLod.kNothingSelected"))); return $nodesToDelete; } // Find all transforms that have lod nodes attached // string $sel[] = `ls -tr $selAll`; if( size($sel) == 0 ) { error( (uiRes("m_performDeleteLod.kNoTransformSelected"))); return $nodesToDelete; } string $existingLODConnection; string $transform; int $numSel = size($sel); int $i; int $j; string $pieces[]; string $visAttr = ".lodVisibility"; for( $i = 0; $i < $numSel; $i ++ ) { $transform = $sel[$i]; if( `connectionInfo -id ($transform + $visAttr)` > 0 ) { $existingLODConnection = `connectionInfo -sfd ($transform + $visAttr)`; } else { $existingLODConnection = ""; } if( size($existingLODConnection) > 0 ) { // This node is connected to an lod. // Parse out the node name, then add it to "$nodesToDelete" // $num = `tokenize $existingLODConnection "." $pieces`; if( $num > 0 ) { if( AWNumberOfOccurrencesInStringArray( $pieces[0], $nodesToDelete ) == 0 ) { $nodesToDelete[size($nodesToDelete)] = $pieces[0]; } } } else { // Check if any children of this transform are connected // then use it to find the lod node to delete // string $ch[] = `listRelatives -children $transform`; int $numCh = size($ch); if( $numCh > 0 ) { for( $j = 0; $j < $numCh; $j ++ ) { string $attr = ($transform+"|"+$ch[$j]+$visAttr); if( `connectionInfo -id ($attr)`>0) { $existingLODConnection = `connectionInfo -sfd ($attr)`; } else { $existingLODConnection = ""; } if( size($existingLODConnection) > 0 ) { $num = `tokenize $existingLODConnection "." $pieces`; if( $num > 0 ) { if( AWNumberOfOccurrencesInStringArray( $pieces[0], $nodesToDelete ) == 0 ) { $nodesToDelete[size($nodesToDelete)]= $pieces[0]; } break; } } } } } } int $numNodesToDelete = size($nodesToDelete); if( $numNodesToDelete == 0 ) { error( (uiRes("m_performDeleteLod.kSelectedHaveNoLOD"))); return $nodesToDelete; } // For each node, get its list of outputs // The outputs need to be made visible once the lod nodes are deleted // string $connection[]; string $visibilityAttr[]; string $ungrouped[]; for( $i = 0; $i < $numNodesToDelete; $i ++ ) { string $parent = $nodesToDelete[$i]; // try to "reset" its threshold values to something arbitrary // This will force "undo" to restore the threshold values int $numThresholds = `getAttr -size ($parent + ".th")`; for($c=0; $c<$numThresholds; $c++) { setAttr ($parent + ".th[" +$c + "]") 0.666; } // try to "reset" its display values to something arbritrary // This will force "undo" to restore the display values int $numDisplay = `getAttr -size ($parent + ".dl")`; for($c=0; $c<$numDisplay; $c++) { setAttr ($parent + ".dl[" +$c + "]") 0; } // explicitly break each connection on the output attr // This will force "undo" to restore each connection int $numOutputs = `getAttr -size ($parent + ".o")`; string $conn[]; for($c=0; $c<$numOutputs; $c++) { $conn = `connectionInfo -dfs ($parent+".o["+$c+"]")`; if( size($conn) > 0 ) { disconnectAttr ($parent+".o["+$c+"]") $conn[0]; } } string $msg = (uiRes("m_performDeleteLod.kDeleteNode")) ; print `format -stringArg $parent $msg` ; string $ch[] = `listRelatives -children $parent`; int $removalCandidate[]; int $numCh = size($ch); string $lodRoot = ""; if( !`exists lodRoot` ){ eval("source \"lodUtils.mel\""); } $lodRoot = lodRoot(); // For each child that already exists as a node rooted to world, // rename it, so that ungrouping the parent won't cause it to be // renamed. This is a situation that is more likely to happen with // the new LOD naming scheme, since the same names will be used in // different LOD groups. // // Since names may change, we also take note of whether the name // currently matches the LOD_* hierarchy, and record that // information in the $removalCandidates array. This will allow us // to remove nodes that we likely created. // for($c=0; $c<$numCh; $c++) { string $child = $ch[$c]; string $fullChild = $parent + "|" + $child; $removalCandidate[$c] = isSameObject( $fullChild, $parent +"|"+ $lodRoot + $c); if( `objExists ("|"+$child)` ){ string $rootName = `match "^[^0-9]+" $child`; rename $fullChild ($rootName + "#"); } } // Recompute the list of children // clear($ch); $ch = `listRelatives -children $parent`; // The ungroup command doesn't behave nicely when undone (for an // lodGroup node), so we manually reparent the children to the world so // that if an undo of the ungroup is done, the children get re-parented // in the correct order. See MAYA-55758, MAYA-56711. // TODO( "HACK", "Workaround due to defect MAYA-56711", "MAYA-56711" ); // Get the grand-parent, if any; if there is one, re-parent each child // to it, otherwise re-parent them to world. // string $grandParent = firstParentOf( $parent ); for($c=0; $c<$numCh; $c++) { string $child = $parent+"|" + $ch[$c]; if( $grandParent == "" ){ parent -w $child; } else { parent $child $grandParent; } } delete $parent; for($c=0; $c<$numCh; $c++) { string $child = $grandParent + "|" + $ch[$c]; // If we are using the new naming convention (see lodUtils.mel // for more info), remove group nodes that we (most likely) // created, unless the users has added extra children to them. // if( $removalCandidate[$c] ){ string $grandChildren[] = `listRelatives -children $child`; int $numGrandChildren = size($grandChildren); if( $numGrandChildren == 0 ){ // Child has no descendants, delete it. // delete $child; continue; } else if( $numGrandChildren == 1 ){ // Only one child, just ungroup the child if the // grandchild is a transform; this will also delete // the node, which is desired as we no longer need it. // string $grandChild = $grandChildren[0]; string $fullGrandChild = $child + "|" + $grandChild; if( `objectType -isAType "transform" $fullGrandChild`){ if( `objExists ("|"+$grandChild)` ){ // The grandChild already exists as a node // rooted to the world; rename it now, so that // we'll know its new name and save it for // the final selection. // string $rootName = `match "^[^0-9]+" $grandChild`; $grandChild = `rename $fullGrandChild ( $rootName + "#")`; } ungroup $child; $ungrouped[size($ungrouped)] = $grandChild; continue; } else { $ungrouped[size($ungrouped)] = $child; } } else { // Child has multiple children; we need to keep the // child around, and add it to the selection list. // $ungrouped[size($ungrouped)] = $child; } } // turn lodVisibility on for all cases, to ensure visibility // eval("setAttr " + $child + ".lodVisibility on"); } } if( size($ungrouped) > 0 ){ select -r $ungrouped; } // return deleted nodenames return $nodesToDelete; }