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