// =========================================================================== // 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. // =========================================================================== // // // Creation Date: May 16, 2003 // source "removeDuplicateNetworksUtils.mel"; global proc int removeDuplicateShadingNetworks( int $selected ) // // Description: // Compare each shading network within the current scene with each other // and colapse duplicate shading networks into one. If $selected is set to // true than all selected shading networks will be compared with every other // shading network in the scene. The selected nodes will be kept, and any // duplicates found will be deleted. If $selected is set to false, then // each shading network in the scene will be compared with each other. // Duplicate shading networks will be deleted in alphabetical order based on // shadingEngine node name. In order to have all duplicate networks collapse // into a particular network, rename that network such that it is last in // alphabetical order. // { // Are we being called during an Optimize Scene Size operation? // If so, we need to display progress information. This was done // as a global variable to avoid having to change the signature of // the proc, as that could break many scripts, both internal and // customer-written. // int $showProgress = cleanUp_ShouldReportProgress(); // To avoid trying to delete default shading networks only consider // shadingEngine nodes not part of $readOnly. string $readOnly[] = { "initialParticleSE", "initialShadingGroup" }; int $numDeleted = 0; int $numUnselectedEngines = 0; string $shadingEngines[] = `ls -type shadingEngine`; // Are we only analysing a sub-set of the shaders? if ( $selected ) { // Get the list of selected shaders string $selectedEngines[]; string $selection[] = `ls -selection`; if ( size( $selection ) == 0 ) { // Nothing selected error (uiRes("m_removeDuplicateShadingNetworks.kNothingSelected")); } $selectedEngines = `ls -selection -type shadingEngine`; if ( size( $selectedEngines ) == 0 ) { // If no selectedEngines were selected, try to find all // selectedEngines connected to the selected nodes. string $connections[] = `listConnections $selection`; $selectedEngines = stringArrayRemoveDuplicates ( `ls -type shadingEngine $connections` ); } if ( size( $selectedEngines ) == 0 ) { // If there are still no selectedEngines selected then show an // error. error (uiRes("m_removeDuplicateShadingNetworks.kNeedShader")); } // Rearrange the list of all the shaders in the scene, to put // the selected shaders at the end (highest array indicies), so // that we can use the same network comparison loop, and just // exit early once we finish testing the selected shaders // $shadingEngines = stringArrayRemove( $selectedEngines, $shadingEngines); $numUnselectedEngines = size( $shadingEngines); $shadingEngines = stringArrayCatenate( $shadingEngines, $selectedEngines); } // Now that we've handled selection, remove the duplicate networks! if( $showProgress ) { cleanUp_StartProgress( size($shadingEngines) , (uiRes("m_removeDuplicateShadingNetworks.kDeleteDuplicateShadingNetworks")), 1 ); } int $x = 0; int $i; // Take an initial pass through the shading engines to calculate // a hash value for each network. Without this, the network // comparison can take several hours on a large scene // int $hashValues[]; for ( $i = `size $shadingEngines`; $i-- > 0; ) { if( $showProgress ) { if( cleanUp_SetProgress( $x++ / 2) ) break; } $hashValues[ $i] = calculateShadingNetworkHash( $shadingEngines[ $i]); // print ( "Hashed shader " + $i + " to " + $hashValues[ $i] + "\n"); } // Now perform a brute force comparison of every shader selected // for optimisation; first testing for matching hash value and if // that matches, then testing for network equivalence // string $network1[]; for ( $i = `size $shadingEngines`; $i-- > $numUnselectedEngines; ) { if( $showProgress ) { if( cleanUp_SetProgress($x++ / 2) ) break; } // Can this node be duplicated? if( $hashValues[ $i] == 0) continue; // print ( "Looking for duplicates of shader " + $i + "\n"); int $j; for ( $j = $i; $j-- > 0; ) { if ( $hashValues[ $i] == $hashValues[ $j] ) { string $comparison = `shadingNetworkCompare $shadingEngines[$i] $shadingEngines[$j]`; if ( `shadingNetworkCompare -q -equivalent $comparison` ) { $network1 = `shadingNetworkCompare -q -network1 $comparison`; // If the networks are equivalent then assign all // the geometry connected to the imported node to // the existing duplicate. string $geometry[] = `sets -query $shadingEngines[ $i ]`; if ( size( $geometry ) > 0 ) { // sets can return invalid geometry, so catch it catchQuiet( `sets -edit -forceElement $shadingEngines[ $j ] $geometry` ); } // // Move any other dagSetMember connections (including // render layer adjustments) to new network too. // string $connections[] = `listConnections -plugs true -connections true ($shadingEngines[$i]+".dagSetMembers")`; for ($k = 0; $k < size($connections); $k += 2) { string $setDstPlug = $connections[$k]; string $srcPlug = $connections[$k+1]; disconnectAttr $srcPlug $setDstPlug; connectAttr -nextAvailable $srcPlug ($shadingEngines[$j]+".dagSetMembers"); } // // Delete $network1 to remove the duplicate network // entirely. string $n; for ( $n in $network1 ) { delete $n; } $numDeleted++; // Clear the string arrays clear $network1; // And stop $j = 0; } shadingNetworkCompare -delete $comparison; } // Clear the string arrays clear $network1; } } if( $showProgress ) { cleanUp_EndProgress(); } return $numDeleted; }