May 22
I saw a post on www.cgtalk.com where a user wanted to render the selected meshes bounding box as a render region using the current render settings. He gave this example:

I thought this was an interesting challege that the Python API could handle since it can access the M3dView class which lets you test points in the Maya 3d space and get what pixel they are at in the viewport. Here is the finished script, also posted in my downloads section:
rtRenderSelectedMeshesRegion.zip
Cheers,
Ryan
Apr 04
I am finally posting the poseReader plug-in I converted. You can find it in the downloads section here:
http://www.rtrowbridge.com/blog/downloads/
It was originally written by Michael B. Comet so the concept was created by him and he deserves the credit. I converted his C++ code into a Maya Python API plug-in. Hopefully with no bugs, but there very well could be some still lurking. If you find any feel free to tell me and I will look into fixing them. I think this was a good exercise in converting a plug-in. It helped me with understanding better how to read C++ into Python. Not that I will be doing that often but it is still a good learning experience.
This changes the poseReader from being a plug-in that must be compiled for every version of Maya to a plug-in that will work on any platform and for any version of Maya using Python. That’s pretty cool I think.
Feel free to pick it apart and learn from it.
Cheers,
RyanT
Mar 17
I saw a post on www.cgtalk.com requesting an example of how to create a compound attribute on a node. Here is a full working example with a detailed description of how it works following the example:
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
kcompUtilNodeTypeName = "compoundExampleNode"
kcompUtilNodeClassify = "utility/general"
kcompUtilNodeId = OpenMaya.MTypeId(0x87325)
# define a new matrixUtilNode class derived from the MPxNode class
class rtcompUtilNode(OpenMayaMPx.MPxNode):
# class variables
compIn = OpenMaya.MObject()
compOut = OpenMaya.MObject()
input = OpenMaya.MObject()
output = OpenMaya.MObject()
def __init__(self):
OpenMayaMPx.MPxNode.__init__(self)
# arguments ( self, MPlug, MDataBlock)
def compute(self, plug, dataBlock):
# if these attributes are requested, recompute their values
if plug == rtcompUtilNode.compOut or plug.parent() == rtcompUtilNode.compOut:
# get MDataHandle's to attributes
#
try:
input_dataHandle = dataBlock.inputValue( rtcompUtilNode.input )
except:
sys.stderr.write( "Failed to get MDataHandle inputValue input" )
raise
try:
output_dataHandle = dataBlock.outputValue( rtcompUtilNode.output )
except:
sys.stderr.write( "Failed to get MDataHandle outputValue output" )
raise
# get values from dataHandle
#
input_value = input_dataHandle.asFloat()
# set the output
output_dataHandle.setFloat(input_value)
# set the plug clean so maya knows it can update
dataBlock.setClean(plug)
else:
return OpenMaya.kUnknownParameter
return OpenMaya.MStatus.kSuccess
def nodeCreator():
return OpenMayaMPx.asMPxPtr( rtcompUtilNode() )
# create and initialize the attributes to the node
def nodeInitializer():
nAttr = OpenMaya.MFnNumericAttribute()
cAttr = OpenMaya.MFnCompoundAttribute()
# create input attributes
#
rtcompUtilNode.input = nAttr.create("input", "i", OpenMaya.MFnNumericData.kFloat, 0.0)
nAttr.setWritable(True)
nAttr.setStorable(True)
nAttr.setReadable(True)
nAttr.setKeyable(True)
rtcompUtilNode.output = nAttr.create("output", "o", OpenMaya.MFnNumericData.kFloat, 0.0)
nAttr.setWritable(False)
nAttr.setStorable(False)
nAttr.setReadable(True)
# create compound attribute
#
rtcompUtilNode.compIn = cAttr.create( "compIn", "ci" )
cAttr.addChild( rtcompUtilNode.input )
rtcompUtilNode.compOut = cAttr.create( "compOut", "co" )
cAttr.addChild( rtcompUtilNode.output )
# add attribues
#
rtcompUtilNode.addAttribute( rtcompUtilNode.compIn )
rtcompUtilNode.addAttribute( rtcompUtilNode.compOut )
# Setup which attributes affect each other
rtcompUtilNode.attributeAffects ( rtcompUtilNode.compIn, rtcompUtilNode.compOut )
# initialize the script plug-in
def initializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject, "Autodesk", "1.0", "Any")
try:
mplugin.registerNode( kcompUtilNodeTypeName, kcompUtilNodeId, nodeCreator, nodeInitializer, OpenMayaMPx.MPxNode.kDependNode, kcompUtilNodeClassify)
except:
sys.stderr.write( "Failed to register node: %s" % kcompUtilNodeTypeName )
raise
# uninitialize the script plug-in
def uninitializePlugin(mobject):
mplugin = OpenMayaMPx.MFnPlugin(mobject)
try:
mplugin.deregisterNode( kcompUtilNodeId )
except:
sys.stderr.write( "Failed to deregister node: %s" % kcompUtilNodeTypeName )
raise
Continue reading »
Feb 15
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.
Continue reading »
Feb 03
I found this out the hard way while working on my 4×4MatrixToTRS plugin. So I thought it would be handy to pass along. There are a few bugs with the MTransformationMatrix class when using Python. You can get around them, you just need to know about them to do so. The main bug seems to be that any function of this class that asks for RotationOrder &order will not work with Python. It will always throws an error.
So if you are attempting to get the Euler rotation in a certain order like I was then you need to find a work around. What I found was I just need to use the MTransformationMatrix.rotation() function to get the quaternion then I could use the MQuaternion.asEulerRotation() function and from there I could use the MEulerRotation functions to get what I needed. Here are two examples one that does not work that should and one that does work. I have let Autodesk know about this issue.
If you want to get the rotation value of the MTransformationMatrix class this is the wrong way to do it:
Continue reading »
Feb 03
I have been meaning to post this for some time well here it is finally. Hopefully this plugin is commented well enough to understand. I have included the source so you can tinker with it. I have also included an html file that looks like a traditional Maya Node help file. Which lists all the attributes and what they do.
Since the script is rather long I wont post it here. Please take a look at it and if you have any questions feel free to post or e-mail me.
You can find the new python plugin at my new downloads page.
Have fun!
-RyanT
Dec 09
I answered a question about working with meshes using the python API on cgtalk and thought I would go more in depth on it.
First if you have not written anything using the API you need to know where the documentation is. If I tell you about a class and a function in that class you will only know about what I tell you and that is not very helpful. I looked on Autodesks website and found the latest documentation. This is for Maya 2009. Now there are changes between versions but the main reason for pointing you to this version is they reorganized the pages and added some new help. Also since this is how they will look from now on you should get familiar with it. The location of the docs are here:
Python Command
http://download.autodesk.com/us/maya/2009help/CommandsPython/index.html
Python API
http://download.autodesk.com/us/maya/2009help/API/main.html
Maya has two main ways to interact with it, using either Maya Commands or Maya API. Almost any time a MEL command is created it is also available to Python. There are some exceptions though. Autodesk did not make any of the string MEL commands available to Python because those are specifically made for MEL and do not apply to Python which already has a stronger suite of string functions. This also applies to the MEL commands that interact with your system like creating and reading files and printing to them.
Open up the Python API document and click on the Classes tab. This will show you all the classes available to you with C++ and Python. By default this tab shows the Alphabetical List. With this form of the documentation you also get the “Class List” tab which shows short descriptions of each class.
Today I will show how to get some information from a mesh. This Python script is using the API but a nice feature about Python is you do not need to create a Plugin to do this. It is fine to do so, but you dont have to like you do with C++. So even if you are writing a C++ plugin you could use Python just to quickly build up an idea of what your going to write just doing it in the script editor. No compiling!
Copy and paste this into a Python tab in your script editor and make sure to have a mesh selected so that it has something to work with:
Continue reading »
Nov 07
The last time I spoke about how to setup a MMatrix and use it with python. By default there are no vector classes that are part of python. This is not a problem since you can use the Maya API.
The MVector is actualy much easier to work with. You do not need to use the MScriptUtil class with MVector’s you can just simply give it a default value and start working with the new object. For example:
# Import the general maya API classes
import maya.OpenMaya as OpenMaya
# Create two MVectors
vectorA = OpenMaya.MVector(1.0, 1.0, 1.0)
vectorB = OpenMaya.MVector(2.0, 2.0, 2.0)
# Do some operations on them
vectorC = (vectorA + vectorB)
vectorD = (vectorA - vectorB)
# vectorC after adding vectorA and vectorB
print vectorC.x
print vectorC.y
print vectorC.z
# vectorD after subtracting vectorA and vectorB
print vectorD.x
print vectorD.y
print vectorD.z
# get the length of vectorC
print vectorC.length()
# normalize vectorC
vectorC.normalize()
# print the new normalized values
print vectorC.x
print vectorC.y
print vectorC.z
Note that if you want more information on the MVector class you can look it up in the Maya help documents.
Hopefully that helps!
-RyanT
Nov 05
I have talked to a few people that think there are no good ways to deal with Vectors or Matrices in Python. I wanted to present an example of how to use the Maya API to create an MMatrix class and introduce how the MScriptUtil class works to deal with API functions that use pointers.
# 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
Continue reading »
Recent Comments