Filter: Safe | Wed, Apr 29, 11:45 AM CDT

Renderosity Forums / Poser Python Scripting



Welcome to the Poser Python Scripting Forum

Forum Moderators: Lobo3433, Staff Forum Coordinators: Anim8dtoon

Poser Python Scripting F.A.Q (Last Updated: 2026 Apr 22 10:09 am)

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: Move morph as a whole in any direction


adp001 ( ) posted Fri, 14 August 2020 at 8:19 AM ยท edited Mon, 27 April 2026 at 6:40 PM

I made a morph. Nothing special. But then I thought: The whole morph should move a bit to the right.

Tried it with Posers morph brush: Didn*t work.

So I made a little script to do the job. Fine. For this one.

Based on this idea I made a script that can move a morph by letting it follow to the movement of another object (a prop?).

It's really simple:

    morphdata = collect_morphdata(morph)
    orig_coords = last_coords = move_actor.WorldDisplacement()

    def tloop():
        global orig_coords, last_coords, morphdata
        t = 300
        if StopFlag:
            update_morph(morph, morphdata, [0, 0, 0])
            SCENE.DrawAll()
            print("STOPPED")
            return

        coords = move_actor.WorldDisplacement()
        if coords != last_coords:
            last_coords = coords
            diff = zip_sub(coords, orig_coords)
            update_morph(morph, morphdata, zip_mul(diff, .5))
            SCENE.DrawAll()
            t = 100

        wx.CallLater(t, tloop)

    tloop()

For a demonstration: Load a figure. Create a morph named "ABC" in the "Chest" actor. Load any prop, name it "Mover". Start the following (complete) script:

from __future__ import print_function
import wx

SCENE = poser.Scene()
StopFlag = False
morphdata = None
orig_coords = None
last_coords = None


def collect_morphdata(morphparam):
    assert isinstance(morphparam, poser.ParmType)
    ar = list()
    for idx in range(morphparam.Actor().Geometry().NumVertices()):
        x, y, z = morphparam.MorphTargetDelta(idx)
        if x != 0 or y != 0 or z != 0:
            ar.append((idx, x, y, z))
    return ar


def update_morph(morphparam, ar, offset):
    assert isinstance(morphparam, poser.ParmType)
    assert isinstance(ar, list)

    for idx, x, y, z in ar:
        morphparam.SetMorphTargetDelta(idx, x + offset[0], y + offset[1], z + offset[2])


def zip_sub(a, b):
    if isinstance(b, (int, float)):
        return [n - b for n in a]
    else:
        return [x - y for x, y in zip(a, b)]


def zip_add(a, b):
    if isinstance(b, (int, float)):
        return [n + b for n in a]
    else:
        return [x + y for x, y in zip(a, b)]


def zip_mul(a, b):
    if isinstance(b, (int, float)):
        return [n * b for n in a]
    else:
        return [x * y for x, y in zip(a, b)]


class Aborted(Exception):
    pass


try:
    try:
        move_actor = SCENE.Actor("Mover")
    except poser.error:
        raise Aborted("Make sure an actor named 'Mover' exists.")

    try:
        body_actor = SCENE.CurrentFigure().Actor("Chest")
    except poser.error:
        raise Aborted("Make sure a figure with an actor named 'Chest' exists.")

    morph = body_actor.Parameter("ABC")
    if not morph:
        raise Aborted("Make sure a morph named 'ABC' exist in actor 'Chest'.")

except Aborted as err:
    print(err)
    print("Nothing done.")

else:
    print("Started - move object 'mover'")
    print("ATTENTION: update occurs after releasing the mouse.")
    print()
    print("Enter 'StopFlag=True' in a Python console to stop and reset the morph.")

    morphdata = collect_morphdata(morph)
    orig_coords = last_coords = move_actor.WorldDisplacement()

    def tloop():
        global orig_coords, last_coords, morphdata
        t = 300
        if StopFlag:
            update_morph(morph, morphdata, [0, 0, 0])
            SCENE.DrawAll()
            print("STOPPED")
            return

        coords = move_actor.WorldDisplacement()
        if coords != last_coords:
            last_coords = coords
            diff = zip_sub(coords, orig_coords)
            update_morph(morph, morphdata, zip_mul(diff, .5))
            SCENE.DrawAll()
            t = 100

        wx.CallLater(t, tloop)

    tloop()




HartyBart ( ) posted Sat, 22 August 2020 at 3:14 PM ยท edited Sat, 22 August 2020 at 3:15 PM

I tried it with a NosePointed nose morph, located in the Head....

        body_actor = SCENE.CurrentFigure().Actor("Head")
    except poser.error:
        raise Aborted("Make sure a figure with an actor named 'Head' exists.")

    morph = body_actor.Parameter("NosePointed")
    if not morph:
        raise Aborted("Make sure a morph named 'NosePointed' exist in actor 'Head'.")

But it had no effect at all on the nose, on moving and then releasing the Mover cube. The messages from the script appeared to be the standard guidance, not errors. Does it only work on certain types of morphs?



Learn the Secrets of Poser 11 and Line-art Filters.


adp001 ( ) posted Sun, 23 August 2020 at 4:06 AM

Any morph with delta-information will do (created with the morph-brush for example).

If you dial the morph from the Poser Palette – does anything happen? If yes, the script should be able to work with it.




bwldrd ( ) posted Sun, 23 August 2020 at 10:36 AM ยท edited Sun, 23 August 2020 at 10:39 AM

Pretty neat. Also found out that if you delete the mover, it hides the polys the morph was affecting, while set at anything other than 0. This could be a cool way to add transparency to a mesh without using a map.

--------------------------------------------------------------------------------

Consider me insane if you wish, but is your reality any better?


adp001 ( ) posted Sun, 23 August 2020 at 11:28 AM ยท edited Sun, 23 August 2020 at 11:28 AM

If the Mover is deleted, nothing should actually happen. The last known morph state remains as it is and is not changed anymore. "update_morph" is no longer called.

But: Actually, there should be an error message, because "move_actor.WorldDisplacement()" cannot be executed by Poser anymore (the "move_actor" is gone).

The script here is not intended for production. In order to use the method in a meaningful way, a little bit more work is needed around it.




adp001 ( ) posted Sun, 23 August 2020 at 12:02 PM ยท edited Sun, 23 August 2020 at 12:03 PM

A Warning!

Don't try scripts like this with Python-Threads! Poser is not thread-safe and may crash if you update data Poser is also using.




adp001 ( ) posted Sun, 12 September 2021 at 7:53 AM ยท edited Sun, 12 September 2021 at 7:55 AM

And a new one. This time able to translate and rotate morphs!

Bildschirmfoto vom 2021-09-12 14-18-15.png

The "Mover" is a cube generated on the fly. (green if inactive, red if active). Grab that cube and move it around (after you selected an actor and a morph and clicked "Start"). Or use the dials to position more exactly. The morph will follow the movement.

This is not new. But now you can rotate the "mover" and your morph will rotate! Rotation center is the position of the mover. This is why "No Translation" exist: If you check it, you can move the mover to a new position to set a rotation center.

Note: It may last a moment after pressing "Start" until the "mover" appears. Poser has to create that new grouping object first.

I'll post the source here, but to be sure better download it from here, because the editor here may destray parts of the script. And the source code is more readable on my website.

Download from here.

from __future__ import print_function

import math
import sys

import numpy as NP
import 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()
X, Y, Z = range(3)


def actor_has_geom(ac):
    return isinstance(ac, poser.ActorType) 
           and hasattr(ac, "Geometry") 
           and ac.Geometry() is not None 
           and ac.Geometry().NumVertices() > 0


def is_morphtarget(parm):
    return isinstance(parm, poser.ParmType) 
           and parm.IsMorphTarget() 
           and parm.NumMorphTargetDeltas() != 0


def _rotate(ar, theta, axis=(0, 0, 0), order="XYZ"):
    AX, AY, AZ = axis

    def _X(c, s, ar=ar):
        return NP.dot(ar, NP.array([
            [1.0, AY, AZ],
            [AX, c, -s],
            [AX, s, c]
        ]))

    def _Y(c, s, ar=ar):
        return NP.dot(ar, NP.array([
            [c, AY, -s],
            [AX, 1.0, AZ],
            [s, AY, c]
        ]))

    def _Z(c, s, ar=ar):
        return NP.dot(ar, NP.array([
            [c, -s, AZ],
            [s, c, AZ],
            [AX, AY, 1.0],
        ]))

    for entry in order.upper():
        idx = "XYZ".index(entry)
        ar = locals().get("_" + entry)(math.cos(theta[idx]), math.sin(theta[idx]), ar)

    return ar


def rotated_poserVerts(verts, theta, order):
    return _rotate(NP.array([[v.X(), v.Y(), v.Z()] for v in verts]), theta, order)


def rotate_actor(actor, theta, order):
    if isinstance(actor, basestring):
        try:
            actor = SCENE.Actor(actor)
        except poser.error:
            actor = SCENE.ActorByInternalName(actor)
    geom = actor.Geometry()
    for verts, vv in zip(rotated_poserVerts(geom.Vertices(), theta, order), geom.Vertices()):
        vv.SetX(verts[0])
        vv.SetY(verts[1])
        vv.SetZ(verts[2])


class Mover(object):
    """
    This class uses Posers callbacks. Because of this no Poser object
    can be directly hold in a variable (actor, morph, etc.).
    Internal names are used instead to avoid crashes.
    """

    __slots__ = "_saved_active", 
                "_figure_iname", "_moveactor_iname", "_morphactor_iname", "_morphname", 
                "morphindices", "morphdata", "morph_origdata", "morphcenter", 
                "_morph_min", "_morph_max", 
                "mover_startpos", "last_coords", "use_trans", "use_rot", 
                "current_rotation"

    def __init__(self, morphparameter):
        assert is_morphtarget(morphparameter), "Parameter has no Morphdata."
        assert actor_has_geom(morphparameter.Actor()), "Actor to morph must have Geometry."

        self.last_coords = NP.array([0, 0, 0], NP.float)
        self.current_rotation = NP.array([0, 0, 0], NP.float)

        self._saved_active = [False, ]
        self._figure_iname = None
        self._morphname = self._morphactor_iname = None
        self._moveactor_iname = None
        self.morphindices = self.morphdata = self.morph_origdata = None
        self.use_trans = self.use_rot = False

        self.createMover()
        self.setmorph(morphparameter)
        self.morphcenter = self.get_morph_center(False)

        self._morph_min, self._morph_max = self.get_morph_minmax(True)
        self.mover_startpos = self.mover_defaultpos()
        self.move_mover(self.mover_startpos)
        self.set_movercolor(0, 255, 0)

        SCENE.DrawAll()

    @property
    def active(self):
        return self._saved_active[-1]

    @property
    def morphactor(self):
        try:
            return SCENE.ActorByInternalName(self._morphactor_iname)
        except poser.error:
            print("Actor '%s' does not exist anymore." % self._morphactor_iname)
            self.stop()

    @morphactor.setter
    def morphactor(self, actor):
        if actor is None:
            self._morphactor_iname = None
        else:
            assert isinstance(actor, poser.ActorType)
            self._morphactor_iname = actor.InternalName()

    @property
    def moveactor(self):
        try:
            return SCENE.ActorByInternalName(self._moveactor_iname)
        except poser.error:
            print("Move actor does not exist anymore.")
            self.stop()


    @moveactor.setter
    def moveactor(self, actor):
        if actor is None:
            self._moveactor_iname = None
        else:
            assert isinstance(actor, poser.ActorType)
            self._moveactor_iname = actor.InternalName()

    @property
    def figure(self):
        try:
            return SCENE.FigureByInternalName(self._figure_iname)
        except poser.error:
            return None

    @figure.setter
    def figure(self, figure):
        if figure is None:
            self._figure_iname = None
        else:
            assert isinstance(figure, poser.FigureType)
            self._figure_iname = figure.InternalName()

    @property
    def morph(self):
        try:
            return self.morphactor.Parameter(self._morphname)
        except Exception:
            print("Morph '%s' does not exist anymore." % self._morphname)

    @morph.setter
    def morph(self, parameter):
        assert isinstance(parameter, poser.ParmType)
        self._morphname = parameter.InternalName()

    def mover_defaultpos(self):
        c = NP.array(self.get_morph_center(True))
        c[2] = self._morph_max[2] + 0.02
        return c

    def push_active(self, v):
        self._saved_active.append(bool(v))
        return v

    def pop_active(self):
        return None if not self._saved_active 
            else self._saved_active.pop()

    def start(self):
        SCENE.SelectFigure(self.figure)
        self._saved_active = [False, ]
        self.reset_mover()
        self._start_mover()
        self.set_movercolor(255, 0, 0)
        self._saved_active = [True, ]
        SCENE.SelectActor(self.moveactor)

    def stop(self):
        SCENE.SelectFigure(self.figure)
        self._saved_active = [False, ]
        self._stop_mover()
        self.set_movercolor(0, 255, 0)

    def set_movercolor(self, r, g, b):
        s = self.moveactor.Material("Preview").ShaderTree()
        s.Node(0).Input(0).SetColor(r, g, b)
        s.UpdatePreview()

    def setmorph(self, morphparm):
        self.push_active(False)
        if isinstance(morphparm, basestring):
            morphparm = SCENE.CurrentActor().Parameter(morphparm)

        if is_morphtarget(morphparm):
            self.morph = morphparm
            self.morphactor = ac = morphparm.Actor()

            fig = ac.ItsFigure() if ac.IsBodyPart() else SCENE.Figures()[0]
            self.figure = fig if fig else None

            numv = ac.Geometry().NumVertices()
            self.morph_origdata = NP.array([morphparm.MorphTargetDelta(idx)
                                            for idx in range(numv)])
            self.morphindices = NP.array([idx for idx, v in enumerate(self.morph_origdata)
                                          if not all(v == (0, 0, 0))], NP.int32)
            self.morphdata = self.morph_origdata[self.morphindices]

        else:
            print("Choosen Parameter is not a morphtarget with geometry.")
            print("Actor:", self._morphactor_iname, "- Parameter:", self._morphname)

        self.pop_active()

    def rotate_morphdata(self, theta, order):
        if not self.use_rot:
            self.morphdata = _rotate(self.morphdata, theta, self.morphcenter, order=order)

    def update_morph(self):
        """
        Called from callbacks if mover was moved or
        rotated and morph needs to be updated.
        """
        self.last_coords = NP.array(self.moveactor.WorldDisplacement())
        diff = [0, 0, 0] if self.use_trans 
            else (self.last_coords - self.mover_startpos) * .25
        ar = self.morphdata + diff
        m = self.morph
        for idx, (x, y, z) in zip(self.morphindices, ar):
            m.SetMorphTargetDelta(idx, x, y, z)
        SCENE.DrawAll()

    def undo_morph(self):
        m = self.morph
        if m:
            for idx in self.morphindices:
                x, y, z = self.morph_origdata[idx]
                m.SetMorphTargetDelta(idx, x, y, z)
            self.morphdata = self.morph_origdata.copy()
            self.mover_startpos = self.moveactor.WorldDisplacement()
            SCENE.DrawAll()

    def current_morph_permanent(self):
        self.push_active(False)
        self.update_morph()  # make sure last changes are done.
        self.setmorph(self.morph)  # setting it will take the data currently in morph
        center = self.get_morph_center(True)
        self.morphcenter = center
        self.mover_startpos = self.mover_defaultpos()
        self.move_mover(self.mover_startpos)
        SCENE.DrawAll()
        self.pop_active()

    def get_morph_minmax(self, world=False):
        geom = self.morph.Actor().Geometry()
        verts = NP.array([[v.X(), v.Y(), v.Z()]
                          for v in (geom.WorldVertices() if world else geom.Vertices())])
        verts = verts[self.morphindices] + NP.array([self.morph.MorphTargetDelta(i)
                                                     for i in self.morphindices])
        return NP.min(verts, axis=0), NP.max(verts, axis=0)

    def get_morph_center(self, world=False):
        """:rtype: NP.ndarray"""
        _min, _max = self.get_morph_minmax(world)
        return _min + (_max - _min) / 2.0

    def __trans__(self, parm, value):
        """Callback on translation changes."""
        if self.active:
            idx = [poser.kParmCodeXTRAN, poser.kParmCodeYTRAN, poser.kParmCodeZTRAN].index(parm.TypeCode())
            if self.last_coords[idx] != parm.Actor().WorldDisplacement()[idx]:
                self.update_morph()
        return value

    def __rot__(self, parm, value):
        """Callback on rotation changes."""
        if self.active:
            idx = [poser.kParmCodeXROT, poser.kParmCodeYROT, poser.kParmCodeZROT].index(parm.TypeCode())
            r = math.radians(value)
            if self.current_rotation[idx] != r:
                self.current_rotation[idx] = r
                self.rotate_morphdata(self.current_rotation, "XYZ"[idx])
                self.update_morph()
        return value

    def createMover(self):
        try:
            ac = SCENE.Actor("MorphMover")
        except poser.error:
            ac = SCENE.CreateGrouping()
            ac.SetName("MorphMover")
            ac.ParameterByCode(poser.kParmCodeASCALE).SetValue(.15)
            ac.SetDisplayStyle(poser.kDisplayCodeFLATLINED)
        ac.SetVisible(True)
        self._moveactor_iname = ac.InternalName()
        return ac

    def move_mover(self, coords):
        ma = self.moveactor
        if ma:
            self.push_active(False)
            ma.ParameterByCode(poser.kParmCodeXTRAN).SetValue(coords[X])
            ma.ParameterByCode(poser.kParmCodeYTRAN).SetValue(coords[Y])
            ma.ParameterByCode(poser.kParmCodeZTRAN).SetValue(coords[Z])
            self.last_coords = NP.array(coords, NP.float)
            SCENE.DrawAll()
            self.pop_active()

    def reset_mover(self):
        ma = self.moveactor
        if ma:
            self.mover_startpos = NP.array(self.moveactor.WorldDisplacement())
            self.move_mover(self.mover_startpos)

    def _start_mover(self):
        ma = self.moveactor
        if ma:
            for code in (poser.kParmCodeXROT, poser.kParmCodeYROT, poser.kParmCodeZROT):
                p = ma.ParameterByCode(code)
                p.SetValue(0)
                p.SetUpdateCallback(self.__rot__)

            for code in (poser.kParmCodeXSCALE, poser.kParmCodeYSCALE, poser.kParmCodeZSCALE):
                v = ma.ParameterByCode(code).Value()
                ma.ParameterByCode(code).SetUpdateCallback(lambda a, b: v)

            for code in (poser.kParmCodeXTRAN, poser.kParmCodeYTRAN, poser.kParmCodeZTRAN):
                ma.ParameterByCode(code).SetUpdateCallback(self.__trans__)

    def _stop_mover(self):
        ma = self.moveactor
        if ma:
            for code in (poser.kParmCodeXTRAN, poser.kParmCodeYTRAN, poser.kParmCodeZTRAN,
                         poser.kParmCodeXROT, poser.kParmCodeYROT, poser.kParmCodeZROT,
                         poser.kParmCodeASCALE,
                         poser.kParmCodeXSCALE, poser.kParmCodeYSCALE, poser.kParmCodeZSCALE):
                ma.ParameterByCode(code).ClearUpdateCallback()
            for code in (poser.kParmCodeXROT, poser.kParmCodeYROT, poser.kParmCodeZROT):
                ma.ParameterByCode(code).SetValue(0)
            for code in (poser.kParmCodeXSCALE, poser.kParmCodeYSCALE, poser.kParmCodeZSCALE):
                ma.ParameterByCode(code).SetValue(1)


# ----------------------------------------------------------------
# wxPython UI related
# ----------------------------------------------------------------

def collectActornames(figure=None):
    if figure is None:
        figure = SCENE.CurrentFigure()
    return [ac.Name() for ac in (SCENE.Actors() if not figure else figure.Actors())]


def collectMorphnames(actor=None, filter=None):
    if filter is None:
        filter = lambda n: True
    if actor is None:
        actor = SCENE.CurrentActor()
    return [p.Name() for p in actor.Parameters() if filter(p.Name()) and is_morphtarget(p)]


class MyFrame(wx.Frame):
    def __init__(self, parent, *args, **kwargs):
        super(MyFrame, self).__init__(parent, wx.ID_ANY, *args, **kwargs)

        self.morph_mover = None  # type: None or Mover
        self._selected_actor = None
        self._selected_parameter = dict()
        self.init_ui()

        self.Bind(wx.EVT_CLOSE, self.ev_close)
        self.Bind(wx.EVT_SIZE, self.ev_size)
        self.Bind(wx.EVT_CHECKBOX, self.on_check)
        self.Bind(wx.EVT_BUTTON, self.on_button)
        self.Bind(wx.EVT_CHOICE, self.on_choice)

    @property
    def selected_actor(self):
        if self._selected_actor:
            try:
                return SCENE.ActorByInternalName(self._selected_actor)
            except poser.error:
                pass
        return None

    @property
    def selected_parameter(self):
        if self.selected_actor:
            return self._selected_parameter.get(self._selected_actor, None)
        return None

    def startMover(self):
        if self.morph_mover is not None:
            self.morph_mover.start()
        elif self.selected_parameter is not None:
            ac = self.selected_actor
            if ac:
                try:
                    parm = ac.Parameter(self.selected_parameter)
                    self.morph_mover = Mover(parm)
                    self.morph_mover.start()
                except poser.error:
                    print("Can't use parameter '%s' in actor '%s'." % (
                    self.selected_parameter, self.selected_actor.Name()))
        if self.morph_mover:
            self.morph_mover.use_trans = self.FindWindowByName("cb_notranslation").IsChecked()
            self.morph_mover.use_rot = self.FindWindowByName("cb_norotation").IsChecked()

    def ev_close(self, event):
        if self.morph_mover is not None:
            self.morph_mover.stop()
            self.morph_mover.moveactor.Delete()
        event.Skip()

    def ev_size(self, event):
        self.SetSize(event.Size)
        self.Refresh()
        event.Skip()

    def init_ui(self):
        panel = wx.Panel(self)
        main_sz = wx.BoxSizer(wx.VERTICAL)
        sz_standard = (0, wx.EXPAND | wx.LEFT | wx.RIGHT, 8)
        sz_choice = (0, wx.EXPAND | wx.LEFT | wx.RIGHT, 8)
        sz_check = (1, wx.ALIGN_CENTER | wx.ALL, 8)
        btn_style = wx.NO_BORDER
        choice_style = wx.CB_SORT | wx.NO_BORDER
        spacersize = 12

        main_sz.Add(wx.StaticText(panel, wx.ID_ANY, "Select Actor"), *sz_choice)
        main_sz.Add(wx.Choice(panel, wx.ID_ANY, style=choice_style, name="choice_actors",
                              choices=collectActornames()), *sz_choice)
        main_sz.AddSpacer(spacersize)
        main_sz.Add(wx.StaticText(panel, wx.ID_ANY, "Select Morph"), *sz_choice)
        main_sz.Add(
            wx.Choice(panel, wx.ID_ANY, style=choice_style, name="choice_parameters",
                      choices=collectMorphnames()), *sz_choice)
        main_sz.AddSpacer(spacersize)
        main_sz.AddStretchSpacer(1)

        btn_sz = wx.GridSizer(4, 2, vgap=2, hgap=2)
        btn_sz.Add(wx.CheckBox(panel, wx.ID_ANY, label="No Translation", name="cb_notranslation"), *sz_check)
        btn_sz.Add(wx.CheckBox(panel, wx.ID_ANY, label="No Rotation", name="cb_norotation"), *sz_check)
        btn_sz.Add(wx.Button(panel, wx.ID_ANY, label="Start", style=btn_style, name="btn_start"), *sz_standard)
        btn_sz.Add(wx.Button(panel, wx.ID_ANY, label="Stop", style=btn_style, name="btn_stop"), *sz_standard)
        btn_sz.Add(wx.Button(panel, wx.ID_ANY, label="Reload", style=btn_style, name="btn_reload"), *sz_standard)
        btn_sz.Add(wx.Button(panel, wx.ID_ANY, label="Reset Mover", style=btn_style, name="btn_reset"), *sz_standard)
        btn_sz.Add(wx.Button(panel, wx.ID_ANY, label="Reset Morph", style=btn_style, name="btn_undo"), *sz_standard)
        btn_sz.Add(wx.Button(panel, wx.ID_ANY, label="Morph Permanent", style=btn_style, name="btn_permanent"),
                   *sz_standard)
        main_sz.Add(btn_sz, 0, wx.ALIGN_CENTER)
        main_sz.AddSpacer(spacersize)

        main_sz.AddStretchSpacer(1)
        main_sz.Layout()
        panel.SetSizer(main_sz)

        self.reload_actors()

    def reload_actors(self):
        ac = SCENE.CurrentActor()
        self._selected_actor = ac.InternalName()
        ac_choice = self.FindWindowByName("choice_actors")
        ac_choice.Clear()
        map(ac_choice.Append, collectActornames(None if not hasattr(ac, "ItsFigure")
                                                else ac.ItsFigure()))
        ac_choice.SetStringSelection(ac.Name())
        self.reload_parms()

    def reload_parms(self):
        ac = self.selected_actor
        if ac:
            choice = self.FindWindowByName("choice_parameters")  # type: wx.Choice
            choice.Clear()
            for name in collectMorphnames(ac, filter=lambda n: n[0] not in ".-"):
                choice.Append(name)
            sel = self.selected_parameter
            if not sel:
                sel = choice.GetString(0)
                self._selected_parameter[self._selected_actor] = sel
            choice.SetStringSelection(sel)

    def on_check(self, event):
        obj = event.GetEventObject()  # type: wx.CheckBox
        name = obj.Name.lower()
        if self.morph_mover:
            if "notrans" in name:
                self.morph_mover.use_trans = obj.IsChecked()
            if "norot" in name:
                self.morph_mover.use_rot = obj.IsChecked()
            self.morph_mover.update_morph()

    def on_button(self, event):
        obj = event.GetEventObject()  # type: wx.Button
        name = obj.Name.lower()
        if "start" in name:
            self.startMover()
        elif "stop" in name:
            self.morph_mover.stop()
        elif "reload" in name:
            self.reload_actors()
        elif "reset" in name:
            self.morph_mover.reset_mover()
        elif "undo" in name:
            self.morph_mover.undo_morph()
        elif "permanent" in name:
            self.morph_mover.current_morph_permanent()

    def on_choice(self, event):
        obj = event.GetEventObject()  # type: wx.Choice
        name = obj.Name.lower()
        sel_str = obj.GetStringSelection()
        if "actor" in name:
            self._selected_actor = SCENE.Actor(sel_str).InternalName()
            self.reload_parms()
        elif "parameter" in name:
            self._selected_parameter[self._selected_actor] = sel_str
            if self.morph_mover is not None:
                self.morph_mover.stop()
                self.morph_mover = None
                self.startMover()


if __name__ == "__main__":
    app = poser.WxApp()
    aui = poser.WxAuiManager()  # type: wx.aui.AuiManager
    root = aui.GetManagedWindow()  # type: wx.Window
    main = MyFrame(root)
    main.Show()

By the way: This is not meant for production but to show and test what is possible with Poser Python.




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.