Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
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.
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)
Owner

jedypod commented Jan 31, 2017

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment