import sd import math from PySide2 import QtGui from sd.api.sduimgr import SDUIMgr from sd.api.sdproperty import SDPropertyCategory import sd.api.sdtype from sd.api.sdapplication import SDApplicationPath def selection(D): ctx = sd.getContext() app = ctx.getSDApplication() uiMgr = app.getUIMgr() selection = uiMgr.getCurrentGraphSelectedNodes() if (D == 1): print("selection len " + str(len(selection))) for node in selection: print("node %s" % node) return selection def sortByY(selection, D): nodeList = [] for i1, nodeA in enumerate(selection): pos = [0, 0] node = [] nodePos = nodeA.getPosition() pos[0] = nodePos.x pos[1] = nodePos.y node.append(nodeA) node.append(pos) nodeList.append(node) # sorting by y nodeList.sort(key=lambda x: x[1][1]) return nodeList def setPosition(selection, posOffset, D): for e, i in enumerate(selection): x = selection[0][1][0] # This will add the offset to y value y = selection[0][1][1] + (e * posOffset) selection[e][0].setPosition(sd.api.sdbasetypes.float2( x, y )) selection[e][1] = [x, y] # usage example : setPosition(sortByY(selection(D),D),posOffset,D) return selection def addNode(name, pos=[0, 0]): ctx = sd.getContext() app = ctx.getSDApplication() ui_manager = app.getUIMgr() sd_graph = ui_manager.getCurrentGraph() node_def_id = 'sbs::compositing::{definition}'.format(definition=name) sd_node = sd_graph.newNode(node_def_id) sd_node.setPosition(sd.api.sdbasetypes.float2(pos[0], pos[1])) return sd_node def connect(nodeA, nodeB, inProp, outProp): nodeA.newPropertyConnectionFromId(inProp, nodeB, outProp) def nodeInputs(node): nodeInputs = node.getProperties(SDPropertyCategory.Input) for i in range(len(nodeInputs)): print("node Inputs \n") print(nodeInputs[i].getId()) print(nodeInputs[i].getType()) return nodeInputs def nodeOutputs(node): nodesOutputs = node.getProperties(SDPropertyCategory.Output) for i in range(len(nodesOutputs)): print("node Outputs \n") print(nodesOutputs[i].getId()) print(nodesOutputs[i].getType()) return nodesOutputs def blendMerge( posOffset,D): sel = selection(D) if len(sel) == 0 : return ("selection is empty") sel = setPosition(sortByY(sel, D),posOffset,D) if D == 1: print(sel) propInBlend0 = "opacity" propInBlend1 = "source" propInBlend2 = "destination" propOutBlend = "unique_filter_output" propOutColortoMask = "output" blendName = "blend" blendNodeName = "Blend" colorMaskNodeName = "Color to Mask" singleNodes = [] selTemp1 = [] selTemp2 = [] recCounter = 0 def blendMergeRecursive( sel,selTemp1,selTemp2,posOffset,singleNodes,recCounter,D): ready = "Your tree is ready \n" #recursion exit conditions if len(sel) == 1 and len(singleNodes) == 0: return print(ready) if len(sel) == 0 and len(singleNodes) == 1: return print(ready) if len(sel) == 0 and len(singleNodes) == 0: return print(ready) #Group list by group_size / pairing group_size = 2 sel = [sel[i:i+group_size ] for i in range(0, len(sel), group_size )] for i1, v1 in enumerate(sel): if D == 1: print("sel loop, i1: \n" + str(i1)) print("sel loop, v1: \n" + str(v1)) print("sel loop, v1 len: \n" + str(len(v1))) v1Len = len(v1) if v1Len == 2: if D == 1 : print("v1 len == 2 case, node 1 : \n" + str(v1[0][0])) print("v1 len == 2 case,node 2 : \n" + str(v1[1][0])) print("v1 len == 2 case,pos 1 : \n" + str(v1[0][1])) print("v1 len == 2 case,pos 2 : \n" + str(v1[1][1])) node1 = v1[0][0] node2 = v1[1][0] pos1 = v1[0][1] pos2 = v1[1][1] node1Name = node1.getDefinition().getLabel() node2Name = node1.getDefinition().getLabel() if D == 1: print("v1 len == 2 case, node1 name: \n" + str(node1Name )) print("v1 len == 2 case, node2 name: \n" + str(node2Name )) if node1Name == colorMaskNodeName : pos3 = [(pos1[0] + posOffset), pos1[1] ] pos4 = [(pos2[0] + posOffset), pos2[1] ] node3 = addNode(blendName,pos3) node4 = addNode(blendName, pos4) connect(node1,node3,propOutColortoMask,propInBlend0) connect(node2,node4,propOutColortoMask,propInBlend0) if recCounter % 2 == 0 : selTemp1.append([node3,pos3]) selTemp1.append([node4, pos4]) if recCounter % 2 == 1 : selTemp2.append([node3, pos3]) selTemp2.append([node4, pos4]) if node2Name == blendNodeName : pos3 = [(pos1[0] + posOffset), ((pos1[1] + pos2[1]) / 2)] node3 = addNode(blendName, pos3) connect(node1, node3, propOutBlend , propInBlend1) connect(node2, node3, propOutBlend, propInBlend2) if recCounter % 2 == 0: selTemp1.append([node3, pos3]) if recCounter % 2 == 1: selTemp2.append([node3, pos3]) if v1Len == 1: singleNodesLen = len(singleNodes) if D == 1 : print("single node == 1 case, len: \n" + str(singleNodesLen)) if singleNodesLen < 2: if D == 1: print("single Node < 2 item case, incoming v1: \n" + str(v1)) node1 = v1[0][0] pos1 = v1[0][1] node1Name = node1.getDefinition().getLabel() if D == 1: print("single node < 2 item case, list: \n" + str(node1)) print("single node < 2 item case, node ID: \n" + str(node1)) print("single node < 2 item case, node name: \n" + str(node1Name)) print("single node < 2 item case, pos1: \n" + str(pos1)) if node1Name == blendNodeName: singleNodes.append([node1,pos1]) if node1Name == colorMaskNodeName: # if our node is a color mask, we connect it to a blend pos3 = [(pos1[0] + posOffset), pos1[1]] node3 = addNode(blendName, pos3) connect(node1, node3, propOutColortoMask, propInBlend0) # reset the single node array singleNodes = [] # add the new blend to the single node list if recCounter % 2 == 0: selTemp1.append([node3, pos3]) if recCounter % 2 == 1: selTemp2.append([node3, pos3]) # recalculate single Node Len in case we reach a pair so we blend them together singleNodesLen = len(singleNodes) if D == 1: print("Single node 1 new len after <2 case: \n" + str(singleNodesLen)) if singleNodesLen == 2 : if D==1: print("single Node 2 item case, list : \n" + str(singleNodes)) print("single Node 2 item case, pos 1 : \n" + str(singleNodes[0][1])) print("single Node 2 item case, pos 2 : \n" + str(singleNodes[1][1])) print("single Node 2 item case, node 1 : \n" + str(singleNodes[0][0])) print("single Node 2 item case, node 2 : \n" + str(singleNodes[1][0])) # if the array have two single node we create a blend and connect them node1 = singleNodes[0][0] node2 = singleNodes[1][0] pos1 = singleNodes[0][1] pos2 = singleNodes[1][1] posx = max(pos1[0],pos2[0]) pos3 = [posx + posOffset, ((pos1[1] + pos2[1]) / 2)] node3 = addNode(blendName, pos3) connect(node2, node3, propOutBlend, propInBlend1) connect(node1, node3, propOutBlend, propInBlend2) # we reset the array singleNodes = [] # we add our single blend to the temp selection array if recCounter % 2 == 0: selTemp1.append([node3, pos3]) if recCounter % 2 == 1: selTemp2.append([node3, pos3]) # we alternate temp lists so they don't accumulate the results for more than one recursion if recCounter % 2 == 0: sel = selTemp1 selTemp2 = [] if recCounter % 2 == 1: sel = selTemp2 selTemp1 = [] recCounter += 1 return blendMergeRecursive(sel,selTemp1,selTemp2,posOffset,singleNodes,recCounter,D) blendMergeRecursive(sel,selTemp1,selTemp2,posOffset,singleNodes,recCounter,D) return posOffset = 150 Debug = 0 blendMerge(posOffset,Debug)