Elyg
11/3/2017 - 4:52 PM

Houdini shelf scripts

Houdini python shelf script

import hou
import re
import os

###########################################################################################################
def pullLoadedAssets():
    """
    This function creates edit nodes for the selected nodes, and sets merge nodes paths to unlocked and point to the Fasset Group node's guts
    """
    nodes = hou.selectedNodes()
    for node in nodes:
        node.setSelected(False, False)
        childNodes = node.children()
        vals = len(childNodes)
        allow_create = 0
        if(vals > 2):
            message = "The '%s' will create %s nodes, conitnue?"%(node.name(), vals)
            excessive_warning = hou.ui.displayMessage(message, buttons=('OK',"CANCEL"))
            allow_create = excessive_warning
            print allow_create
            
        if(allow_create == 0):
            for childNode in childNodes:
                nodePath = childNode.path()+"/contents/OUT"
                if(hou.node(nodePath)== None):
                    print "Couldn't find /geo/../../contents/OUT child node, skipping"
                    continue
                
                editNode = node.createOutputNode('fxfassetedit')
                editNodePath = editNode.path()+"/EDIT_NETWORK/IN"
                
                mergeNode = hou.node(editNodePath)
                parmEdit = mergeNode.parm("objpath1")
                parmEdit.lock(False)
                parmEdit.set(nodePath)
                
                nodeAbsPath = mergeNode.parm("objpath1").evalAsString()
                otherNode = hou.node(nodeAbsPath)
                relPath = mergeNode.relativePathTo(otherNode)
                mergeNode.parm("objpath1").set(relPath)
                
                otherNodeName = re.sub(node.name()+":", '', childNode.name())
                editNode.setName(otherNodeName, True)
                editNode.setSelected(True, False)
                editNode.setDisplayFlag(False)
###########################################################################################################

###########################################################################################################
def pullFxEditsToGeo():
    """
    This function creates a geo node and imports all the selected nodes' /contents/OUT nodes with merge nodes
    """
    nodes = hou.selectedNodes()

    newGeoNode = hou.node("/obj").createNode("geo")
    newGeoNode.setName("FETCH_ASSETS")

    avgPosX = 0
    avgPosY = 0
    minY = nodes[0].position()[1]

    for node in nodes:
        avgPosX +=node.position()[0]
        avgPosY +=node.position()[1]
        minY = min(minY, node.position()[1])
        node.setDisplayFlag(False)
        
    avgPosX /= len(nodes)
    avgPosY /= len(nodes) 
    newGeoNode.setPosition((avgPosX, (minY-avgPosY)+avgPosY-2))

    childrenNodes = newGeoNode.children()
    for childNode in childrenNodes:
        childNode.destroy()

    for id, node in enumerate(nodes):
        mergeNode = newGeoNode.createNode("object_merge")
        name = node.name().split("_")
        
        mergeNode.setName("IN_"+name[0].upper())
        mergeNode.setColor(hou.Color( (0.0, 0.6, 1.0) ) )
        parmEdit = mergeNode.parm("objpath1")
        parmEdit.set(node.path()+"/contents/OUT")
        
        nodeAbsPath = mergeNode.parm("objpath1").evalAsString()
        otherNode = hou.node(nodeAbsPath)
        relPath = mergeNode.relativePathTo(otherNode)
        parmEdit.set(relPath)
        
        mergeNode.setPosition((id*3, 0))
        nullNode = mergeNode.createOutputNode("null")
        nullNode.setName("OUT_"+name[0].upper())
        nullNode.setColor(hou.Color( (0.6, 1.0, 0.6) ) )

    #newChildrenNodes = newGeoNode.children()
    #newGeoNode.layoutChildren(newChildrenNodes, horizontal_spacing=-1.0, vertical_spacing=0.0)
    newGeoNode.setSelected(True, True)
    newGeoNode.setColor(hou.Color( (0.6, 0.6, 1.0) ) )
###########################################################################################################

###########################################################################################################
def createObjRopNetFromGeo():
    """
    This function creates a rop network at object level and fetches all fxCache nodes and links them up (the connections might not be in the correct order)
    """
    nodes = hou.selectedNodes()
    if(len(nodes)!=0):
        insideRopChildren = []
        if(hou.node("/obj/ropnet1")==None):
            newRopNode = hou.node("/obj").createNode("ropnet")   
        else:
            newRopNode = hou.node("/obj/ropnet1")
            
        ropNodeChildren = []
        for node in nodes:
            fetchNodes = []
            fxCacheNodes = []
            colour = node.color()
            insideRopChildren = newRopNode.children()
            childrenNodes = node.allSubChildren()
            
            for childNode in childrenNodes:
                if(childNode.type().name() == "fxcache"):
                    fxCacheNodes.append(childNode)
            for fxCacheNode in fxCacheNodes:           
                valid = 1
                orgName = fxCacheNode.name()
                fetchNode = newRopNode.createNode("fetch")
                relPath = fetchNode.relativePathTo(fxCacheNode)+"/ropnet1/OUT"
                for ropChild in insideRopChildren:
                    if(ropChild.type().name() == "fetch"):
                        if(ropChild.evalParm("source") == relPath):
                            valid = 0
                            break
                if(valid == 1):
                    parmSource = fetchNode.parm("source")
                    parmSource.set(relPath)
                    fetchNode.setName(node.name().upper()+"_"+orgName, True)
                    fetchNode.setColor(colour)
                    fetchNodes.append(fetchNode)
                else:
                    fetchNode.destroy()
            
            for i, fetchNode in enumerate(fetchNodes):
                print fetchNode
                nodeSize = len(fetchNodes)
                index = (nodeSize-i)-1
                if(index-1 >= 0):
                    fetchNodes[index].setInput(0, fetchNodes[index-1])
                else:
                    ropNodeChildren.append(fetchNode)
                
        if(newRopNode.node("OUT") == None):
            groupNode = newRopNode.createNode("grouping_v1_")
            groupNode.setName("OUT")
        else:
            groupNode = newRopNode.node("OUT")
        
        #ropNodeChildren = newRopNode.children()
        for input, fetchNode in enumerate(ropNodeChildren):
            if(fetchNode == groupNode):
                continue
            if(input <= 10):
                groupNode.setInput(input, fetchNode)
        
        #newRopNode.layoutChildren(newRopNode.children(), horizontal_spacing=1.0, vertical_spacing=1.0)
        newRopNode.setColor(hou.Color( (0.4, 0.2, 0.6) ) )
        groupNode.setColor(hou.Color( (0.6, 1, 0.6) ) )
###########################################################################################################

###########################################################################################################
def createRopUiFromSwitchNodes(recreate=False):
    """
    Generates toggles and buttons for the selected ropnet, from all the switch nodes inside
    """
    node = hou.selectedNodes()[0]
    group = node.parmTemplateGroup()
    folder = hou.FolderParmTemplate("folder", "Render Control")
    switchNodes = []
    toggleParms = []
    groupNode = None
    if(node.type().name() == "ropnet"):
        ropChildren = node.children()
        for ropNode in ropChildren:
            if(ropNode.type().name() == "grouping_v1_"):
                groupNode = ropNode
            if(ropNode.type().name() == "switch"):
            	if(recreate==False):
                	name = ropNode.inputs()[0].name()
                else:
                	name = ropNode.inputs()[1].name()
                if(recreate==False):
                	ropNode.setName("tgl_"+name, unique_name=True)
                ropNode.parm("index").deleteAllKeyframes()   
                folder.addParmTemplate(hou.ToggleParmTemplate(name, name, 1))
                switchNodes.append(ropNode)
                toggleParms.append(name)
                

             
    button_run = groupNode.parm("dispatcher_run")
    button_dispatch = groupNode.parm("dispatcher_submit")

    folder.addParmTemplate(hou.SeparatorParmTemplate("sep"))
    folder.addParmTemplate(hou.ButtonParmTemplate("dispatcher_run", "Run...", join_with_next=True))
    folder.addParmTemplate(hou.ButtonParmTemplate("dispatcher_submit", "Submit..."))

    group.append(folder)
    node.setParmTemplateGroup(group)   

    node.parm("execute").hide(True)
    node.parm("renderdialog").hide(True)
    button_run.set(node.parm("dispatcher_run"))
    button_dispatch.set(node.parm("dispatcher_submit"))

        if(recreate==False):
	        orgNode = switchNode.inputs()
	        switchNode.setFirstInput(nullNode)
	        switchNode.setInput(1, orgNode[0])
	        if(len(orgNode[0].inputs())>0):
	        	switchNode.setInput(0, orgNode[0].inputs()[0])
###########################################################################################################

###########################################################################################################
def setMergeRelative():
    """
    Sets object merges node to the relative path and renames it
    """
    selected_nodes = hou.selectedNodes()

    for node in selected_nodes:
        nodeAbsPath = node.parm("objpath1").evalAsString()
        otherNode = hou.node(nodeAbsPath)
        if(otherNode == None):
            continue
        otherNodeName = otherNode.name()
        testMatch = re.match('OUT_', otherNodeName)
        if testMatch==None:
            otherNodeName = 'IN_'+otherNodeName
        else:
            otherNodeName = re.sub('OUT_', 'IN_', otherNodeName)
        relPath = node.relativePathTo(otherNode)
        node.parm("objpath1").set(relPath)
        node.setName(otherNodeName.upper(), True)
        node.setColor(hou.Color( (0.0, 0.6, 1.0) ) )
###########################################################################################################

###########################################################################################################
def setFetchRelative():
    """
    Sets selected fetch nodes to the relative path
    """
    selected_nodes = hou.selectedNodes()

    for node in selected_nodes:
        nodeAbsPath = node.parm("source").evalAsString()
        otherNode = hou.node(nodeAbsPath)
        if(otherNode == None):
            continue
        otherNodeParent = otherNode.parent()
        otherNodeName = otherNodeParent.parent().name()
        relPath = node.relativePathTo(otherNode)
        node.parm("source").set(relPath)
        node.setName(otherNodeName, True)
###########################################################################################################

###########################################################################################################
def splitById ():

    #============================================================
    def make_blast_by_attrib_node(attrib_name, attrib_type, blast_type):
        """
            Makes blast node with incoming parms
        """

        if len(hou.selectedNodes())==0:
            return
            
        node = hou.selectedNodes()[0]
        geo = node.geometry()
        types = ["point","prim"]
        
        if attrib_type not in types:
            return
            
        if attrib_type == "point":
            vals = set(geo.pointIntAttribValues(attrib_name))
        if attrib_type == "prim":
            vals = set(geo.primIntAttribValues(attrib_name))
      

        # Im lazy so i copied code sue me
        
        if blast_type == "multi":
            
            num_vals = len(vals)
            allow_create = 0
            # check to stop exessive node creation
            if num_vals>20:
                message = "WOAH WOAH WOAH!! This would create %s of nodes for %s attribute"%( len(vals), attrib_name)
                excessive_warning = hou.ui.displayMessage(message, buttons=('OK',"CANCEL"))
                # reset allow create
                allow_create = excessive_warning
                
            if allow_create != 1:
                for v in vals:
                    keep_val = "@%s==%s"%(attrib_name, v)           
                    newnode = node.createOutputNode("blast","%s_%s"%(attrib_name, "separate"))
                    newnode.parm("group").set(keep_val)
                    newnode.parm("negate").set(1)
                    
                    if attrib_type == "point":
                        newnode.parm("grouptype").set(3)
                    if attrib_type == "prim":
                        newnode.parm("grouptype").set(4)
                
        if blast_type == "single":
            grouplist = []
            for v in vals:
                grouplist.append("@%s==%s"%(attrib_name, v))
            
            expstr = " ".join(grouplist)
            newnode = node.createOutputNode("blast","%s_%s"%(attrib_name, "separate"))
            newnode.parm("group").set(expstr)
            newnode.parm("negate").set(1)
            
            if attrib_type == "point":
                newnode.parm("grouptype").set(3)
            if attrib_type == "prim":
                newnode.parm("grouptype").set(4)
    def blast_by_attr_dialog():
        message = "Input attribute name and type"
        message += "\n"
        message += "prim or point"
        
        attrib_window = hou.ui.readMultiInput(message,["Attribute Name", "Attribute Type"],buttons=("Single Blast", "Multi Blast", "Cancel"), initial_contents=["groupId", "prim"])
        
        if attrib_window[0] == 1:
            blast_type = "multi"
            make_blast_by_attrib_node(attrib_window[1][0], attrib_window[1][1], blast_type)
        if attrib_window[0] == 0:
            blast_type = "single"
            make_blast_by_attrib_node(attrib_window[1][0], attrib_window[1][1], blast_type)

    blast_by_attr_dialog()
###########################################################################################################

###########################################################################################################
def createSopWrangle():
    """
    Creates an attribute wrangle
    """
    made = 0
    try:
        node = hou.selectedNodes()[0]
        outputNodes = node.outputs()
        print outputNodes
        nodes = []
        for nodeNew in outputNodes:
            for conn in nodeNew.inputConnections():
                if(nodeNew == conn.inputNode()):
                    print nodeNew
                    index = conn.inputIndex()
                    print index
                    nodeNew.append([nodeNew, index])
        #print nodes
        newnode = node.createOutputNode("attribwrangle")
        newnode.parm("class").set("point")
        #if(len(outputNodes)>0):
            #print node
            #outputNodes[0].setInput(0, newnode)
        newnode.setSelected(True, True)
        newnode.setDisplayFlag(True)
        newnode.setRenderFlag(True)
        made =1
    except:
        print "No selected nodes"
    if(made == 0):
        try:
            for id, pane in  enumerate(hou.ui.currentPaneTabs()):
                if(pane.type().name() == "NetworkEditor"):
                    pos = pane.cursorPosition()
                    newnode = pane.pwd().createNode("attribwrangle")
                    newnode.move(pos)
                    newnode.parm("class").set("point")
                    newnode.setSelected(True, True)
                    newnode.setDisplayFlag(True)
                    newnode.setRenderFlag(True)
        except:
                "Failed to create node"
###########################################################################################################

###########################################################################################################
def empty():
    print "I am empty!!!"
###########################################################################################################