目录
工程起始节点配置
node = hou.node('/obj')
#列出所需创建的obj层级节点
names = ['null', 'Cam', 'CJ', 'Ani', 'Ref', 'FX']
#如已有所列的节点删除
nodes = []
for name in names:
newnode = node.node(name)
nodes.append(newnode)
for newnode in nodes:
if newnode:
newnode.destroy()
#创建obj层级的null节点,设置场景比例
null = node.createNode('null', 'null')
null.parm('scale').set(0.01)
null.setDisplayFlag(0)
pos = null.position()
idx = -4
for name in names:
if name != 'null':
if name == 'Cam':
newnode = null.createOutputNode('alembicarchive', 'Cam')
newnode.parm('fileName').set('$HIP/abc/$OS.abc')
newnode.setDisplayFlag(0)
newnode.setPosition([pos[0]+idx-2, pos[1]-2])
elif name == 'FX':
newnode = node.createNode('geo', name)
newnode.setDisplayFlag(0)
newnode.setPosition([pos[0], pos[1]-4])
newnode.setColor(hou.Color((0.1,0.5,1)))
else:
newnode = null.createOutputNode('geo', name)
newnode.setDisplayFlag(0)
newnode.setPosition([pos[0]+idx, pos[1]-2])
abc_node = newnode.createNode('alembic', name)
abc_node.parm('fileName').set('$HIP/abc/$OS.abc')
OUT_node = abc_node.createOutputNode('null', 'OUT_'+name)
OUT_node.move([0,-2])
idx += 4
#在FX节点内导入外部CJ、Ani、Ref
geo_FX = hou.node('/obj/FX')
merge = geo_FX.createNode('merge')
merge_pos = merge.position()
OUT_node = merge.createOutputNode('null', 'Inputs')
OUT_node.move([0,-2])
OUT_node.setDisplayFlag(1)
OUT_node.setRenderFlag(1)
idx = -4
for name in names:
if name != 'null' and name != 'Cam' and name != 'FX':
obj_merge = geo_FX.createNode('object_merge')
obj_merge.parm('objpath1').set('/obj/'+name+'/OUT_'+name)
obj_merge.parm('xformtype').set(1)
obj_merge.move([merge_pos[0]+idx, merge_pos[1]+2])
merge.setNextInput(obj_merge)
idx += 4
#创建用于渲染的节点
Render_node = node.node('Render_')
if Render_node:
Render_node.destroy()
Render_node = node.createNode('geo', 'Render_')
Render_node.setPosition([pos.x(), pos.y()-6])
Render_node.setDisplayFlag(0)
Render_node.setColor(hou.Color((1,0,0)))
obj_merge = Render_node.createNode('object_merge')
obj_merge.parm('xformtype').set(1)
obj_merge.setRenderFlag(0)
OUT_node = Render_node.createNode('null', 'OUT')
OUT_node.move([0,-2])
OUT_node.setDisplayFlag(1)
#在obj层级创建材质渲染相关节点
cam_node = hou.node('/obj/Cam')
cam_pos = cam_node.position()
mat_node = node.node('matnet')
if mat_node:
mat_node.destroy()
mat_node = node.createNode('matnet', 'matnet')
mat_node.setPosition([cam_pos[0], cam_pos[1]-2])
mat_node.createNode('principledshader::2.0')
rop_node = node.node('ropnet')
if rop_node:
rop_node.destroy()
rop_node = node.createNode('ropnet', 'ropnet')
rop_node.setPosition([cam_pos[0], cam_pos[1]-3])
rop_node.createNode('ifd')
递归获取所有子节点(包括自身)
#递归获取所有子节点,包括自身
#等价于node.allSubChildren(),但此不包括自身
def allnodes(nodes, node):
nodes.append(node.name())
if(len(node.children()) != 0):
for i in node.children():
allnodes(nodes, i)
拆分所选节点的组
import os
if(len(hou.selectedNodes()) == 0):
hou.ui.displayMessage("未选择节点")
else:
node = hou.selectedNodes()[0]
geo = node.geometry()
full_path = os.path.dirname(node.path())
pos = node.position()
groups = geo.primGroups()
x = -3
for group in groups:
x += 3
next_pos = [pos[0]+x, pos[1]-2]
output_pos = [pos[0]+x, pos[1]-3]
grpname = group.name()
blast_node = hou.node(full_path).createNode("blast","blast_"+grpname)
blast_node.setFirstInput(node)
blast_node.setPosition(next_pos)
#blast_node.setParms({"group":grpname})
blast_node.parm("group").set(grpname)
#blast_node.setParms({"negate":1})
blast_node.parm("negate").set(1)
output_node = hou.node(full_path).createNode("null","OUT_"+grpname)
output_node.setFirstInput(blast_node)
output_node.setPosition(output_pos)
output_node.setColor(hou.Color(0.302,0.525,0.114))
读取指定缓存路径下的若干缓存
import os
node = hou.selectedNodes()[0]
pos = node.position()
full_path = os.path.dirname(node.path())
files = os.listdir(node.parm("./basedir").eval())
merge_node = hou.node(full_path).createNode("merge","files")
x=0
for file in files:
x += 3
next_pos = [pos[0]+x, pos[1]]
file_node = hou.node(full_path).createNode("file","file")
file_node.setPosition(next_pos)
file_node.parm("file").set("$HIP/geo/"+node.name()+"/"+file+"/"+file+".$F4.bgeo.sc")
merge_node.setNextInput(file_node)
merge_node.setPosition([pos[0]+3, pos[1]-4])
根据节点左右位置排序
import os
nodes = hou.selectedNodes()
if len(nodes) == 1:
node = nodes[0]
inputNodes = node.inputs()
if len(inputNodes) > 1:
inputNodes = sorted(inputNodes, key=lambda x : (x.position())[0])
for i in range(len(inputNodes)):
node.setInput(i, inputNodes[i])
添加打开缓存目录的按钮
//Callback Script
exec(hou.pwd().parm('code').eval())
import os
filepath = hou.pwd().parm('path').eval()
if os.path.exists(filepath) and os.path.isfile(filepath):
dir = os.path.dirname(filepath)
hou.ui.showInFileBrowser(dir)
print(dir)
else:
print("path wrong!")
import os
filepath = hou.pwd().parm('path').eval()
if os.path.exists(filepath) and os.path.isfile(filepath):
splitpath = filepath.split('/')
dir = "/".join(splitpath[0:-1])
hou.ui.showInFileBrowser(dir)
print(dir)
else:
print("path wrong!")
添加节点参数工具
node = hou.selectedNodes()[0]
button_idx, values = hou.ui.readMultiInput(
"Add Parms", ("Label", "name", "type", "size"),
initial_contents=("Label", "newparameter", "float", "1"),
title="Add Parms",
buttons=("OK", "Cancel"),
help="type: float or f, int or i, vetor or v, string or s"
)
if button_idx==0:
if values[2] == 'float' or values[2] == 'f':
parm = hou.FloatParmTemplate(values[1], values[0], int(values[3]))
if values[2] == 'int' or values[2] == 'i':
parm = hou.IntParmTemplate(values[1], values[0], int(values[3]))
if values[2] == 'vector' or values[2] == 'v':
parm = hou.FloatParmTemplate(values[1], values[0], int(values[3]))
if values[2] == 'string' or values[2] == 's':
parm = hou.StringParmTemplate(values[1], values[0], int(values[3]))
node.addSpareParmTuple(parm)
删除节点参数工具
node = hou.selectedNodes()[0]
button_idx, values = hou.ui.readMultiInput(
"Del Parms", ("name",),
initial_contents=("delparameter",),
title="Del Parms",
buttons=("Del parm", "Del All SpareParms", "Cancel"),
)
if button_idx==0:
parm_tuple = node.parmTuple(values[0])
parmTuples = node.parmTuples()
if parm_tuple in parmTuples:
node.removeSpareParmTuple(parm_tuple)
if button_idx==1:
node.removeSpareParms()
缓存每个Rop Geometry Output并渲染
import os
nodes = hou.selectedNodes()
R_nodes = [];
#创建单独的用于渲染的节点
idx = 2
for node in nodes:
#获取原始输出路径
file = node.parm('sopoutput').unexpandedString()
#创建obj层级的节点,如已存在先删除
newnode = hou.node('/obj/'+'render_'+node.name())
if newnode:
newnode.destroy()
pos = node.parent().position()
newnode = hou.node('/obj').createNode('geo', 'render_'+node.name())
newnode.setPosition([pos.x(), pos.y()-idx])
newnode.setColor(hou.Color((1,0,0)))
#在obj层级的节点内,创建加载缓存的节点
newfilenode = newnode.createNode('file', node.name())
#也可使用newnullnode = newfilenode.createOutputNode('null', 'display')
newnullnode = newnode.createNode('null', 'display')
newnullnode.move([0, -2])
newnullnode.setInput(0, newfilenode)
newfilenode.parm('file').set(file)
newfilenode.setRenderFlag(True)
newnullnode.setDisplayFlag(True)
#创建mantra渲染节点,如已存在先删除
R_node = hou.node('/out/'+node.name())
if R_node:
R_node.destroy()
R_node = hou.node('/out').createNode('ifd', node.name())
R_node.move([0, -idx+2])
R_node.parm('vobject').set('')
R_node.parm('forceobject').set(newnode.name())
R_node.parm('vm_picture').set('$HIP/render/$OS/$OS.$F4.exr')
R_nodes.append(R_node)
idx += 2
#缓存几何体
for node in nodes:
node.render() #等价于 node.parm('execute').pressButton()
#渲染
for node in R_nodes:
node.render() #等价于 node.parm('execute').pressButton()
写入写出数据
将参数数据写入txt文本
def fun(kwargs):
node = kwargs['node']
parm = node.parmTuple('s').eval()
lines = str(parm)
f = open('C:/test.txt', 'w')
f.writelines(lines)
f.close()
将指定参数数据写入JSON
def fun(kwargs):
import json
node = kwargs['node']
parms = node.parmsInFolder(['myparms'])
data = {}
data['parms'] = []
for parm in parms:
name = parm.name()
value = str(parm.eval())
data['parms'].append({
'name': name,
'value': value
})
with open('c:/parms.json', 'w') as outfile:
json.dump(data, outfile, indent=4)
将指定参数的几何体属性数据写入JSON
import json
nodes = hou.selectedNodes()
node = nodes[0]
path = node.parm('path').eval()
multiparm = node.parm('attribs')
instances = multiparm.multiParmInstances()
attrs = []
for attr in instances:
attrs.append(attr.eval())
data = {
'point': []
}
geo = node.geometry()
points = geo.points()
for point in points:
id = point.number()
pos = point.position()
pos_arr = [pos[0], pos[1], pos[2]]
point_data = {
'id': id,
'pos': pos_arr
}
for x in attrs:
if geo.findPointAttrib(x) is not None:
point_data[x] = point.attribValue(x)
data['point'].append(point_data)
json_obj = json.dumps(data, indent=4, sort_keys=True)
with open(path, 'w') as outfile:
outfile.write(json_obj)
将几何体所有属性数据导入JSON
import json
nodes = hou.selectedNodes()
node = nodes[0]
path = node.parm('path').eval()
data = {
'point': []
}
geo = node.geometry()
points = geo.points()
attrbs = geo.pointAttribs()
for point in points:
point_data = {}
id = point.number()
point_data['id'] = id
for x in attrbs:
point_data[x.name()] = point.attribValue(x.name())
data['point'].append(point_data)
json_obj = json.dumps(data, indent=4, sort_keys=True)
with open(path, 'w') as outfile:
outfile.write(json_obj)
从JSON导入几何体属性数据
import os
import json
node = hou.pwd()
geo = node.geometry()
json_path = node.parm('path').evalAsString()
if len(json_path) > 0 and os.path.isfile(json_path):
data = {}
with open(json_path, 'r') as fp:
data = json.load(fp)
if len(data) > 0:
for point in data['points']:
pos = point['P']
position = hou.Vector3(float(pos[0]), float(pos[1]), float(pos[2]))
newpt = geo.createPoint()
newpt.setPosition(position)
for name, value in point.items():
if name != 'P' and name != 'id':
if geo.findPointAttrib(name) == None:
attrib = geo.addAttrib(hou.attribType.Point, name, value)
newpt.setAttribValue(name, value)