Skip to content

Instantly share code, notes, and snippets.

@julik
Created September 16, 2011 16:22
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save julik/1222470 to your computer and use it in GitHub Desktop.
Iteratively reduce keyframes on linear segments in Nuke
import math
DELTA = 0.0001
def is_linear_segment(before, current, after, delta):
dx = after.x - before.x
dy = after.y - before.y
t = (current.x - before.x) / dx
linear_y = before.y + (dy * t)
return math.fabs(linear_y - current.y) < delta
# Iteratively removes keyframes in the passed AnimationCurve which are on a linear segment between the neighbouring keyframes
# until there are no such keyframes left on the curve
def reduce_animation(animCurve):
keyframesRemoved = reduction_pass(animCurve)
while keyframesRemoved > 0:
keyframesRemoved = reduction_pass(animCurve)
# Removes all keyframes in the passed AnimationCurve which are on a linear segment between the neighbouring keyframes
def reduction_pass(curve):
to_remove_at = []
keys = curve.keys()
# Scan all the keys in blocks of three, and remove the ones where the differential is small
for idx, current in enumerate(keys):
if idx == 0 or (idx + 1 == len(keys)):
pass
else:
before, after = keys[idx-1], keys[idx+1]
if is_linear_segment(before, current, after, DELTA):
# bake the tangents on the before and the after
before.interpolation = nuke.LINEAR
after.interpolation = nuke.LINEAR
after.lslope = 0
to_remove_at.append(current)
# Delete keys when we are not iterating over them. Prudent.
curve.removeKey(to_remove_at)
print "Killed " + str(len(to_remove_at)) + " keys"
return len(to_remove_at)
# k = nuke.selectedNode()["size"]
# reduce_animation(k.animation(0))
def simplify():
u = nuke.Undo()
u.begin()
knob_names = nuke.animations() # Returns the animations names under this knob
for knob_name_with_suffix in knob_names:
# Since the names are like "translate.x" what we gotta do is to chop off the suffix
knob_name = knob_name_with_suffix.split(".")[0]
# so that we can get at the knob object and do...
k = nuke.thisNode()[knob_name]
for curve in k.animations():
reduce_animation(curve) # bam!
u.end()
# Add the command to the knob menu in the node bin
m = nuke.menu("Animation");
m.addCommand("Simplify curve", "simplify()")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment