Forum Moderators: Staff
Poser Python Scripting F.A.Q (Last Updated: 2024 Sep 18 2:50 am)
So this morning I did a simple test and ran the following script the same way as above:
actor = scene.CurrentActor()
parm = actor.ParameterByCode(poser.kParmCodeXSCALE)
parm.setValue(0.66)
This didn't reset the undo buffer and I was able to undo my script. So possibly the LoadLibraryPose method does reset the Undo buffer and I should make my own function.
How... :(
Yarp - author of P3DO Organizer for Poser
As you probably know, a Poser file can do all sorts of things. Not just set a pose. So what should one do before loading such a file to make Undo possible? In your example, setting a single parameter, the matter is clear: the old value goes into the undo buffer. When loading a pose file, you would have to save the entire scene beforehand for an undo if you want to cover everything. Something you can do with Poser Python: poser.SaveDocument([filename]).
But saving the whole scene takes time. Possibly a lot of time. And that even though the loaded file may have changed very little.
Yes, I have been thinking about such a workaround.
Instead of saving the whole document I would save a Pose of the current figure before loading a Pose,a Light before loading a Light and so on. Far from being perfect but better than nothing.
There's something missing in my process. As you say, I should save the scene state before changing it. There are some intriguing commands like MemorizeAll. But all the combinations I have tried so far have failed.
Yarp - author of P3DO Organizer for Poser
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 :)
Got it!
Works fast enough now :)
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, parmcodes=None, include_morphs=True):
assert isinstance(actor, poser.ActorType)
if parmcodes is None:
parmcodes = set()
else:
parmcodes = set(parmcodes)
geom = actor.Geometry() if actor_hasgeom(actor) else None
parm_dict = dict()
for parm in actor.Parameters(): # type: poser.ParmType
if parmcodes and parm.TypeCode() not in parmcodes:
continue
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 set_parms(actor, parm_dicts, include_morphs=True):
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 and include_morphs:
for entry in parm_value:
parm.SetMorphTargetDelta(*entry)
else:
value = getattr(parm, parm_key)()
if value != parm_value:
attr_name = "Set%s" % parm_key
getattr(parm, attr_name)(parm_value)
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
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 != "InternalName":
if getattr(actor, key)() != value:
try:
getattr(actor, "Set%s" % key)(value)
except poser.error:
pass
def collectFigure(figure, parmcodes=None, include_morphs=True):
actors = [collectActor(ac, parmcodes=parmcodes, include_morphs=include_morphs)
for ac in figure.Actors() if ac.IsBodyPart()]
figure_dict = dict(Actors=actors, InternalName=figure.InternalName())
for name in dir(poser.FigureType):
if name.startswith("Set"):
attr_name = name[3:]
try:
value = getattr(figure, attr_name)()
except Exception:
continue
figure_dict[attr_name] = value
return figure_dict
def undoFigure(figure, figure_dict, include_morphs=True):
assert isinstance(figure, poser.FigureType)
assert isinstance(figure_dict, dict)
for key, value in figure_dict.items():
if key == "InternalName":
pass
elif key == "Actors":
for ac_dict in value:
ac = figure.ActorByInternalName(ac_dict["InternalName"])
undoActor(ac, ac_dict, include_morphs=include_morphs)
else:
if getattr(figure, key)() != value:
getattr(figure, "Set%s" % key)(value)
def collectLights(parmcodes=None):
light_list = list()
for light in poser.Scene().Lights():
light_list.append(collectActor(light, parmcodes=parmcodes, include_morphs=False))
return light_list
def undoLights(light_list):
for light in light_list:
try:
ac = poser.Scene().ActorByInternalName(light["InternalName"])
except poser.error:
continue
undoActor(ac)
def collectCams(parmcodes=None):
cam_list = list()
for cam in poser.Scene().Cameras():
cam_list.append(collectActor(cam, parmcodes=parmcodes, include_morphs=False))
return cam_list
def undoCams(cam_list):
for cam in cam_list:
try:
ac = poser.Scene().ActorByInternalName(cam["InternalName"])
except poser.error:
continue
undoActor(ac)
def collectProps(parmcodes=None, include_morphs=False):
prop_list = list()
for prop in [ac for ac in poser.Scene().Actors() if ac.IsProp()]:
prop_list.append(collectActor(prop, parmcodes=parmcodes, include_morphs=include_morphs))
return prop_list
def undoProps(prop_list):
for prop in prop_list:
try:
ac = poser.Scene().ActorByInternalName(prop["InternalName"])
except poser.error:
continue
undoActor(ac)
# You may restrict collected parameters by an allowed list of parmcodes. E.g.:
# parmcodes = [
# poser.kParmCodeXROT,
# poser.kParmCodeYROT,
# poser.kParmCodeZROT,
# poser.kParmCodeXTRAN,
# poser.kParmCodeYTRAN,
# poser.kParmCodeZTRAN,
# ...
# ]
parmcodes = None
lights = collectLights(parmcodes=parmcodes)
cams = collectCams(parmcodes=parmcodes)
props = collectProps(parmcodes=parmcodes)
figure = collectFigure(poser.Scene().CurrentFigure(), parmcodes=parmcodes)
print("Scene data collected for undo.")
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.
Hi Dizzi I think I have been tired of the Poser interface for the last 20 years or so. P3DO has all that too. I am just trying to improve the P3DO Poser interface.
P3DO Explorer 2.8
Yes I am loading a regular pose. Do those http request still work with the flash library disabled ? I tend to favor solutions where I am in control of what the program is doing. But it is not always possible.
At the moment I am seeing a solution similar to what adp001 is suggesting. That would be to save the status before loading. Far from perfect but simple and usable.
Another solution is to ask the Poser team to fix that. I don't see why they erase the undo list when LoadLibraryPose is called.
Yarp - author of P3DO Organizer for Poser
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).
i found another problem : if you do a actor.MarkGeomChanged() before even doing a FigureCollect() you'll have a total mess undo. For me the figure merged with the figure it was conformed . removed it and undo worked this happens in Poser 11.1.1.35510.
Logs :
figure Collect:(figure and actor)
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'BODY:2'//obj:'|Actor object at 0x00000000135AF708|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'CenterOfMass:2'//obj:'|Actor object at 0x00000000135AF1F8|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'GoalCenterOfMass:2'//obj:'|Actor object at 0x00000000135AF600|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'hip:2'//obj:'|Actor object at 0x000000001353BE10|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'abdomen:2'//obj:'|Actor object at 0x000000001353B960|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'rThigh:2'//obj:'|Actor object at 0x000000001353B660|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'rShin:2'//obj:'|Actor object at 0x000000001353BDB0|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'rFoot:2'//obj:'|Actor object at 0x000000001353B7E0|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'lThigh:2'//obj:'|Actor object at 0x000000001353BB58|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'lShin:2'//obj:'|Actor object at 0x000000001353BA50|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'lFoot:2'//obj:'|Actor object at 0x000000001353BD08|'
figure Undo: (figure and actor)
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'BODY:2'//obj:'|Actor object at 0x000000001353D798|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'CenterOfMass:2'//obj:'|Actor object at 0x000000001353BAE0|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'GoalCenterOfMass:2'//obj:'|Actor object at 0x000000001353BEA0|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'hip:2'//obj:'|Actor object at 0x000000001353B948|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'abdomen:2'//obj:'|Actor object at 0x000000001353BD08|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'rThigh:2'//obj:'|Actor object at 0x000000001353B9A8|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'rShin:2'//obj:'|Actor object at 0x000000001353BE10|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'rFoot:2'//obj:'|Actor object at 0x000000001353B960|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'lThigh:2'//obj:'|Actor object at 0x000000001353B660|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'lShin:2'//obj:'|Actor object at 0x000000001353BDB0|'
figure 'V4Hot_Shoes':'Figure 2'//obj:'|Figure object at 0x000000001353D3A8|', actor 'lFoot:2'//obj:'|Actor object at 0x000000001353B2A0|'
dictionary data before calling and figure checking name/internalname : ac = figure.ActorByInternalName(ac_dict["InternalName"])
figure 'V4Hot_Shoes':'Figure 2' // actor 'BODY:2'
figure 'V4Hot_Shoes':'Figure 2' // actor 'hip:2'
figure 'V4Hot_Shoes':'Figure 2' // actor 'abdomen:2'
File "F:LocalRuntimeLibraries!BarzingsplitCR2.py", line 609, in undoFigure
ac = figure.Actor(ac_dict["InternalName"])
poser.error: Figure has no actor by that name
------
This is not a complete replacement for Posers undo. Can't be, because the Python API has restrictions.
Seems you removed an actor or renamed "InternalName". The error can be catched, but makes this undo useless.
Here is a version with a check:
def undoFigure(figure, figure_dict, include_morphs=True):
assert isinstance(figure, poser.FigureType)
assert isinstance(figure_dict, dict)
for key, value in figure_dict.items():
if key == "InternalName":
pass
elif key == "Actors":
for ac_dict in value:
try:
ac = figure.ActorByInternalName(ac_dict["InternalName"])
except poser.error:
print("Actor '%s' no longer exists." % ac_dict["InternalName"])
else:
undoActor(ac, ac_dict, include_morphs=include_morphs)
else:
if getattr(figure, key)() != value:
getattr(figure, "Set%s" % key)(value)
A more stable version (but still no replacement for the original Undo) can be created using the script as an AddOn. But, as I said, still no replacement. So I'm not really interested in extending this script further. It's nice for certain situations. Not more.
in the log, you see it's not the case, figure and actors are the same between the "collect" and the "undo". the last actor that appears in the log : figure 'V4Hot_Shoes':'Figure 2' // actor 'abdomen:2', is flushed in the log file just before : ac = figure.ActorByInternalName(ac_dict["InternalName"]) that goes in error and abdomen:2 is part of the figure (logs just above)
But, yes, i'll probably make a personal version because i don't need a total undo. Just ckecking the name of actors in my case should be enough. since you put the figure as parameter of the undo, it should assume the actors are the good ones
Why do you ask – you can see it in the source :)
ValueOps are not saved either. And neither are materials. I made this script once mainly to be able to undo changes in morphtargets. The rest was more playing around. I posted it here to show a startpoint for something more useful.
Today I made something to convert material files to json. Tomorrow I'm going to do it the other way around – json mat-files to Poser. For a possibility to exchange materials between Poser and Blender. That's far more interesting (Blenders Cycle is still serveral times faster and has far more options than Posers implemtation) :)
formoz posted at 7:55PM Fri, 30 April 2021 - #4418086
ok, i just experienced that even with file.flush(), you're not necessarily getting the last lines before a crash ... :)
I can't see on which part this script could be able to crash your Poser. Raising an error condition: Ok. But no crash. There must be something other in your script.
adp001 posted at 4:09AM Sat, 01 May 2021 - #4418096
formoz posted at 7:55PM Fri, 30 April 2021 - #4418086
ok, i just experienced that even with file.flush(), you're not necessarily getting the last lines before a crash ... :)
I can't see on which part this script could be able to crash your Poser. Raising an error condition: Ok. But no crash. There must be something other in your script.
yes absolutely, like reloading figure between the the collect and the undo.... Finally, i had to heavely personalized your scripts, keeping only numeric values, checking actors internalname differently (removing the instantiation check ":"), added a new parameter for this called "only_parms")
adp001 posted at 4:17AM Sat, 01 May 2021 - #4418095
Today I made something to convert material files to json. Tomorrow I'm going to do it the other way around – json mat-files to Poser. For a possibility to exchange materials between Poser and Blender. That's far more interesting (Blenders Cycle is still serveral times faster and has far more options than Posers implemtation) :)
ah nice, i need to install blender. Blender use Json for its Files ? or you did a script on Blender to import your json ? I currently do a "CR2 (symetry) splitter" and reverse a "CR2 Mirrorer". It includs all : obj, weightMap, Morphs, MAterials and even merge a sculpting morph in geometry if needed.
formoz posted at 3:14PM Sat, 01 May 2021 - #4418115
ah nice, i need to install blender. Blender use Json for its Files ?
No. B lender uses "blend files" for anything. But json makes an easy internediate format. Easy to import in any other software without without the need of many knowledge about the source internals.
or you did a script on Blender to import your json ?
Yes. That was the easy part. Blender has a nearly full fledged Python API.
I currently do a "CR2 (symetry) splitter" and reverse a "CR2 Mirrorer".
Can you tell what it is good for?
you can try, if loading files from outside poser still works (that was how the air library from Poser 8 communicated with Poser). Here' some C# code for loading and saving, port should be the one from the poser.ini:
load:
System.Net.WebClient Client = new System.Net.WebClient();
Client.Encoding = Encoding.UTF8;
Client.QueryString.Add("id", Util.EncodeUtfUriComponent(filename));
Client.QueryString.Add("op", "addItem");
Stream strm = Client.OpenRead(new Uri("http://localhost:11530/apps/lms/api.py"));
StreamReader sr = new StreamReader(strm);
string line;
do {
line = sr.ReadLine();
Console.WriteLine(line);
}
while (line != null);
strm.Close();
save:
string Path = SaveDialog.GetSavePath(); if (Path == null) return; System.Net.WebClient Client = new System.Net.WebClient(); Client.Encoding = Encoding.UTF8; Client.QueryString.Add("op", "saveItem"); Client.QueryString.Add("categoryId", Category); Client.QueryString.Add("folderId", Util.EncodeUtfUriComponent(Path));
//Stream strm =
IntPtr poserHandle = Util.GetPoserWindowHandle(this);
if (poserHandle != IntPtr.Zero)
SetForegroundWindow(poserHandle);
try {
Client.OpenRead(new Uri("http://localhost:11530/apps/lms/api.py"));
Cool, but instead of running this as an http request maybe running it as a Poser script would work too.
Since you can run python script with arguments there's a chance it runs ok.
If this doesn't I will save a Pose before loading a Pose and use it as a workaround undo system. Far from being satisfactory but bettet than nothing.
Yarp - author of P3DO Organizer for Poser
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.
Hi, whenever I load a Pose into Poser with P3DO the undo buffer is reset and the action is not undoable.
In order to load a pose into Poser I run a python script and call scene.LoadLibraryPose then scene.Draw and that's about all.
I have been looking all day for information on that process, but I still don't have any clue on how I could fix that.
Reading Poser dopcumentation, opening official Poser scripts and others. Found nothing.
Any idea ?
I would be grateful even if the answer is there's no way to do that. This is something that has been bothering me for years. And now that I have decided to fix it, it is even more frustrating :)
I haven't asked Poser yet. Will be filling a ticket if the answer is negative here.,
Yarp - author of P3DO Organizer for Poser