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

May 18

In response to an e-mail I received I wrote back this response. I figured I would post it.

So I was given this example and asked what the u charter was for in front of each string name returned in the list.


aList = cmds.ls(selection=True)
print aList

>>[u'pSphere1', u'pSphere2', u'pSphere3', u'pSphere4']

The long and the short of it is Unicode allows more characters than ASCII. ASCII can hold 256 values and Unicode can hold 65,536 values. This allows computers to support complex languages with many characters. If you want a more complex explanation go here:

http://www.amk.ca/python/howto/unicode

Getting back to the example. So the aList returns a list of string names using Python Unicode. Thats what the u stands for. It shouldnt bother you though nor affect anything.

So if you have two spheres in your scene and you run this in the script editor it will return u’pSphere2′ and u’pSphere1′ like this:


import maya.cmds as cmds

getlist = cmds.ls(sl=True)
print getlist
>>[u'pSphere2', u'pSphere1']

Continue reading »

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 »

Mar 12

I saw this screenshot which shows how the muscles flex on Fight Nighty Round 4 and I had to post something. The character TD’s working on Fight Night Round 4 deserve a pat on the back for their great work. Check out this screenshot from their game which was recently posted on www.ign.com

By the way I will be posting new Python examples soon. We have been really busy at work and I have not had the time to do any updates.

For those that have used Michael Comet’s Pose Reader I converted it to Python and will be posting that soon. His Pose Reader is a great way for driving muscles in the way these guys are showing above. The Pose Reader he wrote allows you to basicly take a snapshot of where a transform currently is. Then you can adjust a cone to check how close the specified transform is to the snapshot. The closer it is the closer the value changes from 0 to 1. You can use this value to drive whatever you need. Its really cool and very useful.

I have not used his Pose Deformer node for anything but I am working on converting that to Python as well. I will pose a zip with his C++ code and the Python code so people can learn from it.

Later,
RyanT

Feb 24

I saw users on www.cgtalk.com talking about this and I thought I would post it to show how Python is bridging the gap not only between MEL and the C++ API in Maya. But Python is bridging the gap between software as well.

Here are the steps to make Python work in 3ds Max.

# Step 1: Download Python Version x.x any version at http://www.python.org/download/
# Step 2: Download and install pywin32 which has the win32com python module in it here: http://sourceforge.net/projects/pywin32/
# Step 3: Make sure to download the win32com for the python version you have downloaded
# Step 4: Open up the Python IDLE Shell and select File\New Window
# Step 5: Copy and paste this code, written by David Mackenzie and posted on cgtalk.com:

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 13

I was curious if it was possible to overload the [] operators twice in a row to imitate a matrix while still using a single array. Someone gave me an example to go off of and here is a working example of how to make a flatMatrix class in python.

Try this in the Python script tab in Maya:

class SubItem:

	def __init__(self, parent, idx):
		self.parent = parent
		self.idx = idx

	def __repr__(self):
		return repr(self.parent.data[self.idx])

	def __setitem__(self, subIdx, item):
		index = (self.idx * self.parent.col) + subIdx
		self.parent.data[index] = item

	def __getitem__(self, subIdx):
		index = (self.idx * self.parent.col) + subIdx
		return self.parent.data[index]

class flatMatrix:
	def __init__(self, data):
		self.data = data
		self.col = 4

	def __setitem__(self, key, item):
		return SubItem(self, key, item) 

	def __getitem__(self, idx):
		return SubItem(self, idx)

A = flatMatrix([0,1,2,3,
		4,5,6,7,
		8,9,10,11,
		12,13,14,15])

print A[0][0]

A[0][0] = 50

print A[0][0]

I think its kind of cool. Not so sure I dig how complex it is to read though.
-RyanT

Feb 10

I have been converting a C++ plugin to Python and I came across some C++ code that I was unsure how to convert to Python. I needed to overload several operators like +, -, <<, and [] so how does one go about this? First thing which is always best is to find the python.org help docs.

http://www.python.org/doc/2.5.2/ref/numeric-types.html

Unfortunately they dont have any good examples so I went searching for more. And here is an example I compiled after my search concluded. The lambda function might seem a bit confusing at first but it simply defines two variables ( in this case ) then it runs an expression and at the end of it, it defines what those variables are. The map() function is even more simple. map() can run a function on a list. For example:

#map() example
def add_one(a):
	return (a+1)

foo = [1,2,3,4]
foobar = map(add_one, foo)
print foobar
>>[2, 3, 4, 5]

lambda is special in that it is a function and operates on lists so its allowed to be inside of map()

#lambda example
foo = [1,2,3,4]
bar = [1,2,3,4]
foobar = lambda x, y: x + y, foo, bar
print foobar
( at 0x0000000017A9BEB8>, [1, 2, 3, 4], [1, 2, 3, 4])

And last here is the overload operators example:

Continue reading »

Feb 04

I ran into this module and just thought it was cool so I thought I would mention it here. Python has a few modules for working with processing URL’s and using ftp. So you could create a tool that you share with the public and have it read a URL which would allow you to dynamically create start up messages or even tell the user that the tool has been updated. Ahhhh.. that could get scary.

import urllib2

# Open the URL for reading
urlFile = urllib2.urlopen('http://www.rtrowbridge.com/blog/about/')

# Get info abou the URL
urlFile.info()

# Read the URL source code
for line in urlFile:
	try:
		print line
	except:
		pass

Cheers,
-RyanT