Maya node evaluation and dependency within compute() method

Working on some custom nodes, I ran into something I’ve not considered before.

Here are my nodes in the graph -

A Plate node takes position inputs, marks a “tick” attribute dirty to indicate to a central Solver node that it has changed.

This triggers the Solver to compute, updating the output matrix plugs.

Except, by default, using only the attributeAffects() function and with an empty compute() method on the Solver, the Solver does not actually recompute when the Plate changes.

Here is (test case) compute code for the Plate -

And here for the Solver -

The two commented lines in the solver query the datablock inputArrayValue() for the tick plug attributes - with these lines commented, as in the image, the solver does not compute when the input transform changes.

With these lines active though, the solver does compute and triggers the compute of the previous Plate node, within the same scope. This seems wild to me - is this actually how Maya works? With the datablock of one node responsible for micromanaging the computes of all its inputs?
If it is, then what’s the point of attributeAffects() at all? Or is this just an artefact of the python implementation?

I’ve verified that attributeAffects() is run correctly for both nodes, on both the outer compound attributes and the leaf attributes themselves.

If anyone has any experience with this I’d love your insight.

Reading the documentation, there seems to be a bunch of gotchas as to when attributeAffects will and will not work:

attributeAffects(whenChanges, isAffected) -> None

This method specifies that a particular input attribute affects a specific output attribute.  This is required to make evaluation efficient.  When an input changes, only the affected outputs will be computed. Output attributes cannot be keyable - if they are keyable, this method will fail.

This method must be called for every attribute dependency when initializing the node's attributes.  The attributes must first be added using the MPxNode.addAttribute() method.  Failing to call this method will cause the node not to update when its inputs change. If there are no calls to this method in a node's initialization, then the compute method will never be called.

This method will only work during the static initialization method of the user defined node class.  The initialization method is the one that is passed into MFnPlugin.registerNode().  As a result, it does not work with dynamic attributes. For an alternate solution which handles dynamic as well as non-dynamic attributes refer to MPxNode.setDependentsDirty.()

I am guessing you would have already read through the docs, but there might be something in there that will explain the behavior you are seeing?

And yeah, maya’s dirty bit propagation is not great - hence it’s terrible performance.