123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- import fnmatch
- import nuke
-
-
- # martin@keller.io
- __version__ = '1.0'
-
- MODES = ['MergeBackIntoStream','SelectOnly', 'ContactSheet']
- #PATTERNDEFAULT = "*direct* !*indirect* !*default"
- PATTERNDEFAULT = ""
- PATTERNIGNORE = "*variance *denoise* *matte* P N Z rgba albedo"
- INIT_DONE = False
-
- class ChannelSelect(KellerNukePlugin):
-
- def configurePlugin(self):
- self.menu = nuke.menu('Nodes')
- m = self.menu.addMenu('Workgroup','Toolbar_Workgroup.png')
- m.addCommand('ChannelSelect', 'import ChannelSelect; ChannelSelect.createChannelSelect()', icon=':qrc/images/ToolbarChannel.png')
- nuke.addKnobChanged(onKnobChanged)
- nuke.addOnCreate(onCreate, nodeClass=('Group'))
-
- def unconfigurePlugin(self):
- self.menu.removeItem('ChannelSelect')
- nuke.removeKnobChanged(onKnobChanged)
- nuke.removeOnCreate(onCreate)
- pass
-
-
- # events
- def onKnobChanged():
- global INIT_DONE
- if not INIT_DONE:
- # not ready
- return
-
- k = nuke.thisKnob()
- # do a refresh on these knobs
- refresh_resolved = ['pattern', 'pattern_exclude', 'update']
-
- if k.name() in refresh_resolved:
- print('ChannelSelect: Info. Event refresh triggered.')
- # Config changed, loading new tasks
- n = nuke.thisNode()
-
- pattern = n['pattern'].value()
- pattern_exclude = n['pattern_exclude'].value()
- resolved = resolvePattern(n, pattern, pattern_exclude)
- if resolved:
- resString = '\n'.join(resolved)
-
- if not resolved:
- n['resolved'].setValue('NO MATCH')
- else:
- n['resolved'].setValue(resString)
- pass
-
-
- def onCreate():
- print('ChannelSelect: Info. On Create refresh triggered.')
- n = nuke.thisNode()
- # % (r * 255, g * 255, b * 255, 1), 16): change r g and b to your liking
- hexColour = int('%02x%02x%02x%02x' % (0 * 255, 0 * 255, 0 * 255, 1), 16)
- n['tile_color'].setValue(hexColour)
-
-
-
- def createChannelSelect():
- # get selected Node (for connecting our node below)
- try:
- s = nuke.selectedNode()
- except:
- s = None
- # deselect all Nodes
- for a in nuke.allNodes():
- a.knob('selected').setValue(False)
-
- # create Group
- n = nuke.collapseToGroup(show = False)
- n.setName('ChannelSelect')
- # % (r * 255, g * 255, b * 255, 1), 16): change r g and b to your liking
- hexColour = int('%02x%02x%02x%02x' % (0 * 255, 0 * 255, 0 * 255, 1), 16)
- n['tile_color'].setValue(hexColour)
-
- if s is not None:
- n.setInput(0, s)
- n.setXYpos(s.xpos(), s.ypos() + 100)
-
- # tab ChannelSelect
- k = nuke.Tab_Knob('select', 'select')
- n.addKnob(k)
-
- # Pattern
- k = nuke.EvalString_Knob('pattern', 'pattern')
- n.addKnob(k)
- n.knob('pattern').setTooltip('*diffuse* *SSS*\nwith exclude (! or ^):\n*direct* !*indirect*')
- n.knob('pattern').setValue(PATTERNDEFAULT)
-
- # Update
- k = nuke.PyScript_Knob('update', 'Set', 'ChannelSelect.updatePattern(nuke.thisNode())')
- n.addKnob(k)
- n.knob('update').setTooltip('Creates Nodes in Group based on Search Pattern')
-
- # Pattern
- k = nuke.EvalString_Knob('pattern_exclude', 'exclude')
- n.addKnob(k)
- n.knob('pattern_exclude').setTooltip('always exclude this pattern')
- n.knob('pattern_exclude').setValue(PATTERNIGNORE)
-
- # Resolved Channels
- k = nuke.Multiline_Eval_String_Knob('resolved', 'preview')
- n.addKnob(k)
- n.knob('resolved').setTooltip('These AOVs are found based on your search Pattern above. Press Set to use these aovs.')
-
- # Divide and Conquer
- k = nuke.Text_Knob('divider1', '')
- n.addKnob(k)
-
- # unpremult
- k = nuke.Boolean_Knob('unpremult', 'unpremult')
- n.addKnob(k)
- n.knob('unpremult').setValue(True)
- n.knob('unpremult').setFlag(nuke.STARTLINE)
-
- # Divide and Conquer
- k = nuke.Text_Knob('divider2', '')
- n.addKnob(k)
-
- # Saturation
- k = nuke.Double_Knob('saturation', 'saturation')
- n.addKnob(k)
- n.knob('saturation').setRange(0,1)
- n.knob('saturation').setValue(1)
-
- # Divide and Conquer
- k = nuke.Text_Knob('divider3', '')
- n.addKnob(k)
-
- # Exposure
- k = nuke.Double_Knob('exposure', 'exposure')
- n.addKnob(k)
- n.knob('exposure').setRange(-2,2)
-
- # Divide and Conquer
- k = nuke.Text_Knob('divider', '')
- n.addKnob(k)
-
- # Blackpoint
- k = nuke.Color_Knob('blackpoint', 'blackpoint')
- n.addKnob(k)
- n.knob('blackpoint').setRange(-1,1)
- n.knob('blackpoint').setValue([0, 0, 0])
-
- # Whitepoint
- k = nuke.Color_Knob('whitepoint', 'whitepoint')
- n.addKnob(k)
- n.knob('whitepoint').setRange(0,4)
- n.knob('whitepoint').setValue(1)
- n.knob('whitepoint').setValue([1, 1, 1])
-
- # Lift
- k = nuke.Color_Knob('black', 'lift')
- n.addKnob(k)
- n.knob('black').setRange(-1,1)
- n.knob('black').setValue([0, 0, 0])
-
- # Multiply
- k = nuke.Color_Knob('multiply', 'multiply')
- n.addKnob(k)
- n.knob('multiply').setValue([1, 1, 1])
- n.knob('multiply').setRange(0, 4)
-
- # Gamma
- k = nuke.Double_Knob('gamma', 'gamma')
- n.addKnob(k)
- n.knob('gamma').setValue(1)
- n.knob('gamma').setRange(0.2, 2)
-
- # Compensate Mult
- k = nuke.Boolean_Knob('compensate', 'compensate mult')
- n.addKnob(k)
- n.knob('compensate').setValue(True)
- n.knob('compensate').setFlag(nuke.STARTLINE)
-
- # Reset Values
- k = nuke.PyScript_Knob('reset', 'reset', 'ChannelSelect.resetValues(nuke.thisNode())')
- n.addKnob(k)
- n.knob('reset').setTooltip('Reset Color Correct values')
- n.knob('reset').setFlag(nuke.STARTLINE)
-
- # Divide and Conquer
- k = nuke.Text_Knob('divider4', '')
- n.addKnob(k)
-
- # Mode
- k = nuke.Enumeration_Knob('mode', 'mode', MODES)
- n.addKnob(k)
- k.setTooltip('MergeBackIntoStream: Shuffles the resolved aovs, applies the grading options and merges the result back to main comp stream\n\nSelectOnly: Just shuffles the resolved aovs and adds them together.\n\nLayerContactSheet: Displays the LayerContactSheet with layer names. Note. You need to Press Set in order for this to work. An empty Pattern is possible')
- n.knob('mode').clearFlag(nuke.STARTLINE)
-
- # refresh again
- n.knob('pattern').setValue('*key*')
- n.knob('pattern').setValue(PATTERNDEFAULT)
- tmp = n.knob('resolved').getValue()
-
- global INIT_DONE
- INIT_DONE = True
- return None
-
-
- def resetValues(n):
- n['exposure'].setValue(0)
- n['blackpoint'].setValue(0)
- n['whitepoint'].setValue(1)
- n['saturation'].setValue(1)
- n['black'].setValue(0)
- n['multiply'].setValue([1, 1, 1])
- n['gamma'].setValue(1)
- n['compensate'].setValue(True)
-
-
- def resolvePattern(n, pattern, pattern_exclude):
- if pattern == "":
- return None
-
- channels = n.channels()
- layers = list(set([c.split('.')[0] for c in channels]))
- layers.sort()
-
- matchChannels = []
- ignoreChannels = []
- ignoreChannels2 = []
-
- # pattern
- for p in pattern.split(' '):
- matchChannels += (fnmatch.filter(layers, p))
- # excludes
- if p[0] == '!' or p[0] == '^':
- ignoreChannels += (fnmatch.filter(layers, p[1:]))
-
- # pattern exclude
- for p in pattern_exclude.split(' '):
- ignoreChannels2 += (fnmatch.filter(layers, p))
-
- matchChannels = list(set(matchChannels) - set(ignoreChannels) - set(ignoreChannels2))
- matchChannels.sort()
-
- return matchChannels
-
-
- def updatePattern(n):
-
- V_OFFSET = 250
-
- # n = node
- pattern = n['pattern'].value()
- pattern_exclude = n['pattern_exclude'].value()
- resolved = resolvePattern(n, pattern,pattern_exclude)
-
- # create nodes
- # input and output of Group
- input = nuke.toNode('Input1')
- output = nuke.toNode('Output1')
-
- # delete old nodes
- g = nuke.toNode(n.name())
- #oldNodes = [i for i in g.nodes() if '__' in i['name'].value()]
- oldNodes = [i for i in g.nodes() if '__' in i['label'].value()]
-
- for node in oldNodes:
- nuke.delete(node)
-
- # dot input
- dot_input = nuke.nodes.Dot(xpos=input.xpos() , ypos=input.ypos()+100)
- dot_input['name'].setValue('dot_input__')
- dot_input['label'].setValue('dot_input__')
- #dot_input['note_font_size'].setValue(25)
- # connect to the input1 node
-
- # dot input 2
- dot_input2 = nuke.nodes.Dot(xpos=dot_input.xpos()+1500 , ypos=dot_input.ypos())
- dot_input2['name'].setValue('dot_input2__')
- dot_input2['label'].setValue('dot_input2__')
- #dot_input2['note_font_size'].setValue(25)
- # connect to the input1 node
-
- # unpremult
- unpremult = nuke.nodes.Unpremult(xpos=dot_input.xpos()+700 , ypos=dot_input.ypos() )
- #unpremult['name'].setValue('unpremult_node__')
- unpremult['label'].setValue('unpremult__')
-
- # dot resolved
- dot_resolved = nuke.nodes.Dot(xpos=dot_input.xpos() , ypos=dot_input.ypos() + V_OFFSET)
- dot_resolved['name'].setValue('dot_resolved__')
- dot_resolved['label'].setValue('dot_resolved__')
- #dot_resolved['note_font_size'].setValue(25)
-
- # dot resolved2
- dot_resolved2 = nuke.nodes.Dot(xpos=dot_resolved.xpos() - 100, ypos=dot_resolved.ypos())
- dot_resolved2['name'].setValue('dot_resolved2__')
- dot_resolved2['label'].setValue('dot_resolved2__')
- #dot_resolved2['note_font_size'].setValue(25)
-
- # dot resolved3
- dot_resolved3 = nuke.nodes.Dot(xpos=dot_resolved2.xpos(), ypos=dot_resolved.ypos() + V_OFFSET)
- dot_resolved3['name'].setValue('dot_resolved3__')
- dot_resolved3['label'].setValue('dot_resolved3__')
- #dot_resolved3['note_font_size'].setValue(25)
-
- # merge from
- merge_from = nuke.nodes.Merge2(xpos=dot_input.xpos()+500 , ypos=dot_input.ypos() )
- merge_from['operation'].setValue('from')
- merge_from['name'].setValue('merge_from__')
- merge_from['label'].setValue('merge_from__')
-
- # exposure
- exposure = nuke.nodes.EXPTool(xpos=dot_resolved.xpos() , ypos=dot_resolved.ypos() + V_OFFSET)
- exposure['name'].setValue('exposure__')
- exposure['label'].setValue('exposure__')
-
- # grade
- grade = nuke.nodes.Grade(xpos=exposure.xpos() , ypos=exposure.ypos() + V_OFFSET)
- grade['name'].setValue('grade__')
- grade['label'].setValue('grade__')
-
- # saturation
- saturation = nuke.nodes.Saturation(xpos=grade.xpos() , ypos=exposure.ypos() + V_OFFSET)
- saturation['name'].setValue('saturation__')
- saturation['label'].setValue('saturation__')
-
- # merge plus
- merge_plus = nuke.nodes.Merge2(xpos=saturation.xpos() , ypos=saturation.ypos() + V_OFFSET)
- merge_plus['operation'].setValue("plus")
- merge_plus['name'].setValue('merge_plus__')
- merge_plus['label'].setValue('merge_plus__')
-
- # dot input From
- dot_input_from = nuke.nodes.Dot(xpos=merge_from.xpos() , ypos=merge_plus.ypos())
- dot_input_from['name'].setValue('dot_input_from__')
- dot_input_from['label'].setValue('dot_input_from__')
- #dot_input_from['note_font_size'].setValue(25)
-
- # contact_sheet_all
- contact_sheet_all = nuke.nodes.LayerContactSheet(xpos=merge_plus.xpos() +250 , ypos=merge_plus.ypos() + 200)
- contact_sheet_all['name'].setValue('contact_sheet__')
- contact_sheet_all['label'].setValue('contact_sheet__')
-
- # switch
- switch = nuke.nodes.Switch(xpos=merge_plus.xpos() , ypos=merge_plus.ypos() + V_OFFSET)
- switch['name'].setValue('switch__')
- switch['label'].setValue('switch__')
-
- # premult
- premult = nuke.nodes.Premult(xpos=switch.xpos()+50 , ypos=switch.ypos() )
- #premult['name'].setValue('premult_node__')
- premult['label'].setValue('premult_node__')
-
- # dot output
- dot_output = nuke.nodes.Dot(xpos=dot_input.xpos() , ypos=dot_input.ypos() + V_OFFSET)
- dot_output['name'].setValue('dot_output__')
- dot_output['label'].setValue('dot_output__')
- #dot_output['note_font_size'].setValue(25)
-
- # create new nodes
- i = 1
- j = 0
- offset = 100
-
- merge_resolved = None
- if resolved:
- if len(resolved) > 0:
- for r in resolved:
- # shuffle
- shuffle = nuke.nodes.Shuffle(xpos=dot_input.xpos() - (len(resolved)/2)*offset + (i * offset), ypos=dot_input.ypos() + offset)
- shuffle['in'].setValue(resolved[i - 1])
- shuffle['in2'].setValue('rgba')
- shuffle['out'].setValue('rgb')
- shuffle['name'].setValue('shuffle__' + str(i))
- # set label of aov
- shuffle['label'].setValue(resolved[i - 1] + '__')
- # connect to the dot dot_input
- shuffle.setInput(0, dot_input)
-
- # create plus
- if i == 1:
- merge_resolved = nuke.nodes.Merge2(xpos=dot_input.xpos(), ypos=dot_output.ypos() + 50)
- merge_resolved['operation'].setValue("plus")
- merge_resolved['name'].setValue("merge_resolved__")
- merge_resolved['label'].setValue("merge_resolved__")
-
- # connect plus
- # skip Mask Input
- if j==2:
- j+=1
- # connect input
- merge_resolved.setInput(j, shuffle)
-
- # next please
- i += 1
- j += 1
-
- # connect to the input1 node
- unpremult.setInput(0,merge_resolved)
- dot_resolved.setInput(0, unpremult)
-
- else:
- # shuffle
- shuffle = nuke.nodes.Shuffle(xpos=dot_input.xpos() + (i * offset), ypos=dot_input.ypos() + offset)
- # create black in rgb and a
- shuffle['in'].setValue('none')
- shuffle['in2'].setValue('none')
- shuffle['out'].setValue('rgb')
- shuffle['name'].setValue('shuffle_empty__')
- shuffle['label'].setValue('shuffle_empty__')
-
- shuffle.setInput(0, dot_input)
-
- # remove old input connections
- #for r in range(output.inputs()):
- # output.setInput(r, None)
-
- # connect to the input1 node
- dot_resolved.setInput(0, shuffle)
-
- # connect the nodes
- dot_input.setInput(0, input)
- dot_input2.setInput(0, dot_input)
- dot_input_from.setInput(0, merge_from)
- dot_resolved2.setInput(0, dot_resolved)
- dot_resolved3.setInput(0, dot_resolved2)
- merge_plus.setInput(1, saturation)
- merge_plus.setInput(0, dot_input_from)
- grade.setInput(0, exposure)
- saturation.setInput(0, grade)
- exposure.setInput(0, dot_resolved)
- merge_from.setInput(0, dot_input2)
- merge_from.setInput(1, dot_resolved)
- contact_sheet_all.setInput(0, dot_input2)
- switch.setInput(0, premult)
- switch.setInput(1, contact_sheet_all)
- switch.setInput(2, dot_resolved3)
- premult.setInput(0,merge_plus)
- dot_output.setInput(0,switch)
- output.setInput(0, dot_output)
-
- # link the nodes
- exposure['mode'].setValue('Stops')
- exposure['gang'].setValue(0)
- exposure['red'].setExpression('parent.exposure')
- exposure['green'].setExpression('parent.exposure')
- exposure['blue'].setExpression('parent.exposure')
- unpremult['disable'].setExpression('parent.unpremult == 1 ? 0 :1')
- premult['disable'].setExpression('parent.unpremult == 1 ? 0 :1')
-
- grade['multiply'].setValue([1,1,1,1])
- grade['multiply'].setExpression('parent.multiply.r',0)
- grade['multiply'].setExpression('parent.multiply.g',1)
- grade['multiply'].setExpression('parent.multiply.b',2)
-
- grade['blackpoint'].setValue([0,0,0,0])
- grade['blackpoint'].setExpression('parent.blackpoint.r',0)
- grade['blackpoint'].setExpression('parent.blackpoint.g',1)
- grade['blackpoint'].setExpression('parent.blackpoint.b',2)
-
- grade['whitepoint'].setValue([1,1,1,1])
- grade['whitepoint'].setExpression('parent.whitepoint.r',0)
- grade['whitepoint'].setExpression('parent.whitepoint.g',1)
- grade['whitepoint'].setExpression('parent.whitepoint.b',2)
-
- grade['black'].setValue([0,0,0,0])
- grade['black'].setExpression('parent.black.r',0)
- grade['black'].setExpression('parent.black.g',1)
- grade['black'].setExpression('parent.black.b',2)
-
- grade['white'].setValue([1, 1, 1, 1])
- grade['white'].setExpression('parent.compensate == 1 ? 1/((parent.multiply.r+parent.multiply.g+parent.multiply.b)/3) : 1')
- #grade['white'].setExpression(['parent.compensate == 1 ? 1/((parent.multiply.r+parent.multiply.g+parent.multiply.b)/3) : 1,parent.compensate == 1 ? 1/((parent.multiply.r+parent.multiply.g+parent.multiply.b)/3) : 1,parent.compensate == 1 ? 1/((parent.multiply.r+parent.multiply.g+parent.multiply.b)/3) : 1,1'])
- grade['gamma'].setExpression('parent.gamma')
-
- saturation['saturation'].setExpression('parent.saturation')
-
- contact_sheet_all['width'].setExpression('parent.width')
- contact_sheet_all['height'].setExpression('parent.height')
- contact_sheet_all['showLayerNames'].setValue(1)
- # again. Weird Update Issues
- contact_sheet_all['showLayerNames'].setExpression('parent.mode == 0 ? 0 :1')
- switch['which'].setExpression('parent.mode == 0 ? 0 :(parent.mode == 1 ? 2 : 1)')
-
- # arrange the nodes
- dot_input.setXYpos(input.xpos(), input.ypos() + 100)
- if merge_resolved:
- merge_resolved.setXYpos(input.xpos(), input.ypos() + 350)
- unpremult.setXYpos(merge_resolved.xpos(), merge_resolved.ypos() + 75)
-
- dot_resolved.setXYpos(input.xpos(), input.ypos() + 500)
- dot_resolved2.setXYpos(dot_resolved.xpos()-250, dot_resolved.ypos())
- dot_resolved3.setXYpos(dot_resolved2.xpos(), dot_resolved2.ypos() + 500)
- exposure.setXYpos(dot_resolved.xpos(), dot_resolved.ypos()+150)
- grade.setXYpos(exposure.xpos(), exposure.ypos() + 150)
- saturation.setXYpos(grade.xpos(), grade.ypos() + 150)
- merge_plus.setXYpos(saturation.xpos(), saturation.ypos() + 150)
- premult.setXYpos(merge_plus.xpos(), merge_plus.ypos() + 75)
- switch.setXYpos(premult.xpos(), premult.ypos() + 150)
- dot_output.setXYpos(switch.xpos(), switch.ypos() + 150)
- output.setXYpos(dot_output.xpos(), dot_output.ypos() + 150)
- merge_from.setXYpos(dot_input2.xpos(), dot_resolved.ypos())
- dot_input_from.setXYpos(merge_from.xpos(), merge_plus.ypos())
-
- n['label'].setValue('[value pattern]')
- return None
|