Script that can delete non-matching keyframes between controls?

Script that can delete non-matching keyframes between controls?

T2Slade
Explorer Explorer
375 Views
2 Replies
Message 1 of 3

Script that can delete non-matching keyframes between controls?

T2Slade
Explorer
Explorer

I have almost no coding experience so please excuse my ignorance.

Is it possible to create a Mel or Python script that can delete keyframes that are not present on 2 (or all) controllers that are selected?

 

For example, I select 2 controls which have keyframes on frames
Control A: 1 2 3 4 5
Control B: 1    3    5

 

Then the results will be
Control A: 1    3    5
Control B: 1    3    5

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

FirespriteNate
Advocate
Advocate
Accepted solution

This is a lot more complex in practice than it first appears, and there are so many caveats you will have to consider.

 

Objects/controls don't technically have keyframes, they have (multiple) attributes/channels that are connected to animation curve nodes, and these nodes store keys. However, each attribute (e.g. TranslateX, RotateY, RotateZ, etc..) could easily be connected to anim curves with different numbers of keys on different frames.

 

Additionally, keyframes aren't necessarily always on interger (whole number) values, you could have a key on frame 9.99998 for example, and this wouldn't necessarily match with another objects key on frame 10.

 

Anim curves could also have keys outside of the animation range you are interested in, you may not even notice (for example lets say you had an anim that was 240 frames long, but one of your selected objects actually had an old unused key at frame 300 - using your simple logic, this would result in ALL keyframes being deleted).

 

Having said all that, if your use case is completely basic and none of these issues are likely, then you could do it with something like this (I've simplified it and expanded the code as much as possible to help you see what's going on at each point)

Run in a Script Editor Python Tab:

 

from maya import cmds

# we set animation range length we check:
animLength = 240

# first iterate over the selection to determine all "global" (shared) keys
selected = cmds.ls(sl=True, tr=True)
globalSharedKeys = set(range(animLength+1))
for item in selected:
    allKeys = set(cmds.keyframe(item, q=True))
    print(item, 'All Key Frames:', allKeys)
    globalSharedKeys.intersection_update(allKeys)

print('found all shared keys:', globalSharedKeys)

# now we know which are our shared keys, iterate over the selection 
# again and delete any key that is NOT in this list
for item in selected:
    allKeys = set(cmds.keyframe(item, q=True))
    for frame in allKeys:
        if frame not in globalSharedKeys:
            cmds.cutKey(animation='objects', time=(frame,), clear=True)

 

I think that should roughly do what you asked for, caveats notwithstanding.

(Just make sure you set the animLength accordingly. If your animation is 844 frames long, change the 240 on the third line to 844).

 

And, for the love of god, always save your work before running any script you copied from online! 😄 

Message 3 of 3

T2Slade
Explorer
Explorer

This will work perfectly for what I need it for and with your very thorough explanation I think I can manage to tweak it if needed. Much MUCH appreciated, this saves me countless hours of time.