yarp opened this issue on Apr 23, 2021 ยท 28 posts
adp001 posted Sat, 24 April 2021 at 11:58 AM
I tried to make a "discrete" Undo before. Turns out it is slower than saving the whole scene. But maybe you can use something of it to play around:
from __future__ import print_function
import sys
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
def actor_hasgeom(ac):
assert isinstance(ac, poser.ActorType)
return hasattr(ac, "Geometry")
and ac.Geometry() is not None
and ac.Geometry().NumVertices() > 0
def collect_parms(actor, include_morphs=True):
assert isinstance(actor, poser.ActorType)
geom = actor.Geometry() if actor_hasgeom(actor) else None
parm_dict = dict()
for parm in actor.Parameters(): # type: poser.ParmType
d = parm_dict.setdefault(parm.InternalName(), dict())
for entry in dir(poser.ParmType):
if "MorphTargetDelta" in entry:
# This is a special case
if entry.startswith("Set"):
# This one isn't needed here.
continue
morph = list()
if geom is not None and include_morphs and parm.IsMorphTarget():
for i in range(geom.NumVertices()):
x, y, z = parm.MorphTargetDelta(i)
if x != 0 or y != 0 or z != 0:
morph.append((i, x, y, z))
d["MorphTargetDelta"] = morph or None
elif entry.startswith("Set"):
# For an undo we need to save anything we can "Set"
attr_name = entry[3:]
if attr_name in ("ValueFrame", "RangeConstant", "RangeLinear", "RangeSpline",
"SplineBreak", "UpdateCallback"):
# ignore this in this version...
continue
value = getattr(parm, attr_name)()
d[attr_name] = value
parm_dict[parm.InternalName()] = d
return parm_dict
def collectFigure(figure):
actor_dict = dict()
for actor in figure.Actors():
actor_dict[actor.InternalName()] = collect_parms(actor, include_morphs=True)
return actor_dict
def collectLights():
light_dict = dict()
for light in poser.Scene().Lights():
light_dict[light.InternalName()] = collect_parms(light)
return light_dict
def collectCams():
cam_dict = dict()
for cam in poser.Scene().Cameras():
cam_dict[cam.InternalName()] = collect_parms(cam)
return cam_dict
def collectProps():
prop_dict = dict()
for prop in [ac for ac in poser.Scene().Actors() if ac.IsProp()]:
prop_dict[prop.InternalName()] = collect_parms(prop)
return prop_dict
def set_parms(actor, parm_dicts):
assert isinstance(actor, poser.ActorType)
assert isinstance(parm_dicts, dict)
for parm_name, parm_dict in parm_dicts.items():
parm = actor.Parameter(parm_name)
if not parm:
continue
for parm_key, parm_value in parm_dict.items():
if parm_key == "MorphTargetDelta":
if parm_value is not None:
for entry in parm_value:
parm.SetMorphTargetDelta(*entry)
else:
attr_name = "Set%s" % parm_key
getattr(parm, attr_name)(parm_value)
def undo_figure(figure, actor_dict):
print("Undo figure", end=" ")
assert isinstance(figure, poser.FigureType)
inames = set(ac.InternalName() for ac in figure.Actors())
for key, value in actor_dict.items():
print(key, end=" ")
poser.Scene().ProcessSomeEvents()
if key in inames:
set_parms(figure.ActorByInternalName(key), value)
print("Done")
def undo_lights(light_dict):
print("Undo lights", end=" ")
inames = set(ac.InternalName() for ac in poser.Scene().Lights())
for key, value in light_dict.items():
print(key, end=" ")
if key in inames:
set_parms(poser.Scene().ActorByInternalName(key), value)
print("Done")
def undo_cams(cam_dict):
print("Undo cams", end=" ")
inames = set(ac.InternalName() for ac in poser.Scene().Cameras())
for key, value in cam_dict.items():
print(key, end=" ")
if key in inames:
set_parms(poser.Scene().ActorByInternalName(key), value)
print("Done")
def undo_props(prop_dict):
print("Undo props", end=" ")
inames = set(ac.InternalName() for ac in poser.Scene().Actors() if ac.IsProp())
for key, value in prop_dict.items():
print(key, end=" ")
if key in inames:
set_parms(poser.Scene().ActorByInternalName(key), value)
print("Done")
lights = collectLights()
cams = collectCams()
props = collectProps()
actors = collectFigure(poser.Scene().CurrentFigure())
print("Scene data collected for undo.")
poser.Scene().ProcessSomeEvents()
print("Undo figure now.")
poser.Scene().ProcessSomeEvents()
undo_figure(poser.Scene().CurrentFigure(), actors)
#undo_cams(cams)
#undo_lights(lights)
#undo_props(props)
Saving is quit fast. But when undoing something it feels like Poser has died. So better try undoing lights or cams first :)