Announcements

Between mid-October and November, the content on AREA will be relocated to the Autodesk Community M&E Hub and the Autodesk Community Gallery. Learn more HERE.

Python API and setDependentsDirty not working?

Python API and setDependentsDirty not working?

Anonymous
Not applicable
1,947 Views
4 Replies
Message 1 of 5

Python API and setDependentsDirty not working?

Anonymous
Not applicable

I have been trying to add some dynamic attributes to my Python API custom node and have been having no luck getting the dependency relationships working.  My understanding is that using the MPxNode.setDependentsDirty method is the way to go.  The method gets called when a plug is dirtied and it is responsible for returning a list of dependent plugs which should also be dirtied.  None of the scripted devkit examples demonstrate this functionality so I had to make one.  Attached is a Python port of the "affectsNode.cpp" example...  it is a straight port to Python with the only exception that I create the dynamic attributes in the postConstructor method.

 

To test this, load the module and, in the Node Editor window add the node (Tab... then type "affects").  Experiment with typing values in for the 'A' attribute and note that setDependentsDirty  is being called and 'B' is supposedly being marked dirty.  Hover your mouse over the 'B' attribute in the Node Editor and note that the value returned is zero.  Also note that the compute method on the node is never called.  All behavior points to the affectedPlugs MPlugArray being ignored.

 

I've tested this behavior on Maya 2017 and 2018 but an internet search suggests this problem may be quite old.  As an aside, I also looked into overriding the MPxNode.dependsOn method in my node but that method doesn't seem to ever get called.

 

Any suggestions?

Rob Engle

 

AND...  I just tried to post this and the web form doesn't allow '*.py' attachments?  On a programming forum?  Renamed it to affectsNode.txt

Accepted solutions (1)
1,948 Views
4 Replies
Replies (4)
Message 2 of 5

cheng_xi_li
Autodesk Support
Autodesk Support
Accepted solution

Hi,

 

There are two problems 

 

1.Please don't return self in setDependentsDirty, removing them(there is also one in compute) make it working properly.

2.It should be MDataHandle.setInt, Python doesn't have overload, so set it is different in Python.

 

 

After fixing the issues in your sample, it seems working again.

 

affects::setDependentsDirty, "A" being dirtied
dirtying "B"
affectedPlugs [u'affects1.B']
setAttr "affects1.A" 3;
getAttr affects1.B;
affects::compute(), plug being computed is "affects1.B"
found dynamic attribute "A", copying its value to "B"
// Result: 3 //

 

Yours,

Li

Message 3 of 5

Anonymous
Not applicable

Excellent.  This fix appears to work for me as well.  One other question... clearly the return value from setDependentsDirty is being used since it is affecting the result.  Removing the 'return' statement in Python is the equivalent of 'return None'.  If I call OpenMaya.MPxNode.setDependentsDirty it returns the self object.  Perhaps 'self' is supposed to mean "I didn't do anything?"

The online Python 2.0 API documentation says that setDependentsDirty is supposed to return 'self' and doesn't provide any further guidance on the return value.  compute(), on the other hand gives a pretty clear indication of when to return self vs None.

 

For reference, here is what the 2018 docs say... Note that the referenced example and IMPORTANT NOTE are missing.

OpenMaya.MPxNode.setDependentsDirty( ) 
setDependentsDirty(plug, plugArray) -> self

This method can be overridden in user defined nodes to specify which plugs should be set dirty based upon an input plug which Maya is marking dirty. The list of plugs for Maya to mark dirty is returned by the plug array. This method handles both dynamic as well as non-dynamic plugs and is useful in the following ways:

- Allows attributeAffects-style relationships to be handled for dynamically-added attributes. Since MPxNode.attributeAffects() can only be used with non-dynamic attributes, use of this method allows a way for all attributes of a node to affect one another, both dynamic and non-dynamic.

- Provides more flexible relationships than what is available with MPxNode.attributeAffects(). For example, you may wish to not dirty plugs when the current frame is one. However, as the routine is called during dirty propagation, there are restrictions on what can be done within the routine, most importantly you must not cause any dependency graph computation. For details, see the IMPORTANT NOTE below.

This method is designed to work harmoniously with MPxNode.attributeAffects() on the same node. Alternately, you can do all affects relationships within a yourNode.setDependentsDirty() implementation.

The body of a user-implemented setDependentsDirty() implementation might look like the following example, which causes the plug called "B" to be set dirty whever plug "A" is changed, i.e. A affects B
* plug (MPlug) - plug which is being set dirty by Maya.
* plugArray the programmer should add any plugs which they want to set dirty to this list.

0 Likes
Message 4 of 5

cheng_xi_li
Autodesk Support
Autodesk Support

Hi,

 

self should be default value and means returning nothing.

 

I guess the document for Python API 2.0 should be improved on how setDependentsDirty or MStatus working in general.

 

Yours,

Li

0 Likes
Message 5 of 5

Anonymous
Not applicable

Yes... documentation needs improvement.

 

For setDependentsDirty, since it is possible that multiple levels of class hierarchy might need to process the same "plugBeingDirtied" the examples and documentation should really be more clear about how to properly chain behavior.  Assume, for example, that I have a dynamic attribute which depends on (making this up) "visibility," shouldn't the proper behavior in setDependentsDirty be to add its own dependents and then make sure any superclasses get a chance to chime in on other dependents?  Some of the C++ examples seem to call the superclass method and others don't.  Very inconsistent usage and the documentation is vague.  A solid example (e.g. affectsNode.py) would help as well.

 

Note that, for MPxNode.compute method it is more explicit about return values...

 

"When evaluating the dependency graph, Maya will first call the compute method for this node. If the plug that is provided to the compute indicates that that the attribute was defined by the Maya parent node, the compute method should return None. When this occurs, Maya will call the internal Maya node from which the user-defined node is derived to compute the plug's value."

 

however it doesn't say what to return if there is no need for further computation.  I have been using self because the function signature in the documentation says that is what is returned...  "compute(plug, dataBlock) -> self"

All of the "new API" examples return None regardless of whether the value was computed or not.

 

Thanks!

Rob

 

 

 

 

0 Likes