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