def createReadNode(infos): log("createReadNode '%s'" % infos) global zoomTargetNode, zoomTimer if (infos): nuke.Undo().begin("Create Read Nodes From RV") try: nukescripts.misc.clear_selection_recursive() if (rvmon): rvmon.restoreBegin() last = None for i in infos: last = nuke.nodes.Read(file=i[0], first=i[1], last=i[2], name=i[3]) last['selected'].setValue(True) # zoomTargetNode = last # nuke.show(zoomTargetNode) # zoomTimer = threading.Timer (0.1, zoomToNode) # zoomTimer.start() if (rvmon): rvmon.zoomTargetNode = last.name() rvmon.restoreComplete() except Exception, msg: nuke.message("Read node creation failed:\n%s" % (msg, )) nuke.Undo().end()
def run(self): flipbookToRun = flipbooking.gFlipbookFactory.getApplication( self._flipbookEnum.value()) if (flipbookToRun): if not os.access(flipbookToRun.path(), os.X_OK): raise RuntimeError("%s cannot be executed (%s)." % ( flipbookToRun.name(), flipbookToRun.path(), )) nodeToFlipbook = None rootProxyMode = nuke.root().proxy() try: # Need this to prevent Bug 5295 nuke.Undo().disable() nuke.root().setProxy(self._useProxy.value()) if self._cleanup.value(): self._deleteTemporaries() calledOnNode = self._node if self._node.Class() == "Viewer": self._node = self._node.input( int(self._node.knob("input_number").value())) runFlipbook = False # In many cases we need to create a temporary node and render that. if not self._requireIntermediateNode(self._node): nodeToFlipbook = self._node runFlipbook = True else: nodeToFlipbook = self._createIntermediateNode() runFlipbook = not self._bgRender.value() if nodeToFlipbook and runFlipbook: # get default options and extra options needed by the selected # Flipbook application options = self._getOptions(nodeToFlipbook) extraOptions = flipbookToRun.getExtraOptions( self, nodeToFlipbook) options.update(extraOptions) flipbookToRun.runFromNode( nodeToFlipbook, nuke.FrameRanges(self._frameRange.value().split(',')), self._selectedViews(), options) finally: if self._node != nodeToFlipbook: nuke.delete(nodeToFlipbook) nuke.root().setProxy(rootProxyMode) nuke.Undo().enable() else: raise RuntimeError( "No flipbook called " + self._flipbookEnum.value() + " found. Was it deregistered while the dialog was open?")
def replace_knobs(self): ''' Replace knob_matches with replace string ''' if not self.knob_matches or not self.replace_text.text(): return nuke.Undo().begin() for knob, val in self.knob_matches.items(): knob.setValue(val[1]) nuke.Undo().end() self.find_knobs()
def mouseReleaseEvent(self,event): ''' Execute the buttons' self.function (str) ''' if self.selected: nuke.Undo().name(self.text()) nuke.Undo().begin() self.invokeButton() nuke.Undo().end() return True
def mouseReleaseEvent(self, event): ''' Execute the buttons' self.function (str) ''' if self.selected: nuke.Undo().name(self.text()) nuke.Undo().begin() try: exec self.function except: pass nuke.Undo().end() return True
def scale(axis, scale, pivot='max'): # Scale selected nodes by factor of xscale, yscale # param: axis - one of 0 or 1 - x or y scale # param: float scale - factor to scale. 1 will do nothing. 2 will scale up 1 grid unit. # param: str pivot - where to scale from. One of min | max | center pivots = ['min', 'max', 'center'] if pivot not in pivots: return nodes = nuke.selectedNodes() if len(nodes) < 2: return positions = {n: get_pos(n) for n in nodes} sort = sorted(positions.items(), key=lambda (k, v): v[axis]) minpos = sort[0][1][axis] maxpos = sort[-1][1][axis] if pivot == 'max': pivot_pos = maxpos elif pivot == 'min': pivot_pos = minpos elif pivot == 'center': pivot_pos = (minpos - maxpos) / 2 + minpos nuke.Undo().begin() for node, pos in positions.iteritems(): if axis: new_pos = (pos[1] - pivot_pos) * scale + pivot_pos set_pos(node, pos[0], new_pos) if node.Class() == 'BackdropNode': bdpos = ((pos[1] + node['bdheight'].getValue()) - pivot_pos) * scale + pivot_pos - node.ypos() print pos[1] print new_pos print bdpos if scale > 0: node['bdheight'].setValue(bdpos) else: node.setXYpos(pos[0], int(new_pos - abs(bdpos))) else: new_pos = (pos[0] - pivot_pos) * scale + pivot_pos set_pos(node, new_pos, pos[1]) if node.Class() == 'BackdropNode': bdpos = ((pos[0] + node['bdwidth'].getValue()) - pivot_pos) * scale + pivot_pos - node.xpos() if scale > 0: node['bdwidth'].setValue(bdpos) else: node.setXYpos(int(new_pos - abs(bdpos)), int(node.ypos())) nuke.Undo().end()
def run(self): frame_ranges = nuke.FrameRanges( self._frameRange.value().split(',')) views = self._selectedViews() try: nuke.Undo().disable() if (self.isBackgrounded()): nuke.executeBackgroundNuke( nuke.EXE_PATH, self._nodeSelection, frame_ranges, views, self._getBackgroundLimits(), continueOnError=self._continueOnError.value()) elif self._termRender.value(): terminal_render(self._nodeSelection, frame_ranges, views, self._numInstances.value(), self._numThreads.value(), self._maxMem.value()) else: nuke.executeMultiple( self._nodeSelection, frame_ranges, views, continueOnError=self._continueOnError.value()) except RuntimeError, e: if self._exceptOnError or e.args[0][ 0: 9] != "Cancelled": # TO DO: change this to an exception type raise
def run(self): frame_ranges = nuke.FrameRanges(self._frameRange.value().split(',')) views = self._selectedViews() rootProxyMode = nuke.root().proxy() try: nuke.Undo().disable() nuke.root().setProxy(self._useProxy.value()) if (self.isBackgrounded()): print frame_ranges make_out(self._nodeSelection) nuke.executeBackgroundNuke( nuke.EXE_PATH, self._nodeSelection, frame_ranges, views, self._getBackgroundLimits(), continueOnError=self._continueOnError.value()) else: if (self.skipExisting()): nuke.addBeforeFrameRender(skippy, nodeClass='Write') else: nuke.removeBeforeFrameRender(skippy, nodeClass='Write') make_out(self._nodeSelection) nuke.executeMultiple( self._nodeSelection, frame_ranges, views, continueOnError=self._continueOnError.value()) except RuntimeError, e: if self._exceptOnError or e.args[0][ 0: 9] != "Cancelled": # TO DO: change this to an exception type raise
def run(self): if self.isTimelineWrite() and self._frameServerRender.value(): from hiero.ui.nuke_bridge.nukestudio import scriptSaveAndReRender scriptSaveAndReRender() return frame_ranges = nuke.FrameRanges(self._frameRange.value().split(',')) views = self._selectedViews() rootProxyMode = nuke.root().proxy() try: nuke.Undo().disable() nuke.root().setProxy(self._useProxy.value()) if (self.isBackgrounded()): nuke.executeBackgroundNuke( nuke.EXE_PATH, self._nodeSelection, frame_ranges, views, self._getBackgroundLimits(), continueOnError=self._continueOnError.value()) else: nuke.executeMultiple( self._nodeSelection, frame_ranges, views, continueOnError=self._continueOnError.value()) except RuntimeError, e: if self._exceptOnError or e.args[0][ 0: 9] != "Cancelled": # TO DO: change this to an exception type raise
def renderTmpFiles(self, node, seqDir, start, end, incr): log("renderTmpFiles %s %s %s %s %s" % (node.name(), seqDir, start, end, incr)) """ if (start == end) : targetPath = seqDir + "/" + node.name() + (".%d." % start) + self.outputFileFormat else : targetPath = seqDir + "/" + node.name() + ".#." + self.outputFileFormat """ targetPath = seqDir + "/" + node.name() + ".#." + self.outputFileFormat log("targetPath %s" % targetPath) # XXX handle proxy renders fieldname = "file" """ if self.proxy: fieldname = "proxy" """ nuke.Undo().disable() writeNode = nuke.nodes.Write(tile_color='0xff000000') writeNode[fieldname].setValue(targetPath) writeNode.setInput(0, node) ret = True try: nuke.executeMultiple((writeNode, ), ([start, end, incr], )) except Exception, msg: nuke.message("Render failed:\n%s" % (msg, )) ret = False
def run(self): frame_ranges = nuke.FrameRanges(self._frameRange.value().split(',')) views = self._selectedViews() rootProxyMode = nuke.root().proxy() try: nuke.Undo().disable() nuke.root().setProxy(self._useProxy.value()) nuke.executeMultiple(self._nodeSelection, frame_ranges, views, continueOnError=self._continueOnError.value()) except RuntimeError, e: if self._exceptOnError or e.args[0][ 0: 9] != "Cancelled": # TO DO: change this to an exception type raise
def cache_particles_panel(particleCacheNode): particleCacheNode.knobs()["particle_cache_render_in_progress"].setValue( True) try: nuke.Undo().disable() rootNode = nuke.root() firstFrame = rootNode['first_frame'].getValue() lastFrame = rootNode['last_frame'].getValue() # Extra frames added for motion blur padding = int(particleCacheNode['particle_cache_padding'].getValue()) nuke.executeMultiple( (particleCacheNode, ), ([firstFrame - padding, lastFrame + padding, 1], )) except RuntimeError, e: nuke.tprint(e) if e.args[0][ 0:9] != "Cancelled": # TO DO: change this to an exception type raise
def distributeEvenly(self, axis): ''' Equalize the amount of space between selected nodes. ''' selection = self.getSelection() allPositionsDict = {} for node in selection: position = float( node.knob(axis + 'pos').value() + self.getScreenSize(node, axis)) if position in allPositionsDict.keys(): allPositionsDict[position].append(node) else: allPositionsDict[position] = [node] allPositions = sorted(allPositionsDict.keys()) amount = len(allPositions) if amount < 3: return minPos = allPositions[0] maxPos = allPositions[-1] stepSize = (maxPos - minPos) / (amount - 1) self.undo = nuke.Undo() self.undo.begin("Distribute evenly") for index, i in enumerate(allPositions): newPos = minPos + index * stepSize for node in allPositionsDict[i]: node.knob(axis + 'pos').setValue(newPos - self.getScreenSize(node, axis)) self.undo.end() self.undo = None
def restoreCheckpoint(nukeScript, nodeName, date): log("restoreCheckpoint %s %s %s" % (nukeScript, nodeName, date)) # We ask on rv side now, since otherwise dialog can come up behind rv. # # ans = nuke.ask ("Restore checkpoint: %s, %s ?" % (nodeName, date)) # log (" ans %s" % ans) log(" reading checkpoint script") nuke.Undo().begin("Restore %s, %s" % (nodeName, date)) try: nukescripts.misc.clear_selection_recursive() try: v = nuke.activeViewer().node().name() except: v = None if (rvmon): rvmon.restoreBegin() nodes = nuke.root().nodes() for n in nodes: #log (" deleting %s %s %s" % (n.name(), type(n).__name__, n.Class())) nuke.delete(n) nuke.scriptReadFile(nukeScript) if (v): n = nuke.toNode(v) if (n): nuke.show(n) if (rvmon): rvmon.restoreComplete() log(" checkpoint restore complete") except Exception, msg: nuke.message("Checkpoint restore failed:\n%s" % (msg, ))
rootProxyMode = nuke.root().proxy() try: nuke.Undo().disable() nuke.root().setProxy(self._useProxy.value()) nuke.executeMultiple(self._nodeSelection, frame_ranges, views, continueOnError=self._continueOnError.value()) except RuntimeError, e: if self._exceptOnError or e.args[0][ 0: 9] != "Cancelled": # TO DO: change this to an exception type raise finally: nuke.root().setProxy(rootProxyMode) nuke.Undo().enable() class RenderDialog(ExecuteDialog): def _titleString(self): return "Render" def _idString(self): return "uk.co.thefoundry.RenderDialog" def __init__(self, dialogState, groupContext, nodeSelection=[], exceptOnError=True): ExecuteDialog.__init__(self, dialogState, groupContext, nodeSelection,
class RvMonitor: class LockedFifo: def __init__(self): self.first = () self.lock = threading.Lock() def append(self, data): self.lock.acquire() node = [data, ()] if self.first: self.last[1] = node else: self.first = node self.last = node self.lock.release() def pop(self): # # don't lock unless we have to # node = self.first if (node == ()): return () self.lock.acquire() node = self.first if (node != ()): self.first = node[1] ret = node[0] else: ret = () self.lock.release() return ret def clear(self): while (self.pop() != ()): pass class LockedFlag: def __init__(self): self.lock = threading.Lock() self.value = False def set(self): self.lock.acquire() self.value = True self.lock.release() def unset(self): self.lock.acquire() self.value = False self.lock.release() def isSet(self): self.lock.acquire() ret = self.value self.lock.release() return ret def __init__(self): self.rvc = rvNetwork.RvCommunicator("Nuke") self.port = 45128 self.initialized = False self.running = False self.selectedNode = None self.commands = self.LockedFifo() self.crashFlag = self.LockedFlag() self.sessionDir = "" self.syncSelection = False self.syncFrameChange = False self.syncReadChanges = False self.rvExecPath = "" self.updateFromPrefs() self.portFile = self.sessionDir + "/rv" + str(os.getpid()) self.zoomTargetNode = None log("adding callbacks") # nuke.addUpdateUI (self.updateUI) nuke.addKnobChanged(self.knobChanged) nuke.addOnCreate(self.onCreate) nuke.addOnDestroy(self.onDestroy) nuke.addOnScriptClose(self.onScriptClose) nuke.addOnScriptLoad(self.onScriptLoad) def __del__(self): # Squirrel away a ref to the Popen object because it has a bug that # will print an error message when we delete it if we do it at this # point. This prevents it from getting garbage collected until later. global rvmonProc rvmonProc = self.rvProc def restoreBegin(self): log("restoreBegin") nuke.removeKnobChanged(self.knobChanged) nuke.removeOnCreate(self.onCreate) nuke.removeOnDestroy(self.onDestroy) def restoreComplete(self): log("restoreComplete") nuke.addKnobChanged(self.knobChanged) nuke.addOnCreate(self.onCreate) nuke.addOnDestroy(self.onDestroy) self.allSyncUpdate() def updateFromPrefs(self): log("rvMonitor updateFromPrefs") rvPrefs = RvPreferences() self.rvExecPath = rvPrefs.prefs["rvExecPath"] self.extraArgs = rvPrefs.prefs["extraArgs"] rvSettings = RvSettings(rvPrefs.prefs["sessionDirBase"]) self.sessionDir = rvSettings.settings["sessionDir"] log(" sessionDir '%s'" % self.sessionDir) self.syncSelection = rvSettings.settings["syncSelection"] self.syncFrameChange = rvSettings.settings["syncFrameChange"] self.syncReadChanges = rvSettings.settings["syncReadChanges"] self.outputFileFormat = rvSettings.settings["outputFileFormat"] def onScriptClose(self): log("onScriptClose") nuke.removeOnDestroy(self.onDestroy) nuke.removeKnobChanged(self.knobChanged) if (self.rvc.connected): log(" disconnecting from rv") #self.rvc.disconnect() self.running = False log(" sleeping after disconnect") time.sleep(0.3) def onScriptLoad(self): log("onScriptLoad") """ XXX On script load want to disconnect and shutdown rv, since incoming script may have different sessionDir, etc. """ def onCreate(self): log("onCreate %s" % nuke.thisNode().name()) node = nuke.thisNode() if (not node or type(node).__name__ != "Node"): return if (self.syncReadChanges and (str(node.Class()) == "Read" or str(node.Class()) == "Write")): self.queueCommand("self.viewReadsInRv([\"%s\"])" % node.name()) def onDestroy(self): log("onDestroy") node = nuke.thisNode() if (node and type(node).__name__ == "Node"): log("destroying node of class '%s'" % str(node.Class())) if (self.syncReadChanges and (str(node.Class()) == "Read" or str(node.Class()) == "Write")): self.queueCommand("self.removeObsoleteReads()") def updateAndSyncSelection(self, force=False): nodes = nuke.selectedNodes() if (len(nodes) == 1): node = nodes[0] if (node.Class() == "Viewer"): node = node.input(int(nuke.knob(node.name() + ".input_number"))) if (not node): return log("updateAndSyncSelection old %s new %s" % (self.selectedNode, node.name())) if (force or node.name() != self.selectedNode): self.selectedNode = node.name() self.queueCommand("self.selectCurrentByNodeName()") self.queueCommand("self.changeFrame(%d)" % nuke.frame()) else: self.selectedNode = None def knobChanged(self): nname = "" kname = "" if (doDebug): if (nuke.thisNode()): try: log("type '%s'" % type(nuke.thisNode()).__name__) log("class '%s'" % nuke.thisNode().Class()) nname = nuke.thisNode().name() except: pass if (nuke.thisKnob()): kname = nuke.thisKnob().name() log("knobChanged node '%s' knob '%s' val '%s'\n" % (nname, kname, str(nuke.thisKnob().value()))) node = nuke.thisNode() knob = nuke.thisKnob() if (not node or not knob): return if (type(node).__name__ != "Node" and type(node).__name__ != "Root" and type(node).__name__ != "Viewer"): return # # Track selection changes # if (self.syncSelection and knob.name() == "selected" and self.running): log("selection changed") self.updateAndSyncSelection() # # Track frame changes # elif (self.syncFrameChange and str(node.Class()) == "Viewer" and knob.name() == "frame" and self.running): log("frame change") self.queueCommand("self.changeFrame(%d)" % knob.value()) # # Track read/write changes # elif (self.syncReadChanges and (str(node.Class()) == "Read" or str(node.Class()) == "Write") and self.running and (knob.name() == "colorspace" or knob.name() == "first" or knob.name() == "last" or knob.name() == "label" or knob.name() == "frame_mode" or knob.name() == "frame" or knob.name() == "file")): log("read/write knob changed") self.queueCommand("self.viewReadsInRv([\"%s\"])" % node.name()) # # Track read/write name changes # elif (self.syncReadChanges and (str(node.Class()) == "Read" or str(node.Class()) == "Write") and self.running and (knob.name() == "name")): log("read/write name changed") self.queueCommand("self.removeObsoleteReads()") self.queueCommand("self.viewReadsInRv([\"%s\"])" % node.name()) # # Track settings changes # elif (str(node.Class()) == "Root" and re.match("^rvSettings_.*", knob.name())): log("setting changed") self.updateFromPrefs() if (self.running): if (knob.name() == "rvSettings_sessionDir"): log("sessionDir setting changed: '%s'" % self.sessionDir) log("restarting rv") self.running = False while (self.thread.isAlive()): time.sleep(0.1) rvmon.initializeRvSide() else: self.allSyncUpdate() # # Implement delayed "frame on node" # elif (self.zoomTargetNode and knob.name() == "ypos"): self.zoomToNode() def changeFrame(self, f): """ """ self.ensureConnection() self.rvc.remoteEval(""" require commands; commands.setFrame (%d); commands.redraw(); """ % f) def selectCurrentByNodeName(self): """ """ self.ensureConnection() self.rvc.remoteEval(""" require rvnuke_mode; rvnuke_mode.theMode().selectCurrentByNodeName ("%s"); """ % self.selectedNode) def spawn(self): log("spawn") self.ensureConnection() if (not self.rvc.connected): self.running = False log("connect in spawn failed") self.initialized = False return while (self.running): if (not self.rvc.connected): log("not connected in spawn loop") self.running = False self.crashFlag.set() break # # Send messages to RV # # log ("send messages to RV") try: while (1): cmd = self.commands.pop() if (cmd == ()): break log("running queued command '%s'" % cmd) self.eval(cmd) except: log("can't send messages to RV, shutting down.") try: self.rvc.disconnect() except: pass self.running = False self.crashFlag.set() log("disconnected, crashed = True") # log ("done sending messages to RV") # # Wait for messages from RV # try: # log ("selecting") select.select([self.rvc.sock], [], [], 0.1) # log ("selecting done") except: log("rvc select/wait error: %s" % sys.exc_info()[1]) # # Handle messages from RV # try: # log ("process rv events") self.rvc.processEvents() except: log("can't process messages from the RV side, shutting down.") try: self.rvc.disconnect() except: pass self.running = False self.crashFlag.set() log("disconnected, crashed = True") break # # Clear any queued commands # self.commands.clear() try: log("polling rv process") self.rvProc.poll() if (not self.rvProc.returncode and self.rvc.connected): log("terminating rv process") self.rvc.remoteEval(""" require rvnuke_mode; rvnuke_mode.theMode().exit(); """) self.rvc.connected = False # this stuff doesn't work in python 2.5.1 (Nuke 6.1) # self.rvProc.terminate() # self.rvProc.kill() # self.rvProc.wait() # log ("returncode %s" % self.rvProc.returncode)) except: log("error terminating rv: %s\n" % sys.exc_info()[1]) self.initialized = False def ensureConnection(self, force=False): if (self.rvc.connected): return log("ensureConnection crashed %d force %s" % (self.crashFlag.isSet(), force)) """ if (self.crashFlag.isSet() and not force) : log ("prev crashed and not force, so returning") return """ self.crashFlag.unset() args = [ "-flags", "ModeManagerPreload=rvnuke_mode", "-network", "-networkPort", str(self.port), "-flags", "rvnukePortFile=%s" % self.portFile ] usingBuild = False if (self.rvExecPath != ""): cmd = [self.rvExecPath] else: try: src = os.environ["SRC_ROOT"] usingBuild = True except: pass cmd = [src + "/build/run", "--p", src + "/bin/nsapps/RV64"] if (not usingBuild and not os.path.exists(self.rvExecPath)): nuke.executeInMainThread(nuke.message, ( "Sorry '%s' does not exist, please use the 'RV Preferences' menu item or toolbar button to designate the RV executable." % self.rvExecPath, )) return fullcmd = cmd + self.extraArgs.split() + args log("starting cmd %s" % str(fullcmd)) try: os.remove(self.portFile) except: pass try: self.rvProc = subprocess.Popen(fullcmd) self.rvProc.poll() if (self.rvProc.returncode): log("ERROR: failed to start RV '%s' return: %d" % (cmd[0], self.rvProc.returncode)) sys.stderr.write( "ERROR: failed to start RV '%s' return: %d\n" % (cmd[0], self.rvProc.returncode)) return except: log("ERROR: failed to start RV '%s'" % cmd[0]) sys.stderr.write("ERROR: failed to start RV '%s'\n" % cmd[0]) return self.port = 0 for i in range(300): if (os.path.exists(self.portFile)): f = open(self.portFile) self.port = int(f.read()) f.close() break else: time.sleep(0.1) log("got port: %d" % self.port) if (self.port == 0): log("ERROR: failed to connect to running RV") sys.stderr.write("ERROR: failed to connect to running RV\n") return try: os.remove(self.portFile) except: pass if (self.port != 0): log("connecting") self.rvc.connect("127.0.0.1", self.port) if (not self.rvc.connected): log("connect failed") self.rvc.handlers["remote-python-eval"] = pythonHandler def queueCommand(self, cmd): log("queueCommand '%s'" % cmd) self.commands.append(cmd) def setSessionDir(self): # XXX check running ? self.rvc.remoteEval(""" require rvnuke_mode; rvnuke_mode.theMode().initFromNuke ("%s", %d, "%s"); """ % (self.sessionDir, protocolVersion, nuke.env['ExecutablePath'])) def allSyncUpdate(self): if (not self.running): return if (self.syncReadChanges): readNodes = [ n.name() for n in nuke.allNodes() if (type(n).__name__ == "Node" and ( n.Class() == "Read" or n.Class() == "Write")) ] if (readNodes): self.queueCommand("self.viewReadsInRv(%s)" % str(readNodes)) self.queueCommand("self.removeObsoleteReads()") if (self.syncSelection): self.updateAndSyncSelection(True) if (self.syncFrameChange): self.queueCommand("self.changeFrame(%d)" % nuke.frame()) def prepForRender(self, node, renderType): log("prepForRender %s %s" % (node.name(), renderType)) baseDir = self.sessionDir + "/" + renderType dateString = time.strftime("%b %d %H:%M:%S") if (renderType == "checkpoint"): dateStringForName = "_" + re.sub(" ", "_", re.sub(":", "_", dateString)) else: dateStringForName = "" nodeDir = baseDir + "/" + node.name() + dateStringForName if (not os.path.exists(nodeDir)): log("making directory '%s'" % nodeDir) os.makedirs(nodeDir) nuke.scriptSave(nodeDir + "/" + renderType + ".nk") return dateString def renderTmpFiles(self, node, seqDir, start, end, incr): log("renderTmpFiles %s %s %s %s %s" % (node.name(), seqDir, start, end, incr)) """ if (start == end) : targetPath = seqDir + "/" + node.name() + (".%d." % start) + self.outputFileFormat else : targetPath = seqDir + "/" + node.name() + ".#." + self.outputFileFormat """ targetPath = seqDir + "/" + node.name() + ".#." + self.outputFileFormat log("targetPath %s" % targetPath) # XXX handle proxy renders fieldname = "file" """ if self.proxy: fieldname = "proxy" """ nuke.Undo().disable() writeNode = nuke.nodes.Write(tile_color='0xff000000') writeNode[fieldname].setValue(targetPath) writeNode.setInput(0, node) ret = True try: nuke.executeMultiple((writeNode, ), ([start, end, incr], )) except Exception, msg: nuke.message("Render failed:\n%s" % (msg, )) ret = False log("deleting writeNode") nuke.delete(writeNode) nuke.Undo().enable() return ret
nuke.scriptReadFile(nukeScript) if (v): n = nuke.toNode(v) if (n): nuke.show(n) if (rvmon): rvmon.restoreComplete() log(" checkpoint restore complete") except Exception, msg: nuke.message("Checkpoint restore failed:\n%s" % (msg, )) nuke.Undo().end() log(" done") def killRV(): if (rvmon): # if (rvmon.rvc.connected) : # rvmon.rvc.disconnect() rvmon.running = False def testMenu(): log("node %s" % nuke.thisNode().name()) log("knob %s" % nuke.thisKnob().name())
def doFixGimbalFlip(): p = doFixGimbalFlipPanel(nuke.selectedNode()) if p.showModalDialog(): #user did not hit cancel button undo = nuke.Undo() undo.begin("Fix Gimbal Flip") tErrorPercent = p.tErrorPercent.value() if (tErrorPercent > 100): tErrorPercent = 100 if (tErrorPercent < 0.000001): tErrorPercent = 0.000001 tFrameRange = nuke.FrameRange(p.tFrameRange.value()) tFirstFrame = tFrameRange.first() tLastFrame = tFrameRange.last() knob_names = nuke.animations( ) # Returns the animations names under this knob i = getKnobIndex( ) #find out if user only clicked on a single knob index, or the entire knob print "knob index: " + str(i) j = 0 #index for knob #print " knob_names " + str( knob_names) for knob_name_with_suffix in knob_names: #print "knob_name_with_suffix " + str(knob_name_with_suffix) if (i > -1): j = i #print "for knob_name_with_suffix in knob_names:" knob_name = getKnobName(knob_name_with_suffix) # so that we can get at the knob object and do... k = nuke.thisNode()[knob_name] print knob_name + "." + str(j) if (k.isAnimated(j)): tOriginalCurve = k.animation(j) tKeys = tOriginalCurve.keys() #tOrigFirstFrame = tKeys[0].x #tOrigLastFrame = tKeys[len(tKeys)-1].x tKeysLen = len(tKeys) tLastValue = tKeys[0].y #print "tErrorThreshold " + str(tErrorThreshold) n = nuke.selectedNode() for f in range(0, tKeysLen): tFrame = tKeys[f].x if (tFrame >= tFirstFrame) and (tFrame <= tLastFrame): tValue = tKeys[f].y #print "tValue " + str(tValue) tLastDiff = tLastValue - tValue tPredictedValue = tValue + tLastDiff tDiff = tPredictedValue - tValue #print str(tFrame) + " tLastValue " + str(tLastValue) + " tValue " + str(tValue) + " tLastDiff " + str(tLastDiff) #print str(tFrame) + " tPredictedValue " + str(tPredictedValue) + " tValue " + str(tValue) + " tDiff " + str(tDiff) if (tDiff > (180 - tErrorPercent)) | (tDiff < -(180 - tErrorPercent)): print "gimbal flip at " + str(tFrame) print str(tFrame) + " tPredictedValue " + str( tPredictedValue) + " tValue " + str( tValue) + " tDiff " + str(tDiff) #print "fixing keys " + str(i) + " to " + str(tKeysLen) print "fixing frames " + str( tKeys[f].x) + " to " + str( tKeys[tKeysLen - 1].x) for k in range(f, tKeysLen): #k.animation(j) tFixFrame = tKeys[k].x if (tFixFrame >= tFirstFrame) and (tFixFrame <= tLastFrame): tOldValue = tKeys[k].y if (tDiff > 0): tNewValue = tOldValue + 180 else: tNewValue = tOldValue - 180 #print str(tFixFrame) + " tOldValue " + str(tOldValue) + " tNewValue " + str(tNewValue) tOriginalCurve.setKey(tFixFrame, tNewValue) if (tDiff > 0): tLastValue = tValue + 180 else: tLastValue = tValue - 180 else: tLastValue = tValue else: print "No animation found in " + knob_name + " index " + str(j) #break the loop if we are only running script on single knob index if (i > -1): #print "breaking" break else: j = j + 1 #print "j " + str(j) undo.end()
def align(direction): # Align nodes to the farthest outlier in the specified direction. # param: direction - one of: left | right | up | down nodes = nuke.selectedNodes() if len(nodes) < 2: return horizontally = ['left', 'right'] vertically = ['up', 'down'] if direction in horizontally: align = 0 elif direction in vertically: align = 1 else: print 'Error: invalid direction specified: {0}'.format(direction) return positions = {n: get_pos(n) for n in nodes} sorted_positions = sorted(positions.items(), key=lambda (k, v): v[align]) if direction in ['down', 'right']: sorted_positions.reverse() target = sorted_positions[0] target_pos = target[1] offset = 0 other_axis = abs(1 - align) sorted_other_axis = sorted(positions.items(), key=lambda (k, v): v[other_axis]) nuke.Undo().begin() for i in range(len(sorted_other_axis)): node = sorted_other_axis[i][0] pos = sorted_other_axis[i][1] if i == 0: distance = 0 overlapping = False prev_pos = pos else: prev_pos = sorted_other_axis[i - 1][1] # Compare current node position to previous node position. # If difference is < overlap threshold, nodes are overlapping. distance = abs(pos[other_axis] + grid[other_axis] * offset - prev_pos[other_axis]) overlap_threshold = [ int(node.screenWidth() * 1.1), int(node.screenHeight() * 1.1) ] overlapping = distance < overlap_threshold[other_axis] if overlapping: offset += 1 new_pos = pos new_pos[other_axis] = int(pos[other_axis] + grid[other_axis] * offset) # Set value into sorted_other_axis also so we access the right value on the next loop sorted_other_axis[i][1][other_axis] = new_pos[other_axis] if align: set_pos(node, new_pos[other_axis], target_pos[align]) else: set_pos(node, target_pos[align], new_pos[other_axis]) i += 1 nuke.Undo().end()
def align_nodes(self, direction, node=None): """ If only one node is selected, the node will align to the nearest connected node in the desired direction. Multiple nodes will align to the selected node that's the furthest away in the desired direction Overlapping nodes will be placed next to the overlapped node instead of overlapping it. Takes a node's screensize into account to ensure correct alignment no matter what kind of node it is. Ignores Viewers and child nodes with hidden inputs :param direction: up, down, left or right to place nodes. :param node: optional node to use if not placing based reset selection :return: """ # USER SETTINGS # defines the amount of space that's kept between the nodes. the higher the multiplier, the more space. multiplier_x = 1 multiplier_y = 1 dont_move = False selection = nuke.selectedNodes() if selection: # set the axis based reset direction, and which element of our 2D positions list to use. 0 = x, 1 = y if direction in ['left', 'right']: axis = 'x' index = 0 else: axis = 'y' index = 1 # MULTIPLE NODES # if multiple nodes are selected, all the nodes will align to the node that's the # furthest away in the specified direction if len(selection) > 1: all_pos = [[], []] for node in selection: all_pos[0].append(node.knob('xpos').value() + (self.get_screen_size(node)[0])) all_pos[1].append(node.knob('ypos').value() + (self.get_screen_size(node)[1])) # check whether all selected nodes already share the same position values to prevent overlapping # if so, do nothing if not all_pos[1 - index].count(all_pos[1 - index][0]) == len(all_pos[1 - index]): if direction in ["left", "up"]: destination = min(all_pos[index]) else: destination = max(all_pos[index]) else: dont_move = True # SINGLE NODE # if only one node is selected, the selected node will snap to the nearest # connected node in the specified direction elif len(selection) == 1: current_node = selection[0] # create a list of all the connected nodes input_nodes = current_node.dependencies() output_nodes = current_node.dependent() # remove nodes with hidden inputs and viewer nodes # not every node has a hide input knob (read node for example), so use a "try" in case it doesn't for node in output_nodes: try: if node.knob('hide_input').value() or node.Class() == 'Viewer': output_nodes.remove(node) except: pass if current_node.knob('hide_input'): if current_node.knob('hide_input').value(): input_nodes = [] connected_nodes = input_nodes + output_nodes # create a list for every connected node containing the following # [xpos,ypos,relative xpos, relative ypos, node] positions = [] for node in connected_nodes: x_pos = node.xpos() + self.get_screen_size(node)[0] y_pos = node.ypos() + self.get_screen_size(node)[1] current_node_x_pos = current_node.xpos() + self.get_screen_size(current_node)[0] current_node_y_pos = current_node.ypos() + self.get_screen_size(current_node)[1] positions.append( [x_pos, y_pos, x_pos - current_node_x_pos, y_pos - current_node_y_pos, node] ) # sort the list based on the relative positions sorted_nodes_by_pos = sorted(positions, key=operator.itemgetter(index + 2)) # remove nodes from list to make sure the first item is the node closest to the current_node # use the operator module to switch dynamically between ">=" and "<=" # the positive direction variable is used later to correctly calculate to offset in case # nodes are about to overlap if direction in ['right', 'down']: equation = operator.le positive_direction = -1 else: sorted_nodes_by_pos.reverse() equation = operator.ge positive_direction = 1 try: while equation(sorted_nodes_by_pos[0][index + 2], 0): sorted_nodes_by_pos.pop(0) except: pass # checking whether there are nodes to align to in the desired direction # if there are none, don't move the node if len(sorted_nodes_by_pos) != 0: destination = sorted_nodes_by_pos[0][index] current_position = [current_node_x_pos, current_node_y_pos] destination_position = [current_node_x_pos, current_node_y_pos] destination_position[index] = destination # remove the relative positions from the position list for i in range(len(positions)): positions[i] = [positions[i][:2], positions[i][-1]] # Making sure the nodes won't overlap after being aligned. # If they are about to overlap the node will be placed next to the node it tried to snap to. for i in positions: # calculate the difference between the destination and the position of the node it will align to difference = [(abs(i[0][0] - destination_position[0])) * 1.5, (abs(i[0][1] - destination_position[1])) * 1.5] # define the amount of units a node should offset to not overlap offset_x = 0.75 * (3 * self.get_screen_size(current_node)[0] + self.get_screen_size(i[1])[0]) offset_y = 3 * self.get_screen_size(current_node)[1] + self.get_screen_size(i[1])[1] offsets = [int(offset_x), int(offset_y)] # check in both directions whether the node is about to overlap: if difference[0] < offsets[0] and difference[1] < offsets[1]: multiplier = [multiplier_x, multiplier_y][index] offset = positive_direction * multiplier * offsets[index] # find out whether the nodes are already very close to each other # (even closer than they would be after aligning) # don't move the node if that's the case if abs(offset) < abs(destination - current_position[index]): destination = destination + offset else: dont_move = True # stop looping through the list when a suitable node to align to is found break else: dont_move = True else: dont_move = True # MOVE THE SELECTED NODES nuke.Undo().name('Align Nodes') nuke.Undo().begin() for node in selection: if not dont_move: if axis == 'x': node.setXpos(int(destination - self.get_screen_size(node)[index])) else: node.setYpos(int(destination - self.get_screen_size(node)[index])) if node: # let nuke place node.autoplace()
def breakoutLayers( node, sRGB = True, brkType = BreakoutType.e2D ): if not node: return if node.metadata( 'input/filereader') != 'psd': nuke.message( "Selected node is not PSD file reader" ) return nuke.Undo().begin() blendMap = {} blendMap['norm'] = "normal" blendMap['scrn'] = "screen" blendMap['div '] = "color dodge" blendMap['over'] = "overlay" blendMap['mul '] = "multiply" blendMap['dark'] = "darken" blendMap['idiv'] = "color burn" blendMap['lbrn'] = "linear burn" blendMap['lite'] = "lighten" blendMap['lddg'] = "linear dodge" blendMap['lgCl'] = "lighter color" blendMap['sLit'] = "soft light" blendMap['hLit'] = "hard light" blendMap['lLit'] = "linear light" blendMap['vLit'] = "vivid light" blendMap['pLit'] = "pin light" blendMap['hMix'] = "hard mix" blendMap['diff'] = "difference" blendMap['smud'] = "exclusion" blendMap['fsub'] = "subtract" blendMap['fdiv'] = "divide" blendMap['hue '] = "hue" blendMap['sat '] = "saturation" blendMap['colr'] = "color" blendMap['lum '] = "luminosity" metaData = node.metadata() layers = getLayers(metaData) xspacing = 80 dotXfudge = 34 dotYfudge = 4 backdropXfudge = -( xspacing/2 ) + 10 backdropYfudge = -40 spacing = 70 x = node.xpos() y = node.ypos() curY = y + spacing * 2 if not sRGB: colorSpace = nuke.nodes.Colorspace() colorSpace['channels'].setValue( 'all' ) colorSpace['colorspace_out'].setValue( 'sRGB') colorSpace.setInput(0, node ) colorSpace.setXYpos( x, curY ) inputNode = colorSpace else: inputNode = node curX = x curY = y + spacing * 2 topY = curY lastLayer = None background = None scene = None cards = [] camera = None i = 0 for l in layers: try: if l.attrs['divider/type'] > 0: ## hidden divider or start of group continue except: pass i = i + 1 if i > 100: nuke.message( "Too many layers, stopping at layer 100." ) break; name = l.attrs['nukeName'] curY = topY if i % 2 : tileColor = 2829621248 else: tileColor = 1751668736 backdrop = nuke.nodes.BackdropNode(tile_color = tileColor, note_font_size=18) backdrop.setXYpos( curX + backdropXfudge, curY + backdropYfudge ) curY += spacing/2 dot = nuke.nodes.Dot() dot.setInput( 0, inputNode ) dot.setXYpos( curX + dotXfudge , curY + dotYfudge) curY += spacing inputNode = dot shuffle = nuke.nodes.Shuffle() shuffle['label'].setValue( name ) shuffle['in'].setValue( name ) shuffle['in2'].setValue( 'none' ) shuffle['red'].setValue( 'red' ) shuffle['green'].setValue( 'green' ) shuffle['blue'].setValue( 'blue' ) shuffle['alpha'].setValue( 'alpha' ) ## if no 'alpha' assume alpha of 1 alphaChan = name + ".alpha" if not alphaChan in inputNode.channels(): shuffle['alpha'].setValue( 'white' ) shuffle['black'].setValue( 'red2' ) shuffle['white'].setValue( 'green2' ) shuffle['red2'].setValue( 'blue2' ) shuffle['green2'].setValue( 'alpha2' ) shuffle['out'].setValue( 'rgba' ) shuffle['out2'].setValue( 'none' ) shuffle.setInput(0, inputNode ) shuffle.setXYpos( curX, curY ) curY += spacing crop = nuke.nodes.Crop() crop['box'].setValue( l.attrs['x'], 0 ) crop['box'].setValue( l.attrs['y'], 1 ) crop['box'].setValue( l.attrs['r'], 2 ) crop['box'].setValue( l.attrs['t'], 3 ) crop.setInput(0, shuffle ) crop.setXYpos( curX, curY ) if brkType == BreakoutType.e2_5D: card = nuke.nodes.Card3D() card.setXYpos( curX, curY + spacing ) card.setInput(0, crop ) cards.append( card ) layer = card else: layer = crop curY += spacing * 2 merge = None try: operation = blendMap[ l.attrs['blendmode'] ] except: print "unknown blending mode " + l.attrs['blendmode'] operation = "normal" if brkType != BreakoutType.e3D: if lastLayer: psdMerge = nuke.nodes.PSDMerge() psdMerge['operation'].setValue( operation ) psdMerge.setInput(0, lastLayer ) psdMerge.setInput(1, layer ) psdMerge.setXYpos( curX, curY ) psdMerge['sRGB'].setValue( sRGB ) psdMerge['mix'].setValue( (l.attrs['opacity'] / 255.0) ) try: if ( l.attrs['mask/disable'] != True ): psdMerge['maskChannelInput'].setValue( name + '.mask' ) if ( l.attrs['mask/invert'] == True ) : psdMerge['invert_mask'].setValue( True ) except: pass lastLayer = psdMerge else: dot = nuke.nodes.Dot() dot.setInput( 0, layer ) dot.setXYpos( curX + dotXfudge, curY + dotYfudge ) lastLayer = dot else: premult = nuke.nodes.Premult() premult.setXYpos( curX, curY - spacing ) premult.setInput(0, layer ) card = nuke.nodes.Card2() card.setInput(0, premult ) card.setXYpos( curX, curY ) cards.append ( card ) curY += spacing backdrop['bdwidth'].setValue( xspacing * 2 + backdropXfudge * 2 + 50) backdrop['bdheight'].setValue( ( curY - backdrop.ypos() ) - backdropYfudge - 50 ) backdrop['label'].setValue( l.attrs['name'] ) curY += spacing curX = curX + xspacing * 2 + backdropXfudge * 2 + 50 if brkType != BreakoutType.e2D: if brkType == BreakoutType.e3D: scene = nuke.nodes.Scene() scene.setXYpos( curX, curY + spacing ) scanlineRender = nuke.nodes.ScanlineRender() scanlineRender.setXYpos( curX, curY + spacing*3) camera = nuke.nodes.Camera2() camera.setXYpos( curX + spacing*2, curY + spacing*3 ) camera['translate'].setValue(2, 2 ) scanlineRender.setInput(1, scene ) scanlineRender.setInput(2, camera ) if len(cards): noOp = nuke.nodes.NoOp() noOp.setXYpos( curX, cards[0].ypos() ) noOpName = noOp['name'].getValue() k = nuke.Double_Knob("zspacing" ) noOp.addKnob( k ) k.setValue( 0.1 ) curZ = len(cards) if brkType == BreakoutType.e2_5D and len(cards): camera = nuke.nodes.Camera2() camera.setXYpos( curX, cards[0].ypos() - spacing *2 ) camera['translate'].setValue(2, 2 ) for card in cards: expr = noOpName + '.zspacing * -' + str(curZ) card['translate'].setExpression( expr, 2 ) curZ = curZ - 1 if camera: card.setInput(1, camera ) if brkType == BreakoutType.e3D: scene.setInput( scene.inputs(), card ) if not sRGB: colorSpace2 = nuke.nodes.Colorspace() colorSpace2['channels'].setValue( 'all' ) colorSpace2['colorspace_in'].setValue( 'sRGB') colorSpace2.setInput(0, lastLayer ) colorSpace2.setXYpos( lastLayer.xpos(), lastLayer.ypos() + 2 * spacing ) nuke.Undo().end()
def doReduceKeyframes(): p = doReduceKeyframesPanel(nuke.selectedNode()) if p.showModalDialog(): #user did not hit cancel button undo = nuke.Undo() undo.begin("Reduce keyframes") tErrorPercent = p.tErrorPercent.value() if (tErrorPercent > 100): tErrorPercent = 100 if (tErrorPercent < 0.000001): tErrorPercent = 0.000001 #print "tErrorPercent " + str(tErrorPercent) tFrameRange = nuke.FrameRange(p.tFrameRange.value()) tFirstFrame = tFrameRange.first() tLastFrame = tFrameRange.last() knob_names = nuke.animations( ) # Returns the animations names under this knob i = getKnobIndex( ) #find out if user only clicked on a single knob index, or the entire knob #print "knob index: " + str(i) j = 0 #index for knob for knob_name_with_suffix in knob_names: if (i > -1): j = i #print "for knob_name_with_suffix in knob_names:" knob_name = getKnobName(knob_name_with_suffix) # so that we can get at the knob object and do... k = nuke.thisNode()[knob_name] if (k.isAnimated(j)): tOriginalCurve = k.animation(j) tKeys = tOriginalCurve.keys() tOrigFirstFrame = tKeys[0].x tOrigLastFrame = tKeys[len(tKeys) - 1].x tOrigKeys = len(tOriginalCurve.keys()) fErrorHeight = getCurveHeight(tOriginalCurve, tFirstFrame, tLastFrame) tErrorThreshold = fErrorHeight * (tErrorPercent / 100) #print "tErrorThreshold " + str(tErrorThreshold) if (tOrigKeys > 2): #no point in reducing a straight line! x = nuke.selectedNode() #create a temp knob to copy new keyframes into tempname = "temp_" + knob_name + str(j) tTempKnob = nuke.Double_Knob(tempname) tTempKnob.setAnimated() tTempKnob.setValueAt(tOriginalCurve.evaluate(tFirstFrame), tFirstFrame) tTempKnob.setValueAt(tOriginalCurve.evaluate(tLastFrame), tLastFrame) tTempCurve = tTempKnob.animation(0) #if we are only reducing keyframes on a smaller frame range, then copy the original keyframes into the other frames if (tFirstFrame > tOrigFirstFrame) | (tLastFrame < tOrigLastFrame): tKeys = x[knob_name].animation(j).keys() tCopyKeys = [] for tKey in tKeys: if ((tKey.x < tFirstFrame) | (tKey.x > tLastFrame)): tCopyKeys.append(tKey) tTempKnob.animation(0).addKey(tCopyKeys) #do a quick check to see if 2 keyframes are enough deltaH = (tLastFrame - tFirstFrame) deltaV = (tTempKnob.getValueAt(tLastFrame) - tTempKnob.getValueAt(tFirstFrame)) tMasterSlope = 90 - getAngle(deltaH, deltaV) if (tMasterSlope < 0): tMasterSlope = tMasterSlope + 360 if (findErrorHeight(tOriginalCurve, tTempCurve, tFirstFrame, tLastFrame, tMasterSlope) < tErrorThreshold): print "Looks like this selection of frames was a straight line. Reduce the error threshold % if it isn't" else: #otherwise we run the keyframe reducing function on the selected frame range recursion = findGreatestErrorFrame( tOriginalCurve, tFirstFrame, tLastFrame, tErrorThreshold, tTempKnob, tTempCurve, 0) #copy our reduced keyframes from the temp knob back into our original knob x[knob_name].copyAnimation(j, tTempKnob.animation(0)) #calculate how much we have reduced number of keyframes tFinalKeys = len(x[knob_name].animation(j).keys()) tReductionPC = int( (float(tFinalKeys) / float(tOrigKeys)) * 100) print knob_name + "[" + str(j) + "] had " + str( tOrigKeys) + " keys reduced to " + str( tFinalKeys) + " keys (" + str(tReductionPC) + "%)" else: print "No animation found in " + knob_name + " index " + str(j) #break the loop if we are only running script on single knob index if (i > -1): break else: j = j + 1 undo.end()
def __init__(self, action_name='custom_undo'): self.queue = nuke.Undo(action_name)
def AlignNodes(direction): #-------------------------------------- #USER SETTINGS #when nodes are about to overlap as a result of an alignment, the nodes are placed next to each other instead. #the multiplier variables define the amount of space that's kept between the nodes #1 is default, the higher the multiplier, the more space. #-------------------------------------- multiplierX = 1 multiplierY = 1 #-------------------------------------- selection = nuke.selectedNodes() dontmove = False if direction in ['left','right']: axis = 'x' index = 0 else: axis = 'y' index = 1 #-------------------------------------- #MULTIPLE NODES #if multiple nodes are selected, all the nodes will align to the node that's the furthest away in the specified direction #-------------------------------------- if len(selection) > 1: allPos = [[],[]] for i in selection: allPos[0].append(i.knob('xpos').value()+(getScreenSize(i)[0])) allPos[1].append(i.knob('ypos').value()+(getScreenSize(i)[1])) #check whether all selected nodes already share the same position values to prevent overlapping #if so, do nothing if not allPos[1-index].count(allPos[1-index][0]) == len(allPos[1-index]): if direction in ["left","up"]: destination = min(allPos[index]) else: destination = max(allPos[index]) else: dontmove = True #-------------------------------------- #SINGLE NODE #if only one node is selected, the selected node will snap to the nearest connected node (both input and output) in the specified direction #-------------------------------------- elif len(selection) == 1: curNode = selection[0] #create a list of all the connected nodes inputNodes = curNode.dependencies() outputNodes = curNode.dependent() #remove nodes with hidden inputs and viewer nodes, #as you probably wouldn't want to snap to those #not every node has a hide input knob (read node for example), so use a "try" in case it hasn't for i in outputNodes: try: if i.knob('hide_input').value() or i.Class() == 'Viewer': outputNodes.remove(i) except: pass if curNode.knob('hide_input'): if curNode.knob('hide_input').value(): inputNodes = [] connectedNodes = inputNodes + outputNodes #create a list for every connected node containing the following [xpos,ypos,relative xpos, relative ypos, node] #store those lists in an other list positions = [] for i in connectedNodes: xPos = i.xpos() + getScreenSize(i)[0] yPos = i.ypos() + getScreenSize(i)[1] curNodexPos = curNode.xpos() + getScreenSize(curNode)[0] curNodeyPos = curNode.ypos() + getScreenSize(curNode)[1] positions.append([xPos,yPos,xPos-curNodexPos,yPos-curNodeyPos, i]) # sort the list based on the relative positions sortedList = sorted(positions, key=operator.itemgetter(index+2)) #remove nodes from list to make sure the first item is the node closest to the curNode #use the operator module to switch dynamically between ">=" and "<=" #the positiveDirection variable is used later to correctly calculate to offset in case nodes are about to overlap if direction in ['right','down']: equation = operator.le positiveDirection = -1 else: sortedList.reverse() equation = operator.ge positiveDirection = 1 try: while equation(sortedList[0][index+2],0): sortedList.pop(0) except: pass #checking whether there are nodes to align to in the desired direction #if there are none, don't move the node if len(sortedList) != 0: destination = sortedList[0][index] curPosition = [curNodexPos,curNodeyPos] destinationPosition = [curNodexPos,curNodeyPos] destinationPosition[index] = destination #remove the relative positions from the positionlist for i in range(len(positions)): positions[i] = [positions[i][:2],positions[i][-1]] # Making sure the nodes won't overlap after being aligned. # If they are about to overlap the node will be placed next to the node it tried to snap to. for i in positions: #calculate the difference between the destination and the position of the node it will align to difference = [(abs(i[0][0]-destinationPosition[0]))*1.5,(abs(i[0][1]-destinationPosition[1]))*1.5] #define the amount of units a node should offsetted to not overlap offsetX = 0.75 * (3 * getScreenSize(curNode)[0] + getScreenSize(i[1])[0]) offsetY = 3 * getScreenSize(curNode)[1] + getScreenSize(i[1])[1] offsets = [int(offsetX),int(offsetY)] #check in both directions whether the node is about to overlap: if difference[0] < offsets[0] and difference[1] < offsets[1]: multiplier = [multiplierX,multiplierY][index] offset = positiveDirection * multiplier * offsets[index] #find out whether the nodes are already very close to each other #(even closer than they would be after aligning) #don't move the node if that's the case if abs(offset) < abs(destination - curPosition[index]): destination = destination + offset else: dontmove = True #stop looping through the list when a suitable node to align to is found break else: dontmove = True else: dontmove = True #-------------------------------------- #MOVE THE SELECTED NODES #-------------------------------------- nuke.Undo().name('Align Nodes') nuke.Undo().begin() for i in selection: if not dontmove: if axis == 'x': i.setXpos(int(destination-getScreenSize(i)[index])) else: i.setYpos(int(destination-getScreenSize(i)[index])) nuke.Undo().end()
def scanTree(self): ''' Calculate all need information regarding the current selection. Before doing any actual scaling. This method is called when the user starts dragging one of the sliders. ''' selection = self.getSelection() #if there are less than two nodes selected. Don't do any scaling at all if len(selection) < 2: self.ignore = True self.undo = None return #Dictionary of all nodes with current position values. {[Node object] : (x pos, y position)} #Positions are all neutralized by taking the size of the node in account. self.nodePositions = {} allXpos = [] allYpos = [] for node in selection: #create lists and a dictionary storing position data if node.Class() != 'BackdropNode': x = node.xpos() + (node.screenWidth() / 2) y = node.ypos() + (node.screenHeight() / 2) self.nodePositions[node] = (x, y) allXpos.append(x) allYpos.append(y) else: #If a backdrop node is encountered, store the width and height as well as the regular position data. #store the nodes inside the backdrop in a list backdropSelection = node.getNodes() if len(backdropSelection) > 0: allPositionData = [[ n.xpos(), n.ypos(), n.screenWidth(), n.screenHeight() ] for n in backdropSelection] selectionX = min( [pos[0] + (pos[2] / 2) for pos in allPositionData]) selectionY = min( [pos[1] + (pos[3] / 2) for pos in allPositionData]) selectionW = max( [pos[0] + (pos[2] / 2) for pos in allPositionData]) selectionH = max( [pos[1] + (pos[3] / 2) for pos in allPositionData]) offsetX = node.xpos() - selectionX offsetY = node.ypos() - selectionY offsetW = (node.xpos() + node.knob('bdwidth').value()) - selectionW offsetH = (node.ypos() + node.knob('bdheight').value()) - selectionH self.nodePositions[node] = (selectionX, selectionY, selectionW, selectionH, offsetX, offsetY, offsetW, offsetH) else: #if backdrop is empty, threat it as any other node x = node.xpos() + (node.screenWidth() / 2) y = node.ypos() + (node.screenHeight() / 2) self.nodePositions[node] = (x, y) allXpos.append(x) allYpos.append(y) #calculate the most extreme values to define the borders of the selection minXpos = min(allXpos) maxXpos = max(allXpos) maxYpos = max(allYpos) minYpos = min(allYpos) #set the pivotpoint self.pivotX = (maxXpos * self.setPivotWidget.pivot[0]) + ( minXpos * (1 - self.setPivotWidget.pivot[0])) self.pivotY = (maxYpos * self.setPivotWidget.pivot[1]) + ( minYpos * (1 - self.setPivotWidget.pivot[1])) self.ignore = False #add the scaling of the nodes to the stack of preformed actions to offer the user the option to undo it. self.undo = nuke.Undo() self.undo.begin("Scale Nodes")
def autoShuffleReads(nodes): import re import nuke nuke.Undo().name('organize and split') nuke.Undo().begin() readList = [] yPosAvg = 0 xPosAvg = 0 count = 0 try: nodes # does a exist in the current namespace except NameError: nodes = nuke.selectedNodes() for curNode in nodes: if curNode.Class() == 'Read': readList.append({'file': nuke.filename(curNode), 'node': curNode}) yPosAvg = yPosAvg + curNode['ypos'].value() xPosAvg = xPosAvg + curNode['xpos'].value() count += 1 readListSorted = sorted(readList, key=lambda k: k['file']) xPosAvg = int(xPosAvg / count) yPosAvg = int(yPosAvg / count) count = 0 for readNode in readListSorted: readNode['node']['xpos'].setValue(xPosAvg - 110 * count) readNode['node']['ypos'].setValue(yPosAvg) readNode['node']['selected'].setValue(True) count += 1 for n in nuke.selectedNodes(): n.autoplace() prevNode = nuke.nodes.Dot() originalDot = prevNode for curNode in nuke.selectedNodes(): if curNode.Class() == 'Read': count += 1 filename = nuke.filename(curNode) passName = filename.split('.')[1] if re.match(r'^[A-Za-z0-9_]+$', passName): newLayer = nuke.Layer(passName, [ passName + '.red', passName + '.green', passName + '.blue' ]) shuffle = nuke.nodes.Shuffle(label=passName, inputs=[curNode]) shuffle['out'].setValue(passName) dotNode = nuke.nodes.Dot(inputs=[shuffle]) copyNode = nuke.nodes.Copy(inputs=[prevNode, dotNode], channels=passName, selected=True) prevNode = copyNode else: masterNode = curNode if count % 2 == 0: curNode['ypos'].setValue(curNode['ypos'].value() + 110) originalDot.setInput(0, masterNode) backdrop = nukescripts.autoBackdrop() backdrop.knob('tile_color').setValue(2139062271) nuke.Undo().end()
def breakoutLayers(node, sRGB=True): if not node: return nuke.Undo().begin() blendMap = {} blendMap['norm'] = "normal" blendMap['scrn'] = "screen" blendMap['div '] = "color dodge" blendMap['over'] = "overlay" blendMap['mul '] = "multiply" blendMap['dark'] = "darken" blendMap['idiv'] = "color burn" blendMap['lbrn'] = "linear burn" blendMap['lite'] = "lighten" blendMap['lddg'] = "linear dodge" blendMap['lgCl'] = "lighter color" blendMap['sLit'] = "soft light" blendMap['hLit'] = "hard light" blendMap['lLit'] = "linear light" blendMap['vLit'] = "vivid light" blendMap['pLit'] = "pin light" blendMap['hMix'] = "hard mix" blendMap['diff'] = "difference" blendMap['smud'] = "exclusion" blendMap['fsub'] = "subtract" blendMap['fdiv'] = "divide" blendMap['hue '] = "hue" blendMap['sat '] = "saturation" blendMap['colr'] = "color" blendMap['lum '] = "luminosity" metaData = node.metadata() layers = getLayers(metaData) xspacing = 80 dotXfudge = 34 dotYfudge = 4 backdropXfudge = -(xspacing / 2) + 10 backdropYfudge = -40 spacing = 70 x = node.xpos() y = node.ypos() curY = y + spacing * 2 if not sRGB: colorSpace = nuke.nodes.Colorspace() colorSpace['channels'].setValue('all') colorSpace['colorspace_out'].setValue('sRGB') colorSpace.setInput(0, node) colorSpace.setXYpos(x, curY) inputNode = colorSpace else: inputNode = node curX = x curY = y + spacing * 2 topY = curY lastLayer = None background = None i = 0 for l in layers: try: if l.attrs['divider/type'] > 0: ## hidden divider or start of group continue except: pass i = i + 1 if i > 100: nuke.message("Too many layers, stopping at layer 100.") break name = l.attrs['nukeName'] curY = topY if i % 2: tileColor = 2829621248 else: tileColor = 1751668736 backdrop = nuke.nodes.BackdropNode(tile_color=tileColor, note_font_size=18) backdrop.setXYpos(curX + backdropXfudge, curY + backdropYfudge) curY += spacing / 2 dot = nuke.nodes.Dot() dot.setInput(0, inputNode) dot.setXYpos(curX + dotXfudge, curY + dotYfudge) curY += spacing inputNode = dot shuffle = nuke.nodes.Shuffle() shuffle['label'].setValue(name) shuffle['in'].setValue(name) shuffle['in2'].setValue('none') shuffle['red'].setValue('red') shuffle['green'].setValue('green') shuffle['blue'].setValue('blue') shuffle['alpha'].setValue('alpha') ## if no 'alpha' assume alpha of 1 alphaChan = name + ".alpha" if not alphaChan in inputNode.channels(): shuffle['alpha'].setValue('white') shuffle['black'].setValue('red2') shuffle['white'].setValue('green2') shuffle['red2'].setValue('blue2') shuffle['green2'].setValue('alpha2') shuffle['out'].setValue('rgba') shuffle['out2'].setValue('none') shuffle.setInput(0, inputNode) shuffle.setXYpos(curX, curY) curY += spacing crop = nuke.nodes.Crop() crop['box'].setValue(l.attrs['x'], 0) crop['box'].setValue(l.attrs['y'], 1) crop['box'].setValue(l.attrs['r'], 2) crop['box'].setValue(l.attrs['t'], 3) crop.setInput(0, shuffle) crop.setXYpos(curX, curY) curY += spacing * 2 layer = crop merge = None try: operation = blendMap[l.attrs['blendmode']] except: print "unknown blending mode " + l.attrs['blendmode'] operation = "normal" if lastLayer: psdMerge = nuke.nodes.PSDMerge() psdMerge['operation'].setValue(operation) psdMerge.setInput(0, lastLayer) psdMerge.setInput(1, layer) psdMerge.setXYpos(curX, curY) psdMerge['sRGB'].setValue(sRGB) psdMerge['mix'].setValue((l.attrs['opacity'] / 255.0)) try: if (l.attrs['mask/disable'] != True): psdMerge['maskChannelInput'].setValue(name + '.mask') if (l.attrs['mask/invert'] == True): psdMerge['invert_mask'].setValue(True) except: pass lastLayer = psdMerge else: dot = nuke.nodes.Dot() dot.setInput(0, layer) dot.setXYpos(curX + dotXfudge, curY + dotYfudge) lastLayer = dot curY += spacing backdrop['bdwidth'].setValue(xspacing * 2 + backdropXfudge * 2 + 50) backdrop['bdheight'].setValue((curY - backdrop.ypos()) - backdropYfudge - 50) backdrop['label'].setValue(l.attrs['name']) curY += spacing curX = curX + xspacing * 2 + backdropXfudge * 2 + 50 if not sRGB: colorSpace2 = nuke.nodes.Colorspace() colorSpace2['channels'].setValue('all') colorSpace2['colorspace_in'].setValue('sRGB') colorSpace2.setInput(0, lastLayer) colorSpace2.setXYpos(lastLayer.xpos(), lastLayer.ypos() + 2 * spacing) nuke.Undo().end()