Advertisement
Guest User

Untitled

a guest
Jul 17th, 2019
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.91 KB | None | 0 0
  1. #----------------------------------------------------------------------------------------------------------
  2. # Wouter Gilsing
  3. # woutergilsing@hotmail.com
  4. # May 2016
  5. # v1.1
  6. #----------------------------------------------------------------------------------------------------------
  7.  
  8. import nuke
  9. import operator
  10.  
  11. def alignNodes(direction):
  12.  
  13. #--------------------------------------
  14. #USER SETTINGS
  15. #when nodes are about to overlap as a result of an alignment, the nodes are placed next to each other instead.
  16. #the multiplier variables define the amount of space that's kept between the nodes
  17. #1 is default, the higher the multiplier, the more space.
  18. #--------------------------------------
  19. multiplierX = 1
  20. multiplierY = 1
  21. #--------------------------------------
  22.  
  23. selection = nuke.selectedNodes()
  24. dontmove = False
  25.  
  26. if direction in ['left','right']:
  27. axis = 'x'
  28. index = 0
  29. else:
  30. axis = 'y'
  31. index = 1
  32.  
  33. #--------------------------------------
  34. #MULTIPLE NODES
  35. #if multiple nodes are selected, all the nodes will align to the node that's the furthest away in the specified direction
  36. #--------------------------------------
  37.  
  38. if len(selection) > 1:
  39.  
  40. allPos = [[],[]]
  41. for i in selection:
  42. allPos[0].append(i.knob('xpos').value()+(getScreenSize(i)[0]))
  43. allPos[1].append(i.knob('ypos').value()+(getScreenSize(i)[1]))
  44.  
  45. #check whether all selected nodes already share the same position values to prevent overlapping
  46. #if so, do nothing
  47. if not allPos[1-index].count(allPos[1-index][0]) == len(allPos[1-index]):
  48. if direction in ["left","up"]:
  49. destination = min(allPos[index])
  50. else:
  51. destination = max(allPos[index])
  52. else:
  53. dontmove = True
  54.  
  55. #--------------------------------------
  56. #SINGLE NODE
  57. #if only one node is selected, the selected node will snap to the nearest connected node (both input and output) in the specified direction
  58. #--------------------------------------
  59.  
  60. elif len(selection) == 1:
  61. curNode = selection[0]
  62.  
  63. #create a list of all the connected nodes
  64. inputNodes = curNode.dependencies()
  65. outputNodes = curNode.dependent()
  66.  
  67. #remove nodes with hidden inputs and viewer nodes,
  68. #as you probably wouldn't want to snap to those
  69. #not every node has a hide input knob (read node for example), so use a "try" in case it hasn't
  70. for i in outputNodes:
  71. try:
  72. if i.knob('hide_input').value() or i.Class() == 'Viewer':
  73. outputNodes.remove(i)
  74. except:
  75. pass
  76.  
  77. if curNode.knob('hide_input'):
  78. if curNode.knob('hide_input').value():
  79. inputNodes = []
  80.  
  81. connectedNodes = inputNodes + outputNodes
  82.  
  83. #create a list for every connected node containing the following [xpos,ypos,relative xpos, relative ypos, node]
  84. #store those lists in an other list
  85.  
  86. positions = []
  87.  
  88. for i in connectedNodes:
  89. xPos = i.xpos() + getScreenSize(i)[0]
  90. yPos = i.ypos() + getScreenSize(i)[1]
  91. curNodexPos = curNode.xpos() + getScreenSize(curNode)[0]
  92. curNodeyPos = curNode.ypos() + getScreenSize(curNode)[1]
  93.  
  94. positions.append([xPos,yPos,xPos-curNodexPos,yPos-curNodeyPos, i])
  95.  
  96. # sort the list based on the relative positions
  97. sortedList = sorted(positions, key=operator.itemgetter(index+2))
  98.  
  99. #remove nodes from list to make sure the first item is the node closest to the curNode
  100. #use the operator module to switch dynamically between ">=" and "<="
  101. #the positiveDirection variable is used later to correctly calculate to offset in case nodes are about to overlap
  102. if direction in ['right','down']:
  103. equation = operator.le
  104. positiveDirection = -1
  105. else:
  106. sortedList.reverse()
  107. equation = operator.ge
  108. positiveDirection = 1
  109.  
  110. try:
  111. while equation(sortedList[0][index+2],0):
  112. sortedList.pop(0)
  113. except:
  114. pass
  115.  
  116. #checking whether there are nodes to align to in the desired direction
  117. #if there are none, don't move the node
  118. if len(sortedList) != 0:
  119. destination = sortedList[0][index]
  120.  
  121. curPosition = [curNodexPos,curNodeyPos]
  122. destinationPosition = [curNodexPos,curNodeyPos]
  123. destinationPosition[index] = destination
  124.  
  125. #remove the relative positions from the positionlist
  126. for i in range(len(positions)):
  127. positions[i] = [positions[i][:2],positions[i][-1]]
  128.  
  129. # Making sure the nodes won't overlap after being aligned.
  130. # If they are about to overlap the node will be placed next to the node it tried to snap to.
  131. for i in positions:
  132.  
  133. #calculate the difference between the destination and the position of the node it will align to
  134. difference = [(abs(i[0][0]-destinationPosition[0]))*1.5,(abs(i[0][1]-destinationPosition[1]))*1.5]
  135.  
  136. #define the amount of units a node should offsetted to not overlap
  137. offsetX = 0.75 * (3 * getScreenSize(curNode)[0] + getScreenSize(i[1])[0])
  138. offsetY = 3 * getScreenSize(curNode)[1] + getScreenSize(i[1])[1]
  139. offsets = [int(offsetX),int(offsetY)]
  140.  
  141. #check in both directions whether the node is about to overlap:
  142. if difference[0] < offsets[0] and difference[1] < offsets[1]:
  143.  
  144. multiplier = [multiplierX,multiplierY][index]
  145. offset = positiveDirection * multiplier * offsets[index]
  146.  
  147. #find out whether the nodes are already very close to each other
  148. #(even closer than they would be after aligning)
  149. #don't move the node if that's the case
  150. if abs(offset) < abs(destination - curPosition[index]):
  151. destination = destination + offset
  152.  
  153. else:
  154. dontmove = True
  155.  
  156. #stop looping through the list when a suitable node to align to is found
  157. break
  158. else:
  159. dontmove = True
  160.  
  161. else:
  162. dontmove = True
  163.  
  164. #--------------------------------------
  165. #MOVE THE SELECTED NODES
  166. #--------------------------------------
  167.  
  168. nuke.Undo().name('Align Nodes')
  169. nuke.Undo().begin()
  170.  
  171. for i in selection:
  172. if not dontmove:
  173. if axis == 'x':
  174. i.setXpos(int(destination-getScreenSize(i)[index]))
  175. else:
  176. i.setYpos(int(destination-getScreenSize(i)[index]))
  177.  
  178. nuke.Undo().end()
  179.  
  180. def getScreenSize(node):
  181.  
  182. #--------------------------------------
  183. #To get the position of a node in the DAG you can use the xpos/ypos knobs.
  184. #However, that position is heavely influenced by the size of the node.
  185. #When horizontally aligned, a Dot node will have a different ypos than a blur node for example.
  186. #To neuralize a nodes postionvalues you have to add the half the nodes screen dimensions to the positionvalues.
  187. #--------------------------------------
  188.  
  189. return [node.screenWidth()/2, node.screenHeight()/2]
  190.  
  191.  
  192.  
  193. #--------------------------------------
  194. #EXAMPLE MENU.PY CODE
  195. #--------------------------------------
  196.  
  197. '''
  198. import W_smartAlign
  199.  
  200. menuBar = nuke.menu("Nuke")
  201. menuBar.addCommand("Edit/Node/Align/Left", 'W_smartAlign.alignNodes("left")', "Alt+left", shortcutContext=2)
  202. menuBar.addCommand("Edit/Node/Align/Right", 'W_smartAlign.alignNodes("right")', "Alt+right", shortcutContext=2)
  203. menuBar.addCommand("Edit/Node/Align/Up", 'W_smartAlign.alignNodes("up")', "Alt+up", shortcutContext=2)
  204. menuBar.addCommand("Edit/Node/Align/Down", 'W_smartAlign.alignNodes("down")', "Alt+down", shortcutContext=2)
  205.  
  206. '''
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement