######################################################################## ### PROXY TOOLS 1.0 ### by Brian Willard ### mybikeislost@gmail.com ### ### Generates reformat and write nodes for rendering proxies on a farm ### option to process all read nodes, selected read nodes, or all quicktime files in a script ### reads metadata to determine filetype to handle quicktime files with and without and extension. ### process sequences proxy subfolders ### option to create a read node that reflects the new proxy/fullres path ### TODO: add support for r3d files ### ### ######################################################################## import re import os import sys import nuke import nukescripts def proxyTools(): def _buildPROXIES(selection, processPlates, createRead, formatFullVal, formatProxyVal, formatProxySizeVal): print '\n######## PROXYTOOLS Variables ########\n' print 'selection: ' +selection print 'processPlates: ' +processPlates print 'createRead: ' +str(createRead) print 'formatFullVal: ' +formatFullVal print 'formatProxyVal: ' +formatProxyVal print 'formatProxySizeVal: ' +formatProxySizeVal print '\n###############################\n' ### Figure out what we're rendering and build a list (all, selected, quicktime) readlist = [] if selection ==('selected'): readlist= [i for i in nuke.selectedNodes() if i.Class() =='Read'] if readlist ==[]: nuke.message('no Read nodes selected!') return if selection == ('all'): readlist= [i for i in nuke.allNodes() if i.Class() =='Read'] if selection == ('quicktime'): readlist = [i for i in nuke.allNodes() if i.metadata('input/filereader') == 'QuickTime'] ### Figure out if we're rendering fullres, proxies, or both if processPlates == 'both': processProxy = True processFull = True print 'rendering Proxy and FullRes' if processPlates == 'proxy': processFull = False processProxy = True print 'rendering Proxy only' if processPlates == 'full': processFull = True processProxy = False print 'rendering FullRes only' if sys.platform.startswith('win'): pathslash = ('\\') else: pathslash = ('/') for i in readlist: curNode = i truncpath = i.knob('file').value().rfind(pathslash) truncfile = i.knob('file').value().rfind('.mov') dirpath = i.knob('file').value()[:truncpath] print '\n######## Begin ' +i.name() + ' ########\n' ### Get filename and padding info from source knob if i.metadata('input/filereader') == 'QuickTime': filetype='quicktime' filepath = i.knob('file').getValue('fileName') filename = os.path.splitext(i.knob('file').getValue('fileName').split(pathslash)[-1])[-2] padding = 4 print 'source file is a quicktime ' fullFmt = str(int((i.format().width()))) +'x' +str(int((i.format().height()))) print 'filepath: ' +filepath print 'filename: ' +filename print 'fullFmt: ' +fullFmt resFolder = False else: filetype='imgSequence' filepath = i.knob('file').getValue('fileName') filename =(i.knob('file').getValue('fileName')).split('.')[-3].split(pathslash)[-1] parentfolder = (i.knob('file').getValue('fileName')).split('.')[-3].split(pathslash)[-2] fullFmt = str(int((i.format().width()))) +'x' +str(int((i.format().height()))) print 'source file is an image sequence' print 'filepath: ' +filepath print 'filename: ' +filename print 'parentfolder: ' +parentfolder print 'fullFmt: ' +fullFmt if parentfolder == fullFmt: resFolder = True print 'we are in a resolution folder, rendering 1 level up' dirpath = os.sep.join(dirpath.split(pathslash)[:-1]) print 'adjusted output path is: ' +dirpath else: resFolder = False print 'fullres not in a format folder, creating sub folders' #print 'adjusted output path is: ' +dirpath number = re.search('(%+\d+d)|(#+)|(%d)' , filepath) if number: padding = len(number.group(1)) path = i.knob('file').value() if path.find('rnd'): os.path.basename(path) foldername = filename + '_IMG' # try: # os.mkdir(dirpath +pathslash +foldername) # except OSError: pass ###################################################### ### BUILD PROXY ### FILTER TYPES BY PROXY RASTER: Full (Impulse), half (Cubic), quarter (Cubic) ### ###################################################### if processProxy == True: ### CREATE FORMAT m = nuke.createNode('Reformat', inpanel = False) m.setInput(0,i) m.setXYpos((int(i.knob('xpos').value())), (int(i.knob('ypos').value())+125)) m.knob('type').setValue('scale') if formatProxySizeVal ==('full'): sizeVal = 1.0 m.knob('filter').setValue('Impulse') elif formatProxySizeVal ==('half'): sizeVal = 0.5 m.knob('filter').setValue('Cubic') elif formatProxySizeVal ==('quarter'): sizeVal = 0.25 m.knob('filter').setValue('Cubic') m.knob('scale').setValue(sizeVal) m.knob('label').setValue('Filter: '+ m.knob('filter').value()+ '\nProxy Size: ' +formatProxySizeVal) ### CREATE WRITE n = nuke.createNode('Write', inpanel=False) n.setXYpos((int(m.knob('xpos').value())), (int(m.knob('ypos').value())+50)) proxyFmt = str(int((i.format().width())*sizeVal)) +'x' +str(int((i.format().height())*sizeVal)) print 'proxyFmt: ' +proxyFmt if formatProxyVal ==('exr'): if resFolder == True: n.knob('file').setValue(dirpath +pathslash +proxyFmt +pathslash + filename +'.' + '%0'+str(padding)+'d.exr') else: n.knob('file').setValue(dirpath +pathslash + foldername +pathslash +proxyFmt +pathslash + filename +'.' + '%0'+str(padding)+'d.exr') n.knob('file_type').setValue('exr') n.knob('channels').setValue('all') n.knob('colorspace').setValue(int(i.knob('colorspace').getValue())) n.knob('premultiplied').setValue(i.knob('premultiplied').value()) n.knob('raw').setValue(i.knob('raw').value()) n.knob('stereo').setValue(False) elif formatProxyVal ==('jpeg'): n.knob('file_type').setValue('jpeg') n.knob('channels').setValue('all') n.knob('_jpeg_quality').setValue(0.97) if resFolder == True: n.knob('file').setValue(dirpath +pathslash +proxyFmt +pathslash + filename +'.' + '%0'+str(padding)+'d.jpg') else: n.knob('file').setValue(dirpath +pathslash + foldername +pathslash +proxyFmt +pathslash + filename +'.' + '%0'+str(padding)+'d.jpg') n.knob('disable').setExpression('!inrange(frame, '+ str(i.knob('first').value()) + ', ' + str(i.knob('last').value()) + ')',0) n.knob('label').setValue('PROXY \n Format: ' + proxyFmt) print 'Proxy output: ' +n.knob('file').getValue() ###################################################### ### BUILD FULL RES ### ### ###################################################### #move 'dot' up in DAG if processFull == True: d = nuke.createNode('Dot', inpanel=False) d.setInput(0,i) d.setXYpos((int(i.knob('xpos').value())+160), (int(i.knob('ypos').value())+45)) o = nuke.createNode('Write', inpanel=False) o.setInput(0,d) o.setXYpos((int(d.knob('xpos').value()-33)), (int(d.knob('ypos').value())+120)) fullFmt = str(o.format().width()) +'x' +str(o.format().height()) if formatFullVal ==('exr'): o.knob('file_type').setValue('exr') o.knob('channels').setValue('all') o.knob('colorspace').setValue(int(i.knob('colorspace').getValue())) o.knob('premultiplied').setValue(i.knob('premultiplied').value()) if resFolder == True: o.knob('file').setValue(dirpath+pathslash +fullFmt +pathslash + filename +'.' + '%0'+str(padding)+'d.exr') else: o.knob('file').setValue(dirpath+pathslash + foldername +pathslash +fullFmt +pathslash + filename +'.' + '%0'+str(padding)+'d.exr') o.knob('raw').setValue(i.knob('raw').value()) o.knob('stereo').setValue(False) elif formatFullVal ==('jpeg'): o.knob('file_type').setValue('jpeg') o.knob('channels').setValue('all') o.knob('_jpeg_quality').setValue(0.97) o.knob('file').setValue(dirpath+pathslash + foldername +pathslash +fullFmt +pathslash + filename +'.' + '%0'+str(padding)+'d.jpg') o.knob('label').setValue('FULL \n Format: [value format.w]x[value format.h]') o.knob('disable').setExpression('!inrange(frame, '+ str(i.knob('first').value()) + ', ' + str(i.knob('last').value()) + ')',0) print 'FullRes output: ' +o.knob('file').getValue() ###################################################### ### CREATE READ FROM OUR PROXY/FULL RASTER RENDERS ### ### ###################################################### if createRead == True: p = nuke.createNode('Read', inpanel = False) print '\n#### generating ' +p.name() +'####\n' if processFull== True: p.knob('file').setValue((o.knob('file').getValue('fileName'))) else: p.knob('file').setValue((i.knob('file').getValue('fileName'))) print 'file path: ' +p.knob('file').getValue('fileName') if processProxy == True: p.knob('proxy').setValue((n.knob('file').getValue('fileName'))) print 'proxy path: ' +p.knob('proxy').getValue('fileName') p.knob('first').setValue(int(i.knob('first').value())) p.knob('last').setValue(int(i.knob('last').value())) p.knob('first').setValue(int(i.knob('origfirst').value())) p.knob('origlast').setValue(int(i.knob('origlast').value())) p.setXYpos((int(i.knob('xpos').value())), (int(i.knob('ypos').value())+300)) print '\n######## Finished ' +i.name() + ' ########\n' class ProxyToolsPanel(nukescripts.PythonPanel): def __init__(self): nukescripts.PythonPanel.__init__(self, 'Proxy Tools v1.0', 'com.mybikeislost.ProxyTools') ### Create KNOBS self.processSelectionKnob = nuke.Enumeration_Knob('processSelection', 'Process Reads:', ['all', 'selected', 'quicktime']) self.processPlatesKnob = nuke.Enumeration_Knob('processPlates', 'Process Plates:', ['both', 'full', 'proxy']) self.createReadKnob = nuke.Boolean_Knob('create write node with our full/proxy paths from above', 'Create Read') self.dividerKnob = nuke.Text_Knob('div name','','') self.formatFullKnob = nuke.Enumeration_Knob('format', 'Full Res Format', ['exr', 'jpeg']) self.dividerKnob2 = nuke.Text_Knob('div name','','') self.formatProxyKnob = nuke.Enumeration_Knob('proxy_Format', 'Proxy Format:', ['jpeg', 'exr']) self.proxySizeKnob = nuke.Enumeration_Knob('proxy_Size', 'Proxy Size:', ['half', 'full', 'quarter']) self.dividerKnob3 = nuke.Text_Knob('div name','','') ### ADD KNOBS for k in ( self.processSelectionKnob, self.processPlatesKnob, self.createReadKnob, self.dividerKnob, self.formatFullKnob, self.dividerKnob2, self.formatProxyKnob, self.proxySizeKnob, self.dividerKnob3 ): self.addKnob( k ) def showModalDialog(self): result = nukescripts.PythonPanel.showModalDialog(self) if result: selection = str(self.processSelectionKnob.value()) processPlates = str(self.processPlatesKnob.value()) createRead = self.createReadKnob.value() formatFullVal =str(self.formatFullKnob.value()) formatProxyVal = self.formatProxyKnob.value() formatProxySizeVal = str(self.proxySizeKnob.value()) _buildPROXIES(selection, processPlates, createRead, formatFullVal, formatProxyVal, formatProxySizeVal) def showProxyTools(): ProxyToolsPanel().showModalDialog() showProxyTools()