[Maya][Python] PSA: Sending lists of keys to keyframe commands

python
maya

#1

Have you ever wanted to send a list of times to one of Maya’s keyframe commands (keyframe, setKeyframe, copyKey, cutKey, keyTangent, etc.) only do discover that it accepts a time range instead? Don’t worry. There is a way to do what you want!

The trick is to send a list of single-frame time ranges. For example:

keysToCut = [5, 20, 25, 47, 48]
timeRange = [(key,) for key in keysToCut]
cmds.cutKey('pCube1.translateX', time=timeRange, clear=True)

This also works for the “index” and “float” flags.

Why this works:
The clue is in the documentation for each command flag. For example, look up the “cutKey” command, and scroll down to the section about the “time” flag. On the right-hand side of the page are a “C” and an “M”. The “M” is what is important. It means that the flag can be passed multiple values. So if the flag accepts a float, you can pass it a list of floats. If the flag accepts a tuple, you can pass it a list of tuples. In this case, a single-frame time range can be specified as a single-item tuple, like (keyTime,), so we pass a list of those.


#2

Just going to add, you will also have to reverse your array. If you don’t reverse your array before you remove your keys, you’re going to be collapsing your array, since Maya automatically handles the indexes of keys in the background.

In your example you are iterating through [5, 20, etc]. When you cut key 5 it will make key 6 shift into 5.


#3

Ah, yes. I hadn’t thought about that. I always use “time”, so it is not a problem. But definitely if you are using “index” this would be a problem. Thanks!

Edit: Actually, I just tried it with “index” and I didn’t run into a problem. I am using Maya 2016. What version of Maya are you using?


#4

Hey sorry for the late response, I don’t get notifications to my email.
When you say ‘index’ are you talking about an array? Sorry I am not familiar with ‘index’ if not.

The index in my example was a element, or key in the array.


#5

By “index”, I mean the “index” flag. The original example posted above uses the “time” flag. But it also works if you use the “index” flag instead. (The Maya docs define the “index” flag as “index of a key on an animCurve”.)

keysToCut = [2, 3, 5, 8, 9]
timeRange = [(key,) for key in keysToCut]
cmds.cutKey('pCube1.translateX', index=timeRange, clear=True)

I didn’t reverse the order in this example, and it still worked.


#6

Hey, I just figured out that a list comprehension isn’t necessary to make a list of single-element tuples. Using “zip” on the list has the same result. This simplifies the code.

keysToCut = [5, 20, 25, 47, 48]
cmds.cutKey('pCube1.translateX', time=zip(keysToCut), clear=True)