With this code, you can automatically create dots at a perfectly straight angle between the two nodes you have selected. You can align it in X to the top or the bottom node, depending on what you want. It doesn't matter the order of your selection. For X aligned to the bottom node of my selection I use ctrl+., and for X aligned to the top node I use shift+..

This code is particularly useful when you are connecting nodes that are far away in the Node Graph.
Expand Auto Dot
import nuke
def lowDot():
def XYCheck():
topNode = None
sideNode = None
# Check if Y and X positions are the same
for i in nuke.selectedNodes():
if topNode is None:
topNodeName = i['name'].getValue()
topNode = i['ypos'].getValue() + (i.screenHeight()/2)
elif i['ypos'].getValue() + (i.screenHeight()/2) < topNode:
topNodeName = i['name'].getValue()
topNode = i['ypos'].getValue() + (i.screenHeight()/2)
elif i['ypos'].getValue() + (i.screenHeight()/2) == topNode:
nuke.message('Both nodes have the same Y position. No dot created.')
return
if sideNode is None:
sideNode = i['xpos'].getValue() + (i.screenWidth()/2)
elif i['xpos'].getValue() + (i.screenWidth()/2) < sideNode:
sideNode = i['xpos'].getValue() + (i.screenWidth()/2)
elif i['xpos'].getValue() + (i.screenWidth()/2) == sideNode:
nuke.message('Both nodes have the same X position. No dot created.')
return
for i in nuke.selectedNodes():
if i.maxInputs() == 0 and i['name'].getValue() != topNodeName:
nuke.message('Lowest selected node does not have an input to connect. No dot created.')
return
createLowDot()
def createLowDot():
topNode = None
# Check highest Y position
for i in nuke.selectedNodes():
if topNode is None:
topNode = i['ypos'].getValue()
elif i['ypos'].getValue() < topNode:
topNode = i['ypos'].getValue()
sel = nuke.selectedNodes()
for i in sel:
# If it is the lowest in Y
if not i['ypos'].getValue() == topNode:
# We will connect the dot here, so we save its
# name and Y position for later.
dotOutput = i['name'].getValue()
sideNodePos = i['ypos'].getValue()
i['selected'].setValue(False)
# If the node is the highest in Y
if i['ypos'].getValue() == topNode:
# Check if it is connected to the lowest one
existingConnections = []
topNodeXPos = i['xpos'].getValue()
i['selected'].setValue(True)
# Save the name of the node for later
dotInput = i['name'].getValue()
for conn in nuke.selectedNode().dependent():
connName = conn['name'].getValue()
existingConnections.append(connName)
i['selected'].setValue(False)
# We store some sizes and positions that we will use later to
# move the dot to an approximate position.
dotSize = nuke.toNode('preferences').knob('dot_node_scale').value()
dotCenter = (12*dotSize)/2 # 12 is width and height by default
dotOutWidthCenter = nuke.toNode(str(dotOutput)).screenWidth() / 2
topNodeXPos = topNodeXPos + (dotOutWidthCenter - dotCenter)
dotOutHeightCenter = nuke.toNode(str(dotOutput)).screenHeight() / 2
dotInWidthCenter = nuke.toNode(str(dotInput)).screenWidth() / 2
if not nuke.toNode(str(dotOutput)).Class() == 'Dot':
sideNodePos = sideNodePos + (dotOutHeightCenter - dotCenter)
else:
topNodeXPos = topNodeXPos + (dotInWidthCenter - dotCenter)
if nuke.toNode(str(dotInput)).Class() == 'Dot':
topNodeXPos = topNodeXPos - (dotOutWidthCenter - dotCenter)
# If we found both high and low nodes are connected
if existingConnections != []:
nuke.toNode(dotOutput)['selected'].setValue(True)
# We create an empty list and populate it with the lowest node
# dependencies names (nodes connected to its inputs).
dependenciesList = []
for node in nuke.selectedNode().dependencies():
depName = node.name()
dependenciesList.append(depName)
# We check the number of the highest input connected and use
# it to populate an empty list with 1 (if the input in that
# position is connected) and 0 (if it is not connected).
# For example, if a Merge has A connected, but not B or mask,
# the list would be [0,1].
maxInputConnected = nuke.selectedNode().inputs()
connectedList = []
for i in range(maxInputConnected):
connResult = 1 if nuke.selectedNode().input(i) else 0
connectedList.append(connResult)
# We also save the number of dependencies found
depNumber = len(connectedList)
# Now we have to check what input is connected to the
# highest node. To do that we will create two different
# counters: one for the number of dependencies and
# another one for the number of connections. A node can
# have two dependencies and three connections, example:
# a Merge with B and Mask connected, but not A, will
# have two dependencies (or one if B and Mask are
# connected to the same node) and three connections (A
# counts as a connection even if it is not connected).
depCounter = 0
connCounter = 0
while connCounter <= (depNumber-1):
# Using connectedList we created before, we'll add
# the string 'Nope' as an element to later match
# the node name to the correct input number.
if connectedList[connCounter] == 1:
depCounter = depCounter + 1
connCounter = connCounter + 1
elif connectedList[depCounter] == 0:
dependenciesList.insert(depCounter, 'Nope')
connCounter = connCounter + 1
# Now both dependenciesList and connectedList have the
# same number of elements, so we just need to find the
# position of the highest node in dependenciesList to know
# to what input of the lowest node it's connected to.
try:
inputNumber = dependenciesList.index(dotInput)
except ValueError:
maxInputsNumber = nuke.toNode(dotOutput).maxInputs()
if depNumber == maxInputsNumber:
try:
inputNumber = connectedList.index(0)
except ValueError:
inputNumber = 0
else:
# Find the first position with a 0 in connectedList, and that
# would be the first available input to connect to the dot.
try:
inputNumber = connectedList.index(0)
except ValueError:
if maxInputsNumber > depNumber+1:
inputNumber = depNumber
else:
inputNumber = 0
nuke.toNode(dotOutput)['selected'].setValue(False)
# We create our dot on the positions we calculated and
# select it to connect the input we checked before.
nuke.nodes.Dot(xpos=topNodeXPos, ypos=sideNodePos, selected=1).setInput(0, nuke.toNode(dotInput)) #for some reason this step takes longer than expected
nuke.toNode(dotOutput).setInput(inputNumber, nuke.selectedNode())
# Now we will check if other nodes were connected to the
# dot input,because those will be connected to the new dot
# for esthetic purposes. First we look for all the nodes
# sharing the same center as our new dot.
sameCenterList = []
for i in nuke.allNodes():
# We make sure to remove the new dot and its input from
# these next steps.
if not i['selected'].getValue() == True and i['name'].getValue() != dotInput:
nodeName = i['name'].getValue()
nodeCenter = i['xpos'].getValue() + nuke.toNode(nodeName).screenWidth() / 2
if nodeCenter == topNodeXPos + dotCenter:
sameCenterList.append(nodeName)
# Now we have a list on nodes sharing the same X position.
# Using our new list, we are going to check if those nodes are
# also connected to the dot input.
depList = []
for node in sameCenterList:
for i in nuke.toNode(node).dependencies():
nodeName = i.name()
if nodeName == dotInput:
depList.append(node)
# We have removed all the nodes sharing the X position that were
# not connected to the dot input.
for i in depList:
# Following the same method we did before, we fill a list
# with the names of all the dependencies of the nodes sharing
# X position with the new dot and also conected to its input.
dependenciesList = []
for node in nuke.toNode(i).dependencies():
depName = node.name()
dependenciesList.append(depName)
# Another list with 1 (if the input is connected) and 0
# (if it is not connected). Ex: if a Merge has A connected,
# but not B or mask, the list would be [0,1].
maxInputConnected = nuke.toNode(i).inputs()
connectedList = []
for x in range(maxInputConnected):
connResult = 1 if nuke.toNode(i).input(x) else 0
connectedList.append(connResult)
# We also save the number of dependencies found
depNumber = len(connectedList)
# Now we have to check what input is connected to the
# dot input. To do that we will create two different
# counters: one for the number of dependencies and
# another one for the number of connections
depCounter = 0
connCounter = 0
while connCounter <= (depNumber-1):
# Using connectedList we created before, we'll add
# the string 'Nope' as an element to later match
# the node name to the correct input number.
if connectedList[connCounter] == 1:
depCounter = depCounter + 1
connCounter = connCounter + 1
elif connectedList[depCounter] == 0:
dependenciesList.insert(depCounter, 'Nope')
connCounter = connCounter + 1
# Now both dependenciesList and connectedList have the
# same number of elements, so we just need to find the
# position of the highest node in dependenciesList to know
# to what input of the lowest node it's connected to.
try:
inputNumber = dependenciesList.index(dotInput)
except ValueError:
maxInputsNumber = nuke.toNode(i).maxInputs()
if depNumber == maxInputsNumber:
inputNumber = connectedList.index(0)
elif depNumber == maxInputsNumber-1:
inputNumber = depNumber
else:
# Find the first position with a 0 in connectedList, and that
# would be the first available input to connect to the dot.
try:
inputNumber = connectedList.index(0)
except ValueError:
if maxInputsNumber > depNumber+1:
inputNumber = depNumber
else:
inputNumber = 0
nuke.toNode(i).setInput(inputNumber, nuke.selectedNode())
for i in nuke.allNodes():
i['selected'].setValue(False)
# If nodes are not connected, we will find what is the first input
# of the lowest node that is not connected.
else:
maxInputConnected = nuke.toNode(dotOutput).inputs()
connectedList = []
for i in range(maxInputConnected):
connResult = 1 if nuke.toNode(dotOutput).input(i) else 0
connectedList.append(connResult)
# We also save the number of dependencies found to check if it
# is the max allowed.
depNumber = len(connectedList)
maxInputsNumber = nuke.toNode(dotOutput).maxInputs()
nuke.toNode(str(dotInput))['selected'].setValue(True)
# We create our dot on the positions we calculated and
# select it to connect the input we checked before.
nuke.nodes.Dot(xpos=topNodeXPos, ypos=sideNodePos, selected=1).setInput(0, nuke.toNode(dotInput)) #for some reason this step takes longer than expected
if depNumber == maxInputsNumber:
try:
firstFreeInput = connectedList.index(0)
nuke.toNode(dotOutput).setInput(firstFreeInput, nuke.selectedNode())
except ValueError:
nuke.toNode(dotOutput).setInput(0, nuke.selectedNode())
elif depNumber == maxInputsNumber-1:
try:
firstFreeInput = connectedList.index(0)
nuke.toNode(dotOutput).setInput(firstFreeInput, nuke.selectedNode())
except ValueError:
nuke.toNode(dotOutput).setInput(depNumber, nuke.selectedNode())
else:
# Find the first position with a 0 in connectedList, and that
# would be the first available input to connect to the dot.
try:
firstFreeInput = connectedList.index(0)
nuke.toNode(dotOutput).setInput(firstFreeInput, nuke.selectedNode())
except ValueError:
if maxInputsNumber > depNumber+1:
nuke.toNode(dotOutput).setInput(depNumber, nuke.selectedNode())
else:
nuke.toNode(dotOutput).setInput(0, nuke.selectedNode())
for i in nuke.allNodes():
i['selected'].setValue(False)
selNodesList = []
for i in nuke.selectedNodes():
selNodesNames = i['name'].getValue()
selNodesList.append(selNodesNames)
if len(selNodesList) != 2:
nuke.message('Please, select two nodes to run this action.')
else:
XYCheck()
def highDot():
def XYCheck():
topNode = None
sideNode = None
# Check if Y and X positions are the same
for i in nuke.selectedNodes():
if topNode is None:
topNodeName = i['name'].getValue()
topNode = i['ypos'].getValue() + (i.screenHeight()/2)
elif i['ypos'].getValue() + (i.screenHeight()/2) < topNode:
topNodeName = i['name'].getValue()
topNode = i['ypos'].getValue() + (i.screenHeight()/2)
elif i['ypos'].getValue() + (i.screenHeight()/2) == topNode:
nuke.message('Both nodes have the same Y position. No dot created.')
return
if sideNode is None:
sideNode = i['xpos'].getValue() + (i.screenWidth()/2)
elif i['xpos'].getValue() + (i.screenWidth()/2) < sideNode:
sideNode = i['xpos'].getValue() + (i.screenWidth()/2)
elif i['xpos'].getValue() + (i.screenWidth()/2) == sideNode:
nuke.message('Both nodes have the same X position. No dot created.')
return
for i in nuke.selectedNodes():
if i.maxInputs() == 0 and i['name'].getValue() != topNodeName:
nuke.message('Lowest selected node does not have an input to connect. No dot created.')
return
createHighDot()
def createHighDot():
topNode = None
# Check highest Y position
for i in nuke.selectedNodes():
if topNode is None:
topNode = i['ypos'].getValue()
elif i['ypos'].getValue() < topNode:
topNode = i['ypos'].getValue()
sel = nuke.selectedNodes()
for i in sel:
# If it is the lowest in Y
if not i['ypos'].getValue() == topNode:
# We will connect the dot here, so we save its
# name and X position for later.
dotOutput = i['name'].getValue()
sideNodePos = i['xpos'].getValue()
i['selected'].setValue(False)
# If the node is the highest in Y
if i['ypos'].getValue() == topNode:
# Check if it is connected to the lowest one
existingConnections = []
topNodeYPos = i['ypos'].getValue()
i['selected'].setValue(True)
# Save the name of the node for later
dotInput = i['name'].getValue()
for conn in nuke.selectedNode().dependent():
connName = conn['name'].getValue()
existingConnections.append(connName)
i['selected'].setValue(False)
# We store some sizes and positions that we will use later to
# move the dot to an approximate position.
dotSize = nuke.toNode('preferences').knob('dot_node_scale').value()
dotCenter = (12*dotSize)/2 # 12 is width and height by default
dotOutWidthCenter = nuke.toNode(str(dotOutput)).screenWidth() / 2
sideNodePos = sideNodePos + (dotOutWidthCenter - dotCenter)
dotOutHeightCenter = nuke.toNode(str(dotOutput)).screenHeight() / 2
dotInWidthCenter = nuke.toNode(str(dotInput)).screenWidth() / 2
dotInHeightCenter = nuke.toNode(str(dotInput)).screenHeight() / 2
if not nuke.toNode(str(dotOutput)).Class() == 'Dot':
topNodeYPos = topNodeYPos + (dotInHeightCenter - dotCenter)
else:
sideNodePos = sideNodePos - (dotOutWidthCenter - dotCenter)
topNodeYPos = topNodeYPos + (dotInHeightCenter - dotCenter)
if nuke.toNode(str(dotInput)).Class() == 'Dot':
sideNodePos = sideNodePos - (dotInHeightCenter - dotCenter)
# If we found both high and low nodes are connected
if existingConnections != []:
nuke.toNode(dotOutput)['selected'].setValue(True)
# We create an empty list and populate it with the lowest node
# dependencies names (nodes connected to its inputs).
dependenciesList = []
for node in nuke.selectedNode().dependencies():
depName = node.name()
dependenciesList.append(depName)
# We check the number of the highest input connected and use
# it to populate an empty list with 1 (if the input in that
# position is connected) and 0 (if it is not connected).
# For example, if a Merge has A connected, but not B or mask,
# the list would be [0,1].
maxInputConnected = nuke.selectedNode().inputs()
connectedList = []
for i in range(maxInputConnected):
connResult = 1 if nuke.selectedNode().input(i) else 0
connectedList.append(connResult)
# We also save the number of dependencies found
depNumber = len(connectedList)
# Now we have to check what input is connected to the
# highest node. To do that we will create two different
# counters: one for the number of dependencies and
# another one for the number of connections. A node can
# have two dependencies and three connections, example:
# a Merge with B and Mask connected, but not A, will
# have two dependencies (or one if B and Mask are
# connected to the same node) and three connections (A
# counts as a connection even if it is not connected).
depCounter = 0
connCounter = 0
while connCounter <= (depNumber-1):
# Using connectedList we created before, we'll add
# the string 'Nope' as an element to later match
# the node name to the correct input number.
if connectedList[connCounter] == 1:
depCounter = depCounter + 1
connCounter = connCounter + 1
elif connectedList[depCounter] == 0:
dependenciesList.insert(depCounter, 'Nope')
connCounter = connCounter + 1
# Now both dependenciesList and connectedList have the
# same number of elements, so we just need to find the
# position of the highest node in dependenciesList to know
# to what input of the lowest node it's connected to.
try:
inputNumber = dependenciesList.index(dotInput)
except ValueError:
maxInputsNumber = nuke.toNode(dotOutput).maxInputs()
if depNumber == maxInputsNumber:
try:
inputNumber = connectedList.index(0)
except ValueError:
inputNumber = 0
elif depNumber == maxInputsNumber-1:
inputNumber = depNumber
else:
# Find the first position with a 0 in connectedList, and that
# would be the first available input to connect to the dot.
try:
inputNumber = connectedList.index(0)
except ValueError:
if maxInputsNumber > depNumber+1:
inputNumber = depNumber
else:
inputNumber = 0
nuke.toNode(dotOutput)['selected'].setValue(False)
# We create our dot on the positions we calculated and
# select it to connect the input we checked before.
nuke.nodes.Dot(xpos=sideNodePos, ypos=topNodeYPos, selected=1).setInput(0, nuke.toNode(dotInput)) #for some reason this step takes longer than expected
nuke.toNode(dotOutput).setInput(inputNumber, nuke.selectedNode())
# Now we will check if other nodes were connected to the
# dot input,because those will be connected to the new dot
# for esthetic purposes. First we look for all the nodes
# sharing the same center as our new dot.
sameCenterList = []
for i in nuke.allNodes():
# We make sure to remove the new dot and its input from
# these next steps.
if not i['selected'].getValue() == True and i['name'].getValue() != dotInput:
nodeName = i['name'].getValue()
nodeCenter = i['ypos'].getValue() + nuke.toNode(nodeName).screenHeight() / 2
if nodeCenter == topNodeYPos + dotCenter:
sameCenterList.append(nodeName)
# Now we have a list on nodes sharing the same X position.
# Using our new list, we are going to check if those nodes are
# also connected to the dot input.
depList = []
for node in sameCenterList:
for i in nuke.toNode(node).dependencies():
nodeName = i.name()
if nodeName == dotInput:
depList.append(node)
# We have removed all the nodes sharing the X position that were
# not connected to the dot input.
for i in depList:
# Following the same method we did before, we fill a list
# with the names of all the dependencies of the nodes sharing
# X position with the new dot and also conected to its input.
dependenciesList = []
for node in nuke.toNode(i).dependencies():
depName = node.name()
dependenciesList.append(depName)
# Another list with 1 (if the input is connected) and 0
# (if it is not connected). Ex: if a Merge has A connected,
# but not B or mask, the list would be [0,1].
maxInputConnected = nuke.toNode(i).inputs()
connectedList = []
for x in range(maxInputConnected):
connResult = 1 if nuke.toNode(i).input(x) else 0
connectedList.append(connResult)
# We also save the number of dependencies found
depNumber = len(connectedList)
# Now we have to check what input is connected to the
# dot input. To do that we will create two different
# counters: one for the number of dependencies and
# another one for the number of connections
depCounter = 0
connCounter = 0
while connCounter <= (depNumber-1):
# Using connectedList we created before, we'll add
# the string 'Nope' as an element to later match
# the node name to the correct input number.
if connectedList[connCounter] == 1:
depCounter = depCounter + 1
connCounter = connCounter + 1
elif connectedList[depCounter] == 0:
dependenciesList.insert(depCounter, 'Nope')
connCounter = connCounter + 1
# Now both dependenciesList and connectedList have the
# same number of elements, so we just need to find the
# position of the highest node in dependenciesList to know
# to what input of the lowest node it's connected to.
try:
inputNumber = dependenciesList.index(dotInput)
except ValueError:
maxInputsNumber = nuke.toNode(i).maxInputs()
if depNumber == maxInputsNumber:
inputNumber = connectedList.index(0)
elif depNumber == maxInputsNumber-1:
inputNumber = depNumber
else:
# Find the first position with a 0 in connectedList, and that
# would be the first available input to connect to the dot.
try:
inputNumber = connectedList.index(0)
except ValueError:
if maxInputsNumber > depNumber+1:
inputNumber = depNumber
else:
inputNumber = 0
nuke.toNode(i).setInput(inputNumber, nuke.selectedNode())
for i in nuke.allNodes():
i['selected'].setValue(False)
# If nodes are not connected, we will find what is the first input
# of the lowest node that is not connected.
else:
maxInputConnected = nuke.toNode(dotOutput).inputs()
connectedList = []
for i in range(maxInputConnected):
connResult = 1 if nuke.toNode(dotOutput).input(i) else 0
connectedList.append(connResult)
# We also save the number of dependencies found to check if it
# is the max allowed.
depNumber = len(connectedList)
maxInputsNumber = nuke.toNode(dotOutput).maxInputs()
nuke.toNode(str(dotInput))['selected'].setValue(True)
# We create our dot on the positions we calculated and
# select it to connect the input we checked before.
nuke.nodes.Dot(xpos=sideNodePos, ypos=topNodeYPos, selected=1).setInput(0, nuke.toNode(dotInput)) #for some reason this step takes longer than expected
if depNumber == maxInputsNumber:
try:
print 'here'
firstFreeInput = connectedList.index(0)
nuke.toNode(dotOutput).setInput(firstFreeInput, nuke.selectedNode())
except ValueError:
nuke.toNode(dotOutput).setInput(0, nuke.selectedNode())
elif depNumber == maxInputsNumber-1:
try:
firstFreeInput = connectedList.index(0)
nuke.toNode(dotOutput).setInput(firstFreeInput, nuke.selectedNode())
except ValueError:
nuke.toNode(dotOutput).setInput(depNumber, nuke.selectedNode())
else:
# Find the first position with a 0 in connectedList, and that
# would be the first available input to connect to the dot.
try:
firstFreeInput = connectedList.index(0)
nuke.toNode(dotOutput).setInput(firstFreeInput, nuke.selectedNode())
except ValueError:
if maxInputsNumber > depNumber+1:
nuke.toNode(dotOutput).setInput(depNumber, nuke.selectedNode())
else:
nuke.toNode(dotOutput).setInput(0, nuke.selectedNode())
for i in nuke.allNodes():
i['selected'].setValue(False)
selNodesList = []
for i in nuke.selectedNodes():
selNodesNames = i['name'].getValue()
selNodesList.append(selNodesNames)
if len(selNodesList) != 2:
nuke.message('Please, select two nodes to run this action.')
else:
XYCheck()