|
import nuke, nukescripts, os |
|
|
|
|
|
''' |
|
## Hidden Input Handler |
|
# Add these lines to your menu.py: |
|
|
|
import hidden_input_handler |
|
nuke.toolbar('Nodes').addCommand('Other/PostageStamp', 'hidden_input_handler.create()', 'alt+shift+p') |
|
nuke.menu("Nuke").addCommand('Edit/Cut', lambda: hidden_input_handler.cut(), 'ctrl+x') |
|
nuke.menu("Nuke").addCommand('Edit/Copy', lambda: hidden_input_handler.copy(), 'ctrl+c') |
|
nuke.menu("Nuke").addCommand('Edit/Paste', lambda: hidden_input_handler.paste(), 'ctrl+v') |
|
nuke.menu("Nuke").addCommand('Edit/PasteNormal', lambda: nuke.nodePaste(nukescripts.cut_paste_file()), 'ctrl+alt+shift+v', index=6) # In case you need to paste with the default treatment of hidden inputs |
|
''' |
|
|
|
grid_x = int(nuke.toNode('preferences').knob('GridWidth').value()) |
|
grid_y = int(nuke.toNode('preferences').knob('GridHeight').value()) |
|
|
|
|
|
def copy(): |
|
#hidden_input_nodes = [n for n in nuke.selectedNodes() if 'PostageStamp' in n.Class()] |
|
hidden_input_nodes = [n for n in nuke.selectedNodes() if 'hide_input' in n.knobs() and n['hide_input'].value()] |
|
for ps in hidden_input_nodes: |
|
input_node = ps.input(0) |
|
if input_node: |
|
if not 'input_node' in ps.knobs(): |
|
ps.addKnob(nuke.String_Knob('input_node', 'input_node', input_node.fullName())) |
|
if input_node: |
|
ps['input_node'].setValue(input_node.fullName()) |
|
else: |
|
ps['input_node'].setValue('') |
|
if nuke.selectedNodes(): |
|
nuke.nodeCopy(nukescripts.cut_paste_file()) |
|
return |
|
|
|
def cut(): |
|
hidden_input_nodes = [n for n in nuke.selectedNodes() if 'hide_input' in n.knobs() and n['hide_input'].value()] |
|
for ps in hidden_input_nodes: |
|
input_node = ps.input(0) |
|
if input_node: |
|
if not 'input_node' in ps.knobs(): |
|
ps.addKnob(nuke.String_Knob('input_node', 'input_node', input_node.fullName())) |
|
if input_node: |
|
ps['input_node'].setValue(input_node.fullName()) |
|
else: |
|
ps['input_node'].setValue('') |
|
if nuke.selectedNodes(): |
|
nuke.nodeCopy(nukescripts.cut_paste_file()); nukescripts.node_delete(popupOnError=True) |
|
return |
|
|
|
def paste(): |
|
nuke.nodePaste(nukescripts.cut_paste_file()) |
|
hidden_input_nodes = [n for n in nuke.selectedNodes() if 'hide_input' in n.knobs() and n['hide_input'].value()] |
|
for ps in hidden_input_nodes: |
|
if 'input_node' in ps.knobs(): |
|
ps.setInput(0, nuke.toNode(ps['input_node'].getValue())) |
|
return |
|
|
|
|
|
def create(): |
|
## Creates a postage stamp for each selected node |
|
nodes = nuke.selectedNodes() |
|
# Deselect all nodes |
|
for n in nuke.allNodes(): |
|
n.setSelected(False) |
|
created_ps = [] |
|
for target_node in nodes: |
|
ps = nuke.createNode("Dot", "hide_input 1", inpanel=False) |
|
created_ps.append(ps) |
|
if not ps.setInput(0, target_node): |
|
nuke.delete(ps) |
|
nuke.message('Cannot connect PostageStamp to this node!\n\nIs it Deep or 3D?') |
|
return |
|
# Set up PostageStamp |
|
target_nodename = target_node.name().replace(" ", "\\ ") |
|
target_node = nuke.toNode(target_nodename) |
|
# Uses expression links |
|
# if target_node.Class() == 'Read': |
|
# ps.knob('label').setValue('[value {0}.label]\\n[file tail [value [topnode].file]]'.format(target_nodename)) |
|
# elif target_node['label'].value(): |
|
# ps.knob('label').setValue('[value this.input0.label]'.format(target_nodename)) |
|
# else: |
|
# ps.knob('label').setValue('[value this.input0.name]'.format(target_nodename)) |
|
|
|
# Bakes label values onto nodes (if you change the input it will be out of date, but will be faster in big scripts) |
|
if target_node.Class() == 'Read': |
|
#ps.knob('label').setValue( nuke.tcl("value [topnode {0}].label".format(ps.fullName())) + '\n' + nuke.tcl("file tail [value [topnode {0}].file]".format(ps.fullName()))) |
|
ps.knob('label').setValue("| " + target_node['label'].getValue() + '\n' + os.path.basename(target_node['file'].getValue())) |
|
#ps.knob('label').setValue(nuke.tcl("value {0}.label]\\n[file tail [value {0}.file]".format(target_node.fullName()))) |
|
#ps.knob('label').setValue(target_node['file'].getValue()) |
|
# ps.knob('label').setValue('[value {0}.label]\\n[file tail [value [topnode].file]]'.format(target_nodename)) |
|
elif target_node['label'].value(): |
|
ps.knob('label').setValue("| " + target_node['label'].getValue()) |
|
#ps.knob('label').setValue('[value this.input0.label]'.format(target_nodename)) |
|
else: |
|
ps.knob('label').setValue("| " + target_node.name()) |
|
#ps.knob('label').setValue('[value this.input0.name]'.format(target_nodename)) |
|
|
|
|
|
## If you instead prefer to label the PS nodes with the topnode info |
|
# topnode = nuke.toNode(nuke.tcl("full_name [topnode %s]" % target_nodename)) |
|
# if topnode.Class() == 'Read': |
|
# ps.knob('label').setValue('{0}\\n[file tail [value [topnode].file]]'.format(ps.knob('label').value())) |
|
# elif topnode['label'].value(): |
|
# ps.knob('label').setValue('[file tail [value [topnode].label]]') |
|
# else: |
|
# ps.knob('label').setValue('[file tail [value [topnode].name]]') |
|
|
|
#ps.addKnob(nuke.Tab_Knob('Set Input', "Input")) |
|
#ps.addKnob(nuke.PyScript_Knob("set_input", "Set Input To Selected Node")) |
|
#ps.knob('set_input').setCommand("n = nuke.thisNode()\nn.setInput(0, nuke.selectedNode())\nn['label'].setValue('[file tail [value [topnode].file]]')") |
|
#ps.knob('set_input').setTooltip('Set the input to the selected node.') |
|
#ps.addKnob(nuke.String_Knob('input_node', 'input_node', ps.input(0).fullName())) |
|
ps.setXYpos(target_node.xpos()-grid_x*2, target_node.ypos()-grid_y*0) |
|
nuke.autoplaceSnap(ps) |
|
# Select all created postagestamps |
|
for n in created_ps: |
|
n.setSelected(True) |
|
|
|
|
Description
A python tool to enhance the default behavior when copying / cutting and pasting nodes with hidden inputs. Instead of the pasted copy becoming disconnected, the node with the hidden input is connected to the node that the original was connected to.
There is also a shortcut included to create a dot node with a hidden input connected to the selected node. This is useful mainly for situations where you have a single roto that you need to use in many places in the script, or if you need to link many scanline renders to a single camera and layout resolution node, so that they can be easily swapped if you switch to a different shot.
Please don't put hidden inputs everywhere in your script. Comp responsibly!