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!!!"
###########################################################################################################