Someone sent me an e-mail trying to understand more about how to read the Maya API docs. Since they are written for C++ users it can be hard to understand them unless you understand a little more about C++. So below is my rather long winded answer. The only way you would completely understand this would be to read a C++ book but I think this gives most people a basic enough understanding that they can at least know what functions they can use, what to pass to those functions, and what to expect after doing that.
First off you find the Maya API documentation here:
http://download.autodesk.com/us/maya/2009help/API/classes.html
So lets say you are using this function:
MStatus MItMeshPolygon::getConnectedEdges ( MIntArray &edges )
Which you can find in the class:
MItMeshPolygon.
Class Function Return Data Type
MStatus MItMeshPolygon::getConnectedEdges ( MIntArray &edges )
MStatus is what the function will return when executed, in MEL it looks like:
global proc string foo()
The keyword string tells the procedure that it will return a string. In C++ you MUST define a variables type before putting that value into that type. Very much like MEL. So this would error:
string $foo = "value"; $foo = 1; >> Error: Line 1.13: Invalid redeclaration of variable "$foo" as a different type. //
So Autodesk shows the return data type at the beginning of the function.
MStatus MItMeshPolygon::getConnectedEdges ( MIntArray &edges )
This is important to C++ users, but not always to Python users.
Something to note and this is true 100% of the time. Anytime a Maya API function states that it returns a MStatus or it asks for a MStatus type you should pretend it doesnt exist when using Python for example:
MItMeshPolygon (const MDagPath &polyObject, MObject &component=MObject::kNullObj, MStatus *ReturnStatus=NULL)
In python you can only do this:
foo = OpenMaya.MItMeshPolygon( polyObject, component )
The MStatus argument is dropped, attempting to pass it a variable will produce an error.
Another note about returned types Python does not require or even allow you to define a parameter name as a type so you can type anything to get the data from a function. So it does not matter as much what it returns. The only time you need to know what the type is, if you need to work with what is returned so you can call that objects functions.
Class Function Name
MStatus MItMeshPolygon::getConnectedEdges ( MIntArray &edges )
The first word before the :: means the object class that this function is a part of. You already know what class this function is a part of because you looked up that class and are looking at the page of functions for that class. Things to note though and this can get confusing when coming out of a script language background like MEL. All the functions listed on the class object MItMeshPolygon page may not be all the functions it can call. It might have more. How can this be? Well some classes are derived from other classes. I cant give a MEL example since MEL has not such thing as a class.
But here is a python example:
class fruit(): def __init__(self): self.amount = 0 class apple(fruit): def __init__(self, amt): self.amount = amt # Return float value of how many pies the amount attribute will make # Eights apples to make a pie def bakepie(self): return (self.amount / 8.0) class bannana(fruit): def __init__(self, amt): self.amount = amt # Return float value of how many pies the amount attribute will make # Four bannans to make a pie def bakepie(self): return (self.amount / 4.0) fruitsack = apple( 25 ) print fruitsack.bakepie() >>3.125 fruitsack = bannana( 25 ) print fruitsack.bakepie() >>6.25
The apple and bannana classes derives from the fruit class. This means that the apple and bannana classes also has a .amount attribute. Even though they do not have that attribute themselves. In the Maya API many of the C++ classes have this. So sometimes you might be looking for a function that is avaiable within that very class but it is part of its derived functions.
The MFnDoubleArrayData class is a good example of this. It only has about eight functions, but if you click on its “List of all members” it also has functions from the classes MFnBase and MFnData. Go to this address to see it:
http://download.autodesk.com/us/maya/2009help/API/class_m_fn_double_array_data.html
Click on the “List of all members link.
Something you should also note is that a function which says “NO SCRIPT SUPPORT.” does not work in Python.
You can not call those functions. Many documented functions will describe other methods to use when your using Python. Simply click on that function and it will jump you to a description of that function. Sometimes you just have to find another way to do what your trying to do.
Class Function Arguments
MStatus MItMeshPolygon::getConnectedEdges ( MIntArray &edges )
This is the functions argument list. As I said before if one of the arguments is a MStatus argument. Ignore it and do not pass anything to that argument or you will get an error. In any case that you see a “&” character that means you are passing a variable as a reference. What this means is that the variable passed to that function can be changed in place and this allows a function in C++ to return data to several different variables at once. A function could change data in each of the referenced variables and also return data as well. Most of the time when you pass data as a reference to a function it only returns a MStatus object back to you, which in Python anything that returns a MStatus returns ‘None’ because the MStatus class is never used in the Python API.
In MEL you can do something like this when you pass an array to a procedure. If the procedure adds or removes anything from that array it will edit that array in place. So if you execute the code below:
global proc foobar( string $fooArray[] )
{
for($i=1; $i < 5; $i++)
{
$fooArray[size($fooArray)] = $i;
}
}
string $foo[];
foobar($foo);
print $foo;
>>1
>>2
>>3
>>4
The reason for this is the $foo array was passed as a reference. This is the only case where MEL does this.
C++ can do this with any variable. You recognize this by looking for the “&” next to an argument in the C++ API documentation.
Sometimes you will see arguments like MStatus with a “*” this means it is a pointer, which is another C++ thing. Examples of this are the MStatus class and the MString class. Neither of these classes are avalable for use with Python. In the case of a MString you simply should pass a regular Python string to class that lists a MString type argument.
In C++ you need to define a pointer before passing the argument to a reference. Python does not have either of these as part of its programming language. Because of this the MScriptUtil class implements methods for Python to create fake pointers to help it pass data to arugments where it normally could not.
The MScriptUtil class lets you define a pointer variable which you can then send to a Maya API function and then you need to use the MScriptUtil class to retrieve that data from the variable after the API function has done something with it.
# import mayas general API classes import maya.OpenMaya as OpenMaya # the MScriptUtil class is very important to python API users # it allows python users to pass variable to an API function like it were a pointer # Called by RTrunPointerExample() def RTpointerExample( ptr ): print 'ptr changed using MScriptUtil'; OpenMaya.MScriptUtil.setDouble ( ptr, 2.0 ) def RTrunPointerExample(): # Define a MScriptUtil object fooba = OpenMaya.MScriptUtil() # Define the pointer type # only use the types that end in Ptr ptr = fooba.asDoublePtr() # Set a value OpenMaya.MScriptUtil.setDouble ( ptr, 1.0 ) # Print that value print 'ptr = ', (OpenMaya.MScriptUtil.getDouble( ptr )) # Call a function passing it the pointer RTpointerExample( ptr ) # Print the new value print 'ptr = ', (OpenMaya.MScriptUtil.getDouble( ptr )) # execute this RTrunPointerExample() # which prints: >> ptr = 1.0 >> ptr changed using MScriptUtil >> ptr = 2.0
I have a few examples of how to use MScriptUtil on my site, either use my sites search tool or look here:
http://www.rtrowbridge.com/blog/2009/02/03/python-api-mtransformationmatrixgetrotation-bug/
http://www.rtrowbridge.com/blog/2008/11/07/python-and-api-mvectors/
http://www.rtrowbridge.com/blog/2008/11/05/vectors-and-matrices-in-python/
To further show how a reference variable is being used the documentation will display [in] and [out] next to its Parameters. This tells you what the intent of the referenced variable is. So if it says [in] you can forget what you passed to the variable. If it says [out] next to the parameter the function is attempting to change the referenced variable you passed to it. So if you passed a function a referenced MVector that was (0,0,0) it will be changed if you look at it after passing it to the function.
Other things to look for when reading the documentation:
Function Overloading
In C++ you can overload a function to accept several different types of data or to accept different amounts of arguments. For example look at the MVector class:
1. MVector ()
2. MVector (const MVector &)
3. MVector (const MFloatPoint &)
4. MVector (const MFloatVector &)
5. MVector (const MPoint &)
6. MVector (double xx, double yy, double zz=0.0)
7. MVector (const double d[3])
8. ~MVector ()
MVector() anytime a class calls itself as a “function” it is called a constructor in C++. This is how that class initializes itself and creates a object that can be referenced by a variable in Python.
1. MVector() just initializes that class object to default values. In Python it would look like this:
import maya.OpenMaya as OpenMaya
vec = OpenMaya.MVector()
2. MVector(const MVector &)
This overloaded version of the MVector constructor asks for another MVector, the Parameters section of this states it is a [in] parameter so you are passing a MVector in and it will return a MVector which is a copy of the MVector which you passed in. Python example:
import maya.OpenMaya as OpenMaya
vecA = OpenMaya.MVector()
vecB = OpenMaya.MVector( vecA )
3. MVector (const MFloatPoint &)
This overloaded version of the MVector constructor asks for a MFloatPoint class object. The parameter states it is passed [in] so you are passing the MFloatPoint class object in to change the MVector you are constructing.
mfpoint = OpenMaya.MFloatPoint()
vec = OpenMaya.MVector( mfpoint )
4. MVector (const MFloatVector &)
This overloaded version of the MVector constructor asks for a MFloatVector class object.
mfvector = OpenMaya.MFloatVector()
vec = OpenMaya.MVector( mfvector )
5. MVector (const MPoint &)
Now it is asking for a MPoint class object.
mpnt = OpenMaya.MPoint()
vec = OpenMaya.MVector( mpnt )
6. MVector (double xx, double yy, double zz=0.0)
Now it is asking for float values.
vec = OpenMaya.MVector( 1.0, 2.0, 3.0 )
7. MVector (const double d[3])
This is sketchy documentation. It technically must be passed as a reference. Python can not just pass it a
double array like this:
vec = openMaya.MVector( [1.0, 2.0, 3.0 ) >># Error: UnknownError: # >># Traceback (most recent call last): >># line 1 of>># line 8311 of file C:\buildforge\Maya_Main_Win64_Build\build\wrk\optim\runTime\Python\Lib\site-packages\maya\OpenMaya.py >>in module __init__ >># NotImplementedError: Wrong number of arguments for overloaded function 'new_MVector'. >># Possible C/C++ prototypes are: >># MVector() >># MVector(MVector const &) >># MVector(MFloatPoint const &) >># MVector(MFloatVector const &) >># MVector(MPoint const &) >># MVector(double,double,double) >># MVector(double const [3]) # #The correct way is this: doubleArray = OpenMaya.MScriptUtil() doubleArray.createFromList( [1.0, 2.0, 3.0], 3 ) doubleArrayPtr = doubleArray.asDoublePtr() vec = OpenMaya.MVector( doubleArrayPtr ) print vec.x, vec.y, vec.z
8. ~MVector ()
This is not callable by python, it is called a deconstructor and it is what is called when an object is
deleted from memory.
Class Operator Overloads
Anytime you see a class object that says operator this is simply C++ way of overloading operators like + - / * []. Sometimes these are supported for the specific class so Python users can use it. Sometimes it is not. Python can overload operators as well, I have two blog posts explaining how to do this:
http://www.rtrowbridge.com/blog/2009/02/10/python-class-operator-overloading/
http://www.rtrowbridge.com/blog/2009/02/13/python-class-operator-overloading-part-2/
Class Function Friends (Are Not Pythons Friend)
Sometimes a class has friend functions. These are functions that in C++ are shared between other classes. So they are kind of like public property, you may use it but no one owns it. Python doesnt have any way of accessing these functions as far as I know.
Class Protected Members
Any function that is in a list under the header “Protected Member Functions” is private to that function and can not be accessed outside of it. Even with C++. An example class that has this is the MFnComponent class. The className() function is protected.
Well that is your crash course in translating C++ into Python. If I forgot something I will add it here.
Cheers,
-RyanT
June 21st, 2009 at 7:18 am
Great post again. I’m slowly starting to get into it.
July 20th, 2009 at 10:18 pm
I found this really helpful. Thanks.
September 23rd, 2009 at 1:02 pm
This is very useful, I was look for how to get pointer variable being used in open maya however the document by autodesk is badly written.
Thanks a lot man
October 19th, 2009 at 11:29 pm
great work. you can exhaust the cases
January 19th, 2010 at 6:58 pm
+1 - super awesome. Thanks for taking the time to share!