So, found a solution - it seems like MArrayDataHandle.setClean() / setAllClean() are buggy - or else I'm using them wrong somehow. If we switch the above "setClean" statements to instead use dataBlock.setClean, everything works as expected, with compute run only once (unless the input is changed).
On Mon, Aug 14, 2017 at 4:25 PM Paul Molodowitch <[email protected]> wrote: > Hi all - I’m trying to make a custom MPxNode that has an array attribute, > that I’m building with an MArrayDataBuilder. > > However, even thought I call both MArrayDataHandle.setClean() and > setAllClean() after building the array, the compute seems to always get > called whenever I call getAttr on the array attribute without an index, and > whenever I call evaluateNumElements(). I can, however, call getAttr on a > specific element - getAttr myNode.myAttr[3] - without triggering the > compute. > > Is this normal? > > Here’s some code to illustrate what I mean - you can execute this straight > from a script editor: > > from pymel.api.plugins import DependNodeimport maya.OpenMaya as om > class MyNode(DependNode): > _typeId = om.MTypeId(0x812EF) > _name = 'MyNode' > > @classmethod > def initialize(cls): > # input > nAttr = om.MFnNumericAttribute() > cls.input = nAttr.create( "input", "in", om.MFnNumericData.kFloat, > 0.0 ) > nAttr.setStorable(True) > cls.addAttribute(cls.input) > > nAttr = om.MFnNumericAttribute() > cls.myAttr = nAttr.create("myAttr", "mya", om.MFnNumericData.kFloat, > 0.0) > nAttr.setStorable(True) > nAttr.setArray(True) > nAttr.setUsesArrayDataBuilder(True) > cls.addAttribute(cls.myAttr) > cls.attributeAffects(cls.input, cls.myAttr) > > def compute(self, plug, dataBlock): > print "compute called on %s" % plug.name() > if plug == self.myAttr: > arrayHandle = dataBlock.outputArrayValue(self.myAttr) > numElements = arrayHandle.elementCount() > print "numElements: ", numElements > if arrayHandle.elementCount() < 10: > builder = arrayHandle.builder() > elemHandle = builder.addLast() > elemHandle.setFloat(numElements) > elemHandle.setClean() > arrayHandle.set(builder) > arrayHandle.setClean() > arrayHandle.setAllClean() > print "new numElements: ", arrayHandle.elementCount() > return > elif plug == self.input: > dataBlock.setClean(self.input) > return > return om.kUnknownParameter > MyNode.register() > import pymel.core as pmimport maya.cmds as cmds > mynode = pm.createNode('MyNode') > attrName = "%s.myAttr" %mynodeprint cmds.getAttr(attrName)print > mynode.myAttr.evaluateNumElements()print mynode.myAttr.numElements()print > "dirty?", mynode.myAttr.isDirty()print cmds.getAttr(attrName) > > A few notes: > > - This reproduction code is in Python, but I came across this while > writing C++. The results seem the same. > - The “attributeAffects” bit seems to be necessary - without it, the > compute is apparently never called. > > > -- You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAAssL7Z-5iUj3-3%2Bk3yEJg63RANjsA6na07k_gZQCr83qvsDgg%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
