Perhaps the following script (used as lib) may be helpful when working with materials:
def node_exist(stree, ntype, name):
"""
Check if a node of a certain type and name exist.
:param stree: Shadertree
:param ntype: Type of node
:param name: Name of node
:return: Node or None if nothing was fond
:type stree: poser.ShaderTree()
:type ntype: poser.ShaderNodeType()
:type name: basestring | str
"""
for node in stree.Nodes(): # type: poser.ShaderNodeType
if node.Type() == ntype and node.Name() == name:
return node
return None
def get_or_create_node(stree, ntype, name):
"""
Find a node in a shadertree. Create the node if it not yet exists.
:param stree: ShaderTree
:param ntype: Type of node
:param name: Name of node
:return: Node
:type stree: poser.ShaderTree()
:type ntype: poser.ShaderNodeType()
:type name: basestring | str
"""
node = node_exist(stree, ntype, name)
if not node:
node = stree.CreateNode(ntype)
node.SetName(name)
return node
def copy_input(source_input, target_input):
"""
Copy one Input-port of a shadernode to another.
:type source_input: poser.ShaderNodeInputType()
:type target_input: poser.ShaderNodeInputType()
:return: None
"""
assert isinstance(source_input, poser.ShaderNodeInputType)
assert isinstance(target_input, poser.ShaderNodeInputType)
target_input.SetName(source_input.Name())
if source_input.CanBeAnimated():
target_input.SetAnimated(source_input.Animated())
v = source_input.Value()
t = source_input.Type()
if t == poser.kNodeInputCodeCOLOR:
target_input.SetColor(*v)
elif t == poser.kNodeInputCodeSTRING:
target_input.SetString(v)
elif t == poser.kNodeInputCodeFLOAT:
target_input.SetFloat(v)
return target_input
def copy_node(source_node, target_node, target_tree):
"""
Copy a complete node to shadertree |target_tree|.
Nodes referencing this node are also copied if they do not yet
exist in the target shader tree.
:type source_node: poser.ShaderNodeType()
:type target_node: poser.ShaderNodeType()
:type target_tree: poser.ShaderTree()
:return: None
"""
assert isinstance(source_node, poser.ShaderNodeType)
assert isinstance(target_node, poser.ShaderNodeType)
assert isinstance(target_tree, poser.ShaderTreeType)
for inp_idx, node_input in enumerate(source_node.Inputs()):
copy_input(node_input, target_node.Input(inp_idx))
in_node = node_input.InNode()
if isinstance(in_node, poser.ShaderNodeType):
new_node = get_or_create_node(target_tree, in_node.Type(), in_node.Name())
copy_node(in_node, new_node, target_tree)
target_inp = target_node.Input(inp_idx)
target_tree.AttachTreeNodes(target_node, target_inp.Name(), new_node)
target_node.SetName(source_node.Name())
target_node.SetInputsCollapsed(source_node.InputsCollapsed())
target_node.SetLocation(*source_node.Location())
target_node.SetPreviewCollapsed(source_node.PreviewCollapsed())
def copy_shadertree(source_tree, target_tree):
"""
Copy all nodes of a shadertree into another shadertree.
:type source_tree: poser.ShaderTreeType()
:type target_tree: poser.ShaderTreeType()
:return: None
"""
assert isinstance(source_tree, poser.ShaderTreeType)
assert isinstance(target_tree, poser.ShaderTreeType)
for source_node in source_tree.Nodes(): # type: poser.ShaderNodeType
target_node = get_or_create_node(target_tree, source_node.Type(), source_node.Name())
copy_node(source_node, target_node, target_tree)
target_tree.UpdatePreview()
def copy_material(source_material, target_material, clean=True):
"""
Copy the contents of one material completely into another material.
If flag |clean| is set to True, all nodes in |target_material| are
deleted first.
:type source_material: poser.MaterialType
:type target_material: poser.MaterialType
:type clean: bool
:return: None
"""
assert isinstance(source_material, poser.MaterialType)
assert isinstance(target_material, poser.MaterialType)
target_layer_names = [l.Name() for l in target_material.Layers()]
for source_idx, source_layer in enumerate(source_material.Layers()):
if source_layer.Name() not in target_layer_names:
target_material.CreateLayer(source_layer.Name())
target_layer_names = [l.Name() for l in target_material.Layers()]
target_idx = target_layer_names.index(source_layer.Name())
source_tree = source_material.LayerShaderTree(source_idx)
target_tree = target_material.LayerShaderTree(target_idx)
if clean:
for node in target_tree.Nodes():
if not node.Type() in "PoserSurface CyclesSurface":
node.Delete()
copy_shadertree(source_tree, target_tree)
for renderengine in (poser.kRenderEngineCodeFIREFLY,
poser.kRenderEngineCodeSUPERFLY,
poser.kRenderEngineCodePOSER4):
root_node = source_tree.RendererRootNode(renderengine)
if root_node:
try:
# !!!!! Needs some work !!!!
troot = target_tree.NodeByInternalName(root_node.InternalName())
target_tree.SetRendererRootNode(renderengine, troot)
except poser.error:
pass
def copy_material_to_actor(source_material, target_actor, materialname=None):
"""
Copy a complete material into a Poser actor.
If |materialname| is not None, it is used as name for the target material.
:type source_material: poser.MaterialType()
:type target_actor: poser.ActorType()
:type materialname: basestring | str | None
:return: None
"""
assert isinstance(source_material, poser.MaterialType)
assert isinstance(target_actor, poser.ActorType)
source_matname = source_material.Name()
target_matname = materialname or source_matname
if target_matname not in [m.Name() for m in target_actor.Materials()]:
target_actor.Geometry().AddMaterialName(source_material.Name())
target_material = target_actor.Material(target_matname)
copy_material(source_material, target_material)
def copy_materials(source_poserobj, target_poserobj):
"""
Copy materials from one Poser Actor/Figure to another Actor/Figure.
:type source_poserobj: poser.ActorType() | poser.FigureType()
:param target_poserobj: poser.ActorType() | poser.FigureType()
:return: None
"""
if isinstance(source_poserobj, poser.FigureType):
source_poserobj = source_poserobj.RootActor()
if isinstance(target_poserobj, poser.FigureType):
target_poserobj = source_poserobj.RootActor() # type: poser.ActorType
for material in source_poserobj.Materials():
copy_material_to_actor(material, target_poserobj)