| Trees | Indices | Help |
|
|---|
|
|
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 13 from threading import Thread 14 from nukescripts import utils, sys, os, captureViewer 15 16 #import traceback 17 18 ############################################################################## 19 # Dialogs 20 ############################################################################## 212546 47 _gRenderDialogState = DialogState() 48 _gFlipbookDialogState = DialogState() 49 _gViewerCaptureDialogState = DialogState() 5027 """Return the given knob's stored last state value. 28 If none exists, defaultValue is returned. 29 Values are stored in a dict referenced by knob name, so names must be unique!""" 30 return self.getValue(knob.name(), defaultValue)3133 """Store the knob's current value as the 'last state' for the next time the dialog is opened. 34 Values are stored in a dict referenced by knob name, so names must be unique!""" 35 self.saveValue(knob.name(), knob.value())3638 """Convenience method for setting a value straight on a knob.""" 39 knob.setValue(self.get(knob, defaultValue))44 """Recalls the value. If it was not set before, it will return the defaultValue.""" 45 return self._state.get(id, defaultValue)54 57 61 65 6918971 oc = nuke.OutputContext() 72 allViews = [oc.viewname(i) for i in xrange(1, oc.viewcount())] 73 return " ".join(allViews)7476 """Add knobs for view selection.""" 77 oc = nuke.OutputContext() 78 if (oc.viewcount() > 2): 79 self._viewSelection = nuke.MultiView_Knob("multi_view", "Views") 80 self._viewSelection.fromScript(self._state.get(self._viewSelection, self._getDefaultViews())) 81 self.addKnob(self._viewSelection) 82 self._viewSelection.clearFlag(nuke.NO_MULTIVIEW)8385 """Add the knob and make sure it cannot be animated.""" 86 knob.setFlag(nuke.NO_ANIMATION | nuke.NO_MULTIVIEW) 87 super(ExecuteDialog, self).addKnob(knob)8890 self._state = dialogState 91 self._nodeSelection = nodeSelection 92 self._exceptOnError = exceptOnError 93 94 nukescripts.PythonPanel.__init__(self, self._titleString(), self._idString(), False) 95 96 self._viewers = {} 97 for n in nuke.allNodes("Viewer", groupContext): 98 self._viewers[n.name()] = n 99 self._specialRanges = ["input", "global", "custom"] 100 101 self._addPreKnobs() 102 103 # Frame range knobs 104 self._rangeEnum = nuke.Enumeration_Knob( "frame_range", "Frame range", self._specialRanges + self._viewers.keys() ) 105 self._state.setKnob(self._rangeEnum, "input") 106 self.addKnob( self._rangeEnum ) 107 108 self._frameRange = nuke.String_Knob( "frame_range_string", "") 109 self._frameRange.clearFlag(nuke.STARTLINE) 110 if self._rangeEnum.value() == "custom": 111 self._state.setKnob(self._frameRange, str(nuke.root().frameRange())) 112 else: 113 self._setFrameRangeFromSource(self._rangeEnum.value()) 114 115 self.addKnob(self._frameRange) 116 117 # Proxy 118 self._useProxy = nuke.Boolean_Knob("use_proxy", "Use proxy") 119 self._useProxy.setFlag(nuke.STARTLINE) 120 self._state.setKnob(self._useProxy, nuke.root().proxy()) 121 self.addKnob(self._useProxy) 122 123 self._addPostKnobs() 124 125 self._continueOnError = nuke.Boolean_Knob("continue", "Continue on error") 126 self._state.setKnob(self._continueOnError, True) 127 self._continueOnError.setFlag(nuke.STARTLINE) 128 self.addKnob(self._continueOnError) 129 130 self._addViewKnob() 131 132 self._addTrailingKnobs()133135 self._state.save(knob) 136 if (knob == self._frameRange): 137 self._rangeEnum.setValue("custom") 138 self._state.save(self._rangeEnum) 139 self._state.saveValue("customRange", knob.value()) 140 if (knob == self._rangeEnum): 141 self._setFrameRangeFromSource(knob.value()) 142 self._state.save(self._frameRange)143145 if (source == "input"): 146 try: 147 activeInput = nuke.activeViewer().activeInput() 148 self._frameRange.setValue(str(nuke.activeViewer().node().upstreamFrameRange(activeInput))) 149 except: 150 self._frameRange.setValue(str(nuke.root().frameRange())) 151 elif (source == "global"): 152 self._frameRange.setValue(str(nuke.root().frameRange())) 153 elif (source == "custom"): 154 customRange = self._state.getValue("customRange", None) 155 if customRange: 156 self._frameRange.setValue(str(customRange)) 157 else: 158 self._frameRangeFromViewer(source);159161 """"Set the framerange knob to have the framerange from the given viewer.""" 162 viewerRange = str(self._viewers[viewer].playbackRange()) 163 self._frameRange.setValue(viewerRange)164166 try: 167 return self._viewSelection.value().split() 168 except AttributeError: 169 # If we didn't add the view selection knob, there should be just the one view. 170 return [nuke.OutputContext().viewname(1)]171 174176 frame_ranges = nuke.FrameRanges(self._frameRange.value().split(',')) 177 views = self._selectedViews() 178 rootProxyMode = nuke.root().proxy() 179 try: 180 nuke.Undo().disable() 181 nuke.root().setProxy(self._useProxy.value()) 182 nuke.executeMultiple(self._nodeSelection, frame_ranges, views, continueOnError = self._continueOnError.value()) 183 except RuntimeError, e: 184 if self._exceptOnError or e.args[0][0:9] != "Cancelled": # TO DO: change this to an exception type 185 raise 186 finally: 187 nuke.root().setProxy(rootProxyMode) 188 nuke.Undo().enable()193 196 199336201 if self.isTimelineWrite(): 202 self._frameServerRender = nuke.Boolean_Knob("frameserver_render", "Render to timeline") 203 self._state.setKnob( self._frameServerRender, True) 204 self._frameServerRender.setFlag(nuke.STARTLINE) 205 self.addKnob(self._frameServerRender)206208 # Background render stuff 209 self._bgRender = nuke.Boolean_Knob("bg_render", "Render in background") 210 self._state.setKnob(self._bgRender, False) 211 self._bgRender.setFlag(nuke.STARTLINE) 212 self.addKnob(self._bgRender) 213 self._numThreads = nuke.Int_Knob("num_threads", "Thread limit") 214 self._numThreads.setVisible(self._bgRender.value()) 215 self._state.setKnob(self._numThreads, max(nuke.NUM_CPUS / 2, 1)) 216 self.addKnob(self._numThreads) 217 self._maxMem = nuke.String_Knob("max_memory", "Memory limit") 218 self._state.setKnob(self._maxMem, str(max(nuke.memory("max_usage") / 2097152, 16)) + "M") 219 self._maxMem.setVisible(self._bgRender.value()) 220 self.addKnob(self._maxMem)221 222 227229 ExecuteDialog.knobChanged(self, knob) 230 231 bgRenderVisible = False 232 frameServerRender = False 233 try: 234 frameServerRender = self._frameServerRender.value() 235 except: 236 pass 237 238 if not frameServerRender and self._bgRender.value(): 239 bgRenderVisible = True 240 241 self._bgRender.setVisible( not frameServerRender ) 242 self._numThreads.setVisible(bgRenderVisible) 243 self._maxMem.setVisible(bgRenderVisible) 244 245 if frameServerRender: 246 self._rangeEnum.setValue( "global" ) 247 self._setFrameRangeFromSource(self._rangeEnum.value()) 248 self._rangeEnum.setEnabled( False ) 249 self._frameRange.setEnabled( False ) 250 self._useProxy.setVisible( False ) 251 self._continueOnError.setVisible( False ) 252 else: 253 self._rangeEnum.setEnabled( True ) 254 self._frameRange.setEnabled( True ) 255 self._useProxy.setVisible( True ) 256 self._continueOnError.setVisible( True )257 258260 """Return whether the background rendering option is enabled.""" 261 return self._bgRender.value()262264 265 if not nuke.env['studio']: 266 return False 267 268 if len(self._nodeSelection) > 1 or len(self._nodeSelection) < 1: 269 return False 270 271 write = self._nodeSelection[0] 272 273 if write == nuke.root(): 274 ## must be a render of all 'write' nodes, this is tricky as there may be other executable nodes apart from write nodes 275 ## lets assume the write nodes are write, writegeo, particlecache, and diskcache 276 277 # there is a bug here however as there may be groups they are executable which will be skipped right now 278 279 writeNodes = nuke.allNodes( 'Write' ) 280 writeNodes.extend( nuke.allNodes( 'WriteGeo') ) 281 writeNodes.extend( nuke.allNodes( 'ParticleCache') ) 282 writeNodes.extend( nuke.allNodes( 'DiskCache') ) 283 284 if len(writeNodes) > 1: 285 return False 286 287 if len(writeNodes) > 0: 288 write = writeNodes[0] 289 290 timelineWriteNode = None 291 292 try: 293 from foundry.frameserver.nuke.workerapplication import GetWriteNode 294 timelineWriteNode = GetWriteNode() 295 except: 296 pass 297 298 if not timelineWriteNode: 299 return False 300 301 if timelineWriteNode.name() != write.name(): 302 return False 303 304 ## double check that this script is actually in a timeline 305 try: 306 from hiero.ui import isInAnyProject 307 return isInAnyProject( nuke.scriptName() ) 308 except: 309 pass 310 311 return False312314 if self.isTimelineWrite() and self._frameServerRender.value(): 315 from hiero.ui.nuke_bridge.nukestudio import scriptSaveAndReRender 316 scriptSaveAndReRender() 317 return 318 319 frame_ranges = nuke.FrameRanges(self._frameRange.value().split(',')) 320 views = self._selectedViews() 321 rootProxyMode = nuke.root().proxy() 322 try: 323 nuke.Undo().disable() 324 nuke.root().setProxy(self._useProxy.value()) 325 if (self.isBackgrounded()): 326 nuke.executeBackgroundNuke(nuke.EXE_PATH, self._nodeSelection, 327 frame_ranges, views, self._getBackgroundLimits(), continueOnError = self._continueOnError.value()) 328 else: 329 nuke.executeMultiple(self._nodeSelection, frame_ranges, views, continueOnError = self._continueOnError.value()) 330 except RuntimeError, e: 331 if self._exceptOnError or e.args[0][0:9] != "Cancelled": # TO DO: change this to an exception type 332 raise 333 finally: 334 nuke.root().setProxy(rootProxyMode) 335 nuke.Undo().enable()340 343899345 # Init attributes 346 self._node = node 347 self._takeNodeSettings = takeNodeSettings 348 self._customKnobs = [] 349 350 # init super 351 RenderDialog.__init__(self, dialogState, groupContext) 352 353 # Override the initial frame range value 354 self._state.setKnob(self._rangeEnum, "input") 355 self._setFrameRangeFromSource(self._rangeEnum.value()) 356 357 if self._takeNodeSettings: 358 self._viewerForSettings.setValue(node.name()) 359 self.knobChanged(self._viewerForSettings)360362 self._flipbookEnum = nuke.Enumeration_Knob( "flipbook", "Flipbook", flipbooking.gFlipbookFactory.getNames() ) 363 self._state.setKnob(self._flipbookEnum, "Default") 364 self.addKnob( self._flipbookEnum ) 365 self._viewerForSettings = nuke.Enumeration_Knob("viewer_settings", "Take settings from", ["-"] + self._viewers.keys()) 366 if not self._takeNodeSettings: 367 self._viewerForSettings.setValue("-") 368 self.addKnob(self._viewerForSettings) 369 370 self._defaultValues = nuke.PyScript_Knob("default", "Defaults") 371 self.addKnob(self._defaultValues) 372 373 # Region of Interest knobs 374 self._useRoi = nuke.Boolean_Knob("use_roi", "Enable ROI") 375 self._useRoi.setFlag(nuke.STARTLINE) 376 self._state.setKnob(self._useRoi, False) 377 self.addKnob(self._useRoi) 378 self._roi = nuke.BBox_Knob("roi", "Region of Interest") 379 self._state.setKnob(self._roi, (0, 0, 0, 0)) 380 self.addKnob(self._roi) 381 self._roi.setVisible(self._useRoi.value()) 382 383 # Channel knobs 384 self._channels = nuke.Channel_Knob( "channels_knob", "Channels") 385 if self._node.Class() == "Write": 386 self._channels.setValue(self._node.knob("channels").value()) 387 else: 388 self._state.setKnob(self._channels, "rgba") 389 self._channels.setFlag(nuke.STARTLINE | nuke.NO_CHECKMARKS) 390 self.addKnob( self._channels )391393 super(FlipbookDialog, self)._addPostKnobs() 394 # Misc knobs 395 self._cleanup = nuke.Boolean_Knob("cleanup", "Delete existing temporary files") 396 self._cleanup.setFlag(nuke.STARTLINE) 397 self._state.setKnob(self._cleanup, True) 398 self.addKnob(self._cleanup) 399 400 # LUT knobs 401 self._luts = nuke.Enumeration_Knob("lut", "LUT", nuke.ViewerProcess.registeredNames()) 402 if self._takeNodeSettings: 403 self._state.setKnob(self._luts, self._lutFromViewer(self._viewerForSettings.value())) 404 else: 405 self._state.setKnob(self._luts, self._lutFromViewer()) 406 self.addKnob(self._luts) 407 408 self._burnInLUT = nuke.Boolean_Knob("burnin", "Burn in the LUT") 409 self._state.setKnob(self._burnInLUT, False) 410 self.addKnob(self._burnInLUT) 411 412 # Audio knobs 413 audioList = [] 414 audioList.append( "None" ) 415 for node in nuke.allNodes("AudioRead"): 416 audioList.append( node.name() ) 417 self._audioSource = nuke.Enumeration_Knob( "audio", "Audio", audioList ) 418 self._state.setKnob(self._audioSource, audioList[0] ) 419 self.addKnob( self._audioSource )420422 self.flipbookKnobs()423425 try: 426 beforeKnobs = self.knobs() 427 flipbookToRun = flipbooking.gFlipbookFactory.getApplication(self._flipbookEnum.value()) 428 flipbookToRun.dialogKnobs(self) 429 afterKnobs = self.knobs() 430 self._customKnobs = list(set(beforeKnobs.values()) ^ set(afterKnobs.values())) 431 except NotImplementedError: 432 pass433 436438 oc = nuke.OutputContext() 439 self._views = [oc.viewname(i) for i in xrange(1, oc.viewcount())] 440 if (oc.viewcount() > 2): 441 supportedViews = self._selectedFlipbook().capabilities()["maximumViews"] 442 if (int(supportedViews) > 1): 443 self._viewSelection = nuke.MultiView_Knob("views", "Views") 444 else: 445 self._viewSelection = nuke.OneView_Knob("views", "View", self._views) 446 activeView = nuke.activeViewer().view() 447 if activeView == "": 448 activeView = self._views[0] 449 450 # Retrieve previous view selection or default to selecting all available views 451 previousViews = self._state.getValue(self._viewSelection.name(), " ".join(self._views)).split() 452 # Get the intersection of the previous selection and the available views 453 viewsToRestore = set(self._views).intersection(previousViews) 454 if viewsToRestore: 455 self._viewSelection.setValue(" ".join(viewsToRestore)) 456 else: 457 self._viewSelection.setValue(activeView) 458 self.addKnob(self._viewSelection) 459 self._viewSelection.clearFlag(nuke.NO_MULTIVIEW)460 463465 try: 466 if viewerName == "": 467 return nuke.ViewerProcess.node().knob("current").value() 468 else: 469 return nuke.ViewerProcess.node(viewer=viewerName).knob("current").value() 470 except AttributeError: 471 return "None"472474 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._luts475 479481 RenderDialog.knobChanged(self, knob) 482 if knob == self._defaultValues: 483 self._setKnobAndStore(self._useRoi, False) 484 self._setKnobAndStore(self._roi, (0, 0, 0, 0)) 485 self._roi.setVisible(False) 486 self._maxMem.setVisible(False) 487 self._numThreads.setVisible(False) 488 self._setKnobAndStore(self._viewerForSettings, "-") 489 self._setKnobAndStore(self._channels, "rgba") 490 self._setKnobAndStore(self._useProxy, False) 491 self._setKnobAndStore(self._frameRange, str(nuke.root().frameRange())) 492 self._setKnobAndStore(self._rangeEnum, "input") 493 self._setKnobAndStore(self._continueOnError, True) 494 self._setKnobAndStore(self._bgRender, False) 495 self._setKnobAndStore(self._luts, "sRGB") 496 self._setKnobAndStore(self._burnInLUT, False) 497 self._setKnobAndStore(self._cleanup, True) 498 self._setKnobAndStore(self._maxMem, str(max(nuke.memory("max_usage") / 2097152, 16)) + "M") 499 self._setKnobAndStore(self._numThreads, max(nuke.NUM_CPUS / 2, 1)) 500 elif (knob == self._viewerForSettings): 501 if self._viewerForSettings.value() != "-": 502 viewer = self._viewers[self._viewerForSettings.value()] 503 self._setKnobAndStore(self._useRoi, viewer.roiEnabled()) 504 roi = viewer.roi() 505 if roi != None: 506 self._roi.fromDict(roi) 507 self._state.save(self._roi) 508 self._channels.fromScript(viewer.knob("channels").toScript()) 509 self._state.save(self._channels) 510 self._setKnobAndStore(self._useProxy, nuke.root().proxy()) 511 self._frameRangeFromViewer(viewer.name()) 512 self._state.save(self._frameRange) 513 self._setKnobAndStore(self._rangeEnum, viewer.name()) 514 self._roi.setVisible(self._useRoi.value()) 515 self._setKnobAndStore(self._luts, self._lutFromViewer(viewer.name())) 516 elif (knob == self._useRoi): 517 self._roi.setVisible(self._useRoi.value()) 518 elif self._isViewerSettingKnob(knob): 519 self._viewerForSettings.setValue("-") 520 self._state.save(self._viewerForSettings) 521 elif knob == self._luts: 522 self._burnInLUT.setEnabled(self._luts.value() != "None") 523 524 if knob == self._flipbookEnum: 525 for k in self._customKnobs: 526 self.removeKnob(k) 527 self.removeKnob(self.okButton) 528 self.removeKnob(self.cancelButton) 529 self._customKnobs = [] 530 self.flipbookKnobs() 531 self._makeOkCancelButton() 532 elif knob in self._customKnobs: 533 try: 534 flipbookToRun = flipbooking.gFlipbookFactory.getApplication(self._flipbookEnum.value()) 535 flipbookToRun.dialogKnobChanged(self, knob) 536 except NotImplementedError: 537 pass538540 """Delete all the files in the range to be rendered.""" 541 temporariesPath = self._getIntermediatePath() 542 isFilePerView = temporariesPath.find("%V") != -1 543 selectedViews = self._selectedViews() 544 temporariesPath = temporariesPath .replace("%V", "%s") 545 for r in nuke.FrameRanges(self._frameRange.value().split(',')): 546 deleteRange = xrange(r.minFrame(), r.maxFrame() + 1) 547 548 for v in selectedViews: 549 for i in deleteRange: 550 if isFilePerView and (len(selectedViews) > 1): 551 f = temporariesPath % (i, v,) 552 else: 553 f = temporariesPath % i 554 555 if os.access(f, os.F_OK): 556 os.remove(f)557 560562 """Get the path for the temporary files. May be filled in using printf syntax.""" 563 flipbooktmp="" 564 if flipbooktmp == "": 565 try: 566 flipbooktmp = self._selectedFlipbook().cacheDir() 567 except: 568 try: 569 flipbooktmp = os.environ["NUKE_DISK_CACHE"] 570 except: 571 flipbooktmp = nuke.value("preferences.DiskCachePath") 572 573 if len(self._selectedViews()) > 1: 574 flipbookFileNameTemp = "nuke_tmp_flip.%04d.%V." + self._getIntermediateFileType() 575 else: 576 flipbookFileNameTemp = "nuke_tmp_flip.%04d." + self._getIntermediateFileType() 577 flipbooktmpdir = os.path.join(flipbooktmp, "flipbook") 578 if not os.path.exists(flipbooktmpdir): 579 os.mkdir(flipbooktmpdir) 580 581 if not os.path.isdir(flipbooktmpdir): 582 raise RuntimeError("%s already exists and is not a directory, please delete before flipbooking again" % flipbooktmpdir) 583 flipbooktmp = os.path.join(flipbooktmpdir, flipbookFileNameTemp) 584 585 if nuke.env['WIN32']: 586 flipbooktmp = re.sub(r"\\", "/", str(flipbooktmp)) 587 return flipbooktmp588590 if nodeToTest.Class() == "Read" or nodeToTest.Class() == "Write": 591 flipbookToRun = flipbooking.gFlipbookFactory.getApplication(self._flipbookEnum.value()) 592 flipbookCapabilities = flipbookToRun.capabilities() 593 594 # Check if we can read it in directly.. 595 filePath = nuke.filename(nodeToTest) 596 # There might be a prefix that overrides the extension, if so, this will 597 # confuse the flipbook probably, so just create a render. 598 if ':' in filePath: 599 readerPrefix = filePath.split(':')[0] 600 if len(readerPrefix) > 1: # 1 is a drive letter 601 return True 602 fileExtension = os.path.splitext(filePath)[1].lower()[1:] 603 flipbookSupportsFileType = fileExtension in flipbookCapabilities.get("fileTypes", []) 604 if not flipbookSupportsFileType: 605 return True 606 607 # Not all flipbooks can handle weird channels 608 flipbookSupportsArbitraryChannels = flipbookCapabilities.get("arbitraryChannels", False) 609 if self._channels.value() not in set(["rgb", "rgba", "alpha"]) and not flipbookSupportsArbitraryChannels: 610 return True 611 channelKnob = nodeToTest.knob("channels") 612 if channelKnob != None and channelKnob.value() != self._channels.value(): 613 return True 614 615 ## if flipbook doesn't support roi and the roi option is on we need the intermediate node because we're going to insert a crop 616 if self._useRoi.value() and self._useRoi.enabled(): 617 if not flipbookCapabilities.get("roi", False): 618 return True 619 620 if self._burnInLUT.value() and self._burnInLUT.enabled(): 621 return True 622 623 # Separate view files 624 # TODO Temporary workaround to deal with MediaSource not being aware of 625 # the %V notation for specifiying separate view files. 626 if "%V" in filePath or "%v" in filePath: 627 return True 628 629 return False 630 else: 631 return True632634 """Helper function to get the appropriate colorspace to set on the Write node when burning the 635 viewer color transform into the render.""" 636 637 writeColorspace = None 638 639 lut = self._getLUT() 640 641 # Determine whether we're using original Nuke, rather than OCIO, color management. 642 usingNukeColorspaces = False 643 rootNode = nuke.root() 644 if rootNode: 645 colorManagementKnob = rootNode.knob("colorManagement") 646 if colorManagementKnob: 647 usingNukeColorspaces = (colorManagementKnob.value() == "Nuke") # Note: Must use value() rather than getValue(). 648 649 if usingNukeColorspaces: 650 651 # We're using Nuke colorspace management so the our lut knob will correspond to the appropriate 652 # colorspace name, except for rec1886, which we need to map to Gamma2.4. 653 # If the lut is the special case of None then don't set writeColorspace (to match the original behaviour). 654 # (The rec1886 -> Gamma2.4 mapping matches what's done in register_default_viewer_processes, in 655 # NukeScripts/src/ViewerProcess.py - I suppose we could consider adding something into 656 # nuke/src/Python/PythonObjects/ViewerProcess.cpp to allow the python code to look-up into ViewerProcessMap 657 # so we could parse the registered args to obtain the colorspace but that seems like overkill and not much 658 # less fragile.) 659 if lut == "rec1886": 660 writeColorspace = "Gamma2.4" 661 elif lut != "None": 662 writeColorspace = lut 663 664 else: 665 666 # We're using OCIO color management so we expect our lut string to contain a view name 667 # followed by a single space and a display name in parantheses. 668 # For example, the aces 1.0.1 config has lots of views but all for the display called ACES, 669 # hence here we might get lut set to, for example, 670 # DCDM P3 gamut clip (ACES) 671 # As another example, the spi-vfx config has views for two displays, DCIP3 and sRGB, so we might get 672 # Film (DCIP3) 673 # or 674 # Film (sRGB) 675 # etc. 676 # The nuke-default config has a single display called 'default' so we get lut set to 677 # None (default) 678 # or 679 # sRGB (default) 680 # etc. The nuke-default case is a bit confusing because the _view_ names almost match colorspace names 681 # and also correspond to legacy Nuke colorspace managament options. 682 # 683 # Anyway, what we actually need to return is the actual colorspace the particualr combination of 684 # view and display name map to, as defined in the relevant OCIO config file. 685 686 displayName = "" 687 viewName = "" 688 689 NUKE_LUT_FORMAT = '(.*) \((.*)\)$' 690 matchResult = re.match( NUKE_LUT_FORMAT , lut) 691 if matchResult is not None: 692 693 viewName = matchResult.group(1) 694 displayName = matchResult.group(2) 695 696 if rootNode: 697 writeColorspace = rootNode.getOCIOColorspaceFromViewTransform(displayName, viewName) 698 699 return writeColorspace700 701703 """Create a write node to render out the current node so that output may be used for flipbooking.""" 704 flipbooktmp = self._getIntermediatePath() 705 706 fieldname = "file" 707 if self._useProxy.value(): 708 fieldname = "proxy" 709 710 fixup = nuke.createNode("Group", "tile_color 0xff000000", inpanel = False) 711 with fixup: 712 fixup.setName("Flipbook") 713 inputNode = nuke.createNode("Input", inpanel = False) 714 shuffle = nuke.createNode("Shuffle", inpanel = False) 715 shuffle.knob("in").setValue(self._channels.value()) 716 if self._useRoi.value(): 717 crop = nuke.createNode( "Crop", inpanel = False ) 718 crop['box'].fromScript( self._roi.toScript() ) 719 write = nuke.createNode("Write", fieldname+" {"+flipbooktmp+"}", inpanel = False) 720 write.knob('file_type').setValue(self._getIntermediateFileType()) 721 selectedViews = self._selectedViews() 722 write.knob('views').fromScript(" ".join(selectedViews)) 723 724 if self._getIntermediateFileType() == "exr": 725 write.knob('compression').setValue("B44") 726 # Set the 'heroview' to be the first of the selected views. If we don't 727 # do this then then 'heroview' is by default set to be 1 which may not 728 # be a valid view for this clip. The 'heroview' is used as a fallback if 729 # no view has been set on the reader. This assumes the user has selected 730 # sensible views if they haven't then the write may still fail. 731 if len(selectedViews) > 0: 732 firstView = nuke.OutputContext().viewFromName(selectedViews[0]) 733 write.knob('heroview').setValue(firstView) 734 735 writeColorspace = "" 736 737 if self._burnInLUT.value(): 738 # The user has chosen to burn the viewer transform into the intermedate render so set the colorspace 739 # on the Write node appropriately. 740 writeColorspace = self._getBurninWriteColorspace() 741 else: 742 # The viewer transform is not being burnt into the intermediate render, set the Write node's colorspace 743 # to whatever the current working space is - when reading the file back in the flipbook we'll ssume 744 # the media was written out in the working space. 745 rootNode = nuke.root() 746 if rootNode: 747 workingSpaceKnob = rootNode.knob("workingSpaceLUT") 748 if workingSpaceKnob: 749 writeColorspace = workingSpaceKnob.value() 750 751 if writeColorspace: 752 write.knob('colorspace').setValue(writeColorspace) 753 754 outputNode = nuke.createNode("Output", inpanel = False) 755 #If called on a Viewer connect fixup node to the one immediately above if exists. 756 if self._node.Class() == "Viewer": 757 fixup.setInput(0, self._node.input(int(nuke.knob(self._node.fullName()+".input_number")))) 758 else: 759 fixup.setInput(0, self._node) 760 761 try: 762 # Throws exception on render failure 763 if (self.isBackgrounded()): 764 nuke.executeBackgroundNuke(nuke.EXE_PATH, [write], 765 nuke.FrameRanges(self._frameRange.value().split(',')), self._selectedViews(), 766 self._getBackgroundLimits(), self._continueOnError.value(), 767 self._flipbookEnum.value(), self._getOptions(write)) 768 else: 769 nuke.executeMultiple((write,), 770 nuke.FrameRanges(self._frameRange.value().split(',')), self._selectedViews(), 771 self._continueOnError.value()) 772 except RuntimeError, msg: 773 if msg.args[0][0:9] == "Cancelled": 774 splitMsg = string.split(msg.args[0]) 775 776 msg = """Render did not complete, do you want to show the completed range? 777 Frame range %s contains %s frames but only %s finished.""" % (self._frameRange.value(), splitMsg[3], splitMsg[1]) 778 if nuke.ask(msg) == False: 779 nuke.delete(fixup) 780 fixup = None 781 else: 782 nuke.delete(fixup) 783 fixup = None 784 nuke.message("Flipbook render failed:\n%s" % (msg.args[0],)) 785 # except BaseException, be: 786 # print be.__class__.__name__ 787 # traceback.print_exc() 788 finally: 789 return fixup790792 return self._luts.value()793795 nukeNode = nuke.toNode( self._audioSource.value() ) 796 ret = "" 797 if nukeNode != None: 798 ret = nukeNode["file"].getEvaluatedValue() 799 800 return ret801803 options = { 804 } 805 806 try: 807 options['pixelAspect'] = float(nuke.value(nodeToFlipbook.name()+".pixel_aspect")) 808 except: 809 pass 810 811 try: 812 f = nodeToFlipbook.format() 813 options['dimensions'] = { 'width' : f.width(), 'height' : f.height() } 814 except: 815 pass 816 817 # LUT 818 if not self._burnInLUT.value(): 819 inputColourspace = "linear" 820 outputColourspace = "linear" 821 # Check if we have a different than linear input 822 if self._node.Class() == "Read" or self._node.Class() == "Write": 823 lut = self._node.knob("colorspace").value() 824 # Might be in the format of "default (foo)", if so, get at "foo". 825 if lut[:7] == "default": 826 lut = lut[9:-1] 827 inputColourspace = lut 828 829 # Check our output 830 lut = self._getLUT() 831 if lut != "None": 832 outputColourspace = lut 833 834 if inputColourspace == outputColourspace: 835 options["lut"] = inputColourspace 836 else: 837 options["lut"] = inputColourspace + "-" + outputColourspace 838 # AUDIO 839 audioTrack = self._getAudio() 840 if audioTrack != "": 841 options["audio"] = audioTrack 842 843 # ROI 844 if self._useRoi.value(): 845 roi = self._roi.toDict() 846 if (roi["r"] - roi["x"] > 0) and (roi["t"] - roi["y"] > 0): 847 options["roi"] = bboxToTopLeft(int(nuke.value(nodeToFlipbook.name()+".actual_format.height")), roi) 848 849 850 return options851853 flipbookToRun = flipbooking.gFlipbookFactory.getApplication(self._flipbookEnum.value()) 854 if (flipbookToRun): 855 if not os.access(flipbookToRun.path(), os.X_OK): 856 raise RuntimeError("%s cannot be executed (%s)." % (flipbookToRun.name(), flipbookToRun.path(),) ) 857 858 nodeToFlipbook = None 859 rootProxyMode = nuke.root().proxy() 860 try: 861 # Need this to prevent Bug 5295 862 nuke.Undo().disable() 863 nuke.root().setProxy(self._useProxy.value()) 864 865 if self._cleanup.value(): 866 self._deleteTemporaries() 867 868 calledOnNode = self._node 869 if self._node.Class() == "Viewer": 870 self._node = self._node.input(int(self._node.knob("input_number").value())) 871 872 runFlipbook = False 873 # In many cases we need to create a temporary node and render that. 874 if not self._requireIntermediateNode( self._node ): 875 nodeToFlipbook = self._node 876 runFlipbook = True 877 else: 878 nodeToFlipbook = self._createIntermediateNode() 879 runFlipbook = not self._bgRender.value() 880 881 if nodeToFlipbook and runFlipbook: 882 # get default options and extra options needed by the selected 883 # Flipbook application 884 options = self._getOptions( nodeToFlipbook ) 885 extraOptions = flipbookToRun.getExtraOptions( self, nodeToFlipbook ) 886 options.update( extraOptions ) 887 888 flipbookToRun.runFromNode(nodeToFlipbook, 889 nuke.FrameRanges(self._frameRange.value().split(',')), 890 self._selectedViews(), options ) 891 892 finally: 893 if self._node != nodeToFlipbook: 894 nuke.delete(nodeToFlipbook) 895 nuke.root().setProxy(rootProxyMode) 896 nuke.Undo().enable() 897 else: 898 raise RuntimeError("No flipbook called " + self._flipbookEnum.value() + " found. Was it deregistered while the dialog was open?")903 906987908 909 # init super 910 FlipbookDialog.__init__(self, dialogState, groupContext, node, True) 911 912 self._bgRender.setVisible(False) 913 self._useProxy.setVisible(False) 914 self._continueOnError.setVisible(False) 915 916 self._viewerForSettings.setVisible(False) 917 self._defaultValues.setVisible(False) 918 919 self._useRoi.setVisible(False) 920 self._roi.setVisible(False) 921 922 self._channels.setVisible(False) 923 self._luts.setVisible(False) 924 925 self._audioSource.setVisible(False) 926 self._burnInLUT.setVisible(False) 927 928 try: 929 ## this may not exist, just ignore if not present 930 self._viewSelection.setVisible(False) 931 except: 932 pass 933 934 customWriteActive = node['file'].getValue() != self._getIntermediatePath() and node['file'].getValue() != '' 935 self._customWrite = nuke.Boolean_Knob( 'custom', 'Customise write path' ) 936 self._customWrite.setValue( customWriteActive ) 937 self.addKnob( self._customWrite ) 938 939 self._noFlipbook = nuke.Boolean_Knob( 'write', 'No flipbook' ) 940 self._noFlipbook.setFlag( nuke.STARTLINE ) 941 self._noFlipbook.setVisible( customWriteActive ) 942 self._noFlipbook.setValue( self._state.get( self._noFlipbook, False ) ) 943 self.addKnob( self._noFlipbook ) 944 945 self._file = nuke.File_Knob( 'file', 'Write path' ) 946 defaultPath = self._node['file'].value() 947 if defaultPath == self._getIntermediatePath(): 948 defaultPath = '' 949 self._file.setValue ( self._state.get(self._file, defaultPath ) ) 950 self._file.setVisible( customWriteActive ) 951 952 self.addKnob( self._file )953955 try: 956 FlipbookDialog.knobChanged(self, knob) 957 if (knob == self._customWrite): 958 self._noFlipbook.setVisible( self._customWrite.value() ) 959 self._file.setVisible( self._customWrite.value() ) 960 if ( not self._customWrite.value() ): 961 self._node['file'].setValue( self._getIntermediatePath() ) 962 elif( knob == self._noFlipbook ): 963 self._flipbookEnum.setEnabled( not self._noFlipbook.value() ) 964 except: 965 pass966 969971 """ Return an instance of a CaptureViewer class, which when executed captures the viewer. 972 """ 973 flipbook = flipbooking.gFlipbookFactory.getApplication(self._flipbookEnum.value()) 974 if flipbook and not os.access(flipbook.path(), os.X_OK): 975 raise RuntimeError("%s cannot be executed (%s)." % (flipbook.name(), flipbook.path(),) ) 976 977 # build up the args 978 frameRange = self._frameRange.value() 979 viewer = self._node 980 selectedViews = self._selectedViews() 981 defaultWritePath = self._getIntermediatePath() 982 customWritePath = self._file.value() if self._customWrite.value() else "" 983 doFlipbook = not self._noFlipbook.value() 984 doCleanup = self._cleanup.value() 985 986 return captureViewer.CaptureViewer(flipbook, frameRange, viewer, selectedViews, defaultWritePath, customWritePath, doFlipbook, doCleanup)989 """Shows the dialog if dialog.showModalDialog() == True""" 990 if (dialog.showModalDialog() == True): 991 dialog.run()992 994 """Present a dialog that executes the given list of nodes.""" 995 groupContext = nuke.root() 996 d = ExecuteDialog(_gRenderDialogState, groupContext, nodesToExecute, exceptOnError) 997 _showDialog(d) 998 1000 """Present a dialog that renders the given list of nodes.""" 1001 groupContext = nuke.root() 1002 d = RenderDialog(_gRenderDialogState, groupContext, nodesToRender, exceptOnError) 1003 _showDialog(d) 10041006 """Returns the flipbook dialog object created when flipbooking node""" 1007 if node is None: 1008 raise RuntimeError("Can't launch flipbook, require a node."); 1009 if node.Class() == "Viewer" and node.inputs() == 0: 1010 raise RuntimeError("Can't launch flipbook, there is nothing connected to the viewed input."); 1011 1012 if not (nuke.canCreateNode("Write")): 1013 nuke.message("Flipbooking is not permitted in Nuke Assist") 1014 return 1015 1016 groupContext = nuke.root() 1017 1018 e = FlipbookDialog(_gFlipbookDialogState, groupContext, node, takeNodeSettings) 1019 return e10201022 """Present a dialog that flipbooks the given node.""" 1023 e = _getFlipbookDialog( node, takeNodeSettings ) 1024 _showDialog(e)1025 1026 # because the capture button could have been triggered via a progress bar in update_handles 1027 # we defer the capture run until the main event loop is pumped103210361034 ## only runs the dialog capture function when we are outside update_handles 1035 utils.executeInMainThreadWithResult( self.captureViewer, )1038 if node is None: 1039 raise RuntimeError("Can't launch flipbook, requires a viewer node."); 1040 if node.Class() != "Viewer" and node.inputs() == 0: 1041 raise RuntimeError("Can't launch flipbook, this is not a viewer node."); 1042 1043 if not (nuke.canCreateNode("Write")): 1044 nuke.message("Viewer capture is not permitted in Nuke Assist") 1045 return 1046 1047 groupContext = nuke.root() 1048 e = ViewerCaptureDialog(_gViewerCaptureDialogState, groupContext, node) 1049 if (e.showModalDialog() == True): 1050 # Bug 38516 - Be careful about what gets passed to the ViewerCaptureDialogThread, since anything 1051 # created here will be destroyed in a different thread. This can cause problems, such as crashes, 1052 # if a Qt widget gets passed. 1053 captureViewer = e.captureViewer() 1054 thread = ViewerCaptureDialogThread(captureViewer) 1055 thread.start()10561058 """Present a dialog that flipbooks the currently selected node.""" 1059 try: 1060 showFlipbookDialog(nuke.selectedNode()) 1061 except ValueError, ve: 1062 raise RuntimeError("Can't launch flipbook, %s." % (ve.args[0]))10631065 """Convert the roi passed from a origin at the bottom left to the top left. 1066 Also replaces the r and t keys with w and h keys. 1067 @param height: the height used to determine the top. 1068 @param roi: the roi with a bottom left origin, must have x, y, r & t keys. 1069 @result dict with x, y, w & h keys""" 1070 topLeftRoi = { 1071 "x": roi["x"], 1072 "y": height - roi["y"] - (roi["t"] - roi["y"]), 1073 "w": roi["r"] - roi["x"], 1074 "h": roi["t"] - roi["y"] } 1075 return topLeftRoi10761078 """ 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.""" 1079 _gRenderDialogState.saveValue(name, value)10801082 """ 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.""" 1083 _gFlipbookDialogState.saveValue(name, value)1084
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Apr 23 23:13:22 2016 | http://epydoc.sourceforge.net |