So basically I've got a python node called *simpleLocator* with an 
attribute called *pointCount *(type *kInt*) which is used to generate some 
random points. These points can be passed out as an array with the 
attribute *outPoints *(type *kDoubleArray *for this example). I've setup *
attributeAffects*() so that outPoints depends on pointCount, so it should 
update if the user edits the number of points. This node needs to draw the 
points every frame with OpenGL as well, but only compute as needed. So far 
so good. Here's my example code (also attached to this post), stripped to 
the bare essentials and it almost works:

http://hastebin.com/vixiyaruda.py


When compute() is called though, plug never equals aOutPoints. Ever, ever.

    def compute( self, plug, data ):
        if plug == simpleLocator.aOutPoints:
            print( 'aOutPoints needs to be computed, but we never get 
here...' )
            return om.MStatus.kSuccess
        else:
            return om.MStatus.kUnknownParameter


What's normal practice here? Should I just query my 
simpleLocator.aPointCount every time draw is called and only 
call generatePoints() if the value of aPointCount has been changed? Should 
I derive from a node other than MPxLocator and implement my own draw 
method? Does MPxLocator behave different in C++? Any help, any insight 
would be greatly appreciated. Thanks.

-shawn
PS- If you're curious, the real node is generating blue noise for thousands 
of points and is fairly expensive to calculate.

-- 
view archives: http://groups.google.com/group/python_inside_maya
change your subscription settings: 
http://groups.google.com/group/python_inside_maya/subscribe
"""
import maya.cmds as mc
pluginFile = 'SimpleLocator.py'
pluginNode = 'simpleLocator'
# unload
if mc.pluginInfo( pluginFile, q=True, l=True ):
    # cleanup nodes first
    for node in mc.ls( type=pluginNode ):
        tf = mc.listRelatives( node, p=True )[0]
        print( 'Deleting node: %s' % node )
        mc.delete( node )
        mc.delete( tf )
    print( 'Unloading plugin: %s' % pluginFile )
    mc.unloadPlugin( pluginFile, force=True )
# load
print( 'Loading plugin: %s' % pluginFile )
mc.loadPlugin( pluginFile, quiet=True )
print( 'Creating test node: %s' % pluginNode )
mc.createNode( pluginNode )
"""

import sys
import random

import maya.OpenMaya as om
import maya.OpenMayaMPx as mpx
import maya.OpenMayaRender as mr


nodeTypeName = 'simpleLocator'
nodeTypeId = om.MTypeId(0x00070)


glRenderer = mr.MHardwareRenderer.theRenderer()
glFT = glRenderer.glFunctionTable()


class simpleLocator( mpx.MPxLocatorNode ):

    # class variables
    aPointCount = om.MObject()
    aOutPoints  = om.MObject()
 
    def __init__( self ):
        mpx.MPxLocatorNode.__init__( self )

        self.pointCount = 10
        self.points = []
        self.generatePoints()

    def generatePoints( self ):
        random.seed( 1242)

        self.points = []
        for i in xrange( self.pointCount ):
            self.points.append( (random.uniform(-5,5), random.uniform(-5,5), 0) )

    def drawPoints( self ):
        glFT.glPointSize( 4 )

        glFT.glBegin( mr.MGL_POINTS )
        for p in self.points:
            glFT.glVertex3f( p[0], p[1], p[2] )
        glFT.glEnd()

    def compute( self, plug, data ):
        if plug == simpleLocator.aOutPoints:
            print( 'aOutPoints needs to be computed.' )
            return om.MStatus.kSuccess
        else:
            return om.MStatus.kUnknownParameter

    def draw( self, view, path, style, status ):
        view.beginGL()
        self.drawPoints()
        view.endGL()


def nodeCreator():
    return mpx.asMPxPtr( simpleLocator() )


def nodeInitializer():

    nAttr = om.MFnNumericAttribute()
    tAttr = om.MFnTypedAttribute()

    simpleLocator.aPointCount = nAttr.create( 'pointCount', 'ptc', om.MFnNumericData.kInt )
    nAttr.setKeyable( True )
    nAttr.setDefault( 100 )
    simpleLocator.addAttribute( simpleLocator.aPointCount )

    simpleLocator.aOutPoints = tAttr.create( 'outPoints', 'opts', om.MFnData.kDoubleArray )
    tAttr.setStorable( False )
    tAttr.setWritable( False )
    tAttr.setReadable( True )
    simpleLocator.addAttribute( simpleLocator.aOutPoints )

    simpleLocator.attributeAffects( simpleLocator.aPointCount, simpleLocator.aOutPoints )

    return om.MStatus.kSuccess


def initializePlugin( obj ):
    plugin = mpx.MFnPlugin( obj )
    try:
        plugin.registerNode( nodeTypeName, 
                             nodeTypeId,
                             nodeCreator,
                             nodeInitializer,
                             mpx.MPxNode.kLocatorNode )
    except:
        sys.stderr.write( 'Failed to register node: %s' % nodeTypeName )
        raise


def uninitializePlugin( obj ):
    plugin = mpx.MFnPlugin( obj )
    try:
        plugin.deregisterNode( nodeTypeId )
    except:
        sys.stderr.write( 'Failed to deregister node: %s' % nodeTypeName )
        raise

Reply via email to