Created
September 16, 2011 16:22
-
-
Save julik/1222470 to your computer and use it in GitHub Desktop.
Iteratively reduce keyframes on linear segments in Nuke
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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