1 """Functions used by the CameraTracker node"""
2
3 import nuke
4 import nukescripts
5 import os
6
7 import camerapresets
8
9
10
11
12
14 """Populate the export menu on a CameraTracker node."""
15
16
17 entries = [
18
19 ( 'Camera', 'nukescripts.cameratracker.createCamera(nuke.thisNode())', "Create a Camera linked to the calculated projection."),
20 ( 'Camera rig', 'nukescripts.cameratracker.createCameraRig(nuke.thisNode())', "Create a multi-view rig with a Camera per view."),
21 ( 'Camera set', 'nukescripts.cameratracker.createCameraSet(nuke.thisNode())', "Create a set of Cameras, one Camera per solved frame."),
22 ( 'Scene', 'nukescripts.cameratracker.createScene(nuke.thisNode())', "Create a Scene with a Camera and PointCloud for the camera solve."),
23 ( 'Scene+', 'nukescripts.cameratracker.createEverything(nuke.thisNode())', "Create a Scene with a Camera, PointCloud, ScanlineRender, and LensDistortion (Undistort) node."),
24 ( 'Point cloud', 'nukescripts.cameratracker.createPointCloud(nuke.thisNode())', "Create a PointCloud for the camera solve."),
25 ( 'Distortion', 'nukescripts.cameratracker.createLensDistortion(nuke.thisNode())',
26 "Create a LensDistortion node preconfigured for distortion using the same settings as the CameraTracker. " +
27 "You can use this node to distort your CG or other elements before comping them back over the input footage."),
28 ( 'Undistortion', 'nukescripts.cameratracker.createUndistortion(nuke.thisNode())',
29 "Create a LensDistortion node preconfigured for undistortion using the same settings as the CameraTracker. " +
30 "You can apply this node to your input footage to make it match CG elements rendered using the calculated camera."),
31 ( 'Cards', 'nukescripts.cameratracker.createCards(nuke.thisNode())', "Create a group of cards.")
32
33 ]
34
35 k = cameraTracker['exportMenu']
36 k.setValues([ "%s\t%s" % (script, label) for label, script, _ in entries ])
37
38
39 tooltipLines = [ "Create new camera and point cloud nodes based on the results of the solve. The available options are:", "" ]
40 for label, _, tooltip in entries:
41 tooltipLines.append("<b>%s:</b> %s" % (label, tooltip))
42
43 k.setTooltip(os.linesep.join(tooltipLines))
44
45
53
54
55
56
57
59 """Create a camera node based on the projection calculated by the solver."""
60 x = solver.xpos()
61 y = solver.ypos()
62 w = solver.screenWidth()
63 h = solver.screenHeight()
64 m = int(x + w/2)
65 numviews = len( nuke.views() )
66 link = False
67 linkKnob = solver.knob("linkOutput")
68 if linkKnob:
69 link = bool(linkKnob.getValue())
70
71 camera = nuke.createNode('Camera', '', False)
72 camera.setInput(0,None)
73 camera.setXYpos(m - int(camera.screenWidth()/2), y + w)
74 if link:
75 camera.knob("focal").setExpression(solver.name() + ".focalLength")
76 camera.knob("haperture").setExpression(solver.name() + ".aperture.x")
77 camera.knob("vaperture").setExpression(solver.name() + ".aperture.y")
78 camera.knob("translate").setExpression(solver.name() + ".camTranslate")
79 camera.knob("rotate").setExpression(solver.name() + ".camRotate")
80 camera.knob("win_translate").setExpression(solver.name() + ".windowTranslate")
81 camera.knob("win_scale").setExpression(solver.name() + ".windowScale")
82 else:
83 camera.knob("focal").fromScript(solver.knob("focalLength").toScript(False))
84 camera.knob("translate").fromScript(solver.knob("camTranslate").toScript(False))
85 camera.knob("rotate").fromScript(solver.knob("camRotate").toScript(False))
86 camera.knob("win_translate").fromScript(solver.knob("windowTranslate").toScript(False))
87 camera.knob("win_scale").fromScript(solver.knob("windowScale").toScript(False))
88 for i in xrange(numviews):
89 camera.knob("haperture").setValue(solver.knob("aperture").getValue(0,i+1),0,0,i+1)
90 camera.knob("vaperture").setValue(solver.knob("aperture").getValue(1,i+1),0,0,i+1)
91
92
94 """Create a multi-view rig with a camera per view."""
95 numviews = len( nuke.views() )
96 if numviews < 2:
97 nuke.message("Creating a camera rig requires multiple views.\n" +
98 "You can add additional views in your <em>Project Settings</em>, on the <em>Views</em> tab.")
99 return
100
101 x = solver.xpos()
102 y = solver.ypos()
103 w = solver.screenWidth()
104 h = solver.screenHeight()
105 m = int(x + w/2)
106 link = False
107 linkKnob = solver.knob("linkOutput")
108 if linkKnob:
109 link = bool(linkKnob.getValue())
110
111 join = nuke.nodes.JoinViews()
112 join.setInput(0,None)
113 join.setXYpos(m + int(w*1.5) + int(w * numviews/2), y + w)
114
115 for i in xrange(numviews):
116 viewStr = nuke.views()[i]
117 camera = nuke.nodes.Camera()
118 camera.setInput(0,None)
119 if link:
120 camera.knob("focal").setExpression(solver.name() + ".focalLength." + viewStr)
121 camera.knob("haperture").setExpression(solver.name() + ".aperture." + viewStr + ".x")
122 camera.knob("vaperture").setExpression(solver.name() + ".aperture." + viewStr + ".y")
123 camera.knob("translate").setExpression(solver.name() + ".camTranslate." + viewStr)
124 camera.knob("rotate").setExpression(solver.name() + ".camRotate." + viewStr)
125 camera.knob("win_translate").setExpression(solver.name() + ".windowTranslate." + viewStr)
126 camera.knob("win_scale").setExpression(solver.name() + ".windowScale." + viewStr)
127 else:
128 if solver.knob("focalLength").isAnimated():
129 camera.knob("focal").copyAnimation(0,solver.knob("focalLength").animation(0,i+1))
130 else:
131 camera.knob("focal").setValue(solver.knob("focalLength").getValue(0,i+1),0,0,i+1)
132 if solver.knob("camTranslate").isAnimated():
133 camera.knob("translate").copyAnimation(0,solver.knob("camTranslate").animation(0,i+1))
134 camera.knob("translate").copyAnimation(1,solver.knob("camTranslate").animation(1,i+1))
135 camera.knob("translate").copyAnimation(2,solver.knob("camTranslate").animation(2,i+1))
136 else:
137 camera.knob("translate").setValue(solver.knob("camTranslate").getValue(0,i+1),0,0,i+1)
138 camera.knob("translate").setValue(solver.knob("camTranslate").getValue(1,i+1),1,0,i+1)
139 camera.knob("translate").setValue(solver.knob("camTranslate").getValue(2,i+1),2,0,i+1)
140 if solver.knob("camRotate").isAnimated():
141 camera.knob("rotate").copyAnimation(0,solver.knob("camRotate").animation(0,i+1))
142 camera.knob("rotate").copyAnimation(1,solver.knob("camRotate").animation(1,i+1))
143 camera.knob("rotate").copyAnimation(2,solver.knob("camRotate").animation(2,i+1))
144 else:
145 camera.knob("rotate").setValue(solver.knob("camRotate").getValue(0,i+1),0,0,i+1)
146 camera.knob("rotate").setValue(solver.knob("camRotate").getValue(1,i+1),1,0,i+1)
147 camera.knob("rotate").setValue(solver.knob("camRotate").getValue(2,i+1),2,0,i+1)
148 camera.knob("win_translate").setValue(solver.knob("windowTranslate").getValue(0,i+1),0,0,i+1)
149 camera.knob("win_scale").setValue(solver.knob("windowScale").getValue(0,i+1),0,0,i+1)
150 camera.knob("haperture").setValue(solver.knob("aperture").getValue(0,i+1),0,0,i+1)
151 camera.knob("vaperture").setValue(solver.knob("aperture").getValue(1,i+1),0,0,i+1)
152 camera.setXYpos(m + 2*w + w*i, y)
153 if numviews==2:
154 if i==0:
155 camera.knob("gl_color").setValue(0xFF0000FF)
156 camera.knob("tile_color").setValue(0xFF0000FF)
157 if i==1:
158 camera.knob("gl_color").setValue(0x00FF00FF)
159 camera.knob("tile_color").setValue(0x00FF00FF)
160 camera.setName( viewStr )
161 join.setInput(i,camera)
162
163
165 """Create a set of Cameras, one Camera per solved frame."""
166 numCameras = solver["camTranslate"].getNumKeys()
167
168 if numCameras >= 100:
169 ok = nuke.ask("This will create %d cards, which may take some time.\nAre you sure?" % numCameras)
170 if not ok:
171 return
172
173 if numCameras == 0:
174 nuke.message("You can only create a camera set when you have solved cameras.")
175 return
176
177 x = solver.xpos()
178 y = solver.ypos()
179 w = solver.screenWidth()
180 h = solver.screenHeight()
181 m = int(x + w*2)
182 link = False
183 linkKnob = solver.knob("linkOutput")
184 if linkKnob:
185 link = bool(linkKnob.getValue())
186 exprStr = "[python {nuke.toNode('" + solver.fullName() +"')"
187
188 group = nuke.createNode("Group", '', False)
189 group.begin()
190 group.setName("Cameras")
191 group.setXYpos(m + w, y + w)
192 if numCameras>0:
193 scene = nuke.createNode("Scene", '', False)
194 sw = scene.screenWidth()
195 sh = scene.screenHeight()
196 inImg = nuke.createNode("Input", '', False)
197 inImg.setName("img");
198 inImg.setXYpos(m + int(w*(numCameras-1)/2) - int(sw/2), y)
199 out = nuke.createNode("Output", '', False)
200 out.setXYpos(m + int(w*(numCameras-1)/2) - int(sw/2), y + 4*w)
201 out.setInput(0, scene)
202 scene.setXYpos(m + int(w*(numCameras-1)/2) - int(sw/2), y + 3*w)
203 for i in xrange(numCameras):
204 frame = solver.knob("camTranslate").getKeyTime(i)
205 camera = nuke.createNode("Camera", '', False)
206 camera.setSelected(False)
207 camera.setInput(0,inImg)
208 camera.setXYpos(m + w*i - int(sw/2), y + 2*w)
209 scene.setInput(i, camera)
210 if link:
211 camera.knob("focal").setExpression( exprStr + ".knob('focalLength').getValueAt(" + str(frame) + ")}]" )
212 camera.knob("haperture").setExpression( exprStr + ".knob('aperture').getValueAt(" + str(frame) + ",0)}]" )
213 camera.knob("vaperture").setExpression( exprStr + ".knob('aperture').getValueAt(" + str(frame) + ",1)}]" )
214 camera.knob("translate").setExpression( exprStr + ".knob('camTranslate').getValueAt(" + str(frame) + ",0)}]",0 )
215 camera.knob("translate").setExpression( exprStr + ".knob('camTranslate').getValueAt(" + str(frame) + ",1)}]",1 )
216 camera.knob("translate").setExpression( exprStr + ".knob('camTranslate').getValueAt(" + str(frame) + ",2)}]",2 )
217 camera.knob("rotate").setExpression( exprStr + ".knob('camRotate').getValueAt(" + str(frame) + ",0)}]",0 )
218 camera.knob("rotate").setExpression( exprStr + ".knob('camRotate').getValueAt(" + str(frame) + ",1)}]",1 )
219 camera.knob("rotate").setExpression( exprStr + ".knob('camRotate').getValueAt(" + str(frame) + ",2)}]",2 )
220 else:
221 camera.knob("focal").setValue( solver.knob("focalLength").getValueAt(frame) )
222 camera.knob("haperture").setValue( solver.knob("aperture").getValueAt(frame,0) )
223 camera.knob("vaperture").setValue( solver.knob("aperture").getValueAt(frame,1) )
224 camera.knob("translate").setValue( solver.knob("camTranslate").getValueAt(frame) )
225 camera.knob("rotate").setValue( solver.knob("camRotate").getValueAt(frame) )
226 group.end()
227 group.setInput(0,solver)
228 return group
229
231 """Create a Scene with a Camera and PointCloud for the camera solve."""
232 scene = nuke.createNode('Scene', '', False)
233 camera = nuke.createNode('Camera', '', False)
234 pointCloud = nuke.createNode('CameraTrackerPointCloud', '', False)
235 sw = scene.screenWidth()
236 sh = scene.screenHeight()
237 x = cameraTracker.xpos()
238 y = cameraTracker.ypos()
239 w = cameraTracker.screenWidth()
240 h = cameraTracker.screenHeight()
241 m = int(x + w/2)
242 camera.setXYpos(m + w, y + w + int((h-sh)/2))
243 pointCloud.setXYpos(m - int(pointCloud.screenWidth()/2), y + w)
244 scene.setXYpos(m - int(sw/2), y + w*2 - int((sh-h)/2))
245 camera.setInput(0,None)
246 pointCloud.setInput(0,cameraTracker)
247 scene.setInput(0,camera)
248 scene.setInput(1,pointCloud)
249 numviews = len( nuke.views() )
250 link = False
251 linkKnob = cameraTracker.knob("linkOutput")
252 if linkKnob:
253 link = bool(linkKnob.getValue())
254 if link:
255 camera.knob("focal").setExpression(cameraTracker.name() + ".focalLength")
256 camera.knob("haperture").setExpression(cameraTracker.name() + ".aperture.x")
257 camera.knob("vaperture").setExpression(cameraTracker.name() + ".aperture.y")
258 camera.knob("translate").setExpression(cameraTracker.name() + ".camTranslate")
259 camera.knob("rotate").setExpression(cameraTracker.name() + ".camRotate")
260 camera.knob("win_translate").setExpression(cameraTracker.name() + ".windowTranslate")
261 camera.knob("win_scale").setExpression(cameraTracker.name() + ".windowScale")
262 else:
263 camera.knob("focal").fromScript(cameraTracker.knob("focalLength").toScript(False))
264 camera.knob("translate").fromScript(cameraTracker.knob("camTranslate").toScript(False))
265 camera.knob("rotate").fromScript(cameraTracker.knob("camRotate").toScript(False))
266 camera.knob("win_translate").fromScript(cameraTracker.knob("windowTranslate").toScript(False))
267 camera.knob("win_scale").fromScript(cameraTracker.knob("windowScale").toScript(False))
268 for i in xrange(numviews):
269 camera.knob("haperture").setValue(cameraTracker.knob("aperture").getValue(0,i+1),0,0,i+1)
270 camera.knob("vaperture").setValue(cameraTracker.knob("aperture").getValue(1,i+1),0,0,i+1)
271 return [scene, camera, pointCloud]
272
273
275 """Create a Scene with a Camera, PointCloud, ScanlineRender, and LensDistortion (Undistort) node."""
276 [scene, camera, pointCloud] = createScene(cameraTracker);
277 lensDistort = createUndistortion(cameraTracker)
278 scanline = nuke.createNode('ScanlineRender', '', False)
279
280
281 dummyCamera = nuke.createNode('Camera', '', False)
282
283 cameraToSceneDot = nuke.createNode('Dot', '', False)
284 cameraToScanlineRenderDot = nuke.createNode('Dot', '', False)
285 lensToScanlineDot = nuke.createNode('Dot', '', False)
286
287 sw = dummyCamera.screenWidth()
288 sh = dummyCamera.screenHeight()
289 x = cameraTracker.xpos()
290 y = cameraTracker.ypos()
291 w = cameraTracker.screenWidth()
292 h = cameraTracker.screenHeight()
293
294
295 dw = 12
296 dh = 12
297 m = int(x + w/2)
298 hspacing = int(w*1.5)
299 vspacing = w
300
301 nuke.delete(dummyCamera);
302
303 camera.setXYpos( m - hspacing - int(sw/2), y + vspacing + int((h-sh)/2))
304 pointCloud.setXYpos( m - int(w/2), y + vspacing)
305 lensDistort.setXYpos( m + hspacing - int(w/2), y + vspacing)
306 scene.setXYpos( m - int(sw/2), y + 2*vspacing + int((h-sh)/2))
307 scanline.setXYpos( m - int(w/2), y + 3*vspacing)
308
309 cameraToSceneDot.setXYpos( m - hspacing - int(dw/2), y + 2*vspacing + int((h-dh)/2) )
310 cameraToScanlineRenderDot.setXYpos( m - hspacing - int(dw/2), y + 3*vspacing + int((h-dh)/2) )
311 lensToScanlineDot.setXYpos( m + hspacing - int(dw/2), y + 3*vspacing + int((h-dh)/2) )
312
313 cameraToSceneDot.setInput(0, camera)
314 cameraToScanlineRenderDot.setInput(0, cameraToSceneDot)
315 lensToScanlineDot.setInput(0, lensDistort)
316
317 camera.setInput(0,None)
318 pointCloud.setInput(0,cameraTracker)
319
320
321 if cameraTracker.inputs() > 0 and cameraTracker.input(0) != None:
322 lensDistort.setInput(0, cameraTracker.input(0))
323 else:
324 lensDistort.setInput(0, None)
325 scene.setInput(0,cameraToSceneDot)
326 scene.setInput(1,pointCloud)
327 scanline.setInput(0, lensToScanlineDot)
328 scanline.setInput(1, scene)
329 scanline.setInput(2, cameraToScanlineRenderDot)
330
331
337
338
341
342
345
346
348 """Create a LensDistortion node which matches the settings calculated by the CameraTracker."""
349 _clearSelection()
350
351 lensDistort = nuke.createNode('LensDistortion', '', False)
352 lensDistort.setInput(0, cameraTracker.input(0))
353 link = cameraTracker["linkOutput"].getValue()
354 _copyKnob(cameraTracker, "lensType", lensDistort, "lensType", link)
355 _copyKnob(cameraTracker, "distortion1", lensDistort, "distortion1", link)
356 _copyKnob(cameraTracker, "distortion2", lensDistort, "distortion2", link)
357 _copyKnob(cameraTracker, "distortionCenter", lensDistort, "distortionCenter", link)
358 _copyKnob(cameraTracker, "anamorphicSqueeze", lensDistort, "anamorphicSqueeze", link)
359 _copyKnob(cameraTracker, "asymmetricDistortion", lensDistort, "asymmetricDistortion", link)
360 lensDistort['invertDistortion'].setValue(invertDistortion)
361 _copyKnob(cameraTracker, "filter", lensDistort, "filter", False)
362 _copyKnob(cameraTracker, "cardScale", lensDistort, "cardScale", False)
363 _copyKnob(cameraTracker, "a", lensDistort, "a", False)
364 _copyKnob(cameraTracker, "b", lensDistort, "b", False)
365 _copyKnob(cameraTracker, "c", lensDistort, "c", False)
366
367 lensDistort.selectOnly()
368
369 return lensDistort
370
371
373 numCameras = solver["camTranslate"].getNumKeys()
374
375 if numCameras >= 100:
376 ok = nuke.ask("This will create %d cards, which may take some time.\nAre you sure?" % numCameras)
377 if not ok:
378 return
379
380 if numCameras == 0:
381 nuke.message("You can only create a card set when you have solved cameras.")
382 return
383
384 x = solver.xpos()
385 y = solver.ypos()
386 w = solver.screenWidth()
387 h = solver.screenHeight()
388 m = int(x + w*2)
389 link = False
390 linkKnob = solver.knob("linkOutput")
391 if linkKnob:
392 link = bool(linkKnob.getValue())
393 exprStr = "[python {nuke.toNode('" + solver.fullName() +"')"
394
395 group = nuke.createNode("Group", '', False)
396 group.begin()
397 group.setName("Cards")
398 group.setXYpos(m + w, y + w)
399 if numCameras>0:
400 scene = nuke.createNode("Scene", '', False)
401 sw = scene.screenWidth()
402 sh = scene.screenHeight()
403 inImg = nuke.createNode("Input", '', False)
404 inImg.setName("img");
405 inImg.setXYpos(m + int(w*(numCameras-1)/2) - int(sw/2), y)
406 out = nuke.createNode("Output", '', False)
407 out.setXYpos(m + int(w*(numCameras-1)/2) - int(sw/2), y + 5*w)
408 out.setInput(0, scene)
409 group.addKnob(nuke.Tab_Knob('cards','Cards'))
410 zDistKnob = nuke.Double_Knob('z','z')
411 zDistKnob.setRange(0,100)
412 zDistKnob.setTooltip("Cards are placed this far from origin. Use this to make a pan & tile dome of this radius.")
413 zDistKnob.setDefaultValue([1])
414 group.addKnob(zDistKnob)
415 for i in xrange(numCameras):
416 frame = solver.knob("camTranslate").getKeyTime(i)
417 hold = nuke.createNode("FrameHold", '', False)
418 hold.setInput(0, inImg)
419 hold.knob("first_frame").setValue(frame)
420 hold.setXYpos(m + w*i - int(w/2), y + w)
421 camera = nuke.createNode("Camera", '', False)
422 camera.setInput(0,None)
423 if link:
424 camera.knob("focal").setExpression( exprStr + ".knob('focalLength').getValueAt(" + str(frame) + ")}]" )
425 camera.knob("haperture").setExpression( exprStr + ".knob('aperture').getValueAt(" + str(frame) + ",0)}]" )
426 camera.knob("vaperture").setExpression( exprStr + ".knob('aperture').getValueAt(" + str(frame) + ",1)}]" )
427 camera.knob("translate").setExpression( exprStr + ".knob('camTranslate').getValueAt(" + str(frame) + ",0)}]",0 )
428 camera.knob("translate").setExpression( exprStr + ".knob('camTranslate').getValueAt(" + str(frame) + ",1)}]",1 )
429 camera.knob("translate").setExpression( exprStr + ".knob('camTranslate').getValueAt(" + str(frame) + ",2)}]",2 )
430 camera.knob("rotate").setExpression( exprStr + ".knob('camRotate').getValueAt(" + str(frame) + ",0)}]",0 )
431 camera.knob("rotate").setExpression( exprStr + ".knob('camRotate').getValueAt(" + str(frame) + ",1)}]",1 )
432 camera.knob("rotate").setExpression( exprStr + ".knob('camRotate').getValueAt(" + str(frame) + ",2)}]",2 )
433 else:
434 camera.knob("focal").setValue( solver.knob("focalLength").getValueAt(frame) )
435 camera.knob("haperture").setValue( solver.knob("aperture").getValueAt(frame,0) )
436 camera.knob("vaperture").setValue( solver.knob("aperture").getValueAt(frame,1) )
437 camera.knob("translate").setValue( solver.knob("camTranslate").getValueAt(frame) )
438 camera.knob("rotate").setValue( solver.knob("camRotate").getValueAt(frame) )
439 camera.setXYpos(m + w*i - int(sw/2), y + 3*w)
440 card = nuke.createNode("Card", '', False)
441 card.setSelected(False)
442 card.knob("lens_in_focal").setExpression( camera.name() + ".focal" )
443 card.knob("lens_in_haperture").setExpression( camera.name() + ".haperture" )
444 card.knob("translate").setExpression( camera.name() + ".translate" )
445 card.knob("rotate").setExpression( camera.name() + ".rotate" )
446 card.knob("z").setExpression( "parent.z" )
447 card.setInput(0, hold)
448 card.setXYpos(m + w*i - int(w/2), y + 2*w)
449 scene.setInput(i*2,camera)
450 scene.setInput(i*2+1,card)
451 scene.setXYpos(m + int(w*(numCameras-1)/2) - int(sw/2), y + 4*w)
452 group.end()
453 group.setInput(0,solver)
454 return group
455
456
457 -def _copyKnob(fromNode, fromKnobName, toNode, toKnobName, link):
464
465
469
470
471
472
473
474
476 """Finds the index of the preset knob and sets the film back size knob accordingly."""
477 filmbackSizeKnob = cameraTracker['filmBackSize']
478 selectedFilmbackSize = nukescripts.camerapresets.getFilmBackSize(selectedPresetIdx)
479 filmbackSizeKnob.setValue( selectedFilmbackSize[0], 0 )
480 filmbackSizeKnob.setValue( selectedFilmbackSize[1], 1 )
481
482
483 filmBackUnits = cameraTracker['filmBackUnits']
484 filmBackUnits.setValue(0)
485
486
487
488
489
490
494
495
496 if not nuke.env['assist']:
497 nuke.addOnCreate(cameratrackerCreateCallback, nodeClass='CameraTracker')
498 nuke.addOnCreate(cameratrackerCreateCallback, nodeClass='CameraTracker1_0')
499
500
501
502
503
505 """
506 Modal dialog for selecting a Linkable node in the script.
507
508 The following class creates a modal dialog with one UI element: an enum of nodes
509 that derive from the LinkableI class. (The LinkableI interface allows us to easily query and import
510 2D data from a variety of sources, particularly the Tracker node.) The user then selects their source node
511 to import the data from. Once Ok'ed, the code below creates a new user track for each LinkableInfo object
512 returned in the node.linkableKnobs() function with an XY co-ordinate, and then copies each animation curve
513 entry.
514 """
515
523
524
531
533 """Copies the x, y animation curves from one XYKnob linkable object to another."""
534 linkKnobSrc = linkableSrc.knob()
535 linkKnobDst = linkableDst.knob()
536 linkableSrcIndices = linkableSrc.indices()
537 linkableDstIndices = linkableDst.indices()
538
539
540 linkKnobDst.setValue(linkableSrc.enabled(), 0)
541
542
543 linkKnobDst.clearAnimated(int(linkableDstIndices[0]))
544 linkKnobDst.clearAnimated(int(linkableDstIndices[1]))
545
546
547 for i in xrange(0, linkKnobSrc.getNumKeys(int(linkableSrcIndices[0]))):
548 t = linkKnobSrc.getKeyTime(i, int(linkableSrcIndices[0]))
549
550
551
552 if i == 0:
553 linkKnobDst.setAnimated(int(linkableDstIndices[0]))
554 linkKnobDst.setAnimated(int(linkableDstIndices[1]))
555
556
557 linkKnobDst.setValueAt( linkKnobSrc.getValueAt(t, int(linkableSrcIndices[0])), t, int(linkableDstIndices[0]) )
558 linkKnobDst.setValueAt( linkKnobSrc.getValueAt(t, int(linkableSrcIndices[1])), t, int(linkableDstIndices[1]) )
559
560
561 if i == 0 and t != 0:
562 linkKnobDst.removeKeyAt(0, int(linkableDstIndices[0]))
563 linkKnobDst.removeKeyAt(0, int(linkableDstIndices[1]))
564
565
567 """Import data from a Tracker node into the CameraTracker node."""
568
569 strSrcNode = LinkableImportPanel().showModalDialog(cameraTracker)
570 if not strSrcNode:
571 return
572
573
574 srcNode = nuke.toNode(strSrcNode)
575
576 linkablesSrc = srcNode.linkableKnobs(nuke.KnobType.eXYKnob)
577 linkablesDst = cameraTracker.linkableKnobs(nuke.KnobType.eXYKnob)
578
579
580
581
582 startIndex = len(linkablesDst)
583
584
585 numValidTracks = 0
586
587 for linkableSrc in linkablesSrc:
588 linkableSrcIndices = linkableSrc.indices()
589
590
591 if len(linkableSrcIndices) != 2:
592 continue
593
594
595
596
597
598 cameraTracker['addUserTrack'].execute()
599
600
601 linkablesDst = cameraTracker.linkableKnobs(nuke.KnobType.eXYKnob)
602
603 if startIndex >= len(linkablesDst):
604 continue;
605
606 linkableDst = linkablesDst[startIndex]
607
608 _copyLinkableXYAnimCurve(linkableSrc, linkableDst)
609
610
611 startIndex = startIndex + 1
612
613
614 trackEnabled = linkableSrc.enabled()
615 cameraTrackKnob = linkableDst.knob()
616 cameraTrackIndices = linkableDst.indices()
617 if len(cameraTrackIndices) != 2:
618 continue
619
620
621
622 cameraTrackEnabledIdx = cameraTrackIndices[0] - 2
623 cameraTrackKnob.setValue( trackEnabled, int(cameraTrackEnabledIdx) )
624
626 """Export data from the CameraTracker node into a Tracker node."""
627 tracker = nuke.createNode('Tracker4', '', True)
628 x = cameraTracker.xpos()
629 y = cameraTracker.ypos()
630 w = cameraTracker.screenWidth()
631 h = cameraTracker.screenHeight()
632 m = int(x + w/2)
633 tracker.setXYpos(m - int(tracker.screenWidth()/2), y + w)
634
635
636 linkablesSrc = cameraTracker.linkableKnobs(nuke.KnobType.eXYKnob)
637 linkablesDst = tracker.linkableKnobs(nuke.KnobType.eXYKnob)
638
639
640
641
642 startIndex = len(linkablesDst)
643
644 numValidTracks = 0
645
646 trackEnabledDict = {}
647 for linkableSrc in linkablesSrc:
648 linkableSrcIndices = linkableSrc.indices()
649
650
651 if len(linkableSrcIndices) < 2:
652 continue
653
654
655
656
657
658 tracker['add_track'].execute()
659
660 linkablesDst = tracker.linkableKnobs(nuke.KnobType.eXYKnob)
661
662 if startIndex >= len(linkablesDst):
663 continue;
664
665 linkableDst = linkablesDst[startIndex]
666
667 _copyLinkableXYAnimCurve(linkableSrc, linkableDst)
668
669
670 trackEnabledDict[linkableDst] = linkableSrc.enabled()
671
672
673 startIndex = startIndex + 1
674
675
676
677
678
679 for linkableDst, userTrackEnabled in trackEnabledDict.iteritems():
680 trackKnob = linkableDst.knob()
681 trackIndices = linkableDst.indices()
682 if len(trackIndices) != 2:
683 continue
684
685
686
687
688 trackEnabledIdx = trackIndices[0] - 2
689 trackOffsetXIdx = trackIndices[1] + 1
690 trackOffsetYIdx = trackIndices[1] + 2
691 trackKnob.clearAnimated( int(trackOffsetXIdx) )
692 trackKnob.clearAnimated( int(trackOffsetYIdx) )
693 trackKnob.clearAnimated( int(trackEnabledIdx) )
694 trackKnob.setValue( userTrackEnabled, int(trackEnabledIdx) )
695
696 trackKnob.clearAnimated( int(trackEnabledIdx) )
697
698
706
707
715