API Guide

Using the Maya Python API
It is possible to write basic scripts that use the wrapper, iterator and function set classes of the Maya API. These scripts can query and manipulate the Maya model but are not fully integrated into Maya. A scripted plug-in provides a more complex solution that is tightly integrated into Maya. In this section, we discuss how to write both basic and scripted plug-in scripts along with standalone scripts. As this is a Python based API, knowledge of Python is required.

Importing modules
The Maya Python API is contained in a number of Python modules. You must import the functionality that you wish to use in your script. Additionally, the Maya Python API lives in the Maya namespace; therefore, an extra prefix is required. To import the OpenMaya module, run the following:
import maya.OpenMaya

Help on a module or class
Information can be displayed about any of the modules or classes using the help command. For example, if you wish to display the class information for MVector, use: help(maya.OpenMaya.MVector) It is also possible to display the information of an entire module: help(maya.OpenMaya) This operation will take a while to return since the OpenMaya module is very large.

Writing scripts
The Maya Python API modules contain the classes that are available for Python programming. These classes are separated into different categories and have appropriate naming conventions to signify their association. Classes include: MFn Any class with this prefix is a function set used to operate on MObjects of a particular type. MIt These classes are iterators and work on MObjects similar to the way a function set does. For example, MItCurveCV is used to operate on an individual NURBS curve CV (there is no MFnNurbsCurveCV), or, iteratively, on all the CVs of a curve. MPx Classes with this prefix are all “Proxies”, that is, API classes designed for you to derive from and create your own object types.

1.attribute( attrName ) plug = OpenMaya. attrObject ) return plug # Find the persp camera node print "Find the persp camera".MVector(0. MIntArray.OpenMaya as OpenMaya vector1 = OpenMaya.name() print "Plug value %g" % translatePlug. although not all.M classes Most.OpenMaya.asDouble() The example above demonstrates the following: To instantiate a class.2) newVector = vector1 + vector2 + vector3 print "newVector %f.OpenMaya. Scripted plug-ins allow a developer to support functionality such as the undoing of commands and the building of appropriate requires lines into the Maya scene file. MObjects can be created using node = OpenMaya.MPlug( nodeObject. We can use wrapper and function set classes to write scripts such as the following: import maya.apiTypeStr() # Print the translateX value translatePlug = nameToNodePlug( "translateX". %f " % (newVector. .getDependNode( 0.MObject(). Note For the sake of clarity.1. Another advantage of using a scripted plug-in is that its functionality is available in both MEL and Python.OpenMaya as OpenMaya # function that returns a node object given a name def nameToNode( name ): selectionList = OpenMaya.MObject() selectionList.0) vector3 = maya. The following is a script that finds the persp node and prints out its translateX attribute value: # import the OpenMaya module import maya. Examples of this class are: MVector. use the fn = OpenMaya.y. perspNode = nameToNode( "persp" ) print "APItype %d" % perspNode.MSelectionList() selectionList.add( name ) node = OpenMaya. you must instantiate the correct type in order to pass it as a parameter of the class.z) It is possible to shorten the symbol names used by modifying the import command: import maya. newVector.MFnFunctionSet() notation. nodeObject ): depNodeFn = OpenMaya. and so forth. %f.MFnDependencyNode( nodeObject ) attrObject = depNodeFn. node ) return node # function that finds a plug given a node object and plug name def nameToNodePlug( attrName. Although Python is a typeless language.MVector(1.OpenMaya vector1 = maya.OpenMaya. Python strings are passed and returned in place of the MString wrapper class. the example above has omitted error checking.apiType() print "APItype string %s" % perspNode. newVector.x. of these classes are “Wrappers”.0. Scripted plug-ins Scripted plug-ins allow a developer to create a solution that is tightly coupled with Maya.MVector(0.MVector(0.0) vector2 = maya. perspNode ) print "Plug name: %s" % translatePlug.0.0) Scripts can access dependency graph information using the Maya Python API classes.

py”) The load and execute steps can also be invoked in the MEL editor using: . Warnings will be issued that entry points cannot be found.unloadPlugin(“helixCmd.cmds.py. Any file ending with a . these items will not load.loadPlugin() command To run an example such as helixCmd. The plug-in can either be loaded from the Plug-in Manager or from the MEL or Python command tabs. Invoking this Python script does the following: Import the Maya module so that the cmds module becomes available Invoke the custom command spHelix() Notes The sp prefix is used for “scripted plug-in”.cmds. load the plug-in and enter the following in the Python Editor tab: import maya maya.Using a scripted plug-in We have extended the Maya Plug-in Manager to support the loading and unloading of scripted plug-ins. Scripted plug-ins must be loaded using the loadPlugin command. use the maya. Select the Loaded check-box or the Auto load check box to either load or auto-load the scripted plug-in. it is possible to have a non scripted plug-in . In MEL.py script on the MAYA_PLUG_IN_PATH. This plug-in can also be unloaded using the Python command: maya.cmds.spHelix(). In Python.py extension that is on the MAYA_PLUG_IN_PATH is displayed in the Plug-in Manager. use the loadPlugin() command. Note Although. It cannot be loaded by running the source of a scripted plug-in.

Implement the required functionality of the proxy class. import polyModifier Any secondary scripts must be located in the same directory as the scripted plug-in. all proxy nodes are registered: # Initialize the script plug-in def initializePlugin(mobject): mplugin = OpenMayaMPx. Register and unregister the proxy class within these entry points. Importing Python uses the import keyword to include functionality from a module into a script.write( "Failed to unregister command: %s\n" % kPluginCmdName ) raise .OpenMaya as OpenMaya import maya. during the load. spHelix(). The following sections describe these pieces in more detail with examples. Maya searches for an uninitializePlugin() function. For example: import maya. the scripted plug-in fails to load. Scripted plug-in uninitialization When Maya is attempting to unload the plug-in.stderr.py. If this is not found. The scripted plug-in must: Define initializePlugin and uninitializePlugin entry points. cmdCreator ) except: sys. Scripted plug-in initialization When a scripted plug-in is loaded. Within this function. This requires importing the necessary modules. the previously found uninitializePlugin() function is called to unload the resources of the plug-in.write( "Failed to register command: %s\n" % kPluginCmdName ) raise If the initializePlugin() function is not found. The import command is used to load the functionality of the secondary file into the scripted plug-in.loadPlugin helixCmd. then the scripted plug-in fails to load.OpenMayaMPx as OpenMayaMPx import sys It is possible for a scripted plug-in to be split among several files.stderr. Implement creator and initialize methods (as required) which Maya calls to build the proxy class.registerCommand( kPluginCmdName.MFnPlugin(mobject) try: mplugin. Maya searches for an initializePlugin() function in its definition. def uninitializePlugin(mobject): mplugin = OpenMayaMPx. Writing a scripted plug-in Writing a scripted plug-in requires the definition of some specialized functions within the plug-in. In addition.MFnPlugin(mobject) try: mplugin.deregisterCommand( kPluginCmdName ) except: sys.

"in".outputValue( sineNode.__init__(self) def doIt(self.plug.MPxCommand): def __init__(self): OpenMayaMPx.create( "output". This call transfers ownership of the object from Python to Maya.MFnNumericData.MPxNode): # class variables input = OpenMaya. class scriptedCommand(OpenMayaMPx.sin( inputFloat ) * 10.kFloat. 0. followed by the normal argument list. def cmdCreator(): return OpenMayaMPx.argList): print "Hello World!" The scriptedCommand class is derived from OpenMayaMPx.input = nAttr.0 outputHandle = dataBlock.MPxCommand): # .asMPxPtr( scriptedCommand() ) It is very important to call the OpenMayaMPx.. This will leave a dangling pointer in Maya. The constructor or __init__ method must call the parent class __init__ method.0 ) .__init__(self) def compute(self. Virtual methods are implemented on the derived class which are called from Maya.MFnNumericAttribute(). OpenMaya.output ) outputHandle. sineNode.OpenMaya as OpenMaya import maya.setClean( plug ) # creator def nodeCreator(): return OpenMayaMPx.asMPxPtr() on the newly created proxy object.MTypeId(0x8700) # Node definition class sineNode(OpenMayaMPx.inputValue( sineNode.MPxNode. the output of which is the sine function. Class implementation Implementing a proxy class requires deriving from the Maya Python API object.MPxCommand.MFnNumericAttribute(). This command’s doIt() method simply prints out “Hello World!”.OpenMayaMPx as OpenMayaMPx kPluginNodeTypeName = "spSineNode" sineNodeId = OpenMaya.output ): dataHandle = dataBlock.0 ) nAttr.asFloat() result = math.MObject() output = OpenMaya.create( "input". "out". 0.input ) inputFloat = dataHandle. Initialization Functions Initialization functions are used within scripted plug-ins that define new proxy nodes using the MPxNode class.output = nAttr.Creator functions Creator functions are used to return a derived version of a proxy class to Maya.MPxCommand.dataBlock): if ( plug == sineNode..MFnNumericData. OpenMaya. sineNode.setFloat( result ) dataBlock. An example of a class definition and a creator function is: class scriptedCommand(OpenMayaMPx. sys import maya. Program errors will occur if you do not make this call since Python can unreference this object and destroy it.MObject() def __init__(self): OpenMayaMPx. The following is an example that demonstrates how to create a simple scripted plug-in node. import math.asMPxPtr( sineNode() ) # initializer def nodeInitializer(): # input nAttr = OpenMaya.kFloat.setStorable(1) # output nAttr = OpenMaya. All class methods require self as the first parameter.

Error Conditions The Maya Python API uses Python exceptions for querying and setting error states in script.stderr.MFnPlugin(mobject) try: mplugin.setWritable(1) # add attributes sineNode.registerNode( kPluginNodeTypeName. As the plug-in loads.addAttribute( sineNode.MFnPlugin(mobject) try: mplugin.stderr.nAttr.write( "Failed to register node: %s" % kPluginNodeTypeName ) raise # uninitialize the script plug-in def uninitializePlugin(mobject): mplugin = OpenMayaMPx. 2.stderr.write( "Failed to deregister node: %s" % kPluginNodeTypeName ) pass The only change being that the raise keyword has been changed to pass.write( "Failed to deregister node: %s" % kPluginNodeTypeName ) raise In this example. A call fails and the failure state needs to be cleared: This code can be modified to catch the error and still allow the plug-in to unload if the deregisterNode() call fails: def uninitializePlugin(mobject): mplugin = OpenMayaMPx.output ) # initialize the script plug-in def initializePlugin(mobject): mplugin = OpenMayaMPx. In most cases. Unknown parameter return value In the Maya Python API. exceptions are used even though the class documentation indicates that a method has a return value.addAttribute( sineNode. sineNodeId. sineNode.setStorable(1) nAttr. This technique is useful for writing iterator code that may fail if incorrect objects are being examined. an unknown parameter return value is used to indicate that a method cannot handle a specific case and it is up to the caller to take care of the operation. A call fails and the failure state needs to be preserved: def uninitializePlugin(mobject): mplugin = OpenMayaMPx. the uninitializePlugin() call passes the exception back to Maya and the plug-in fails to unload.input. One such . if the deregisterNode() call failed. There are many situations where an exception can occur: 1.output ) sineNode.stderr.input ) sineNode.deregisterNode( sineNodeId ) except: sys.MFnPlugin(mobject) try: mplugin.deregisterNode( sineNodeId ) except: sys. nodeCreator.MFnPlugin(mobject) try: mplugin.deregisterNode( sineNodeId ) except: sys.write( "Failed to register node: %s" % kPluginNodeTypeName ) raise The nodeInitializer() function is passed to registerNode() in the initializePlugin() function. 3. nodeInitializer ) except: sys. Maya calls the nodeInitializer() function to create the attributes of the node.attributeAffects( sineNode.

similar code can be used: envelope = OpenMayaMPx.x. 4.fullPathName() print "\tparent %s" % parent. In Python. parent. This includes attribute objects that are used to define the node.write( "Failed to install dag parent added callback\n" ) messageIdSet = False else: messageIdSet = True return id # Call the message creator messageId = createParentAddedCallback( "_noData_" ) Modify Parameter Values Instead of Using an Assignment In Python.OpenMaya as OpenMaya array = OpenMaya." print "\tchild %s" % child.method is MPxNode::compute(). MUint64Array.MVector() vectorTest(v) print “%g %g %g” % (v.9): array. A Python function is passed for the callback.v. an exception will occur when the message is invoked and information will be written to the console.v. Client data in the form of a python object can also be passed with most messages. 6] # Accessing static MObjects of an MPx class The proxy classes provide some standard information to a developer about the node that is being used. MFloatArray. MUintArray.addParentAddedCallback( dagParentAddedCallback.5. either modify the parameter value or write the code so that a new value is returned.MPxDeformerNode_envelope After making this call.fullPathName() print "\tclient data %s" % clientData # Create the mesage def createParentAddedCallback(stringData): try: id = OpenMaya. it is best to modify a parameter rather than using an assignment. and MDoubleArray) support Python-style slicing.MVector(1. Messages Message classes are supported in the Maya Python API.z) v = OpenMaya.y. The following is an example of a message: # Message callback def dagParentAddedCallback( child. If it does not.append( i ) array[2:8:2] # Result:[2.v. This function must have the exact number of parameters required by the callback message.MUintArray() for i in range(0. the Python code would return OpenMaya. Rewrite the vectorTest() function as follows: .y. clientData ): print "dagParentAddedCallback.cvar. stringData ) except: sys. For example: import maya.x.stderr. The code below contains an assignment and demonstrates how an error can occur: import maya. To access a static class MObject in the Maya Python API..MDagMessage.v.9) v = lv print "%g %g %g" % (v. In this situation. the envelope will be an MObject for MPxDeformerNode::envelope. Classes support slicing All of the number arrays (MIntArray.kUnknownParameter..z) The second print command will emit all zeroes.OpenMaya as OpenMaya def vectorTest(v): lv = OpenMaya.

py module is used to create.MObject() try: # This plugin normally creates the curve by passing in the # cv's.__init__(self) def doIt(self. See the following code for an example: import maya.MPointArray() knotSequences = OpenMaya.MFnNurbsCurve.5.y v. argData = OpenMaya.y = lv. nknots): knotSequences.v. deg.MDoubleArray() # Set up cvs and knots for the helix # for i in range(0.sin(i) ) ) for i in range(0. As a result.MPoint( radius * math. float& etc.MVector(1. 0.isFlagSet(kPitchFlag): pitch = argData.MPxCommand): def __init__(self): OpenMayaMPx.OpenMaya as OpenMaya import maya.isFlagSet(kRadiusFlag): radius = argData. math kPluginCmdName="spHelix" kPitchFlag = "-p" kPitchLongFlag = "-pitch" kRadiusFlag = "-r" kRadiusLongFlag = "-radius" # command class scriptedCommand(OpenMayaMPx. 0) if argData.x v. # if True: curveFn.9) v.create( controlVertices. args) if argData.5 # Parse the arguments. ncvs): controlVertices. get and set values of these types.MPxCommand.cos(i). 0) controlVertices = OpenMaya.def vectorTest(v): lv = OpenMaya.y. char&.OpenMayaMPx as OpenMayaMPx import sys.flagArgumentDouble(kPitchFlag.kOpen.syntax().z = lv.v.x = lv. set and access the values of these items.MArgDatabase(self. special calls are required to create. Commands with Arguments Commands with arguments must use the MSyntax and MArgParser classes within a scripted MPxCommand. Set this to False to get that behaviour. A utility class called MScriptUtil that exists in the OpenMaya.flagArgumentDouble(kRadiusFlag.append( i ) # Now create the curve # curveFn = OpenMaya.append( OpenMaya.x. args): deg = 3 ncvs = 20 spans = ncvs . knotSequences.z print "%g %g %g" % (v. all references are treated as pointers. In the Maya Python API. nullObj ) .deg nknots = spans+2*deg-1 radius = 4.MFnNurbsCurve() nullObj = OpenMaya. OpenMaya. radius * math.z) References to Basic Types The Maya Python API contains many calls in which return values or parameters are references to basic types such as: int&. A function to create curves by passing in the ep's # has been added. 0.0 pitch = 0. pitch * i.

addFlag(kPitchFlag. False.MFnPlugin(mobject. OpenMaya.write( "Error creating curve. kTrackingDictionary = {} 2.write( "Failed to unregister command: %s\n" % kPluginCmdName ) raise sys.else: OpenMaya.createWithEditPoints(controlVertices.\n" ) raise False. As a result. Protected methods The Maya Python API contains several methods that should only be called from the class the method belongs to.MSyntax() syntax. kPitchLongFlag. these pointer values are not the same as the self of a Python class. there are methods that are creators of classes that can exist outside of the class. "Any") try: mplugin. kRadiusLongFlag. False) curveFn. you wish to maintain a vector as a class variable.stderr. We follow the Python designation of using an _ as the first letter of the method name to indicate that protection applies to this method. . it is natural to define methods within the Python class for handling the getting and setting of state.asHashable() method to store self in the dictionary.stderr.registerCommand( kPluginCmdName. except: # Creator def cmdCreator(): # Create the command return OpenMayaMPx.kDouble) return syntax # Initialize the script plug-in def initializePlugin(mobject): mplugin = OpenMayaMPx.MSyntax. Follow these steps: 1. Several examples of these methods exist in the MPxNode class: _forceCache() _setMPSafe() Please respect the method usage requirements of protected methods in the Maya Python API. A workaround using a dictionary and a special function OpenMayaMPx. "1. these methods return a pointer value.MSyntax. use the OpenMayaMPx. This example includes the syntax creator function along with parsing operations in the doIt() method of the class.0". syntaxCreator ) except: sys. For example. Often. Within the Maya Python API.MFnNurbsCurve. cmdCreator.kOpen. Need self but only API object is available When implementing a proxy class in Python.kDouble) syntax.asHashable() makes this possible.addFlag(kRadiusFlag. In the initialization method of the object of interest.stderr.write( "Failed to register command: %s\n" % kPluginCmdName ) raise # Uninitialize the script plug-in def uninitializePlugin(mobject): mplugin = OpenMayaMPx. Declare a dictionary object. there is no straight forward way to access the class variables defined on self.asMPxPtr( scriptedCommand() ) # Syntax creator def syntaxCreator(): syntax = OpenMaya.MFnPlugin(mobject) try: mplugin. "Autodesk". 3. OpenMaya.deregisterCommand( kPluginCmdName ) except: sys. In the Maya Python API.

value notation such as: OpenMaya. This is done using notation such as the following: matrix = OpenMayaMPx. a MStreamUtils class is available for creating and using these type of objects.def __init__(self): OpenMayaMPx.asHashable(newCmd).0) 4.asHashable(self)] = self 3. 0. see the Development Kit. A simple “hello world” standalone script follows: import maya. Operating System Types There are some methods in the Maya Python API that require <iosteam> operating system types.MHardwareRenderer. None) # Set the class variable self.MPxTransformationMatrix.MSyntax.0. These scripts are run from the command line. the scripts will require calling into the parent class.glFunctionTable() Standalone Scripts It is possible to write standalone scripts that make use of the wrapper classes and function sets to modify the Maya model.write( "Failed in initialize standalone application" ) .asMatrix(self) Enum values Enum values are accessed using a moduleName.__delta = OpenMaya._newToolCommand() # Use pointer to get to self of the command self.MPxToolCommand.0. Retrieve self from the dictionary using the pointer.standalone import maya.__init__(self) self.__cmd = kTrackingDictionary.initialize( name='python' ) except: sys.className.setVector(0.OpenMaya as OpenMaya import sys def main( argv = None ): try: maya.theRenderer() glFT = glRenderer. # Code is in a different class # Pointer is returned newCmd = self. As these are not included in Python.asHashable(self)] For examples that demonstrate these principles.setCommandString(kPluginCmdName) self. Please check the Development kit for examples on how to use this class. 0.stderr.kDouble Using OpenGL We have provided a wrapper class MGLFunctionTable for using OpenGL functionality in script on all of our support platforms.standalone. To acquire a reference to this class use the following code: glRenderer = OpenMayaRender.MVector() kTrackingDictionary[OpenMayaMPx. Clean up the tracking dictionary.get(OpenMayaMPx. Calling into the Parent class Often when writing an MPx proxy class. def __del__(self): del kTrackingDictionary[OpenMayaMPx.__cmd.

MGlobal(). For example: $MAYA_LOCATION/bin/mayapy helloWorld. function sets and wrapper classes can be used to create and modify a Maya model.stderr.raise sys. This script must be run using the Python executable that is supplied with Maya.executeCommand( "print \"Hello world! (command script output)\\n\"" ) if __name__ == "__main__": main() After the standalone is initialized.py .write( "Hello world! (script output)\n" ) OpenMaya.

Sign up to vote on this title
UsefulNot useful