Python 'OptimizeSceneSize'

Hey All,
I’m looking for a way to run the menu command File-OptimizeSceneSize in Maya from within Python or Mel.
im really only needing the ‘delete unused nodes’ and ‘delete duplicate shading networks’ functions from within this. Ive managed to get the mel command for this but can’t get it to run without a click ‘ok’ pop up, thus breaking my batch script which I need this to run in.

Any idea would be greatly appreciated

You can temporarily suppress warnings. I haven’t tested this or used it for years, so I only think this is the relevant command. I don’t know if it will suppress that prompt:

import maya.cmds as cmds
cmds.scriptEditorInfo(suppressWarnings=0,suppressInfo=0,se=0)

You might want to wrap it in try / except / finally logic so it turns it back on at the end, even in the event of a failure.

You might also be able to find the mel procedures and fork them yourself. Or I also found this old script on Github, but didn’t inspect it or try it: https://github.com/shyal/osbTools/blob/master/mel/cleanUpScene.mel

this won’t directly answer your question, so feel free to tell me to bugger off.
marcus’ maya scene size analyzer tool might be relevant to what you are doing. it tells you what takes up how much space in your maya scene https://github.com/mottosso/maya-sniffer

Abit shotgun for a fly approach but you can overload the optimizeScene Mel command in your local userScripts to suppress dialogs or modify the behaviour as you need.
It’s not usually the best option but it does give you the ability to add missing functionality.

Let’s try to understand the Maya MEL code and understand how it can be adapted to our needs…

MEL commands:

whatIs OptimizeScene;
// Result: Run Time Command
runTimeCommand   -q -c "OptimizeScene";
// Result: cleanUpScene 1
whatIs cleanUpScene;
// Result: Mel procedure found in: C:/Program Files/Autodesk/Maya2023/scripts/startup/cleanUpScene.mel

Well, let’s take a look at the code in this file…
cleanUpScene.mel (global proc cleanUpScene):
Wow!
This file is incredibly over-commented!
All the logic is painted in the most detailed way with the most detailed comments!

//...
//	cleanUpScene:
//		$option = 1: does the cleanup operation
//		$option = 2: option window for cleanup
//		$option = 3: cleanup operation for everything regardless of options
//
global proc cleanUpScene (int $option)
{
	//	call the initialization function to register user cleanup operations
	//
	cleanUp_RegisterUserCleanUps();

	if ($option == 1) {	
		// Do the cleanup
		setOptionVars (false);
		performCleanUpScene();
	} else if ($option == 2) {
		// Option window for the cleanup work
		cleanUpOptions();
	} else if ($option == 3) {
		performCleanUpSceneForEverything();
	}
}
//...

Well, let’s see the code in the global procedure “perform CleanUp Scene ()”…

// ...
global proc performCleanUpScene ()
{
	string $ok	   = (uiRes("m_cleanUpScene.kOK"));
	string $result = $ok;
	string $cancel = (uiRes("m_cleanUpScene.kCancel"));		
	
	//
	//	We will use catch statements around each individual optimization
	//	step to detect any errors (syntax errors or other error conditions)
	//	that may occur.  This is important so that errors in one step
	//	do not cause the whole process to abort.  Also, since the optimization
	//	steps mess around with the progress bar and the global cursor state,
	//	it is important that we restore these things to their previous
	//	states before this function exits.
	//
	int $errorCount = 0;

	cleanUp_Initialize();

	//	so that we can suppress the user confirmation dialog
	//	during automated testing
	//
	int $suppressDialog = 0;
	if( size(`getenv "MAYA_TESTING_CLEANUP"`) > 0 )
	{
		$suppressDialog = 1;
	}
	
	if( !$suppressDialog )
	{
		// Confirm that a cleanup is desired (since this is not undoable)
		$result = `confirmDialog 
			-title (uiRes("m_cleanUpScene.kVerifyingAction")) 
			-message (uiRes("m_cleanUpScene.kOptimizeCurrSceneSize"))  
			-button $ok -button $cancel`; 
	}
	
	if (!`about -batch` && $result != $ok) {
		return;
	}
// ....

Wow, the developers have already provided in the code the ability to not use the confirm dialog!
And the developers even introduced a special Maya ENV variable for this case: "MAYA_TESTING_CLEANUP".

Variable: MAYA_TESTING_CLEANUP
Description: Will suppress user confirmation dialogs during automated testing
Since: 2014

It can be seen from the code that it is not the value of the variable that is analyzed (the value can be arbitrary), but the very presence of the "MAYA_TESTING_CLEANUP" variable in the environment.
Therefore, after creating a variable "MAYA_TESTING_CLEANUP" with an arbitrary value (eg “enable”) and using this variable, we must take care to remove this variable from the environment!
Otherwise, all subsequent function calls for the cleanup module will stop launching windows with confirm dialogs!

We can use this environment variable for our own purposes, for example in this way:

MEL WAY:

// ....
// Optional. Analizing the current scene and/or setting cleanUp options...

if (size(`getenv "MAYA_TESTING_CLEANUP"`) == 0)
    {
        putenv "MAYA_TESTING_CLEANUP" "enable";
        cleanUpScene 1;
        python("import os")
        python("del os.environ[\"MAYA_TESTING_CLEANUP\"]");
    }
else
    {
        cleanUpScene 1;
    }

// ....

PYTHON WAY:

import maya.mel as mel
import os

# Optional. Analizing the current scene and/or setting cleanUp options...

if "MAYA_TESTING_CLEANUP" not in os.environ:
    os.environ["MAYA_TESTING_CLEANUP"] = "enable"
    mel.eval("cleanUpScene 1;")
    del os.environ["MAYA_TESTING_CLEANUP"]
else: mel.eval("cleanUpScene 1;")

This will be equivalent to clicking the “Optimize Now” button next to the desired option (for example, “Remove duplicate Shading networks”) in the “Optimize Scene Size Options” window.

MEL WAY:

// ....
// 

if (size(`getenv "MAYA_TESTING_CLEANUP"`) == 0)
    {
        putenv "MAYA_TESTING_CLEANUP" "enable";
        scOpt_performOneCleanup( {"shadingNetworksOption"} );
        python("import os")
        python("del os.environ[\"MAYA_TESTING_CLEANUP\"]");
    }
else
    {
        scOpt_performOneCleanup( {"shadingNetworksOption"} );
    }

// ....

PYTHON WAY:

import maya.mel as mel
import os

if "MAYA_TESTING_CLEANUP" not in os.environ:
    os.environ["MAYA_TESTING_CLEANUP"] = "enable"
    mel.eval("scOpt_performOneCleanup( {\"shadingNetworksOption\"} );")
    del os.environ["MAYA_TESTING_CLEANUP"]
else: mel.eval("scOpt_performOneCleanup( {\"shadingNetworksOption\"} );")

You can pass several optimization parameters to the “scOpt_performOneCleanup” function.

For example (MEL WAY):

scOpt_performOneCleanup( { "shadingNetworksOption", "groupIDnOption" } );

Valid values must match the values returned by this function (MEL WAY):

string $valid_vales[] = `scOpt_allCleanUpOptionVars`

For example (MEL WAY):

print `scOpt_allCleanUpOptionVars`;

nurbsSrfOption
nurbsCrvOption
unusedNurbsSrfOption
locatorOption
clipOption
poseOption
ptConOption
pbOption
deformerOption
unusedSkinInfsOption
expressionOption
groupIDnOption
animationCurveOption
snapshotOption
unitConversionOption
shaderOption
cachedOption
transformOption
displayLayerOption
renderLayerOption
setsOption
partitionOption
referencedOption
brushOption
unknownNodesOption
shadingNetworksOption

I hope this is exactly what you are trying to do…
Good luck!
:slight_smile:

UPD:

In the original version, I mistakenly specified “scOpt_performCleanup”, it will be correct: “scOpt_performOneCleanup

By changing the “numeric_vars” variable (simply listing the option numbers from the “all_option_vars” global options list), you can control which options are enabled for clearing.

In the examples below, the “numeric_vars” variable includes the option numbers to “Remove unused” and “Remove duplicate Shading networks

MEL:

// Create list ("$all_option_vars[]") for all cleanup options

string $all_option_vars[] = {
        "nurbsSrfOption",          // 0
    "nurbsCrvOption",          // 1
    "unusedNurbsSrfOption",    // 2
    "locatorOption",           // 3
    "clipOption",              // 4
    "poseOption",              // 5
    "ptConOption",             // 6
    "pbOption",                // 7
    "deformerOption",          // 8
    "unusedSkinInfsOption",    // 9
    "expressionOption",        // 10
    "groupIDnOption",          // 11
    "animationCurveOption",    // 12
    "snapshotOption",          // 13
    "unitConversionOption",    // 14
    "shaderOption",            // 15
    "cachedOption",            // 16
        "transformOption",         // 17
        "displayLayerOption",      // 18
        "renderLayerOption",       // 19
        "setsOption",              // 20
        "partitionOption",         // 21
    "referencedOption",        // 22
    "brushOption",             // 23
        "unknownNodesOption",      // 24
    "shadingNetworksOption"   // 25
                            };
// Remove duplicate Shading networks --> $all_option_vars[25] ("shadingNetworksOption")
// Remove unused -- >  $all_option_vars[1:16, 22:23]
// Create integer list ("$numeric_vars[]") for number options "Remove unused" and "Remove duplicate Shading networks" (in "$all_option_vars").

int $numeric_vars[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,22,23,25};
// Create options list ($select_vars) for "$numeric_vars" in "$all_option_vars"
string $select_vars[];
for ($item in $numeric_vars)
{
    $select_vars[size($select_vars)]= $all_option_vars[$item];
}

// cleanup

if (size(`getenv "MAYA_TESTING_CLEANUP"`) == 0)
    {
        putenv "MAYA_TESTING_CLEANUP" "enable";
        scOpt_performOneCleanup( $select_vars );
        python("import os");
        python("del os.environ[\"MAYA_TESTING_CLEANUP\"]");
    }
else
    {
        scOpt_performOneCleanup( $select_vars );
    }

PYTHON:

import os
import maya.mel as mel
# Create list ("all_option_vars[]") for all cleanup options

all_option_vars = [
        "nurbsSrfOption",          # 0
    "nurbsCrvOption",          # 1
    "unusedNurbsSrfOption",    # 2
    "locatorOption",           # 3
    "clipOption",              # 4
    "poseOption",              # 5
    "ptConOption",             # 6
    "pbOption",                # 7
    "deformerOption",          # 8
    "unusedSkinInfsOption",    # 9
    "expressionOption",        # 10
    "groupIDnOption",          # 11
    "animationCurveOption",    # 12
    "snapshotOption",          # 13
    "unitConversionOption",    # 14
    "shaderOption",            # 15
    "cachedOption",            # 16
        "transformOption",         # 17
        "displayLayerOption",      # 18
        "renderLayerOption",       # 19
        "setsOption",              # 20
        "partitionOption",         # 21
    "referencedOption",        # 22
    "brushOption",             # 23
        "unknownNodesOption",      # 24
    "shadingNetworksOption"   # 25
                            ]

# "Remove duplicate Shading networks" --> all_option_vars[25] ("shadingNetworksOption").
# "Remove unused" -- >  all_option_vars[1:16, 22:23] ("nurbsCrvOption", etk...).
# Create integer list ("numeric_vars") for numbers for "Remove unused" and "Remove duplicate Shading networks" (in "all_option_vars").

numeric_vars = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,22,23,25]

# Create string options list ("select_vars") for "numeric_vars" in "all_option_vars".
select_vars = []
for number in numeric_vars: select_vars.append(all_option_vars[number])

# cleanup
mel.eval("$select_vars = python(\"select_vars\")")
if "MAYA_TESTING_CLEANUP" not in os.environ:
    os.environ["MAYA_TESTING_CLEANUP"] = "enable"
    mel.eval("scOpt_performOneCleanup($select_vars)")
    del os.environ["MAYA_TESTING_CLEANUP"]
else: mel.eval("scOpt_performOneCleanup($select_vars)")

For simplicity and clarity, I deliberately did not format the code in functions. In the final code, of course, you probably want more harmony and aesthetics :slight_smile:
I apologize for the confusion of presentation, English is not my native language.

1 Like