Forum: Poser Python Scripting


Subject: Something more about Poser Materials

adp001 opened this issue on Apr 04, 2021 ยท 3 posts


adp001 posted Sun, 04 April 2021 at 11:56 PM

from __future__ import division, print_function

try:
    import poser
except ImportError:
    from PoserLibs import POSER_FAKE as poser

if sys.version_info.major > 2:
    basestring = str
    map = lambda a, b: [a(_b) for _b in b]

SCENE = poser.Scene()


def node_exist(stree, ntype, name):
    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):
    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):
    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):
    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):
    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)


def copy_material(source_material, target_material, clean=True):
    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)


def copy_material_to_actor(source_material, target_actor):
    assert isinstance(source_material, poser.MaterialType)
    assert isinstance(target_actor, poser.ActorType)

    if not source_material.Name() in [m.Name() for m in target_actor.Materials()]:
        target_actor.Geometry().AddMaterialName(source_material.Name())

    copy_material(source_material, target_actor.Material(source_material.Name()))


def copy_materials(source_poserobj, target_poserobj):
    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)




adp001 posted Mon, 05 April 2021 at 12:02 AM

Copy nodes from one existing material to another existing material:

copy_material(material_A, material_B)

Copy an existing materials to any actor. Material is created if it does not exist already:

copy_material_to_actor(existing_material, target_actor)

Copy a set of materials from one poser object (actor or figure) to another object (actor or figure):


copy_materials(source, target)




adp001 posted Mon, 05 April 2021 at 1:03 AM

Update: Set the correct render engine in Shadertree.

def copy_material(source_material, target_material, clean=True):
    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:
                troot = target_tree.NodeByInternalName(root_node.InternalName())
                target_tree.SetRendererRootNode(renderengine, troot)