Getting values from channels on Anim Layers using OpenMaya

Hi all, I need some help with Animation-related + OpenMaya API help.

I am using OpenMaya to iterate rig controllers I have in my scene, in which I am mainly targeting at the rotational attributes.

However I got a snag if the animation data of the controller(s) comes from an animation layer.

rig_controls = cmds.ls(selection=True)
m_sel = OpenMaya.MSelectionList()
for ctrl in rig_controls:
    m_sel.add(ctrl)

nodes = []
curves = []
# For each controller
for idx in range(m_sel.length()):
    mfn_dep = OpenMaya.MFnDependencyNode(m_sel.getDependNode(idx))
    plug = mfn_dep.findPlug("rotate", False)
    node_curves = []
    is_valid = False
    # Per Rotate Axis
    for idx, _ in enumerate(["x", "y", "z"]):
        child = plug.child(idx) #>>> returns <ctrl name>.rotate<x/ y/ z>
        # Assumed locked channels cannot be flipped or fixed easily.
        if child.isLocked:
            is_valid = False
            break
        if OpenMayaAnim.MAnimUtil.isAnimated(child):
            is_valid = True
        # Connect to anim curve
        connected = child.connectedTo(True, False)

        if connected:

            crv = OpenMayaAnim.MFnAnimCurve(connected[0].node())

            try:
                # Has actual animation
                if crv.isStatic: #>>> errors if the said curve comes from animation layer
                    is_valid = False
                    break

            except RuntimeError:
                res = cmds.keyframe(child, query=True, timeChange=True, selected=False)
                if not res:
                    is_valid = False
                    break
            
            node_curves.append(crv)

    # Is a controller with 3 channel anim curves
    if is_valid:
        nodes.append(plug.name().rsplit(".", 1)[0])
        curves.append(node_curves)


first = "100"
start_time = OpenMaya.MTime(first)
# Row is controller entry of animation for a given frame
rotations = [
    (
        math.degrees(crv[0].evaluate(start_time)),
        math.degrees(crv[1].evaluate(start_time)), 
        math.degrees(crv[2].evaluate(start_time))
    ) for crv in curves
]

It will errors out at the crv.isStatic line where the error is as follows: # Error: (kFailure): Object does not exist
To rectify this issue, I have use try...except... which seems to bypass it but then it hits another problem later on during the math code portion.

Tried looking through the OpenMayaAnim documents but could not find much if there is a command that deals with animation being on Animation Layers.

Is there a better way that I can go around with this in which I am trying to gather animated rotational values using Maya API?

Any insights on this, anyone?

First, and foremost, give us a script that reproduces the error without any setup on our part. We should be able to copy/paste the script into the editor, run it, and see the error starting from either a file you provide, or an empty scene.

Then make sure to include your whole script. You’re missing all the imports.

And debug your script first.
In line 51, MTime doesn’t take a string as an input.
Then curves variable is a list of lists. I’m guessing at line 47 you meant to use curves.extend(node_curves)? If not, your list comprehension starting at line 53 is wrong.

Or even better, don’t include that extra stuff in your script, it just gets in the way of your question. In your file setup function, you could create exactly 1 object with animation on a layer (meaning no for loop at line 9) with animation only on the X rotation (no for loop on line 15). Then everything after line 43 can just go away.

Now, my actual guess at what is wrong:
At line 24 you get the input connections to the node, however when there are animation layers, those input connections aren’t animation curve nodes, those are AnimLayer nodes.

2 Likes

Thanks for getting back.

Had wanted to close this topic but I can’t. Instead I will create another thread that details much more information.