Nuke Timeout – EP07 – Copy/Paste With Inputs

Sometimes I find myself in a situation where I would like to duplicate a specific set of nodes while re-using the same inputs on them.
A simple copy/paste forces me to manually connect all the dependencies that I didn’t select. I will show you a simple solution to accomplish this automatically with the help of some python.

First of all, we have to know the python command that Nuke uses to copy and paste node selections.
For that I’m importing the nuke module.

import nuke

It’s not so important for an open Nuke session, since the module is loaded automatically, but we will need it once we tell Nuke to load our python script from an external source while starting the software.

# With the following command we can copy a selection into the clipboard:

nuke.nodeCopy(‘%clipboard%’)


# For pasting we use:

nuke.nodePaste(‘%clipboard%’)

My initial idea was to store our node selection in a list before copying it. When we then bring in the duplicated nodes from our clipboard, they will be selected – so we can store them in a second list.
Now we could walk through that new list and cross-reference it with the first list, in order to get the inputs connected again.

This approach is problematic though.
Nuke doesn’t paste the nodes in the same order they were selected for copying – meaning there is no way to figure out in which order the user selected the nodes before storing them in the clipboard.

We have to come up with another solution.
How can we make sure that the pasted nodes know which nodes they have to connect with? Well, we simply let them carry over that information inside themselves.
Let’s set up a little function.

def copy_with_inputs():

    copy_nodes = nuke.selectedNodes()

    for node in copy_nodes:
        collected_dependencies = []
        temp_user_tab = nuke.Tab_Knob('temp', 'Temp')
        temp_user_knob = nuke.Multiline_Eval_String_Knob('dependencies', 'Dependencies')
        node.addKnob(temp_user_tab)
        node.addKnob(temp_user_knob)

        for i in range(node.inputs()):
            input_node = node.input(i).name()
            collected_dependencies.append(input_node)
            separator = ","

        node.knob('dependencies').setValue(separator.join(collected_dependencies))

   nuke.nodeCopy('%clipboard%')

copy_with_inputs()

I’m collecting my selection in a list.
I will use a for loop to go through every single node. I define an empty list (collected_dependencies) first that will later store all of the node’s connections.
Now I set up a temp user tab, as well as a multiline knob, that will print the dependencies.
With the inputs method, I can check how many inputs of a node are connected to some other node. I use this information for the range command to go through and check every one of those inputs and add the name of the connected node to our collected_dependencies list.
If I would simply print that list into our text knob later, I would also print the brackets which are characteristic for lists.
That’s why I’m using the join method. This method joins all elements of the list into one string – but I’m using a separator to add commas in between.
I’ll paste this string into the temp user text knob.
Finally I perform the nodeCopy command and run the function.

As we can see, the selected nodes now show our temp user knobs including the names of its respective connections.

If I paste the nodes from our clipboard, the duplicates carry over this information.
Of course I want to get rid of those knobs on both, copy and paste nodes, eventually.
So let’s adjust our code.

I’ve added some additional sections to our previous script (printed in bold):

import nuke

def copy_with_inputs():

    copy_nodes = nuke.selectedNodes()

    # if no nodes selected, show Nuke message
    if len(copy_nodes) == 0:
        nuke.message('No node selected.')
    else:

        for node in copy_nodes:
            collected_dependencies = []
            temp_user_tab = nuke.Tab_Knob('temp', 'Temp')
            temp_user_knob = nuke.Multiline_Eval_String_Knob('dependencies', 'Dependencies')
            node.addKnob(temp_user_tab)
            node.addKnob(temp_user_knob)

            for i in range(node.inputs()):

                # if a specific input is not connected, store the input name as "none" in the list
                try:
                    input_node = node.input(i).name()
                except:
                    input_node = "none"
                collected_dependencies.append(input_node)
                separator = ","

            node.knob('dependencies').setValue(separator.join(collected_dependencies))

        nuke.nodeCopy('%clipboard%')

        
        # removing temp tab and knob
        for node in copy_nodes:
            knobs = node.knobs()
            node.removeKnob(knobs['dependencies'])
            node.removeKnob(knobs['temp'])

Now we have to create our function to paste our nodes and set the connections right.

def paste_with_inputs():

    nuke.nodePaste('%clipboard%')
    paste_nodes = nuke.selectedNodes()

    # read out content of temp user knob to see how many nodes the original node was connected to & their names
    for node in paste_nodes:

        # checking if temp user tab/knob are present, otherwise stop script and finish with simple "paste"
        if node.knob('dependencies'):
            collected_dependencies = node.knob('dependencies').getValue().split(",")

            # iterating over dependencies and setting the connections
            for i, x in enumerate(collected_dependencies):
                if not node.input(i):
                    node.setInput(i, nuke.toNode(x))

            # removing temp tab and knob
            knobs = node.knobs()
            node.removeKnob(knobs['dependencies'])
            node.removeKnob(knobs['temp'])

        else:
            continue

I’ll save both functions in one file called copy_paste_with_inputs.py and the only thing left to do is to add it to our Nuke menu.py.
Don’t forget to import the script a.k.a. module we just saved. Let’s also assign some shortcuts, in this case Ctrl+Shift+c and Ctrl+Shift+v.

import copy_paste_with_inputs

nuke_menu = nuke.menu('Nuke')
split_nuke_menu = nuke_menu.addMenu('Split The Diff')
split_nuke_menu.addCommand('Copy With Inputs', 'copy_paste_with_inputs.copy_with_inputs()', 'Ctrl+Shift+c')
split_nuke_menu.addCommand('Paste With Inputs', 'copy_paste_with_inputs.paste_with_inputs()', 'Ctrl+Shift+v')

Back to Nuke:

Our menu commands have been successfully added.

Let’s select the nodes, ctrl+shift+c and ctrl+shift+v.

The nodes are copied over and their inputs connected to the respective nodes.

Let’s check our fail prevention. I have nothing selected. Ctrl+shift+c – we get the error message.

I hope you’ve enjoyed that little project. You can download the python script here: copy_paste_with_inputs