Forum: Poser Python Scripting


Subject: HDR Background

adp001 opened this issue on May 08, 2021 ยท 12 posts


adp001 posted Sat, 08 May 2021 at 9:52 AM

Creating a HDR Background and a Grouping Object to rotate it.

from __future__ import print_function
import sys, os, math, wx

try:
    import poser
except ImportError:
    # Not required while inside Poser Python, but very helpfull for external editors.
    # See https://adp.spdns.org
    from PoserLibs import POSER_FAKE as poser

if sys.version_info.major > 2:
    # Python 3 (Poser 12 and above)
    map = lambda a, b: [a(_b) for _b in b]
    basestring = str
else:
    range = xrange

SCENE = poser.Scene()
P_ROTS = poser.kParmCodeXROT, poser.kParmCodeYROT, poser.kParmCodeZROT
ROTOBJ_COLOR = (200, 100, 120)


def do_rot(parm, newvalue):
    assert isinstance(parm, poser.ParmType)
    shdr = SCENE.BackgroundShaderTree()
    node = [n for n in shdr.Nodes() if n.Type() == "ccl_Mapping"]
    if not node:
        return
    idx = P_ROTS.index(parm.TypeCode())
    vec = node[0].InputByInternalName("Rotation").Value()
    vec[idx] = math.radians(newvalue)

    return newvalue


def get_node(shader, nodetype, name=None):
    """:rtype: poser.ShaderNodeType"""
    for node in shader.Nodes():
        if node.Type() == nodetype:
            if name and node.Name() != name:
                continue
            return node
    return None


def get_or_create_node(shader, nodetype, name=None):
    node = get_node(shader, nodetype, name)
    if node is None:
        node = shader.CreateNode(nodetype)
    return node


def get_input(node, inp_name):
    """:rtype: poser.ShaderNodeInputType"""
    for inp in node.Inputs():
        if inp.Name() == inp_name:
            return inp
    return None


def delete_actor(iname):
    try:
        SCENE.ActorByInternalName(iname).Delete()
    except poser.error:
        pass


def create_background(imagename=None):
    SCENE.Actor("GROUND").SetVisible(0)
    shdr = SCENE.BackgroundShaderTree()
    bkgrnd = get_or_create_node(shdr, poser.kNodeTypeCodeBACKGROUND)
    get_input(bkgrnd, "Color").SetColor(1.0, 1.0, 1.0)
    get_input(bkgrnd, "Specular_Color").SetColor(0.0, 0.0, 0.0)
    get_input(bkgrnd, "Diffuse_Color").SetColor(1.0, 1.0, 1.0)
    get_input(bkgrnd, "Cast_Light").SetFloat(1)

    hsv = get_or_create_node(shdr, poser.kNodeTypeCodeCyclesHSV)
    img = get_or_create_node(shdr, poser.kNodeTypeCodeCyclesENVIRONMENTTEXTURE)
    mapping = get_or_create_node(shdr, poser.kNodeTypeCodeCyclesMAPPING)
    tcoords = get_or_create_node(shdr, poser.kNodeTypeCodeCyclesTEXTURECOORDINATE)

    shdr.AttachTreeNodes(bkgrnd, "Color", hsv)
    shdr.AttachTreeNodes(hsv, "Color", img)
    shdr.AttachTreeNodes(img, "Vector", mapping)
    shdr.AttachTreeNodes(mapping, "Vector", tcoords)

    if isinstance(imagename, basestring):
        get_input(img, "Image").SetString(imagename)

    shdr.UpdatePreview()


def create_rotobj():
    def _cb_intens(parm, value):
        node = get_node(SCENE.BackgroundShaderTree(), poser.kNodeTypeCodeCyclesHSV)
        if node:
            get_input(node, "Value").SetFloat(value)
        return value

    def _rot_set(inp, xyz, v):
        vec = list(inp.Value())
        vec[xyz] = v
        inp.SetColor(*vec)

    def _cb_xrot(parm, value):
        shdr = SCENE.BackgroundShaderTree()
        node = get_node(shdr, poser.kNodeTypeCodeCyclesMAPPING)
        if node:
            _rot_set(get_input(node, "Rotation"), 0, math.radians(value))
        return value

    def _cb_yrot(parm, value):
        shdr = SCENE.BackgroundShaderTree()
        node = get_node(shdr, poser.kNodeTypeCodeCyclesMAPPING)
        if node:
            _rot_set(get_input(node, "Rotation"), 1, math.radians(value))
        return value

    def _cb_zrot(parm, value):
        shdr = SCENE.BackgroundShaderTree()
        node = get_node(shdr, poser.kNodeTypeCodeCyclesMAPPING)
        if node:
            _rot_set(get_input(node, "Rotation"), 2, math.radians(value))
        return value

    try:
        obj = SCENE.Actor("WorldRotation")
    except poser.error:
        obj = SCENE.CreateGrouping()
        obj.SetName("WorldRotation")
        obj.SetDisplayStyle(poser.kDisplayCodeEDGESONLY)

        shdr = obj.Material("Preview").ShaderTree()
        r, g, b = map(lambda n: 1.0 / 255.0 * n, ROTOBJ_COLOR)
        shdr.Node(0).Input(0).SetColor(r, g, b)
        shdr.UpdatePreview()

    parmnames = [p.Name() for p in obj.Parameters()]
    for parmname, cb, pp in [
                         ("Z Rotation", _cb_zrot, (None, None, 0, None)),
                         ("Y Rotation", _cb_yrot, (None, None, 0, 1)),
                         ("X Rotation", _cb_xrot, (None, None, 0, 1)),
                         ("Intensity", _cb_intens, (0, 2, 1, 1))
                         ]:
        if parmname not in parmnames:
            p = obj.CreateValueParameter(parmname)
            min_v, max_v, default_v, sens = pp
            if min_v:
                p.SetMinValue(0)
            if max_v:
                p.SetMaxValue(2)
            if default_v:
                p.SetValue(1)
            if min_v or max_v:
                p.SetForceLimits(1)
                p.ApplyLimits()
            if sens:
                p.SetSensitivity(sens)
            p.SetUpdateCallback(cb)
    return obj


if __name__ == "__main__":
    filename = None
    with wx.FileDialog(None, "Select Background Image") as dlg:
        if dlg.ShowModal() == wx.ID_OK:
            filename = os.path.join(dlg.GetPath())
    create_background(filename)
    obj = create_rotobj()
    SCENE.DrawAll()

Bildschirmfoto vom 2021-05-08 16-51-28.png