Nuke Python

From bernie's
Jump to: navigation, search

Create dots from selected

s = nuke.selectedNodes()
counter = -1
pos = [0,0]
dots = []
#dots are super 'sticky' need to remove selection
for node in nuke.allNodes(recurseGroups=True):
    node['selected'].setValue(False)
for n in reversed(s):
    counter += 1
    dot=nuke.createNode('Dot')
    dot.setInput(0, n)
    if counter == 0:
        #dot.autoplace()
        pos = [dot['xpos'].value(),dot['ypos'].value()]
        x = int(pos[0])
        y = int(pos[1])
        dot.setXYpos(x,y)
    else:
        x = int(pos[0]+counter*30)
        y = int(pos[1])
        dot.setXYpos(x,y)

    dot.knob('label').setValue(n.name())
    dots.append(dot)

for d in dots:
    d['selected'].setValue(True)

switch with inputs according to y pos

def getKey(item):
    return item['ypos'].value()

sel = nuke.selectedNodes()
sorted(sel, key=getKey)

switch = nuke.nodes.Switch(inputs=sel)

Check MXI SLs with Nuke (maxwell render)

Reads metadata

fAIuyTt.png

def checkMXI_SL():
    '''takes mxi read node and checks its SLs metadata and outputs frames under certain treshold'''

    sl_threshold = 18.0
    txt = nuke.getInput('Print frames with SL below:', str(sl_threshold))
    if txt:
        sl_threshold = float(txt)
    output = ''

    task = nuke.ProgressTask("Checking MXI SLs") 
    task.setMessage("Progress")

    for node in nuke.selectedNodes():
        if node.Class() == 'Read':
            firstframe = int(node['first'].value())
            #lastframe = firstframe + 10
            lastframe = int(node['last'].value())
            for i in range(firstframe, lastframe):
                percentage = int(100.0*(i-firstframe)/(lastframe-firstframe))
                task.setProgress(percentage)
                if task.isCancelled(): 
                    break;

                sl = node.metadata('SAMPLING_LEVEL',i)
                if  sl < sl_threshold:
                        task.setMessage('Frame ['+str(i)+'] SL'+"{0:.1f}".format(sl))                        
                        logline = 'Frame ' + str(i) + ': ' + "{0:.2f}".format(sl) + '\n'
                        output = output + logline
            task.setProgress(100)
    del task

    p = nuke.Panel('Results')
    if output == '':
        output = 'All MXI are above or equal to '+str(sl_threshold)
    p.addNotepad('Results:',output)
    ret = p.show()

checkMXI_SL()

Rainbow colored gradient in nuke expression

dlg2rOF.png

red   : ( r * 6 >= 2 && r * 6 <= 4 ) ? 0 : ( r * 6 <= 1 || r * 6  >= 5) ? 1 : ( 1 - abs ( ( r * 6 ) % 2 - 1 ) )
green : ( r * 6 >= 4 && r * 6 <= 6 ) ? 0 : ( r * 6 >= 1 && r * 6  <= 3) ? 1 : ( 1 - abs ( ( r * 6 ) % 2 - 1 ) )
blue  : ( r * 6 >= 0 && r * 6 <= 2 ) ? 0 : ( r * 6 >= 3 && r * 6  <= 5) ? 1 : ( 1 - abs ( ( r * 6 ) % 2 - 1 ) )

But better:

r: from 0 to 1
g: 1
b: 1

colorspace in HSV out sRGB

Quick Tips

#knobs and values of a node
print(nuke.selectedNode())

Create proxy from File with reformat

exr to png

#creates RGBA8bit PNG with .5 scale and write next to file with .png extension. So /path/to/file.exr.png
for node in nuke.selectedNodes():
    if node.Class() == 'Read':
        readPath = node['file'].evaluate()
        reformat = nuke.nodes.Reformat(inputs=[node],type=2,scale=.5)
        write = nuke.nodes.Write(inputs=[reformat],channels='rgba',file=readPath+'.png',file_type='png')

        node['selected'].setValue(0)
        write['selected'].setValue(1)

png to exr

#reads to EXR
for node in nuke.selectedNodes():
    if node.Class() == 'Read':
        readPath = node['file'].evaluate()
        #reformat = nuke.nodes.Reformat(inputs=[node],type=2,scale=.5)
        write = nuke.nodes.Write(inputs=[node],channels='rgba',file=readPath+'.exr',file_type='exr')

        node['selected'].setValue(0)
        write['selected'].setValue(1)

Contact Sheet Ordered From Lasso-Selected

# takes a selection of read nodes, and places them in a contact sheet according to their position
# in the node graph
# first input of contact sheet determines text & text positions, it defaults to the read image name

# to do: auto number the Contact sheet

from random import random


def linkKnobs(sourceNode, destNode, knobs = []):
    for knob in knobs:
        for idx, item in enumerate(sourceNode[knob].array()):
            expression =  sourceNode.name()+'.'+str(knob)+'.'+str(idx)
            destNode[knob].setExpression(expression,idx)


nodes = nuke.selectedNodes()
nodeList = []
minmaxX = [1000000,-1000000]
minmaxY = [1000000,-1000000]
averagePosition = [0,0]
counter = 0

for node in nodes:
    counter = counter + 1
    nodePos = [node['xpos'].value(),node['ypos'].value()]
    averagePosition = [averagePosition[0]+nodePos[0],averagePosition[1]+nodePos[1]]
    minmaxX = [min(minmaxX[0],nodePos[0]),max(minmaxX[1],nodePos[0])]
    minmaxY = [min(minmaxY[0],nodePos[1]),max(minmaxY[1],nodePos[1])]
    nodeList.append([node,nodePos[0],nodePos[1]])

averagePosition = [averagePosition[0]/(counter*1.0),averagePosition[1]/(counter*1.0)]
horizontalSort = True

if minmaxX[1]-minmaxX[0] > minmaxY[1]-minmaxY[0]:
    horizontalSort = True
    nodeList.sort(key=lambda x: x[1])
else:
    horizontalSort = False
    nodeList.sort(key=lambda x: x[2])

textNodes = []
for array in nodeList:

    textNode = nuke.nodes.Text2(inputs=[array[0]],xjustify='left',yjustify='bottom',box='15 15 3000 1000')
    textNodes.append(textNode)

    if horizontalSort:
        textNode.setXpos( int(array[0]['xpos'].value()) )
        textNode.setYpos( int(array[0]['ypos'].value() + 200.0) )
    else:
        textNode.setXpos( int(array[0]['xpos'].value() + 200.0) )
        textNode.setYpos( int(array[0]['ypos'].value() + 20 ) )
    nuke.autoplaceSnap(textNode)

#ratio = nodeList[0][0].width()/nodeList[0][0].height()
#print ratio
#print len(nodeList)
cs = nuke.nodes.ContactSheet(inputs=textNodes)

if horizontalSort:
    cs.setXYpos(int(averagePosition[0] + 0),int(averagePosition[1] + 350))
else:
    cs.setXYpos(int(averagePosition[0] + 350),int(averagePosition[1] + 0))

nuke.autoplaceSnap(cs)

controlText = textNodes[0]
controlText.knob('message').setValue('[lindex [split [lindex [split [knob [topnode].file] .] 0] /] end]')
controlText.knob('tile_color').setValue(int('%02x%02x%02x%02x' % (random()*255,random()*255,random()*255,1),16))


for n in textNodes[1:]:

    n.knob('message').setValue('[expr [knob '+controlText.name()+'.message]]')
    linkKnobs(controlText,n,['box','global_font_scale','yjustify','xjustify','font_size','font_width','font_height','kerning','tracking','baseline_shift','leading','translate','rotate','scale','center'])

Automatically merge files into single channel

bE5OYQu.png

If you didn't toggle multi-channel exr you big dummy

This might bug around ' simplename = strpath.split("/").pop().split("_v0")[0].split("_").pop() ' since it was specific to my project (this line figures out the channel name)

def sortAccordingToNodeGraphPosition(nodes):
    '''sorts a node list according to their graph position. Hack-ish but works (?)'''
    nodeList = []
    minmaxX = [1000000,-1000000]
    minmaxY = [1000000,-1000000]
    averagePosition = [0,0]
    counter = 0
    
    for node in nodes:
        counter = counter + 1
        nodePos = [node['xpos'].value(),node['ypos'].value()]
        averagePosition = [averagePosition[0]+nodePos[0],averagePosition[1]+nodePos[1]]
        minmaxX = [min(minmaxX[0],nodePos[0]),max(minmaxX[1],nodePos[0])]
        minmaxY = [min(minmaxY[0],nodePos[1]),max(minmaxY[1],nodePos[1])]
        nodeList.append([node,nodePos[0],nodePos[1]])
    
    averagePosition = [averagePosition[0]/(counter*1.0),averagePosition[1]/(counter*1.0)]
    horizontalSort = True
    
    if minmaxX[1]-minmaxX[0] > minmaxY[1]-minmaxY[0]:
        horizontalSort = True
        nodeList.sort(key=lambda x: x[1])
    else:
        horizontalSort = False
        nodeList.sort(key=lambda x: x[2])
    
    sortedList = [node for node, x,y in nodeList]
    return sortedList


selReads = nuke.selectedNodes()
selReads = sortAccordingToNodeGraphPosition(selReads)
shuffleInputs = []
selReadslen = len(selReads)
for i in range(selReadslen):

    #curRead = selReads[selReadslen-1-i]
    curRead = selReads[i]
    strpath = curRead['file'].value()
    simplename = strpath.split("/").pop().split("_v0")[0].split("_").pop()
    #goes from 'D:/longpath/folder/v006/superlongname_360_beauty_v006.%04d.exr' to  'beauty'


    if i > 0:
        shuffle = nuke.nodes.ShuffleCopy()
        shuffleInputs.append(shuffle)
        shuffle.setInput(0, shuffleInputs[i-1])
        shuffle.setInput(1, curRead)


        cmd = "add_layer {%s " % simplename
        for each in ["r", "g", "b", "a"]:
            cmd += "%s.%s " % (simplename, each)
        
        cmd += "}"
        
        #set using tcl can't figure out python for this
        nuke.tcl(cmd)
        shuffle["label"].setValue("[knob this.out]")
        shuffle["out"].setValue(simplename)
        shuffle["out2"].setValue('rgba')
        shuffle["red"].setValue("red")
        shuffle["green"].setValue("green")
        shuffle["blue"].setValue("blue")
        shuffle["alpha"].setValue("alpha")
        shuffle["black"].setValue("red2")
        shuffle["white"].setValue("green2")
        shuffle["red2"].setValue("blue2")
        shuffle["green2"].setValue("alpha2")

    
    else:
        shuffleInputs.append(curRead)
    
    

Automatically extract channels

source: http://www.muttsy.net/blog/2011/10/20/shuffle-out-all-channels/

import os

createWrite = False
nodes = nuke.selectedNodes()
for node in nodes:
    if node.Class() == 'Read':
        channels = node.channels()
        layers = list( set([channel.split('.')[0] for channel in channels]) )
        layers.sort()
        #readPath = node['file'].evaluate()
        readPath = os.path.splitext(readPath)[0]
        print(readPath)
        if 'rgba' in layers:
            layers.remove('rgba')
        for layer in layers:
            shuffleNode = nuke.nodes.Shuffle(label=layer,inputs=[node])
            shuffleNode['in'].setValue( layer )
            shuffleNode['postage_stamp'].setValue(True)
            if createWrite:
                writeNode = nuke.nodes.Write(label=layer,inputs=[shuffleNode])
                writeNode['file'].value = readPath+layer+'.png'
                print(readPath+layer+'.png')
    else:
        pass



Auto write new folders

for w in nuke.allNodes("Write"):
w.knob("beforeRender").setValue("import os\nif not os.path.isdir(os.path.dirname(nuke.thisNode()['file'].evaluate())):\n  os.makedirs(os.path.dirname(nuke.thisNode()['file'].evaluate()))")