Forum: Poser Python Scripting


Subject: Move morph as a whole in any direction

adp001 opened this issue on Aug 14, 2020 ยท 7 posts


adp001 posted Fri, 14 August 2020 at 8:19 AM

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()