attributeChange scriptjob and its lying ways. Help.

attributeChange scriptjob and its lying ways. Help.

robotProdigy
Advocate Advocate
3,654 Views
2 Replies
Message 1 of 3

attributeChange scriptjob and its lying ways. Help.

robotProdigy
Advocate
Advocate

I've ran into an issue with a script job calling its callback function when it shouldn't. Specifically, if I make a locator, put an enum attribute on it, key the enum attribute, then create a attributeChange scriptJob who calla a function when the enum attribute changes, the event fires whenever I go to a new keyframe regardless of whether the attribute changes or not.

 

Below is a Python script that will setup that specific example. For it to break (which is what this demonstrates), you must select the locator after this script is ran (not its shape). Now go to any frame, and the script editor will erroneously update with "attribute changed.", when in fact the attribute has not been changed. 

I'm guessing this is a bug, but if anyone knows otherwise, with a work-around, I will gladly give you 3 million dollars shortly before I wake up in the morning 🙂

 

 

 

import pymel.core as pm

# Make a locator
locator = pm.createNode('locator').getParent()

# Creating enum attribute with 2 stepped keyframes
locator.addAttr('my_enum', attributeType='enum', enumName='foxtrot:zulu:')
locator.my_enum.setKeyable(True)
locator.my_enum.setKey(time=10, value=0)


# Create even with callback function
def my_func():
    print('attribute changed.')
job_id = pm.scriptJob(attributeChange=[locator.my_enum, my_func])

Remember, manually select the locator after running the script for the problem to occur.


-Paul

 

0 Likes
Accepted solutions (1)
3,655 Views
2 Replies
Replies (2)
Message 2 of 3

cornelh
Alumni
Alumni

Hi robotProdigy,

 

I would also ask for help via the Python Inside Maya mailing list, as they would be well suited to figuring this out.  I myself have limited knowledge of Pymel, and eventhouh I am quite incised by you 3 million dollar offer,  I must say I do lack the know-how to help on this one.

 

Best of luck

0 Likes
Message 3 of 3

robotProdigy
Advocate
Advocate
Accepted solution

Thanks Housein. I'll keep that link for furtur purposes - I'll probably need it. 

 

For everyone else, I have a solution for anyone else bogged down with this issue.

I think the issue with Maya's attributeChange script job is it will simply report ANYTHING that happens to the target attribute no matter how trivial. With Maya's MEL command engine, we don't get the tools available to us to exclude the types of attributes changes that qualify as a callable event.

 

When connecting a callback to an attribute changed event through Maya Python's API, things are different, and we can very explicitly specify exactly what kind of attribute changes count as a callable event. I'm posting a simple easy to understand (relatively speaking - this is lower level API stuff) solution below. There is one caviat. DONT have a script editor open in your layout when running the below script. It must be floating else your Maya will crash. I submitted this issue to Autodesk just a little while ago.

 

import pymel.core as pm
import maya.OpenMaya as om

def changed_radius(msg, m_plug, otherMplug, clientData):

    # msg  kIncomingDirection = 2048
    # msg  kAttributeSet = 8
    # 2048 + 8 = 2056
    if msg == 2056:
        if m_plug.partialName() == 'rz':

            m_node = m_plug.node()

            # Get node's rotateZ value
            rz_val = om.MFnDependencyNode(m_node).findPlug('rz').asFloat()

            # Set node's scaleX value to that of rotateZ
            att = om.MFnDependencyNode(m_node).findPlug('sx').setFloat(rz_val)


pm.polySphere()

# Get sphere's MObject
sellist = om.MSelectionList()
sellist.add('pSphere1')
node = om.MObject()
sellist.getDependNode(0, node)

# Connect callback to event
id = om.MNodeMessage.addAttributeChangedCallback(node, changed_radius)

After running this, you must specifically change the value of the sphere's rotate Z attribute all by itself, no if ands or buts. An fcurve driving this channel will not qualify as a change in this specific example, as we ignore that on purpose. We have that much control with the API.

Cheers,
Paul W