-
Notifications
You must be signed in to change notification settings - Fork 0
/
fcnuke.py
118 lines (102 loc) · 4.56 KB
/
fcnuke.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
from __future__ import with_statement
import nuke, nukescripts, os, re
import framecurve
# On the current node, add a userknob for the framecurve
def add_framecurve(onNode):
if "framecurve" in onNode.knobs():
return
framecurveKnob = nuke.Double_Knob("framecurve", "timewarp frame")
framecurveKnob.setTooltip( "This contains the retiming framecurve animation")
onNode.addKnob(framecurveKnob)
onNode["framecurve"].setAnimated()
onNode["framecurve"].setValueAt(1.0, 1)
apply_timewarps_to_knobs(onNode)
onNode["label"].setValue("TW to [value framecurve]")
# TODO: We want our retime knob to appear in a separate tab
def organize_retime_tab(onNode):
pass
# This fails on Nuke < 6.3 but there ain't much we can do
def make_keyframes_linear(knob):
for curve in knob.animations():
for key in curve.keys():
key.interpolation = nuke.LINEAR
def animate_framecurve_from_file(fc_path, to_node):
with open(fc_path) as fc_file:
curve = load_and_validate_stream(fc_file)
load_curve_into_knob(curve, to_node["framecurve"])
def apply_timewarps_to_knobs(inNode):
"""
Walks all the knobs in the passed node and changes them to be retimed
with the framecurve value
"""
for knob_name in inNode.knobs():
if knob_name == "framecurve":
pass
else:
k = inNode.knob(knob_name)
if k.visible() and k.isAnimated():
# Apply the magic framecurve expr!
k.setExpression("curve(framecurve(frame))")
def apply_framecurve(toNode, framecurve_path):
if not "framecurve" in toNode.knobs():
add_framecurve(toNode)
organize_retime_tab(toNode)
# Apply the file at path
animate_framecurve_from_file(framecurve_path, toNode)
def grab_file():
return nuke.getFilename("Select the framecurve file", "*.framecurve.txt", default="/", favorites="", type="", multiple=False)
def apply_framecurve_from_selected_files_to_selected_nodes():
# Load the animation
framecurve_path = grab_file()
selected = filter(lambda n: n.Class() != "Viewer" and n.name() != "VIEWER_INPUT", nuke.selectedNodes())
for n in selected:
apply_framecurve(n, framecurve_path)
def load_curve_into_knob(curve, knob):
"""
Load a passed framecurve.Curve object into the passed Knob object, resetting
all the animations
"""
knob.clearAnimated()
knob.setAnimated()
for correlation in framecurve.simplify(curve):
knob.setValueAt(correlation.value, correlation.at) #, index=1, view=1)
make_keyframes_linear(knob)
def load_and_validate_stream(fc_stream):
parsed_curve = framecurve.parse(fc_stream)
validator = framecurve.validate(curve = parsed_curve)
if not validator.ok:
raise Exception("The framecurve file had problems: " + "\n".join(validator.errors))
return parsed_curve
def load_framecurve_into_focused_knob():
"""
Can be used as a callback on an animated knob in the Animation menu. It will replace
the animation in the currently selected knob's curve with a curve loaded from Framecurve
"""
# Load the framecurve into tuples
framecurve_path = grab_file()
if framecurve_path == None:
return
with open(framecurve_path) as fc_file:
curve = load_and_validate_stream(fc_file)
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]
load_curve_into_knob(curve, k)
def all_script_frames():
from_f = nuke.root()["first_frame"].getValue()
to_f = nuke.root()["last_frame"].getValue()
return xrange(int(from_f), int(to_f) + 1)
def export_framecurve_from_this_knob():
fc_path = nuke.getFilename("Name the framecurve file to write to", "*.framecurve.txt", default="shot.framecurve.txt", favorites="", type="", multiple=False)
fc = framecurve.Curve()
curve_name_with_suffix = nuke.animations()[0]
knob_name = curve_name_with_suffix.split(".")[0]
this_knob = nuke.thisNode()[knob_name]
with open(fc_path, "w") as fc_file:
for curve in nuke.animations():
for frame in all_script_frames():
fc.append(framecurve.FrameCorrelation(at=frame, value=this_knob.getValueAt(frame)))
framecurve.serialize(fc_file, framecurve.simplify(fc))