Using nuke.animation without tearing your hair out

Written by Nathan Rusch on .

This is quite possibly the most stubborn Nuke Python function I've ever encountered, and it took me a lot of poking and prodding to get it worked out, so I figured I should spread the knowledge around.

nuke.animation is the Python equivalent of (/wrapper for?) the TCL "animation" command. It allows you to perform operations on animation data, including the "Generate..." command found in any knob's "Edit" menu. This is the main reason I became interested in it in the first place, as I was writing a function to bake expressions to keyframes and figured Nuke already had some kind of automated process for it. Alas, the process turned out to be so painful that I just went ahead and wrote my own workaround (the script can be found here: http://www.nukepedia.com/gizmos/bake-expressions/).

In hindsight, I actually prefer my method as it avoids the funky subframe animation interpolation issues caused by the "Generate" command, but accessing these commands may prove useful in the future (though quite a few of them have much more friendly Python-native equivalents now).

Syntax

Anything enclosed in "<>" is an optional argument.

The basic syntax is:

nuke.animation("object", "command", <("param", <"param", "param", ...>)>)

Unfortunately, this is quite different from the syntax indicated by the function's docstring.

The syntax can also differ based on which command you're running, so the param sequence isn't always necessary.

Commands

Some of the possible commands and their basic syntax are listed below (I ran out of steam trying to fully document them all, but this should give you an idea of how to use the function).

For these examples, we will assume Grade1.blackpoint is the knob we want to operate on, and for any commands that operate on a frame range, the range 0-100 will be used.

IMPORTANT NOTE: Calling any of the commands that explicitly require an argument list without providing one will insta-crash Nuke. You've been warned, and so has The Foundry.

clear

nuke.animation("Grade1.blackpoint", "clear")

Takes no arguments, and deletes all keys from the animation. The knob remains in autokey mode, but no keys exist and the value is reset to default.

 

erase

nuke.animation("Grade1.blackpoint", "erase", ("0", "100"))

This will delete all keys between frames 0 and 100. This range is first-inclusive, last-exclusive, so in this example, the key at frame 0 would be erased, but the key at frame 100 would still exist. Also, the second "frame" argument is optional, so calling this with the argument sequence ("25", ) would only erase the key at frame 25.

 

expression

nuke.animation("Grade1.blackpoint", "expression")

This will simply return the current expression assigned to the knob as a string. Alternatively:

nuke.animation("Grade1.blackpoint", "expression", ("Grade2.whitepoint", ))

As you might expect, this will assign the expression "Grade2.whitepoint" to the knob.

 

generate

nuke.animation("Grade1.blackpoint", "generate", ("0", "100", "1", field, expression, <field, expression...>))

Probably the most complex of these commands, this will call the Generate command (found in any knob's "Edit" menu) for the frame range  0-100 (incremented by 1) and for each frame, evaluate each expression for its preceding field and store the results in the knob's animation curve. This will also break expression links.

Possible "field" values (from the docstring) include:
x: Sets the frame number for the next keyframe
y: Sets the keyframe value
dy: Sets the left slope
ldy: Sets left and right slope to the same value
la: Length of the left slope handle in the x direction. A value of 1 generates a handle that is 1/3 the distance to the next keyframe
ra: Same as la but for the right handle.

So, to simply bake the expression driving Grade1.blackpoint into keyframes using the default interpolation, you would call:

nuke.animation("Grade1.blackpoint", "generate", ("0", "100", "1", "y", "blackpoint"))

 

Other Commands

Since "generate" is the one I've gotten the most questions about and also wondered at the longest myself, I'll leave the detailed documentation at that. However, here are the remaining commands and a rough syntax for each (partially culled from the docstring).

-"index", ("x", ): Returns the index of the last key with x <= t. Returns -1 for none.

-"is_key", ("x", ): Returns a non-zero value if there is a key with x == t. The actual return value is the index+1.

-"move", ("field", "expression", <"field", "expression", ...>): Replaces all selected keys in an animation with new ones as explained above in "generate"

-"name": Returns a user-friendly name for this animation. This will eliminate any common prefix between this animation and all other selected ones, and also replaces mangled names returned by animations with nice ones.

-"size": Returns the number of keys in the animation.

-"test": Errors if no points in the animation are selected. I don't think this actually works. -Nathan

-"y" ("frame", <"newValue">): Gets or sets the value of an animation at "frame."

-"x" ("frame", <"newXPos">): Gets or sets the horizontal postion of a key.

 

Hopefully this will be of use to someone.

Comments   

 
0 # Tom Pushpathadam 2010-10-11 00:10
Great example! One question. If you assign a node object to a variable like
g= nukeNodes.Grade()
how would you pass the actual node name into the "object" field? I tried
nameg = g.name()
n2 = nameg + ".blackpoint"

then
nuke.animation( n2, "generate")

Gives me an empty result..
 
 
0 # Nathan Rusch 2010-10-11 09:56
Are you just getting an empty return value in Python, or is the function actually not working? There's no reason you can't pass in defined variables instead of simple strings.

However, keep in mind that it will always return an empty Python value, so you can't judge its success or failure based solely on what you get back from the call.
 
 
0 # Tom Pushpathadam 2010-10-11 23:26
Figured out that the editor returns the result only if you are executing a single line like:
nuke.animation( n2,"generate")

If you run a multi-line statement, you need to assign the result to a variable, then print the variable ..ex:

g= nukeNodes.Grade ()
nameg = g.name()
n2 = nameg + ".blackpoint"
result = nuke.animation( n2, "generate")
print result
 
 
0 # Nathan Rusch 2010-10-11 23:35
Ah, good to know. I am curious about what platform you're on though. On Windows (7 x64 at least), there's a current bug with nuke.animation where any calls to any of the operations that require a parameter list will crash Nuke 100% of the time. Are you seeing this? Are you on a different platform? Or is your sample code simply lacking the parameters?
 
 
0 # Nathan Rusch 2010-10-11 23:55
Sorry, that bug should read:

"...any calls to any of the operations that require a parameter sequence without passing one will crash Nuke 100% of the time."
 
 
0 # Tom Pushpathadam 2010-10-12 12:51
I tried the snippet on osx and a sony variant of linux. Haven't hit the bug.
 
 
0 # Alexey Kuchinski 2010-10-17 14:32
Heya Nathan, thanks a lot, what about simple copy Animation, paste Animation - i am really tearing my hears :-)
 

You have no rights to post comments

We have 279 guests and 14 members online