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