Plus minus average node interface

maya

#1

Hi, i’m wondering how to create a similar interface to the plus minus average node with the maya api. When you connect an attribute to the PMA node it creates another input, like it’s dynamically making inputs based on what’s connected? Does anyone know how this is done?

Is it possible to do similar to outputs? For example you have a user specified number of outputs based on a slider?

Thanks.


#2

This is achieved through Maya’s sparse array system - OpenMaya arrayAttributeBuilder and MArrayDataHandle are your best inroads to understanding it. Using a user-specified attribute to set array lengths like that should be possible, but it’s not something I’ve ever done.


#4

Awesome! Thanks for pointing me in the right direction. After a little bit of blood, sweat and tears I finally have a node that works with an output array. It takes a single input and divides it by the number of outputs connected and then outputs the different values to the different outputs.

I pretty much cobbled this together from what I could gather from the help docs and other peoples code examples. Use at your own risk! I’m sure it could be improved but it works. Posting the code because it might help someone else.

import maya.OpenMayaMPx as OpenMayaMPx
import maya.OpenMaya as OpenMaya

class arrayTest(OpenMayaMPx.MPxNode):
    kPluginNodeId = OpenMaya.MTypeId(0x00000012) #change this number to something unique

    input1VecAttr = OpenMaya.MObject()
    output1WgtAttr = OpenMaya.MObject()

    def __init__(self):
        OpenMayaMPx.MPxNode.__init__(self)

    def compute(self, plug, dataBlock):
        if plug == arrayTest.output1WgtAttr:
        #calculations here
        #get inputs
        dataHandleInput = dataBlock.inputValue(arrayTest.input1VecAttr)
        inVal = dataHandleInput.asFloat()

        #get ouput array
        arrayDataHandle = OpenMaya.MArrayDataHandle(dataBlock.outputArrayValue(arrayTest.output1WgtAttr))
        myBuilder = OpenMaya.MArrayDataBuilder(arrayTest.output1WgtAttr, 0)

        for i in range(arrayDataHandle.elementCount()):
            #arrayDataHandle.next()
            output = inVal/(i+1)
            #output = inVal + outValue

            myElementHandle = OpenMaya.MDataHandle(myBuilder.addElement(i))
            myElementHandle.setFloat(output)

        arrayDataHandle.set(myBuilder)
        arrayDataHandle.setAllClean()

        dataBlock.setClean(plug)

    else:
        return OpenMaya.kUnknownParameter

def creator():
    return OpenMayaMPx.asMPxPtr(arrayTest())

def initialize():
    nAttr = OpenMaya.MFnNumericAttribute()
    arrayTest.input1VecAttr = nAttr.create("input", "in", OpenMaya.MFnNumericData.kFloat)
    #nAttr.setConnectable(1)
    #nAttr.setArray(1)
    #nAttr.setUsesArrayDataBuilder(1)
    nAttr.setReadable(1)
    nAttr.setWritable(1)
    nAttr.setStorable(1)
    nAttr.setKeyable(1)
    arrayTest.addAttribute(arrayTest.input1VecAttr)

    nAttr = OpenMaya.MFnNumericAttribute()
    arrayTest.output1WgtAttr = nAttr.create("Output", "out", OpenMaya.MFnNumericData.kFloat)
    #nAttr.setConnectable(0)
    nAttr.setArray(1)
    nAttr.setUsesArrayDataBuilder(1)
    nAttr.setReadable(1)
    nAttr.setWritable(0)
    nAttr.setStorable(0)
    nAttr.setKeyable(0)
    arrayTest.addAttribute(arrayTest.output1WgtAttr)

    arrayTest.attributeAffects(arrayTest.input1VecAttr, arrayTest.output1WgtAttr)

def initializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj, 'Author', '1.0')
    try:
        plugin.registerNode('arrayTest', arrayTest.kPluginNodeId, creator, initialize)
    except:
        raise RuntimeError, 'Failed to register node'


def uninitializePlugin(obj):
    plugin = OpenMayaMPx.MFnPlugin(obj)
    try:
        plugin.deregisterNode(arrayTest.kPluginNodeId)
    except:
        raise RuntimeError, 'Failed to register node'