Introduction to the Maya API

Object Types

The Maya API consists of four types of C++ objects: wrappers, objects, function sets, and proxies.

Wrappers

A wrapper is simply a convenience class for a data or mathematical structure. The Maya API includes wrappers for arrays, vectors, matrices, quaternions, etc. Wrappers also include utility tools such as selection lists, DAG paths, viewports, etc. These classes start with the “M” prefix. Examples include MIntArray, MFloatArray, MMatrix, MVector, MQuaternion, MPlane, MPointArray, MSelectionList, etc.

Wrappers also include iterators, which are classes used to traverse over sequences of data. There are iterators to traverse Maya’s dependency graph, to iterate over a meshes vertices, edges, and faces, to iterate over a surfaces cvs, etc. Iterator classes are prefixed with “MIt” and include MItMesh, MItDependencyGraph, MItKeyFrame, MItMeshEdge, MItSurfaceCV, etc.

Objects

An object, known as an MObject, is the generic base class that represents all Maya objects (curves, surfaces, DAG nodes, DG nodes, lights, shaders, textures, IK solvers, dynamics fields, etc). This common base allows many different types of MObjects to be passed through the API and lets API developers take advantage of the inheritance structure of all the nodes in Maya. Each instance of an MObject represents either a node or an attribute on a node. However, an MObject is not really the actual node or attribute, but rather a handle to the node or attribute. This is so Maya can maintain ownership of the nodes and attributes and make sure it runs all the necessary routines to keep Maya running smoothly. Because an MObject is a pointer to an internal Maya object, you should not hang on to MObjects between calls to your plug-in as Maya may move these internal objects around in memory making your MObject invalid. To access specific functionality of the data that an MObject represents, we use function sets.

Function Sets

Because MObjects are the base class for all nodes, it is not practical to include all the functions necessary to interact with the node in the MObject class. The functions that operate on a specific type of node are broken into C++ classes called function sets. For example there are function sets for cameras, skin clusters, IK handles, meshes, surfaces, transforms, etc. Function sets operate on MObjects. The general workflow for objects and function sets is to determine what function set an object is compatible with, using the MFn::Type enumeration, and then attaching that function set to the object:

if (obj.hasFn(MFn::kMesh)) {
  MFnMesh fnMesh(obj);
}
if obj.hasFn(OpenMaya.MFn.kMesh):
    fnMesh = OpenMaya.MFnMesh(obj)

Often, you will already know the type of data that an MObject represents and won’t need to explicitly check the type of data. Function set classes are prefixed with “MFn”. Examples include MFnMesh, MFnNurbsCurve, MFnDagNode, MFnLatticeDeformer, MFnRenderPass, etc.

The object/function set workflow creates a separation of data vs. functionality, which differentiates from classic OOP where a class usually encapsulates both data and functionality to operate on the data. In Maya, data is represented with MObjects and functionality is achieved with function sets.

Proxies

Proxies are the abstract classes that plug-in developers use to implement new types of Maya objects such as custom nodes, deformers, ik solvers, commands, transforms, etc. When developing a new object, we create a new class that inherits from one of these proxy classes and then implement all the required functions. Proxy classes are prefixed with “MPx” and include MPxNode, MPxDeformerNode, MPxConstraint, MPxCommand, MPxIkSolver, etc.

Error Checking

Error checking in C++ is done with the MStatus class. Most functions in the API accept or return an MStatus variable. We can query this variable to determine if a specific function succeeded or not. If a function fails, the MStatus variable contains information about why the function failed. It is important to check for these errors because when functions fail in the Maya API, they fail silently. There will be no warning, the rest of the code may just not work or Maya might just crash. Therefore, you should always check if a function succeeded with MStatus.

// oMesh is an MObject for a mesh object and so can’t be used with
// the NURBS surface function set
MFnNurbsSurface fnSurface(oMesh, &status);
if (status.error()) {
  std::cerr << "\nAPI error detected in " << __FILE__ << " at line " << __LINE__ << endl;
  status.perror("Something went wrong!");
}

The Maya API comes with a couple of useful macros for checking MStatus variables. These are:

CHECK_MSTATUS(status);
CHECK_MSTATUS_AND_RETURN_IT(status);

The CHECK_MSTATUS macro performs the same functionality as above. The CHECK_MSTATUS_AND_RETURN_IT macro is the same as CHECK_MSTATUS except it returns the status if it failed.

MStatus is not available with Python. When using the Maya API with Python, a failed function will throw an exception and you can use Python’s built-in error handling to deal with it.

try:
    fnSurface = OpenMaya.MFnNurbsSurface(oMesh)
except:
    print "Something went wrong!"

2 thoughts on “Introduction to the Maya API”

Leave A Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

<code> For inline code.
[sourcecode] For multiline code.