Forum: Poser Python Scripting


Subject: Is there a way to support Undo with LoadLibraryPose

yarp opened this issue on Apr 23, 2021 ยท 28 posts


adp001 posted Tue, 27 April 2021 at 2:50 PM

formoz posted at 2:26PM Tue, 27 April 2021 - #4417828

tested it, i had a poser crash and i chased down the culprit :

rFoot:6
key: NumbSubdivRenderLevels, MemorizedValue: '0', CurrentValue:'0'
key: ShadingRate, MemorizedValue: '0.20000000298', CurrentValue:'0.20000000298'
key: VisibleInIDL, MemorizedValue: '1', CurrentValue:'1'
key: VisibleInReflections, MemorizedValue: '1', CurrentValue:'1'
key: CreaseAngle, MemorizedValue: '80.0', CurrentValue:'80.0'
key: Parent, MemorizedValue: 'Actor object at 0x0000000013F215D0', CurrentValue:'Actor object at 0x0000000010CD1DF8'
key: VisibleInRender, MemorizedValue: '1', CurrentValue:'1'
key: SmoothPolys, MemorizedValue: '1', CurrentValue:'1'
key: AnimatableOrigin, MemorizedValue: '0', CurrentValue:'0'
key: BackfaceCull, MemorizedValue: '0', CurrentValue:'0'
key: DisplayStyle, MemorizedValue: '4', CurrentValue:'4'
key: Name, MemorizedValue: 'Right Foot', CurrentValue:'Right Foot'
key: Geometry, MemorizedValue: 'Geom object at 0x0000000013F3CF30', CurrentValue:'Geom object at 0x0000000013F51F90'
key: CastsShadows, MemorizedValue: '1', CurrentValue:'1'
key: AlignmentRotationXYZ, MemorizedValue: '(5.164360046386719, -7.982140064239502, -3.025599956512451)', CurrentValue:'(5.164360046386719, -7.982140064239502, -3.025599956512451)'
key: Orientation, MemorizedValue: '(5.164360046386719, -7.982140064239502, -3.025599956512451)', CurrentValue:'(5.164360046386719, -7.982140064239502, -3.025599956512451)'
key: Origin, MemorizedValue: '(-0.02469700016081333, 0.031172700226306915, -0.019022399559617043)', CurrentValue:'(-0.02469700016081333, 0.031172700226306915, -0.019022399559617043)'
key: NumbSubdivLevels, MemorizedValue: '0', CurrentValue:'0'
key: Bends, MemorizedValue: '1', CurrentValue:'1'
key: SubdivideWithFigure, MemorizedValue: '1', CurrentValue:'1'
key: VisibleInCamera, MemorizedValue: '1', CurrentValue:'1'
key: Visible, MemorizedValue: '1', CurrentValue:'1'
key: Static, MemorizedValue: '1', CurrentValue:'1'
key: DisplayOrigin, MemorizedValue: '0', CurrentValue:'0'
key: DisplacementBounds, MemorizedValue: '0.0', CurrentValue:'0.0'
key: OnOff, MemorizedValue: '1', CurrentValue:'1'

i had to remove "Parent" from collected attribs to avoid the crash, astonishly it didn't crash on geometry change. but i do'nt understand why the geometry changed while i changed it before collect and not after.

I didn't have any trouble with "Parent" in my tests. But I have a clue why it comes to an error condition.

The script stores the "real reference". But this reference (actually more or less a memory address) may be dropped by Posers internal engine without notification. I know of this and avoid it usually by storing "InternalName" instead of the address.

function "collectActor" and "undoActor" should be changed to do exactly this: Storing/restoring the InternalName (including a test if this actor still exists). Having parents restored should be part of "Undo".

here we go:

def collectActor(actor, parmcodes=None, include_morphs=True):
    parms = collect_parms(actor, parmcodes=parmcodes, include_morphs=include_morphs)
    actor_dict = dict(Parameters=parms, InternalName=actor.InternalName())
    for name in dir(poser.ActorType):
        if name.startswith("Set"):
            attr_name = name[3:]
            if attr_name in ("EndPoint",):
                continue
            elif attr_name == "Parent":
                value = actor.Parent().InternalName()
            else:
                try:
                    value = getattr(actor, attr_name)()
                except Exception:
                    continue
            actor_dict[attr_name] = value
    return actor_dict


def undoActor(actor, actor_dict, include_morphs=True):
    assert isinstance(actor, poser.ActorType)
    for key, value in actor_dict.items():
        if key == "Parameters":
            set_parms(actor, value, include_morphs=include_morphs)
        elif key == "Parent":
            try:
                actor.SetParent(poser.Scene().ActorByInternalName(value))
            except poser.error:
                continue
        elif key != "InternalName":
            if getattr(actor, key)() != value:
                try:
                    getattr(actor, "Set%s" % key)(value)
                except poser.error:
                    pass

Maybe this hack may not work as expected at the end, because "SetParent" can have more than just the actor as parameter ('inheritBends' and 'realign*; both set to 0 by default).