Knob Animation and Python: A Primer
Accessing Animation Data
Nuke provides a number of Python interfaces for interacting with animated knobs and animation curves.
Since the vast majority of the animatable knobs in Nuke are in some way derived from the same Array_Knob class, they all include the same .animation() and .animations() methods for fetching any existing animation as AnimationCurve objects (these will be discussed in a later article, along with the AnimationKey objects they contain).
NOTE: For the purposes of this article, a single view is implied, but unless explicitly noted, all methods mentioned here can take an additional optional argument specifying which view to operate on.
The .animation() method takes a parameter index argument, and returns the AnimationCurve object for that knob index directly. Even if an array knob has only a single value, the method still needs to be passed an index. Here, a ‘blackpoint’ knob has animation applied to it:
1 |
g1 = nuke.toNode("Grade1") |
Conversely, the .animations() method takes no arguments and returns a list of all AnimationCurve objects for all indices of the knob. If an array knob has a single/multiple value option, the list returned will reflect this accordingly. Here, our ‘blackpoint’ knob has been set to use multiple values:
4 |
print g1['blackpoint'].animations()
|
NOTE: Cloned nodes share the same AnimationCurve instances between similar knobs.
Copying Animations
Existing animations can also be easily copied between knobs, with common methods again provided by the Array_Knob class. Hand in hand with .animation() and .animations() are the .copyAnimation() and .copyAnimations() methods.
The .copyAnimation() method takes a knob index and an AnimationCurve object as arguments, and, as you might expect, copies the AnimationCurve object to the specified index.
6 |
g3 = nuke.toNode("Grade3") |
The .copyAnimations() method takes a sequence of AnimationCurve objects (as returned by the .animations() method) and copies them to the knob’s indices.
9 |
g3['blackpoint'].copyAnimations(g1['blackpoint'].animations())
|
However, an important limitation of this method is shown below. In this scenario, ‘Grade1.blackpoint’ is set to a four-value array, with only the first and last indices of the array animated. Thus, Grade1.blackpoint’s .animations() method will return a two-item list, with no reference to which index each item came from.
Consequently, when the knob’s animation is copied to the ‘blackpoint’ knob of Grade3 with the .copyAnimations() method shown above, the AnimationCurve objects found in the argument list are simply applied to the target knob in order. Thus, the animation from index 3 of the source knob (the “alpha” component) is incorrectly copied to index 1 of the target knob.
As a result, it is usually best to test each knob index individually for animation, and perform your desired operation on that index only based on the result.
This can be done using the knob's .isAnimated() method. This method takes an optional index argument, and simply returns a boolean indicating whether or not the specified index (or any part of the knob, if the index argument is omitted) is animated.
10 |
g1['blackpoint'].isAnimated(0)
|
Other Useful Methods
11 |
g1['blackpoint'].hasExpression()
|
Returns a boolean indicating whether the knob has an expression. Can take an optional index argument to check single channels. Does not accept "view" argument.
12 |
g1['blackpoint'].arraySize()
|
Returns the number of elements (or indices) in the array knob. Note that this will always return the maximum size. Does not accept "view" argument.
13 |
g1['blackpoint'].singleValue()
|
Returns a boolean indicating whether or not the knob is set to use a single value. Does not accept "view" argument.
And Remember...
A full list of all a knob's methods can, of course, be found using Python's "help()" function (which should be your best friend if you're new to the language or new to using it in Nuke). Just run help(KNOB) from Nuke's script editor (where KNOB is a knob object, not just a knob name).