Sat, Feb 1, 5:58 PM CST

Renderosity Forums / Poser Python Scripting



Welcome to the Poser Python Scripting Forum

Forum Moderators: Staff

Poser Python Scripting F.A.Q (Last Updated: 2024 Dec 02 3:16 pm)

We now have a ProPack Section in the Poser FreeStuff.
Check out the new Poser Python Wish List thread. If you have an idea for a script, jot it down and maybe someone can write it. If you're looking to write a script, check out this thread for useful suggestions.

Also, check out the official Python site for interpreters, sample code, applications, cool links and debuggers. This is THE central site for Python.

You can now attach text files to your posts to pass around scripts. Just attach the script as a txt file like you would a jpg or gif. Since the forum will use a random name for the file in the link, you should give instructions on what the file name should be and where to install it. Its a good idea to usually put that info right in the script file as well.

Checkout the Renderosity MarketPlace - Your source for digital art content!



Subject: Hack: Cleam morphs covered by specific materials


adp001 ( ) posted Tue, 06 April 2021 at 4:36 AM · edited Sun, 19 January 2025 at 1:56 PM

For a special case I needed a script able to clean a morph if that morph touches a certain material. So I made one (not very well tested, but it seems to work):

from __future__ import division, print_function

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

import sys, wx
if sys.version_info.major > 2:
    # Python 3 (Poser 12 and above)
    basestring = str
    from importlib import reload

    map = lambda a, b: [a(_b) for _b in b]
    newIdRef = wx.NewIdRef
else:
    # Python 2 (Poser 11 and below)
    newIdRef = wx.NewId


def find_polys(polys, materialindexlist):
    """Find and return polygons with material index contained in materialindexlist."""
    poly_indices = list()
    for idx, poly in enumerate(polys): # type: (int, poser.PolygonType)
        if poly.MaterialIndex() in materialindexlist:
            poly_indices.append(idx)

    return poly_indices


def verts_from_polys(geom, polyindices):
    """Find and return vertices contained in polygons."""
    assert isinstance(geom, poser.GeomType)
    assert isinstance(polyindices, list)
    vertexindices = list()
    sets = geom.Sets()
    polys = geom.Polygons()

    for polyidx in polyindices:
        p = polys[polyidx]  # type: poser.PolygonType
        vertexindices.extend(sets[p.Start():p.Start()+p.NumVertices()])

    return vertexindices


def reset_morphs_in_material(figure, materiallist, morphlist=None):
    assert isinstance(figure, poser.FigureType)
    if isinstance(materiallist, basestring):
        materiallist = [materiallist, ]
    if isinstance(morphlist, basestring):
        morphlist = [morphlist, ]
    assert hasattr(materiallist, "__iter__")
    assert hasattr(morphlist, "__iter__")

    # Make a list of materialnames from figure.
    figure_matnames = [m.Name() for m in figure.Materials()]

    # Convert all materials in materiallist to index positions.
    # materiallist must contain strings or poser.Material objects.
    try:
        materiallist = [figure_matnames.index(m if isinstance(m, basestring) else m.Name())
                        for m in materiallist]
    except AttributeError:
        print("One or more materials is not string or ")
        return None
    except IndexError:
        print("One or more Materialnames could not be found.")
        return None

    for ac in [_ac for _ac in figure.Actors() if _ac.IsBodyPart()]:  # type: poser.ActorType
        if hasattr(ac, "Geometry"):
            geom = ac.Geometry()
            if not geom or geom.NumVertices() == 0:
                continue
            vertex_indices = verts_from_polys(geom, find_polys(geom.Polygons(), materiallist))
            if len(vertex_indices) != 0:
                for morph in [p for p in ac.Parameters() if p.IsMorphTarget()]:  # type: poser.ParmType
                    if morphlist is not None and morph not in morphlist:
                        continue

                    if morph.NumMorphTargetDeltas() != 0:
                        cnt = 0
                        for idx in range(geom.NumVertices()):
                            v = morph.MorphTargetDelta(idx)
                            if v[0] != 0 or v[1] != 0 or v[2] != 0:
                                if idx in vertex_indices:
                                    cnt += 1
                                    morph.SetMorphTargetDelta(idx, 0, 0, 0)
                        if cnt:
                            print(cnt, "morph vertices in", ac.Name(), ">", morph.Name())

Usage:

reset_morphs_in_material(figure, materiallist, morphlist)

"morphlist" is a list of morphnames or None. In case of None all morphs are used.

"materiallist" is a list of materialnames or poser.Materials(). Vertices contained in a morph and covered by one of the named materials are set to 0.

I used this to clean up morphs for hair with a lot of materialgroups. And for cloth to clean "buttons". It's faster and easier as using the morphbrush :)




an0malaus ( ) posted Thu, 08 April 2021 at 10:33 AM

Nice! :-)



My ShareCG Stuff

Verbosity: Profusely promulgating Graham's number epics of complete and utter verbiage by the metric monkey barrel.


adp001 ( ) posted Thu, 08 April 2021 at 11:07 AM · edited Thu, 08 April 2021 at 11:08 AM

Thanks. But it wont work with a morphlist, because I forgot ".Name()" after "morph" :)

Here is a working version:

from __future__ import division, print_function

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

import sys, wx
if sys.version_info.major > 2:
    # Python 3 (Poser 12 and above)
    basestring = str
    from importlib import reload

    map = lambda a, b: [a(_b) for _b in b]
    newIdRef = wx.NewIdRef
else:
    # Python 2 (Poser 11 and below)
    newIdRef = wx.NewId


def find_polys(polys, materialindexlist):
    """Find and return polygons with material index contained in materialindexlist."""
    poly_indices = list()
    for idx, poly in enumerate(polys): # type: (int, poser.PolygonType)
        if poly.MaterialIndex() in materialindexlist:
            poly_indices.append(idx)

    return poly_indices


def verts_from_polys(geom, polyindices):
    """Find and return vertices contained in polygons."""
    assert isinstance(geom, poser.GeomType)
    assert isinstance(polyindices, list)
    vertexindices = list()
    sets = geom.Sets()
    polys = geom.Polygons()

    for polyidx in polyindices:
        p = polys[polyidx]  # type: poser.PolygonType
        vertexindices.extend(sets[p.Start():p.Start()+p.NumVertices()])

    return vertexindices


def reset_morphs_in_material(figure, materiallist, morphlist=None):
    assert isinstance(figure, poser.FigureType)
    if isinstance(materiallist, basestring):
        materiallist = [materiallist, ]
    if isinstance(morphlist, basestring):
        morphlist = [morphlist, ]
    assert hasattr(materiallist, "__iter__")
    assert hasattr(morphlist, "__iter__")

    # Make a list of materialnames from figure.
    figure_matnames = [m.Name() for m in figure.Materials()]

    # Convert all materials in materiallist to index positions.
    # materiallist must contain strings or poser.Material objects.
    try:
        materiallist = [figure_matnames.index(m if isinstance(m, basestring) else m.Name())
                        for m in materiallist]
    except AttributeError:
        print("One or more materials is not string or ")
        return None
    except IndexError:
        print("One or more Materialnames could not be found.")
        return None

    for ac in [_ac for _ac in figure.Actors() if _ac.IsBodyPart()]:  # type: poser.ActorType
        if hasattr(ac, "Geometry"):
            geom = ac.Geometry()
            if not geom or geom.NumVertices() == 0:
                continue
            vertex_indices = verts_from_polys(geom, find_polys(geom.Polygons(), materiallist))
            if len(vertex_indices) != 0:
                for morph in [p for p in ac.Parameters() if p.IsMorphTarget()]:  # type: poser.ParmType
                    if morphlist is not None and morph.Name() not in morphlist:
                        continue

                    if morph.NumMorphTargetDeltas() != 0:
                        cnt = 0
                        for idx in range(geom.NumVertices()):
                            v = morph.MorphTargetDelta(idx)
                            if v[0] != 0 or v[1] != 0 or v[2] != 0:
                                if idx in vertex_indices:
                                    cnt += 1
                                    morph.SetMorphTargetDelta(idx, 0, 0, 0)
                        if cnt:
                            print(cnt, "morph vertices in", ac.Name(), ">", morph.Name())




Privacy Notice

This site uses cookies to deliver the best experience. Our own cookies make user accounts and other features possible. Third-party cookies are used to display relevant ads and to analyze how Renderosity is used. By using our site, you acknowledge that you have read and understood our Terms of Service, including our Cookie Policy and our Privacy Policy.