Do you wonder why error messages about some plug-in or other that Maya cannot find continue to appear when you load a scene? Do you wish you could force Maya to unload a plug-in when saving your scene so you can avoid having it load again with the scene file ?
The objective of this tutorial is help you understand why Maya might include a reference to a plug-in in a scene file, and how to prevent Maya from doing so.
To complete this tutorial, you will need Maya 2015 SP6 or Maya 2015 Ext1 & SP6 because this Service Pack release includes two new MEL commands : unknownPlugin and unknownNode; this tutorial demonstrates how to use both of them.
What is the requires command and why is it recorded in the scene file ?
The requires command included in the scene file header tells Maya to load a plug-in file.
The Maya Software Development Kit allows developers to define new types of nodes. Before artists can use your custom node in Maya, the plug-in that defines the node's type and behaviour must be loaded and the node-type must be registered in Maya's internal plug-in database.
Let's say you have written a plug-in which registers a new node-type called "myCustomNodeType". Once the plug-in is loaded, you can create a node of this type with the following command:
createNode "myCustomNodeType" -name "customNode01";
When you save or export this node to a Maya file, this createNode command is included in the scene file (in a binary file, Maya records the node-type id instead of the node-type label).
With this createNode command referring to a custom node-type, Maya also writes information in the scene file about the plug-in that registered that node-type.
So if your scene contains a custom node, your scene file will contain at least two commands:
//
requires -nodeType "myCustomNodeType" "myPlugin" "1.0";
...
createNode "myCustomNodeType" -name "customNode01";
//
When reading your scene file, Maya will check to see if the required plug-in is already loaded. If not, Maya attempts to locate the plug-in file by searching the directory paths in the environment variable MAYA_PLUG_IN_PATH. Whether the plug-in loads, or not, Maya will continue to execute the remaining commands in the scene file and proceeds to rebuild the scene graph.
- if the plug-in has successfully registered the custom node-type, the evaluation of the scene graph will produce the correct results. Maya considers this plug-in to be 'in-use'
- if the plug-in cannot be loaded, instances of your custom node-type will be categorised as "unknown" when queried because Maya does not have the blue-print for the node-type. Whenever there is an "unknown" node in the scene, Maya prints an error warning of potential data-loss.
What is less known is that the plug-in's name and node-type(s) is recorded into Maya's plug-in database whether the plug-in loads or not. Maya makes the assumption that the requires command is included in the file header because the plug-in registers a node-type that is required to define some data in your scene.
When the scene file is next saved, Maya will record a new requires command for every plug-in that it 'in-use' or might define some data in the scene file.
As scenes evolve and pass through the pipeline, and plug-ins become redundant, scene files accumulate references to plug-ins that no longer define data in the scene file.
The following examples demonstrate how to identify which plug-ins will be written to the next scene file, and how to prevent this.
I. How to remove a loaded plug-in from the scene file : Mayatomr
When the Mayatomr plug-in initialises, it registers new node-types and immediately adds custom nodes to your scene.
Let me demonstrate that because these custom nodes are saved with the scene, Maya writes a requires command for the Mayatomr plug-in:
- open Maya 2015 and ensure that the Mayatomr plug-in is not set to Autoload
- load the Mayatomr plug-in
- the plug-in adds custom nodes to the scene, creating a dependency on certain node-types registered by the plug-in. Executing this command shows that the plug-in is considered 'in-use':
pluginInfo -query -pluginsInUse;
// Result: Mayatomr 2015.0 - 3.12.1.18 - save the scene as "test.ma"
- in a new scene, unload the Mayatomr plug-in
- load the scene "test.ma" and notice that the Mayatomr is reloaded
You cannot simply unload the plug-in, as Maya will prevent you from doing this as it knows the plug-in defines a service, eg a node-type, that is 'in-use'.
To prevent Maya from recording a requires command and therefore loading the plug-in again on file open, it is necessary to remove all nodes with a dependency on the plug-in from your scene. - query the node-types registered by Mayatomr:
string $nodeTypes[] = `pluginInfo -query -dependNode Mayatomr`; - identify and delete instances of any of these node-types:
//
string $type = "";
for ($type in $nodeTypes)
{
string $node = "";
string $nodes[] = `ls -type $type`;
for ($node in $nodes)
{
lockNode -lock 0 $node;
delete $node;
}
}
//remove all references to Mayatomr nodes on the undo list
flushUndo;
// - query whether the Mayatomr is still 'in-use':
pluginInfo -query -pluginsInUse;
// Nothing to see here - save the scene again
By removing all instances of nodes defined by the Mayatomr plug-in, the plug-in is no longer considered 'in-use'.
Regardless of whether the plug-in is loaded, or not, if the scene contains no dependencies on the plug-in and the plug-in is not considered to be 'in-use', then Maya does not write a requires command to file.
II. How to identify and remove an unloaded plug-in from Maya's internal database
As previously mentioned, if the scene file contains a requires command for a plug-in that cannot be loaded, information about this plug-in (and any node-types which are assumed to be 'in-use' in the scene) is recorded in Maya's plug-in database and written into the next scene file.
Let's begin this example by creating a file with a dependency on a plug-in that is not in the MAYA_PLUG_IN_PATH:
- open Maya 2015 SP6 or Maya 2016 (previous versions do not include the MEL commands unknownPlugin and unknownNodes)
- load a plug-in that defines a node-type, but which is not in your MAYA_PLUG_IN_PATH; for example, "animCubeNode.py" from the Maya devkit samples
- create an instance of the plug-ins registered node-type
createNode spAnimCube;
// Result: spAnimCube1 // - query the list of plug-ins 'in-use':
pluginInfo -query -pluginsInUse;
// Result: animCubeNode.py Unknown // - save the scene file as "test.ma"
- restart Maya to remove all reference to "animCubeNode.py" from Maya's plug-in database
- open "test.ma" - there should be errors in the Script Editor because the plug-in cannot be loaded:
# Error: RuntimeError: file <maya console> line 1: Plug-in, "animCubeNode.py", was not found on MAYA_PLUG_IN_PATH. #
// Warning: Unrecognized node type 'spAnimCube'; preserving node information during this session. // - query the list of plug-ins 'in-use' - the pluginInfo command only works for loaded plug-ins
pluginInfo -query -pluginsInUse;
//
However, save the file again and look at the scene file in a text editor. Maya has retained the requires line to "animCubeNode.py".
This is how you remove it: - find all "unknown" nodes in the scene
string $node="";
string $unknownNodes[] = `ls -type "unknown"`; - identify the plug-in that defines the original node-type
for ($node in $unknownNodes)
{
string $plugin = `unknownNode -query -plugin $node`;
if ($plugin != "")
print ($node + " is defined by the plug-in " + $plugin + "\n");
}
As with the previous example, you cannot simply remove the reference to the plug-in because there are node dependencies in the scene, which must be removed first.
unknownPlugin -remove animCubeNode.py;
// Error: line 1: Plug-in cannot be removed - node/data type defined by it still in use. // - remove the nodes with a dependency on the "animCubeNode.py" plug-in
/* remove the unloaded plug-in "animCubeNode.py" from the internal database by deleting node dependencies */
string $node="";
string $unknownNodes[] = `ls -type "unknown"`;
string $pluginOfInterest = "animCubeNode.py";
for ($node in $unknownNodes)
{
string $plugin = `unknownNode -query -plugin $node`;
if ($plugin == $pluginOfInterest)
{
lockNode -lock 0 $node;
delete $node;
}
}
// remove references to animCubeNode on the undo list
flushUndo;
// - In a new Maya session, load the scene file and check for the "animCubeNode.py" plug-in:
unknownPlugin -query -list;
// nothing to see here
unknownPlugin -remove animCubeNode.py
// Error: No matching unknown plug-in. //
As demonstrated with the Mayatomr example, after all node dependencies have been removed, Maya no longer considers the plug-in to be required and will not write a requires command for it.
III. remove all other references to unknown plug-ins
As we've seen, removing all nodes of the type defined by a plug-in is the best way to prevent Maya from writing a "requires" line for this plug-in to the scene file.
Occasionally your scene will still contain references to plug-ins which have no apparent dependencies in the scene at all. References to these plug-ins will persist into the next scene file but can be identified and removed without any risk as the following example demonstrates.
Let's begin by creating a reference to a dummy plug-in:
- open Maya 2015 SP6 or Maya 2016 (previous versions do not include the MEL command unknownPlugin)
- execute the following line to add a dummy plug-in to the database
requires "dummyPlugin" "1.0"; - save the scene as "test.ma"
Maya includes a reference to this plug-in in the scene file, although this is clearly no reason to do so. - remove the plug-in with the unknownPlugin command
/* first reduce the list of unknownPlugins by removing unknownNodes, as demonstrated in the previous example. Then all remaining unknownPlugins can be removed with the following commands */
string $plugin;
string $unknownPlugins[] = `unknownPlugin -query -list`;
for ($plugin in $unknownPlugins)
{
unknownPlugin -remove $plugin;
}
You now have all the elements to identify and remove plug-ins from your scene file, and effectively manage which plug-ins are recorded to scene file and loaded on file open.
A last word about working with references to external scene files, which also include "requires" commands.
When a reference is loaded, Maya ensures that all plug-ins 'in-use' are loaded. Now, when you save the host scene file, Maya writes a reference to these plug-ins even if the nodes belong in the referenced scene file.
It is strongly recommended that never try to remove plug-ins when your scene file contains file references. Instead open each file individually, remove the plug-ins there, and save the file again.
With the commands outlined in this tutorial, you could set-up a pre-file save callback function that removes unwanted plug-ins. You should never need to worry about your scene file containing redundant plug-in references again.
Thanks for reading !
Owen
Hi Owen,
These are all really great workarounds. Thanks for putting together this tutorial. However I am more interested in finding out whether there are plans to fix the core problem here which is,
a) Maya's "in use" criteria is pretty naive and doesn't seem to handle default nodes that haven't been used yet, or extension attributes, very well.
Just because a plugin added a default node doesn't mean the scene is actually using it. So either Maya should allow for more nuanced meanings for "in use", and/or it should encourage (by either raising an error/warning) plugin writers to only add default nodes on first-use of their tools.
Expanding the meaning of "in use" will also help reduce those spurious "unsaved changes" dialogs you get even when you haven't modified your scene.
b) Plugins need to make sure they delete any of their default nodes that aren't being used in uninitializePlugin. So plugins either need to maintain their own "really in use" flag, or use a new and improved Maya "in use" feature.
Is this something that could be addressed in future releases of Maya?
Thanks,
Sivanny
Posted by: Sivanny Selvakumar | 17/04/2015 at 12:18 AM