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('LensDistortion2', '', 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, "distortionDenominator0", link)
356 _copyKnob(cameraTracker, "distortion2", lensDistort, "distortionDenominator1", link)
357 _copyKnob(cameraTracker, "distortionCenter", lensDistort, "centre", link)
358 _copyKnob(cameraTracker, "anamorphicSqueeze", lensDistort, "anamorphicSqueeze", link)
359 _copyKnobIdx(cameraTracker, "asymmetricDistortion", 0, lensDistort, "distortionDenominatorX00", 0, link)
360 _copyKnobIdx(cameraTracker, "asymmetricDistortion", 1, lensDistort, "distortionDenominatorY00", 0, link)
361
362 if invertDistortion:
363 lensDistort['output'].setValue('Undistort')
364 else:
365 lensDistort['output'].setValue('Redistort')
366
367 lensDistort['projection'].setValue('Rectilinear')
368 lensDistort['distortionModelPreset'].setValue('NukeX Classic')
369
370 lensDistort.selectOnly()
371
372 return lensDistort
373
374
376 numCameras = solver["camTranslate"].getNumKeys()
377
378 if numCameras >= 100:
379 ok = nuke.ask("This will create %d cards, which may take some time.\nAre you sure?" % numCameras)
380 if not ok:
381 return
382
383 if numCameras == 0:
384 nuke.message("You can only create a card set when you have solved cameras.")
385 return
386
387 x = solver.xpos()
388 y = solver.ypos()
389 w = solver.screenWidth()
390 h = solver.screenHeight()
391 m = int(x + w*2)
392 link = False
393 linkKnob = solver.knob("linkOutput")
394 if linkKnob:
395 link = bool(linkKnob.getValue())
396 exprStr = "[python {nuke.toNode('" + solver.fullName() +"')"
397
398 group = nuke.createNode("Group", '', False)
399 group.begin()
400 group.setName("Cards")
401 group.setXYpos(m + w, y + w)
402 if numCameras>0:
403 scene = nuke.createNode("Scene", '', False)
404 sw = scene.screenWidth()
405 sh = scene.screenHeight()
406 inImg = nuke.createNode("Input", '', False)
407 inImg.setName("img");
408 inImg.setXYpos(m + int(w*(numCameras-1)/2) - int(sw/2), y)
409 out = nuke.createNode("Output", '', False)
410 out.setXYpos(m + int(w*(numCameras-1)/2) - int(sw/2), y + 5*w)
411 out.setInput(0, scene)
412 group.addKnob(nuke.Tab_Knob('cards','Cards'))
413 zDistKnob = nuke.Double_Knob('z','z')
414 zDistKnob.setRange(0,100)
415 zDistKnob.setTooltip("Cards are placed this far from origin. Use this to make a pan & tile dome of this radius.")
416 zDistKnob.setDefaultValue([1])
417 group.addKnob(zDistKnob)
418 for i in xrange(numCameras):
419 frame = solver.knob("camTranslate").getKeyTime(i)
420 hold = nuke.createNode("FrameHold", '', False)
421 hold.setInput(0, inImg)
422 hold.knob("first_frame").setValue(frame)
423 hold.setXYpos(m + w*i - int(w/2), y + w)
424 camera = nuke.createNode("Camera", '', False)
425 camera.setInput(0,None)
426 if link:
427 camera.knob("focal").setExpression( exprStr + ".knob('focalLength').getValueAt(" + str(frame) + ")}]" )
428 camera.knob("haperture").setExpression( exprStr + ".knob('aperture').getValueAt(" + str(frame) + ",0)}]" )
429 camera.knob("vaperture").setExpression( exprStr + ".knob('aperture').getValueAt(" + str(frame) + ",1)}]" )
430 camera.knob("translate").setExpression( exprStr + ".knob('camTranslate').getValueAt(" + str(frame) + ",0)}]",0 )
431 camera.knob("translate").setExpression( exprStr + ".knob('camTranslate').getValueAt(" + str(frame) + ",1)}]",1 )
432 camera.knob("translate").setExpression( exprStr + ".knob('camTranslate').getValueAt(" + str(frame) + ",2)}]",2 )
433 camera.knob("rotate").setExpression( exprStr + ".knob('camRotate').getValueAt(" + str(frame) + ",0)}]",0 )
434 camera.knob("rotate").setExpression( exprStr + ".knob('camRotate').getValueAt(" + str(frame) + ",1)}]",1 )
435 camera.knob("rotate").setExpression( exprStr + ".knob('camRotate').getValueAt(" + str(frame) + ",2)}]",2 )
436 else:
437 camera.knob("focal").setValue( solver.knob("focalLength").getValueAt(frame) )
438 camera.knob("haperture").setValue( solver.knob("aperture").getValueAt(frame,0) )
439 camera.knob("vaperture").setValue( solver.knob("aperture").getValueAt(frame,1) )
440 camera.knob("translate").setValue( solver.knob("camTranslate").getValueAt(frame) )
441 camera.knob("rotate").setValue( solver.knob("camRotate").getValueAt(frame) )
442 camera.setXYpos(m + w*i - int(sw/2), y + 3*w)
443 card = nuke.createNode("Card", '', False)
444 card.setSelected(False)
445 card.knob("lens_in_focal").setExpression( camera.name() + ".focal" )
446 card.knob("lens_in_haperture").setExpression( camera.name() + ".haperture" )
447 card.knob("translate").setExpression( camera.name() + ".translate" )
448 card.knob("rotate").setExpression( camera.name() + ".rotate" )
449 card.knob("z").setExpression( "parent.z" )
450 card.setInput(0, hold)
451 card.setXYpos(m + w*i - int(w/2), y + 2*w)
452 scene.setInput(i*2,camera)
453 scene.setInput(i*2+1,card)
454 scene.setXYpos(m + int(w*(numCameras-1)/2) - int(sw/2), y + 4*w)
455 group.end()
456 group.setInput(0,solver)
457 return group
458
459
460 -def _copyKnob(fromNode, fromKnobName, toNode, toKnobName, link):
467
468 -def _copyKnobIdx(fromNode, fromKnobName, fromKnobIdx, toNode, toKnobName, toKnobIdx, link):
481
482
486
487
488
489
490
491
493 """Finds the index of the preset knob and sets the film back size knob accordingly."""
494 filmbackSizeKnob = cameraTracker['filmBackSize']
495 selectedFilmbackSize = nukescripts.camerapresets.getFilmBackSize(selectedPresetIdx)
496 filmbackSizeKnob.setValue( selectedFilmbackSize[0], 0 )
497 filmbackSizeKnob.setValue( selectedFilmbackSize[1], 1 )
498
499
500 filmBackUnits = cameraTracker['filmBackUnits']
501 filmBackUnits.setValue(0)
502
503
504
505
506
507
511
512
513 if not nuke.env['assist']:
514 nuke.addOnCreate(cameratrackerCreateCallback, nodeClass='CameraTracker')
515 nuke.addOnCreate(cameratrackerCreateCallback, nodeClass='CameraTracker1_0')
516
517
518
519
520
522 """
523 Modal dialog for selecting a Linkable node in the script.
524
525 The following class creates a modal dialog with one UI element: an enum of nodes
526 that derive from the LinkableI class. (The LinkableI interface allows us to easily query and import
527 2D data from a variety of sources, particularly the Tracker node.) The user then selects their source node
528 to import the data from. Once Ok'ed, the code below creates a new user track for each LinkableInfo object
529 returned in the node.linkableKnobs() function with an XY co-ordinate, and then copies each animation curve
530 entry.
531 """
532
540
541
548
550 """Copies the x, y animation curves from one XYKnob linkable object to another."""
551 linkKnobSrc = linkableSrc.knob()
552 linkKnobDst = linkableDst.knob()
553 linkableSrcIndices = linkableSrc.indices()
554 linkableDstIndices = linkableDst.indices()
555
556
557 linkKnobDst.setValue(linkableSrc.enabled(), 0)
558
559
560 linkKnobDst.clearAnimated(int(linkableDstIndices[0]))
561 linkKnobDst.clearAnimated(int(linkableDstIndices[1]))
562
563
564 for i in xrange(0, linkKnobSrc.getNumKeys(int(linkableSrcIndices[0]))):
565 t = linkKnobSrc.getKeyTime(i, int(linkableSrcIndices[0]))
566
567
568
569 if i == 0:
570 linkKnobDst.setAnimated(int(linkableDstIndices[0]))
571 linkKnobDst.setAnimated(int(linkableDstIndices[1]))
572
573
574 linkKnobDst.setValueAt( linkKnobSrc.getValueAt(t, int(linkableSrcIndices[0])), t, int(linkableDstIndices[0]) )
575 linkKnobDst.setValueAt( linkKnobSrc.getValueAt(t, int(linkableSrcIndices[1])), t, int(linkableDstIndices[1]) )
576
577
578 if i == 0 and t != 0:
579 linkKnobDst.removeKeyAt(0, int(linkableDstIndices[0]))
580 linkKnobDst.removeKeyAt(0, int(linkableDstIndices[1]))
581
582
584 """Import data from a Tracker node into the CameraTracker node."""
585
586 strSrcNode = LinkableImportPanel().showModalDialog(cameraTracker)
587 if not strSrcNode:
588 return
589
590
591 srcNode = nuke.toNode(strSrcNode)
592
593 linkablesSrc = srcNode.linkableKnobs(nuke.KnobType.eXYKnob)
594 linkablesDst = cameraTracker.linkableKnobs(nuke.KnobType.eXYKnob)
595
596
597
598
599 startIndex = len(linkablesDst)
600
601
602 numValidTracks = 0
603
604 for linkableSrc in linkablesSrc:
605 linkableSrcIndices = linkableSrc.indices()
606
607
608 if len(linkableSrcIndices) != 2:
609 continue
610
611
612
613
614
615 cameraTracker['addUserTrack'].execute()
616
617
618 linkablesDst = cameraTracker.linkableKnobs(nuke.KnobType.eXYKnob)
619
620 if startIndex >= len(linkablesDst):
621 continue;
622
623 linkableDst = linkablesDst[startIndex]
624
625 _copyLinkableXYAnimCurve(linkableSrc, linkableDst)
626
627
628 startIndex = startIndex + 1
629
630
631 trackEnabled = linkableSrc.enabled()
632 cameraTrackKnob = linkableDst.knob()
633 cameraTrackIndices = linkableDst.indices()
634 if len(cameraTrackIndices) != 2:
635 continue
636
637
638
639 cameraTrackEnabledIdx = cameraTrackIndices[0] - 2
640 cameraTrackKnob.setValue( trackEnabled, int(cameraTrackEnabledIdx) )
641
643 """Export data from the CameraTracker node into a Tracker node."""
644 tracker = nuke.createNode('Tracker4', '', True)
645 x = cameraTracker.xpos()
646 y = cameraTracker.ypos()
647 w = cameraTracker.screenWidth()
648 h = cameraTracker.screenHeight()
649 m = int(x + w/2)
650 tracker.setXYpos(m - int(tracker.screenWidth()/2), y + w)
651
652
653 linkablesSrc = cameraTracker.linkableKnobs(nuke.KnobType.eXYKnob)
654 linkablesDst = tracker.linkableKnobs(nuke.KnobType.eXYKnob)
655
656
657
658
659 startIndex = len(linkablesDst)
660
661 numValidTracks = 0
662
663 trackEnabledDict = {}
664 for linkableSrc in linkablesSrc:
665 linkableSrcIndices = linkableSrc.indices()
666
667
668 if len(linkableSrcIndices) < 2:
669 continue
670
671
672
673
674
675 tracker['add_track'].execute()
676
677 linkablesDst = tracker.linkableKnobs(nuke.KnobType.eXYKnob)
678
679 if startIndex >= len(linkablesDst):
680 continue;
681
682 linkableDst = linkablesDst[startIndex]
683
684 _copyLinkableXYAnimCurve(linkableSrc, linkableDst)
685
686
687 trackEnabledDict[linkableDst] = linkableSrc.enabled()
688
689
690 startIndex = startIndex + 1
691
692
693
694
695
696 for linkableDst, userTrackEnabled in trackEnabledDict.iteritems():
697 trackKnob = linkableDst.knob()
698 trackIndices = linkableDst.indices()
699 if len(trackIndices) != 2:
700 continue
701
702
703
704
705 trackEnabledIdx = trackIndices[0] - 2
706 trackOffsetXIdx = trackIndices[1] + 1
707 trackOffsetYIdx = trackIndices[1] + 2
708 trackKnob.clearAnimated( int(trackOffsetXIdx) )
709 trackKnob.clearAnimated( int(trackOffsetYIdx) )
710 trackKnob.clearAnimated( int(trackEnabledIdx) )
711 trackKnob.setValue( userTrackEnabled, int(trackEnabledIdx) )
712
713 trackKnob.clearAnimated( int(trackEnabledIdx) )
714
715
723
724
732