Package nukescripts :: Module renderdialog
[hide private]
[frames] | no frames]

Source Code for Module nukescripts.renderdialog

  1  # Copyright (c) 2010 The Foundry Visionmongers Ltd.  All Rights Reserved. 
  2  from __future__ import with_statement 
  3  import nuke 
  4  import nukescripts 
  5  import flipbooking 
  6  from nukescripts import pyAppUtils 
  7  import os 
  8  import string 
  9  import subprocess 
 10  import uuid 
 11  import re 
 12  #import traceback 
 13   
 14  ############################################################################## 
 15  # Dialogs 
 16  ############################################################################## 
 17   
18 -class DialogState:
19 - def __init__(self):
20 self._state = {}
21
22 - def get(self, knob, defaultValue = None):
23 """Return the given knob's stored last state value. 24 If none exists, defaultValue is returned. 25 Values are stored in a dict referenced by knob name, so names must be unique!""" 26 return self.getValue(knob.name(), defaultValue)
27
28 - def save(self, knob):
29 """Store the knob's current value as the 'last state' for the next time the dialog is opened. 30 Values are stored in a dict referenced by knob name, so names must be unique!""" 31 self.saveValue(knob.name(), knob.value())
32
33 - def setKnob(self, knob, defaultValue = None):
34 """Convenience method for setting a value straight on a knob.""" 35 knob.setValue(self.get(knob, defaultValue))
36 - def saveValue(self, id, value):
37 """Stores the value with the given id.""" 38 self._state[id] = value
39 - def getValue(self, id, defaultValue = None):
40 """Recalls the value. If it was not set before, it will return the defaultValue.""" 41 return self._state.get(id, defaultValue)
42 43 _gRenderDialogState = DialogState() 44 _gFlipbookDialogState = DialogState() 45
46 -class ExecuteDialog(nukescripts.PythonPanel):
47 - def _titleString(self):
48 return "Execute"
49
50 - def _idString(self):
51 return "uk.co.thefoundry.ExecuteDialog"
52
53 - def _addPreKnobs(self):
54 """Add knobs that must appear before the render knobs.""" 55 return
56
57 - def _addPostKnobs(self):
58 """Add knobs that must appear after the render knobs.""" 59 return
60
61 - def _getDefaultViews(self):
62 oc = nuke.OutputContext() 63 allViews = [oc.viewname(i) for i in xrange(1, oc.viewcount())] 64 return " ".join(allViews)
65
66 - def _addViewKnob(self):
67 """Add knobs for view selection.""" 68 oc = nuke.OutputContext() 69 if (oc.viewcount() > 2): 70 self._viewSelection = nuke.MultiView_Knob("multi_view", "Views") 71 self._viewSelection.fromScript(self._state.get(self._viewSelection, self._getDefaultViews())) 72 self.addKnob(self._viewSelection) 73 self._viewSelection.clearFlag(nuke.NO_MULTIVIEW)
74
75 - def addKnob(self, knob):
76 """Add the knob and make sure it cannot be animated.""" 77 knob.setFlag(nuke.NO_ANIMATION | nuke.NO_MULTIVIEW) 78 super(ExecuteDialog, self).addKnob(knob)
79
80 - def __init__(self, dialogState, groupContext, nodeSelection = [], exceptOnError = True):
81 self._state = dialogState 82 self._nodeSelection = nodeSelection 83 self._exceptOnError = exceptOnError 84 85 nukescripts.PythonPanel.__init__(self, self._titleString(), self._idString(), False) 86 87 self._viewers = {} 88 for n in nuke.allNodes("Viewer", groupContext): 89 self._viewers[n.name()] = n 90 self._specialRanges = ["input", "global", "custom"] 91 92 self._addPreKnobs() 93 94 # Frame range knobs 95 self._rangeEnum = nuke.Enumeration_Knob( "frame_range", "Frame range", self._specialRanges + self._viewers.keys() ) 96 self._state.setKnob(self._rangeEnum, "input") 97 self.addKnob( self._rangeEnum ) 98 self._frameRange = nuke.String_Knob( "frame_range_string", "") 99 self._frameRange.clearFlag(nuke.STARTLINE) 100 if self._rangeEnum.value() == "custom": 101 self._state.setKnob(self._frameRange, str(nuke.root().frameRange())) 102 else: 103 self._setFrameRangeFromSource(self._rangeEnum.value()) 104 105 self.addKnob(self._frameRange) 106 107 # Proxy 108 self._useProxy = nuke.Boolean_Knob("use_proxy", "Use proxy") 109 self._useProxy.setFlag(nuke.STARTLINE) 110 self._state.setKnob(self._useProxy, nuke.root().proxy()) 111 self.addKnob(self._useProxy) 112 113 self._addPostKnobs() 114 115 self._continueOnError = nuke.Boolean_Knob("continue", "Continue on error") 116 self._state.setKnob(self._continueOnError, True) 117 self._continueOnError.setFlag(nuke.STARTLINE) 118 self.addKnob(self._continueOnError) 119 120 self._addViewKnob()
121
122 - def knobChanged( self, knob ):
123 self._state.save(knob) 124 if (knob == self._frameRange): 125 self._rangeEnum.setValue("custom") 126 self._state.save(self._rangeEnum) 127 if (knob == self._rangeEnum): 128 self._setFrameRangeFromSource(knob.value()) 129 self._state.save(self._frameRange)
130
131 - def _setFrameRangeFromSource(self, source):
132 if (source == "input"): 133 try: 134 activeInput = nuke.activeViewer().activeInput() 135 self._frameRange.setValue(str(nuke.activeViewer().node().input(activeInput).frameRange())) 136 except: 137 self._frameRange.setValue(str(nuke.root().frameRange())) 138 elif (source == "global"): 139 self._frameRange.setValue(str(nuke.root().frameRange())) 140 elif (source == "custom"): 141 pass 142 else: 143 self._frameRangeFromViewer(source);
144
145 - def _frameRangeFromViewer( self, viewer ):
146 """"Set the framerange knob to have the framerange from the given viewer.""" 147 viewerRange = str(self._viewers[viewer].knob("frame_range").value()) 148 if viewerRange == "": 149 viewerRange = str(self._viewers[viewer].playbackRange()) 150 self._frameRange.setValue(viewerRange)
151
152 - def _selectedViews(self):
153 try: 154 return self._viewSelection.value().split() 155 except AttributeError: 156 # If we didn't add the view selection knob, there should be just the one view. 157 return [nuke.OutputContext().viewname(1)]
158
159 - def addToPane(self):
161
162 - def run(self):
163 frame_ranges = nuke.FrameRanges(self._frameRange.value().split(',')) 164 views = self._selectedViews() 165 rootProxyMode = nuke.root().proxy() 166 try: 167 nuke.Undo().disable() 168 nuke.root().setProxy(self._useProxy.value()) 169 nuke.executeMultiple(self._nodeSelection, frame_ranges, views, continueOnError = self._continueOnError.value()) 170 except RuntimeError, e: 171 if self._exceptOnError or e.args[0][0:9] != "Cancelled": # TO DO: change this to an exception type 172 raise 173 finally: 174 nuke.root().setProxy(rootProxyMode) 175 nuke.Undo().enable()
176
177 -class RenderDialog(ExecuteDialog):
178 - def _titleString(self):
179 return "Render"
180
181 - def _idString(self):
182 return "uk.co.thefoundry.RenderDialog"
183
184 - def __init__(self, dialogState, groupContext, nodeSelection = [], exceptOnError = True):
185 ExecuteDialog.__init__(self, dialogState, groupContext, nodeSelection, exceptOnError)
186
187 - def _addPostKnobs(self):
188 # Background render stuff 189 self._bgRender = nuke.Boolean_Knob("bg_render", "Render in background") 190 self._state.setKnob(self._bgRender, False) 191 self._bgRender.setFlag(nuke.STARTLINE) 192 self.addKnob(self._bgRender) 193 self._numThreads = nuke.Int_Knob("num_threads", "Thread limit") 194 self._numThreads.setVisible(self._bgRender.value()) 195 self._state.setKnob(self._numThreads, max(nuke.NUM_CPUS / 2, 1)) 196 self.addKnob(self._numThreads) 197 self._maxMem = nuke.String_Knob("max_memory", "Memory limit") 198 self._state.setKnob(self._maxMem, str(max(nuke.memory("max_usage") / 2097152, 16)) + "M") 199 self._maxMem.setVisible(self._bgRender.value()) 200 self.addKnob(self._maxMem)
201 202
203 - def _getBackgroundLimits(self):
204 return { 205 "maxThreads": self._numThreads.value(), 206 "maxCache": self._maxMem.value() }
207
208 - def knobChanged( self, knob ):
209 ExecuteDialog.knobChanged(self, knob) 210 211 if (knob == self._bgRender): 212 self._numThreads.setVisible(self._bgRender.value()) 213 self._maxMem.setVisible(self._bgRender.value())
214
215 - def isBackgrounded(self):
216 """Return whether the backgroun rendering option is enabled.""" 217 return self._bgRender.value()
218
219 - def run(self):
220 frame_ranges = nuke.FrameRanges(self._frameRange.value().split(',')) 221 views = self._selectedViews() 222 rootProxyMode = nuke.root().proxy() 223 try: 224 nuke.Undo().disable() 225 nuke.root().setProxy(self._useProxy.value()) 226 if (self.isBackgrounded()): 227 nuke.executeBackgroundNuke(nuke.EXE_PATH, self._nodeSelection, 228 frame_ranges, views, self._getBackgroundLimits(), continueOnError = self._continueOnError.value()) 229 else: 230 nuke.executeMultiple(self._nodeSelection, frame_ranges, views, continueOnError = self._continueOnError.value()) 231 except RuntimeError, e: 232 if self._exceptOnError or e.args[0][0:9] != "Cancelled": # TO DO: change this to an exception type 233 raise 234 finally: 235 nuke.root().setProxy(rootProxyMode) 236 nuke.Undo().enable()
237
238 -class FlipbookDialog( RenderDialog ):
239 - def _titleString( self ):
240 return "Flipbook"
241
242 - def _idString( self ):
243 return "uk.co.thefoundry.FlipbookDialog"
244
245 - def __init__(self, dialogState, groupContext, node, takeNodeSettings):
246 # Init attributes 247 self._node = node 248 self._takeNodeSettings = takeNodeSettings 249 250 # init super 251 RenderDialog.__init__(self, dialogState, groupContext) 252 253 # Override the initial frame range value 254 self._state.setKnob(self._rangeEnum, "input") 255 self._setFrameRangeFromSource(self._rangeEnum.value()) 256 257 if self._takeNodeSettings: 258 self._viewerForSettings.setValue(node.name()) 259 self.knobChanged(self._viewerForSettings)
260
261 - def _addPreKnobs( self ):
262 self._flipbookEnum = nuke.Enumeration_Knob( "flipbook", "Flipbook", flipbooking.gFlipbookFactory.getNames() ) 263 self._state.setKnob(self._flipbookEnum, "FrameCycler") 264 self.addKnob( self._flipbookEnum ) 265 self._viewerForSettings = nuke.Enumeration_Knob("viewer_settings", "Take settings from", ["-"] + self._viewers.keys()) 266 if not self._takeNodeSettings: 267 self._viewerForSettings.setValue("-") 268 self.addKnob(self._viewerForSettings) 269 270 self._defaultValues = nuke.PyScript_Knob("default", "Defaults") 271 self.addKnob(self._defaultValues) 272 273 # Region of Interest knobs 274 self._useRoi = nuke.Boolean_Knob("use_roi", "Enable ROI") 275 self._useRoi.setFlag(nuke.STARTLINE) 276 self._state.setKnob(self._useRoi, False) 277 self.addKnob(self._useRoi) 278 self._roi = nuke.BBox_Knob("roi", "Region of Interest") 279 self._state.setKnob(self._roi, (0, 0, 0, 0)) 280 self.addKnob(self._roi) 281 self._roi.setVisible(self._useRoi.value()) 282 283 # Channel knobs 284 self._channels = nuke.Channel_Knob( "channels_knob", "Channels") 285 if self._node.Class() == "Write": 286 self._channels.setValue(self._node.knob("channels").value()) 287 else: 288 self._state.setKnob(self._channels, "rgba") 289 self._channels.setFlag(nuke.STARTLINE | nuke.NO_CHECKMARKS) 290 self.addKnob( self._channels )
291
292 - def _addPostKnobs( self ):
293 super(FlipbookDialog, self)._addPostKnobs() 294 # Misc knobs 295 self._cleanup = nuke.Boolean_Knob("cleanup", "Delete existing temporary files") 296 self._cleanup.setFlag(nuke.STARTLINE) 297 self._state.setKnob(self._cleanup, True) 298 self.addKnob(self._cleanup) 299 300 # LUT knobs 301 self._luts = nuke.Enumeration_Knob("lut", "LUT", nuke.ViewerProcess.registeredNames()) 302 if self._takeNodeSettings: 303 self._state.setKnob(self._luts, self._lutFromViewer(self._viewerForSettings.value())) 304 else: 305 self._state.setKnob(self._luts, self._lutFromViewer()) 306 self.addKnob(self._luts) 307 308 self._burnInLUT = nuke.Boolean_Knob("burnin", "Burn in the LUT") 309 self._state.setKnob(self._burnInLUT, False) 310 self.addKnob(self._burnInLUT) 311 312 # Audio knobs 313 audioList = [] 314 audioList.append( "None" ) 315 for node in nuke.allNodes("AudioRead"): 316 audioList.append( node.name() ) 317 self._audioSource = nuke.Enumeration_Knob( "audio", "Audio", audioList ) 318 self.addKnob( self._audioSource )
319 320
321 - def _getDefaultViews(self):
322 return nuke.activeViewer().view()
323
324 - def _addViewKnob(self):
325 oc = nuke.OutputContext() 326 self._views = [oc.viewname(i) for i in xrange(1, oc.viewcount())] 327 if (oc.viewcount() > 2): 328 supportedViews = self._selectedFlipbook().capabilities()["maximumViews"] 329 if (int(supportedViews) > 1): 330 self._viewSelection = nuke.MultiView_Knob("views", "Views") 331 else: 332 self._viewSelection = nuke.OneView_Knob("views", "View", self._views) 333 activeView = nuke.activeViewer().view() 334 if activeView == "": 335 activeView = self._views[0] 336 self._state.setKnob(self._viewSelection, activeView) 337 self.addKnob(self._viewSelection) 338 self._viewSelection.clearFlag(nuke.NO_MULTIVIEW)
339
340 - def _selectedFlipbook(self):
341 return flipbooking.gFlipbookFactory.getApplication(self._flipbookEnum.value())
342
343 - def _lutFromViewer(self, viewerName = ""):
344 try: 345 if viewerName == "": 346 return nuke.ViewerProcess.node().knob("current").value() 347 else: 348 return nuke.ViewerProcess.node(viewer=viewerName).knob("current").value() 349 except AttributeError: 350 return "None"
351
352 - def _isViewerSettingKnob(self, knob):
353 return knob == self._useRoi or knob == self._roi or knob == self._channels or knob == self._useProxy or knob == self._frameRange or knob == self._rangeEnum or knob == self._luts
354
355 - def _setKnobAndStore(self, knob, val):
356 knob.setValue(val) 357 self._state.save(knob)
358
359 - def knobChanged(self, knob):
360 RenderDialog.knobChanged(self, knob) 361 if knob == self._defaultValues: 362 self._setKnobAndStore(self._useRoi, False) 363 self._setKnobAndStore(self._roi, (0, 0, 0, 0)) 364 self._roi.setVisible(False) 365 self._maxMem.setVisible(False) 366 self._numThreads.setVisible(False) 367 self._setKnobAndStore(self._viewerForSettings, "-") 368 self._setKnobAndStore(self._channels, "rgba") 369 self._setKnobAndStore(self._useProxy, False) 370 self._setKnobAndStore(self._frameRange, str(nuke.root().frameRange())) 371 self._setKnobAndStore(self._rangeEnum, "input") 372 self._setKnobAndStore(self._continueOnError, True) 373 self._setKnobAndStore(self._bgRender, False) 374 self._setKnobAndStore(self._luts, "sRGB") 375 self._setKnobAndStore(self._burnInLUT, False) 376 self._setKnobAndStore(self._cleanup, True) 377 self._setKnobAndStore(self._maxMem, str(max(nuke.memory("max_usage") / 2097152, 16)) + "M") 378 self._setKnobAndStore(self._numThreads, max(nuke.NUM_CPUS / 2, 1)) 379 elif (knob == self._viewerForSettings): 380 if self._viewerForSettings.value() != "-": 381 viewer = self._viewers[self._viewerForSettings.value()] 382 self._setKnobAndStore(self._useRoi, viewer.roiEnabled()) 383 roi = viewer.roi() 384 if roi != None: 385 self._roi.fromDict(roi) 386 self._state.save(self._roi) 387 self._channels.fromScript(viewer.knob("channels").toScript()) 388 self._state.save(self._channels) 389 self._setKnobAndStore(self._useProxy, nuke.root().proxy()) 390 self._frameRangeFromViewer(viewer.name()) 391 self._state.save(self._frameRange) 392 self._setKnobAndStore(self._rangeEnum, viewer.name()) 393 self._roi.setVisible(self._useRoi.value()) 394 self._setKnobAndStore(self._luts, self._lutFromViewer(viewer.name())) 395 elif (knob == self._useRoi): 396 self._roi.setVisible(self._useRoi.value()) 397 elif self._isViewerSettingKnob(knob): 398 self._viewerForSettings.setValue("-") 399 self._state.save(self._viewerForSettings) 400 elif knob == self._luts: 401 self._burnInLUT.setEnabled(self._luts.value() != "None")
402
403 - def _deleteTemporaries(self):
404 """Delete all the files in the range to be rendered.""" 405 temporariesPath = self._getIntermediatePath() 406 temporariesPath = temporariesPath .replace("%V", "%s") 407 for r in nuke.FrameRanges(self._frameRange.value().split(',')): 408 deleteRange = xrange(r.minFrame(), r.maxFrame() + 1) 409 410 for v in self._selectedViews(): 411 for i in deleteRange: 412 if len(self._selectedViews()) > 1: 413 f = temporariesPath % (i, v,) 414 else: 415 f = temporariesPath % i 416 417 if os.access(f, os.F_OK): 418 os.remove(f)
419
420 - def _getIntermediateFileType(self):
421 return _gFlipbookDialogState.getValue('intermediateFormat', 'exr')
422
423 - def _getIntermediatePath(self):
424 """Get the path for the temporary files. May be filled in using printf syntax.""" 425 flipbooktmp="" 426 if flipbooktmp == "": 427 try: 428 flipbooktmp = self._selectedFlipbook().cacheDir() 429 except: 430 try: 431 flipbooktmp = os.environ["NUKE_DISK_CACHE"] 432 except: 433 flipbooktmp = nuke.value("preferences.DiskCachePath") 434 435 if len(self._selectedViews()) > 1: 436 flipbookFileNameTemp = "nuke_tmp_flip.%04d.%V." + self._getIntermediateFileType() 437 else: 438 flipbookFileNameTemp = "nuke_tmp_flip.%04d." + self._getIntermediateFileType() 439 flipbooktmpdir = os.path.join(flipbooktmp, "flipbook") 440 if not os.path.exists(flipbooktmpdir): 441 os.mkdir(flipbooktmpdir) 442 443 if not os.path.isdir(flipbooktmpdir): 444 raise RuntimeError("%s already exists and is not a directory, please delete before flipbooking again" % flipbooktmpdir) 445 flipbooktmp = os.path.join(flipbooktmpdir, flipbookFileNameTemp) 446 447 if nuke.env['WIN32']: 448 flipbooktmp = re.sub(r"\\", "/", str(flipbooktmp)) 449 return flipbooktmp
450
451 - def _requireIntermediateNode(self):
452 if self._node.Class() == "Read" or self._node.Class() == "Write": 453 flipbookToRun = flipbooking.gFlipbookFactory.getApplication(self._flipbookEnum.value()) 454 flipbookCapabilities = flipbookToRun.capabilities() 455 456 # Check if we can read it in directly.. 457 filePath = nuke.filename(self._node) 458 # There might be a prefix that overrides the extension, if so, this will 459 # confuse the flipbook probably, so just create a render. 460 if ':' in filePath: 461 readerPrefix = filePath.split(':')[0] 462 if len(readerPrefix) > 1: # 1 is a drive letter 463 return True 464 fileExtension = os.path.splitext(filePath)[1].lower()[1:] 465 flipbookSupportsFileType = fileExtension in flipbookCapabilities.get("fileTypes", []) 466 if not flipbookSupportsFileType: 467 return True 468 469 # Not all flipbooks can handle weird channels 470 flipbookSupportsArbitraryChannels = flipbookCapabilities.get("arbitraryChannels", False) 471 if self._channels.value() not in set(["rgb", "rgba", "alpha"]) and not flipbookSupportsArbitraryChannels: 472 return True 473 channelKnob = self._node.knob("channels") 474 if channelKnob != None and channelKnob.value() != self._channels.value(): 475 return True 476 477 if self._burnInLUT.value() and self._burnInLUT.enabled(): 478 return True 479 480 return False 481 else: 482 return True
483
484 - def _createIntermediateNode(self):
485 """Create a write node to render out the current node so that output may be used for flipbooking.""" 486 flipbooktmp = self._getIntermediatePath() 487 488 fieldname = "file" 489 if self._useProxy.value(): 490 fieldname = "proxy" 491 492 fixup = nuke.createNode("Group", "tile_color 0xff000000", inpanel = False) 493 with fixup: 494 fixup.setName("Flipbook") 495 inputNode = nuke.createNode("Input", inpanel = False) 496 shuffle = nuke.createNode("Shuffle", inpanel = False) 497 shuffle.knob("in").setValue(self._channels.value()) 498 write = nuke.createNode("Write", fieldname+" {"+flipbooktmp+"}", inpanel = False) 499 write.knob('file_type').setValue(self._getIntermediateFileType()) 500 write.knob('views').fromScript(" ".join(self._selectedViews())) 501 502 if self._getIntermediateFileType() == "exr": 503 write.knob('compression').setValue("B44") 504 if self._burnInLUT.value(): 505 lut = self._getLUT() 506 if lut != "None": 507 write.knob('colorspace').setValue(lut) 508 outputNode = nuke.createNode("Output", inpanel = False) 509 #If called on a Viewer connect fixup node to the one immediately above if exists. 510 if self._node.Class() == "Viewer": 511 fixup.setInput(0, self._node.input(int(nuke.knob(self._node.fullName()+".input_number")))) 512 else: 513 fixup.setInput(0, self._node) 514 515 try: 516 # Throws exception on render failure 517 if (self.isBackgrounded()): 518 nuke.executeBackgroundNuke(nuke.EXE_PATH, [write], 519 nuke.FrameRanges(self._frameRange.value().split(',')), self._selectedViews(), 520 self._getBackgroundLimits(), self._continueOnError.value(), 521 self._flipbookEnum.value(), self._getOptions(write)) 522 else: 523 nuke.executeMultiple((write,), 524 nuke.FrameRanges(self._frameRange.value().split(',')), self._selectedViews(), 525 self._continueOnError.value()) 526 except RuntimeError, msg: 527 if msg.args[0][0:9] == "Cancelled": 528 splitMsg = string.split(msg.args[0]) 529 530 msg = """Render did not complete, do you want to show the completed range? 531 Frame range %s contains %s frames but only %s finished.""" % (self._frameRange.value(), splitMsg[3], splitMsg[1]) 532 if nuke.ask(msg) == False: 533 nuke.delete(fixup) 534 fixup = None 535 else: 536 nuke.delete(fixup) 537 fixup = None 538 nuke.message("Flipbook render failed:\n%s" % (msg.args[0],)) 539 # except BaseException, be: 540 # print be.__class__.__name__ 541 # traceback.print_exc() 542 finally: 543 return fixup
544
545 - def _getLUT(self):
546 return self._luts.value()
547
548 - def _getAudio(self):
549 nukeNode = nuke.toNode( self._audioSource.value() ) 550 ret = "" 551 if nukeNode != None: 552 ret = nukeNode["file"].getEvaluatedValue() 553 554 # if the platform is not windows and we have spaces in the audio name then we cant use audio 555 # as framecycler does not support spaces in the name 556 if nuke.env['WIN32'] == False: 557 if ret != "": 558 # check if we have spaces 559 if (' ' in ret) == True : 560 nuke.message("Framecycler does not currently support spaces in the audio file name, to enable audio please ensure the audio file contains no spaces.") 561 ret = "" 562 return ret
563
564 - def _getOptions(self, nodeToFlipbook):
565 options = { 566 } 567 568 try: 569 options['pixelAspect'] = float(nuke.value(nodeToFlipbook.name()+".pixel_aspect")) 570 except: 571 pass 572 573 try: 574 f = nodeToFlipbook.format() 575 options['dimensions'] = { 'width' : f.width(), 'height' : f.height() } 576 except: 577 pass 578 579 # LUT 580 if not self._burnInLUT.value(): 581 inputColourspace = "linear" 582 outputColourspace = "linear" 583 # Check if we have a different than linear input 584 if self._node.Class() == "Read" or self._node.Class() == "Write": 585 lut = self._node.knob("colorspace").value() 586 # Might be in the format of "default (foo)", if so, get at "foo". 587 if lut[:7] == "default": 588 lut = lut[9:-1] 589 inputColourspace = lut 590 591 # Check our output 592 lut = self._getLUT() 593 if lut != "None": 594 outputColourspace = lut 595 596 if inputColourspace == outputColourspace: 597 options["lut"] = inputColourspace 598 else: 599 options["lut"] = inputColourspace + "-" + outputColourspace 600 # AUDIO 601 audioTrack = self._getAudio() 602 if audioTrack != "": 603 options["audio"] = audioTrack 604 605 # ROI 606 if self._useRoi.value(): 607 roi = self._roi.toDict() 608 if (roi["r"] - roi["x"] > 0) and (roi["t"] - roi["y"] > 0): 609 options["roi"] = bboxToTopLeft(int(nuke.value(nodeToFlipbook.name()+".actual_format.height")), roi) 610 611 return options
612
613 - def run(self):
614 flipbookToRun = flipbooking.gFlipbookFactory.getApplication(self._flipbookEnum.value()) 615 if (flipbookToRun): 616 if not os.access(flipbookToRun.path(), os.X_OK): 617 raise RuntimeError("%s cannot be executed (%s)." % (flipbookToRun.name(), flipbookToRun.path(),) ) 618 619 nodeToFlipbook = None 620 rootProxyMode = nuke.root().proxy() 621 try: 622 # Need this to prevent Bug 5295 623 nuke.Undo().disable() 624 nuke.root().setProxy(self._useProxy.value()) 625 626 if self._cleanup.value(): 627 self._deleteTemporaries() 628 calledOnNode = self._node 629 if self._node.Class() == "Viewer": 630 self._node = self._node.input(int(self._node.knob("input_number").value())) 631 632 runFlipbook = False 633 # In many cases we need to create a temporary node and render that. 634 if not self._requireIntermediateNode(): 635 nodeToFlipbook = self._node 636 runFlipbook = True 637 else: 638 nodeToFlipbook = self._createIntermediateNode() 639 runFlipbook = not self._bgRender.value() 640 641 if nodeToFlipbook and runFlipbook: 642 filename = nuke.filename(nodeToFlipbook) 643 if filename is None or filename == "": 644 raise RuntimeError("Cannot run a flipbook on '%s', expected to find a filename and there was none." % (nodeToFlipbook.fullName(),)) 645 flipbookToRun.run(filename, 646 nuke.FrameRanges(self._frameRange.value().split(',')), 647 self._selectedViews(), self._getOptions(nodeToFlipbook)) 648 finally: 649 if self._node != nodeToFlipbook: 650 nuke.delete(nodeToFlipbook) 651 nuke.root().setProxy(rootProxyMode) 652 nuke.Undo().enable() 653 else: 654 raise RuntimeError("No flipbook called " + self._flipbookEnum.value() + " found. Was it deregistered while the dialog was open?")
655
656 -def showExecuteDialog(nodesToExecute, exceptOnError = True):
657 """Present a dialog that executes the given list of nodes.""" 658 groupContext = nuke.root() 659 d = ExecuteDialog(_gRenderDialogState, groupContext, nodesToExecute, exceptOnError) 660 if d.showModalDialog() == True: 661 d.run() 662
663 -def showRenderDialog(nodesToRender, exceptOnError = True):
664 """Present a dialog that renders the given list of nodes.""" 665 groupContext = nuke.root() 666 d = RenderDialog(_gRenderDialogState, groupContext, nodesToRender, exceptOnError) 667 if d.showModalDialog() == True: 668 d.run() 669
670 -def showFlipbookDialog(node, takeNodeSettings = False):
671 """Present a dialog that flipbooks the given node.""" 672 if node is None: 673 raise RuntimeError("Can't launch flipbook, require a node."); 674 if node.Class() == "Viewer" and node.inputs() == 0: 675 raise RuntimeError("Can't launch flipbook, there is nothing connected to the viewed input."); 676 677 groupContext = nuke.root() 678 679 e = FlipbookDialog(_gFlipbookDialogState, groupContext, node, takeNodeSettings) 680 if (e.showModalDialog() == True): 681 e.run()
682
683 -def showFlipbookDialogForSelected():
684 """Present a dialog that flipbooks the currently selected node.""" 685 try: 686 showFlipbookDialog(nuke.selectedNode()) 687 except ValueError, ve: 688 raise RuntimeError("Can't launch flipbook, %s." % (ve.args[0]))
689
690 -def bboxToTopLeft(height, roi):
691 """Convert the roi passed from a origin at the bottom left to the top left. 692 Also replaces the r and t keys with w and h keys. 693 @param height: the height used to determine the top. 694 @param roi: the roi with a bottom left origin, must have x, y, r & t keys. 695 @result dict with x, y, w & h keys""" 696 topLeftRoi = { 697 "x": roi["x"], 698 "y": height - roi["y"] - (roi["t"] - roi["y"]), 699 "w": roi["r"] - roi["x"], 700 "h": roi["t"] - roi["y"] } 701 return topLeftRoi
702
703 -def setRenderDialogDefaultOption(name, value):
704 """ Set a particular option to the given value. The type of the value differs per option, giving the wrong value may result in exceptions. The options are read every time the dialog is opened, though not every knob in the dialog has it's value stored.""" 705 _gRenderDialogState.saveValue(name, value)
706
707 -def setFlipbookDefaultOption(name, value):
708 """ Set a particular option to the given value. The type of the value differs per option, giving the wrong value may result in exceptions. The options are read every time the dialog is opened, though not every knob in the dialog has it's value stored.""" 709 _gFlipbookDialogState.saveValue(name, value)
710